org.freehep.graphicsio.gif.NeuQuant Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of freehep-graphicsio Show documentation
Show all versions of freehep-graphicsio Show documentation
FreeHEP GraphicsIO Base Library
package org.freehep.graphicsio.gif;
/* 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.
*/
public class NeuQuant {
public static final int ncycles = 100; // no. of learning cycles
public static final int netsize = 255; // number of colours used
public static final int specials = 3; // number of reserved colours used
public static final int bgColour = specials-1; // reserved background colour
public static final int cutnetsize = netsize - specials;
public static final int maxnetpos = netsize-1;
public static final int initrad = netsize/8; // for 256 cols, radius starts at 32
public static final int radiusbiasshift = 6;
public static final int radiusbias = 1 << radiusbiasshift;
public static final int initBiasRadius = initrad*radiusbias;
public static final int radiusdec = 30; // factor of 1/30 each cycle
public static final int alphabiasshift = 10; // alpha starts at 1
public static final int initalpha = 1< 30) throw new RuntimeException ("Sample must be 1..30");
samplefac = sample;
setPixels (pixels);
setUpArrays ();
}
public int getColorCount () {
return netsize;
}
public int[] getColorMap() {
// keep entry 0 free for transparent color
int[] c = new int[netsize+1];
c[0] = 0x00000000;
for (int i=0; inetsize) hi=netsize;
int j = i+1;
int k = i-1;
int q = 0;
while ((jlo)) {
double a = (alpha * (rad*rad - q*q)) / (rad*rad);
q ++;
if (jlo) {
double [] p = network[k];
p[0] -= (a*(p[0] - b));
p[1] -= (a*(p[1] - g));
p[2] -= (a*(p[2] - r));
k--;
}
}
}
private int contest (double b, double g, double r) { // Search for biased BGR values
// finds closest neuron (min dist) and updates freq
// finds best neuron (min dist-bias) and returns position
// for frequently chosen neurons, freq[i] is high and bias[i] is negative
// bias[i] = gamma*((1/netsize)-freq[i])
double bestd = Float.MAX_VALUE;
double bestbiasd = bestd;
int bestpos = -1;
int bestbiaspos = bestpos;
for (int i=specials; i> radiusbiasshift;
if (rad <= 1) rad = 0;
// System.err.println("beginning 1D learning: samplepixels=" + samplepixels + " rad=" + rad);
int step = 0;
int pos = 0;
if ((lengthcount%prime1) != 0) step = prime1;
else {
if ((lengthcount%prime2) !=0) step = prime2;
else {
if ((lengthcount%prime3) !=0) step = prime3;
else step = prime4;
}
}
i = 0;
while (i < samplepixels) {
int p = pixels [pos / pixels[0].length][pos % pixels[0].length];
int red = (p >> 16) & 0xff;
int green = (p >> 8) & 0xff;
int blue = (p ) & 0xff;
double b = blue;
double g = green;
double r = red;
if (i == 0) { // remember background colour
network [bgColour] [0] = b;
network [bgColour] [1] = g;
network [bgColour] [2] = r;
}
int j = specialFind (b, g, r);
j = j < 0 ? contest (b, g, r) : j;
if (j >= specials) { // don't learn for specials
double a = (1.0 * alpha) / initalpha;
altersingle (a, j, b, g, r);
if (rad > 0) alterneigh (a, rad, j, b, g, r); // alter neighbours
}
pos += step;
while (pos >= lengthcount) pos -= lengthcount;
i++;
if (i%delta == 0) {
alpha -= alpha / alphadec;
biasRadius -= biasRadius / radiusdec;
rad = biasRadius >> radiusbiasshift;
if (rad <= 1) rad = 0;
}
}
// System.err.println("finished 1D learning: final alpha=" + (1.0 * alpha)/initalpha + "!");
}
private void fix() {
for (int i=0; i 255) x = 255;
colormap[i][j] = x;
}
colormap[i][3] = i;
}
}
private void inxbuild() {
// Insertion sort of network and building of netindex[0..255]
int previouscol = 0;
int startpos = 0;
for (int i=0; i>1;
for (int j=previouscol+1; j>1;
for (int j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; // really 256
}
public int convert (int pixel) {
int alfa = (pixel >> 24) & 0xff;
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = (pixel ) & 0xff;
int i = inxsearch(b, g, r);
int bb = colormap[i][0];
int gg = colormap[i][1];
int rr = colormap[i][2];
return (alfa << 24) | (rr << 16) | (gg << 8) | (bb);
}
public int lookup (int pixel) {
int r = (pixel >> 16) & 0xff;
int g = (pixel >> 8) & 0xff;
int b = (pixel ) & 0xff;
int i = inxsearch(b, g, r);
// compensate for transparent color
return i+1;
}
private int not_used_slow_inxsearch(int b, int g, int r) {
// Search for BGR values 0..255 and return colour index
int bestd = 1000; // biggest possible dist is 256*3
int best = -1;
for (int i = 0; i=0)) {
if (i= bestd) i = netsize; // stop iter
else {
if (dist<0) dist = -dist;
int a = p[0] - b; if (a<0) a = -a;
dist += a;
if (dist=0) {
int [] p = colormap[j];
int dist = g - p[1]; // inx key - reverse dif
if (dist >= bestd) j = -1; // stop iter
else {
if (dist<0) dist = -dist;
int a = p[0] - b; if (a<0) a = -a;
dist += a;
if (dist
© 2015 - 2024 Weber Informatics LLC | Privacy Policy