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
00065
00066
00067
00068
00069 #define IW44IMAGE_IMPLIMENTATION
00070
00071
00072
00073 #include "IW44Image.h"
00074 #include "ZPCodec.h"
00075 #include "GBitmap.h"
00076 #include "GPixmap.h"
00077 #include "IFFByteStream.h"
00078 #include "GRect.h"
00079
00080 #include <stdlib.h>
00081 #include <string.h>
00082 #include <math.h>
00083 #include "MMX.h"
00084 #undef IWTRANSFORM_TIMER
00085 #ifdef IWTRANSFORM_TIMER
00086 #include "GOS.h"
00087 #endif
00088
00089 #include <assert.h>
00090 #include <string.h>
00091 #include <math.h>
00092
00093 #ifndef NEED_DECODER_ONLY
00094
00095
00096 #ifdef HAVE_NAMESPACES
00097 namespace DJVU {
00098 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00099 }
00100 #endif
00101 #endif
00102
00103 #define IWALLOCSIZE 4080
00104 #define IWCODEC_MAJOR 1
00105 #define IWCODEC_MINOR 2
00106 #define DECIBEL_PRUNE 5.0
00107
00108
00110
00112
00113
00114
00115
00116
00117
00118 static const float iw_norm[16] = {
00119 2.627989e+03F,
00120 1.832893e+02F, 1.832959e+02F, 5.114690e+01F,
00121 4.583344e+01F, 4.583462e+01F, 1.279225e+01F,
00122 1.149671e+01F, 1.149712e+01F, 3.218888e+00F,
00123 2.999281e+00F, 2.999476e+00F, 8.733161e-01F,
00124 1.074451e+00F, 1.074511e+00F, 4.289318e-01F
00125 };
00126
00127 static const int iw_shift = 6;
00128 static const int iw_round = (1<<(iw_shift-1));
00129
00130 static const struct { int start; int size; }
00131 bandbuckets[] =
00132 {
00133
00134 { 0, 1 },
00135 { 1, 1 }, { 2, 1 }, { 3, 1 },
00136 { 4, 4 }, { 8, 4 }, { 12,4 },
00137 { 16,16 }, { 32,16 }, { 48,16 },
00138 };
00139
00140
00151 class IWBitmap::Encode : public IWBitmap
00152 {
00153 public:
00155 virtual ~Encode(void);
00160 Encode(void);
00165 void init(const GBitmap &bm, const GP<GBitmap> mask=0);
00166
00172 virtual int encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parms);
00177 virtual void encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms);
00182 virtual void close_codec(void);
00183 protected:
00184 Codec::Encode *ycodec_enc;
00185 };
00186
00197 class IWPixmap::Encode : public IWPixmap
00198 {
00199 public:
00200 enum CRCBMode {
00201 CRCBnone=IW44Image::CRCBnone,
00202 CRCBhalf=IW44Image::CRCBhalf,
00203 CRCBnormal=IW44Image::CRCBnormal,
00204 CRCBfull=IW44Image::CRCBfull };
00206 virtual ~Encode(void);
00211 Encode(void);
00218 void init(const GPixmap &bm, const GP<GBitmap> mask=0, CRCBMode crcbmode=CRCBnormal);
00219
00225 virtual int encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parms);
00230 virtual void encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms);
00235 virtual void close_codec(void);
00236 protected:
00237 Codec::Encode *ycodec_enc, *cbcodec_enc, *crcodec_enc;
00238 };
00239
00240 class IW44Image::Map::Encode : public IW44Image::Map
00241 {
00242 public:
00243 Encode(const int w, const int h) : Map(w,h) {}
00244
00245 void create(const signed char *img8, int imgrowsize,
00246 const signed char *msk8=0, int mskrowsize=0);
00247
00248 void slashres(int res);
00249 };
00250
00251 class IW44Image::Codec::Encode : public IW44Image::Codec
00252 {
00253 public:
00254 Encode(IW44Image::Map &map);
00255
00256 virtual int code_slice(ZPCodec &zp);
00257 float estimate_decibel(float frac);
00258
00259 void encode_buckets(ZPCodec &zp, int bit, int band,
00260 IW44Image::Block &blk, IW44Image::Block &eblk, int fbucket, int nbucket);
00261 int encode_prepare(int band, int fbucket, int nbucket, IW44Image::Block &blk, IW44Image::Block &eblk);
00262 IW44Image::Map emap;
00263 };
00264
00265 IW44Image::Codec::Encode::Encode(IW44Image::Map &map)
00266 : Codec(map), emap(map.iw,map.ih) {}
00267
00269
00272 class IW44Image::Transform::Encode : IW44Image::Transform
00273 {
00274 public:
00275
00277 static void forward(short *p, int w, int h, int rowsize, int begin, int end);
00278
00279
00281 static void RGB_to_Y(const GPixel *p, int w, int h, int rowsize,
00282 signed char *out, int outrowsize);
00284 static void RGB_to_Cb(const GPixel *p, int w, int h, int rowsize,
00285 signed char *out, int outrowsize);
00287 static void RGB_to_Cr(const GPixel *p, int w, int h, int rowsize,
00288 signed char *out, int outrowsize);
00289 };
00290
00291
00293
00295
00296
00297
00298
00299
00300
00301
00302 #ifdef MMX
00303
00304 static const short w9[] = {9,9,9,9};
00305 static const short w1[] = {1,1,1,1};
00306 static const int d8[] = {8,8};
00307 static const int d16[] = {16,16};
00308
00309
00310 static inline void
00311 mmx_fv_1 ( short* &q, short* e, int s, int s3 )
00312 {
00313 while (q<e && (((long)q)&0x7))
00314 {
00315 int a = (int)q[-s] + (int)q[s];
00316 int b = (int)q[-s3] + (int)q[s3];
00317 *q -= (((a<<3)+a-b+8)>>4);
00318 q++;
00319 }
00320 while (q+3<e)
00321 {
00322 MMXar( movq, q-s,mm0);
00323 MMXar( movq, q+s,mm2);
00324 MMXrr( movq, mm0,mm1);
00325 MMXrr( punpcklwd, mm2,mm0);
00326 MMXrr( punpckhwd, mm2,mm1);
00327 MMXar( pmaddwd, w9,mm0);
00328 MMXar( pmaddwd, w9,mm1);
00329 MMXar( movq, q-s3,mm2);
00330 MMXar( movq, q+s3,mm4);
00331 MMXrr( movq, mm2,mm3);
00332 MMXrr( punpcklwd, mm4,mm2);
00333 MMXrr( punpckhwd, mm4,mm3);
00334 MMXar( pmaddwd, w1,mm2);
00335 MMXar( pmaddwd, w1,mm3);
00336 MMXar( paddd, d8,mm0);
00337 MMXar( paddd, d8,mm1);
00338 MMXrr( psubd, mm2,mm0);
00339 MMXrr( psubd, mm3,mm1);
00340 MMXir( psrad, 4,mm0);
00341 MMXar( movq, q,mm7);
00342 MMXir( psrad, 4,mm1);
00343 MMXrr( packssdw, mm1,mm0);
00344 MMXrr( psubw, mm0,mm7);
00345 MMXra( movq, mm7,q);
00346 #if defined(_MSC_VER) && defined(_DEBUG)
00347 MMXemms;
00348 #endif
00349 q += 4;
00350 }
00351 }
00352
00353 static inline void
00354 mmx_fv_2 ( short* &q, short* e, int s, int s3 )
00355 {
00356 while (q<e && (((long)q)&0x7))
00357 {
00358 int a = (int)q[-s] + (int)q[s];
00359 int b = (int)q[-s3] + (int)q[s3];
00360 *q += (((a<<3)+a-b+16)>>5);
00361 q ++;
00362 }
00363 while (q+3<e)
00364 {
00365 MMXar( movq, q-s,mm0);
00366 MMXar( movq, q+s,mm2);
00367 MMXrr( movq, mm0,mm1);
00368 MMXrr( punpcklwd, mm2,mm0);
00369 MMXrr( punpckhwd, mm2,mm1);
00370 MMXar( pmaddwd, w9,mm0);
00371 MMXar( pmaddwd, w9,mm1);
00372 MMXar( movq, q-s3,mm2);
00373 MMXar( movq, q+s3,mm4);
00374 MMXrr( movq, mm2,mm3);
00375 MMXrr( punpcklwd, mm4,mm2);
00376 MMXrr( punpckhwd, mm4,mm3);
00377 MMXar( pmaddwd, w1,mm2);
00378 MMXar( pmaddwd, w1,mm3);
00379 MMXar( paddd, d16,mm0);
00380 MMXar( paddd, d16,mm1);
00381 MMXrr( psubd, mm2,mm0);
00382 MMXrr( psubd, mm3,mm1);
00383 MMXir( psrad, 5,mm0);
00384 MMXar( movq, q,mm7);
00385 MMXir( psrad, 5,mm1);
00386 MMXrr( packssdw, mm1,mm0);
00387 MMXrr( paddw, mm0,mm7);
00388 MMXra( movq, mm7,q);
00389 #if defined(_MSC_VER) && defined(_DEBUG)
00390 MMXemms;
00391 #endif
00392 q += 4;
00393 }
00394 }
00395
00396 #endif
00397
00399
00401
00402 static void
00403 filter_fv(short *p, int w, int h, int rowsize, int scale)
00404 {
00405 int y = 0;
00406 int s = scale*rowsize;
00407 int s3 = s+s+s;
00408 h = ((h-1)/scale)+1;
00409 y += 1;
00410 p += s;
00411 while (y-3 < h)
00412 {
00413
00414 {
00415 short *q = p;
00416 short *e = q+w;
00417 if (y>=3 && y+3<h)
00418 {
00419
00420 #ifdef MMX
00421 if (scale==1 && MMXControl::mmxflag>0)
00422 mmx_fv_1(q, e, s, s3);
00423 #endif
00424 while (q<e)
00425 {
00426 int a = (int)q[-s] + (int)q[s];
00427 int b = (int)q[-s3] + (int)q[s3];
00428 *q -= (((a<<3)+a-b+8)>>4);
00429 q += scale;
00430 }
00431 }
00432 else if (y<h)
00433 {
00434
00435 short *q1 = (y+1<h ? q+s : q-s);
00436 while (q<e)
00437 {
00438 int a = (int)q[-s] + (int)(*q1);
00439 *q -= ((a+1)>>1);
00440 q += scale;
00441 q1 += scale;
00442 }
00443 }
00444 }
00445
00446 {
00447 short *q = p-s3;
00448 short *e = q+w;
00449 if (y>=6 && y<h)
00450 {
00451
00452 #ifdef MMX
00453 if (scale==1 && MMXControl::mmxflag>0)
00454 mmx_fv_2(q, e, s, s3);
00455 #endif
00456 while (q<e)
00457 {
00458 int a = (int)q[-s] + (int)q[s];
00459 int b = (int)q[-s3] + (int)q[s3];
00460 *q += (((a<<3)+a-b+16)>>5);
00461 q += scale;
00462 }
00463 }
00464 else if (y>=3)
00465 {
00466
00467 short *q1 = (y-2<h ? q+s : 0);
00468 short *q3 = (y<h ? q+s3 : 0);
00469 if (y>=6)
00470 {
00471 while (q<e)
00472 {
00473 int a = (int)q[-s] + (q1 ? (int)(*q1) : 0);
00474 int b = (int)q[-s3] + (q3 ? (int)(*q3) : 0);
00475 *q += (((a<<3)+a-b+16)>>5);
00476 q += scale;
00477 if (q1) q1 += scale;
00478 if (q3) q3 += scale;
00479 }
00480 }
00481 else if (y>=4)
00482 {
00483 while (q<e)
00484 {
00485 int a = (int)q[-s] + (q1 ? (int)(*q1) : 0);
00486 int b = (q3 ? (int)(*q3) : 0);
00487 *q += (((a<<3)+a-b+16)>>5);
00488 q += scale;
00489 if (q1) q1 += scale;
00490 if (q3) q3 += scale;
00491 }
00492 }
00493 else
00494 {
00495 while (q<e)
00496 {
00497 int a = (q1 ? (int)(*q1) : 0);
00498 int b = (q3 ? (int)(*q3) : 0);
00499 *q += (((a<<3)+a-b+16)>>5);
00500 q += scale;
00501 if (q1) q1 += scale;
00502 if (q3) q3 += scale;
00503 }
00504 }
00505 }
00506 }
00507 y += 2;
00508 p += s+s;
00509 }
00510 }
00511
00512 static void
00513 filter_fh(short *p, int w, int h, int rowsize, int scale)
00514 {
00515 int y = 0;
00516 int s = scale;
00517 int s3 = s+s+s;
00518 rowsize *= scale;
00519 while (y<h)
00520 {
00521 short *q = p+s;
00522 short *e = p+w;
00523 int a0=0, a1=0, a2=0, a3=0;
00524 int b0=0, b1=0, b2=0, b3=0;
00525 if (q < e)
00526 {
00527
00528 a1 = a2 = a3 = q[-s];
00529 if (q+s<e)
00530 a2 = q[s];
00531 if (q+s3<e)
00532 a3 = q[s3];
00533 b3 = q[0] - ((a1+a2+1)>>1);
00534 q[0] = b3;
00535 q += s+s;
00536 }
00537 while (q+s3 < e)
00538 {
00539
00540 a0=a1;
00541 a1=a2;
00542 a2=a3;
00543 a3=q[s3];
00544 b0=b1;
00545 b1=b2;
00546 b2=b3;
00547 b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+8) >> 4);
00548 q[0] = b3;
00549 q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+16) >> 5);
00550 q += s+s;
00551 }
00552 while (q < e)
00553 {
00554
00555 a1=a2;
00556 a2=a3;
00557 b0=b1;
00558 b1=b2;
00559 b2=b3;
00560 b3 = q[0] - ((a1+a2+1)>>1);
00561 q[0] = b3;
00562 q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+16) >> 5);
00563 q += s+s;
00564 }
00565 while (q-s3 < e)
00566 {
00567
00568 b0=b1;
00569 b1=b2;
00570 b2=b3;
00571 b3=0;
00572 if (q-s3 >= p)
00573 q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+16) >> 5);
00574 q += s+s;
00575 }
00576 y += scale;
00577 p += rowsize;
00578 }
00579 }
00580
00581
00583
00585
00586
00587
00588
00589
00590
00591 void
00592 IW44Image::Transform::Encode::forward(short *p, int w, int h, int rowsize, int begin, int end)
00593 {
00594
00595
00596 filter_begin(w,h);
00597
00598 for (int scale=begin; scale<end; scale<<=1)
00599 {
00600 #ifdef IWTRANSFORM_TIMER
00601 int tv,th;
00602 th = tv = GOS::ticks();
00603 #endif
00604 filter_fh(p, w, h, rowsize, scale);
00605 #ifdef IWTRANSFORM_TIMER
00606 th = GOS::ticks();
00607 tv = th - tv;
00608 #endif
00609 filter_fv(p, w, h, rowsize, scale);
00610 #ifdef IWTRANSFORM_TIMER
00611 th = GOS::ticks()-th;
00612 DjVuPrintErrorUTF8("forw%d\tv=%dms h=%dms\n", scale,th,tv);
00613 #endif
00614 }
00615
00616 filter_end();
00617 }
00618
00620
00622
00623 static const float
00624 rgb_to_ycc[3][3] =
00625 { { 0.304348F, 0.608696F, 0.086956F },
00626 { 0.463768F, -0.405797F, -0.057971F },
00627 {-0.173913F, -0.347826F, 0.521739F } };
00628
00629
00630
00631 void
00632 IW44Image::Transform::Encode::RGB_to_Y(const GPixel *p, int w, int h, int rowsize,
00633 signed char *out, int outrowsize)
00634 {
00635 int rmul[256], gmul[256], bmul[256];
00636 for (int k=0; k<256; k++)
00637 {
00638 rmul[k] = (int)(k*0x10000*rgb_to_ycc[0][0]);
00639 gmul[k] = (int)(k*0x10000*rgb_to_ycc[0][1]);
00640 bmul[k] = (int)(k*0x10000*rgb_to_ycc[0][2]);
00641 }
00642 for (int i=0; i<h; i++, p+=rowsize, out+=outrowsize)
00643 {
00644 const GPixel *p2 = p;
00645 signed char *out2 = out;
00646 for (int j=0; j<w; j++,p2++,out2++)
00647 {
00648 int y = rmul[p2->r] + gmul[p2->g] + bmul[p2->b] + 32768;
00649 *out2 = (y>>16) - 128;
00650 }
00651 }
00652 }
00653
00654 #ifdef min
00655 #undef min
00656 #endif
00657 static inline int min(const int x,const int y) {return (x<y)?x:y;}
00658 #ifdef max
00659 #undef max
00660 #endif
00661 static inline int max(const int x,const int y) {return (x>y)?x:y;}
00662
00663
00664 void
00665 IW44Image::Transform::Encode::RGB_to_Cb(const GPixel *p, int w, int h, int rowsize,
00666 signed char *out, int outrowsize)
00667 {
00668 int rmul[256], gmul[256], bmul[256];
00669 for (int k=0; k<256; k++)
00670 {
00671 rmul[k] = (int)(k*0x10000*rgb_to_ycc[2][0]);
00672 gmul[k] = (int)(k*0x10000*rgb_to_ycc[2][1]);
00673 bmul[k] = (int)(k*0x10000*rgb_to_ycc[2][2]);
00674 }
00675 for (int i=0; i<h; i++, p+=rowsize, out+=outrowsize)
00676 {
00677 const GPixel *p2 = p;
00678 signed char *out2 = out;
00679 for (int j=0; j<w; j++,p2++,out2++)
00680 {
00681 int c = rmul[p2->r] + gmul[p2->g] + bmul[p2->b] + 32768;
00682 *out2 = max(-128, min(127, c>>16));
00683 }
00684 }
00685 }
00686
00687
00688 void
00689 IW44Image::Transform::Encode::RGB_to_Cr(const GPixel *p, int w, int h, int rowsize,
00690 signed char *out, int outrowsize)
00691 {
00692 int rmul[256], gmul[256], bmul[256];
00693 for (int k=0; k<256; k++)
00694 {
00695 rmul[k] = (int)((k*0x10000)*rgb_to_ycc[1][0]);
00696 gmul[k] = (int)((k*0x10000)*rgb_to_ycc[1][1]);
00697 bmul[k] = (int)((k*0x10000)*rgb_to_ycc[1][2]);
00698 }
00699 for (int i=0; i<h; i++, p+=rowsize, out+=outrowsize)
00700 {
00701 const GPixel *p2 = p;
00702 signed char *out2 = out;
00703 for (int j=0; j<w; j++,p2++,out2++)
00704 {
00705 int c = rmul[p2->r] + gmul[p2->g] + bmul[p2->b] + 32768;
00706 *out2 = max(-128, min(127, c>>16));
00707 }
00708 }
00709 }
00710
00711
00713
00715
00716
00717
00718
00719
00720
00721
00722 static void
00723 interpolate_mask(short *data16, int w, int h, int rowsize,
00724 const signed char *mask8, int mskrowsize)
00725 {
00726 int i,j;
00727
00728 short *count;
00729 GPBuffer<short> gcount(count,w*h);
00730 short *cp = count;
00731 for (i=0; i<h; i++, cp+=w, mask8+=mskrowsize)
00732 for (j=0; j<w; j++)
00733 cp[j] = (mask8[j] ? 0 : 0x1000);
00734
00735 short *sdata;
00736 GPBuffer<short> gsdata(sdata,w*h);
00737 short *p = sdata;
00738 short *q = data16;
00739 for (i=0; i<h; i++, p+=w, q+=rowsize)
00740 for (j=0; j<w; j++)
00741 p[j] = q[j];
00742
00743 int split = 1;
00744 int scale = 2;
00745 int again = 1;
00746 while (again && scale<w && scale<h)
00747 {
00748 again = 0;
00749 p = data16;
00750 q = sdata;
00751 cp = count;
00752
00753 for (i=0; i<h; i+=scale, cp+=w*scale, q+=w*scale, p+=rowsize*scale)
00754 for (j=0; j<w; j+=scale)
00755 {
00756 int ii, jj;
00757 int gotz = 0;
00758 int gray = 0;
00759 int npix = 0;
00760 short *cpp = cp;
00761 short *qq = q;
00762
00763 int istart = i;
00764 if (istart+split>h)
00765 {
00766 istart -= scale;
00767 cpp -= w*scale;
00768 qq -= w*scale;
00769 }
00770 int jstart = j;
00771 if (jstart+split>w)
00772 jstart -= scale;
00773
00774 for (ii=istart; ii<i+scale && ii<h; ii+=split, cpp+=w*split, qq+=w*split)
00775 for (jj=jstart; jj<j+scale && jj<w; jj+=split)
00776 {
00777 if (cpp[jj]>0)
00778 {
00779 npix += cpp[jj];
00780 gray += cpp[jj] * qq[jj];
00781 }
00782 else if (ii>=i && jj>=j)
00783 {
00784 gotz = 1;
00785 }
00786 }
00787
00788 if (npix == 0)
00789 {
00790
00791 again = 1;
00792 cp[j] = 0;
00793 }
00794 else
00795 {
00796 gray = gray / npix;
00797
00798 if (gotz)
00799 {
00800 cpp = cp;
00801 qq = p;
00802 for (ii=i; ii<i+scale && ii<h; ii+=1, cpp+=w, qq+=rowsize)
00803 for (jj=j; jj<j+scale && jj<w; jj+=1)
00804 if (cpp[jj] == 0)
00805 {
00806 qq[jj] = gray;
00807 cpp[jj] = 1;
00808 }
00809 }
00810
00811 cp[j] = npix>>2;
00812 q[j] = gray;
00813 }
00814 }
00815
00816 split = scale;
00817 scale = scale+scale;
00818 }
00819 }
00820
00821
00822 static void
00823 forward_mask(short *data16, int w, int h, int rowsize, int begin, int end,
00824 const signed char *mask8, int mskrowsize )
00825 {
00826 int i,j;
00827 signed char *m;
00828 short *p;
00829 short *d;
00830
00831 short *sdata;
00832 GPBuffer<short> gsdata(sdata,w*h);
00833 signed char *smask;
00834 GPBuffer<signed char> gsmask(smask,w*h);
00835
00836 m = smask;
00837 for (i=0; i<h; i+=1, m+=w, mask8+=mskrowsize)
00838 memcpy((void*)m, (void*)mask8, w);
00839
00840 for (int scale=begin; scale<end; scale<<=1)
00841 {
00842
00843 p = data16;
00844 d = sdata;
00845 for (i=0; i<h; i+=scale)
00846 {
00847 for (j=0; j<w; j+=scale)
00848 d[j] = p[j];
00849 p += rowsize * scale;
00850 d += w * scale;
00851 }
00852
00853 IW44Image::Transform::Encode::forward(sdata, w, h, w, scale, scale+scale);
00854
00855 d = sdata;
00856 m = smask;
00857 for (i=0; i<h; i+=scale+scale)
00858 {
00859 for (j=scale; j<w; j+=scale+scale)
00860 if (m[j])
00861 d[j] = 0;
00862 d += w * scale;
00863 m += w * scale;
00864 if (i+scale < h)
00865 {
00866 for (j=0; j<w; j+=scale)
00867 if (m[j])
00868 d[j] = 0;
00869 d += w * scale;
00870 m += w * scale;
00871 }
00872 }
00873
00874 IW44Image::Transform::Decode::backward(sdata, w, h, w, scale+scale, scale);
00875
00876 p = data16;
00877 d = sdata;
00878 m = smask;
00879 for (i=0; i<h; i+=scale)
00880 {
00881 for (j=0; j<w; j+=scale)
00882 if (! m[j])
00883 d[j] = p[j];
00884 p += rowsize*scale;
00885 m += w*scale;
00886 d += w*scale;
00887 }
00888
00889 IW44Image::Transform::Encode::forward(sdata, w, h, w, scale, scale+scale);
00890
00891 p = data16;
00892 d = sdata;
00893 for (i=0; i<h; i+=scale)
00894 {
00895 for (j=0; j<w; j+=scale)
00896 p[j] = d[j];
00897 p += rowsize * scale;
00898 d += w * scale;
00899 }
00900
00901 m = smask;
00902 signed char *m0 = m;
00903 signed char *m1 = m;
00904 for (i=0; i<h; i+=scale+scale)
00905 {
00906 m0 = m1;
00907 if (i+scale < h)
00908 m1 = m + w*scale;
00909 for (j=0; j<w; j+=scale+scale)
00910 if (m[j] && m0[j] && m1[j] && (j<=0 || m[j-scale]) && (j+scale>=w || m[j+scale]))
00911 m[j] = 1;
00912 else
00913 m[j] = 0;
00914 m = m1 + w*scale;
00915 }
00916 }
00917
00918 }
00919
00920 void
00921 IW44Image::Map::Encode::create(const signed char *img8, int imgrowsize,
00922 const signed char *msk8, int mskrowsize )
00923 {
00924 int i, j;
00925
00926 DJVU_PROGRESS_TASK(transf,"create iw44 map",3);
00927
00928 short *data16;
00929 GPBuffer<short> gdata16(data16,bw*bh);
00930
00931 short *p = data16;
00932 const signed char *row = img8;
00933 for (i=0; i<ih; i++)
00934 {
00935 for (j=0; j<iw; j++)
00936 *p++ = (int)(row[j]) << iw_shift;
00937 row += imgrowsize;
00938 for (j=iw; j<bw; j++)
00939 *p++ = 0;
00940 }
00941 for (i=ih; i<bh; i++)
00942 for (j=0; j<bw; j++)
00943 *p++ = 0;
00944
00945 if (msk8)
00946 {
00947
00948 DJVU_PROGRESS_RUN(transf, 1);
00949 interpolate_mask(data16, iw, ih, bw, msk8, mskrowsize);
00950
00951 DJVU_PROGRESS_RUN(transf, 3);
00952 forward_mask(data16, iw, ih, bw, 1, 32, msk8, mskrowsize);
00953 }
00954 else
00955 {
00956
00957 DJVU_PROGRESS_RUN(transf, 3);
00958 IW44Image::Transform::Encode::forward(data16, iw, ih, bw, 1, 32);
00959 }
00960
00961 p = data16;
00962 IW44Image::Block *block = blocks;
00963 for (i=0; i<bh; i+=32)
00964 {
00965 for (j=0; j<bw; j+=32)
00966 {
00967 short liftblock[1024];
00968
00969 short *pp = p + j;
00970 short *pl = liftblock;
00971 for (int ii=0; ii<32; ii++, pp+=bw)
00972 for (int jj=0; jj<32; jj++)
00973 *pl++ = pp[jj];
00974
00975 block->read_liftblock(liftblock, this);
00976 block++;
00977 }
00978
00979 p += 32*bw;
00980 }
00981 }
00982
00983 void
00984 IW44Image::Map::Encode::slashres(int res)
00985 {
00986 int minbucket = 1;
00987 if (res < 2)
00988 return;
00989 else if (res < 4)
00990 minbucket=16;
00991 else if (res < 8)
00992 minbucket=4;
00993 for (int blockno=0; blockno<nb; blockno++)
00994 for (int buckno=minbucket; buckno<64; buckno++)
00995 blocks[blockno].zero(buckno);
00996 }
00997
00998
00999
01000 int
01001 IW44Image::Codec::Encode::encode_prepare(int band, int fbucket, int nbucket, IW44Image::Block &blk, IW44Image::Block &eblk)
01002 {
01003 int bbstate = 0;
01004
01005 if (band)
01006 {
01007
01008 int thres = quant_hi[band];
01009 char *cstate = coeffstate;
01010 for (int buckno=0; buckno<nbucket; buckno++, cstate+=16)
01011 {
01012 const short *pcoeff = blk.data(fbucket+buckno);
01013 const short *epcoeff = eblk.data(fbucket+buckno);
01014 int bstatetmp = 0;
01015 if (! pcoeff)
01016 {
01017 bstatetmp = UNK;
01018
01019 }
01020 else if (! epcoeff)
01021 {
01022 for (int i=0; i<16; i++)
01023 {
01024 int cstatetmp = UNK;
01025 if ((int)(pcoeff[i])>=thres || (int)(pcoeff[i])<=-thres)
01026 cstatetmp = NEW|UNK;
01027 cstate[i] = cstatetmp;
01028 bstatetmp |= cstatetmp;
01029 }
01030 }
01031 else
01032 {
01033 for (int i=0; i<16; i++)
01034 {
01035 int cstatetmp = UNK;
01036 if (epcoeff[i])
01037 cstatetmp = ACTIVE;
01038 else if ((int)(pcoeff[i])>=thres || (int)(pcoeff[i])<=-thres)
01039 cstatetmp = NEW|UNK;
01040 cstate[i] = cstatetmp;
01041 bstatetmp |= cstatetmp;
01042 }
01043 }
01044 bucketstate[buckno] = bstatetmp;
01045 bbstate |= bstatetmp;
01046 }
01047 }
01048 else
01049 {
01050
01051 const short *pcoeff = blk.data(0, &map);
01052 const short *epcoeff = eblk.data(0, &emap);
01053 char *cstate = coeffstate;
01054 for (int i=0; i<16; i++)
01055 {
01056 int thres = quant_lo[i];
01057 int cstatetmp = cstate[i];
01058 if (cstatetmp != ZERO)
01059 {
01060 cstatetmp = UNK;
01061 if (epcoeff[i])
01062 cstatetmp = ACTIVE;
01063 else if ((int)(pcoeff[i])>=thres || (int)(pcoeff[i])<=-thres)
01064 cstatetmp = NEW|UNK;
01065 }
01066 cstate[i] = cstatetmp;
01067 bbstate |= cstatetmp;
01068 }
01069 bucketstate[0] = bbstate;
01070 }
01071 return bbstate;
01072 }
01073
01074
01075
01076 void
01077 IW44Image::Codec::Encode::encode_buckets(ZPCodec &zp, int bit, int band,
01078 IW44Image::Block &blk, IW44Image::Block &eblk,
01079 int fbucket, int nbucket)
01080 {
01081
01082 int bbstate = encode_prepare(band, fbucket, nbucket, blk, eblk);
01083
01084
01085 if ((nbucket<16) || (bbstate&ACTIVE))
01086 {
01087 bbstate |= NEW;
01088 }
01089 else if (bbstate & UNK)
01090 {
01091 zp.encoder( (bbstate&NEW) ? 1 : 0 , ctxRoot);
01092 #ifdef TRACE
01093 DjVuPrintMessage("bbstate[bit=%d,band=%d] = %d\n", bit, band, bbstate);
01094 #endif
01095 }
01096
01097
01098 if (bbstate & NEW)
01099 for (int buckno=0; buckno<nbucket; buckno++)
01100 {
01101
01102 if (bucketstate[buckno] & UNK)
01103 {
01104
01105 int ctx = 0;
01106 #ifndef NOCTX_BUCKET_UPPER
01107 if (band>0)
01108 {
01109 int k = (fbucket+buckno)<<2;
01110 const short *b = eblk.data(k>>4);
01111 if (b)
01112 {
01113 k = k & 0xf;
01114 if (b[k])
01115 ctx += 1;
01116 if (b[k+1])
01117 ctx += 1;
01118 if (b[k+2])
01119 ctx += 1;
01120 if (ctx<3 && b[k+3])
01121 ctx += 1;
01122 }
01123 }
01124 #endif
01125 #ifndef NOCTX_BUCKET_ACTIVE
01126 if (bbstate & ACTIVE)
01127 ctx |= 4;
01128 #endif
01129
01130 zp.encoder( (bucketstate[buckno]&NEW) ? 1 : 0, ctxBucket[band][ctx] );
01131 #ifdef TRACE
01132 DjVuPrintMessage(" bucketstate[bit=%d,band=%d,buck=%d] = %d\n",
01133 bit, band, buckno, bucketstate[buckno] & ~ZERO);
01134 #endif
01135 }
01136 }
01137
01138
01139 if (bbstate & NEW)
01140 {
01141 int thres = quant_hi[band];
01142 char *cstate = coeffstate;
01143 for (int buckno=0; buckno<nbucket; buckno++, cstate+=16)
01144 if (bucketstate[buckno] & NEW)
01145 {
01146 int i;
01147 #ifndef NOCTX_EXPECT
01148 int gotcha = 0;
01149 const int maxgotcha = 7;
01150 for (i=0; i<16; i++)
01151 if (cstate[i] & UNK)
01152 gotcha += 1;
01153 #endif
01154 const short *pcoeff = blk.data(fbucket+buckno);
01155 short *epcoeff = eblk.data(fbucket+buckno, &emap);
01156
01157 for (i=0; i<16; i++)
01158 {
01159 if (cstate[i] & UNK)
01160 {
01161
01162 int ctx = 0;
01163 #ifndef NOCTX_EXPECT
01164 if (gotcha>=maxgotcha)
01165 ctx = maxgotcha;
01166 else
01167 ctx = gotcha;
01168 #endif
01169 #ifndef NOCTX_ACTIVE
01170 if (bucketstate[buckno] & ACTIVE)
01171 ctx |= 8;
01172 #endif
01173
01174 zp.encoder( (cstate[i]&NEW) ? 1 : 0, ctxStart[ctx] );
01175 if (cstate[i] & NEW)
01176 {
01177
01178 zp.IWencoder( (pcoeff[i]<0) ? 1 : 0 );
01179
01180 if (band==0)
01181 thres = quant_lo[i];
01182 epcoeff[i] = thres + (thres>>1);
01183 }
01184 #ifndef NOCTX_EXPECT
01185 if (cstate[i] & NEW)
01186 gotcha = 0;
01187 else if (gotcha > 0)
01188 gotcha -= 1;
01189 #endif
01190 #ifdef TRACE
01191 DjVuPrintMessage(" coeffstate[bit=%d,band=%d,buck=%d,c=%d] = %d\n",
01192 bit, band, buckno, i, cstate[i]);
01193 #endif
01194 }
01195 }
01196 }
01197 }
01198
01199
01200 if (bbstate & ACTIVE)
01201 {
01202 int thres = quant_hi[band];
01203 char *cstate = coeffstate;
01204 for (int buckno=0; buckno<nbucket; buckno++, cstate+=16)
01205 if (bucketstate[buckno] & ACTIVE)
01206 {
01207 const short *pcoeff = blk.data(fbucket+buckno);
01208 short *epcoeff = eblk.data(fbucket+buckno, &emap);
01209 for (int i=0; i<16; i++)
01210 if (cstate[i] & ACTIVE)
01211 {
01212
01213 int coeff = pcoeff[i];
01214 int ecoeff = epcoeff[i];
01215 if (coeff < 0)
01216 coeff = -coeff;
01217
01218 if (band == 0)
01219 thres = quant_lo[i];
01220
01221 int pix = 0;
01222 if (coeff >= ecoeff)
01223 pix = 1;
01224
01225 if (ecoeff <= 3*thres)
01226 zp.encoder(pix, ctxMant);
01227 else
01228 zp.IWencoder(!!pix);
01229
01230 epcoeff[i] = ecoeff - (pix ? 0 : thres) + (thres>>1);
01231 }
01232 }
01233 }
01234 }
01235
01236
01237
01238 float
01239 IW44Image::Codec::Encode::estimate_decibel(float frac)
01240 {
01241 int i,j;
01242 const float *q;
01243
01244 float norm_lo[16];
01245 float norm_hi[10];
01246
01247 q = iw_norm;
01248 for (i=j=0; i<4; j++)
01249 norm_lo[i++] = *q++;
01250 for (j=0; j<4; j++)
01251 norm_lo[i++] = *q;
01252 q += 1;
01253 for (j=0; j<4; j++)
01254 norm_lo[i++] = *q;
01255 q += 1;
01256 for (j=0; j<4; j++)
01257 norm_lo[i++] = *q;
01258 q += 1;
01259
01260 norm_hi[0] = 0;
01261 for (j=1; j<10; j++)
01262 norm_hi[j] = *q++;
01263
01264 float *xmse;
01265 GPBuffer<float> gxmse(xmse,map.nb);
01266
01267 for (int blockno=0; blockno<map.nb; blockno++)
01268 {
01269 float mse = 0;
01270
01271 for (int bandno=0; bandno<10; bandno++)
01272 {
01273 int fbucket = bandbuckets[bandno].start;
01274 int nbucket = bandbuckets[bandno].size;
01275 IW44Image::Block &blk = map.blocks[blockno];
01276 IW44Image::Block &eblk = emap.blocks[blockno];
01277 float norm = norm_hi[bandno];
01278 for (int buckno=0; buckno<nbucket; buckno++)
01279 {
01280 const short *pcoeff = blk.data(fbucket+buckno);
01281 const short *epcoeff = eblk.data(fbucket+buckno);
01282 if (pcoeff)
01283 {
01284 if (epcoeff)
01285 {
01286 for (i=0; i<16; i++)
01287 {
01288 if (bandno == 0)
01289 norm = norm_lo[i];
01290 float delta = (float)(pcoeff[i]<0 ? -pcoeff[i] : pcoeff[i]);
01291 delta = delta - epcoeff[i];
01292 mse = mse + norm * delta * delta;
01293 }
01294 }
01295 else
01296 {
01297 for (i=0; i<16; i++)
01298 {
01299 if (bandno == 0)
01300 norm = norm_lo[i];
01301 float delta = (float)(pcoeff[i]);
01302 mse = mse + norm * delta * delta;
01303 }
01304 }
01305 }
01306 }
01307 }
01308 xmse[blockno] = mse / 1024;
01309 }
01310
01311 int n = 0;
01312 int m = map.nb - 1;
01313 int p = (int)floor(m*(1.0-frac)+0.5);
01314 p = (p>m ? m : (p<0 ? 0 : p));
01315 float pivot = 0;
01316
01317 while (n < p)
01318 {
01319 int l = n;
01320 int h = m;
01321 if (xmse[l] > xmse[h]) { float tmp=xmse[l]; xmse[l]=xmse[h]; xmse[h]=tmp; }
01322 pivot = xmse[(l+h)/2];
01323 if (pivot < xmse[l]) { float tmp=pivot; pivot=xmse[l]; xmse[l]=tmp; }
01324 if (pivot > xmse[h]) { float tmp=pivot; pivot=xmse[h]; xmse[h]=tmp; }
01325 while (l < h)
01326 {
01327 if (xmse[l] > xmse[h]) { float tmp=xmse[l]; xmse[l]=xmse[h]; xmse[h]=tmp; }
01328 while (xmse[l]<pivot || (xmse[l]==pivot && l<h)) l++;
01329 while (xmse[h]>pivot) h--;
01330 }
01331 if (p>=l)
01332 n = l;
01333 else
01334 m = l-1;
01335 }
01336
01337 float mse = 0;
01338 for (i=p; i<map.nb; i++)
01339 mse = mse + xmse[i];
01340 mse = mse / (map.nb - p);
01341
01342 float factor = 255 << iw_shift;
01343 float decibel = (float)(10.0 * log ( factor * factor / mse ) / 2.302585125);
01344 return decibel;
01345 }
01346
01347
01348
01349
01351
01353
01354
01355 void
01356 IW44Image::PrimaryHeader::encode(GP<ByteStream> gbs)
01357 {
01358 gbs->write8(serial);
01359 gbs->write8(slices);
01360 }
01361
01362 void
01363 IW44Image::SecondaryHeader::encode(GP<ByteStream> gbs)
01364 {
01365 gbs->write8(major);
01366 gbs->write8(minor);
01367 }
01368
01369 void
01370 IW44Image::TertiaryHeader::encode(GP<ByteStream> gbs)
01371 {
01372 gbs->write8(xhi);
01373 gbs->write8(xlo);
01374 gbs->write8(yhi);
01375 gbs->write8(ylo);
01376 gbs->write8(crcbdelay);
01377 }
01378
01379
01380
01381 GP<IW44Image>
01382 IW44Image::create_encode(const ImageType itype)
01383 {
01384 switch(itype)
01385 {
01386 case COLOR:
01387 return new IWPixmap::Encode();
01388 case GRAY:
01389 return new IWBitmap::Encode();
01390 default:
01391 return 0;
01392 }
01393 }
01394
01395 GP<IW44Image>
01396 IW44Image::create_encode(const GBitmap &bm, const GP<GBitmap> mask)
01397 {
01398 IWBitmap::Encode *bit=new IWBitmap::Encode();
01399 GP<IW44Image> retval=bit;
01400 bit->init(bm, mask);
01401 return retval;
01402 }
01403
01404
01405 IWBitmap::Encode::Encode(void)
01406 : IWBitmap(), ycodec_enc(0)
01407 {}
01408
01409 IWBitmap::Encode::~Encode()
01410 {
01411 close_codec();
01412 }
01413
01414 void
01415 IWBitmap::Encode::init(const GBitmap &bm, const GP<GBitmap> gmask)
01416 {
01417
01418 close_codec();
01419 delete ymap;
01420 ymap = 0;
01421
01422 int i, j;
01423 int w = bm.columns();
01424 int h = bm.rows();
01425 int g = bm.get_grays()-1;
01426 signed char *buffer;
01427 GPBuffer<signed char> gbuffer(buffer,w*h);
01428
01429 signed char bconv[256];
01430 for (i=0; i<256; i++)
01431 bconv[i] = max(0,min(255,i*255/g)) - 128;
01432
01433
01434 const signed char *msk8 = 0;
01435 int mskrowsize = 0;
01436 GBitmap *mask=gmask;
01437 if (gmask)
01438 {
01439 msk8 = (const signed char*)((*mask)[0]);
01440 mskrowsize = mask->rowsize();
01441 }
01442
01443 for (i=0; i<h; i++)
01444 {
01445 signed char *bufrow = buffer + i*w;
01446 const unsigned char *bmrow = bm[i];
01447 for (j=0; j<w; j++)
01448 bufrow[j] = bconv[bmrow[j]];
01449 }
01450
01451 Map::Encode *eymap=new Map::Encode(w,h);
01452 ymap = eymap;
01453 eymap->create(buffer, w, msk8, mskrowsize);
01454 }
01455
01456 void
01457 IWBitmap::Encode::close_codec(void)
01458 {
01459 delete ycodec_enc;
01460 ycodec_enc = 0;
01461 IWBitmap::close_codec();
01462 }
01463
01464 int
01465 IWBitmap::Encode::encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parm)
01466 {
01467
01468 if (parm.slices==0 && parm.bytes==0 && parm.decibels==0)
01469 G_THROW( ERR_MSG("IW44Image.need_stop") );
01470 if (! ymap)
01471 G_THROW( ERR_MSG("IW44Image.empty_object") );
01472
01473 if (!ycodec_enc)
01474 {
01475 cslice = cserial = cbytes = 0;
01476 ycodec_enc = new Codec::Encode(*ymap);
01477 }
01478
01479 cbytes += sizeof(struct IW44Image::PrimaryHeader);
01480 if (cserial == 0)
01481 cbytes += sizeof(struct IW44Image::SecondaryHeader) + sizeof(struct IW44Image::TertiaryHeader);
01482
01483 int flag = 1;
01484 int nslices = 0;
01485 GP<ByteStream> gmbs=ByteStream::create();
01486 ByteStream &mbs=*gmbs;
01487 DJVU_PROGRESS_TASK(chunk,"encode chunk",parm.slices-cslice);
01488 {
01489 float estdb = -1.0;
01490 GP<ZPCodec> gzp=ZPCodec::create(gmbs, true, true);
01491 ZPCodec &zp=*gzp;
01492 while (flag)
01493 {
01494 if (parm.decibels>0 && estdb>=parm.decibels)
01495 break;
01496 if (parm.bytes>0 && mbs.tell()+cbytes>=parm.bytes)
01497 break;
01498 if (parm.slices>0 && nslices+cslice>=parm.slices)
01499 break;
01500 DJVU_PROGRESS_RUN(chunk, (1+nslices-cslice)|0xf);
01501 flag = ycodec_enc->code_slice(zp);
01502 if (flag && parm.decibels>0.0)
01503 if (ycodec_enc->curband==0 || estdb>=parm.decibels-DECIBEL_PRUNE)
01504 estdb = ycodec_enc->estimate_decibel(db_frac);
01505 nslices++;
01506 }
01507 }
01508
01509 struct IW44Image::PrimaryHeader primary;
01510 primary.serial = cserial;
01511 primary.slices = nslices;
01512 primary.encode(gbs);
01513
01514 if (cserial == 0)
01515 {
01516 struct IW44Image::SecondaryHeader secondary;
01517 secondary.major = IWCODEC_MAJOR + 0x80;
01518 secondary.minor = IWCODEC_MINOR;
01519 secondary.encode(gbs);
01520 struct IW44Image::TertiaryHeader tertiary;
01521 tertiary.xhi = (ymap->iw >> 8) & 0xff;
01522 tertiary.xlo = (ymap->iw >> 0) & 0xff;
01523 tertiary.yhi = (ymap->ih >> 8) & 0xff;
01524 tertiary.ylo = (ymap->ih >> 0) & 0xff;
01525 tertiary.crcbdelay = 0;
01526 tertiary.encode(gbs);
01527 }
01528
01529 mbs.seek(0);
01530 gbs->copy(mbs);
01531
01532 cbytes += mbs.tell();
01533 cslice += nslices;
01534 cserial += 1;
01535 return flag;
01536 }
01537
01538 void
01539 IWBitmap::Encode::encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms)
01540 {
01541 if (ycodec_enc)
01542 G_THROW( ERR_MSG("IW44Image.left_open1") );
01543 int flag = 1;
01544 iff.put_chunk("FORM:BM44", 1);
01545 DJVU_PROGRESS_TASK(iff,"encode iff chunk",nchunks);
01546 for (int i=0; flag && i<nchunks; i++)
01547 {
01548 DJVU_PROGRESS_RUN(iff,i+1);
01549 iff.put_chunk("BM44");
01550 flag = encode_chunk(iff.get_bytestream(),parms[i]);
01551 iff.close_chunk();
01552 }
01553 iff.close_chunk();
01554 close_codec();
01555 }
01556
01557 GP<IW44Image>
01558 IW44Image::create_encode(
01559 const GPixmap &pm, const GP<GBitmap> gmask, CRCBMode crcbmode)
01560 {
01561 IWPixmap::Encode *pix=new IWPixmap::Encode();
01562 GP<IW44Image> retval=pix;
01563 pix->init(pm, gmask,(IWPixmap::Encode::CRCBMode)crcbmode);
01564 return retval;
01565 }
01566
01567 IWPixmap::Encode::Encode(void)
01568 : IWPixmap(), ycodec_enc(0), cbcodec_enc(0), crcodec_enc(0)
01569 {}
01570
01571 IWPixmap::Encode::~Encode()
01572 {
01573 close_codec();
01574 }
01575
01576 void
01577 IWPixmap::Encode::init(const GPixmap &pm, const GP<GBitmap> gmask, CRCBMode crcbmode)
01578 {
01579
01580 close_codec();
01581 delete ymap;
01582 delete cbmap;
01583 delete crmap;
01584 ymap = cbmap = crmap = 0;
01585
01586 int w = pm.columns();
01587 int h = pm.rows();
01588 signed char *buffer;
01589 GPBuffer<signed char> gbuffer(buffer,w*h);
01590
01591 Map::Encode *eymap = new Map::Encode(w,h);
01592 ymap = eymap;
01593
01594 switch (crcbmode)
01595 {
01596 case CRCBnone: crcb_half=1; crcb_delay=-1; break;
01597 case CRCBhalf: crcb_half=1; crcb_delay=10; break;
01598 case CRCBnormal: crcb_half=0; crcb_delay=10; break;
01599 case CRCBfull: crcb_half=0; crcb_delay= 0; break;
01600 }
01601
01602 const signed char *msk8 = 0;
01603 int mskrowsize = 0;
01604 GBitmap *mask=gmask;
01605 if (mask)
01606 {
01607 msk8 = (signed char const *)((*mask)[0]);
01608 mskrowsize = mask->rowsize();
01609 }
01610
01611 DJVU_PROGRESS_TASK(create,"initialize pixmap",3);
01612 DJVU_PROGRESS_RUN(create,(crcb_delay>=0 ? 1 : 3));
01613 Transform::Encode::RGB_to_Y(pm[0], w, h, pm.rowsize(), buffer, w);
01614 if (crcb_delay < 0)
01615 {
01616
01617 signed char *e = buffer + w*h;
01618 for (signed char *b=buffer; b<e; b++)
01619 *b = 255 - *b;
01620 }
01621
01622 eymap->create(buffer, w, msk8, mskrowsize);
01623
01624 if (crcb_delay >= 0)
01625 {
01626 Map::Encode *ecbmap = new Map::Encode(w,h);
01627 cbmap = ecbmap;
01628 Map::Encode *ecrmap = new Map::Encode(w,h);
01629 crmap = ecrmap;
01630
01631 DJVU_PROGRESS_RUN(create,2);
01632 Transform::Encode::RGB_to_Cb(pm[0], w, h, pm.rowsize(), buffer, w);
01633 ecbmap->create(buffer, w, msk8, mskrowsize);
01634
01635 DJVU_PROGRESS_RUN(create,3);
01636 Transform::Encode::RGB_to_Cr(pm[0], w, h, pm.rowsize(), buffer, w);
01637 ecrmap->create(buffer, w, msk8, mskrowsize);
01638
01639 if (crcb_half)
01640 {
01641 ecbmap->slashres(2);
01642 ecrmap->slashres(2);
01643 }
01644 }
01645 }
01646
01647 void
01648 IWPixmap::Encode::encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms)
01649 {
01650 if (ycodec_enc)
01651 G_THROW( ERR_MSG("IW44Image.left_open3") );
01652 int flag = 1;
01653 iff.put_chunk("FORM:PM44", 1);
01654 DJVU_PROGRESS_TASK(iff,"encode pixmap chunk", nchunks);
01655 for (int i=0; flag && i<nchunks; i++)
01656 {
01657 DJVU_PROGRESS_RUN(iff,i+1);
01658 iff.put_chunk("PM44");
01659 flag = encode_chunk(iff.get_bytestream(), parms[i]);
01660 iff.close_chunk();
01661 }
01662 iff.close_chunk();
01663 close_codec();
01664 }
01665
01666 void
01667 IWPixmap::Encode::close_codec(void)
01668 {
01669 delete ycodec_enc;
01670 delete cbcodec_enc;
01671 delete crcodec_enc;
01672 ycodec_enc = crcodec_enc = cbcodec_enc = 0;
01673 IWPixmap::close_codec();
01674 }
01675
01676 int
01677 IWPixmap::Encode::encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parm)
01678 {
01679
01680 if (parm.slices==0 && parm.bytes==0 && parm.decibels==0)
01681 G_THROW( ERR_MSG("IW44Image.need_stop2") );
01682 if (!ymap)
01683 G_THROW( ERR_MSG("IW44Image.empty_object2") );
01684
01685 if (!ycodec_enc)
01686 {
01687 cslice = cserial = cbytes = 0;
01688 ycodec_enc = new Codec::Encode(*ymap);
01689 if (crmap && cbmap)
01690 {
01691 cbcodec_enc = new Codec::Encode(*cbmap);
01692 crcodec_enc = new Codec::Encode(*crmap);
01693 }
01694 }
01695
01696
01697 cbytes += sizeof(struct IW44Image::PrimaryHeader);
01698 if (cserial == 0)
01699 cbytes += sizeof(struct IW44Image::SecondaryHeader) + sizeof(struct IW44Image::TertiaryHeader);
01700
01701 int flag = 1;
01702 int nslices = 0;
01703 GP<ByteStream> gmbs=ByteStream::create();
01704 ByteStream &mbs=*gmbs;
01705 DJVU_PROGRESS_TASK(chunk, "encode pixmap chunk", parm.slices-cslice);
01706 {
01707 float estdb = -1.0;
01708 GP<ZPCodec> gzp=ZPCodec::create(gmbs, true, true);
01709 ZPCodec &zp=*gzp;
01710 while (flag)
01711 {
01712 if (parm.decibels>0 && estdb>=parm.decibels)
01713 break;
01714 if (parm.bytes>0 && mbs.tell()+cbytes>=parm.bytes)
01715 break;
01716 if (parm.slices>0 && nslices+cslice>=parm.slices)
01717 break;
01718 DJVU_PROGRESS_RUN(chunk,(1+nslices-cslice)|0xf);
01719 flag = ycodec_enc->code_slice(zp);
01720 if (flag && parm.decibels>0)
01721 if (ycodec_enc->curband==0 || estdb>=parm.decibels-DECIBEL_PRUNE)
01722 estdb = ycodec_enc->estimate_decibel(db_frac);
01723 if (crcodec_enc && cbcodec_enc && cslice+nslices>=crcb_delay)
01724 {
01725 flag |= cbcodec_enc->code_slice(zp);
01726 flag |= crcodec_enc->code_slice(zp);
01727 }
01728 nslices++;
01729 }
01730 }
01731
01732 struct IW44Image::PrimaryHeader primary;
01733 primary.serial = cserial;
01734 primary.slices = nslices;
01735 primary.encode(gbs);
01736
01737 if (cserial == 0)
01738 {
01739 struct IW44Image::SecondaryHeader secondary;
01740 secondary.major = IWCODEC_MAJOR;
01741 secondary.minor = IWCODEC_MINOR;
01742 if (! (crmap && cbmap))
01743 secondary.major |= 0x80;
01744 secondary.encode(gbs);
01745 struct IW44Image::TertiaryHeader tertiary;
01746 tertiary.xhi = (ymap->iw >> 8) & 0xff;
01747 tertiary.xlo = (ymap->iw >> 0) & 0xff;
01748 tertiary.yhi = (ymap->ih >> 8) & 0xff;
01749 tertiary.ylo = (ymap->ih >> 0) & 0xff;
01750 tertiary.crcbdelay = (crcb_half ? 0x00 : 0x80);
01751 tertiary.crcbdelay |= (crcb_delay>=0 ? crcb_delay : 0x00);
01752 tertiary.encode(gbs);
01753 }
01754
01755 mbs.seek(0);
01756 gbs->copy(mbs);
01757
01758 cbytes += mbs.tell();
01759 cslice += nslices;
01760 cserial += 1;
01761 return flag;
01762 }
01763
01764
01765
01766
01767 int
01768 IW44Image::Codec::Encode::code_slice(ZPCodec &zp)
01769 {
01770
01771 if (curbit < 0)
01772 return 0;
01773
01774 if (! is_null_slice(curbit, curband))
01775 {
01776 for (int blockno=0; blockno<map.nb; blockno++)
01777 {
01778 const int fbucket = bandbuckets[curband].start;
01779 const int nbucket = bandbuckets[curband].size;
01780 encode_buckets(zp, curbit, curband,
01781 map.blocks[blockno], emap.blocks[blockno],
01782 fbucket, nbucket);
01783 }
01784 }
01785 return finish_code_slice(zp);
01786 }
01787
01788
01789
01790 #ifdef HAVE_NAMESPACES
01791 }
01792 # ifndef NOT_USING_DJVU_NAMESPACE
01793 using namespace DJVU;
01794 # endif
01795 #endif
01796 #endif // NEED_DECODER_ONLY
01797