00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
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 
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 {   
00097   
00098   { 0x08,   4,    P }, 
00099   { 0x10,   3,    H }, 
00100   { 0x40,   1,   V0 }, 
00101   { 0x30,   3,  VR1 }, 
00102   { 0x06,   6,  VR2 }, 
00103   { 0x03,   7,  VR3 }, 
00104   { 0x20,   3,  VL1 }, 
00105   { 0x04,   6,  VL2 }, 
00106   { 0x02,   7,  VL3 }, 
00107   { 0x00,   0,   -1 }  
00108 };
00109 
00110 
00111 static const VLCode wcodes[] = {    
00112   
00113   { 0x06a0,  8,    0 }, 
00114   { 0x0380,  6,    1 }, 
00115   { 0x0e00,  4,    2 }, 
00116   { 0x1000,  4,    3 }, 
00117   { 0x1600,  4,    4 }, 
00118   { 0x1800,  4,    5 }, 
00119   { 0x1c00,  4,    6 }, 
00120   { 0x1e00,  4,    7 }, 
00121   { 0x1300,  5,    8 }, 
00122   { 0x1400,  5,    9 }, 
00123   { 0x0700,  5,   10 }, 
00124   { 0x0800,  5,   11 }, 
00125   { 0x0400,  6,   12 }, 
00126   { 0x0180,  6,   13 }, 
00127   { 0x1a00,  6,   14 }, 
00128   { 0x1a80,  6,   15 }, 
00129   { 0x1500,  6,   16 }, 
00130   { 0x1580,  6,   17 }, 
00131   { 0x09c0,  7,   18 }, 
00132   { 0x0300,  7,   19 }, 
00133   { 0x0200,  7,   20 }, 
00134   { 0x05c0,  7,   21 }, 
00135   { 0x00c0,  7,   22 }, 
00136   { 0x0100,  7,   23 }, 
00137   { 0x0a00,  7,   24 }, 
00138   { 0x0ac0,  7,   25 }, 
00139   { 0x04c0,  7,   26 }, 
00140   { 0x0900,  7,   27 }, 
00141   { 0x0600,  7,   28 }, 
00142   { 0x0040,  8,   29 }, 
00143   { 0x0060,  8,   30 }, 
00144   { 0x0340,  8,   31 }, 
00145   { 0x0360,  8,   32 }, 
00146   { 0x0240,  8,   33 }, 
00147   { 0x0260,  8,   34 }, 
00148   { 0x0280,  8,   35 }, 
00149   { 0x02a0,  8,   36 }, 
00150   { 0x02c0,  8,   37 }, 
00151   { 0x02e0,  8,   38 }, 
00152   { 0x0500,  8,   39 }, 
00153   { 0x0520,  8,   40 }, 
00154   { 0x0540,  8,   41 }, 
00155   { 0x0560,  8,   42 }, 
00156   { 0x0580,  8,   43 }, 
00157   { 0x05a0,  8,   44 }, 
00158   { 0x0080,  8,   45 }, 
00159   { 0x00a0,  8,   46 }, 
00160   { 0x0140,  8,   47 }, 
00161   { 0x0160,  8,   48 }, 
00162   { 0x0a40,  8,   49 }, 
00163   { 0x0a60,  8,   50 }, 
00164   { 0x0a80,  8,   51 }, 
00165   { 0x0aa0,  8,   52 }, 
00166   { 0x0480,  8,   53 }, 
00167   { 0x04a0,  8,   54 }, 
00168   { 0x0b00,  8,   55 }, 
00169   { 0x0b20,  8,   56 }, 
00170   { 0x0b40,  8,   57 }, 
00171   { 0x0b60,  8,   58 }, 
00172   { 0x0940,  8,   59 }, 
00173   { 0x0960,  8,   60 }, 
00174   { 0x0640,  8,   61 }, 
00175   { 0x0660,  8,   62 }, 
00176   { 0x0680,  8,   63 }, 
00177   { 0x1b00,  5,   64 }, 
00178   { 0x1200,  5,  128 }, 
00179   { 0x0b80,  6,  192 }, 
00180   { 0x0dc0,  7,  256 }, 
00181   { 0x06c0,  8,  320 }, 
00182   { 0x06e0,  8,  384 }, 
00183   { 0x0c80,  8,  448 }, 
00184   { 0x0ca0,  8,  512 }, 
00185   { 0x0d00,  8,  576 }, 
00186   { 0x0ce0,  8,  640 }, 
00187   { 0x0cc0,  9,  704 }, 
00188   { 0x0cd0,  9,  768 }, 
00189   { 0x0d20,  9,  832 }, 
00190   { 0x0d30,  9,  896 }, 
00191   { 0x0d40,  9,  960 }, 
00192   { 0x0d50,  9, 1024 }, 
00193   { 0x0d60,  9, 1088 }, 
00194   { 0x0d70,  9, 1152 }, 
00195   { 0x0d80,  9, 1216 }, 
00196   { 0x0d90,  9, 1280 }, 
00197   { 0x0da0,  9, 1344 }, 
00198   { 0x0db0,  9, 1408 }, 
00199   { 0x0980,  9, 1472 }, 
00200   { 0x0990,  9, 1536 }, 
00201   { 0x09a0,  9, 1600 }, 
00202   { 0x0c00,  6, 1664 }, 
00203   { 0x09b0,  9, 1728 }, 
00204   { 0x0020, 11, 1792 }, 
00205   { 0x0030, 11, 1856 }, 
00206   { 0x0034, 11, 1920 }, 
00207   { 0x0024, 12, 1984 }, 
00208   { 0x0026, 12, 2048 }, 
00209   { 0x0028, 12, 2112 }, 
00210   { 0x002a, 12, 2176 }, 
00211   { 0x002c, 12, 2240 }, 
00212   { 0x002e, 12, 2304 }, 
00213   { 0x0038, 12, 2368 }, 
00214   { 0x003a, 12, 2432 }, 
00215   { 0x003c, 12, 2496 }, 
00216   { 0x003e, 12, 2560 }, 
00217   { 0x0000,  0,   -1 }  
00218 };
00219 
00220 
00221 static const VLCode bcodes[] = {
00222   
00223   { 0x01b8, 10,    0 }, 
00224   { 0x0800,  3,    1 }, 
00225   { 0x1800,  2,    2 }, 
00226   { 0x1000,  2,    3 }, 
00227   { 0x0c00,  3,    4 }, 
00228   { 0x0600,  4,    5 }, 
00229   { 0x0400,  4,    6 }, 
00230   { 0x0300,  5,    7 }, 
00231   { 0x0280,  6,    8 }, 
00232   { 0x0200,  6,    9 }, 
00233   { 0x0100,  7,   10 }, 
00234   { 0x0140,  7,   11 }, 
00235   { 0x01c0,  7,   12 }, 
00236   { 0x0080,  8,   13 }, 
00237   { 0x00e0,  8,   14 }, 
00238   { 0x0180,  9,   15 }, 
00239   { 0x00b8, 10,   16 }, 
00240   { 0x00c0, 10,   17 }, 
00241   { 0x0040, 10,   18 }, 
00242   { 0x019c, 11,   19 }, 
00243   { 0x01a0, 11,   20 }, 
00244   { 0x01b0, 11,   21 }, 
00245   { 0x00dc, 11,   22 }, 
00246   { 0x00a0, 11,   23 }, 
00247   { 0x005c, 11,   24 }, 
00248   { 0x0060, 11,   25 }, 
00249   { 0x0194, 12,   26 }, 
00250   { 0x0196, 12,   27 }, 
00251   { 0x0198, 12,   28 }, 
00252   { 0x019a, 12,   29 }, 
00253   { 0x00d0, 12,   30 }, 
00254   { 0x00d2, 12,   31 }, 
00255   { 0x00d4, 12,   32 }, 
00256   { 0x00d6, 12,   33 }, 
00257   { 0x01a4, 12,   34 }, 
00258   { 0x01a6, 12,   35 }, 
00259   { 0x01a8, 12,   36 }, 
00260   { 0x01aa, 12,   37 }, 
00261   { 0x01ac, 12,   38 }, 
00262   { 0x01ae, 12,   39 }, 
00263   { 0x00d8, 12,   40 }, 
00264   { 0x00da, 12,   41 }, 
00265   { 0x01b4, 12,   42 }, 
00266   { 0x01b6, 12,   43 }, 
00267   { 0x00a8, 12,   44 }, 
00268   { 0x00aa, 12,   45 }, 
00269   { 0x00ac, 12,   46 }, 
00270   { 0x00ae, 12,   47 }, 
00271   { 0x00c8, 12,   48 }, 
00272   { 0x00ca, 12,   49 }, 
00273   { 0x00a4, 12,   50 }, 
00274   { 0x00a6, 12,   51 }, 
00275   { 0x0048, 12,   52 }, 
00276   { 0x006e, 12,   53 }, 
00277   { 0x0070, 12,   54 }, 
00278   { 0x004e, 12,   55 }, 
00279   { 0x0050, 12,   56 }, 
00280   { 0x00b0, 12,   57 }, 
00281   { 0x00b2, 12,   58 }, 
00282   { 0x0056, 12,   59 }, 
00283   { 0x0058, 12,   60 }, 
00284   { 0x00b4, 12,   61 }, 
00285   { 0x00cc, 12,   62 }, 
00286   { 0x00ce, 12,   63 }, 
00287   { 0x0078, 10,   64 }, 
00288   { 0x0190, 12,  128 }, 
00289   { 0x0192, 12,  192 }, 
00290   { 0x00b6, 12,  256 }, 
00291   { 0x0066, 12,  320 }, 
00292   { 0x0068, 12,  384 }, 
00293   { 0x006a, 12,  448 }, 
00294   { 0x006c, 13,  512 }, 
00295   { 0x006d, 13,  576 }, 
00296   { 0x004a, 13,  640 }, 
00297   { 0x004b, 13,  704 }, 
00298   { 0x004c, 13,  768 }, 
00299   { 0x004d, 13,  832 }, 
00300   { 0x0072, 13,  896 }, 
00301   { 0x0073, 13,  960 }, 
00302   { 0x0074, 13, 1024 }, 
00303   { 0x0075, 13, 1088 }, 
00304   { 0x0076, 13, 1152 }, 
00305   { 0x0077, 13, 1216 }, 
00306   { 0x0052, 13, 1280 }, 
00307   { 0x0053, 13, 1344 }, 
00308   { 0x0054, 13, 1408 }, 
00309   { 0x0055, 13, 1472 }, 
00310   { 0x005a, 13, 1536 }, 
00311   { 0x005b, 13, 1600 }, 
00312   { 0x0064, 13, 1664 }, 
00313   { 0x0065, 13, 1728 }, 
00314   { 0x0020, 11, 1792 }, 
00315   { 0x0030, 11, 1856 }, 
00316   { 0x0034, 11, 1920 }, 
00317   { 0x0024, 12, 1984 }, 
00318   { 0x0026, 12, 2048 }, 
00319   { 0x0028, 12, 2112 }, 
00320   { 0x002a, 12, 2176 }, 
00321   { 0x002c, 12, 2240 }, 
00322   { 0x002e, 12, 2304 }, 
00323   { 0x0038, 12, 2368 }, 
00324   { 0x003a, 12, 2432 }, 
00325   { 0x003c, 12, 2496 }, 
00326   { 0x003e, 12, 2560 }, 
00327   { 0x0000,  0,   -1 }  
00328 };
00329 
00330 
00331 
00332 
00333 
00334 
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   
00345   static GP<VLSource> create(GP<ByteStream> &inp, const bool striped);
00346 
00347   
00348   void nextstripe(void);
00349   
00350   
00351   inline unsigned int peek(void);
00352   
00353   
00354   void preload(void);
00355   
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           
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 
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   
00464   static GP<VLTable> create(VLCode const * const codes, const int nbits);
00465 
00466   
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   
00500   int ncodes = 0;
00501   while (code[ncodes].codelen)
00502     ncodes++;
00503   
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   
00510   int size = (1<<nbits);
00511   gindex.resize(size);
00512   gindex.set(ncodes);
00513   
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     
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 
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   
00574   if (lineno >= height)
00575     return 0;
00576   
00577   if ( striplineno == rowsperstrip )
00578     {
00579       striplineno=0;
00580       lineruns[0] = prevruns[0] = width;
00581       src->nextstripe();
00582     }
00583   
00584   unsigned short *pr = lineruns;
00585   unsigned short *xr = prevruns;
00586   prevruns = pr;
00587   lineruns = xr;
00588   
00589   bool a0color = false;
00590   int a0,rle,b1;
00591   for(a0=0,rle=0,b1=*pr++;a0 < width;)
00592     {
00593       
00594       const int c=mrtable->decode(src);
00595       switch ( c )
00596       {
00597           
00598         case P: 
00599           { 
00600             b1 += *pr++;
00601             rle += b1 - a0;
00602             a0 = b1;
00603             b1 += *pr++;
00604             break;
00605           }
00606           
00607         case H: 
00608           { 
00609             
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             
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           
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           
00669         default: 
00670           {
00671             src->preload();
00672             unsigned int m = src->peek();
00673             
00674             
00675             if ((m & 0xffffff00) == 0x00100100)
00676               {
00677                 lineno = height;
00678                 return 0;
00679               }
00680             
00681             
00682             
00683             else if ((m & 0xffc00000) == 0x03c00000)
00684               {
00685 #ifdef MMRDECODER_REFUSES_UNCOMPRESSED
00686                 G_THROW( ERR_MSG("MMRDecoder.cant_process") );
00687 #else
00688                 
00689                 src->shift(10);
00690                 while ((m = (src->peek() & 0xfc000000)))
00691                   {
00692                     if (m == 0x04000000)       
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                       
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                 
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                 
00741                 break;
00742 #endif
00743               }
00744             
00745             G_THROW(invalid_mmr_data);
00746           }
00747       }
00748       
00749       for(;b1<=a0 && b1<width;pr+=2)
00750       {
00751         b1 += pr[0]+pr[1];
00752       }
00753     }
00754   
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   
00768   
00769   
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   
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   
00796   const unsigned short *xr = scanruns();
00797   if (!xr) return 0;
00798   unsigned char *p=line;
00799   
00800   if (invert)
00801     {
00802       if (! *xr) 
00803       {
00804         xr++;
00805       }else
00806       {
00807         *p = 0; p++;
00808       }
00809     }
00810   
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   
00830   const unsigned short *xr = scanruns();
00831   if (!xr) return 0;
00832   
00833   unsigned char *p = line;
00834   
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 
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   
00878   int width, height, invert;
00879   const bool striped=decode_header(inp, width, height, invert);
00880   
00881   GP<JB2Image> jimg = JB2Image::create();
00882   jimg->set_dimension(width, height);
00883   
00884   int blocksize = MIN(500,MAX(64,MAX(width/17,height/22)));
00885   int blocksperline = (width+blocksize-1)/blocksize;
00886   
00887   GP<MMRDecoder> gdcd=MMRDecoder::create(gbs, width, height, striped);
00888   MMRDecoder &dcd=*gdcd;
00889   
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       
00896       for(; bandline >= 0; bandline--,line--)
00897       {
00898         
00899         const unsigned short *s = dcd.scanruns();
00900         if (s)
00901         {
00902       
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       
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   
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