summaryrefslogtreecommitdiffstats
path: root/kviewshell/plugins/djvu/libdjvu/DjVuPalette.h
blob: 7f9884f1d3fca63611784420c91c71fbea2e389e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
//C-  -*- C++ -*-
//C- -------------------------------------------------------------------
//C- DjVuLibre-3.5
//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
//C- Copyright (c) 2001  AT&T
//C-
//C- This software is subject to, and may be distributed under, the
//C- GNU General Public License, Version 2. The license should have
//C- accompanied the software or you may obtain a copy of the license
//C- from the Free Software Foundation at http://www.fsf.org .
//C-
//C- This program is distributed in the hope that it will be useful,
//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//C- GNU General Public License for more details.
//C- 
//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
//C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech 
//C- Software authorized us to replace the original DjVu(r) Reference 
//C- Library notice by the following text (see doc/lizard2002.djvu):
//C-
//C-  ------------------------------------------------------------------
//C- | DjVu (r) Reference Library (v. 3.5)
//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
//C- | The DjVu Reference Library is protected by U.S. Pat. No.
//C- | 6,058,214 and patents pending.
//C- |
//C- | This software is subject to, and may be distributed under, the
//C- | GNU General Public License, Version 2. The license should have
//C- | accompanied the software or you may obtain a copy of the license
//C- | from the Free Software Foundation at http://www.fsf.org .
//C- |
//C- | The computer code originally released by LizardTech under this
//C- | license and unmodified by other parties is deemed "the LIZARDTECH
//C- | ORIGINAL CODE."  Subject to any third party intellectual property
//C- | claims, LizardTech grants recipient a worldwide, royalty-free, 
//C- | non-exclusive license to make, use, sell, or otherwise dispose of 
//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the 
//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU 
//C- | General Public License.   This grant only confers the right to 
//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to 
//C- | the extent such infringement is reasonably necessary to enable 
//C- | recipient to make, have made, practice, sell, or otherwise dispose 
//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to 
//C- | any greater extent that may be necessary to utilize further 
//C- | modifications or combinations.
//C- |
//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
//C- +------------------------------------------------------------------
// 
// $Id: DjVuPalette.h,v 1.9 2003/11/07 22:08:21 leonb Exp $
// $Name: release_3_5_15 $

#ifndef _DJVUPALETTE_H_
#define _DJVUPALETTE_H_
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if NEED_GNUG_PRAGMAS
# pragma interface
#endif


#include "GContainer.h"
#include "GPixmap.h"
#include <string.h>


#ifdef HAVE_NAMESPACES
namespace DJVU {
# ifdef NOT_DEFINED // Just to fool emacs c++ mode
}
#endif
#endif


/** @name DjVuPalette.h
    Files #"DjVuPalette.h"# and #"DjVuPalette.cpp"# implement a single class
    \Ref{DjVuPalette} which provides facilities for computing optimal color
    palettes, coding color palettes, and coding sequences of color indices.
    @memo 
    DjVuPalette header file
    @version 
    #$Id: DjVuPalette.h,v 1.9 2003/11/07 22:08:21 leonb Exp $#
    @author: 
    L\'eon Bottou <leonb@research.att.com> */
//@{


/** Computing and coding color palettes and index arrays.
    This class provides facilities for computing optimal color palettes,
    coding color palettes, and coding sequences of color indices.
    
    {\bf Creating a color palette} -- The recipe for creating a color palette
    consists in (a) creating a DjVuPalette object, (b) constructing a color
    histogram using \Ref{histogram_add}, and (c) calling function
    \Ref{compute_palette}.

    {\bf Accessing the color palette} -- Conversion between colors and color
    palette indices is easily achieved with \Ref{color_to_index} and
    \Ref{index_to_color}.  There are also functions for computing a palette
    and quantizing a complete pixmap.

    {\bf Sequences of color indices} -- The DjVuPalette object also contains
    an array \Ref{colordata} optionally containing a sequence of color
    indices.  This array will be encoded and decoded by functions \Ref{encode}
    and \Ref{decode}.  This feature simplifies the implementation of the ``one
    color per symbol'' model in DjVu.

    {\bf Coding color palettes and color indices} -- Two functions
    \Ref{encode} and \Ref{decode} are provided for coding the color palette
    and the array of color indices when appropriate.  */
