|
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 |
|