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);
};
|