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

kviewshell

IW44Image.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: IW44Image.cpp,v 1.11 2004/08/06 15:11:29 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 // - Author: Leon Bottou, 08/1998
00065 
00066 // From: Leon Bottou, 1/31/2002
00067 // Lizardtech has split this file into a decoder and an encoder.
00068 // Only superficial changes.  The meat is mine.
00069 
00070 #define IW44IMAGE_IMPLIMENTATION /* */
00071 // -------------------^  not my spelling mistake (Leon Bottou)
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 
00094 #ifdef HAVE_NAMESPACES
00095 namespace DJVU {
00096 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00097 }
00098 #endif
00099 #endif
00100 
00101 
00102 #define IWALLOCSIZE    4080
00103 #define IWCODEC_MAJOR     1
00104 #define IWCODEC_MINOR     2
00105 #define DECIBEL_PRUNE   5.0
00106 
00107 
00109 // WAVELET DECOMPOSITION CONSTANTS
00111 
00112 // Parameters for IW44 wavelet.
00113 // - iw_quant: quantization for all 16 sub-bands
00114 // - iw_norm: norm of all wavelets (for db estimation)
00115 // - iw_border: pixel border required to run filters
00116 // - iw_shift: scale applied before decomposition
00117 
00118 
00119 static const int iw_quant[16] = {
00120   0x004000, 
00121   0x008000, 0x008000, 0x010000,
00122   0x010000, 0x010000, 0x020000,
00123   0x020000, 0x020000, 0x040000,
00124   0x040000, 0x040000, 0x080000, 
00125   0x040000, 0x040000, 0x080000
00126 };
00127 
00128 static const float iw_norm[16] = {
00129   2.627989e+03F,
00130   1.832893e+02F, 1.832959e+02F, 5.114690e+01F,
00131   4.583344e+01F, 4.583462e+01F, 1.279225e+01F,
00132   1.149671e+01F, 1.149712e+01F, 3.218888e+00F,
00133   2.999281e+00F, 2.999476e+00F, 8.733161e-01F,
00134   1.074451e+00F, 1.074511e+00F, 4.289318e-01F
00135 };
00136 
00137 static const int iw_border = 3;
00138 static const int iw_shift  = 6;
00139 static const int iw_round  = (1<<(iw_shift-1));
00140 
00141 class IW44Image::Codec::Decode : public IW44Image::Codec 
00142 {
00143 public:
00144   // Construction
00145   Decode(IW44Image::Map &map) : Codec(map) {}
00146   // Coding
00147   virtual int code_slice(ZPCodec &zp);
00148 };
00149 
00151 // MMX IMPLEMENTATION HELPERS
00153 
00154 
00155 // Note:
00156 // MMX implementation for vertical transforms only.
00157 // Speedup is basically related to faster memory transfer
00158 // The IW44 transform is not CPU bound, it is memory bound.
00159 
00160 #ifdef MMX
00161 
00162 static const short w9[]  = {9,9,9,9};
00163 static const short w1[]  = {1,1,1,1};
00164 static const int   d8[]  = {8,8};
00165 static const int   d16[] = {16,16};
00166 
00167 static void
00168 mmx_bv_1 ( short* &q, short* e, int s, int s3 )
00169 {
00170   while (q<e && (((long)q)&0x7))
00171     {
00172       int a = (int)q[-s] + (int)q[s];
00173       int b = (int)q[-s3] + (int)q[s3];
00174       *q -= (((a<<3)+a-b+16)>>5);
00175       q ++;
00176   }
00177   while (q+3 < e)
00178     {
00179       MMXar( movq,       q-s,mm0);  // MM0=[ b3, b2, b1, b0 ]
00180       MMXar( movq,       q+s,mm2);  // MM2=[ c3, c2, c1, c0 ]
00181       MMXrr( movq,       mm0,mm1);  
00182       MMXrr( punpcklwd,  mm2,mm0);  // MM0=[ c1, b1, c0, b0 ]
00183       MMXrr( punpckhwd,  mm2,mm1);  // MM1=[ c3, b3, c2, b2 ]
00184       MMXar( pmaddwd,    w9,mm0);   // MM0=[ (c1+b1)*9, (c0+b0)*9 ]
00185       MMXar( pmaddwd,    w9,mm1);   // MM1=[ (c3+b3)*9, (c2+b2)*9 ]
00186       MMXar( movq,       q-s3,mm2);
00187       MMXar( movq,       q+s3,mm4);
00188       MMXrr( movq,       mm2,mm3);
00189       MMXrr( punpcklwd,  mm4,mm2);  // MM2=[ d1, a1, d0, a0 ]
00190       MMXrr( punpckhwd,  mm4,mm3);  // MM3=[ d3, a3, d2, a2 ]
00191       MMXar( pmaddwd,    w1,mm2);   // MM2=[ (a1+d1)*1, (a0+d0)*1 ]
00192       MMXar( pmaddwd,    w1,mm3);   // MM3=[ (a3+d3)*1, (a2+d2)*1 ]
00193       MMXar( paddd,      d16,mm0);
00194       MMXar( paddd,      d16,mm1);
00195       MMXrr( psubd,      mm2,mm0);  // MM0=[ (c1+b1)*9-a1-d1+8, ...
00196       MMXrr( psubd,      mm3,mm1);  // MM1=[ (c3+b3)*9-a3-d3+8, ...
00197       MMXir( psrad,      5,mm0);
00198       MMXar( movq,       q,mm7);    // MM7=[ p3,p2,p1,p0 ]
00199       MMXir( psrad,      5,mm1);
00200       MMXrr( packssdw,   mm1,mm0);  // MM0=[ x3,x2,x1,x0 ]
00201       MMXrr( psubw,      mm0,mm7);  // MM7=[ p3-x3, p2-x2, ... ]
00202       MMXra( movq,       mm7,q);
00203 #if defined(_MSC_VER) && defined(_DEBUG)
00204       MMXemms;
00205 #endif
00206       q += 4;
00207     }
00208 }
00209 
00210 
00211 static void
00212 mmx_bv_2 ( short* &q, short* e, int s, int s3 )
00213 {
00214   while (q<e && (((long)q)&0x7))
00215     {
00216       int a = (int)q[-s] + (int)q[s];
00217       int b = (int)q[-s3] + (int)q[s3];
00218       *q += (((a<<3)+a-b+8)>>4);
00219       q ++;
00220     }
00221   while (q+3 < e)
00222     {
00223       MMXar( movq,       q-s,mm0);  // MM0=[ b3, b2, b1, b0 ]
00224       MMXar( movq,       q+s,mm2);  // MM2=[ c3, c2, c1, c0 ]
00225       MMXrr( movq,       mm0,mm1);  
00226       MMXrr( punpcklwd,  mm2,mm0);  // MM0=[ c1, b1, c0, b0 ]
00227       MMXrr( punpckhwd,  mm2,mm1);  // MM1=[ c3, b3, c2, b2 ]
00228       MMXar( pmaddwd,    w9,mm0);   // MM0=[ (c1+b1)*9, (c0+b0)*9 ]
00229       MMXar( pmaddwd,    w9,mm1);   // MM1=[ (c3+b3)*9, (c2+b2)*9 ]
00230       MMXar( movq,       q-s3,mm2);
00231       MMXar( movq,       q+s3,mm4);
00232       MMXrr( movq,       mm2,mm3);
00233       MMXrr( punpcklwd,  mm4,mm2);  // MM2=[ d1, a1, d0, a0 ]
00234       MMXrr( punpckhwd,  mm4,mm3);  // MM3=[ d3, a3, d2, a2 ]
00235       MMXar( pmaddwd,    w1,mm2);   // MM2=[ (a1+d1)*1, (a0+d0)*1 ]
00236       MMXar( pmaddwd,    w1,mm3);   // MM3=[ (a3+d3)*1, (a2+d2)*1 ]
00237       MMXar( paddd,      d8,mm0);
00238       MMXar( paddd,      d8,mm1);
00239       MMXrr( psubd,      mm2,mm0);  // MM0=[ (c1+b1)*9-a1-d1+8, ...
00240       MMXrr( psubd,      mm3,mm1);  // MM1=[ (c3+b3)*9-a3-d3+8, ...
00241       MMXir( psrad,      4,mm0);
00242       MMXar( movq,       q,mm7);    // MM7=[ p3,p2,p1,p0 ]
00243       MMXir( psrad,      4,mm1);
00244       MMXrr( packssdw,   mm1,mm0);  // MM0=[ x3,x2,x1,x0 ]
00245       MMXrr( paddw,      mm0,mm7);  // MM7=[ p3+x3, p2+x2, ... ]
00246       MMXra( movq,       mm7,q);
00247 #if defined(_MSC_VER) && defined(_DEBUG)
00248       MMXemms;
00249 #endif
00250       q += 4;
00251     }
00252 }
00253 #endif /* MMX */
00254 
00255 static void 
00256 filter_bv(short *p, int w, int h, int rowsize, int scale)
00257 {
00258   int y = 0;
00259   int s = scale*rowsize;
00260   int s3 = s+s+s;
00261   h = ((h-1)/scale)+1;
00262   while (y-3 < h)
00263     {
00264       // 1-Lifting
00265       {
00266         short *q = p;
00267         short *e = q+w;
00268         if (y>=3 && y+3<h)
00269           {
00270             // Generic case
00271 #ifdef MMX
00272             if (scale==1 && MMXControl::mmxflag>0)
00273               mmx_bv_1(q, e, s, s3);
00274 #endif
00275             while (q<e)
00276               {
00277                 int a = (int)q[-s] + (int)q[s];
00278                 int b = (int)q[-s3] + (int)q[s3];
00279                 *q -= (((a<<3)+a-b+16)>>5);
00280                 q += scale;
00281               }
00282           }
00283         else if (y<h)
00284           {
00285             // Special cases
00286             short *q1 = (y+1<h ? q+s : 0);
00287             short *q3 = (y+3<h ? q+s3 : 0);
00288             if (y>=3)
00289               {
00290                 while (q<e)
00291                   {
00292                     int a = (int)q[-s] + (q1 ? (int)(*q1) : 0);
00293                     int b = (int)q[-s3] + (q3 ? (int)(*q3) : 0);
00294                     *q -= (((a<<3)+a-b+16)>>5);
00295                     q += scale;
00296                     if (q1) q1 += scale;
00297                     if (q3) q3 += scale;
00298                   }
00299               }
00300             else if (y>=1)
00301               {
00302                 while (q<e)
00303                   {
00304                     int a = (int)q[-s] + (q1 ? (int)(*q1) : 0);
00305                     int b = (q3 ? (int)(*q3) : 0);
00306                     *q -= (((a<<3)+a-b+16)>>5);
00307                     q += scale;
00308                     if (q1) q1 += scale;
00309                     if (q3) q3 += scale;
00310                   }
00311               }
00312             else
00313               {
00314                 while (q<e)
00315                   {
00316                     int a = (q1 ? (int)(*q1) : 0);
00317                     int b = (q3 ? (int)(*q3) : 0);
00318                     *q -= (((a<<3)+a-b+16)>>5);
00319                     q += scale;
00320                     if (q1) q1 += scale;
00321                     if (q3) q3 += scale;
00322                   }
00323               }
00324           }
00325       }
00326       // 2-Interpolation
00327       {
00328         short *q = p-s3;
00329         short *e = q+w;
00330         if (y>=6 && y<h)
00331           {
00332             // Generic case
00333 #ifdef MMX
00334             if (scale==1 && MMXControl::mmxflag>0)
00335               mmx_bv_2(q, e, s, s3);
00336 #endif
00337             while (q<e)
00338               {
00339                 int a = (int)q[-s] + (int)q[s];
00340                 int b = (int)q[-s3] + (int)q[s3];
00341                 *q += (((a<<3)+a-b+8)>>4);
00342                 q += scale;
00343               }
00344           }
00345         else if (y>=3)
00346           {
00347             // Special cases
00348             short *q1 = (y-2<h ? q+s : q-s);
00349             while (q<e)
00350               {
00351                 int a = (int)q[-s] + (int)(*q1);
00352                 *q += ((a+1)>>1);
00353                 q += scale;
00354                 q1 += scale;
00355               }
00356           }
00357       }
00358       y += 2;
00359       p += s+s;
00360     }
00361 }
00362 
00363 static void 
00364 filter_bh(short *p, int w, int h, int rowsize, int scale)
00365 {
00366   int y = 0;
00367   int s = scale;
00368   int s3 = s+s+s;
00369   rowsize *= scale;
00370   while (y<h)
00371     {
00372       short *q = p;
00373       short *e = p+w;
00374       int a0=0, a1=0, a2=0, a3=0;
00375       int b0=0, b1=0, b2=0, b3=0;
00376       if (q<e)
00377         {
00378           // Special case:  x=0
00379           if (q+s < e)
00380             a2 = q[s];
00381           if (q+s3 < e)
00382             a3 = q[s3];
00383           b2 = b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+16) >> 5);
00384           q[0] = b3;
00385           q += s+s;
00386         }
00387       if (q<e)
00388         {
00389           // Special case:  x=2
00390           a0 = a1;
00391           a1 = a2;
00392           a2 = a3;
00393           if (q+s3 < e)
00394             a3 = q[s3];
00395           b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+16) >> 5);
00396           q[0] = b3;
00397           q += s+s;
00398         }
00399       if (q<e)
00400         {
00401           // Special case:  x=4
00402           b1 = b2;
00403           b2 = b3;
00404           a0 = a1;
00405           a1 = a2;
00406           a2 = a3;
00407           if (q+s3 < e)
00408             a3 = q[s3];
00409           b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+16) >> 5);
00410           q[0] = b3;
00411           q[-s3] = q[-s3] + ((b1+b2+1)>>1);
00412           q += s+s;
00413         }
00414       while (q+s3 < e)
00415         {
00416           // Generic case
00417           a0=a1; 
00418           a1=a2; 
00419           a2=a3;
00420           a3=q[s3];
00421           b0=b1; 
00422           b1=b2; 
00423           b2=b3;
00424           b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+16) >> 5);
00425           q[0] = b3;
00426           q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+8) >> 4);
00427           q += s+s;
00428         }
00429       while (q < e)
00430         {
00431           // Special case:  w-3 <= x < w
00432           a0=a1;
00433           a1=a2; 
00434           a2=a3;
00435           a3=0;
00436           b0=b1; 
00437           b1=b2; 
00438           b2=b3;
00439           b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+16) >> 5);
00440           q[0] = b3;
00441           q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+8) >> 4);
00442           q += s+s;
00443         }
00444       while (q-s3 < e)
00445         {
00446           // Special case  w <= x < w+3
00447           b0=b1; 
00448           b1=b2; 
00449           b2=b3;
00450           if (q-s3 >= p)
00451             q[-s3] = q[-s3] + ((b1+b2+1)>>1);
00452           q += s+s;
00453         }
00454       y += scale;
00455       p += rowsize;
00456     }
00457 }
00458 
00459 
00461 // REPRESENTATION OF WAVELET DECOMPOSED IMAGES
00463 
00464 
00465 
00466 //---------------------------------------------------------------
00467 // Zig zag location in a 1024 liftblock.
00468 // These numbers have been generated with the following program:
00469 //
00470 // int x=0, y=0;
00471 // for (int i=0; i<5; i++) {
00472 //   x = (x<<1) | (n&1);  n >>= 1;
00473 //   y = (y<<1) | (n&1);  n >>= 1;
00474 // }
00475 
00476 
00477 static int zigzagloc[1024] = {
00478    0,  16, 512, 528,   8,  24, 520, 536, 256, 272, 768, 784, 264, 280, 776, 792,
00479    4,  20, 516, 532,  12,  28, 524, 540, 260, 276, 772, 788, 268, 284, 780, 796,
00480  128, 144, 640, 656, 136, 152, 648, 664, 384, 400, 896, 912, 392, 408, 904, 920,
00481  132, 148, 644, 660, 140, 156, 652, 668, 388, 404, 900, 916, 396, 412, 908, 924,
00482    2,  18, 514, 530,  10,  26, 522, 538, 258, 274, 770, 786, 266, 282, 778, 794,
00483    6,  22, 518, 534,  14,  30, 526, 542, 262, 278, 774, 790, 270, 286, 782, 798,
00484  130, 146, 642, 658, 138, 154, 650, 666, 386, 402, 898, 914, 394, 410, 906, 922,
00485  134, 150, 646, 662, 142, 158, 654, 670, 390, 406, 902, 918, 398, 414, 910, 926,
00486   64,  80, 576, 592,  72,  88, 584, 600, 320, 336, 832, 848, 328, 344, 840, 856,
00487   68,  84, 580, 596,  76,  92, 588, 604, 324, 340, 836, 852, 332, 348, 844, 860,
00488  192, 208, 704, 720, 200, 216, 712, 728, 448, 464, 960, 976, 456, 472, 968, 984,
00489  196, 212, 708, 724, 204, 220, 716, 732, 452, 468, 964, 980, 460, 476, 972, 988,
00490   66,  82, 578, 594,  74,  90, 586, 602, 322, 338, 834, 850, 330, 346, 842, 858,
00491   70,  86, 582, 598,  78,  94, 590, 606, 326, 342, 838, 854, 334, 350, 846, 862,
00492  194, 210, 706, 722, 202, 218, 714, 730, 450, 466, 962, 978, 458, 474, 970, 986,
00493  198, 214, 710, 726, 206, 222, 718, 734, 454, 470, 966, 982, 462, 478, 974, 990, // 255
00494    1,  17, 513, 529,   9,  25, 521, 537, 257, 273, 769, 785, 265, 281, 777, 793,
00495    5,  21, 517, 533,  13,  29, 525, 541, 261, 277, 773, 789, 269, 285, 781, 797,
00496  129, 145, 641, 657, 137, 153, 649, 665, 385, 401, 897, 913, 393, 409, 905, 921,
00497  133, 149, 645, 661, 141, 157, 653, 669, 389, 405, 901, 917, 397, 413, 909, 925,
00498    3,  19, 515, 531,  11,  27, 523, 539, 259, 275, 771, 787, 267, 283, 779, 795,
00499    7,  23, 519, 535,  15,  31, 527, 543, 263, 279, 775, 791, 271, 287, 783, 799,
00500  131, 147, 643, 659, 139, 155, 651, 667, 387, 403, 899, 915, 395, 411, 907, 923,
00501  135, 151, 647, 663, 143, 159, 655, 671, 391, 407, 903, 919, 399, 415, 911, 927,
00502   65,  81, 577, 593,  73,  89, 585, 601, 321, 337, 833, 849, 329, 345, 841, 857,
00503   69,  85, 581, 597,  77,  93, 589, 605, 325, 341, 837, 853, 333, 349, 845, 861,
00504  193, 209, 705, 721, 201, 217, 713, 729, 449, 465, 961, 977, 457, 473, 969, 985,
00505  197, 213, 709, 725, 205, 221, 717, 733, 453, 469, 965, 981, 461, 477, 973, 989,
00506   67,  83, 579, 595,  75,  91, 587, 603, 323, 339, 835, 851, 331, 347, 843, 859,
00507   71,  87, 583, 599,  79,  95, 591, 607, 327, 343, 839, 855, 335, 351, 847, 863,
00508  195, 211, 707, 723, 203, 219, 715, 731, 451, 467, 963, 979, 459, 475, 971, 987,
00509  199, 215, 711, 727, 207, 223, 719, 735, 455, 471, 967, 983, 463, 479, 975, 991, // 511
00510   32,  48, 544, 560,  40,  56, 552, 568, 288, 304, 800, 816, 296, 312, 808, 824,
00511   36,  52, 548, 564,  44,  60, 556, 572, 292, 308, 804, 820, 300, 316, 812, 828,
00512  160, 176, 672, 688, 168, 184, 680, 696, 416, 432, 928, 944, 424, 440, 936, 952,
00513  164, 180, 676, 692, 172, 188, 684, 700, 420, 436, 932, 948, 428, 444, 940, 956,
00514   34,  50, 546, 562,  42,  58, 554, 570, 290, 306, 802, 818, 298, 314, 810, 826,
00515   38,  54, 550, 566,  46,  62, 558, 574, 294, 310, 806, 822, 302, 318, 814, 830,
00516  162, 178, 674, 690, 170, 186, 682, 698, 418, 434, 930, 946, 426, 442, 938, 954,
00517  166, 182, 678, 694, 174, 190, 686, 702, 422, 438, 934, 950, 430, 446, 942, 958,
00518   96, 112, 608, 624, 104, 120, 616, 632, 352, 368, 864, 880, 360, 376, 872, 888,
00519  100, 116, 612, 628, 108, 124, 620, 636, 356, 372, 868, 884, 364, 380, 876, 892,
00520  224, 240, 736, 752, 232, 248, 744, 760, 480, 496, 992,1008, 488, 504,1000,1016,
00521  228, 244, 740, 756, 236, 252, 748, 764, 484, 500, 996,1012, 492, 508,1004,1020,
00522   98, 114, 610, 626, 106, 122, 618, 634, 354, 370, 866, 882, 362, 378, 874, 890,
00523  102, 118, 614, 630, 110, 126, 622, 638, 358, 374, 870, 886, 366, 382, 878, 894,
00524  226, 242, 738, 754, 234, 250, 746, 762, 482, 498, 994,1010, 490, 506,1002,1018,
00525  230, 246, 742, 758, 238, 254, 750, 766, 486, 502, 998,1014, 494, 510,1006,1022, // 767
00526   33,  49, 545, 561,  41,  57, 553, 569, 289, 305, 801, 817, 297, 313, 809, 825,
00527   37,  53, 549, 565,  45,  61, 557, 573, 293, 309, 805, 821, 301, 317, 813, 829,
00528  161, 177, 673, 689, 169, 185, 681, 697, 417, 433, 929, 945, 425, 441, 937, 953,
00529  165, 181, 677, 693, 173, 189, 685, 701, 421, 437, 933, 949, 429, 445, 941, 957,
00530   35,  51, 547, 563,  43,  59, 555, 571, 291, 307, 803, 819, 299, 315, 811, 827,
00531   39,  55, 551, 567,  47,  63, 559, 575, 295, 311, 807, 823, 303, 319, 815, 831,
00532  163, 179, 675, 691, 171, 187, 683, 699, 419, 435, 931, 947, 427, 443, 939, 955,
00533  167, 183, 679, 695, 175, 191, 687, 703, 423, 439, 935, 951, 431, 447, 943, 959,
00534   97, 113, 609, 625, 105, 121, 617, 633, 353, 369, 865, 881, 361, 377, 873, 889,
00535  101, 117, 613, 629, 109, 125, 621, 637, 357, 373, 869, 885, 365, 381, 877, 893,
00536  225, 241, 737, 753, 233, 249, 745, 761, 481, 497, 993,1009, 489, 505,1001,1017,
00537  229, 245, 741, 757, 237, 253, 749, 765, 485, 501, 997,1013, 493, 509,1005,1021,
00538   99, 115, 611, 627, 107, 123, 619, 635, 355, 371, 867, 883, 363, 379, 875, 891,
00539  103, 119, 615, 631, 111, 127, 623, 639, 359, 375, 871, 887, 367, 383, 879, 895,
00540  227, 243, 739, 755, 235, 251, 747, 763, 483, 499, 995,1011, 491, 507,1003,1019,
00541  231, 247, 743, 759, 239, 255, 751, 767, 487, 503, 999,1015, 495, 511,1007,1023, // 1023
00542 };
00543 
00544 //---------------------------------------------------------------
00545 // *** Class IW44Image::Alloc [declaration]
00546 
00547 struct IW44Image::Alloc // DJVU_CLASS
00548 {
00549   Alloc *next;
00550   short data[IWALLOCSIZE];
00551 };
00552 
00553 //---------------------------------------------------------------
00554 // *** Class IW44Image::Block [implementation]
00555 
00556 
00557 IW44Image::Block::Block(void)
00558 {
00559   pdata[0] = pdata[1] = pdata[2] = pdata[3] = 0;
00560 }
00561 
00562 void 
00563 IW44Image::Block::zero(int n)
00564 {
00565   if (pdata[n>>4])
00566     pdata[n>>4][n&15] = 0;
00567 }
00568 
00569 void  
00570 IW44Image::Block::read_liftblock(const short *coeff, IW44Image::Map *map)
00571 {
00572   int n=0;
00573   for (int n1=0; n1<64; n1++)
00574     {
00575       short *d = data(n1,map);
00576       for (int n2=0; n2<16; n2++,n++)
00577         d[n2] = coeff[zigzagloc[n]];
00578     }
00579 }
00580 
00581 void  
00582 IW44Image::Block::write_liftblock(short *coeff, int bmin, int bmax) const
00583 {
00584   int n = bmin<<4;
00585   memset(coeff, 0, 1024*sizeof(short));
00586   for (int n1=bmin; n1<bmax; n1++)
00587     {
00588       const short *d = data(n1);
00589       if (d == 0)
00590         n += 16;
00591       else
00592         for (int n2=0; n2<16; n2++,n++)
00593           coeff[zigzagloc[n]] = d[n2];
00594     }
00595 }
00596 
00597 //---------------------------------------------------------------
00598 // *** Class IW44Image::Map [implementation]
00599 
00600 
00601 IW44Image::Map::Map(int w, int h)
00602   :  blocks(0), iw(w), ih(h), chain(0)
00603 {
00604   bw = (w+0x20-1) & ~0x1f;
00605   bh = (h+0x20-1) & ~0x1f;
00606   nb = (bw * bh) / (32 * 32);
00607   blocks = new IW44Image::Block[nb];
00608   top = IWALLOCSIZE;
00609 }
00610 
00611 IW44Image::Map::~Map()
00612 {
00613   while (chain)
00614     {
00615       IW44Image::Alloc *next = chain->next;
00616       delete chain;
00617       chain = next;
00618     }
00619   delete [] blocks;
00620 }
00621 
00622 short *
00623 IW44Image::Map::alloc(int n)
00624 {
00625   if (top+n > IWALLOCSIZE)
00626     {
00627       IW44Image::Alloc *n = new IW44Image::Alloc;
00628       n->next = chain;
00629       chain = n;
00630       top = 0;
00631     }
00632   short *ans = chain->data + top;
00633   top += n;
00634   memset((void*)ans, 0, sizeof(short)*n);
00635   return ans;
00636 }
00637 
00638 short **
00639 IW44Image::Map::allocp(int n)
00640 {
00641   // Allocate enough room for pointers plus alignment
00642   short *p = alloc( (n+1) * sizeof(short*) / sizeof(short) );
00643   // Align on pointer size
00644   while ( ((long)p) & (sizeof(short*)-1) )
00645     p += 1;
00646   // Cast and return
00647   return (short**)p;
00648 }
00649 
00650 int 
00651 IW44Image::Map::get_bucket_count(void) const
00652 {
00653   int buckets = 0;
00654   for (int blockno=0; blockno<nb; blockno++)
00655     for (int buckno=0; buckno<64; buckno++)
00656       if (blocks[blockno].data(buckno))
00657         buckets += 1;
00658   return buckets;
00659 }
00660 
00661 unsigned int 
00662 IW44Image::Map::get_memory_usage(void) const
00663 {
00664   unsigned int usage = sizeof(Map);
00665   usage += sizeof(IW44Image::Block) * nb;
00666   for (IW44Image::Alloc *n = chain; n; n=n->next)
00667     usage += sizeof(IW44Image::Alloc);
00668   return usage;
00669 }
00670 
00671 
00672 
00673 
00674 void 
00675 IW44Image::Map::image(signed char *img8, int rowsize, int pixsep, int fast)
00676 {
00677   // Allocate reconstruction buffer
00678   short *data16;
00679   GPBuffer<short> gdata16(data16,bw*bh);
00680   // Copy coefficients
00681   int i;
00682   short *p = data16;
00683   const IW44Image::Block *block = blocks;
00684   for (i=0; i<bh; i+=32)
00685     {
00686       for (int j=0; j<bw; j+=32)
00687         {
00688           short liftblock[1024];
00689           // transfer into IW44Image::Block (apply zigzag and scaling)
00690           block->write_liftblock(liftblock);
00691           block++;
00692           // transfer into coefficient matrix at (p+j)
00693           short *pp = p + j;
00694           short *pl = liftblock;
00695           for (int ii=0; ii<32; ii++, pp+=bw,pl+=32)
00696             memcpy((void*)pp, (void*)pl, 32*sizeof(short));
00697         }
00698       // next row of blocks
00699       p += 32*bw;
00700     }
00701   // Reconstruction
00702   if (fast)
00703     {
00704       IW44Image::Transform::Decode::backward(data16, iw, ih, bw, 32, 2);  
00705       p = data16;
00706       for (i=0; i<bh; i+=2,p+=bw)
00707         for (int jj=0; jj<bw; jj+=2,p+=2)
00708           p[bw] = p[bw+1] = p[1] = p[0];
00709     }
00710   else
00711     {
00712       IW44Image::Transform::Decode::backward(data16, iw, ih, bw, 32, 1);  
00713     }
00714   // Copy result into image
00715   p = data16;
00716   signed char *row = img8;  
00717   for (i=0; i<ih; i++)
00718     {
00719       signed char *pix = row;
00720       for (int j=0; j<iw; j+=1,pix+=pixsep)
00721         {
00722           int x = (p[j] + iw_round) >> iw_shift;
00723           if (x < -128)
00724             x = -128;
00725           else if (x > 127)
00726             x = 127;
00727           *pix = x;
00728         }
00729       row += rowsize;
00730       p += bw;
00731     }
00732 }
00733 
00734 void 
00735 IW44Image::Map::image(int subsample, const GRect &rect, 
00736               signed char *img8, int rowsize, int pixsep, int fast)
00737 {
00738   int i;
00739   // Compute number of decomposition levels
00740   int nlevel = 0;
00741   while (nlevel<5 && (32>>nlevel)>subsample)
00742     nlevel += 1;
00743   int boxsize = 1<<nlevel;
00744   // Parameter check
00745   if (subsample!=(32>>nlevel))
00746     G_THROW( ERR_MSG("IW44Image.sample_factor") );
00747   if (rect.isempty())
00748     G_THROW( ERR_MSG("IW44Image.empty_rect") );    
00749   GRect irect(0,0,(iw+subsample-1)/subsample,(ih+subsample-1)/subsample);
00750   if (rect.xmin<0 || rect.ymin<0 || rect.xmax>irect.xmax || rect.ymax>irect.ymax)
00751     G_THROW( ERR_MSG("IW44Image.bad_rect") );
00752   // Multiresolution rectangles 
00753   // -- needed[i] tells which coeffs are required for the next step
00754   // -- recomp[i] tells which coeffs need to be computed at this level
00755   GRect needed[8];
00756   GRect recomp[8];
00757   int r = 1;
00758   needed[nlevel] = rect;
00759   recomp[nlevel] = rect;
00760   for (i=nlevel-1; i>=0; i--)
00761     {
00762       needed[i] = recomp[i+1];
00763       needed[i].inflate(iw_border*r, iw_border*r);
00764       needed[i].intersect(needed[i], irect);
00765       r += r;
00766       recomp[i].xmin = (needed[i].xmin + r-1) & ~(r-1);
00767       recomp[i].xmax = (needed[i].xmax) & ~(r-1);
00768       recomp[i].ymin = (needed[i].ymin + r-1) & ~(r-1);
00769       recomp[i].ymax = (needed[i].ymax) & ~(r-1);
00770     }
00771   // Working rectangle
00772   // -- a rectangle large enough to hold all the data
00773   GRect work;
00774   work.xmin = (needed[0].xmin) & ~(boxsize-1);
00775   work.ymin = (needed[0].ymin) & ~(boxsize-1);
00776   work.xmax = ((needed[0].xmax-1) & ~(boxsize-1) ) + boxsize;
00777   work.ymax = ((needed[0].ymax-1) & ~(boxsize-1) ) + boxsize;
00778   // -- allocate work buffer
00779   int dataw = work.xmax - work.xmin;     // Note: cannot use inline width() or height()
00780   int datah = work.ymax - work.ymin;     // because Intel C++ compiler optimizes it wrong !
00781   short *data;
00782   GPBuffer<short> gdata(data,dataw*datah);
00783   // Fill working rectangle
00784   // -- loop over liftblocks rows
00785   short *ldata = data;
00786   int blkw = (bw>>5);
00787   const IW44Image::Block *lblock = blocks + (work.ymin>>nlevel)*blkw + (work.xmin>>nlevel);
00788   for (int by=work.ymin; by<work.ymax; by+=boxsize)
00789     {
00790       // -- loop over liftblocks in row
00791       const IW44Image::Block *block = lblock;
00792       short *rdata = ldata;
00793       for (int bx=work.xmin; bx<work.xmax; bx+=boxsize)        
00794         {
00795           // -- decide how much to load
00796           int mlevel = nlevel;
00797           if (nlevel>2)
00798             if (bx+31<needed[2].xmin || bx>needed[2].xmax ||
00799                 by+31<needed[2].ymin || by>needed[2].ymax )
00800               mlevel = 2;
00801           int bmax   = ((1<<(mlevel+mlevel))+15)>>4;
00802           int ppinc  = (1<<(nlevel-mlevel));
00803           int ppmod1 = (dataw<<(nlevel-mlevel));
00804           int ttmod0 = (32 >> mlevel);
00805           int ttmod1 = (ttmod0 << 5);
00806           // -- get current block
00807           short liftblock[1024];
00808           block->write_liftblock(liftblock, 0, bmax );
00809           // -- copy liftblock into image
00810           short *tt = liftblock;
00811           short *pp = rdata;
00812           for (int ii=0; ii<boxsize; ii+=ppinc,pp+=ppmod1,tt+=ttmod1-32)
00813             for (int jj=0; jj<boxsize; jj+=ppinc,tt+=ttmod0)
00814               pp[jj] = *tt;
00815           // -- next block in row
00816           rdata += boxsize;
00817           block += 1;
00818         }
00819       // -- next row of blocks
00820       ldata += dataw << nlevel;
00821       lblock += blkw;
00822     }
00823   // Perform reconstruction
00824   r = boxsize;
00825   for (i=0; i<nlevel; i++)
00826     {
00827       GRect comp = needed[i];
00828       comp.xmin = comp.xmin & ~(r-1);
00829       comp.ymin = comp.ymin & ~(r-1);
00830       comp.translate(-work.xmin, -work.ymin);
00831       // Fast mode shortcuts finer resolution
00832       if (fast && i>=4) 
00833         {
00834           short *pp = data + comp.ymin*dataw;
00835           for (int ii=comp.ymin; ii<comp.ymax; ii+=2, pp+=dataw+dataw)
00836             for (int jj=comp.xmin; jj<comp.xmax; jj+=2)
00837               pp[jj+dataw] = pp[jj+dataw+1] = pp[jj+1] = pp[jj];
00838           break;
00839         }
00840       else
00841         {
00842           short *pp = data + comp.ymin*dataw + comp.xmin;
00843           IW44Image::Transform::Decode::backward(pp, comp.width(), comp.height(), dataw, r, r>>1);
00844         }
00845       r = r>>1;
00846     }
00847   // Copy result into image
00848   GRect nrect = rect;
00849   nrect.translate(-work.xmin, -work.ymin);
00850   short *p = data + nrect.ymin*dataw;
00851   signed char *row = img8;  
00852   for (i=nrect.ymin; i<nrect.ymax; i++)
00853     {
00854       int j;
00855       signed char *pix = row;
00856       for (j=nrect.xmin; j<nrect.xmax; j+=1,pix+=pixsep)
00857         {
00858           int x = (p[j] + iw_round) >> iw_shift;
00859           if (x < -128)
00860             x = -128;
00861           else if (x > 127)
00862             x = 127;
00863           *pix = x;
00864         }
00865       row += rowsize;
00866       p += dataw;
00867     }
00868 }
00869 
00870 
00871 
00872 
00874 // ENCODING/DECODING WAVELET COEFFICIENTS 
00875 //    USING HIERARCHICAL SET DIFFERENCE
00877 
00878 
00879 //-----------------------------------------------
00880 // Class IW44Image::Codec [implementation]
00881 // Maintains information shared while encoding or decoding
00882 
00883 
00884 // Constant
00885 
00886 static const struct { int start; int size; }  
00887 bandbuckets[] = 
00888 {
00889   // Code first bucket and number of buckets in each band
00890   { 0, 1 }, // -- band zero contains all lores info
00891   { 1, 1 }, { 2, 1 }, { 3, 1 }, 
00892   { 4, 4 }, { 8, 4 }, { 12,4 }, 
00893   { 16,16 }, { 32,16 }, { 48,16 }, 
00894 };
00895 
00896 
00897 // IW44Image::Codec constructor
00898 
00899 IW44Image::Codec::Codec(IW44Image::Map &xmap)
00900   : map(xmap), 
00901     curband(0),
00902     curbit(1)
00903 {
00904   // Initialize quantification
00905   int  j;
00906   int  i = 0;
00907   const int *q = iw_quant;
00908   // -- lo coefficients
00909   for (j=0; i<4; j++)
00910     quant_lo[i++] = *q++;
00911   for (j=0; j<4; j++)
00912     quant_lo[i++] = *q;
00913   q += 1;
00914   for (j=0; j<4; j++)
00915     quant_lo[i++] = *q;
00916   q += 1;
00917   for (j=0; j<4; j++)
00918     quant_lo[i++] = *q;
00919   q += 1;
00920   // -- hi coefficients
00921   quant_hi[0] = 0;
00922   for (j=1; j<10; j++)
00923     quant_hi[j] = *q++;
00924   // Initialize coding contexts
00925   memset((void*)ctxStart, 0, sizeof(ctxStart));
00926   memset((void*)ctxBucket, 0, sizeof(ctxBucket));
00927   ctxMant = 0;
00928   ctxRoot = 0;
00929 }
00930 
00931 
00932 // IW44Image::Codec destructor
00933 
00934 IW44Image::Codec::~Codec() {}
00935 
00936 // is_null_slice
00937 // -- check if data can be produced for this band/mask
00938 // -- also fills the sure_zero array
00939 
00940 int 
00941 IW44Image::Codec::is_null_slice(int bit, int band)
00942 {
00943   if (band == 0)
00944     {
00945       int is_null = 1;
00946       for (int i=0; i<16; i++) 
00947         {
00948           int threshold = quant_lo[i];
00949           coeffstate[i] = ZERO;
00950           if (threshold>0 && threshold<0x8000)
00951             {
00952               coeffstate[i] = UNK;
00953               is_null = 0;
00954             }
00955         }
00956       return is_null;
00957     }
00958   else
00959     {
00960       int threshold = quant_hi[band];
00961       return (! (threshold>0 && threshold<0x8000));
00962     }
00963 }
00964 
00965 
00966 // code_slice
00967 // -- read/write a slice of datafile
00968 
00969 int
00970 IW44Image::Codec::Decode::code_slice(ZPCodec &zp)
00971 {
00972   // Check that code_slice can still run
00973   if (curbit < 0)
00974     return 0;
00975   // Perform coding
00976   if (! is_null_slice(curbit, curband))
00977     {
00978       for (int blockno=0; blockno<map.nb; blockno++)
00979         {
00980           int fbucket = bandbuckets[curband].start;
00981           int nbucket = bandbuckets[curband].size;
00982           decode_buckets(zp, curbit, curband, 
00983                            map.blocks[blockno], 
00984                            fbucket, nbucket);
00985         }
00986     }
00987   return finish_code_slice(zp);
00988 }
00989 
00990 // code_slice
00991 // -- read/write a slice of datafile
00992 
00993 int
00994 IW44Image::Codec::finish_code_slice(ZPCodec &zp)
00995 {
00996   // Reduce quantization threshold
00997   quant_hi[curband] = quant_hi[curband] >> 1;
00998   if (curband == 0)
00999     for (int i=0; i<16; i++) 
01000       quant_lo[i] = quant_lo[i] >> 1;
01001   // Proceed to the next slice
01002   if (++curband >= (int)(sizeof(bandbuckets)/sizeof(bandbuckets[0])))
01003     {
01004       curband = 0;
01005       curbit += 1;
01006       if (quant_hi[(sizeof(bandbuckets)/sizeof(bandbuckets[0]))-1] == 0)
01007         {
01008           // All quantization thresholds are null
01009           curbit = -1;
01010           return 0;
01011         }
01012     }
01013   return 1;
01014 }
01015 
01016 // decode_prepare
01017 // -- prepare the states before decoding buckets
01018 
01019 int
01020 IW44Image::Codec::decode_prepare(int fbucket, int nbucket, IW44Image::Block &blk)
01021 {  
01022   int bbstate = 0;
01023   char *cstate = coeffstate;
01024   if (fbucket)
01025     {
01026       // Band other than zero
01027       for (int buckno=0; buckno<nbucket; buckno++, cstate+=16)
01028         {
01029           int bstatetmp = 0;
01030           const short *pcoeff = blk.data(fbucket+buckno);
01031           if (! pcoeff)
01032             {
01033               // cstate[0..15] will be filled later
01034               bstatetmp = UNK;
01035             }
01036           else
01037             {
01038               for (int i=0; i<16; i++)
01039                 {
01040                   int cstatetmp = UNK;
01041                   if (pcoeff[i])
01042                     cstatetmp = ACTIVE;
01043                   cstate[i] = cstatetmp;
01044                   bstatetmp |= cstatetmp;
01045                 }
01046             }
01047           bucketstate[buckno] = bstatetmp;
01048           bbstate |= bstatetmp;
01049         }
01050     }
01051   else
01052     {
01053       // Band zero ( fbucket==0 implies band==zero and nbucket==1 )
01054       const short *pcoeff = blk.data(0);
01055       if (! pcoeff)
01056         {
01057           // cstate[0..15] will be filled later
01058           bbstate = UNK;      
01059         }
01060       else
01061         {
01062           for (int i=0; i<16; i++)
01063             {
01064               int cstatetmp = cstate[i];
01065               if (cstatetmp != ZERO)
01066                 {
01067                   cstatetmp = UNK;
01068                   if (pcoeff[i])
01069                     cstatetmp = ACTIVE;
01070                 }
01071               cstate[i] = cstatetmp;
01072               bbstate |= cstatetmp;
01073             }
01074         }
01075       bucketstate[0] = bbstate;
01076     }
01077   return bbstate;
01078 }
01079 
01080 
01081 // decode_buckets
01082 // -- code a sequence of buckets in a given block
01083 
01084 void
01085 IW44Image::Codec::decode_buckets(ZPCodec &zp, int bit, int band, 
01086                          IW44Image::Block &blk,
01087                          int fbucket, int nbucket)
01088 {
01089   // compute state of all coefficients in all buckets
01090   int bbstate = decode_prepare(fbucket, nbucket, blk);
01091   // code root bit
01092   if ((nbucket<16) || (bbstate&ACTIVE))
01093     {
01094       bbstate |= NEW;
01095     }
01096   else if (bbstate & UNK)
01097     {
01098       if (zp.decoder(ctxRoot))
01099         bbstate |= NEW;
01100 #ifdef TRACE
01101       DjVuPrintMessage("bbstate[bit=%d,band=%d] = %d\n", bit, band, bbstate);
01102 #endif
01103     }
01104   
01105   // code bucket bits
01106   if (bbstate & NEW)
01107     for (int buckno=0; buckno<nbucket; buckno++)
01108       {
01109         // Code bucket bit
01110         if (bucketstate[buckno] & UNK)
01111           {
01112             // Context
01113             int ctx = 0;
01114 #ifndef NOCTX_BUCKET_UPPER
01115             if (band>0)
01116               {
01117                 int k = (fbucket+buckno)<<2;
01118                 const short *b = blk.data(k>>4);
01119                 if (b)
01120                   {
01121                     k = k & 0xf;
01122                     if (b[k])
01123                       ctx += 1;
01124                     if (b[k+1])
01125                       ctx += 1;
01126                     if (b[k+2])
01127                       ctx += 1;
01128                     if (ctx<3 && b[k+3])
01129                       ctx += 1;
01130                   }
01131               }
01132 #endif // NOCTX_BUCKET_UPPER
01133 #ifndef NOCTX_BUCKET_ACTIVE
01134             if (bbstate & ACTIVE)
01135               ctx |= 4; 
01136 #endif
01137             // Code
01138             if (zp.decoder( ctxBucket[band][ctx] ))
01139               bucketstate[buckno] |= NEW;
01140 #ifdef TRACE
01141             DjVuPrintMessage("  bucketstate[bit=%d,band=%d,buck=%d] = %d\n", 
01142                    bit, band, buckno, bucketstate[buckno]);
01143 #endif
01144           }
01145       }
01146 
01147   // code new active coefficient (with their sign)
01148   if (bbstate & NEW)
01149     {
01150       int thres = quant_hi[band];
01151       char *cstate = coeffstate;
01152       for (int buckno=0; buckno<nbucket; buckno++, cstate+=16)
01153         if (bucketstate[buckno] & NEW)
01154           {
01155             int i;
01156             short *pcoeff = (short*)blk.data(fbucket+buckno);
01157             if (!pcoeff)
01158               {
01159                 pcoeff = blk.data(fbucket+buckno, &map);
01160                 // time to fill cstate[0..15]
01161                 if (fbucket == 0) // band zero
01162                   {
01163                     for (i=0; i<16; i++)
01164                       if (cstate[i] != ZERO)
01165                         cstate[i] = UNK;
01166                   }
01167                 else
01168                   {
01169                     for (i=0; i<16; i++)
01170                       cstate[i] = UNK;
01171                   }
01172               }
01173 #ifndef NOCTX_EXPECT
01174             int gotcha = 0;
01175             const int maxgotcha = 7;
01176             for (i=0; i<16; i++)
01177               if (cstate[i] & UNK)
01178                 gotcha += 1;
01179 #endif
01180             for (i=0; i<16; i++)
01181               {
01182                 if (cstate[i] & UNK)
01183                   {
01184                     // find lores threshold
01185                     if (band == 0)
01186                       thres = quant_lo[i];
01187                     // prepare context
01188                     int ctx = 0;
01189 #ifndef NOCTX_EXPECT
01190                     if (gotcha>=maxgotcha)
01191                       ctx = maxgotcha;
01192                     else
01193                       ctx = gotcha;
01194 #endif
01195 #ifndef NOCTX_ACTIVE
01196                     if (bucketstate[buckno] & ACTIVE)
01197                       ctx |= 8;
01198 #endif
01199                     // code difference bit
01200                     if (zp.decoder( ctxStart[ctx] ))
01201                       {
01202                         cstate[i] |= NEW;
01203                         int halfthres = thres>>1;
01204                         int coeff = thres+halfthres-(halfthres>>2);
01205                         if (zp.IWdecoder())
01206                           pcoeff[i] = -coeff;
01207                         else
01208                           pcoeff[i] = coeff;
01209                       }
01210 #ifndef NOCTX_EXPECT
01211                     if (cstate[i] & NEW)
01212                       gotcha = 0;
01213                     else if (gotcha > 0)
01214                       gotcha -= 1;
01215 #endif
01216 #ifdef TRACE
01217                     DjVuPrintMessage("    coeffstate[bit=%d,band=%d,buck=%d,c=%d] = %d\n", 
01218                            bit, band, buckno, i, cstate[i]);
01219 #endif
01220                   }
01221               }
01222           }
01223     }
01224   
01225   // code mantissa bits
01226   if (bbstate & ACTIVE)
01227     {
01228       int thres = quant_hi[band];
01229       char *cstate = coeffstate;
01230       for (int buckno=0; buckno<nbucket; buckno++, cstate+=16)
01231         if (bucketstate[buckno] & ACTIVE)
01232           {
01233             short *pcoeff = (short*)blk.data(fbucket+buckno);
01234             for (int i=0; i<16; i++)
01235               if (cstate[i] & ACTIVE)
01236                 {
01237                   int coeff = pcoeff[i];
01238                   if (coeff < 0)
01239                     coeff = -coeff;
01240                   // find lores threshold
01241                   if (band == 0)
01242                     thres = quant_lo[i];
01243                   // adjust coefficient
01244                   if (coeff <= 3*thres)
01245                     {
01246                       // second mantissa bit
01247                       coeff = coeff + (thres>>2);
01248                       if (zp.decoder(ctxMant))
01249                         coeff = coeff + (thres>>1);
01250                       else
01251                         coeff = coeff - thres + (thres>>1);
01252                     }
01253                   else
01254                     {
01255                       if (zp.IWdecoder())
01256                         coeff = coeff + (thres>>1);
01257                       else
01258                         coeff = coeff - thres + (thres>>1);
01259                     }
01260                   // store coefficient
01261                   if (pcoeff[i] > 0)
01262                     pcoeff[i] = coeff;
01263                   else
01264                     pcoeff[i] = -coeff;
01265                 }
01266           }
01267     }
01268 }
01269 
01270 
01272 // UTILITIES
01274 
01275 
01276 #ifdef min
01277 #undef min
01278 #endif
01279 static inline int
01280 min(const int x, const int y)
01281 {
01282   return (x <= y) ? x : y;
01283 }
01284 
01285 #ifdef max
01286 #undef max
01287 #endif
01288 static inline int
01289 max(const int x, const int y)
01290 {
01291   return (y <= x) ? x : y;
01292 }
01293 
01294 
01295 void 
01296 IW44Image::PrimaryHeader::decode(GP<ByteStream> gbs)
01297 {
01298   serial = gbs->read8();
01299   slices = gbs->read8();
01300 }
01301 
01302 void 
01303 IW44Image::SecondaryHeader::decode(GP<ByteStream> gbs)
01304 {
01305   major = gbs->read8();
01306   minor = gbs->read8();
01307 }
01308 
01309 void 
01310 IW44Image::TertiaryHeader::decode(GP<ByteStream> gbs, int major, int minor)
01311 {
01312   xhi = gbs->read8();
01313   xlo = gbs->read8();
01314   yhi = gbs->read8();
01315   ylo = gbs->read8();
01316   crcbdelay = 0;
01317   if (major== 1 && minor>=2)
01318     crcbdelay = gbs->read8();
01319 }
01320 
01321 
01322 
01324 // CLASS IW44Image
01326 
01327 IW44Image::IW44Image(void)
01328   : db_frac(1.0),
01329     ymap(0), cbmap(0), crmap(0),
01330     cslice(0), cserial(0), cbytes(0)
01331 {}
01332 
01333 IW44Image::~IW44Image()
01334 {
01335   delete ymap;
01336   delete cbmap;
01337   delete crmap;
01338 }
01339 
01340 GP<IW44Image>
01341 IW44Image::create_decode(const ImageType itype)
01342 {
01343   switch(itype)
01344   {
01345   case COLOR:
01346     return new IWPixmap();
01347   case GRAY:
01348     return new IWBitmap();
01349   default:
01350     return 0;
01351   }
01352 }
01353 
01354 int
01355 IW44Image::encode_chunk(GP<ByteStream>, const IWEncoderParms &)
01356 {
01357   G_THROW( ERR_MSG("IW44Image.codec_open2") );
01358   return 0;
01359 }
01360 
01361 void 
01362 IW44Image::encode_iff(IFFByteStream &, int nchunks, const IWEncoderParms *)
01363 {
01364   G_THROW( ERR_MSG("IW44Image.codec_open2") );
01365 }
01366 
01367   
01368 void 
01369 IWBitmap::close_codec(void)
01370 {
01371   delete ycodec;
01372   ycodec = 0;
01373   cslice = cbytes = cserial = 0;
01374 }
01375 
01376 void 
01377 IWPixmap::close_codec(void)
01378 {
01379   delete ycodec;
01380   delete cbcodec;
01381   delete crcodec;
01382   ycodec = crcodec = cbcodec = 0;
01383   cslice = cbytes = cserial = 0;
01384 }
01385 
01386 int 
01387 IW44Image::get_width(void) const
01388 {
01389   return (ymap)?(ymap->iw):0;
01390 }
01391 
01392 int 
01393 IW44Image::get_height(void) const
01394 {
01395   return (ymap)?(ymap->ih):0;
01396 }
01397 
01398 
01400 // CLASS IWBITMAP
01402 
01403 IWBitmap::IWBitmap(void )
01404 : IW44Image(), ycodec(0)
01405 {}
01406 
01407 IWBitmap::~IWBitmap()
01408 {
01409   close_codec();
01410 }
01411 
01412 int
01413 IWBitmap::get_percent_memory(void) const
01414 {
01415   int buckets = 0;
01416   int maximum = 0;
01417   if (ymap) 
01418     {
01419       buckets += ymap->get_bucket_count();
01420       maximum += 64 * ymap->nb;
01421     }
01422   return 100*buckets/ (maximum ? maximum : 1);
01423 }
01424 
01425 unsigned int
01426 IWBitmap::get_memory_usage(void) const
01427 {
01428   unsigned int usage = sizeof(GBitmap);
01429   if (ymap)
01430     usage += ymap->get_memory_usage();
01431   return usage;
01432 }
01433 
01434 
01435 GP<GBitmap> 
01436 IWBitmap::get_bitmap(void)
01437 {
01438   // Check presence of data
01439   if (ymap == 0)
01440     return 0;
01441   // Perform wavelet reconstruction
01442   int w = ymap->iw;
01443   int h = ymap->ih;
01444   GP<GBitmap> pbm = GBitmap::create(h, w);
01445   ymap->image((signed char*)(*pbm)[0],pbm->rowsize());
01446   // Shift image data
01447   for (int i=0; i<h; i++)
01448     {
01449       unsigned char *urow = (*pbm)[i];
01450       signed char *srow = (signed char*)urow;
01451       for (int j=0; j<w; j++)
01452         urow[j] = (int)(srow[j]) + 128;
01453     }
01454   pbm->set_grays(256);
01455   return pbm;
01456 }
01457 
01458 
01459 GP<GBitmap>
01460 IWBitmap::get_bitmap(int subsample, const GRect &rect)
01461 {
01462   if (ymap == 0)
01463     return 0;
01464   // Allocate bitmap
01465   int w = rect.width();
01466   int h = rect.height();
01467   GP<GBitmap> pbm = GBitmap::create(h,w);
01468   ymap->image(subsample, rect, (signed char*)(*pbm)[0],pbm->rowsize());
01469   // Shift image data
01470   for (int i=0; i<h; i++)
01471     {
01472       unsigned char *urow = (*pbm)[i];
01473       signed char *srow = (signed char*)urow;
01474       for (int j=0; j<w; j++)
01475         urow[j] = (int)(srow[j]) + 128;
01476     }
01477   pbm->set_grays(256);
01478   return pbm;
01479 }
01480 
01481 
01482 int
01483 IWBitmap::decode_chunk(GP<ByteStream> gbs)
01484 {
01485   // Open
01486   if (! ycodec)
01487   {
01488     cslice = cserial = 0;
01489     delete ymap;
01490     ymap = 0;
01491   }
01492   // Read primary header
01493   struct IW44Image::PrimaryHeader primary;
01494   primary.decode(gbs);
01495   if (primary.serial != cserial)
01496     G_THROW( ERR_MSG("IW44Image.wrong_serial") );
01497   int nslices = cslice + primary.slices;
01498   // Read auxilliary headers
01499   if (cserial == 0)
01500     {
01501       struct IW44Image::SecondaryHeader secondary;
01502       secondary.decode(gbs);
01503       if ((secondary.major & 0x7f) != IWCODEC_MAJOR)
01504         G_THROW( ERR_MSG("IW44Image.incompat_codec") );
01505       if (secondary.minor > IWCODEC_MINOR)
01506         G_THROW( ERR_MSG("IW44Image.recent_codec") );
01507       // Read tertiary header
01508       struct IW44Image::TertiaryHeader tertiary;
01509       tertiary.decode(gbs, secondary.major & 0x7f, secondary.minor);
01510       if (! (secondary.major & 0x80))
01511         G_THROW( ERR_MSG("IW44Image.has_color") );
01512       // Create ymap and ycodec
01513       int w = (tertiary.xhi << 8) | tertiary.xlo;
01514       int h = (tertiary.yhi << 8) | tertiary.ylo;
01515       assert(! ymap);
01516       ymap = new Map(w, h);
01517       assert(! ycodec);
01518       ycodec = new Codec::Decode(*ymap);
01519     }
01520   // Read data
01521   assert(ymap);
01522   assert(ycodec);
01523   GP<ZPCodec> gzp=ZPCodec::create(gbs, false, true);
01524   ZPCodec &zp=*gzp;
01525   int flag = 1;
01526   while (flag && cslice<nslices)
01527     {
01528       flag = ycodec->code_slice(zp);
01529       cslice++;
01530     }
01531   // Return
01532   cserial += 1;
01533   return nslices;
01534 }
01535 
01536 void 
01537 IWBitmap::parm_dbfrac(float frac)
01538 {
01539   if (frac>0 && frac<=1)
01540     db_frac = frac;
01541   else
01542     G_THROW( ERR_MSG("IW44Image.param_range") );
01543 }
01544 
01545 
01546 int 
01547 IWBitmap::get_serial(void)
01548 {
01549   return cserial;
01550 }
01551 
01552 void 
01553 IWBitmap::decode_iff(IFFByteStream &iff, int maxchunks)
01554 {
01555   if (ycodec)
01556     G_THROW( ERR_MSG("IW44Image.left_open2") );
01557   GUTF8String chkid;
01558   iff.get_chunk(chkid);
01559   if (chkid != "FORM:BM44")
01560     G_THROW( ERR_MSG("IW44Image.corrupt_BM44") );
01561   while (--maxchunks>=0 && iff.get_chunk(chkid))
01562     {
01563       if (chkid == "BM44")
01564         decode_chunk(iff.get_bytestream());
01565       iff.close_chunk();
01566     }
01567   iff.close_chunk();
01568   close_codec();
01569 }
01570 
01571 
01572 
01573 
01575 // CLASS IWENCODERPARMS
01577 
01578 
01579 IWEncoderParms::IWEncoderParms(void)
01580 {
01581   // Zero represent default values
01582   memset((void*)this, 0, sizeof(IWEncoderParms));
01583 }
01584 
01585 
01586 
01587 
01588 
01590 // CLASS IWPIXMAP
01592 
01593 
01594 IWPixmap::IWPixmap(void)
01595 : IW44Image(), crcb_delay(10), crcb_half(0), ycodec(0), cbcodec(0), crcodec(0)
01596 {}
01597 
01598 IWPixmap::~IWPixmap()
01599 {
01600   close_codec();
01601 }
01602 
01603 int
01604 IWPixmap::get_percent_memory(void) const
01605 {
01606   int buckets = 0;
01607   int maximum = 0;
01608   if (ymap)
01609     {
01610       buckets += ymap->get_bucket_count();
01611       maximum += 64*ymap->nb;
01612     }
01613   if (cbmap)
01614     {
01615       buckets += cbmap->get_bucket_count();
01616       maximum += 64*cbmap->nb;
01617     }
01618   if (crmap)
01619     {
01620       buckets += crmap->get_bucket_count();
01621       maximum += 64*crmap->nb;
01622     }
01623   return 100*buckets/ (maximum ? maximum : 1);
01624 }
01625 
01626 unsigned int
01627 IWPixmap::get_memory_usage(void) const
01628 {
01629   unsigned int usage = sizeof(GPixmap);
01630   if (ymap)
01631     usage += ymap->get_memory_usage();
01632   if (cbmap)
01633     usage += cbmap->get_memory_usage();
01634   if (crmap)
01635     usage += crmap->get_memory_usage();
01636   return usage;
01637 }
01638 
01639 
01640 GP<GPixmap> 
01641 IWPixmap::get_pixmap(void)
01642 {
01643   // Check presence of data
01644   if (ymap == 0)
01645     return 0;
01646   // Allocate pixmap
01647   int w = ymap->iw;
01648   int h = ymap->ih;
01649   GP<GPixmap> ppm = GPixmap::create(h, w);
01650   // Perform wavelet reconstruction
01651   signed char *ptr = (signed char*) (*ppm)[0];
01652   int rowsep = ppm->rowsize() * sizeof(GPixel);
01653   int pixsep = sizeof(GPixel);
01654   ymap->image(ptr, rowsep, pixsep);
01655   if (crmap && cbmap && crcb_delay >= 0)
01656   {
01657     cbmap->image(ptr+1, rowsep, pixsep, crcb_half);
01658     crmap->image(ptr+2, rowsep, pixsep, crcb_half);
01659   }
01660   // Convert image data to RGB
01661   if (crmap && cbmap && crcb_delay >= 0)
01662     {
01663       Transform::Decode::YCbCr_to_RGB((*ppm)[0], w, h, ppm->rowsize());
01664     }
01665   else
01666     {
01667       for (int i=0; i<h; i++)
01668         {
01669           GPixel *pixrow = (*ppm)[i];
01670           for (int j=0; j<w; j++, pixrow++)
01671             pixrow->b = pixrow->g = pixrow->r 
01672               = 127 - (int)(((signed char*)pixrow)[0]);
01673         }
01674     }
01675   // Return
01676   return ppm;
01677 }
01678 
01679 
01680 
01681 GP<GPixmap>
01682 IWPixmap::get_pixmap(int subsample, const GRect &rect)
01683 {
01684   if (ymap == 0)
01685     return 0;
01686   // Allocate
01687   int w = rect.width();
01688   int h = rect.height();
01689   GP<GPixmap> ppm = GPixmap::create(h,w);
01690   // Perform wavelet reconstruction
01691   signed char *ptr = (signed char*) (*ppm)[0];
01692   int rowsep = ppm->rowsize() * sizeof(GPixel);
01693   int pixsep = sizeof(GPixel);
01694   ymap->image(subsample, rect, ptr, rowsep, pixsep);
01695   if (crmap && cbmap && crcb_delay >= 0)
01696   {
01697     cbmap->image(subsample, rect, ptr+1, rowsep, pixsep, crcb_half);
01698     crmap->image(subsample, rect, ptr+2, rowsep, pixsep, crcb_half);
01699   }
01700   // Convert image data to RGB
01701   if (crmap && cbmap && crcb_delay >= 0)
01702     {
01703       Transform::Decode::YCbCr_to_RGB((*ppm)[0], w, h, ppm->rowsize());
01704     }
01705   else
01706     {
01707       for (int i=0; i<h; i++)
01708         {
01709           GPixel *pixrow = (*ppm)[i];
01710           for (int j=0; j<w; j++, pixrow++)
01711             pixrow->b = pixrow->g = pixrow->r 
01712               = 127 - (int)(((signed char*)pixrow)[0]);
01713         }
01714     }
01715   // Return
01716   return ppm;
01717 }
01718 
01719 
01720 int
01721 IWPixmap::decode_chunk(GP<ByteStream> gbs)
01722 {
01723   // Open
01724   if (! ycodec)
01725   {
01726       cslice = cserial = 0;
01727       delete ymap;
01728       ymap = 0;
01729   }
01730 
01731   // Read primary header
01732   struct IW44Image::PrimaryHeader primary;
01733   primary.decode(gbs);
01734   if (primary.serial != cserial)
01735     G_THROW( ERR_MSG("IW44Image.wrong_serial2") );
01736   int nslices = cslice + primary.slices;
01737   // Read secondary header
01738   if (cserial == 0)
01739     {
01740       struct IW44Image::SecondaryHeader secondary;
01741       secondary.decode(gbs);
01742       if ((secondary.major & 0x7f) != IWCODEC_MAJOR)
01743         G_THROW( ERR_MSG("IW44Image.incompat_codec2") );
01744       if (secondary.minor > IWCODEC_MINOR)
01745         G_THROW( ERR_MSG("IW44Image.recent_codec2") );
01746       // Read tertiary header
01747       struct IW44Image::TertiaryHeader tertiary;
01748       tertiary.decode(gbs, secondary.major & 0x7f, secondary.minor);
01749       // Handle header information
01750       int w = (tertiary.xhi << 8) | tertiary.xlo;
01751       int h = (tertiary.yhi << 8) | tertiary.ylo;
01752       crcb_delay = 0;
01753       crcb_half = 0;
01754       if (secondary.minor>=2)
01755         crcb_delay = tertiary.crcbdelay & 0x7f;
01756       if (secondary.minor>=2)
01757         crcb_half = (tertiary.crcbdelay & 0x80 ? 0 : 1);
01758       if (secondary.major & 0x80)
01759         crcb_delay = -1;
01760       // Create ymap and ycodec    
01761       assert(! ymap);
01762       assert(! ycodec);
01763       ymap = new Map(w, h);
01764       ycodec = new Codec::Decode(*ymap);
01765       if (crcb_delay >= 0)
01766         {
01767           cbmap = new Map(w, h);
01768           crmap = new Map(w, h);
01769           cbcodec = new Codec::Decode(*cbmap);
01770           crcodec = new Codec::Decode(*crmap);
01771         }
01772     }
01773   // Read data
01774   assert(ymap);
01775   assert(ycodec);
01776   GP<ZPCodec> gzp=ZPCodec::create(gbs, false, true);
01777   ZPCodec &zp=*gzp;
01778   int flag = 1;
01779   while (flag && cslice<nslices)
01780     {
01781       flag = ycodec->code_slice(zp);
01782       if (crcodec && cbcodec && crcb_delay<=cslice)
01783         {
01784           flag |= cbcodec->code_slice(zp);
01785           flag |= crcodec->code_slice(zp);
01786         }
01787       cslice++;
01788     }
01789   // Return
01790   cserial += 1;
01791   return nslices;
01792 }
01793 
01794 
01795 int 
01796 IWPixmap::parm_crcbdelay(const int parm)
01797 {
01798   if (parm >= 0)
01799     crcb_delay = parm;
01800   return crcb_delay;
01801 }
01802 
01803 void 
01804 IWPixmap::parm_dbfrac(float frac)
01805 {
01806   if (frac>0 && frac<=1)
01807     db_frac = frac;
01808   else
01809     G_THROW( ERR_MSG("IW44Image.param_range2") );
01810 }
01811 
01812 int 
01813 IWPixmap::get_serial(void)
01814 {
01815   return cserial;
01816 }
01817 
01818 
01819 void 
01820 IWPixmap::decode_iff(IFFByteStream &iff, int maxchunks)
01821 {
01822   if (ycodec)
01823     G_THROW( ERR_MSG("IW44Image.left_open4") );
01824   GUTF8String chkid;
01825   iff.get_chunk(chkid);
01826   if (chkid!="FORM:PM44" && chkid!="FORM:BM44")
01827     G_THROW( ERR_MSG("IW44Image.corrupt_BM44_2") );
01828   while (--maxchunks>=0 && iff.get_chunk(chkid))
01829     {
01830       if (chkid=="PM44" || chkid=="BM44")
01831         decode_chunk(iff.get_bytestream());
01832       iff.close_chunk();
01833     }
01834   iff.close_chunk();
01835   close_codec();
01836 }
01837 
01839 // NEW FILTERS
01841 
01842 void
01843 IW44Image::Transform::filter_begin(int w, int h)
01844 {
01845   if (MMXControl::mmxflag < 0)  
01846     MMXControl::enable_mmx();
01847 }
01848 
01849 
01850 void
01851 IW44Image::Transform::filter_end(void)
01852 {
01853 #ifdef MMX
01854   if (MMXControl::mmxflag > 0)
01855     MMXemms;
01856 #endif
01857 }
01858 
01859 
01861 // WAVELET TRANSFORM 
01863 
01864 
01865 //----------------------------------------------------
01866 // Function for applying bidimensional IW44 between 
01867 // scale intervals begin(inclusive) and end(exclusive)
01868 
01869 void
01870 IW44Image::Transform::Decode::backward(short *p, int w, int h, int rowsize, int begin, int end)
01871 { 
01872   // PREPARATION
01873   filter_begin(w,h);
01874   // LOOP ON SCALES
01875   for (int scale=begin>>1; scale>=end; scale>>=1)
01876     {
01877 #ifdef IWTRANSFORM_TIMER
01878       int tv,th;
01879       th = tv = GOS::ticks();
01880 #endif
01881       filter_bv(p, w, h, rowsize, scale);
01882 #ifdef IWTRANSFORM_TIMER
01883       th = GOS::ticks();
01884       tv = th - tv;
01885 #endif
01886       filter_bh(p, w, h, rowsize, scale);
01887 #ifdef IWTRANSFORM_TIMER
01888       th = GOS::ticks()-th;
01889       DjVuPrintErrorUTF8("back%d\tv=%dms h=%dms\n", scale,tv,th);
01890 #endif
01891     }
01892   // TERMINATE
01893   filter_end();
01894 }
01895   
01896 
01897 
01898 
01900 // COLOR TRANSFORM 
01902 
01903 /* Converts YCbCr to RGB. */
01904 void 
01905 IW44Image::Transform::Decode::YCbCr_to_RGB(GPixel *p, int w, int h, int rowsize)
01906 {
01907   for (int i=0; i<h; i++,p+=rowsize)
01908     {
01909       GPixel *q = p;
01910       for (int j=0; j<w; j++,q++)
01911         {
01912           signed char y = ((signed char*)q)[0];
01913           signed char b = ((signed char*)q)[1];
01914           signed char r = ((signed char*)q)[2];
01915           // This is the Pigeon transform
01916           int t1 = b >> 2 ; 
01917           int t2 = r + (r >> 1);
01918           int t3 = y + 128 - t1;
01919           int tr = y + 128 + t2;
01920           int tg = t3 - (t2 >> 1);
01921           int tb = t3 + (b << 1);
01922           q->r = max(0,min(255,tr));
01923           q->g = max(0,min(255,tg));
01924           q->b = max(0,min(255,tb));
01925         }
01926     }
01927 }
01928 
01929 
01930 #ifdef HAVE_NAMESPACES
01931 }
01932 # ifndef NOT_USING_DJVU_NAMESPACE
01933 using namespace DJVU;
01934 # endif
01935 #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