#ifdef _WIN32_WCE_EMULATION         // Work around odd behavior under WCE Emulation
#define CALLINGCONVENTION __cdecl
#else
#define CALLINGCONVENTION  /* */
#endif

class DjVuPalette : public GPEnabled
{
protected:
  DjVuPalette(void);
public:
  /// Generic creator
  static GP<DjVuPalette> create(void) {return new DjVuPalette();}

  /// Non-virtual destructor
  ~DjVuPalette();
  // COPY
  DjVuPalette(const DjVuPalette &ref);
  DjVuPalette& operator=(const DjVuPalette &ref);
  // PALETTE COMPUTATION
  /** Resets the color histogram to zero. */
  void histogram_clear();
  /** Adds the color specified by #p# to the histogram.
      Argument #weight# represent the number of pixels with this color. */
  void histogram_add(const GPixel &p, int weight);
  /** Adds the color specified by the triple #bgr# to the histogram.
      Argument #weight# represent the number of pixels with this color. */
  void histogram_add(const unsigned char *bgr, int weight);
  /** Adds the color specified by the weighted triple #bgr# to the histogram.
      Argument #weight# represent the number of pixels with this color.  This
      function will compute the actual color by dividing the elements of the
      #bgr# array by #weight# and then use the unnormalized values to compute
      the average color per bucket.  This is all a way to avoid excessive loss
      of accuracy. */
  void histogram_norm_and_add(const int *bgr, int weight);
  /** Computes an optimal palette for representing an image where colors
      appear according to the histogram.  Argument #maxcolors# is the maximum
      number of colors allowed in the palette (up to 1024).  Argument
      #minboxsize# controls the minimal size of the color cube area affected
      to a color palette entry.  Returns the index of the dominant color. */
  int compute_palette(int maxcolors, int minboxsize=0);
  /** Computes the optimal palette for pixmap #pm#.  This function builds the
      histogram for pixmap #pm# and computes the optimal palette using
      \Ref{compute_palette}. */
  int compute_pixmap_palette(const GPixmap &pm, int ncolors, int minboxsize=0);
  // CONVERSION
  /** Returns the number of colors in the palette. */
  int size() const;
  /** Returns the best palette index for representing color #p#. */
  int color_to_index(const GPixel &p);
  /** Returns the best palette index for representing color #bgr#. */
  int color_to_index(const unsigned char *bgr);
  /** Overwrites #p# with the color located at position #index# in the palette. */
  void index_to_color(int index, GPixel &p) const;
  /** Overwrites #rgb[0..3]# with the color located at 
      position #index# in the palette. */
  void index_to_color(int index, unsigned char *bgr) const;
  /** Quantizes pixmap #pm#. All pixels are replaced by their closest
      approximation available in the palette. */
  void quantize(GPixmap &pm);
  /** Calls \Ref{compute_pixmap_palette} and \Ref{quantize}. */
  int compute_palette_and_quantize(GPixmap &pm, int maxcolors, int minboxsize=0);
  // COLOR CORRECTION
  /** Applies a luminance gamma correction factor of #corr# to the palette
      entries.  Values greater than #1.0# make the image brighter.  Values
      smaller than #1.0# make the image darker.  The documentation of program
      \Ref{ppmcoco} explains how to properly use this function. */
  void color_correct(double corr);
  // COLOR INDEX DATA
  /** Contains an optional sequence of color indices. 
      Function \Ref{encode} and \Ref{decode} also encode and decode this
      sequence when such a sequence is provided. */
  GTArray<short> colordata;
  /** Returns colors from the color index sequence.  Pixel #out# is
      overwritten with the color corresponding to the #nth# element of the
      color sequence \Ref{colordata}. */
  void get_color(int nth, GPixel &out) const;
  // CODING
  /** Writes the palette colors.  This function writes each palette color as a
      RGB triple into bytestream #bs#. */
  void encode_rgb_entries(ByteStream &bs) const;
  /** Reads palette colors.  This function initializes the palette colors by
      reading #palettesize# RGB triples from bytestream #bs#. */
  void decode_rgb_entries(ByteStream &bs, const int palettesize);
  /** Encodes the palette and the color index sequence. This function encodes
      the a version byte, the palette size, the palette colors and the color
      index sequence into bytestream #bs#.  Note that the color histogram is
      never saved. */
  void encode(GP<ByteStream> bs) const;
  /** Initializes the object by reading data from bytestream #bs#.  This
      function reads a version byte, the palette size, the palette and the
      color index sequence from bytestream #bs#.  Note that the color
      histogram is never saved. */
  void decode(GP<ByteStream> bs);

private:
  // Histogram
  int mask;
  GMap<int,int> *hist;
  // Quantization data
  struct PColor { unsigned char p[4]; };
  GTArray<PColor> palette;
  GMap<int,int> *pmap;
  // Helpers
  void allocate_hist();
  void allocate_pmap();
  static int CALLINGCONVENTION bcomp (const void*, const void*);
  static int CALLINGCONVENTION gcomp (const void*, const void*);
  static int CALLINGCONVENTION rcomp (const void*, const void*);
  static int CALLINGCONVENTION lcomp (const void*, const void*);
  int color_to_index_slow(const unsigned char *bgr);
private: // dummy functions
  static void encode(ByteStream *);
  static void decode(ByteStream *);
};


//@}

// ------------ INLINES


inline void 
DjVuPalette::histogram_clear()
{
  delete hist;
  hist = 0;
  mask = 0;
}

inline void 
DjVuPalette::histogram_add(const unsigned char *bgr, int weight)
{
  if (weight > 0)
    {
      if (!hist || hist->size()>=0x4000) 
        allocate_hist();
      int key = (bgr[0]<<16)|(bgr[1]<<8)|(bgr[2])|(mask);
      (*hist)[key] += weight;
    }
}  

inline void 
DjVuPalette::histogram_add(const GPixel &p, int weight)
{
  histogram_add(&p.b, weight);
}

inline void 
DjVuPalette::histogram_norm_and_add(const int *bgr, int weight)
{
  if (weight > 0)
    {
      int p0 = bgr[0]/weight; if (p0>255) p0=255;
      int p1 = bgr[1]/weight; if (p1>255) p1=255;
      int p2 = bgr[2]/weight; if (p2>255) p2=255;
      if (!hist || hist->size()>=0x4000) 
        allocate_hist();
      int key = (p0<<16)|(p1<<8)|(p2)|(mask);
      (*hist)[key] += weight;
    }
}

inline int
DjVuPalette::size() const
{
  return palette.size();
}

inline int 
DjVuPalette::color_to_index(const unsigned char *bgr)
{
  if (! pmap)
    allocate_pmap();
  int key = (bgr[0]<<16)|(bgr[1]<<8)|(bgr[2]);
  GPosition p = pmap->contains(key);
  if ( p)
    return (*pmap)[p];
  return color_to_index_slow(bgr);
}

inline int 
DjVuPalette::color_to_index(const GPixel &p)
{
  return color_to_index(&p.b);
}

inline void 
DjVuPalette::index_to_color(int index, unsigned char *bgr) const
{
  const PColor &color = palette[index];
  bgr[0] = color.p[0];
  bgr[1] = color.p[1];
  bgr[2] = color.p[2];
}

inline void 
DjVuPalette::index_to_color(int index, GPixel &p) const
{
  index_to_color(index, &p.b);
}

inline void
DjVuPalette::get_color(int nth, GPixel &p) const
{
  index_to_color(colordata[nth], p);
}



// ------------ THE END

#ifdef HAVE_NAMESPACES
}
# ifndef NOT_USING_DJVU_NAMESPACE
using namespace DJVU;
# endif
#endif
#endif