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