Blame libdjvu/IW44EncodeCodec.cpp

Packit df99a1
//C-  -*- C++ -*-
Packit df99a1
//C- -------------------------------------------------------------------
Packit df99a1
//C- DjVuLibre-3.5
Packit df99a1
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
Packit df99a1
//C- Copyright (c) 2001  AT&T
Packit df99a1
//C-
Packit df99a1
//C- This software is subject to, and may be distributed under, the
Packit df99a1
//C- GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- or (at your option) any later version. The license should have
Packit df99a1
//C- accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C-
Packit df99a1
//C- This program is distributed in the hope that it will be useful,
Packit df99a1
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit df99a1
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit df99a1
//C- GNU General Public License for more details.
Packit df99a1
//C- 
Packit df99a1
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
Packit df99a1
//C- Lizardtech Software.  Lizardtech Software has authorized us to
Packit df99a1
//C- replace the original DjVu(r) Reference Library notice by the following
Packit df99a1
//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
Packit df99a1
//C-
Packit df99a1
//C-  ------------------------------------------------------------------
Packit df99a1
//C- | DjVu (r) Reference Library (v. 3.5)
Packit df99a1
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
Packit df99a1
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
Packit df99a1
//C- | 6,058,214 and patents pending.
Packit df99a1
//C- |
Packit df99a1
//C- | This software is subject to, and may be distributed under, the
Packit df99a1
//C- | GNU General Public License, either Version 2 of the license,
Packit df99a1
//C- | or (at your option) any later version. The license should have
Packit df99a1
//C- | accompanied the software or you may obtain a copy of the license
Packit df99a1
//C- | from the Free Software Foundation at http://www.fsf.org .
Packit df99a1
//C- |
Packit df99a1
//C- | The computer code originally released by LizardTech under this
Packit df99a1
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
Packit df99a1
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
Packit df99a1
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
Packit df99a1
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
Packit df99a1
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
Packit df99a1
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
Packit df99a1
//C- | General Public License.   This grant only confers the right to 
Packit df99a1
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
Packit df99a1
//C- | the extent such infringement is reasonably necessary to enable 
Packit df99a1
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
Packit df99a1
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
Packit df99a1
//C- | any greater extent that may be necessary to utilize further 
Packit df99a1
//C- | modifications or combinations.
Packit df99a1
//C- |
Packit df99a1
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
Packit df99a1
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
Packit df99a1
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
Packit df99a1
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Packit df99a1
//C- +------------------------------------------------------------------
Packit df99a1
Packit df99a1
#ifdef HAVE_CONFIG_H
Packit df99a1
# include "config.h"
Packit df99a1
#endif
Packit df99a1
#if NEED_GNUG_PRAGMAS
Packit df99a1
# pragma implementation
Packit df99a1
#endif
Packit df99a1
Packit df99a1
// - Author: Leon Bottou, 08/1998
Packit df99a1
// From: Leon Bottou, 1/31/2002
Packit df99a1
// Lizardtech has split this file into a decoder and an encoder.
Packit df99a1
// Only superficial changes.  The meat is mine.
Packit df99a1
Packit df99a1
#define IW44IMAGE_IMPLIMENTATION /* */
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
#include "IW44Image.h"
Packit df99a1
#include "ZPCodec.h"
Packit df99a1
#include "GBitmap.h"
Packit df99a1
#include "GPixmap.h"
Packit df99a1
#include "IFFByteStream.h"
Packit df99a1
#include "GRect.h"
Packit df99a1
Packit df99a1
#include <stddef.h>
Packit df99a1
#include <stdlib.h>
Packit df99a1
#include <string.h>
Packit df99a1
#include <math.h>
Packit df99a1
#include "MMX.h"
Packit df99a1
#undef IWTRANSFORM_TIMER
Packit df99a1
#ifdef IWTRANSFORM_TIMER
Packit df99a1
#include "GOS.h"
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#include <assert.h>
Packit df99a1
#include <string.h>
Packit df99a1
#include <math.h>
Packit df99a1
Packit df99a1
#ifndef NEED_DECODER_ONLY
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
namespace DJVU {
Packit df99a1
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
Packit df99a1
}
Packit df99a1
#endif
Packit df99a1
#endif
Packit df99a1
Packit df99a1
#define IWALLOCSIZE    4080
Packit df99a1
#define IWCODEC_MAJOR     1
Packit df99a1
#define IWCODEC_MINOR     2
Packit df99a1
#define DECIBEL_PRUNE   5.0
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// WAVELET DECOMPOSITION CONSTANTS
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
// Parameters for IW44 wavelet.
Packit df99a1
// - iw_norm: norm of all wavelets (for db estimation)
Packit df99a1
// - iw_shift: scale applied before decomposition
Packit df99a1
Packit df99a1
Packit df99a1
static const float iw_norm[16] = {
Packit df99a1
  2.627989e+03F,
Packit df99a1
  1.832893e+02F, 1.832959e+02F, 5.114690e+01F,
Packit df99a1
  4.583344e+01F, 4.583462e+01F, 1.279225e+01F,
Packit df99a1
  1.149671e+01F, 1.149712e+01F, 3.218888e+00F,
Packit df99a1
  2.999281e+00F, 2.999476e+00F, 8.733161e-01F,
Packit df99a1
  1.074451e+00F, 1.074511e+00F, 4.289318e-01F
Packit df99a1
};
Packit df99a1
Packit df99a1
static const int iw_shift  = 6;
Packit df99a1
static const int iw_round  = (1<<(iw_shift-1));
Packit df99a1
Packit df99a1
static const struct { int start; int size; }  
Packit df99a1
bandbuckets[] = 
Packit df99a1
{
Packit df99a1
  // Code first bucket and number of buckets in each band
Packit df99a1
  { 0, 1 }, // -- band zero contains all lores info
Packit df99a1
  { 1, 1 }, { 2, 1 }, { 3, 1 }, 
Packit df99a1
  { 4, 4 }, { 8, 4 }, { 12,4 }, 
Packit df99a1
  { 16,16 }, { 32,16 }, { 48,16 }, 
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
/** IW44 encoded gray-level image.  This class provided functions for managing
Packit df99a1
    a gray level image represented as a collection of IW44 wavelet
Packit df99a1
    coefficients.  The coefficients are stored in a memory efficient data
Packit df99a1
    structure.  Member function \Ref{get_bitmap} renders an arbitrary segment
Packit df99a1
    of the image into a \Ref{GBitmap}.  Member functions \Ref{decode_iff} and
Packit df99a1
    \Ref{encode_iff} read and write DjVu IW44 files (see \Ref{IW44Image.h}).
Packit df99a1
    Both the copy constructor and the copy operator are declared as private
Packit df99a1
    members. It is therefore not possible to make multiple copies of instances
Packit df99a1
    of this class. */
Packit df99a1
Packit df99a1
class IWBitmap::Encode : public IWBitmap
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  /// Destructor
Packit df99a1
  virtual ~Encode(void);
Packit df99a1
  /** Null constructor.  Constructs an empty IWBitmap object. This object does
Packit df99a1
      not contain anything meaningful. You must call function \Ref{init},
Packit df99a1
      \Ref{decode_iff} or \Ref{decode_chunk} to populate the wavelet
Packit df99a1
      coefficient data structure. */
Packit df99a1
  Encode(void);
Packit df99a1
  /** Initializes an IWBitmap with image #bm#.  This constructor
Packit df99a1
      performs the wavelet decomposition of image #bm# and records the
Packit df99a1
      corresponding wavelet coefficient.  Argument #mask# is an optional
Packit df99a1
      bilevel image specifying the masked pixels (see \Ref{IW44Image.h}). */
Packit df99a1
  void init(const GBitmap &bm, const GP<GBitmap> mask=0);
Packit df99a1
  // CODER
Packit df99a1
  /** Encodes one data chunk into ByteStream #bs#.  Parameter #parms# controls
Packit df99a1
      how much data is generated.  The chunk data is written to ByteStream
Packit df99a1
      #bs# with no IFF header.  Successive calls to #encode_chunk# encode
Packit df99a1
      successive chunks.  You must call #close_codec# after encoding the last
Packit df99a1
      chunk of a file. */
Packit df99a1
  virtual int  encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parms);
Packit df99a1
  /** Writes a gray level image into DjVu IW44 file.  This function creates a
Packit df99a1
      composite chunk (identifier #FORM:BM44#) composed of #nchunks# chunks
Packit df99a1
      (identifier #BM44#).  Data for each chunk is generated with
Packit df99a1
      #encode_chunk# using the corresponding parameters in array #parms#. */
Packit df99a1
  virtual void encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms);
Packit df99a1
  /** Resets the encoder/decoder state.  The first call to #decode_chunk# or
Packit df99a1
      #encode_chunk# initializes the coder for encoding or decoding.  Function
Packit df99a1
      #close_codec# must be called after processing the last chunk in order to
Packit df99a1
      reset the coder and release the associated memory. */
Packit df99a1
  virtual void close_codec(void);
Packit df99a1
protected:
Packit df99a1
  Codec::Encode *ycodec_enc;
Packit df99a1
};
Packit df99a1
Packit df99a1
/** IW44 encoded color image. This class provided functions for managing a
Packit df99a1
    color image represented as a collection of IW44 wavelet coefficients.  The
Packit df99a1
    coefficients are stored in a memory efficient data structure.  Member
Packit df99a1
    function \Ref{get_pixmap} renders an arbitrary segment of the image into a
Packit df99a1
    \Ref{GPixmap}.  Member functions \Ref{decode_iff} and \Ref{encode_iff}
Packit df99a1
    read and write DjVu IW44 files (see \Ref{IW44Image.h}).  Both the copy
Packit df99a1
    constructor and the copy operator are declared as private members. It is
Packit df99a1
    therefore not possible to make multiple copies of instances of this
Packit df99a1
    class. */
Packit df99a1
Packit df99a1
class IWPixmap::Encode : public IWPixmap
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  enum CRCBMode { 
Packit df99a1
    CRCBnone=IW44Image::CRCBnone, 
Packit df99a1
    CRCBhalf=IW44Image::CRCBhalf, 
Packit df99a1
    CRCBnormal=IW44Image::CRCBnormal, 
Packit df99a1
    CRCBfull=IW44Image::CRCBfull };
Packit df99a1
  /// Destructor
Packit df99a1
  virtual ~Encode(void);
Packit df99a1
  /** Null constructor.  Constructs an empty IWPixmap object. This object does
Packit df99a1
      not contain anything meaningful. You must call function \Ref{init},
Packit df99a1
      \Ref{decode_iff} or \Ref{decode_chunk} to populate the wavelet
Packit df99a1
      coefficient data structure. */
Packit df99a1
  Encode(void);
Packit df99a1
  /** Initializes an IWPixmap with color image #bm#.  This constructor
Packit df99a1
      performs the wavelet decomposition of image #bm# and records the
Packit df99a1
      corresponding wavelet coefficient.  Argument #mask# is an optional
Packit df99a1
      bilevel image specifying the masked pixels (see \Ref{IW44Image.h}).
Packit df99a1
      Argument #crcbmode# specifies how the chrominance information should be
Packit df99a1
      encoded (see \Ref{CRCBMode}). */
