| Index: bower_components/gif.js/src/NeuQuant.js
|
| diff --git a/bower_components/gif.js/src/NeuQuant.js b/bower_components/gif.js/src/NeuQuant.js
|
| deleted file mode 100644
|
| index 200d6bbe14877813d90de73a3e385977faecb481..0000000000000000000000000000000000000000
|
| --- a/bower_components/gif.js/src/NeuQuant.js
|
| +++ /dev/null
|
| @@ -1,434 +0,0 @@
|
| -/* 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://members.ozemail.com.au/~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.
|
| - *
|
| - * (JavaScript port 2012 by Johan Nordberg)
|
| - */
|
| -
|
| -function toInt(v) {
|
| - return ~~v;
|
| -}
|
| -
|
| -var ncycles = 100; // number of learning cycles
|
| -var netsize = 256; // number of colors used
|
| -var maxnetpos = netsize - 1;
|
| -
|
| -// defs for freq and bias
|
| -var netbiasshift = 4; // bias for colour values
|
| -var intbiasshift = 16; // bias for fractions
|
| -var intbias = (1 << intbiasshift);
|
| -var gammashift = 10;
|
| -var gamma = (1 << gammashift);
|
| -var betashift = 10;
|
| -var beta = (intbias >> betashift); /* beta = 1/1024 */
|
| -var betagamma = (intbias << (gammashift - betashift));
|
| -
|
| -// defs for decreasing radius factor
|
| -var initrad = (netsize >> 3); // for 256 cols, radius starts
|
| -var radiusbiasshift = 6; // at 32.0 biased by 6 bits
|
| -var radiusbias = (1 << radiusbiasshift);
|
| -var initradius = (initrad * radiusbias); //and decreases by a
|
| -var radiusdec = 30; // factor of 1/30 each cycle
|
| -
|
| -// defs for decreasing alpha factor
|
| -var alphabiasshift = 10; // alpha starts at 1.0
|
| -var initalpha = (1 << alphabiasshift);
|
| -var alphadec; // biased by 10 bits
|
| -
|
| -/* radbias and alpharadbias used for radpower calculation */
|
| -var radbiasshift = 8;
|
| -var radbias = (1 << radbiasshift);
|
| -var alpharadbshift = (alphabiasshift + radbiasshift);
|
| -var alpharadbias = (1 << alpharadbshift);
|
| -
|
| -// four primes near 500 - assume no image has a length so large that it is
|
| -// divisible by all four primes
|
| -var prime1 = 499;
|
| -var prime2 = 491;
|
| -var prime3 = 487;
|
| -var prime4 = 503;
|
| -var minpicturebytes = (3 * prime4);
|
| -
|
| -/*
|
| - Constructor: NeuQuant
|
| -
|
| - Arguments:
|
| -
|
| - pixels - array of pixels in RGB format
|
| - samplefac - sampling factor 1 to 30 where lower is better quality
|
| -
|
| - >
|
| - > pixels = [r, g, b, r, g, b, r, g, b, ..]
|
| - >
|
| -*/
|
| -function NeuQuant(pixels, samplefac) {
|
| - var network; // int[netsize][4]
|
| - var netindex; // for network lookup - really 256
|
| -
|
| - // bias and freq arrays for learning
|
| - var bias;
|
| - var freq;
|
| - var radpower;
|
| -
|
| - /*
|
| - Private Method: init
|
| -
|
| - sets up arrays
|
| - */
|
| - function init() {
|
| - network = [];
|
| - netindex = [];
|
| - bias = [];
|
| - freq = [];
|
| - radpower = [];
|
| -
|
| - var i, v;
|
| - for (i = 0; i < netsize; i++) {
|
| - v = (i << (netbiasshift + 8)) / netsize;
|
| - network[i] = [v, v, v];
|
| - freq[i] = intbias / netsize;
|
| - bias[i] = 0;
|
| - }
|
| - }
|
| -
|
| - /*
|
| - Private Method: unbiasnet
|
| -
|
| - unbiases network to give byte values 0..255 and record position i to prepare for sort
|
| - */
|
| - function unbiasnet() {
|
| - for (var i = 0; i < netsize; i++) {
|
| - network[i][0] >>= netbiasshift;
|
| - network[i][1] >>= netbiasshift;
|
| - network[i][2] >>= netbiasshift;
|
| - network[i][3] = i; // record color number
|
| - }
|
| - }
|
| -
|
| - /*
|
| - Private Method: altersingle
|
| -
|
| - moves neuron *i* towards biased (b,g,r) by factor *alpha*
|
| - */
|
| - function altersingle(alpha, i, b, g, r) {
|
| - network[i][0] -= (alpha * (network[i][0] - b)) / initalpha;
|
| - network[i][1] -= (alpha * (network[i][1] - g)) / initalpha;
|
| - network[i][2] -= (alpha * (network[i][2] - r)) / initalpha;
|
| - }
|
| -
|
| - /*
|
| - Private Method: alterneigh
|
| -
|
| - moves neurons in *radius* around index *i* towards biased (b,g,r) by factor *alpha*
|
| - */
|
| - function alterneigh(radius, i, b, g, r) {
|
| - var lo = Math.abs(i - radius);
|
| - var hi = Math.min(i + radius, netsize);
|
| -
|
| - var j = i + 1;
|
| - var k = i - 1;
|
| - var m = 1;
|
| -
|
| - var p, a;
|
| - while ((j < hi) || (k > lo)) {
|
| - a = radpower[m++];
|
| -
|
| - if (j < hi) {
|
| - p = network[j++];
|
| - p[0] -= (a * (p[0] - b)) / alpharadbias;
|
| - p[1] -= (a * (p[1] - g)) / alpharadbias;
|
| - p[2] -= (a * (p[2] - r)) / alpharadbias;
|
| - }
|
| -
|
| - if (k > lo) {
|
| - p = network[k--];
|
| - p[0] -= (a * (p[0] - b)) / alpharadbias;
|
| - p[1] -= (a * (p[1] - g)) / alpharadbias;
|
| - p[2] -= (a * (p[2] - r)) / alpharadbias;
|
| - }
|
| - }
|
| - }
|
| -
|
| - /*
|
| - Private Method: contest
|
| -
|
| - searches for biased BGR values
|
| - */
|
| - function contest(b, g, r) {
|
| - /*
|
| - 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])
|
| - */
|
| -
|
| - var bestd = ~(1 << 31);
|
| - var bestbiasd = bestd;
|
| - var bestpos = -1;
|
| - var bestbiaspos = bestpos;
|
| -
|
| - var i, n, dist, biasdist, betafreq;
|
| - for (i = 0; i < netsize; i++) {
|
| - n = network[i];
|
| -
|
| - dist = Math.abs(n[0] - b) + Math.abs(n[1] - g) + Math.abs(n[2] - r);
|
| - if (dist < bestd) {
|
| - bestd = dist;
|
| - bestpos = i;
|
| - }
|
| -
|
| - biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));
|
| - if (biasdist < bestbiasd) {
|
| - bestbiasd = biasdist;
|
| - bestbiaspos = i;
|
| - }
|
| -
|
| - betafreq = (freq[i] >> betashift);
|
| - freq[i] -= betafreq;
|
| - bias[i] += (betafreq << gammashift);
|
| - }
|
| -
|
| - freq[bestpos] += beta;
|
| - bias[bestpos] -= betagamma;
|
| -
|
| - return bestbiaspos;
|
| - }
|
| -
|
| - /*
|
| - Private Method: inxbuild
|
| -
|
| - sorts network and builds netindex[0..255]
|
| - */
|
| - function inxbuild() {
|
| - var i, j, p, q, smallpos, smallval, previouscol = 0, startpos = 0;
|
| - for (i = 0; i < netsize; i++) {
|
| - p = network[i];
|
| - smallpos = i;
|
| - smallval = p[1]; // index on g
|
| - // find smallest in i..netsize-1
|
| - for (j = i + 1; j < netsize; j++) {
|
| - q = network[j];
|
| - if (q[1] < smallval) { // index on g
|
| - smallpos = j;
|
| - smallval = q[1]; // index on g
|
| - }
|
| - }
|
| - q = network[smallpos];
|
| - // swap p (i) and q (smallpos) entries
|
| - if (i != smallpos) {
|
| - j = q[0]; q[0] = p[0]; p[0] = j;
|
| - j = q[1]; q[1] = p[1]; p[1] = j;
|
| - j = q[2]; q[2] = p[2]; p[2] = j;
|
| - j = q[3]; q[3] = p[3]; p[3] = j;
|
| - }
|
| - // smallval entry is now in position i
|
| -
|
| - if (smallval != previouscol) {
|
| - netindex[previouscol] = (startpos + i) >> 1;
|
| - for (j = previouscol + 1; j < smallval; j++)
|
| - netindex[j] = i;
|
| - previouscol = smallval;
|
| - startpos = i;
|
| - }
|
| - }
|
| - netindex[previouscol] = (startpos + maxnetpos) >> 1;
|
| - for (j = previouscol + 1; j < 256; j++)
|
| - netindex[j] = maxnetpos; // really 256
|
| - }
|
| -
|
| - /*
|
| - Private Method: inxsearch
|
| -
|
| - searches for BGR values 0..255 and returns a color index
|
| - */
|
| - function inxsearch(b, g, r) {
|
| - var a, p, dist;
|
| -
|
| - var bestd = 1000; // biggest possible dist is 256*3
|
| - var best = -1;
|
| -
|
| - var i = netindex[g]; // index on g
|
| - var j = i - 1; // start at netindex[g] and work outwards
|
| -
|
| - while ((i < netsize) || (j >= 0)) {
|
| - if (i < netsize) {
|
| - p = network[i];
|
| - dist = p[1] - g; // inx key
|
| - if (dist >= 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 < bestd) {
|
| - a = p[2] - r; if (a < 0) a = -a;
|
| - dist += a;
|
| - if (dist < bestd) {
|
| - bestd = dist;
|
| - best = p[3];
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (j >= 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 < bestd) {
|
| - a = p[2] - r; if (a < 0) a = -a;
|
| - dist += a;
|
| - if (dist < bestd) {
|
| - bestd = dist;
|
| - best = p[3];
|
| - }
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - return best;
|
| - }
|
| -
|
| - /*
|
| - Private Method: learn
|
| -
|
| - "Main Learning Loop"
|
| - */
|
| - function learn() {
|
| - var i;
|
| -
|
| - var lengthcount = pixels.length;
|
| - var alphadec = toInt(30 + ((samplefac - 1) / 3));
|
| - var samplepixels = toInt(lengthcount / (3 * samplefac));
|
| - var delta = toInt(samplepixels / ncycles);
|
| - var alpha = initalpha;
|
| - var radius = initradius;
|
| -
|
| - var rad = radius >> radiusbiasshift;
|
| -
|
| - if (rad <= 1) rad = 0;
|
| - for (i = 0; i < rad; i++)
|
| - radpower[i] = toInt(alpha * (((rad * rad - i * i) * radbias) / (rad * rad)));
|
| -
|
| - var step;
|
| - if (lengthcount < minpicturebytes) {
|
| - samplefac = 1;
|
| - step = 3;
|
| - } else if ((lengthcount % prime1) !== 0) {
|
| - step = 3 * prime1;
|
| - } else if ((lengthcount % prime2) !== 0) {
|
| - step = 3 * prime2;
|
| - } else if ((lengthcount % prime3) !== 0) {
|
| - step = 3 * prime3;
|
| - } else {
|
| - step = 3 * prime4;
|
| - }
|
| -
|
| - var b, g, r, j;
|
| - var pix = 0; // current pixel
|
| -
|
| - i = 0;
|
| - while (i < samplepixels) {
|
| - b = (pixels[pix] & 0xff) << netbiasshift;
|
| - g = (pixels[pix + 1] & 0xff) << netbiasshift;
|
| - r = (pixels[pix + 2] & 0xff) << netbiasshift;
|
| -
|
| - j = contest(b, g, r);
|
| -
|
| - altersingle(alpha, j, b, g, r);
|
| - if (rad !== 0) alterneigh(rad, j, b, g, r); // alter neighbours
|
| -
|
| - pix += step;
|
| - if (pix >= lengthcount) pix -= lengthcount;
|
| -
|
| - i++;
|
| -
|
| - if (delta === 0) delta = 1;
|
| - if (i % delta === 0) {
|
| - alpha -= alpha / alphadec;
|
| - radius -= radius / radiusdec;
|
| - rad = radius >> radiusbiasshift;
|
| -
|
| - if (rad <= 1) rad = 0;
|
| - for (j = 0; j < rad; j++)
|
| - radpower[j] = toInt(alpha * (((rad * rad - j * j) * radbias) / (rad * rad)));
|
| - }
|
| - }
|
| - }
|
| -
|
| - /*
|
| - Method: buildColormap
|
| -
|
| - 1. initializes network
|
| - 2. trains it
|
| - 3. removes misconceptions
|
| - 4. builds colorindex
|
| - */
|
| - function buildColormap() {
|
| - init();
|
| - learn();
|
| - unbiasnet();
|
| - inxbuild();
|
| - }
|
| - this.buildColormap = buildColormap;
|
| -
|
| - /*
|
| - Method: getColormap
|
| -
|
| - builds colormap from the index
|
| -
|
| - returns array in the format:
|
| -
|
| - >
|
| - > [r, g, b, r, g, b, r, g, b, ..]
|
| - >
|
| - */
|
| - function getColormap() {
|
| - var map = [];
|
| - var index = [];
|
| -
|
| - for (var i = 0; i < netsize; i++)
|
| - index[network[i][3]] = i;
|
| -
|
| - var k = 0;
|
| - for (var l = 0; l < netsize; l++) {
|
| - var j = index[l];
|
| - map[k++] = (network[j][0]);
|
| - map[k++] = (network[j][1]);
|
| - map[k++] = (network[j][2]);
|
| - }
|
| - return map;
|
| - }
|
| - this.getColormap = getColormap;
|
| -
|
| - /*
|
| - Method: lookupRGB
|
| -
|
| - looks for the closest *r*, *g*, *b* color in the map and
|
| - returns its index
|
| - */
|
| - this.lookupRGB = inxsearch;
|
| -}
|
| -
|
| -module.exports = NeuQuant;
|
|
|