summaryrefslogtreecommitdiff
path: root/libs/freeimage/src/Quantizers.h
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-01-26 17:38:31 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-01-26 17:38:31 +0300
commitdea9c030340e50324eba97c72a27c151bed12e1c (patch)
tree6fc156f40f52a9fc6e6b29e60001959477ee1a5e /libs/freeimage/src/Quantizers.h
parentc6e8f8223cab9d799593b7b2cfa22134aa9745d6 (diff)
AdvaImg:
- freeimage extracted to the separate library; - FI_INTERFACE removed, all references to it are replaced with direct calls of FreeImage_* functions; - unified project for AdvaImg
Diffstat (limited to 'libs/freeimage/src/Quantizers.h')
-rw-r--r--libs/freeimage/src/Quantizers.h354
1 files changed, 354 insertions, 0 deletions
diff --git a/libs/freeimage/src/Quantizers.h b/libs/freeimage/src/Quantizers.h
new file mode 100644
index 0000000000..ad7ee57b9b
--- /dev/null
+++ b/libs/freeimage/src/Quantizers.h
@@ -0,0 +1,354 @@
+// =============================================================
+// Quantizer objects and functions
+//
+// Design and implementation by:
+// - Hervé Drolon <drolon@infonie.fr>
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// 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);
+
+};
+
+/**
+ * LFPQUANT - Lossless Fast Pseudo-Quantization Algorithm
+ *
+ * The Lossless Fast Pseudo-Quantization algorithm is no real quantization
+ * algorithm, since it makes no attempt to create a palette, that is suitable
+ * for all colors of the 24-bit source image. However, it provides very fast
+ * conversions from 24-bit to 8-bit images, if the number of distinct colors
+ * in the source image is not greater than the desired palette size. If the
+ * number of colors in the source image is exceeded, the Quantize method of
+ * this implementation stops the process and returns NULL.
+ *
+ * This implementation uses a very fast hash map implementation to collect
+ * the source image's colors. It turned out that a customized implementation
+ * of a hash table with open addressing (using linear probing) provides the
+ * best performance. The hash table has 512 entries, which prevents the load
+ * factor to exceed 0.5 as we have 256 entries at most. Each entry consumes
+ * 64 bits, so the whole hash table takes 4KB of memory.
+ *
+ * For large images, the LFPQuantizer is typically up to three times faster
+ * than the WuQuantizer.
+ */
+class LFPQuantizer {
+public:
+ /** Constructor */
+ LFPQuantizer(unsigned PaletteSize);
+
+ /** Destructor */
+ ~LFPQuantizer();
+
+ /**
+ * Quantizer
+ * @param dib input 24-bit or 32-bit bitmap to be quantized
+ * @return returns the pseudo-quantized 8-bit bitmap
+ */
+ FIBITMAP* Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette);
+
+protected:
+ /** The maximum size of a palette. */
+ static const unsigned MAX_SIZE = 256;
+
+ /**
+ * The size of the hash table. Must be a power of 2. By sizing it
+ * MAX_SIZE * 2, we ensure the load factor not to exceed 0.5 at any
+ * time, since we will have MAX_SIZE entries at most.
+ */
+ static const unsigned MAP_SIZE = MAX_SIZE * 2;
+
+ /**
+ * With open addressing we need a special value for empty buckets.
+ * Both entry.color and entry.index are 0xFFFFFFFF for an empty
+ * entry.
+ */
+ static const unsigned EMPTY_BUCKET = 0xFFFFFFFF;
+
+ /**
+ * This structure defines a single entry in the hash table. We use
+ * color as the entry's key.
+ */
+ typedef struct MapEntry {
+ unsigned color;
+ unsigned index;
+ } MapEntry;
+
+ /** The hash table. */
+ MapEntry *m_map;
+
+ /**
+ * The current size of the newly created palette. Since the provided
+ * reserve palette could contain duplicates, this is not necessarily
+ * the number of entries in the hash table. Initialized to zero.
+ */
+ unsigned m_size;
+
+ /**
+ * The desired maximum number of entries in the newly created palette.
+ * If m_size exceeds this value, the palette is full and the
+ * quantization process is stopped. Initialized to the desired
+ * palette size.
+ */
+ unsigned m_limit;
+
+ /**
+ * The palette index used for the next color added. Initialized to
+ * zero (the reserve palette is put to the end of the palette).
+ */
+ unsigned m_index;
+
+ /**
+ * Ensures that hash codes that differ only by constant multiples
+ * at each bit position have a bounded number of collisions.
+ * @param h the initial (aka raw) hash code
+ * @return the modified hash code
+ */
+ static inline unsigned hash(unsigned h) {
+ h ^= (h >> 20) ^ (h >> 12);
+ return h ^ (h >> 7) ^ (h >> 4);
+ }
+
+ /**
+ * Returns the palette index of the specified color. Tries to put the
+ * color into the map, if it's not already present in the map. In that
+ * case, a new index is used for the color. Returns -1, if adding the
+ * color would exceed the desired maximum number of colors in the
+ * palette.
+ * @param color the color to get the index from
+ * @return the palette index of the specified color or -1, if there
+ * is no space left in the palette
+ */
+ int GetIndexForColor(unsigned color);
+
+ /**
+ * Adds the specified number of entries of the specified reserve
+ * palette to the newly created palette.
+ * @param *palette a pointer to the reserve palette to copy from
+ * @param size the number of entries to copy
+ */
+ void AddReservePalette(const void *palette, unsigned size);
+
+ /**
+ * Copies the newly created palette into the specified destination
+ * palettte. Although unused palette entries are not overwritten in
+ * the destination palette, it is assumed to have space for at
+ * least 256 entries.
+ * @param palette a pointer to the destination palette
+ */
+ void WritePalette(void *palette);
+
+};