Packit df99a1
  void init(const GPixmap &bm, const GP<GBitmap> mask=0, CRCBMode crcbmode=CRCBnormal);
Packit df99a1
  // CODER
Packit df99a1
  /** Encodes one data chunk into ByteStream #bs#.  Parameter #parms# controls
Packit df99a1
      how much data is generated.  The chunk data is written to ByteStream
Packit df99a1
      #bs# with no IFF header.  Successive calls to #encode_chunk# encode
Packit df99a1
      successive chunks.  You must call #close_codec# after encoding the last
Packit df99a1
      chunk of a file. */
Packit df99a1
  virtual int  encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parms);
Packit df99a1
  /** Writes a color image into a DjVu IW44 file.  This function creates a
Packit df99a1
      composite chunk (identifier #FORM:PM44#) composed of #nchunks# chunks
Packit df99a1
      (identifier #PM44#).  Data for each chunk is generated with
Packit df99a1
      #encode_chunk# using the corresponding parameters in array #parms#. */
Packit df99a1
  virtual void encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms);
Packit df99a1
  /** Resets the encoder/decoder state.  The first call to #decode_chunk# or
Packit df99a1
      #encode_chunk# initializes the coder for encoding or decoding.  Function
Packit df99a1
      #close_codec# must be called after processing the last chunk in order to
Packit df99a1
      reset the coder and release the associated memory. */
Packit df99a1
  virtual void close_codec(void);
Packit df99a1
protected:
Packit df99a1
  Codec::Encode *ycodec_enc, *cbcodec_enc, *crcodec_enc;
Packit df99a1
};
Packit df99a1
Packit df99a1
class IW44Image::Map::Encode : public IW44Image::Map // DJVU_CLASS
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  Encode(const int w, const int h) : Map(w,h) {}
Packit df99a1
  // creation (from image)
Packit df99a1
  void create(const signed char *img8, int imgrowsize, 
Packit df99a1
              const signed char *msk8=0, int mskrowsize=0);
Packit df99a1
  // slash resolution
Packit df99a1
  void slashres(int res);
