// WOUTER // - made it compile as C++ // - fixed /0 bug with small image sizes /* NeuQuant Neural-Net Quantization Algorithm * ------------------------------------------ * * Copyright (c) 1994 Anthony Dekker * * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. * See "Kohonen neural networks for optimal colour quantization" * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367. * for a discussion of the algorithm. * See also http://www.acm.org/~dekker/NEUQUANT.HTML * * Any party obtaining a copy of these files from the author, directly or * indirectly, is granted, free of charge, a full and unrestricted irrevocable, * world-wide, paid up, royalty-free, nonexclusive right and license to deal * in this software and documentation files (the "Software"), including without * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons who receive * copies from any such party to do so, with the only requirement being * that this copyright notice remain intact. */ #include "neuquant.h" #include /* Network Definitions ------------------- */ #define maxnetpos (netsize-1) #define netbiasshift 4 /* bias for colour values */ #define ncycles 100 /* no. of learning cycles */ /* defs for freq and bias */ #define intbiasshift 16 /* bias for fractions */ #define intbias (((int) 1)<>betashift) /* beta = 1/1024 */ #define betagamma (intbias<<(gammashift-betashift)) /* defs for decreasing radius factor */ #define initrad (netsize>>3) /* for 256 cols, radius starts */ #define radiusbiasshift 6 /* at 32.0 biased by 6 bits */ #define radiusbias (((int) 1)<>= netbiasshift; */ /* Fix based on bug report by Juergen Weigert jw@suse.de */ temp = (network[i][j] + (1 << (netbiasshift - 1))) >> netbiasshift; if (temp > 255) temp = 255; network[i][j] = temp; } network[i][3] = i; /* record colour no */ } } /* Output colour map ----------------- */ void writecolourmap(unsigned char *p) { int i,j; for (j=0; j>1; for (j=previouscol+1; j>1; for (j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; /* really 256 */ } /* Search for BGR values 0..255 (after net is unbiased) and return colour index ---------------------------------------------------------------------------- */ int inxsearch(int b, int g, int r) { register int i,j,dist,a,bestd; register int *p; int best; bestd = 1000; /* biggest possible dist is 256*3 */ best = -1; i = netindex[g]; /* index on g */ j = i-1; /* start at netindex[g] and work outwards */ while ((i=0)) { if (i= bestd) i = netsize; /* stop iter */ else { i++; if (dist<0) dist = -dist; a = p[0] - b; if (a<0) a = -a; dist += a; if (dist=0) { p = network[j]; dist = g - p[1]; /* inx key - reverse dif */ if (dist >= bestd) j = -1; /* stop iter */ else { j--; if (dist<0) dist = -dist; a = p[0] - b; if (a<0) a = -a; dist += a; if (dist>(intbiasshift-netbiasshift)); if (biasdist> betashift); *f++ -= betafreq; *p++ += (betafreq<netsize) hi=netsize; j = i+1; k = i-1; q = radpower; while ((jlo)) { a = (*(++q)); if (jlo) { p = network[k]; *p -= (a*(*p - b)) / alpharadbias; p++; *p -= (a*(*p - g)) / alpharadbias; p++; *p -= (a*(*p - r)) / alpharadbias; k--; } } } /* Main Learning Loop ------------------ */ void learn() { register int i,j,b,g,r; int radius,rad,alpha,step,delta,samplepixels; register unsigned char *p; unsigned char *lim; alphadec = 30 + ((samplefac-1)/3); p = thepicture; lim = thepicture + lengthcount; samplepixels = lengthcount/(3*samplefac); //if(samplepixels=ncycles); delta = samplepixels/ncycles; if(!delta) delta = 1; // WOUTER: I guess noone ever tested with small images (mipmaps) alpha = initalpha; radius = initradius; rad = radius >> radiusbiasshift; if (rad <= 1) rad = 0; for (i=0; i= lim) p -= lengthcount; // wouter: was: if (p >= lim) i++; if (i%delta == 0) { alpha -= alpha / alphadec; radius -= radius / radiusdec; rad = radius >> radiusbiasshift; if (rad <= 1) rad = 0; for (j=0; j