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
|
// =============================================================
// Quantizer objects and functions
//
// Design and implementation by:
// - Hervé Drolon <drolon@infonie.fr>
//
// This file is part of FreeImage 3
//
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
// THIS DISCLAIMER.
//
// Use at your own risk!
// =============================================================
//
////////////////////////////////////////////////////////////////
#include "FreeImage.h"
////////////////////////////////////////////////////////////////
/**
Xiaolin Wu color quantization algorithm
*/
class WuQuantizer
{
public:
typedef struct tagBox {
int r0; // min value, exclusive
int r1; // max value, inclusive
int g0;
int g1;
int b0;
int b1;
int vol;
} Box;
protected:
float *gm2;
LONG *wt, *mr, *mg, *mb;
WORD *Qadd;
// DIB data
unsigned width, height;
unsigned pitch;
FIBITMAP *m_dib;
protected:
void Hist3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2, int ReserveSize, RGBQUAD *ReservePalette);
void M3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2);
LONG Vol(Box *cube, LONG *mmt);
LONG Bottom(Box *cube, BYTE dir, LONG *mmt);
LONG Top(Box *cube, BYTE dir, int pos, LONG *mmt);
float Var(Box *cube);
float Maximize(Box *cube, BYTE dir, int first, int last , int *cut,
LONG whole_r, LONG whole_g, LONG whole_b, LONG whole_w);
bool Cut(Box *set1, Box *set2);
void Mark(Box *cube, int label, BYTE *tag);
public:
// Constructor - Input parameter: DIB 24-bit to be quantized
WuQuantizer(FIBITMAP *dib);
// Destructor
~WuQuantizer();
// Quantizer - Return value: quantized 8-bit (color palette) DIB
FIBITMAP* Quantize(int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette);
};
/**
NEUQUANT Neural-Net quantization algorithm by Anthony Dekker
*/
// ----------------------------------------------------------------
// Constant definitions
// ----------------------------------------------------------------
/** number of colours used:
for 256 colours, fixed arrays need 8kb, plus space for the image
*/
//static const int netsize = 256;
/**@name network definitions */
//@{
//static const int maxnetpos = (netsize - 1);
/// bias for colour values
static const int netbiasshift = 4;
/// no. of learning cycles
static const int ncycles = 100;
//@}
/**@name defs for freq and bias */
//@{
/// bias for fractions
static const int intbiasshift = 16;
static const int intbias = (((int)1) << intbiasshift);
/// gamma = 1024
static const int gammashift = 10;
// static const int gamma = (((int)1) << gammashift);
/// beta = 1 / 1024
static const int betashift = 10;
static const int beta = (intbias >> betashift);
static const int betagamma = (intbias << (gammashift-betashift));
//@}
/**@name defs for decreasing radius factor */
//@{
/// for 256 cols, radius starts
//static const int initrad = (netsize >> 3);
/// at 32.0 biased by 6 bits
static const int radiusbiasshift = 6;
static const int radiusbias = (((int)1) << radiusbiasshift);
/// and decreases by a
//static const int initradius = (initrad * radiusbias);
// factor of 1/30 each cycle
static const int radiusdec = 30;
//@}
/**@name defs for decreasing alpha factor */
//@{
/// alpha starts at 1.0
static const int alphabiasshift = 10;
static const int initalpha = (((int)1) << alphabiasshift);
//@}
/**@name radbias and alpharadbias used for radpower calculation */
//@{
static const int radbiasshift = 8;
static const int radbias = (((int)1) << radbiasshift);
static const int alpharadbshift = (alphabiasshift+radbiasshift);
static const int alpharadbias = (((int)1) << alpharadbshift);
//@}
class NNQuantizer
{
protected:
/**@name image parameters */
//@{
/// pointer to input dib
FIBITMAP *dib_ptr;
/// image width
int img_width;
/// image height
int img_height;
/// image line length
int img_line;
//@}
/**@name network parameters */
//@{
int netsize, maxnetpos, initrad, initradius;
/// BGRc
typedef int pixel[4];
/// the network itself
pixel *network;
/// for network lookup - really 256
int netindex[256];
/// bias array for learning
int *bias;
/// freq array for learning
int *freq;
/// radpower for precomputation
int *radpower;
//@}
protected:
/// Initialise network in range (0,0,0) to (255,255,255) and set parameters
void initnet();
/// Unbias network to give byte values 0..255 and record position i to prepare for sort
void unbiasnet();
/// Insertion sort of network and building of netindex[0..255] (to do after unbias)
void inxbuild();
/// Search for BGR values 0..255 (after net is unbiased) and return colour index
int inxsearch(int b, int g, int r);
/// Search for biased BGR values
int contest(int b, int g, int r);
/// Move neuron i towards biased (b,g,r) by factor alpha
void altersingle(int alpha, int i, int b, int g, int r);
/// Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|]
void alterneigh(int rad, int i, int b, int g, int r);
/** Main Learning Loop
@param sampling_factor sampling factor in [1..30]
*/
void learn(int sampling_factor);
/// Get a pixel sample at position pos. Handle 4-byte boundary alignment.
void getSample(long pos, int *b, int *g, int *r);
public:
/// Constructor
NNQuantizer(int PaletteSize);
/// Destructor
~NNQuantizer();
/** Quantizer
@param dib input 24-bit dib to be quantized
@param sampling a sampling factor in range 1..30.
1 => slower (but better), 30 => faster. Default value is 1
@return returns the quantized 8-bit (color palette) DIB
*/
FIBITMAP* Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette, int sampling = 1);
};
|