Packit df99a1
};
Packit df99a1
Packit df99a1
class IW44Image::Codec::Encode : public IW44Image::Codec
Packit df99a1
{
Packit df99a1
public:
Packit df99a1
  Encode(IW44Image::Map &map);
Packit df99a1
  // Coding
Packit df99a1
  virtual int code_slice(ZPCodec &zp;;
Packit df99a1
  float estimate_decibel(float frac);
Packit df99a1
  // Data
Packit df99a1
  void encode_buckets(ZPCodec &zp, int bit, int band,
Packit df99a1
    IW44Image::Block &blk, IW44Image::Block &eblk, int fbucket, int nbucket);
Packit df99a1
  int encode_prepare(int band, int fbucket, int nbucket, IW44Image::Block &blk, IW44Image::Block &eblk);
Packit df99a1
  IW44Image::Map emap;
Packit df99a1
};
Packit df99a1
Packit df99a1
IW44Image::Codec::Encode::Encode(IW44Image::Map &map)
Packit df99a1
: Codec(map), emap(map.iw,map.ih) {}
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
/** IW44Image::Transform::Encode
Packit df99a1
*/
Packit df99a1
Packit df99a1
class IW44Image::Transform::Encode : IW44Image::Transform
Packit df99a1
{
Packit df99a1
 public:
Packit df99a1
 // WAVELET TRANSFORM
Packit df99a1
  /** Forward transform. */
Packit df99a1
  static void forward(short *p, int w, int h, int rowsize, int begin, int end);
Packit df99a1
  
Packit df99a1
  // COLOR TRANSFORM
Packit df99a1
  /** Extracts Y */
Packit df99a1
  static void RGB_to_Y(const GPixel *p, int w, int h, int rowsize, 
Packit df99a1
                       signed char *out, int outrowsize);
Packit df99a1
  /** Extracts Cb */
Packit df99a1
  static void RGB_to_Cb(const GPixel *p, int w, int h, int rowsize, 
Packit df99a1
                        signed char *out, int outrowsize);
Packit df99a1
  /** Extracts Cr */
Packit df99a1
  static void RGB_to_Cr(const GPixel *p, int w, int h, int rowsize, 
Packit df99a1
                        signed char *out, int outrowsize);
Packit df99a1
};
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// MMX IMPLEMENTATION HELPERS
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
// Note:
Packit df99a1
// MMX implementation for vertical transforms only.
Packit df99a1
// Speedup is basically related to faster memory transfer
Packit df99a1
// The IW44 transform is not CPU bound, it is memory bound.
Packit df99a1
Packit df99a1
#ifdef MMX
Packit df99a1
Packit df99a1
static const short w9[]  = {9,9,9,9};
Packit df99a1
static const short w1[]  = {1,1,1,1};
Packit df99a1
static const int   d8[]  = {8,8};
Packit df99a1
static const int   d16[] = {16,16};
Packit df99a1
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
mmx_fv_1 ( short* &q, short* e, int s, int s3 )
Packit df99a1
{
Packit df99a1
  while (q
Packit df99a1
    {
Packit df99a1
      int a = (int)q[-s] + (int)q[s];
Packit df99a1
      int b = (int)q[-s3] + (int)q[s3];
Packit df99a1
      *q -= (((a<<3)+a-b+8)>>4);
Packit df99a1
      q++;
Packit df99a1
    }
Packit df99a1
  while (q+3
Packit df99a1
    {
Packit df99a1
      MMXar( movq,       q-s,mm0);  // MM0=[ b3, b2, b1, b0 ]
Packit df99a1
      MMXar( movq,       q+s,mm2);  // MM2=[ c3, c2, c1, c0 ]
Packit df99a1
      MMXrr( movq,       mm0,mm1);  
Packit df99a1
      MMXrr( punpcklwd,  mm2,mm0);  // MM0=[ c1, b1, c0, b0 ]
Packit df99a1
      MMXrr( punpckhwd,  mm2,mm1);  // MM1=[ c3, b3, c2, b2 ]
Packit df99a1
      MMXar( pmaddwd,    w9,mm0);   // MM0=[ (c1+b1)*9, (c0+b0)*9 ]
Packit df99a1
      MMXar( pmaddwd,    w9,mm1);   // MM1=[ (c3+b3)*9, (c2+b2)*9 ]
Packit df99a1
      MMXar( movq,       q-s3,mm2);
Packit df99a1
      MMXar( movq,       q+s3,mm4);
Packit df99a1
      MMXrr( movq,       mm2,mm3);
Packit df99a1
      MMXrr( punpcklwd,  mm4,mm2);  // MM2=[ d1, a1, d0, a0 ]
Packit df99a1
      MMXrr( punpckhwd,  mm4,mm3);  // MM3=[ d3, a3, d2, a2 ]
Packit df99a1
      MMXar( pmaddwd,    w1,mm2);   // MM2=[ (a1+d1)*1, (a0+d0)*1 ]
Packit df99a1
      MMXar( pmaddwd,    w1,mm3);   // MM3=[ (a3+d3)*1, (a2+d2)*1 ]
Packit df99a1
      MMXar( paddd,      d8,mm0);
Packit df99a1
      MMXar( paddd,      d8,mm1);
Packit df99a1
      MMXrr( psubd,      mm2,mm0);  // MM0=[ (c1+b1)*9-a1-d1+8, ...
Packit df99a1
      MMXrr( psubd,      mm3,mm1);  // MM1=[ (c3+b3)*9-a3-d3+8, ...
Packit df99a1
      MMXir( psrad,      4,mm0);
Packit df99a1
      MMXar( movq,       q,mm7);    // MM7=[ p3,p2,p1,p0 ]
Packit df99a1
      MMXir( psrad,      4,mm1);
Packit df99a1
      MMXrr( packssdw,   mm1,mm0);  // MM0=[ x3,x2,x1,x0 ]
Packit df99a1
      MMXrr( psubw,      mm0,mm7);  // MM7=[ p3-x3, p2-x2, ... ]
Packit df99a1
      MMXra( movq,       mm7,q);
Packit df99a1
#if defined(_MSC_VER) && defined(_DEBUG)
Packit df99a1
      MMXemms;
Packit df99a1
#endif
Packit df99a1
      q += 4;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
static inline void
Packit df99a1
mmx_fv_2 ( short* &q, short* e, int s, int s3 )
Packit df99a1
{
Packit df99a1
  while (q
Packit df99a1
    {
Packit df99a1
      int a = (int)q[-s] + (int)q[s];
Packit df99a1
      int b = (int)q[-s3] + (int)q[s3];
Packit df99a1
      *q += (((a<<3)+a-b+16)>>5);
Packit df99a1
      q ++;
Packit df99a1
    }
Packit df99a1
  while (q+3
Packit df99a1
    {
Packit df99a1
      MMXar( movq,       q-s,mm0);  // MM0=[ b3, b2, b1, b0 ]
Packit df99a1
      MMXar( movq,       q+s,mm2);  // MM2=[ c3, c2, c1, c0 ]
Packit df99a1
      MMXrr( movq,       mm0,mm1);  
Packit df99a1
      MMXrr( punpcklwd,  mm2,mm0);  // MM0=[ c1, b1, c0, b0 ]
Packit df99a1
      MMXrr( punpckhwd,  mm2,mm1);  // MM1=[ c3, b3, c2, b2 ]
Packit df99a1
      MMXar( pmaddwd,    w9,mm0);   // MM0=[ (c1+b1)*9, (c0+b0)*9 ]
Packit df99a1
      MMXar( pmaddwd,    w9,mm1);   // MM1=[ (c3+b3)*9, (c2+b2)*9 ]
Packit df99a1
      MMXar( movq,       q-s3,mm2);
Packit df99a1
      MMXar( movq,       q+s3,mm4);
Packit df99a1
      MMXrr( movq,       mm2,mm3);
Packit df99a1
      MMXrr( punpcklwd,  mm4,mm2);  // MM2=[ d1, a1, d0, a0 ]
Packit df99a1
      MMXrr( punpckhwd,  mm4,mm3);  // MM3=[ d3, a3, d2, a2 ]
Packit df99a1
      MMXar( pmaddwd,    w1,mm2);   // MM2=[ (a1+d1)*1, (a0+d0)*1 ]
Packit df99a1
      MMXar( pmaddwd,    w1,mm3);   // MM3=[ (a3+d3)*1, (a2+d2)*1 ]
Packit df99a1
      MMXar( paddd,      d16,mm0);
Packit df99a1
      MMXar( paddd,      d16,mm1);
Packit df99a1
      MMXrr( psubd,      mm2,mm0);  // MM0=[ (c1+b1)*9-a1-d1+8, ...
Packit df99a1
      MMXrr( psubd,      mm3,mm1);  // MM1=[ (c3+b3)*9-a3-d3+8, ...
Packit df99a1
      MMXir( psrad,      5,mm0);
Packit df99a1
      MMXar( movq,       q,mm7);    // MM7=[ p3,p2,p1,p0 ]
Packit df99a1
      MMXir( psrad,      5,mm1);
Packit df99a1
      MMXrr( packssdw,   mm1,mm0);  // MM0=[ x3,x2,x1,x0 ]
Packit df99a1
      MMXrr( paddw,      mm0,mm7);  // MM7=[ p3+x3, p2+x2, ... ]
Packit df99a1
      MMXra( movq,       mm7,q);
Packit df99a1
#if defined(_MSC_VER) && defined(_DEBUG)
Packit df99a1
      MMXemms;
Packit df99a1
#endif
Packit df99a1
      q += 4;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
#endif /* MMX */
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// NEW FILTERS
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
static void 
Packit df99a1
filter_fv(short *p, int w, int h, int rowsize, int scale)
Packit df99a1
{
Packit df99a1
  int y = 0;
Packit df99a1
  int s = scale*rowsize;
Packit df99a1
  int s3 = s+s+s;
Packit df99a1
  h = ((h-1)/scale)+1;
Packit df99a1
  y += 1;
Packit df99a1
  p += s;
Packit df99a1
  while (y-3 < h)
Packit df99a1
    {
Packit df99a1
      // 1-Delta
Packit df99a1
      {
Packit df99a1
        short *q = p;
Packit df99a1
        short *e = q+w;
Packit df99a1
        if (y>=3 && y+3
Packit df99a1
          {
Packit df99a1
            // Generic case
Packit df99a1
#ifdef MMX
Packit df99a1
            if (scale==1 && MMXControl::mmxflag>0)
Packit df99a1
              mmx_fv_1(q, e, s, s3);
Packit df99a1
#endif
Packit df99a1
            while (q
Packit df99a1
              {
Packit df99a1
                int a = (int)q[-s] + (int)q[s];
Packit df99a1
                int b = (int)q[-s3] + (int)q[s3];
Packit df99a1
                *q -= (((a<<3)+a-b+8)>>4);
Packit df99a1
                q += scale;
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
        else if (y
Packit df99a1
          {
Packit df99a1
            // Special cases
Packit df99a1
            short *q1 = (y+1
Packit df99a1
            while (q
Packit df99a1
              {
Packit df99a1
                int a = (int)q[-s] + (int)(*q1);
Packit df99a1
                *q -= ((a+1)>>1);
Packit df99a1
                q += scale;
Packit df99a1
                q1 += scale;
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
      }
Packit df99a1
      // 2-Update
Packit df99a1
      {
Packit df99a1
        short *q = p-s3;
Packit df99a1
        short *e = q+w;
Packit df99a1
        if (y>=6 && y
Packit df99a1
          {
Packit df99a1
            // Generic case
Packit df99a1
#ifdef MMX
Packit df99a1
            if (scale==1 && MMXControl::mmxflag>0)
Packit df99a1
              mmx_fv_2(q, e, s, s3);
Packit df99a1
#endif
Packit df99a1
            while (q
Packit df99a1
              {
Packit df99a1
                int a = (int)q[-s] + (int)q[s];
Packit df99a1
                int b = (int)q[-s3] + (int)q[s3];
Packit df99a1
                *q += (((a<<3)+a-b+16)>>5);
Packit df99a1
                q += scale;
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
        else if (y>=3)
Packit df99a1
          {
Packit df99a1
            // Special cases
Packit df99a1
            short *q1 = (y-2
Packit df99a1
            short *q3 = (y
Packit df99a1
            if (y>=6)
Packit df99a1
              {
Packit df99a1
                while (q
Packit df99a1
                  {
Packit df99a1
                    int a = (int)q[-s] + (q1 ? (int)(*q1) : 0);
Packit df99a1
                    int b = (int)q[-s3] + (q3 ? (int)(*q3) : 0);
Packit df99a1
                    *q += (((a<<3)+a-b+16)>>5);
Packit df99a1
                    q += scale;
Packit df99a1
                    if (q1) q1 += scale;
Packit df99a1
                    if (q3) q3 += scale;
Packit df99a1
                  }
Packit df99a1
              }
Packit df99a1
            else if (y>=4)
Packit df99a1
              {
Packit df99a1
                while (q
Packit df99a1
                  {
Packit df99a1
                    int a = (int)q[-s] + (q1 ? (int)(*q1) : 0);
Packit df99a1
                    int b = (q3 ? (int)(*q3) : 0);
Packit df99a1
                    *q += (((a<<3)+a-b+16)>>5);
Packit df99a1
                    q += scale;
Packit df99a1
                    if (q1) q1 += scale;
Packit df99a1
                    if (q3) q3 += scale;
Packit df99a1
                  }
Packit df99a1
              }
Packit df99a1
            else
Packit df99a1
              {
Packit df99a1
                while (q
Packit df99a1
                  {
Packit df99a1
                    int a = (q1 ? (int)(*q1) : 0);
Packit df99a1
                    int b = (q3 ? (int)(*q3) : 0);
Packit df99a1
                    *q += (((a<<3)+a-b+16)>>5);
Packit df99a1
                    q += scale;
Packit df99a1
                    if (q1) q1 += scale;
Packit df99a1
                    if (q3) q3 += scale;
Packit df99a1
                  }
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
      }
Packit df99a1
      y += 2;
Packit df99a1
      p += s+s;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
static void 
Packit df99a1
filter_fh(short *p, int w, int h, int rowsize, int scale)
Packit df99a1
{
Packit df99a1
  int y = 0;
Packit df99a1
  int s = scale;
Packit df99a1
  int s3 = s+s+s;
Packit df99a1
  rowsize *= scale;
Packit df99a1
  while (y
Packit df99a1
    {
Packit df99a1
      short *q = p+s;
Packit df99a1
      short *e = p+w;
Packit df99a1
      int a0=0, a1=0, a2=0, a3=0;
Packit df99a1
      int b0=0, b1=0, b2=0, b3=0;
Packit df99a1
      if (q < e)
Packit df99a1
        {
Packit df99a1
          // Special case: x=1
Packit df99a1
          a1 = a2 = a3 = q[-s];
Packit df99a1
          if (q+s
Packit df99a1
            a2 = q[s];
Packit df99a1
          if (q+s3
Packit df99a1
            a3 = q[s3];
Packit df99a1
          b3 = q[0] - ((a1+a2+1)>>1);
Packit df99a1
          q[0] = b3;
Packit df99a1
          q += s+s;
Packit df99a1
        }
Packit df99a1
      while (q+s3 < e)
Packit df99a1
        {
Packit df99a1
          // Generic case
Packit df99a1
          a0=a1; 
Packit df99a1
          a1=a2; 
Packit df99a1
          a2=a3;
Packit df99a1
          a3=q[s3];
Packit df99a1
          b0=b1; 
Packit df99a1
          b1=b2; 
Packit df99a1
          b2=b3;
Packit df99a1
          b3 = q[0] - ((((a1+a2)<<3)+(a1+a2)-a0-a3+8) >> 4);
Packit df99a1
          q[0] = b3;
Packit df99a1
          q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+16) >> 5);
Packit df99a1
          q += s+s;
Packit df99a1
        }
Packit df99a1
      while (q < e)
Packit df99a1
        {
Packit df99a1
          // Special case: w-3 <= x < w
Packit df99a1
          a1=a2; 
Packit df99a1
          a2=a3;
Packit df99a1
          b0=b1; 
Packit df99a1
          b1=b2; 
Packit df99a1
          b2=b3;
Packit df99a1
          b3 = q[0] - ((a1+a2+1)>>1);
Packit df99a1
          q[0] = b3;
Packit df99a1
          q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+16) >> 5);
Packit df99a1
          q += s+s;
Packit df99a1
        }
Packit df99a1
      while (q-s3 < e)
Packit df99a1
        {
Packit df99a1
          // Special case  w <= x < w+3
Packit df99a1
          b0=b1; 
Packit df99a1
          b1=b2; 
Packit df99a1
          b2=b3;
Packit df99a1
          b3=0;
Packit df99a1
          if (q-s3 >= p)
Packit df99a1
            q[-s3] = q[-s3] + ((((b1+b2)<<3)+(b1+b2)-b0-b3+16) >> 5);
Packit df99a1
          q += s+s;
Packit df99a1
        }
Packit df99a1
      y += scale;
Packit df99a1
      p += rowsize;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// WAVELET TRANSFORM 
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
//----------------------------------------------------
Packit df99a1
// Function for applying bidimensional IW44 between 
Packit df99a1
// scale intervals begin(inclusive) and end(exclusive)
Packit df99a1
Packit df99a1
void
Packit df99a1
IW44Image::Transform::Encode::forward(short *p, int w, int h, int rowsize, int begin, int end)
Packit df99a1
{ 
Packit df99a1
Packit df99a1
  // PREPARATION
Packit df99a1
  filter_begin(w,h);
Packit df99a1
  // LOOP ON SCALES
Packit df99a1
  for (int scale=begin; scale
Packit df99a1
    {
Packit df99a1
#ifdef IWTRANSFORM_TIMER
Packit df99a1
      int tv,th;
Packit df99a1
      th = tv = GOS::ticks();
Packit df99a1
#endif
Packit df99a1
      filter_fh(p, w, h, rowsize, scale);
Packit df99a1
#ifdef IWTRANSFORM_TIMER
Packit df99a1
      th = GOS::ticks();
Packit df99a1
      tv = th - tv;
Packit df99a1
#endif
Packit df99a1
      filter_fv(p, w, h, rowsize, scale);
Packit df99a1
#ifdef IWTRANSFORM_TIMER
Packit df99a1
      th = GOS::ticks()-th;
Packit df99a1
      DjVuPrintErrorUTF8("forw%d\tv=%dms h=%dms\n", scale,th,tv);
Packit df99a1
#endif
Packit df99a1
    }
Packit df99a1
  // TERMINATE
Packit df99a1
  filter_end();
Packit df99a1
}
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// COLOR TRANSFORM 
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
static const float 
Packit df99a1
rgb_to_ycc[3][3] = 
Packit df99a1
{ { 0.304348F,  0.608696F,  0.086956F },      
Packit df99a1
  { 0.463768F, -0.405797F, -0.057971F },
Packit df99a1
  {-0.173913F, -0.347826F,  0.521739F } };
Packit df99a1
Packit df99a1
Packit df99a1
/* Extracts Y */
Packit df99a1
void 
Packit df99a1
IW44Image::Transform::Encode::RGB_to_Y(const GPixel *p, int w, int h, int rowsize, 
Packit df99a1
                      signed char *out, int outrowsize)
Packit df99a1
{
Packit df99a1
  int rmul[256], gmul[256], bmul[256];
Packit df99a1
  for (int k=0; k<256; k++)
Packit df99a1
    {
Packit df99a1
      rmul[k] = (int)(k*0x10000*rgb_to_ycc[0][0]);
Packit df99a1
      gmul[k] = (int)(k*0x10000*rgb_to_ycc[0][1]);
Packit df99a1
      bmul[k] = (int)(k*0x10000*rgb_to_ycc[0][2]);
Packit df99a1
    }
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      const GPixel *p2 = p;
Packit df99a1
      signed char *out2 = out;
Packit df99a1
      for (int j=0; j
Packit df99a1
        {
Packit df99a1
          int y = rmul[p2->r] + gmul[p2->g] + bmul[p2->b] + 32768;
Packit df99a1
          *out2 = (y>>16) - 128;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
#ifdef min
Packit df99a1
#undef min
Packit df99a1
#endif
Packit df99a1
static inline int min(const int x,const int y) {return (x
Packit df99a1
#ifdef max
Packit df99a1
#undef max
Packit df99a1
#endif
Packit df99a1
static inline int max(const int x,const int y) {return (x>y)?x:y;}
Packit df99a1
Packit df99a1
/* Extracts Cb */
Packit df99a1
void 
Packit df99a1
IW44Image::Transform::Encode::RGB_to_Cb(const GPixel *p, int w, int h, int rowsize, 
Packit df99a1
                       signed char *out, int outrowsize)
Packit df99a1
{
Packit df99a1
  int rmul[256], gmul[256], bmul[256];
Packit df99a1
  for (int k=0; k<256; k++)
Packit df99a1
    {
Packit df99a1
      rmul[k] = (int)(k*0x10000*rgb_to_ycc[2][0]);
Packit df99a1
      gmul[k] = (int)(k*0x10000*rgb_to_ycc[2][1]);
Packit df99a1
      bmul[k] = (int)(k*0x10000*rgb_to_ycc[2][2]);
Packit df99a1
    }
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      const GPixel *p2 = p;
Packit df99a1
      signed char *out2 = out;
Packit df99a1
      for (int j=0; j
Packit df99a1
        {
Packit df99a1
          int c = rmul[p2->r] + gmul[p2->g] + bmul[p2->b] + 32768;
Packit df99a1
          *out2 = max(-128, min(127, c>>16));
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
/* Extracts Cr */
Packit df99a1
void 
Packit df99a1
IW44Image::Transform::Encode::RGB_to_Cr(const GPixel *p, int w, int h, int rowsize, 
Packit df99a1
                       signed char *out, int outrowsize)
Packit df99a1
{
Packit df99a1
  int rmul[256], gmul[256], bmul[256];
Packit df99a1
  for (int k=0; k<256; k++)
Packit df99a1
    {
Packit df99a1
      rmul[k] = (int)((k*0x10000)*rgb_to_ycc[1][0]);
Packit df99a1
      gmul[k] = (int)((k*0x10000)*rgb_to_ycc[1][1]);
Packit df99a1
      bmul[k] = (int)((k*0x10000)*rgb_to_ycc[1][2]);
Packit df99a1
    }
Packit df99a1
  for (int i=0; i
Packit df99a1
    {
Packit df99a1
      const GPixel *p2 = p;
Packit df99a1
      signed char *out2 = out;
Packit df99a1
      for (int j=0; j
Packit df99a1
        {
Packit df99a1
          int c = rmul[p2->r] + gmul[p2->g] + bmul[p2->b] + 32768;
Packit df99a1
          *out2 = max(-128, min(127, c>>16));
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// MASKING DECOMPOSITION
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
//----------------------------------------------------
Packit df99a1
// Function for applying bidimensional IW44 between 
Packit df99a1
// scale intervals begin(inclusive) and end(exclusive)
Packit df99a1
// with a MASK bitmap
Packit df99a1
Packit df99a1
Packit df99a1
static void
Packit df99a1
interpolate_mask(short *data16, int w, int h, int rowsize,
Packit df99a1
                 const signed char *mask8, int mskrowsize)
Packit df99a1
{
Packit df99a1
  int i,j;
Packit df99a1
  // count masked bits
Packit df99a1
  short *count;
Packit df99a1
  GPBuffer<short> gcount(count,w*h);
Packit df99a1
  short *cp = count;
Packit df99a1
  for (i=0; i
Packit df99a1
    for (j=0; j
Packit df99a1
      cp[j] = (mask8[j] ? 0 : 0x1000);
Packit df99a1
  // copy image
Packit df99a1
  short *sdata;
Packit df99a1
  GPBuffer<short> gsdata(sdata,w*h);
Packit df99a1
  short *p = sdata;
Packit df99a1
  short *q = data16;
Packit df99a1
  for (i=0; i
Packit df99a1
    for (j=0; j
Packit df99a1
      p[j] = q[j];
Packit df99a1
  // iterate over resolutions
Packit df99a1
  int split = 1;
Packit df99a1
  int scale = 2;
Packit df99a1
  int again = 1;
Packit df99a1
  while (again && scale
Packit df99a1
    {
Packit df99a1
      again = 0;
Packit df99a1
      p = data16;
Packit df99a1
      q = sdata;
Packit df99a1
      cp = count;
Packit df99a1
      // iterate over block
Packit df99a1
      for (i=0; i
Packit df99a1
        for (j=0; j
Packit df99a1
          {
Packit df99a1
            int ii, jj;
Packit df99a1
            int gotz = 0;
Packit df99a1
            int gray = 0;
Packit df99a1
            int npix = 0;
Packit df99a1
            short *cpp = cp;
Packit df99a1
            short *qq = q;
Packit df99a1
            // look around when square goes beyond border
Packit df99a1
            int istart = i;
Packit df99a1
            if (istart+split>h)
Packit df99a1
              {
Packit df99a1
                istart -= scale;
Packit df99a1
                cpp -= w*scale;
Packit df99a1
                qq -= w*scale;
Packit df99a1
              }
Packit df99a1
            int jstart = j;
Packit df99a1
            if (jstart+split>w)
Packit df99a1
              jstart -= scale;
Packit df99a1
            // compute gray level
Packit df99a1
            for (ii=istart; ii
Packit df99a1
              for (jj=jstart; jj
Packit df99a1
                {
Packit df99a1
                  if (cpp[jj]>0) 
Packit df99a1
                    {
Packit df99a1
                      npix += cpp[jj];
Packit df99a1
                      gray += cpp[jj] * qq[jj];
Packit df99a1
                    } 
Packit df99a1
                  else if (ii>=i && jj>=j)
Packit df99a1
                    {
Packit df99a1
                      gotz = 1;
Packit df99a1
                    }
Packit df99a1
                }
Packit df99a1
            // process result
Packit df99a1
            if (npix == 0)
Packit df99a1
              {
Packit df99a1
                // continue to next resolution
Packit df99a1
                again = 1;
Packit df99a1
                cp[j] = 0;
Packit df99a1
              }
Packit df99a1
            else
Packit df99a1
              {
Packit df99a1
                gray = gray / npix;
Packit df99a1
                // check whether initial image require fix
Packit df99a1
                if (gotz)
Packit df99a1
                  {
Packit df99a1
                    cpp = cp;
Packit df99a1
                    qq = p;
Packit df99a1
                    for (ii=i; ii
Packit df99a1
                      for (jj=j; jj
Packit df99a1
                        if (cpp[jj] == 0)
Packit df99a1
                          {
Packit df99a1
                            qq[jj] = gray;
Packit df99a1
                            cpp[jj] = 1;
Packit df99a1
                          }
Packit df99a1
                  }
Packit df99a1
                // store average for next iteration
Packit df99a1
                cp[j] = npix>>2;
Packit df99a1
                q[j] = gray;
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
      // double resolution
Packit df99a1
      split = scale;
Packit df99a1
      scale = scale+scale;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
static void
Packit df99a1
forward_mask(short *data16, int w, int h, int rowsize, int begin, int end,
Packit df99a1
             const signed char *mask8, int mskrowsize )
Packit df99a1
{
Packit df99a1
  int i,j;
Packit df99a1
  signed char *m;
Packit df99a1
  short *p;
Packit df99a1
  short *d;
Packit df99a1
  // Allocate buffers
Packit df99a1
  short *sdata;
Packit df99a1
  GPBuffer<short> gsdata(sdata,w*h);
Packit df99a1
  signed char *smask;
Packit df99a1
  GPBuffer<signed char> gsmask(smask,w*h);
Packit df99a1
  // Copy mask
Packit df99a1
  m = smask;
Packit df99a1
  for (i=0; i
Packit df99a1
    memcpy((void*)m, (void*)mask8, w);
Packit df99a1
  // Loop over scale
Packit df99a1
  for (int scale=begin; scale
Packit df99a1
    {
Packit df99a1
      // Copy data into sdata buffer
Packit df99a1
      p = data16;
Packit df99a1
      d = sdata;
Packit df99a1
      for (i=0; i
Packit df99a1
        {
Packit df99a1
          for (j=0; j
Packit df99a1
            d[j] = p[j];
Packit df99a1
          p += rowsize * scale;
Packit df99a1
          d += w * scale;
Packit df99a1
        }
Packit df99a1
      // Decompose
Packit df99a1
      IW44Image::Transform::Encode::forward(sdata, w, h, w, scale, scale+scale);
Packit df99a1
      // Cancel masked coefficients
Packit df99a1
      d = sdata;
Packit df99a1
      m = smask;
Packit df99a1
      for (i=0; i
Packit df99a1
        {
Packit df99a1
          for (j=scale; j
Packit df99a1
            if (m[j])
Packit df99a1
              d[j] = 0;
Packit df99a1
          d += w * scale;
Packit df99a1
          m += w * scale;
Packit df99a1
          if (i+scale < h)
Packit df99a1
            {
Packit df99a1
              for (j=0; j
Packit df99a1
                if (m[j])
Packit df99a1
                  d[j] = 0;
Packit df99a1
              d += w * scale;
Packit df99a1
              m += w * scale;
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      // Reconstruct
Packit df99a1
      IW44Image::Transform::Decode::backward(sdata, w, h, w, scale+scale, scale);
Packit df99a1
      // Correct visible pixels
Packit df99a1
      p = data16;
Packit df99a1
      d = sdata;
Packit df99a1
      m = smask;
Packit df99a1
      for (i=0; i
Packit df99a1
        {
Packit df99a1
          for (j=0; j
Packit df99a1
            if (! m[j])
Packit df99a1
              d[j] = p[j];
Packit df99a1
          p += rowsize*scale;
Packit df99a1
          m += w*scale;
Packit df99a1
          d += w*scale;
Packit df99a1
        }
Packit df99a1
      // Decompose again (no need to iterate actually!)
Packit df99a1
      IW44Image::Transform::Encode::forward(sdata, w, h, w, scale, scale+scale);
Packit df99a1
      // Copy coefficients from sdata buffer
Packit df99a1
      p = data16;
Packit df99a1
      d = sdata;
Packit df99a1
      for (i=0; i
Packit df99a1
        {
Packit df99a1
          for (j=0; j
Packit df99a1
            p[j] = d[j];
Packit df99a1
          p += rowsize * scale;
Packit df99a1
          d += w * scale;
Packit df99a1
        }
Packit df99a1
      // Compute new mask for next scale
Packit df99a1
      m = smask;
Packit df99a1
      signed char *m0 = m;
Packit df99a1
      signed char *m1 = m;
Packit df99a1
      for (i=0; i
Packit df99a1
        {
Packit df99a1
          m0 = m1;
Packit df99a1
          if (i+scale < h)
Packit df99a1
            m1 = m + w*scale;
Packit df99a1
          for (j=0; j
Packit df99a1
            if (m[j] && m0[j] && m1[j] && (j<=0 || m[j-scale]) && (j+scale>=w || m[j+scale]))
Packit df99a1
              m[j] = 1;
Packit df99a1
            else
Packit df99a1
              m[j] = 0;
Packit df99a1
          m = m1 + w*scale;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  // Free buffers
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IW44Image::Map::Encode::create(const signed char *img8, int imgrowsize, 
Packit df99a1
               const signed char *msk8, int mskrowsize )
Packit df99a1
{
Packit df99a1
  int i, j;
Packit df99a1
  // Progress
Packit df99a1
  DJVU_PROGRESS_TASK(transf,"create iw44 map",3);
Packit df99a1
  // Allocate decomposition buffer
Packit df99a1
  short *data16;
Packit df99a1
  GPBuffer<short> gdata16(data16,bw*bh);
Packit df99a1
  // Copy pixels
Packit df99a1
  short *p = data16;
Packit df99a1
  const signed char *row = img8;
Packit df99a1
  for (i=0; i
Packit df99a1
    {
Packit df99a1
      for (j=0; j
Packit df99a1
        *p++ = (int)(row[j]) << iw_shift;
Packit df99a1
      row += imgrowsize;
Packit df99a1
      for (j=iw; j
Packit df99a1
        *p++ = 0;
Packit df99a1
    }
Packit df99a1
  for (i=ih; i
Packit df99a1
    for (j=0; j
Packit df99a1
      *p++ = 0;
Packit df99a1
  // Handle bitmask
Packit df99a1
  if (msk8)
Packit df99a1
    {
Packit df99a1
      // Interpolate pixels below mask
Packit df99a1
      DJVU_PROGRESS_RUN(transf, 1);
Packit df99a1
      interpolate_mask(data16, iw, ih, bw, msk8, mskrowsize);
Packit df99a1
      // Multiscale iterative masked decomposition
Packit df99a1
      DJVU_PROGRESS_RUN(transf, 3);
Packit df99a1
      forward_mask(data16, iw, ih, bw, 1, 32, msk8, mskrowsize);
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      // Perform traditional decomposition
Packit df99a1
      DJVU_PROGRESS_RUN(transf, 3);
Packit df99a1
      IW44Image::Transform::Encode::forward(data16, iw, ih, bw, 1, 32);
Packit df99a1
    }
Packit df99a1
  // Copy coefficient into blocks
Packit df99a1
  p = data16;
Packit df99a1
  IW44Image::Block *block = blocks;
Packit df99a1
  for (i=0; i
Packit df99a1
    {
Packit df99a1
      for (j=0; j
Packit df99a1
        {
Packit df99a1
          short liftblock[1024];
Packit df99a1
          // transfer coefficients at (p+j) into aligned block
Packit df99a1
          short *pp = p + j;
Packit df99a1
          short *pl = liftblock;
Packit df99a1
          for (int ii=0; ii<32; ii++, pp+=bw)
Packit df99a1
            for (int jj=0; jj<32; jj++) 
Packit df99a1
              *pl++ = pp[jj];
Packit df99a1
          // transfer into IW44Image::Block (apply zigzag and scaling)
Packit df99a1
          block->read_liftblock(liftblock, this);
Packit df99a1
          block++;
Packit df99a1
        }
Packit df99a1
      // next row of blocks
Packit df99a1
      p += 32*bw;
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IW44Image::Map::Encode::slashres(int res)
Packit df99a1
{
Packit df99a1
  int minbucket = 1;
Packit df99a1
  if (res < 2)
Packit df99a1
    return;
Packit df99a1
  else if (res < 4)
Packit df99a1
    minbucket=16;
Packit df99a1
  else if (res < 8)
Packit df99a1
    minbucket=4;
Packit df99a1
  for (int blockno=0; blockno
Packit df99a1
    for (int buckno=minbucket; buckno<64; buckno++)
Packit df99a1
      blocks[blockno].zero(buckno);
Packit df99a1
}
Packit df99a1
Packit df99a1
// encode_prepare
Packit df99a1
// -- compute the states prior to encoding the buckets
Packit df99a1
int
Packit df99a1
IW44Image::Codec::Encode::encode_prepare(int band, int fbucket, int nbucket, IW44Image::Block &blk, IW44Image::Block &eblk)
Packit df99a1
{
Packit df99a1
  int bbstate = 0;
Packit df99a1
  // compute state of all coefficients in all buckets
Packit df99a1
  if (band) 
Packit df99a1
    {
Packit df99a1
      // Band other than zero
Packit df99a1
      int thres = quant_hi[band];
Packit df99a1
      char *cstate = coeffstate;
Packit df99a1
      for (int buckno=0; buckno
Packit df99a1
        {
Packit df99a1
          const short *pcoeff = blk.data(fbucket+buckno);
Packit df99a1
          const short *epcoeff = eblk.data(fbucket+buckno);
Packit df99a1
          int bstatetmp = 0;
Packit df99a1
          if (! pcoeff)
Packit df99a1
            {
Packit df99a1
              bstatetmp = UNK;
Packit df99a1
              // cstate[i] is not used and does not need initialization
Packit df99a1
            }
Packit df99a1
          else if (! epcoeff)
Packit df99a1
            {
Packit df99a1
              for (int i=0; i<16; i++)
Packit df99a1
                {
Packit df99a1
                  int cstatetmp = UNK;
Packit df99a1
                  if  ((int)(pcoeff[i])>=thres || (int)(pcoeff[i])<=-thres)
Packit df99a1
                    cstatetmp = NEW|UNK;
Packit df99a1
                  cstate[i] = cstatetmp;
Packit df99a1
                  bstatetmp |= cstatetmp;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          else
Packit df99a1
            {
Packit df99a1
              for (int i=0; i<16; i++)
Packit df99a1
                {
Packit df99a1
                  int cstatetmp = UNK;
Packit df99a1
                  if (epcoeff[i])
Packit df99a1
                    cstatetmp = ACTIVE;
Packit df99a1
                  else if  ((int)(pcoeff[i])>=thres || (int)(pcoeff[i])<=-thres)
Packit df99a1
                    cstatetmp = NEW|UNK;
Packit df99a1
                  cstate[i] = cstatetmp;
Packit df99a1
                  bstatetmp |= cstatetmp;
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
          bucketstate[buckno] = bstatetmp;
Packit df99a1
          bbstate |= bstatetmp;
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  else
Packit df99a1
    {
Packit df99a1
      // Band zero ( fbucket==0 implies band==zero and nbucket==1 )
Packit df99a1
      const short *pcoeff = blk.data(0, &map);
Packit df99a1
      const short *epcoeff = eblk.data(0, &emap;;
Packit df99a1
      char *cstate = coeffstate;
Packit df99a1
      for (int i=0; i<16; i++)
Packit df99a1
        {
Packit df99a1
          int thres = quant_lo[i];
Packit df99a1
          int cstatetmp = cstate[i];
Packit df99a1
          if (cstatetmp != ZERO)
Packit df99a1
            {
Packit df99a1
              cstatetmp = UNK;
Packit df99a1
              if (epcoeff[i])
Packit df99a1
                cstatetmp = ACTIVE;
Packit df99a1
              else if ((int)(pcoeff[i])>=thres || (int)(pcoeff[i])<=-thres)
Packit df99a1
                cstatetmp = NEW|UNK;
Packit df99a1
            }
Packit df99a1
          cstate[i] = cstatetmp;
Packit df99a1
          bbstate |= cstatetmp;
Packit df99a1
        }
Packit df99a1
      bucketstate[0] = bbstate;
Packit df99a1
    }
Packit df99a1
  return bbstate;
Packit df99a1
}
Packit df99a1
Packit df99a1
// encode_buckets
Packit df99a1
// -- code a sequence of buckets in a given block
Packit df99a1
void
Packit df99a1
IW44Image::Codec::Encode::encode_buckets(ZPCodec &zp, int bit, int band, 
Packit df99a1
                         IW44Image::Block &blk, IW44Image::Block &eblk,
Packit df99a1
                         int fbucket, int nbucket)
Packit df99a1
{
Packit df99a1
  // compute state of all coefficients in all buckets
Packit df99a1
  int bbstate = encode_prepare(band, fbucket, nbucket, blk, eblk);
Packit df99a1
Packit df99a1
  // code root bit
Packit df99a1
  if ((nbucket<16) || (bbstate&ACTIVE))
Packit df99a1
    {
Packit df99a1
      bbstate |= NEW;
Packit df99a1
    }
Packit df99a1
  else if (bbstate & UNK)
Packit df99a1
    {
Packit df99a1
      zp.encoder( (bbstate&NEW) ? 1 : 0 , ctxRoot);
Packit df99a1
#ifdef TRACE
Packit df99a1
      DjVuPrintMessage("bbstate[bit=%d,band=%d] = %d\n", bit, band, bbstate);
Packit df99a1
#endif
Packit df99a1
    }
Packit df99a1
  
Packit df99a1
  // code bucket bits
Packit df99a1
  if (bbstate & NEW)
Packit df99a1
    for (int buckno=0; buckno
Packit df99a1
      {
Packit df99a1
        // Code bucket bit
Packit df99a1
        if (bucketstate[buckno] & UNK)
Packit df99a1
          {
Packit df99a1
            // Context
Packit df99a1
            int ctx = 0;
Packit df99a1
#ifndef NOCTX_BUCKET_UPPER
Packit df99a1
            if (band>0)
Packit df99a1
              {
Packit df99a1
                int k = (fbucket+buckno)<<2;
Packit df99a1
                const short *b = eblk.data(k>>4);
Packit df99a1
                if (b)
Packit df99a1
                  {
Packit df99a1
                    k = k & 0xf;
Packit df99a1
                    if (b[k])
Packit df99a1
                      ctx += 1;
Packit df99a1
                    if (b[k+1])
Packit df99a1
                      ctx += 1;
Packit df99a1
                    if (b[k+2])
Packit df99a1
                      ctx += 1;
Packit df99a1
                    if (ctx<3 && b[k+3])
Packit df99a1
                      ctx += 1;
Packit df99a1
                  }
Packit df99a1
              }
Packit df99a1
#endif
Packit df99a1
#ifndef NOCTX_BUCKET_ACTIVE
Packit df99a1
            if (bbstate & ACTIVE)
Packit df99a1
              ctx |= 4; 
Packit df99a1
#endif
Packit df99a1
            // Code
Packit df99a1
            zp.encoder( (bucketstate[buckno]&NEW) ? 1 : 0, ctxBucket[band][ctx] );
Packit df99a1
#ifdef TRACE
Packit df99a1
            DjVuPrintMessage("  bucketstate[bit=%d,band=%d,buck=%d] = %d\n", 
Packit df99a1
                   bit, band, buckno, bucketstate[buckno] & ~ZERO);
Packit df99a1
#endif
Packit df99a1
          }
Packit df99a1
      }
Packit df99a1
  
Packit df99a1
  // code new active coefficient (with their sign)
Packit df99a1
  if (bbstate & NEW)
Packit df99a1
    {
Packit df99a1
      int thres = quant_hi[band];
Packit df99a1
      char *cstate = coeffstate;
Packit df99a1
      for (int buckno=0; buckno
Packit df99a1
        if (bucketstate[buckno] & NEW)
Packit df99a1
          {
Packit df99a1
            int i;
Packit df99a1
#ifndef NOCTX_EXPECT
Packit df99a1
            int gotcha = 0;
Packit df99a1
            const int maxgotcha = 7;
Packit df99a1
            for (i=0; i<16; i++)
Packit df99a1
              if (cstate[i] & UNK)
Packit df99a1
                gotcha += 1;
Packit df99a1
#endif
Packit df99a1
            const short *pcoeff = blk.data(fbucket+buckno);
Packit df99a1
            short *epcoeff = eblk.data(fbucket+buckno, &emap;;
Packit df99a1
            // iterate within bucket
Packit df99a1
            for (i=0; i<16; i++)
Packit df99a1
              {
Packit df99a1
                if (cstate[i] & UNK)
Packit df99a1
                  {
Packit df99a1
                    // Prepare context
Packit df99a1
                    int ctx = 0;
Packit df99a1
#ifndef NOCTX_EXPECT
Packit df99a1
                    if (gotcha>=maxgotcha)
Packit df99a1
                      ctx = maxgotcha;
Packit df99a1
                    else
Packit df99a1
                      ctx = gotcha;
Packit df99a1
#endif
Packit df99a1
#ifndef NOCTX_ACTIVE
Packit df99a1
                    if (bucketstate[buckno] & ACTIVE)
Packit df99a1
                      ctx |= 8;
Packit df99a1
#endif
Packit df99a1
                    // Code
Packit df99a1
                    zp.encoder( (cstate[i]&NEW) ? 1 : 0, ctxStart[ctx] );
Packit df99a1
                    if (cstate[i] & NEW)
Packit df99a1
                      {
Packit df99a1
                        // Code sign
Packit df99a1
                        zp.IWencoder( (pcoeff[i]<0) ? 1 : 0 );
Packit df99a1
                        // Set encoder state
Packit df99a1
                        if (band==0)
Packit df99a1
                          thres = quant_lo[i];
Packit df99a1
                        epcoeff[i] = thres + (thres>>1);
Packit df99a1
                      }
Packit df99a1
#ifndef NOCTX_EXPECT
Packit df99a1
                    if (cstate[i] & NEW)
Packit df99a1
                      gotcha = 0;
Packit df99a1
                    else if (gotcha > 0)
Packit df99a1
                      gotcha -= 1;
Packit df99a1
#endif
Packit df99a1
#ifdef TRACE
Packit df99a1
                    DjVuPrintMessage("    coeffstate[bit=%d,band=%d,buck=%d,c=%d] = %d\n", 
Packit df99a1
                           bit, band, buckno, i, cstate[i]);
Packit df99a1
#endif
Packit df99a1
                  }
Packit df99a1
              }
Packit df99a1
          }
Packit df99a1
    }
Packit df99a1
Packit df99a1
  // code mantissa bits
Packit df99a1
  if (bbstate & ACTIVE)
Packit df99a1
    {
Packit df99a1
      int thres = quant_hi[band];
Packit df99a1
      char *cstate = coeffstate;
Packit df99a1
      for (int buckno=0; buckno
Packit df99a1
        if (bucketstate[buckno] & ACTIVE)
Packit df99a1
          {
Packit df99a1
            const short *pcoeff = blk.data(fbucket+buckno);
Packit df99a1
            short *epcoeff = eblk.data(fbucket+buckno, &emap;;
Packit df99a1
            for (int i=0; i<16; i++)
Packit df99a1
              if (cstate[i] & ACTIVE)
Packit df99a1
                {
Packit df99a1
                  // get coefficient
Packit df99a1
                  int coeff = pcoeff[i];
Packit df99a1
                  int ecoeff = epcoeff[i];
Packit df99a1
                  if (coeff < 0)
Packit df99a1
                    coeff = -coeff;
Packit df99a1
                  // get band zero thresholds
Packit df99a1
                  if (band == 0)
Packit df99a1
                    thres = quant_lo[i];
Packit df99a1
                  // compute mantissa bit
Packit df99a1
                  int pix = 0;
Packit df99a1
                  if (coeff >= ecoeff)
Packit df99a1
                    pix = 1;
Packit df99a1
                  // encode second or lesser mantissa bit
Packit df99a1
                  if (ecoeff <= 3*thres)
Packit df99a1
                    zp.encoder(pix, ctxMant);                      
Packit df99a1
                  else
Packit df99a1
					  zp.IWencoder(!!pix);
Packit df99a1
                  // adjust epcoeff
Packit df99a1
                  epcoeff[i] = ecoeff - (pix ? 0 : thres) + (thres>>1);
Packit df99a1
                }
Packit df99a1
          }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
// IW44Image::Codec::estimate_decibel
Packit df99a1
// -- estimate encoding error (after code_slice) in decibels.
Packit df99a1
float
Packit df99a1
IW44Image::Codec::Encode::estimate_decibel(float frac)
Packit df99a1
{
Packit df99a1
  int i,j;
Packit df99a1
  const float *q;
Packit df99a1
  // Fill norm arrays
Packit df99a1
  float norm_lo[16];
Packit df99a1
  float norm_hi[10];
Packit df99a1
  // -- lo coefficients
Packit df99a1
  q = iw_norm;
Packit df99a1
  for (i=j=0; i<4; j++)
Packit df99a1
    norm_lo[i++] = *q++;
Packit df99a1
  for (j=0; j<4; j++)
Packit df99a1
    norm_lo[i++] = *q;
Packit df99a1
  q += 1;
Packit df99a1
  for (j=0; j<4; j++)
Packit df99a1
    norm_lo[i++] = *q;
Packit df99a1
  q += 1;
Packit df99a1
  for (j=0; j<4; j++)
Packit df99a1
    norm_lo[i++] = *q;
Packit df99a1
  q += 1;
Packit df99a1
  // -- hi coefficients
Packit df99a1
  norm_hi[0] = 0;
Packit df99a1
  for (j=1; j<10; j++)
Packit df99a1
    norm_hi[j] = *q++;
Packit df99a1
  // Initialize mse array
Packit df99a1
  float *xmse;
Packit df99a1
  GPBuffer<float> gxmse(xmse,map.nb);
Packit df99a1
  // Compute mse in each block
Packit df99a1
  for (int blockno=0; blockno
Packit df99a1
    {
Packit df99a1
      float mse = 0;
Packit df99a1
      // Iterate over bands
Packit df99a1
      for (int bandno=0; bandno<10; bandno++)
Packit df99a1
        {
Packit df99a1
          int fbucket = bandbuckets[bandno].start;
Packit df99a1
          int nbucket = bandbuckets[bandno].size;
Packit df99a1
          IW44Image::Block &blk = map.blocks[blockno];
Packit df99a1
          IW44Image::Block &eblk = emap.blocks[blockno];
Packit df99a1
          float norm = norm_hi[bandno];
Packit df99a1
          for (int buckno=0; buckno
Packit df99a1
            {
Packit df99a1
              const short *pcoeff = blk.data(fbucket+buckno);
Packit df99a1
              const short *epcoeff = eblk.data(fbucket+buckno);
Packit df99a1
              if (pcoeff)
Packit df99a1
                {
Packit df99a1
                  if (epcoeff)
Packit df99a1
                    {
Packit df99a1
                      for (i=0; i<16; i++)
Packit df99a1
                        {
Packit df99a1
                          if (bandno == 0)
Packit df99a1
                            norm = norm_lo[i];
Packit df99a1
                          float delta = (float)(pcoeff[i]<0 ? -pcoeff[i] : pcoeff[i]);
Packit df99a1
                          delta = delta - epcoeff[i];
Packit df99a1
                          mse = mse + norm * delta * delta;
Packit df99a1
                        }
Packit df99a1
                    }
Packit df99a1
                  else
Packit df99a1
                    {
Packit df99a1
                      for (i=0; i<16; i++)
Packit df99a1
                        {
Packit df99a1
                          if (bandno == 0)
Packit df99a1
                            norm = norm_lo[i];
Packit df99a1
                          float delta = (float)(pcoeff[i]);
Packit df99a1
                          mse = mse + norm * delta * delta;
Packit df99a1
                        }
Packit df99a1
                    }
Packit df99a1
                }
Packit df99a1
            }
Packit df99a1
        }
Packit df99a1
      xmse[blockno] = mse / 1024;
Packit df99a1
    }
Packit df99a1
  // Compute partition point
Packit df99a1
  int n = 0;
Packit df99a1
  int m = map.nb - 1;
Packit df99a1
  int p = (int)floor(m*(1.0-frac)+0.5);
Packit df99a1
  p = (p>m ? m : (p<0 ? 0 : p));
Packit df99a1
  float pivot = 0;
Packit df99a1
  // Partition array
Packit df99a1
  while (n < p)
Packit df99a1
    {
Packit df99a1
      int l = n;
Packit df99a1
      int h = m;
Packit df99a1
      if (xmse[l] > xmse[h]) { float tmp=xmse[l]; xmse[l]=xmse[h]; xmse[h]=tmp; }
Packit df99a1
      pivot = xmse[(l+h)/2];
Packit df99a1
      if (pivot < xmse[l]) { float tmp=pivot; pivot=xmse[l]; xmse[l]=tmp; }
Packit df99a1
      if (pivot > xmse[h]) { float tmp=pivot; pivot=xmse[h]; xmse[h]=tmp; }
Packit df99a1
      while (l < h)
Packit df99a1
        {
Packit df99a1
          if (xmse[l] > xmse[h]) { float tmp=xmse[l]; xmse[l]=xmse[h]; xmse[h]=tmp; }
Packit df99a1
          while (xmse[l]
Packit df99a1
          while (xmse[h]>pivot) h--;
Packit df99a1
        }
Packit df99a1
      if (p>=l) 
Packit df99a1
        n = l;
Packit df99a1
      else 
Packit df99a1
        m = l-1;
Packit df99a1
    }
Packit df99a1
  // Compute average mse
Packit df99a1
  float mse = 0;
Packit df99a1
  for (i=p; i
Packit df99a1
    mse = mse + xmse[i];
Packit df99a1
  mse = mse / (map.nb - p);
Packit df99a1
  // Return
Packit df99a1
  float factor = 255 << iw_shift;
Packit df99a1
  float decibel = (float)(10.0 * log ( factor * factor / mse ) / 2.302585125);
Packit df99a1
  return decibel;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
// IW44IMAGE ENCODING ROUTINES
Packit df99a1
//////////////////////////////////////////////////////
Packit df99a1
Packit df99a1
Packit df99a1
void 
Packit df99a1
IW44Image::PrimaryHeader::encode(GP<ByteStream> gbs)
Packit df99a1
{
Packit df99a1
  gbs->write8(serial);
Packit df99a1
  gbs->write8(slices);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IW44Image::SecondaryHeader::encode(GP<ByteStream> gbs)
Packit df99a1
{
Packit df99a1
  gbs->write8(major);
Packit df99a1
  gbs->write8(minor);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IW44Image::TertiaryHeader::encode(GP<ByteStream> gbs)
Packit df99a1
{
Packit df99a1
  gbs->write8(xhi);
Packit df99a1
  gbs->write8(xlo);
Packit df99a1
  gbs->write8(yhi);
Packit df99a1
  gbs->write8(ylo);
Packit df99a1
  gbs->write8(crcbdelay);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
GP<IW44Image>
Packit df99a1
IW44Image::create_encode(const ImageType itype)
Packit df99a1
{
Packit df99a1
  switch(itype)
Packit df99a1
  {
Packit df99a1
  case COLOR:
Packit df99a1
    return new IWPixmap::Encode();
Packit df99a1
  case GRAY:
Packit df99a1
    return new IWBitmap::Encode();
Packit df99a1
  default:
Packit df99a1
    return 0;
Packit df99a1
  }
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<IW44Image>
Packit df99a1
IW44Image::create_encode(const GBitmap &bm, const GP<GBitmap> mask)
Packit df99a1
{
Packit df99a1
  IWBitmap::Encode *bit=new IWBitmap::Encode();
Packit df99a1
  GP<IW44Image> retval=bit;
Packit df99a1
  bit->init(bm, mask);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
IWBitmap::Encode::Encode(void)
Packit df99a1
: IWBitmap(), ycodec_enc(0)
Packit df99a1
{}
Packit df99a1
Packit df99a1
IWBitmap::Encode::~Encode()
Packit df99a1
{
Packit df99a1
  close_codec();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
IWBitmap::Encode::init(const GBitmap &bm, const GP<GBitmap> gmask)
Packit df99a1
{
Packit df99a1
  // Free
Packit df99a1
  close_codec();
Packit df99a1
  delete ymap;
Packit df99a1
  ymap = 0;
Packit df99a1
  // Init
Packit df99a1
  int i, j;
Packit df99a1
  int w = bm.columns();
Packit df99a1
  int h = bm.rows();
Packit df99a1
  int g = bm.get_grays()-1;
Packit df99a1
  signed char *buffer;
Packit df99a1
  GPBuffer<signed char> gbuffer(buffer,w*h);
Packit df99a1
  // Prepare gray level conversion table
Packit df99a1
  signed char  bconv[256];
Packit df99a1
  for (i=0; i<256; i++)
Packit df99a1
    bconv[i] = max(0,min(255,i*255/g)) - 128;
Packit df99a1
  // Perform decomposition
Packit df99a1
  // Prepare mask information
Packit df99a1
  const signed char *msk8 = 0;
Packit df99a1
  int mskrowsize = 0;
Packit df99a1
  GBitmap *mask=gmask;
Packit df99a1
  if (gmask)
Packit df99a1
  {
Packit df99a1
    msk8 = (const signed char*)((*mask)[0]);
Packit df99a1
    mskrowsize = mask->rowsize();
Packit df99a1
  }
Packit df99a1
  // Prepare a buffer of signed bytes
Packit df99a1
  for (i=0; i
Packit df99a1
    {
Packit df99a1
      signed char *bufrow = buffer + i*w;
Packit df99a1
      const unsigned char *bmrow = bm[i];
Packit df99a1
      for (j=0; j
Packit df99a1
        bufrow[j] = bconv[bmrow[j]];
Packit df99a1
    }
Packit df99a1
  // Create map
Packit df99a1
  Map::Encode *eymap=new Map::Encode(w,h);
Packit df99a1
  ymap = eymap;
Packit df99a1
  eymap->create(buffer, w, msk8, mskrowsize);
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IWBitmap::Encode::close_codec(void)
Packit df99a1
{
Packit df99a1
  delete ycodec_enc;
Packit df99a1
  ycodec_enc = 0;
Packit df99a1
  IWBitmap::close_codec();
Packit df99a1
}
Packit df99a1
Packit df99a1
int  
Packit df99a1
IWBitmap::Encode::encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parm)
Packit df99a1
{
Packit df99a1
  // Check
Packit df99a1
  if (parm.slices==0 && parm.bytes==0 && parm.decibels==0)
Packit df99a1
    G_THROW( ERR_MSG("IW44Image.need_stop") );
Packit df99a1
  if (! ymap)
Packit df99a1
    G_THROW( ERR_MSG("IW44Image.empty_object") );
Packit df99a1
  // Open codec
Packit df99a1
  if (!ycodec_enc)
Packit df99a1
  {
Packit df99a1
    cslice = cserial = cbytes = 0;
Packit df99a1
    ycodec_enc = new Codec::Encode(*ymap);
Packit df99a1
  }
Packit df99a1
  // Adjust cbytes
Packit df99a1
  cbytes += sizeof(struct IW44Image::PrimaryHeader);
Packit df99a1
  if (cserial == 0)
Packit df99a1
    cbytes += sizeof(struct IW44Image::SecondaryHeader) + sizeof(struct IW44Image::TertiaryHeader);
Packit df99a1
  // Prepare zcoded slices
Packit df99a1
  int flag = 1;
Packit df99a1
  int nslices = 0;
Packit df99a1
  GP<ByteStream> gmbs=ByteStream::create();
Packit df99a1
  ByteStream &mbs=*gmbs;
Packit df99a1
  DJVU_PROGRESS_TASK(chunk,"encode chunk",parm.slices-cslice);
Packit df99a1
  {
Packit df99a1
    float estdb = -1.0;
Packit df99a1
    GP<ZPCodec> gzp=ZPCodec::create(gmbs, true, true);
Packit df99a1
    ZPCodec &zp=*gzp;
Packit df99a1
    while (flag)
Packit df99a1
      {
Packit df99a1
        if (parm.decibels>0  && estdb>=parm.decibels)
Packit df99a1
          break;
Packit df99a1
        if (parm.bytes>0  && mbs.tell()+cbytes>=parm.bytes)
Packit df99a1
          break;
Packit df99a1
        if (parm.slices>0 && nslices+cslice>=parm.slices)
Packit df99a1
          break;
Packit df99a1
        DJVU_PROGRESS_RUN(chunk, (1+nslices-cslice)|0xf);
Packit df99a1
        flag = ycodec_enc->code_slice(zp);
Packit df99a1
        if (flag && parm.decibels>0.0)
Packit df99a1
          if (ycodec_enc->curband==0 || estdb>=parm.decibels-DECIBEL_PRUNE)
Packit df99a1
            estdb = ycodec_enc->estimate_decibel(db_frac);
Packit df99a1
        nslices++;
Packit df99a1
      }
Packit df99a1
  }
Packit df99a1
  // Write primary header
Packit df99a1
  struct IW44Image::PrimaryHeader primary;
Packit df99a1
  primary.serial = cserial;
Packit df99a1
  primary.slices = nslices;
Packit df99a1
  primary.encode(gbs);
Packit df99a1
  // Write auxilliary headers
Packit df99a1
  if (cserial == 0)
Packit df99a1
    {
Packit df99a1
      struct IW44Image::SecondaryHeader secondary;
Packit df99a1
      secondary.major = IWCODEC_MAJOR + 0x80;
Packit df99a1
      secondary.minor = IWCODEC_MINOR;
Packit df99a1
      secondary.encode(gbs);
Packit df99a1
      struct IW44Image::TertiaryHeader tertiary;
Packit df99a1
      tertiary.xhi = (ymap->iw >> 8) & 0xff;
Packit df99a1
      tertiary.xlo = (ymap->iw >> 0) & 0xff;
Packit df99a1
      tertiary.yhi = (ymap->ih >> 8) & 0xff;
Packit df99a1
      tertiary.ylo = (ymap->ih >> 0) & 0xff;
Packit df99a1
      tertiary.crcbdelay = 0;
Packit df99a1
      tertiary.encode(gbs);
Packit df99a1
    }
Packit df99a1
  // Write slices
Packit df99a1
  mbs.seek(0);
Packit df99a1
  gbs->copy(mbs);
Packit df99a1
  // Return
Packit df99a1
  cbytes  += mbs.tell();
Packit df99a1
  cslice  += nslices;
Packit df99a1
  cserial += 1;
Packit df99a1
  return flag;
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IWBitmap::Encode::encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms)
Packit df99a1
{
Packit df99a1
  if (ycodec_enc)
Packit df99a1
    G_THROW( ERR_MSG("IW44Image.left_open1") );
Packit df99a1
  int flag = 1;
Packit df99a1
  iff.put_chunk("FORM:BM44", 1);
Packit df99a1
  DJVU_PROGRESS_TASK(iff,"encode iff chunk",nchunks);
Packit df99a1
  for (int i=0; flag && i
Packit df99a1
    {
Packit df99a1
      DJVU_PROGRESS_RUN(iff,i+1);
Packit df99a1
      iff.put_chunk("BM44");
Packit df99a1
      flag = encode_chunk(iff.get_bytestream(),parms[i]);
Packit df99a1
      iff.close_chunk();
Packit df99a1
    }
Packit df99a1
  iff.close_chunk();
Packit df99a1
  close_codec();
Packit df99a1
}
Packit df99a1
Packit df99a1
GP<IW44Image>
Packit df99a1
IW44Image::create_encode(
Packit df99a1
  const GPixmap &pm, const GP<GBitmap> gmask, CRCBMode crcbmode)
Packit df99a1
{
Packit df99a1
  IWPixmap::Encode *pix=new IWPixmap::Encode();
Packit df99a1
  GP<IW44Image> retval=pix;
Packit df99a1
  pix->init(pm, gmask,(IWPixmap::Encode::CRCBMode)crcbmode);
Packit df99a1
  return retval;
Packit df99a1
}
Packit df99a1
Packit df99a1
IWPixmap::Encode::Encode(void)
Packit df99a1
: IWPixmap(), ycodec_enc(0), cbcodec_enc(0), crcodec_enc(0)
Packit df99a1
{}
Packit df99a1
Packit df99a1
IWPixmap::Encode::~Encode()
Packit df99a1
{
Packit df99a1
  close_codec();
Packit df99a1
}
Packit df99a1
Packit df99a1
void
Packit df99a1
IWPixmap::Encode::init(const GPixmap &pm, const GP<GBitmap> gmask, CRCBMode crcbmode)
Packit df99a1
{
Packit df99a1
  /* Free */
Packit df99a1
  close_codec();
Packit df99a1
  delete ymap;
Packit df99a1
  delete cbmap;
Packit df99a1
  delete crmap;
Packit df99a1
  ymap = cbmap = crmap = 0;
Packit df99a1
  /* Create */
Packit df99a1
  int w = pm.columns();
Packit df99a1
  int h = pm.rows();
Packit df99a1
  signed char *buffer;
Packit df99a1
  GPBuffer<signed char> gbuffer(buffer,w*h);
Packit df99a1
  // Create maps
Packit df99a1
  Map::Encode *eymap = new Map::Encode(w,h);
Packit df99a1
  ymap = eymap;
Packit df99a1
  // Handle CRCB mode
Packit df99a1
  switch (crcbmode) 
Packit df99a1
    {
Packit df99a1
    case CRCBnone:   crcb_half=1; crcb_delay=-1; break;
Packit df99a1
    case CRCBhalf:   crcb_half=1; crcb_delay=10; break;        
Packit df99a1
    case CRCBnormal: crcb_half=0; crcb_delay=10; break;
Packit df99a1
    case CRCBfull:   crcb_half=0; crcb_delay= 0; break;
Packit df99a1
    }
Packit df99a1
  // Prepare mask information
Packit df99a1
  const signed char *msk8 = 0;
Packit df99a1
  int mskrowsize = 0;
Packit df99a1
  GBitmap *mask=gmask;
Packit df99a1
  if (mask)
Packit df99a1
  {
Packit df99a1
    msk8 = (signed char const *)((*mask)[0]);
Packit df99a1
    mskrowsize = mask->rowsize();
Packit df99a1
  }
Packit df99a1
  // Fill buffer with luminance information
Packit df99a1
  DJVU_PROGRESS_TASK(create,"initialize pixmap",3);
Packit df99a1
  DJVU_PROGRESS_RUN(create,(crcb_delay>=0 ? 1 : 3));
Packit df99a1
  Transform::Encode::RGB_to_Y(pm[0], w, h, pm.rowsize(), buffer, w);
Packit df99a1
  if (crcb_delay < 0)
Packit df99a1
    {
Packit df99a1
      // Stupid inversion for gray images
Packit df99a1
      signed char *e = buffer + w*h;
Packit df99a1
      for (signed char *b=buffer; b
Packit df99a1
        *b = 255 - *b;
Packit df99a1
    }
Packit df99a1
  // Create YMAP
Packit df99a1
  eymap->create(buffer, w, msk8, mskrowsize);
Packit df99a1
  // Create chrominance maps
Packit df99a1
  if (crcb_delay >= 0)
Packit df99a1
    {
Packit df99a1
      Map::Encode *ecbmap = new Map::Encode(w,h);
Packit df99a1
      cbmap = ecbmap;
Packit df99a1
      Map::Encode *ecrmap = new Map::Encode(w,h);
Packit df99a1
      crmap = ecrmap;
Packit df99a1
      // Process CB information
Packit df99a1
      DJVU_PROGRESS_RUN(create,2);
Packit df99a1
      Transform::Encode::RGB_to_Cb(pm[0], w, h, pm.rowsize(), buffer, w);
Packit df99a1
      ecbmap->create(buffer, w, msk8, mskrowsize);
Packit df99a1
      // Process CR information
Packit df99a1
      DJVU_PROGRESS_RUN(create,3);
Packit df99a1
      Transform::Encode::RGB_to_Cr(pm[0], w, h, pm.rowsize(), buffer, w); 
Packit df99a1
      ecrmap->create(buffer, w, msk8, mskrowsize);
Packit df99a1
      // Perform chrominance reduction (CRCBhalf)
Packit df99a1
      if (crcb_half)
Packit df99a1
        {
Packit df99a1
          ecbmap->slashres(2);
Packit df99a1
          ecrmap->slashres(2);
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IWPixmap::Encode::encode_iff(IFFByteStream &iff, int nchunks, const IWEncoderParms *parms)
Packit df99a1
{
Packit df99a1
  if (ycodec_enc)
Packit df99a1
    G_THROW( ERR_MSG("IW44Image.left_open3") );
Packit df99a1
  int flag = 1;
Packit df99a1
  iff.put_chunk("FORM:PM44", 1);
Packit df99a1
  DJVU_PROGRESS_TASK(iff,"encode pixmap chunk", nchunks);
Packit df99a1
  for (int i=0; flag && i
Packit df99a1
    {
Packit df99a1
      DJVU_PROGRESS_RUN(iff,i+1);
Packit df99a1
      iff.put_chunk("PM44");
Packit df99a1
      flag = encode_chunk(iff.get_bytestream(), parms[i]);
Packit df99a1
      iff.close_chunk();
Packit df99a1
    }
Packit df99a1
  iff.close_chunk();
Packit df99a1
  close_codec();
Packit df99a1
}
Packit df99a1
Packit df99a1
void 
Packit df99a1
IWPixmap::Encode::close_codec(void)
Packit df99a1
{
Packit df99a1
  delete ycodec_enc;
Packit df99a1
  delete cbcodec_enc;
Packit df99a1
  delete crcodec_enc;
Packit df99a1
  ycodec_enc = crcodec_enc = cbcodec_enc = 0;
Packit df99a1
  IWPixmap::close_codec();
Packit df99a1
}
Packit df99a1
Packit df99a1
int  
Packit df99a1
IWPixmap::Encode::encode_chunk(GP<ByteStream> gbs, const IWEncoderParms &parm)
Packit df99a1
{
Packit df99a1
  // Check
Packit df99a1
  if (parm.slices==0 && parm.bytes==0 && parm.decibels==0)
Packit df99a1
    G_THROW( ERR_MSG("IW44Image.need_stop2") );
Packit df99a1
  if (!ymap)
Packit df99a1
    G_THROW( ERR_MSG("IW44Image.empty_object2") );
Packit df99a1
  // Open
Packit df99a1
  if (!ycodec_enc)
Packit df99a1
  {
Packit df99a1
    cslice = cserial = cbytes = 0;
Packit df99a1
    ycodec_enc = new Codec::Encode(*ymap);
Packit df99a1
    if (crmap && cbmap)
Packit df99a1
    {
Packit df99a1
      cbcodec_enc = new Codec::Encode(*cbmap);
Packit df99a1
      crcodec_enc = new Codec::Encode(*crmap);
Packit df99a1
    }
Packit df99a1
  }
Packit df99a1
Packit df99a1
  // Adjust cbytes
Packit df99a1
  cbytes += sizeof(struct IW44Image::PrimaryHeader);
Packit df99a1
  if (cserial == 0)
Packit df99a1
    cbytes += sizeof(struct IW44Image::SecondaryHeader) + sizeof(struct IW44Image::TertiaryHeader);
Packit df99a1
  // Prepare zcodec slices
Packit df99a1
  int flag = 1;
Packit df99a1
  int nslices = 0;
Packit df99a1
  GP<ByteStream> gmbs=ByteStream::create();
Packit df99a1
  ByteStream &mbs=*gmbs;
Packit df99a1
  DJVU_PROGRESS_TASK(chunk, "encode pixmap chunk", parm.slices-cslice);
Packit df99a1
  {
Packit df99a1
    float estdb = -1.0;
Packit df99a1
    GP<ZPCodec> gzp=ZPCodec::create(gmbs, true, true);
Packit df99a1
    ZPCodec &zp=*gzp;
Packit df99a1
    while (flag)
Packit df99a1
      {
Packit df99a1
        if (parm.decibels>0  && estdb>=parm.decibels)
Packit df99a1
          break;
Packit df99a1
        if (parm.bytes>0  && mbs.tell()+cbytes>=parm.bytes)
Packit df99a1
          break;
Packit df99a1
        if (parm.slices>0 && nslices+cslice>=parm.slices)
Packit df99a1
          break;
Packit df99a1
        DJVU_PROGRESS_RUN(chunk,(1+nslices-cslice)|0xf);
Packit df99a1
        flag = ycodec_enc->code_slice(zp);
Packit df99a1
        if (flag && parm.decibels>0)
Packit df99a1
          if (ycodec_enc->curband==0 || estdb>=parm.decibels-DECIBEL_PRUNE)
Packit df99a1
            estdb = ycodec_enc->estimate_decibel(db_frac);
Packit df99a1
        if (crcodec_enc && cbcodec_enc && cslice+nslices>=crcb_delay)
Packit df99a1
          {
Packit df99a1
            flag |= cbcodec_enc->code_slice(zp);
Packit df99a1
            flag |= crcodec_enc->code_slice(zp);
Packit df99a1
          }
Packit df99a1
        nslices++;
Packit df99a1
      }
Packit df99a1
  }
Packit df99a1
  // Write primary header
Packit df99a1
  struct IW44Image::PrimaryHeader primary;
Packit df99a1
  primary.serial = cserial;
Packit df99a1
  primary.slices = nslices;
Packit df99a1
  primary.encode(gbs);
Packit df99a1
  // Write secondary header
Packit df99a1
  if (cserial == 0)
Packit df99a1
    {
Packit df99a1
      struct IW44Image::SecondaryHeader secondary;
Packit df99a1
      secondary.major = IWCODEC_MAJOR;
Packit df99a1
      secondary.minor = IWCODEC_MINOR;
Packit df99a1
      if (! (crmap && cbmap))
Packit df99a1
        secondary.major |= 0x80;
Packit df99a1
      secondary.encode(gbs);
Packit df99a1
      struct IW44Image::TertiaryHeader tertiary;
Packit df99a1
      tertiary.xhi = (ymap->iw >> 8) & 0xff;
Packit df99a1
      tertiary.xlo = (ymap->iw >> 0) & 0xff;
Packit df99a1
      tertiary.yhi = (ymap->ih >> 8) & 0xff;
Packit df99a1
      tertiary.ylo = (ymap->ih >> 0) & 0xff;
Packit df99a1
      tertiary.crcbdelay = (crcb_half ? 0x00 : 0x80);
Packit df99a1
      tertiary.crcbdelay |= (crcb_delay>=0 ? crcb_delay : 0x00);
Packit df99a1
      tertiary.encode(gbs);
Packit df99a1
    }
Packit df99a1
  // Write slices
Packit df99a1
  mbs.seek(0);
Packit df99a1
  gbs->copy(mbs);
Packit df99a1
  // Return
Packit df99a1
  cbytes  += mbs.tell();
Packit df99a1
  cslice  += nslices;
Packit df99a1
  cserial += 1;
Packit df99a1
  return flag;
Packit df99a1
}
Packit df99a1
Packit df99a1
// code_slice
Packit df99a1
// -- read/write a slice of datafile
Packit df99a1
Packit df99a1
int
Packit df99a1
IW44Image::Codec::Encode::code_slice(ZPCodec &zp)
Packit df99a1
{
Packit df99a1
  // Check that code_slice can still run
Packit df99a1
  if (curbit < 0)
Packit df99a1
    return 0;
Packit df99a1
  // Perform coding
Packit df99a1
  if (! is_null_slice(curbit, curband))
Packit df99a1
    {
Packit df99a1
      for (int blockno=0; blockno
Packit df99a1
        {
Packit df99a1
          const int fbucket = bandbuckets[curband].start;
Packit df99a1
          const int nbucket = bandbuckets[curband].size;
Packit df99a1
          encode_buckets(zp, curbit, curband, 
Packit df99a1
                         map.blocks[blockno], emap.blocks[blockno], 
Packit df99a1
                         fbucket, nbucket);
Packit df99a1
        }
Packit df99a1
    }
Packit df99a1
  return finish_code_slice(zp);
Packit df99a1
}
Packit df99a1
Packit df99a1
Packit df99a1
Packit df99a1
#ifdef HAVE_NAMESPACES
Packit df99a1
}
Packit df99a1
# ifndef NOT_USING_DJVU_NAMESPACE
Packit df99a1
using namespace DJVU;
Packit df99a1
# endif
Packit df99a1
#endif
Packit df99a1
#endif // NEED_DECODER_ONLY
Packit df99a1