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

kviewshell

IW44EncodeCodec.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: IW44EncodeCodec.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 // From: Leon Bottou, 1/31/2002
00066 // Lizardtech has split this file into a decoder and an encoder.
00067 // Only superficial changes.  The meat is mine.
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 // WAVELET DECOMPOSITION CONSTANTS
00112 
00113 // Parameters for IW44 wavelet.
00114 // - iw_norm: norm of all wavelets (for db estimation)
00115 // - iw_shift: scale applied before decomposition
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   // Code first bucket and number of buckets in each band
00134   { 0, 1 }, // -- band zero contains all lores info
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   // CODER
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   // CODER
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 // DJVU_CLASS
00241 {
00242 public:
00243   Encode(const int w, const int h) : Map(w,h) {}
00244   // creation (from image)
00245   void create(const signed char *img8, int imgrowsize, 
00246               const signed char *msk8=0, int mskrowsize=0);
00247   // slash resolution
00248   void slashres(int res);
00249 };
00250 
00251 class IW44Image::Codec::Encode : public IW44Image::Codec
00252 {
00253 public:
00254   Encode(IW44Image::Map &map);
00255   // Coding
00256   virtual int code_slice(ZPCodec &zp);
00257   float estimate_decibel(float frac);
00258   // Data
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  // WAVELET TRANSFORM
00277   static void forward(short *p, int w, int h, int rowsize, int begin, int end);
00278   
00279   // COLOR TRANSFORM
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 // MMX IMPLEMENTATION HELPERS
00295 
00296 
00297 // Note:
00298 // MMX implementation for vertical transforms only.
00299 // Speedup is basically related to faster memory transfer
00300 // The IW44 transform is not CPU bound, it is memory bound.
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);  // MM0=[ b3, b2, b1, b0 ]
00323       MMXar( movq,       q+s,mm2);  // MM2=[ c3, c2, c1, c0 ]
00324       MMXrr( movq,       mm0,mm1);  
00325       MMXrr( punpcklwd,  mm2,mm0);  // MM0=[ c1, b1, c0, b0 ]
00326       MMXrr( punpckhwd,  mm2,mm1);  // MM1=[ c3, b3, c2, b2 ]
00327       MMXar( pmaddwd,    w9,mm0);   // MM0=[ (c1+b1)*9, (c0+b0)*9 ]
00328       MMXar( pmaddwd,    w9,mm1);   // MM1=[ (c3+b3)*9, (c2+b2)*9 ]
00329       MMXar( movq,       q-s3,mm2);
00330       MMXar( movq,       q+s3,mm4);
00331       MMXrr( movq,       mm2,mm3);
00332       MMXrr( punpcklwd,  mm4,mm2);  // MM2=[ d1, a1, d0, a0 ]
00333       MMXrr( punpckhwd,  mm4,mm3);  // MM3=[ d3, a3, d2, a2 ]
00334       MMXar( pmaddwd,    w1,mm2);   // MM2=[ (a1+d1)*1, (a0+d0)*1 ]
00335       MMXar( pmaddwd,    w1,mm3);   // MM3=[ (a3+d3)*1, (a2+d2)*1 ]
00336       MMXar( paddd,      d8,mm0);
00337       MMXar( paddd,      d8,mm1);
00338       MMXrr( psubd,      mm2,mm0);  // MM0=[ (c1+b1)*9-a1-d1+8, ...
00339       MMXrr( psubd,      mm3,mm1);  // MM1=[ (c3+b3)*9-a3-d3+8, ...
00340       MMXir( psrad,      4,mm0);
00341       MMXar( movq,       q,mm7);    // MM7=[ p3,p2,p1,p0 ]
00342       MMXir( psrad,      4,mm1);
00343       MMXrr( packssdw,   mm1,mm0);  // MM0=[ x3,x2,x1,x0 ]
00344       MMXrr( psubw,      mm0,mm7);  // MM7=[ p3-x3, p2-x2, ... ]
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);  // MM0=[ b3, b2, b1, b0 ]
00366       MMXar( movq,       q+s,mm2);  // MM2=[ c3, c2, c1, c0 ]
00367       MMXrr( movq,       mm0,mm1);  
00368       MMXrr( punpcklwd,  mm2,mm0);  // MM0=[ c1, b1, c0, b0 ]
00369       MMXrr( punpckhwd,  mm2,mm1);  // MM1=[ c3, b3, c2, b2 ]
00370       MMXar( pmaddwd,    w9,mm0);   // MM0=[ (c1+b1)*9, (c0+b0)*9 ]
00371       MMXar( pmaddwd,    w9,mm1);   // MM1=[ (c3+b3)*9, (c2+b2)*9 ]
00372       MMXar( movq,       q-s3,mm2);
00373       MMXar( movq,       q+s3,mm4);
00374       MMXrr( movq,       mm2,mm3);
00375       MMXrr( punpcklwd,  mm4,mm2);  // MM2=[ d1, a1, d0, a0 ]
00376       MMXrr( punpckhwd,  mm4,mm3);  // MM3=[ d3, a3, d2, a2 ]
00377       MMXar( pmaddwd,    w1,mm2);   // MM2=[ (a1+d1)*1, (a0+d0)*1 ]
00378       MMXar( pmaddwd,    w1,mm3);   // MM3=[ (a3+d3)*1, (a2+d2)*1 ]
00379       MMXar( paddd,      d16,mm0);
00380       MMXar( paddd,      d16,mm1);
00381       MMXrr( psubd,      mm2,mm0);  // MM0=[ (c1+b1)*9-a1-d1+8, ...
00382       MMXrr( psubd,      mm3,mm1);  // MM1=[ (c3+b3)*9-a3-d3+8, ...
00383       MMXir( psrad,      5,mm0);
00384       MMXar( movq,       q,mm7);    // MM7=[ p3,p2,p1,p0 ]
00385       MMXir( psrad,      5,mm1);
00386       MMXrr( packssdw,   mm1,mm0);  // MM0=[ x3,x2,x1,x0 ]
00387       MMXrr( paddw,      mm0,mm7);  // MM7=[ p3+x3, p2+x2, ... ]
00388       MMXra( movq,       mm7,q);
00389 #if defined(_MSC_VER) && defined(_DEBUG)
00390       MMXemms;
00391 #endif
00392       q += 4;
00393     }
00394 }
00395 
00396 #endif /* MMX */
00397 
00399 // NEW FILTERS
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       // 1-Delta
00414       {
00415         short *q = p;
00416         short *e = q+w;
00417         if (y>=3 && y+3<h)
00418           {
00419             // Generic case
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             // Special cases
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       // 2-Update
00446       {
00447         short *q = p-s3;
00448         short *e = q+w;
00449         if (y>=6 && y<h)
00450           {
00451             // Generic case
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             // Special cases
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           // Special case: x=1
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           // Generic case
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           // Special case: w-3 <= x < w
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           // Special case  w <= x < w+3
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 // WAVELET TRANSFORM 
00585 
00586 
00587 //----------------------------------------------------
00588 // Function for applying bidimensional IW44 between 
00589 // scale intervals begin(inclusive) and end(exclusive)
00590 
00591 void
00592 IW44Image::Transform::Encode::forward(short *p, int w, int h, int rowsize, int begin, int end)
00593 { 
00594 
00595   // PREPARATION
00596   filter_begin(w,h);
00597   // LOOP ON SCALES
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   // TERMINATE
00616   filter_end();
00617 }
00618 
00620 // COLOR TRANSFORM 
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 /* Extracts Y */
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 /* Extracts Cb */
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 /* Extracts Cr */
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 // MASKING DECOMPOSITION
00715 
00716 //----------------------------------------------------
00717 // Function for applying bidimensional IW44 between 
00718 // scale intervals begin(inclusive) and end(exclusive)
00719 // with a MASK bitmap
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   // count masked bits
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   // copy image
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   // iterate over resolutions
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       // iterate over block
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             // look around when square goes beyond border
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             // compute gray level
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             // process result
00788             if (npix == 0)
00789               {
00790                 // continue to next resolution
00791                 again = 1;
00792                 cp[j] = 0;
00793               }
00794             else
00795               {
00796                 gray = gray / npix;
00797                 // check whether initial image require fix
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                 // store average for next iteration
00811                 cp[j] = npix>>2;
00812                 q[j] = gray;
00813               }
00814           }
00815       // double resolution
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   // Allocate buffers
00831   short *sdata;
00832   GPBuffer<short> gsdata(sdata,w*h);
00833   signed char *smask;
00834   GPBuffer<signed char> gsmask(smask,w*h);
00835   // Copy mask
00836   m = smask;
00837   for (i=0; i<h; i+=1, m+=w, mask8+=mskrowsize)
00838     memcpy((void*)m, (void*)mask8, w);
00839   // Loop over scale
00840   for (int scale=begin; scale<end; scale<<=1)
00841     {
00842       // Copy data into sdata buffer
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       // Decompose
00853       IW44Image::Transform::Encode::forward(sdata, w, h, w, scale, scale+scale);
00854       // Cancel masked coefficients
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       // Reconstruct
00874       IW44Image::Transform::Decode::backward(sdata, w, h, w, scale+scale, scale);
00875       // Correct visible pixels
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       // Decompose again (no need to iterate actually!)
00889       IW44Image::Transform::Encode::forward(sdata, w, h, w, scale, scale+scale);
00890       // Copy coefficients from sdata buffer
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       // Compute new mask for next scale
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   // Free buffers
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   // Progress
00926   DJVU_PROGRESS_TASK(transf,"create iw44 map",3);
00927   // Allocate decomposition buffer
00928   short *data16;
00929   GPBuffer<short> gdata16(data16,bw*bh);
00930   // Copy pixels
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   // Handle bitmask
00945   if (msk8)
00946     {
00947       // Interpolate pixels below mask
00948       DJVU_PROGRESS_RUN(transf, 1);
00949       interpolate_mask(data16, iw, ih, bw, msk8, mskrowsize);
00950       // Multiscale iterative masked decomposition
00951       DJVU_PROGRESS_RUN(transf, 3);
00952       forward_mask(data16, iw, ih, bw, 1, 32, msk8, mskrowsize);
00953     }
00954   else
00955     {
00956       // Perform traditional decomposition
00957       DJVU_PROGRESS_RUN(transf, 3);
00958       IW44Image::Transform::Encode::forward(data16, iw, ih, bw, 1, 32);
00959     }
00960   // Copy coefficient into blocks
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           // transfer coefficients at (p+j) into aligned block
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           // transfer into IW44Image::Block (apply zigzag and scaling)
00975           block->read_liftblock(liftblock, this);
00976           block++;
00977         }
00978       // next row of blocks
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 // encode_prepare
00999 // -- compute the states prior to encoding the buckets
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   // compute state of all coefficients in all buckets
01005   if (band) 
01006     {
01007       // Band other than zero
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               // cstate[i] is not used and does not need initialization
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       // Band zero ( fbucket==0 implies band==zero and nbucket==1 )
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 // encode_buckets
01075 // -- code a sequence of buckets in a given block
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   // compute state of all coefficients in all buckets
01082   int bbstate = encode_prepare(band, fbucket, nbucket, blk, eblk);
01083 
01084   // code root bit
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   // code bucket bits
01098   if (bbstate & NEW)
01099     for (int buckno=0; buckno<nbucket; buckno++)
01100       {
01101         // Code bucket bit
01102         if (bucketstate[buckno] & UNK)
01103           {
01104             // Context
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             // Code
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   // code new active coefficient (with their sign)
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             // iterate within bucket
01157             for (i=0; i<16; i++)
01158               {
01159                 if (cstate[i] & UNK)
01160                   {
01161                     // Prepare context
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                     // Code
01174                     zp.encoder( (cstate[i]&NEW) ? 1 : 0, ctxStart[ctx] );
01175                     if (cstate[i] & NEW)
01176                       {
01177                         // Code sign
01178                         zp.IWencoder( (pcoeff[i]<0) ? 1 : 0 );
01179                         // Set encoder state
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   // code mantissa bits
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                   // get coefficient
01213                   int coeff = pcoeff[i];
01214                   int ecoeff = epcoeff[i];
01215                   if (coeff < 0)
01216                     coeff = -coeff;
01217                   // get band zero thresholds
01218                   if (band == 0)
01219                     thres = quant_lo[i];
01220                   // compute mantissa bit
01221                   int pix = 0;
01222                   if (coeff >= ecoeff)
01223                     pix = 1;
01224                   // encode second or lesser mantissa bit
01225                   if (ecoeff <= 3*thres)
01226                     zp.encoder(pix, ctxMant);                      
01227                   else
01228                       zp.IWencoder(!!pix);
01229                   // adjust epcoeff
01230                   epcoeff[i] = ecoeff - (pix ? 0 : thres) + (thres>>1);
01231                 }
01232           }
01233     }
01234 }
01235 
01236 // IW44Image::Codec::estimate_decibel
01237 // -- estimate encoding error (after code_slice) in decibels.
01238 float
01239 IW44Image::Codec::Encode::estimate_decibel(float frac)
01240 {
01241   int i,j;
01242   const float *q;
01243   // Fill norm arrays
01244   float norm_lo[16];
01245   float norm_hi[10];
01246   // -- lo coefficients
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   // -- hi coefficients
01260   norm_hi[0] = 0;
01261   for (j=1; j<10; j++)
01262     norm_hi[j] = *q++;
01263   // Initialize mse array
01264   float *xmse;
01265   GPBuffer<float> gxmse(xmse,map.nb);
01266   // Compute mse in each block
01267   for (int blockno=0; blockno<map.nb; blockno++)
01268     {
01269       float mse = 0;
01270       // Iterate over bands
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   // Compute partition point
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   // Partition array
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   // Compute average mse
01337   float mse = 0;
01338   for (i=p; i<map.nb; i++)
01339     mse = mse + xmse[i];
01340   mse = mse / (map.nb - p);
01341   // Return
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 // IW44IMAGE ENCODING ROUTINES
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   // Free
01418   close_codec();
01419   delete ymap;
01420   ymap = 0;
01421   // Init
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   // Prepare gray level conversion table
01429   signed char  bconv[256];
01430   for (i=0; i<256; i++)
01431     bconv[i] = max(0,min(255,i*255/g)) - 128;
01432   // Perform decomposition
01433   // Prepare mask information
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   // Prepare a buffer of signed bytes
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   // Create map
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   // Check
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   // Open codec
01473   if (!ycodec_enc)
01474   {
01475     cslice = cserial = cbytes = 0;
01476     ycodec_enc = new Codec::Encode(*ymap);
01477   }
01478   // Adjust cbytes
01479   cbytes += sizeof(struct IW44Image::PrimaryHeader);
01480   if (cserial == 0)
01481     cbytes += sizeof(struct IW44Image::SecondaryHeader) + sizeof(struct IW44Image::TertiaryHeader);
01482   // Prepare zcoded slices
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   // Write primary header
01509   struct IW44Image::PrimaryHeader primary;
01510   primary.serial = cserial;
01511   primary.slices = nslices;
01512   primary.encode(gbs);
01513   // Write auxilliary headers
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   // Write slices
01529   mbs.seek(0);
01530   gbs->copy(mbs);
01531   // Return
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   /* Free */
01580   close_codec();
01581   delete ymap;
01582   delete cbmap;
01583   delete crmap;
01584   ymap = cbmap = crmap = 0;
01585   /* Create */
01586   int w = pm.columns();
01587   int h = pm.rows();
01588   signed char *buffer;
01589   GPBuffer<signed char> gbuffer(buffer,w*h);
01590   // Create maps
01591   Map::Encode *eymap = new Map::Encode(w,h);
01592   ymap = eymap;
01593   // Handle CRCB mode
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   // Prepare mask information
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   // Fill buffer with luminance information
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       // Stupid inversion for gray images
01617       signed char *e = buffer + w*h;
01618       for (signed char *b=buffer; b<e; b++)
01619         *b = 255 - *b;
01620     }
01621   // Create YMAP
01622   eymap->create(buffer, w, msk8, mskrowsize);
01623   // Create chrominance maps
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       // Process CB information
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       // Process CR information
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       // Perform chrominance reduction (CRCBhalf)
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   // Check
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   // Open
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   // Adjust cbytes
01697   cbytes += sizeof(struct IW44Image::PrimaryHeader);
01698   if (cserial == 0)
01699     cbytes += sizeof(struct IW44Image::SecondaryHeader) + sizeof(struct IW44Image::TertiaryHeader);
01700   // Prepare zcodec slices
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   // Write primary header
01732   struct IW44Image::PrimaryHeader primary;
01733   primary.serial = cserial;
01734   primary.slices = nslices;
01735   primary.encode(gbs);
01736   // Write secondary header
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   // Write slices
01755   mbs.seek(0);
01756   gbs->copy(mbs);
01757   // Return
01758   cbytes  += mbs.tell();
01759   cslice  += nslices;
01760   cserial += 1;
01761   return flag;
01762 }
01763 
01764 // code_slice
01765 // -- read/write a slice of datafile
01766 
01767 int
01768 IW44Image::Codec::Encode::code_slice(ZPCodec &zp)
01769 {
01770   // Check that code_slice can still run
01771   if (curbit < 0)
01772     return 0;
01773   // Perform coding
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 

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