• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

MMRDecoder.cpp

Go to the documentation of this file.
00001 //C-  -*- C++ -*-
00002 //C- -------------------------------------------------------------------
00003 //C- DjVuLibre-3.5
00004 //C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
00005 //C- Copyright (c) 2001  AT&T
00006 //C-
00007 //C- This software is subject to, and may be distributed under, the
00008 //C- GNU General Public License, Version 2. The license should have
00009 //C- accompanied the software or you may obtain a copy of the license
00010 //C- from the Free Software Foundation at http://www.fsf.org .
00011 //C-
00012 //C- This program is distributed in the hope that it will be useful,
00013 //C- but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //C- GNU General Public License for more details.
00016 //C- 
00017 //C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
00018 //C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
00019 //C- Software authorized us to replace the original DjVu(r) Reference 
00020 //C- Library notice by the following text (see doc/lizard2002.djvu):
00021 //C-
00022 //C-  ------------------------------------------------------------------
00023 //C- | DjVu (r) Reference Library (v. 3.5)
00024 //C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
00025 //C- | The DjVu Reference Library is protected by U.S. Pat. No.
00026 //C- | 6,058,214 and patents pending.
00027 //C- |
00028 //C- | This software is subject to, and may be distributed under, the
00029 //C- | GNU General Public License, Version 2. The license should have
00030 //C- | accompanied the software or you may obtain a copy of the license
00031 //C- | from the Free Software Foundation at http://www.fsf.org .
00032 //C- |
00033 //C- | The computer code originally released by LizardTech under this
00034 //C- | license and unmodified by other parties is deemed "the LIZARDTECH
00035 //C- | ORIGINAL CODE."  Subject to any third party intellectual property
00036 //C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
00037 //C- | non-exclusive license to make, use, sell, or otherwise dispose of 
00038 //C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
00039 //C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
00040 //C- | General Public License.   This grant only confers the right to 
00041 //C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
00042 //C- | the extent such infringement is reasonably necessary to enable 
00043 //C- | recipient to make, have made, practice, sell, or otherwise dispose 
00044 //C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
00045 //C- | any greater extent that may be necessary to utilize further 
00046 //C- | modifications or combinations.
00047 //C- |
00048 //C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
00049 //C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
00050 //C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
00051 //C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00052 //C- +------------------------------------------------------------------
00053 // 
00054 // $Id: MMRDecoder.cpp,v 1.8 2003/11/07 22:08:22 leonb Exp $
00055 // $Name: release_3_5_15 $
00056 
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063 
00064 #include "MMRDecoder.h"
00065 #include "JB2Image.h"
00066 #include "ByteStream.h"
00067 #include "GBitmap.h"
00068 
00069 
00070 #ifdef HAVE_NAMESPACES
00071 namespace DJVU {
00072 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00073 }
00074 #endif
00075 #endif
00076 
00077 
00078 // ----------------------------------------
00079 // MMR CODEBOOKS
00080 
00081 static const char invalid_mmr_data[]= ERR_MSG("MMRDecoder.bad_data");
00082 
00083 struct VLCode 
00084 {
00085   unsigned short code;
00086   short codelen;
00087   short value;
00088 };
00089 
00090 enum MMRMode
00091 { 
00092   P=0, H=1, V0=2, VR1=3, VR2=4, VR3=5, VL1=6, VL2=7, VL3=8 
00093 };
00094 
00095 static const VLCode mrcodes[] =
00096 {   // Codes on 7 bits
00097   // 7 bit codes
00098   { 0x08,   4,    P }, // 0001
00099   { 0x10,   3,    H }, // 001
00100   { 0x40,   1,   V0 }, // 1
00101   { 0x30,   3,  VR1 }, // 011
00102   { 0x06,   6,  VR2 }, // 000011
00103   { 0x03,   7,  VR3 }, // 0000011
00104   { 0x20,   3,  VL1 }, // 010
00105   { 0x04,   6,  VL2 }, // 000010
00106   { 0x02,   7,  VL3 }, // 0000010
00107   { 0x00,   0,   -1 }  // Illegal entry
00108 };
00109 
00110 
00111 static const VLCode wcodes[] = {    
00112   // 13 bit codes
00113   { 0x06a0,  8,    0 }, // 00110101
00114   { 0x0380,  6,    1 }, // 000111
00115   { 0x0e00,  4,    2 }, // 0111
00116   { 0x1000,  4,    3 }, // 1000
00117   { 0x1600,  4,    4 }, // 1011
00118   { 0x1800,  4,    5 }, // 1100
00119   { 0x1c00,  4,    6 }, // 1110
00120   { 0x1e00,  4,    7 }, // 1111
00121   { 0x1300,  5,    8 }, // 10011
00122   { 0x1400,  5,    9 }, // 10100
00123   { 0x0700,  5,   10 }, // 00111
00124   { 0x0800,  5,   11 }, // 01000
00125   { 0x0400,  6,   12 }, // 001000
00126   { 0x0180,  6,   13 }, // 000011
00127   { 0x1a00,  6,   14 }, // 110100
00128   { 0x1a80,  6,   15 }, // 110101
00129   { 0x1500,  6,   16 }, // 101010
00130   { 0x1580,  6,   17 }, // 101011
00131   { 0x09c0,  7,   18 }, // 0100111
00132   { 0x0300,  7,   19 }, // 0001100
00133   { 0x0200,  7,   20 }, // 0001000
00134   { 0x05c0,  7,   21 }, // 0010111
00135   { 0x00c0,  7,   22 }, // 0000011
00136   { 0x0100,  7,   23 }, // 0000100
00137   { 0x0a00,  7,   24 }, // 0101000
00138   { 0x0ac0,  7,   25 }, // 0101011
00139   { 0x04c0,  7,   26 }, // 0010011
00140   { 0x0900,  7,   27 }, // 0100100
00141   { 0x0600,  7,   28 }, // 0011000
00142   { 0x0040,  8,   29 }, // 00000010
00143   { 0x0060,  8,   30 }, // 00000011
00144   { 0x0340,  8,   31 }, // 00011010
00145   { 0x0360,  8,   32 }, // 00011011
00146   { 0x0240,  8,   33 }, // 00010010
00147   { 0x0260,  8,   34 }, // 00010011
00148   { 0x0280,  8,   35 }, // 00010100
00149   { 0x02a0,  8,   36 }, // 00010101
00150   { 0x02c0,  8,   37 }, // 00010110
00151   { 0x02e0,  8,   38 }, // 00010111
00152   { 0x0500,  8,   39 }, // 00101000
00153   { 0x0520,  8,   40 }, // 00101001
00154   { 0x0540,  8,   41 }, // 00101010
00155   { 0x0560,  8,   42 }, // 00101011
00156   { 0x0580,  8,   43 }, // 00101100
00157   { 0x05a0,  8,   44 }, // 00101101
00158   { 0x0080,  8,   45 }, // 00000100
00159   { 0x00a0,  8,   46 }, // 00000101
00160   { 0x0140,  8,   47 }, // 00001010
00161   { 0x0160,  8,   48 }, // 00001011
00162   { 0x0a40,  8,   49 }, // 01010010
00163   { 0x0a60,  8,   50 }, // 01010011
00164   { 0x0a80,  8,   51 }, // 01010100
00165   { 0x0aa0,  8,   52 }, // 01010101
00166   { 0x0480,  8,   53 }, // 00100100
00167   { 0x04a0,  8,   54 }, // 00100101
00168   { 0x0b00,  8,   55 }, // 01011000
00169   { 0x0b20,  8,   56 }, // 01011001
00170   { 0x0b40,  8,   57 }, // 01011010
00171   { 0x0b60,  8,   58 }, // 01011011
00172   { 0x0940,  8,   59 }, // 01001010
00173   { 0x0960,  8,   60 }, // 01001011
00174   { 0x0640,  8,   61 }, // 00110010
00175   { 0x0660,  8,   62 }, // 00110011
00176   { 0x0680,  8,   63 }, // 00110100
00177   { 0x1b00,  5,   64 }, // 11011
00178   { 0x1200,  5,  128 }, // 10010
00179   { 0x0b80,  6,  192 }, // 010111
00180   { 0x0dc0,  7,  256 }, // 0110111
00181   { 0x06c0,  8,  320 }, // 00110110
00182   { 0x06e0,  8,  384 }, // 00110111
00183   { 0x0c80,  8,  448 }, // 01100100
00184   { 0x0ca0,  8,  512 }, // 01100101
00185   { 0x0d00,  8,  576 }, // 01101000
00186   { 0x0ce0,  8,  640 }, // 01100111
00187   { 0x0cc0,  9,  704 }, // 011001100
00188   { 0x0cd0,  9,  768 }, // 011001101
00189   { 0x0d20,  9,  832 }, // 011010010
00190   { 0x0d30,  9,  896 }, // 011010011
00191   { 0x0d40,  9,  960 }, // 011010100
00192   { 0x0d50,  9, 1024 }, // 011010101
00193   { 0x0d60,  9, 1088 }, // 011010110
00194   { 0x0d70,  9, 1152 }, // 011010111
00195   { 0x0d80,  9, 1216 }, // 011011000
00196   { 0x0d90,  9, 1280 }, // 011011001
00197   { 0x0da0,  9, 1344 }, // 011011010
00198   { 0x0db0,  9, 1408 }, // 011011011
00199   { 0x0980,  9, 1472 }, // 010011000
00200   { 0x0990,  9, 1536 }, // 010011001
00201   { 0x09a0,  9, 1600 }, // 010011010
00202   { 0x0c00,  6, 1664 }, // 011000  (what did they think?)
00203   { 0x09b0,  9, 1728 }, // 010011011
00204   { 0x0020, 11, 1792 }, // 00000001000
00205   { 0x0030, 11, 1856 }, // 00000001100
00206   { 0x0034, 11, 1920 }, // 00000001101
00207   { 0x0024, 12, 1984 }, // 000000010010
00208   { 0x0026, 12, 2048 }, // 000000010011
00209   { 0x0028, 12, 2112 }, // 000000010100
00210   { 0x002a, 12, 2176 }, // 000000010101
00211   { 0x002c, 12, 2240 }, // 000000010110
00212   { 0x002e, 12, 2304 }, // 000000010111
00213   { 0x0038, 12, 2368 }, // 000000011100
00214   { 0x003a, 12, 2432 }, // 000000011101
00215   { 0x003c, 12, 2496 }, // 000000011110
00216   { 0x003e, 12, 2560 }, // 000000011111
00217   { 0x0000,  0,   -1 }  // Illegal entry
00218 };
00219 
00220 
00221 static const VLCode bcodes[] = {
00222   // 13 bit codes
00223   { 0x01b8, 10,    0 }, // 0000110111
00224   { 0x0800,  3,    1 }, // 010
00225   { 0x1800,  2,    2 }, // 11
00226   { 0x1000,  2,    3 }, // 10
00227   { 0x0c00,  3,    4 }, // 011
00228   { 0x0600,  4,    5 }, // 0011
00229   { 0x0400,  4,    6 }, // 0010
00230   { 0x0300,  5,    7 }, // 00011
00231   { 0x0280,  6,    8 }, // 000101
00232   { 0x0200,  6,    9 }, // 000100
00233   { 0x0100,  7,   10 }, // 0000100
00234   { 0x0140,  7,   11 }, // 0000101
00235   { 0x01c0,  7,   12 }, // 0000111
00236   { 0x0080,  8,   13 }, // 00000100
00237   { 0x00e0,  8,   14 }, // 00000111
00238   { 0x0180,  9,   15 }, // 000011000
00239   { 0x00b8, 10,   16 }, // 0000010111
00240   { 0x00c0, 10,   17 }, // 0000011000
00241   { 0x0040, 10,   18 }, // 0000001000
00242   { 0x019c, 11,   19 }, // 00001100111
00243   { 0x01a0, 11,   20 }, // 00001101000
00244   { 0x01b0, 11,   21 }, // 00001101100
00245   { 0x00dc, 11,   22 }, // 00000110111
00246   { 0x00a0, 11,   23 }, // 00000101000
00247   { 0x005c, 11,   24 }, // 00000010111
00248   { 0x0060, 11,   25 }, // 00000011000
00249   { 0x0194, 12,   26 }, // 000011001010
00250   { 0x0196, 12,   27 }, // 000011001011
00251   { 0x0198, 12,   28 }, // 000011001100
00252   { 0x019a, 12,   29 }, // 000011001101
00253   { 0x00d0, 12,   30 }, // 000001101000
00254   { 0x00d2, 12,   31 }, // 000001101001
00255   { 0x00d4, 12,   32 }, // 000001101010
00256   { 0x00d6, 12,   33 }, // 000001101011
00257   { 0x01a4, 12,   34 }, // 000011010010
00258   { 0x01a6, 12,   35 }, // 000011010011
00259   { 0x01a8, 12,   36 }, // 000011010100
00260   { 0x01aa, 12,   37 }, // 000011010101
00261   { 0x01ac, 12,   38 }, // 000011010110
00262   { 0x01ae, 12,   39 }, // 000011010111
00263   { 0x00d8, 12,   40 }, // 000001101100
00264   { 0x00da, 12,   41 }, // 000001101101
00265   { 0x01b4, 12,   42 }, // 000011011010
00266   { 0x01b6, 12,   43 }, // 000011011011
00267   { 0x00a8, 12,   44 }, // 000001010100
00268   { 0x00aa, 12,   45 }, // 000001010101
00269   { 0x00ac, 12,   46 }, // 000001010110
00270   { 0x00ae, 12,   47 }, // 000001010111
00271   { 0x00c8, 12,   48 }, // 000001100100
00272   { 0x00ca, 12,   49 }, // 000001100101
00273   { 0x00a4, 12,   50 }, // 000001010010
00274   { 0x00a6, 12,   51 }, // 000001010011
00275   { 0x0048, 12,   52 }, // 000000100100
00276   { 0x006e, 12,   53 }, // 000000110111
00277   { 0x0070, 12,   54 }, // 000000111000
00278   { 0x004e, 12,   55 }, // 000000100111
00279   { 0x0050, 12,   56 }, // 000000101000
00280   { 0x00b0, 12,   57 }, // 000001011000
00281   { 0x00b2, 12,   58 }, // 000001011001
00282   { 0x0056, 12,   59 }, // 000000101011
00283   { 0x0058, 12,   60 }, // 000000101100
00284   { 0x00b4, 12,   61 }, // 000001011010
00285   { 0x00cc, 12,   62 }, // 000001100110
00286   { 0x00ce, 12,   63 }, // 000001100111
00287   { 0x0078, 10,   64 }, // 0000001111
00288   { 0x0190, 12,  128 }, // 000011001000
00289   { 0x0192, 12,  192 }, // 000011001001
00290   { 0x00b6, 12,  256 }, // 000001011011
00291   { 0x0066, 12,  320 }, // 000000110011
00292   { 0x0068, 12,  384 }, // 000000110100
00293   { 0x006a, 12,  448 }, // 000000110101
00294   { 0x006c, 13,  512 }, // 0000001101100
00295   { 0x006d, 13,  576 }, // 0000001101101
00296   { 0x004a, 13,  640 }, // 0000001001010
00297   { 0x004b, 13,  704 }, // 0000001001011
00298   { 0x004c, 13,  768 }, // 0000001001100
00299   { 0x004d, 13,  832 }, // 0000001001101
00300   { 0x0072, 13,  896 }, // 0000001110010
00301   { 0x0073, 13,  960 }, // 0000001110011
00302   { 0x0074, 13, 1024 }, // 0000001110100
00303   { 0x0075, 13, 1088 }, // 0000001110101
00304   { 0x0076, 13, 1152 }, // 0000001110110
00305   { 0x0077, 13, 1216 }, // 0000001110111
00306   { 0x0052, 13, 1280 }, // 0000001010010
00307   { 0x0053, 13, 1344 }, // 0000001010011
00308   { 0x0054, 13, 1408 }, // 0000001010100
00309   { 0x0055, 13, 1472 }, // 0000001010101
00310   { 0x005a, 13, 1536 }, // 0000001011010
00311   { 0x005b, 13, 1600 }, // 0000001011011
00312   { 0x0064, 13, 1664 }, // 0000001100100
00313   { 0x0065, 13, 1728 }, // 0000001100101
00314   { 0x0020, 11, 1792 }, // 00000001000
00315   { 0x0030, 11, 1856 }, // 00000001100
00316   { 0x0034, 11, 1920 }, // 00000001101
00317   { 0x0024, 12, 1984 }, // 000000010010
00318   { 0x0026, 12, 2048 }, // 000000010011
00319   { 0x0028, 12, 2112 }, // 000000010100
00320   { 0x002a, 12, 2176 }, // 000000010101
00321   { 0x002c, 12, 2240 }, // 000000010110
00322   { 0x002e, 12, 2304 }, // 000000010111
00323   { 0x0038, 12, 2368 }, // 000000011100
00324   { 0x003a, 12, 2432 }, // 000000011101
00325   { 0x003c, 12, 2496 }, // 000000011110
00326   { 0x003e, 12, 2560 }, // 000000011111
00327   { 0x0000,  0,   -1 }  // Illegal entry
00328 };
00329 
00330 
00331 
00332 
00333 // ----------------------------------------
00334 // SOURCE OF BITS
00335 
00336 #define VLSBUFSIZE    64
00337 
00338 class MMRDecoder::VLSource : public GPEnabled
00339 {
00340 protected:
00341   VLSource(GP<ByteStream> &inp);
00342   void init(const bool striped);
00343 public:
00344   // Initializes a bit source on a bytestream
00345   static GP<VLSource> create(GP<ByteStream> &inp, const bool striped);
00346 
00347   // Synchronize on the next stripe
00348   void nextstripe(void);
00349   // Returns a 32 bits integer with at least the 
00350   // next sixteen code bits in the high order bits.
00351   inline unsigned int peek(void);
00352   // Ensures that next #peek()# contains at least
00353   // the next 24 code bits.
00354   void preload(void);
00355   // Consumes #n# bits.
00356   void shift(const int n);
00357 private:
00358   GP<ByteStream> ginp;
00359   ByteStream &inp;
00360   unsigned char buffer[ VLSBUFSIZE ];
00361   unsigned int codeword;
00362   int lowbits;
00363   int bufpos;
00364   int bufmax;
00365   int readmax;
00366 };
00367 
00368 MMRDecoder::VLSource::VLSource(GP<ByteStream> &xinp)
00369 : ginp(xinp), inp(*ginp), codeword(0), 
00370   lowbits(0), bufpos(0), bufmax(0),
00371   readmax(-1)
00372 {}
00373 
00374 void
00375 MMRDecoder::VLSource::init(const bool striped)
00376 {
00377   if (striped)
00378     readmax = inp.read32();
00379   lowbits = 32;
00380   preload();
00381 }
00382 
00383 GP<MMRDecoder::VLSource>
00384 MMRDecoder::VLSource::create(GP<ByteStream> &inp, const bool striped)
00385 {
00386   VLSource *src=new VLSource(inp);
00387   GP<VLSource> retval=src;
00388   src->init(striped);
00389   return retval;
00390 }
00391 
00392 void 
00393 MMRDecoder::VLSource::shift(const int n)
00394 { 
00395   codeword<<=n;
00396   lowbits+=n;
00397   if (lowbits>=16)
00398     preload();
00399 }
00400 
00401 inline unsigned int
00402 MMRDecoder::VLSource::peek(void)
00403 {
00404   return codeword;
00405 }
00406 
00407 
00408 void
00409 MMRDecoder::VLSource::nextstripe(void)
00410 {
00411   while (readmax>0)
00412     {
00413       int size = sizeof(buffer);
00414       if (readmax < size) 
00415         size = readmax;
00416       inp.readall(buffer, size);
00417       readmax -= size;
00418     }
00419   bufpos = bufmax = 0;
00420   memset(buffer,0,sizeof(buffer));
00421   readmax = inp.read32();
00422   codeword = 0; 
00423   lowbits = 32;
00424   preload();
00425 }
00426 
00427 void
00428 MMRDecoder::VLSource::preload(void)
00429 {
00430   while (lowbits>=8) 
00431     {
00432       if (bufpos >= bufmax) 
00433     {
00434           // Refill buffer
00435       bufpos = bufmax = 0;
00436           int size = sizeof(buffer);
00437           if (readmax>=0 && readmax<size) 
00438             size = readmax;
00439           if (size>0)
00440             bufmax = inp.read((void*)buffer, size);
00441           readmax -= bufmax;
00442       if (bufmax <= 0)
00443             return;
00444     }
00445       lowbits -= 8;
00446       codeword |= buffer[bufpos++] << lowbits;
00447     }
00448 }
00449 
00450 
00451 
00452 // ----------------------------------------
00453 // VARIABLE LENGTH CODES
00454 
00455 
00456 
00457 class MMRDecoder::VLTable : public GPEnabled
00458 {
00459 protected:
00460   VLTable(const VLCode *codes);
00461   void init(const int nbits);
00462 public:
00463   // Construct a VLTable given a codebook with #nbits# long codes.
00464   static GP<VLTable> create(VLCode const * const codes, const int nbits);
00465 
00466   // Reads one symbol from a VLSource
00467   int decode(MMRDecoder::VLSource *src);
00468 
00469   const VLCode *code;
00470   int codewordshift;
00471   unsigned char *index;
00472   GPBuffer<unsigned char> gindex;
00473 };
00474 
00475 GP<MMRDecoder::VLTable>
00476 MMRDecoder::VLTable::create(VLCode const * const codes, const int nbits)
00477 {
00478   VLTable *table=new VLTable(codes);
00479   GP<VLTable> retval=table;
00480   table->init(nbits);
00481   return retval;
00482 }
00483 
00484 inline int
00485 MMRDecoder::VLTable::decode(MMRDecoder::VLSource *src)    
00486 { 
00487   const VLCode &c = code[ index[ src->peek() >> codewordshift ] ];
00488   src->shift(c.codelen); 
00489   return c.value; 
00490 }
00491 
00492 MMRDecoder::VLTable::VLTable(const VLCode *codes)
00493 : code(codes), codewordshift(0), gindex(index,0)
00494 {}
00495 
00496 void
00497 MMRDecoder::VLTable::init(const int nbits)
00498 {
00499   // count entries
00500   int ncodes = 0;
00501   while (code[ncodes].codelen)
00502     ncodes++;
00503   // check arguments
00504   if (nbits<=1 || nbits>16)
00505     G_THROW(invalid_mmr_data);
00506   if (ncodes>=256)
00507     G_THROW(invalid_mmr_data);
00508   codewordshift = 32 - nbits;
00509   // allocate table
00510   int size = (1<<nbits);
00511   gindex.resize(size);
00512   gindex.set(ncodes);
00513   // process codes
00514   for (int i=0; i<ncodes; i++) {
00515     const int c = code[i].code;
00516     const int b = code[i].codelen;
00517     if(b<=0 || b>nbits)
00518     {
00519       G_THROW(invalid_mmr_data);
00520     }
00521     // fill table entries whose index high bits are code.
00522     int n = c + (1<<(nbits-b));
00523     while ( --n >= c ) {
00524       if(index[n] != ncodes)
00525        G_THROW( ERR_MSG("MMRDecoder.bad_codebook") );
00526       index[n] = i;
00527     }
00528   }
00529 }
00530 
00531 // ----------------------------------------
00532 // MMR DECODER
00533 
00534 
00535 
00536 MMRDecoder::~MMRDecoder() {}
00537 
00538 MMRDecoder::MMRDecoder( const int xwidth, const int xheight )
00539 : width(xwidth), height(xheight), lineno(0), 
00540   striplineno(0), rowsperstrip(0), gline(line,width+8),
00541   glineruns(lineruns,width+4), gprevruns(prevruns,width+4)
00542 {
00543   gline.clear();
00544   glineruns.clear();
00545   gprevruns.clear();
00546   lineruns[0] = width;
00547   prevruns[0] = width;
00548 }
00549 
00550 void
00551 MMRDecoder::init(GP<ByteStream> gbs, const bool striped)
00552 {
00553   rowsperstrip = (striped ? gbs->read16() : height);
00554   src = VLSource::create(gbs, striped);
00555   mrtable = VLTable::create(mrcodes, 7);
00556   btable = VLTable::create(bcodes, 13);
00557   wtable = VLTable::create(wcodes, 13);
00558 }
00559 
00560 GP<MMRDecoder> 
00561 MMRDecoder::create( GP<ByteStream> gbs, const int width,
00562   const int height, const bool striped )
00563 {
00564   MMRDecoder *mmr=new MMRDecoder(width,height);
00565   GP<MMRDecoder> retval=mmr;
00566   mmr->init(gbs,striped);
00567   return retval;
00568 }
00569 
00570 const unsigned short *
00571 MMRDecoder::scanruns(const unsigned short **endptr)
00572 {
00573   // Check if all lines have been returned
00574   if (lineno >= height)
00575     return 0;
00576   // Check end of stripe
00577   if ( striplineno == rowsperstrip )
00578     {
00579       striplineno=0;
00580       lineruns[0] = prevruns[0] = width;
00581       src->nextstripe();
00582     }
00583   // Swap run buffers
00584   unsigned short *pr = lineruns;
00585   unsigned short *xr = prevruns;
00586   prevruns = pr;
00587   lineruns = xr;
00588   // Loop until scanline is complete
00589   bool a0color = false;
00590   int a0,rle,b1;
00591   for(a0=0,rle=0,b1=*pr++;a0 < width;)
00592     {
00593       // Process MMR codes
00594       const int c=mrtable->decode(src);
00595       switch ( c )
00596       {
00597           /* Pass Mode */
00598         case P: 
00599           { 
00600             b1 += *pr++;
00601             rle += b1 - a0;
00602             a0 = b1;
00603             b1 += *pr++;
00604             break;
00605           }
00606           /* Horizontal Mode */
00607         case H: 
00608           { 
00609             // First run
00610             VLTable &table1 = *(a0color ? btable : wtable);
00611             int inc;
00612             do { inc=table1.decode(src); a0+=inc; rle+=inc; } while (inc>=64);
00613             *xr = rle; xr++; rle = 0;
00614             // Second run
00615             VLTable &table2 = *(!a0color ? btable : wtable);
00616             do { inc=table2.decode(src); a0+=inc; rle+=inc; } while (inc>=64);
00617             *xr = rle; xr++; rle = 0;
00618             break;
00619           }
00620           /* Vertical Modes */
00621         case V0:
00622         case VR3:
00623         case VR2:
00624         case VR1:
00625         case VL3:
00626         case VL2:
00627         case VL1:
00628         {
00629           int inc=b1;
00630           switch ( c )
00631           {
00632           case V0:
00633             inc = b1;
00634             b1 += *pr++;
00635             break;
00636           case VR3:
00637             inc = b1+3;
00638             b1 += *pr++;
00639             break;
00640           case VR2:
00641             inc = b1+2;
00642             b1 += *pr++;
00643             break;
00644           case VR1:
00645             inc = b1+1;
00646             b1 += *pr++;
00647             break;
00648           case VL3:
00649             inc = b1-3;
00650             b1 -= *--pr;
00651             break;
00652           case VL2:
00653             inc = b1-2;
00654             b1 -= *--pr;
00655             break;
00656           case VL1:
00657             inc = b1-1;
00658             b1 -= *--pr;
00659             break;
00660           }
00661           *xr = inc+rle-a0;
00662           xr++;
00663           a0 = inc;
00664           rle = 0;
00665           a0color = !a0color;
00666           break;
00667         }
00668           /* Uncommon modes */
00669         default: 
00670           {
00671             src->preload();
00672             unsigned int m = src->peek();
00673             // -- Could be EOFB ``000000000001000000000001''
00674             //    TIFF6 says that all remaining lines are white
00675             if ((m & 0xffffff00) == 0x00100100)
00676               {
00677                 lineno = height;
00678                 return 0;
00679               }
00680             // -- Could be UNCOMPRESSED ``0000001111''
00681             //    TIFF6 says people should not do this.
00682             //    RFC1314 says people should do this.
00683             else if ((m & 0xffc00000) == 0x03c00000)
00684               {
00685 #ifdef MMRDECODER_REFUSES_UNCOMPRESSED
00686                 G_THROW( ERR_MSG("MMRDecoder.cant_process") );
00687 #else
00688                 // ---THE-FOLLOWING-CODE-IS-POORLY-TESTED---
00689                 src->shift(10);
00690                 while ((m = (src->peek() & 0xfc000000)))
00691                   {
00692                     if (m == 0x04000000)       // 000001
00693                       {
00694                         src->shift(6);
00695                         if (a0color)
00696                         {
00697                           *xr = rle;
00698                           xr++;
00699                           rle = 0;
00700                           a0color = !a0color;
00701                         }
00702                         rle += 5;
00703                         a0 += 5;
00704                       }
00705                     else                       // 000010 to 111111 
00706                       { 
00707                         src->shift(1);
00708                         if (a0color == !(m & 0x80000000))
00709                         {
00710                           *xr = rle;
00711                           xr++;
00712                           rle = 0;
00713                           a0color = !a0color;
00714                         }
00715                         rle++;
00716                         a0++;
00717                       }
00718                     if (a0 > width)
00719                       G_THROW(invalid_mmr_data);
00720                   }
00721                 // Analyze uncompressed termination code.
00722                 m = src->peek() & 0xff000000;  
00723                 src->shift(8);
00724                 if ( (m & 0xfe000000) != 0x02000000 )
00725                   G_THROW(invalid_mmr_data);
00726                 if (rle)
00727                 {
00728                   *xr = rle;
00729                   xr++;
00730                   rle = 0;
00731                   a0color = !a0color;
00732                 }                  
00733                 if (a0color == !(m & 0x01000000))
00734                 {
00735                   *xr = rle;
00736                   xr++;
00737                   rle = 0;
00738                   a0color = !a0color;
00739                 }
00740                 // Cross fingers and proceed ...
00741                 break;
00742 #endif
00743               }
00744             // -- Unknown MMR code.
00745             G_THROW(invalid_mmr_data);
00746           }
00747       }
00748       // Next reference run
00749       for(;b1<=a0 && b1<width;pr+=2)
00750       {
00751         b1 += pr[0]+pr[1];
00752       }
00753     }
00754   // Final P must be followed by V0 (they say!)
00755   if (rle > 0)
00756   {
00757     if (mrtable->decode(src) != V0)
00758     {
00759       G_THROW(invalid_mmr_data);
00760     }
00761   }
00762   if (rle > 0)
00763   {
00764     *xr = rle;
00765     xr++;
00766   }
00767   // At this point we should have A0 equal to WIDTH
00768   // But there are buggy files around (Kofax!)
00769   // and we are not the CCITT police.
00770   if (a0 > width) 
00771     {
00772       while (a0 > width && xr > lineruns)
00773         a0 -= *--xr;
00774       if (a0 < width)
00775       {
00776         *xr = width-a0;
00777         xr++;
00778       }
00779     }
00780   /* Increment and return */
00781   if (endptr) 
00782     *endptr = xr;
00783   xr[0] = 0;
00784   xr[1] = 0;
00785   lineno ++;
00786   striplineno ++;
00787   return lineruns;
00788 }
00789 
00790 
00791 
00792 const unsigned char *
00793 MMRDecoder::scanrle(const bool invert, const unsigned char **endptr)
00794 {
00795   // Obtain run lengths
00796   const unsigned short *xr = scanruns();
00797   if (!xr) return 0;
00798   unsigned char *p=line;
00799   // Process inversion
00800   if (invert)
00801     {
00802       if (! *xr) 
00803       {
00804         xr++;
00805       }else
00806       {
00807         *p = 0; p++;
00808       }
00809     }
00810   // Encode lenghts using the RLE format
00811   for(int a0=0;a0 < width;)
00812   {
00813     int count = *xr++;
00814     a0 += count;
00815     GBitmap::append_run(p, count);
00816   }
00817   if (endptr)
00818     *endptr = p;
00819   p[0] = 0;
00820   p[1] = 0;
00821   return line;
00822 }
00823 
00824 
00825 #if 0
00826 const unsigned char *
00827 MMRDecoder::scanline(void)
00828 {
00829   // Obtain run lengths
00830   const unsigned short *xr = scanruns();
00831   if (!xr) return 0;
00832   // Allocate data buffer if needed
00833   unsigned char *p = line;
00834   // Decode run lengths
00835   int a0 = 0;
00836   int a0color = 0;
00837   while (a0 < width)
00838     {
00839       int a1 = a0 + *xr++;
00840       while (a0<a1 && a0<width)
00841         line[a0++] = a0color;
00842       a0color = !a0color;
00843     }
00844   return line;
00845 }
00846 #endif
00847 
00848 
00849 
00850 
00851 // ----------------------------------------
00852 // MAIN DECODING ROUTINE
00853 
00854 bool
00855 MMRDecoder::decode_header(
00856   ByteStream &inp, int &width, int &height, int &invert)
00857 {
00858   unsigned long int magic = inp.read32();
00859   if((magic&0xfffffffc) != 0x4d4d5200)
00860     G_THROW( ERR_MSG("MMRDecoder.unrecog_header") ); 
00861   invert = ((magic & 0x1) ? 1 : 0);
00862   const bool strip =  ((magic & 0x2) ? 1 : 0);
00863   width = inp.read16();
00864   height = inp.read16();
00865   if (width<=0 || height<=0)
00866     G_THROW( ERR_MSG("MMRDecoder.bad_header") );
00867   return strip;
00868 }
00869 
00870 static inline int MAX(int a, int b) { return a>b ? a : b; }
00871 static inline int MIN(int a, int b) { return a<b ? a : b; }
00872 
00873 GP<JB2Image>
00874 MMRDecoder::decode(GP<ByteStream> gbs)
00875 {
00876   ByteStream &inp=*gbs;
00877   // Read header
00878   int width, height, invert;
00879   const bool striped=decode_header(inp, width, height, invert);
00880   // Prepare image
00881   GP<JB2Image> jimg = JB2Image::create();
00882   jimg->set_dimension(width, height);
00883   // Choose pertinent blocksize
00884   int blocksize = MIN(500,MAX(64,MAX(width/17,height/22)));
00885   int blocksperline = (width+blocksize-1)/blocksize;
00886   // Prepare decoder
00887   GP<MMRDecoder> gdcd=MMRDecoder::create(gbs, width, height, striped);
00888   MMRDecoder &dcd=*gdcd;
00889   // Loop on JB2 bands
00890   int line = height-1;
00891   while (line >= 0)
00892     {
00893       int bandline = MIN(blocksize-1,line);
00894       GPArray<GBitmap> blocks(0,blocksperline-1);
00895       // Loop on scanlines
00896       for(; bandline >= 0; bandline--,line--)
00897       {
00898         // Decode one scanline
00899         const unsigned short *s = dcd.scanruns();
00900         if (s)
00901         {
00902       // Loop on blocks
00903           int x = 0;
00904           int b = 0;
00905           int firstx = 0;
00906           bool c = !!invert;
00907           while (x < width)
00908             {
00909               int xend = x + *s++;
00910               while (b<blocksperline)
00911                 {
00912                   int lastx = MIN(firstx+blocksize,width);
00913                   if (c)
00914                     {
00915                       if (!blocks[b])
00916                         blocks[b] = GBitmap::create(bandline+1, lastx-firstx);
00917                       unsigned char *bptr = (*blocks[b])[bandline] - firstx;
00918                       int x1 = MAX(x,firstx);
00919                       int x2 = MIN(xend,lastx);
00920                       while (x1 < x2)
00921                         bptr[x1++] = 1;
00922                     }
00923                   if (xend < lastx)
00924                     break;
00925                   firstx = lastx;
00926                   b ++;
00927                 }
00928               x = xend;
00929               c = !c; 
00930             }
00931     }
00932       }
00933       // Insert blocks into JB2Image
00934       for (int b=0; b<blocksperline; b++)
00935     {
00936       JB2Shape shape;
00937       shape.bits = blocks[b];
00938       if (shape.bits) 
00939         {
00940           shape.parent = -1;
00941           shape.bits->compress();
00942           JB2Blit blit;
00943           blit.left = b*blocksize;
00944           blit.bottom = line+1;
00945           blit.shapeno = jimg->add_shape(shape);
00946           jimg->add_blit(blit);
00947         }
00948     }
00949     }
00950   // Return
00951   return jimg;
00952 }
00953 
00954 
00955 
00956 #ifdef HAVE_NAMESPACES
00957 }
00958 # ifndef NOT_USING_DJVU_NAMESPACE
00959 using namespace DJVU;
00960 # endif
00961 #endif

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal