Coverage Report

Created: 2023-12-08 06:53

/src/freeimage-svn/FreeImage/trunk/Source/Quantizers.h
Line
Count
Source (jump to first uncovered line)
1
// =============================================================
2
// Quantizer objects and functions
3
//
4
// Design and implementation by:
5
// - Hervé Drolon <drolon@infonie.fr>
6
// - Carsten Klein (cklein05@users.sourceforge.net)
7
//
8
// This file is part of FreeImage 3
9
//
10
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
11
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
12
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
13
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
14
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
15
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
16
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
17
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
18
// THIS DISCLAIMER.
19
//
20
// Use at your own risk!
21
// =============================================================
22
23
#ifndef FREEIMAGE_QUANTIZER_H
24
#define FREEIMAGE_QUANTIZER_H
25
26
// 
27
////////////////////////////////////////////////////////////////
28
29
#include "FreeImage.h"
30
31
////////////////////////////////////////////////////////////////
32
33
/**
34
  Xiaolin Wu color quantization algorithm
35
*/
36
class WuQuantizer
37
{
38
public:
39
40
typedef struct tagBox {
41
    int r0;      // min value, exclusive
42
    int r1;      // max value, inclusive
43
    int g0;  
44
    int g1;  
45
    int b0;  
46
    int b1;
47
    int vol;
48
} Box;
49
50
protected:
51
    float *gm2;
52
  LONG *wt, *mr, *mg, *mb;
53
  WORD *Qadd;
54
55
  // DIB data
56
  unsigned width, height;
57
  unsigned pitch;
58
  FIBITMAP *m_dib;
59
60
protected:
61
    void Hist3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2, int ReserveSize, RGBQUAD *ReservePalette);
62
  void M3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2);
63
  LONG Vol(Box *cube, LONG *mmt);
64
  LONG Bottom(Box *cube, BYTE dir, LONG *mmt);
65
  LONG Top(Box *cube, BYTE dir, int pos, LONG *mmt);
66
  float Var(Box *cube);
67
  float Maximize(Box *cube, BYTE dir, int first, int last , int *cut,
68
           LONG whole_r, LONG whole_g, LONG whole_b, LONG whole_w);
69
  bool Cut(Box *set1, Box *set2);
70
  void Mark(Box *cube, int label, BYTE *tag);
71
72
public:
73
  // Constructor - Input parameter: DIB 24-bit to be quantized
74
    WuQuantizer(FIBITMAP *dib);
75
  // Destructor
76
  ~WuQuantizer();
77
  // Quantizer - Return value: quantized 8-bit (color palette) DIB
78
  FIBITMAP* Quantize(int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette);
79
};
80
81
82
/**
83
  NEUQUANT Neural-Net quantization algorithm by Anthony Dekker
84
*/
85
86
// ----------------------------------------------------------------
87
// Constant definitions
88
// ----------------------------------------------------------------
89
90
/** number of colours used: 
91
  for 256 colours, fixed arrays need 8kb, plus space for the image
92
*/
93
//static const int netsize = 256;
94
95
/**@name network definitions */
96
//@{
97
//static const int maxnetpos = (netsize - 1);
98
/// bias for colour values
99
static const int netbiasshift = 4;
100
/// no. of learning cycles
101
static const int ncycles = 100;
102
//@}
103
104
/**@name defs for freq and bias */
105
//@{
106
/// bias for fractions
107
static const int intbiasshift = 16;
108
static const int intbias = (((int)1) << intbiasshift);
109
/// gamma = 1024
110
static const int gammashift = 10;
111
// static const int gamma = (((int)1) << gammashift);
112
/// beta = 1 / 1024
113
static const int betashift = 10;
114
static const int beta = (intbias >> betashift);
115
static const int betagamma = (intbias << (gammashift-betashift));
116
//@}
117
118
/**@name defs for decreasing radius factor */
119
//@{
120
/// for 256 cols, radius starts
121
//static const int initrad = (netsize >> 3);
122
/// at 32.0 biased by 6 bits
123
static const int radiusbiasshift = 6;
124
static const int radiusbias = (((int)1) << radiusbiasshift);
125
/// and decreases by a 
126
//static const int initradius = (initrad * radiusbias);
127
// factor of 1/30 each cycle
128
static const int radiusdec = 30;
129
//@}
130
131
/**@name defs for decreasing alpha factor */
132
//@{
133
/// alpha starts at 1.0
134
static const int alphabiasshift = 10;
135
static const int initalpha = (((int)1) << alphabiasshift);
136
//@}
137
138
/**@name radbias and alpharadbias used for radpower calculation */
139
//@{
140
static const int radbiasshift = 8;
141
static const int radbias = (((int)1) << radbiasshift);
142
static const int alpharadbshift = (alphabiasshift+radbiasshift);
143
static const int alpharadbias = (((int)1) << alpharadbshift); 
144
//@}
145
146
class NNQuantizer
147
{
148
protected:
149
  /**@name image parameters */
150
  //@{
151
  /// pointer to input dib
152
  FIBITMAP *dib_ptr;
153
  /// image width
154
  int img_width;
155
  /// image height
156
  int img_height;
157
  /// image line length
158
  int img_line;
159
  //@}
160
161
  /**@name network parameters */
162
  //@{
163
164
  int netsize, maxnetpos, initrad, initradius;
165
166
  /// BGRc
167
  typedef int pixel[4];
168
  /// the network itself
169
  pixel *network;
170
171
  /// for network lookup - really 256
172
  int netindex[256];
173
174
  /// bias array for learning
175
  int *bias;
176
  /// freq array for learning
177
  int *freq;
178
  /// radpower for precomputation
179
  int *radpower;
180
  //@}
181
182
protected:
183
  /// Initialise network in range (0,0,0) to (255,255,255) and set parameters
184
  void initnet(); 
185
186
  /// Unbias network to give byte values 0..255 and record position i to prepare for sort
187
  void unbiasnet();
188
189
  /// Insertion sort of network and building of netindex[0..255] (to do after unbias)
190
  void inxbuild();
191
192
  /// Search for BGR values 0..255 (after net is unbiased) and return colour index
193
  int inxsearch(int b, int g, int r);
194
195
  /// Search for biased BGR values
196
  int contest(int b, int g, int r);
197
  
198
  /// Move neuron i towards biased (b,g,r) by factor alpha
199
  void altersingle(int alpha, int i, int b, int g, int r);
200
201
  /// Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|]
202
  void alterneigh(int rad, int i, int b, int g, int r);
203
204
  /** Main Learning Loop
205
  @param sampling_factor sampling factor in [1..30]
206
  */
207
  void learn(int sampling_factor);
208
209
  /// Get a pixel sample at position pos. Handle 4-byte boundary alignment.
210
  void getSample(long pos, int *b, int *g, int *r);
211
212
213
public:
214
  /// Constructor
215
  NNQuantizer(int PaletteSize);
216
217
  /// Destructor
218
  ~NNQuantizer();
219
220
  /** Quantizer
221
  @param dib input 24-bit dib to be quantized
222
  @param sampling a sampling factor in range 1..30. 
223
  1 => slower (but better), 30 => faster. Default value is 1
224
  @return returns the quantized 8-bit (color palette) DIB
225
  */
226
  FIBITMAP* Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette, int sampling = 1);
227
228
};
229
230
/**
231
 * LFPQUANT - Lossless Fast Pseudo-Quantization Algorithm
232
 *
233
 * The Lossless Fast Pseudo-Quantization algorithm is no real quantization
234
 * algorithm, since it makes no attempt to create a palette, that is suitable
235
 * for all colors of the 24-bit source image. However, it provides very fast
236
 * conversions from 24-bit to 8-bit images, if the number of distinct colors
237
 * in the source image is not greater than the desired palette size. If the
238
 * number of colors in the source image is exceeded, the Quantize method of
239
 * this implementation stops the process and returns NULL.
240
 *
241
 * This implementation uses a very fast hash map implementation to collect
242
 * the source image's colors. It turned out that a customized implementation
243
 * of a hash table with open addressing (using linear probing) provides the
244
 * best performance. The hash table has 512 entries, which prevents the load
245
 * factor to exceed 0.5 as we have 256 entries at most. Each entry consumes
246
 * 64 bits, so the whole hash table takes 4KB of memory.
247
 *
248
 * For large images, the LFPQuantizer is typically up to three times faster
249
 * than the WuQuantizer.
250
 */
251
class LFPQuantizer {
252
public:
253
  /** Constructor */
254
  LFPQuantizer(unsigned PaletteSize);
255
256
  /** Destructor */
257
  ~LFPQuantizer();
258
259
  /**
260
   * Quantizer
261
   * @param dib input 24-bit or 32-bit bitmap to be quantized
262
   * @return returns the pseudo-quantized 8-bit bitmap
263
   */
264
  FIBITMAP* Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette);
265
266
protected:
267
  /** The maximum size of a palette. */
268
  static const unsigned MAX_SIZE = 256;
269
270
  /**
271
   * The size of the hash table. Must be a power of 2. By sizing it
272
   * MAX_SIZE * 2, we ensure the load factor not to exceed 0.5 at any
273
   * time, since we will have MAX_SIZE entries at most.
274
   */
275
  static const unsigned MAP_SIZE = MAX_SIZE * 2;
276
277
  /**
278
   * With open addressing we need a special value for empty buckets.
279
   * Both entry.color and entry.index are 0xFFFFFFFF for an empty
280
   * entry.
281
   */
282
  static const unsigned EMPTY_BUCKET = 0xFFFFFFFF;
283
284
  /**
285
   * This structure defines a single entry in the hash table. We use
286
   * color as the entry's key.
287
   */
288
  typedef struct MapEntry {
289
    unsigned color;
290
    unsigned index;
291
  } MapEntry;
292
293
  /** The hash table. */
294
  MapEntry *m_map;
295
296
  /**
297
   * The current size of the newly created palette. Since the provided
298
   * reserve palette could contain duplicates, this is not necessarily
299
   * the number of entries in the hash table. Initialized to zero.
300
   */
301
  unsigned m_size;
302
303
  /**
304
   * The desired maximum number of entries in the newly created palette.
305
   * If m_size exceeds this value, the palette is full and the
306
   * quantization process is stopped. Initialized to the desired
307
   * palette size.
308
   */
309
  unsigned m_limit;
310
311
  /**
312
   *  The palette index used for the next color added. Initialized to
313
   *  zero (the reserve palette is put to the end of the palette).
314
   */
315
  unsigned m_index;
316
317
  /**
318
   * Ensures that hash codes that differ only by constant multiples
319
   * at each bit position have a bounded number of collisions.
320
   * @param h the initial (aka raw) hash code
321
   * @return the modified hash code
322
   */
323
0
  static inline unsigned hash(unsigned h) {
324
0
    h ^= (h >> 20) ^ (h >> 12);
325
0
    return h ^ (h >> 7) ^ (h >> 4);
326
0
  }
327
328
  /**
329
   * Returns the palette index of the specified color. Tries to put the
330
   * color into the map, if it's not already present in the map. In that
331
   * case, a new index is used for the color. Returns -1, if adding the
332
   * color would exceed the desired maximum number of colors in the
333
   * palette.
334
   * @param color the color to get the index from
335
   * @return the palette index of the specified color or -1, if there
336
   * is no space left in the palette
337
   */
338
  int GetIndexForColor(unsigned color);
339
340
  /**
341
   * Adds the specified number of entries of the specified reserve
342
   * palette to the newly created palette.
343
   * @param *palette a pointer to the reserve palette to copy from
344
   * @param size the number of entries to copy
345
   */
346
  void AddReservePalette(const void *palette, unsigned size);
347
348
  /**
349
   * Copies the newly created palette into the specified destination
350
   * palettte. Although unused palette entries are not overwritten in
351
   * the destination palette, it is assumed to have space for at
352
   * least 256 entries.
353
   * @param palette a pointer to the destination palette
354
   */
355
  void WritePalette(void *palette);
356
357
};
358
359
#endif // FREEIMAGE_QUANTIZER_H