Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

DWIGifEncode

By: a guest on Dec 24th, 2011  |  syntax: Java  |  size: 36.06 KB  |  views: 69  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. package com.softwhir.dealwithit;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4.  
  5. import android.graphics.Bitmap;
  6. import android.graphics.Bitmap.Config;
  7. import android.graphics.Canvas;
  8. import android.graphics.Paint;
  9.  
  10. public class AnimatedGifEncoder {
  11.  
  12.           protected int width; // image size
  13.  
  14.           protected int height;
  15.  
  16.           protected int transparent = -1; // transparent color if given
  17.  
  18.           protected int transIndex; // transparent index in color table
  19.  
  20.           protected int repeat = -1; // no repeat
  21.  
  22.           protected int delay = 0; // frame delay (hundredths)
  23.  
  24.           protected boolean started = false; // ready to output frames
  25.  
  26.           protected OutputStream out;
  27.  
  28.           protected Bitmap image; // current frame
  29.  
  30.           protected byte[] pixels; // BGR byte array from frame
  31.  
  32.           protected byte[] indexedPixels; // converted frame indexed to palette
  33.  
  34.           protected int colorDepth; // number of bit planes
  35.  
  36.           protected byte[] colorTab; // RGB palette
  37.  
  38.           protected boolean[] usedEntry = new boolean[256]; // active palette entries
  39.  
  40.           protected int palSize = 7; // color table size (bits-1)
  41.  
  42.           protected int dispose = -1; // disposal code (-1 = use default)
  43.  
  44.           protected boolean closeStream = false; // close stream when finished
  45.  
  46.           protected boolean firstFrame = true;
  47.  
  48.           protected boolean sizeSet = false; // if false, get size from first frame
  49.  
  50.           protected int sample = 10; // default sample interval for quantizer
  51.  
  52.           /**
  53.            * Sets the delay time between each frame, or changes it for subsequent frames
  54.            * (applies to last frame added).
  55.            *
  56.            * @param ms
  57.            *          int delay time in milliseconds
  58.            */
  59.           public void setDelay(int ms) {
  60.             delay = ms / 10;
  61.           }
  62.  
  63.           /**
  64.            * Sets the GIF frame disposal code for the last added frame and any
  65.            * subsequent frames. Default is 0 if no transparent color has been set,
  66.            * otherwise 2.
  67.            *
  68.            * @param code
  69.            *          int disposal code.
  70.            */
  71.           public void setDispose(int code) {
  72.             if (code >= 0) {
  73.               dispose = code;
  74.             }
  75.           }
  76.  
  77.           /**
  78.            * Sets the number of times the set of GIF frames should be played. Default is
  79.            * 1; 0 means play indefinitely. Must be invoked before the first image is
  80.            * added.
  81.            *
  82.            * @param iter
  83.            *          int number of iterations.
  84.            * @return
  85.            */
  86.           public void setRepeat(int iter) {
  87.             if (iter >= 0) {
  88.               repeat = iter;
  89.             }
  90.           }
  91.  
  92.           /**
  93.            * Sets the transparent color for the last added frame and any subsequent
  94.            * frames. Since all colors are subject to modification in the quantization
  95.            * process, the color in the final palette for each frame closest to the given
  96.            * color becomes the transparent color for that frame. May be set to null to
  97.            * indicate no transparent color.
  98.            *
  99.            * @param c
  100.            *          Color to be treated as transparent on display.
  101.            */
  102.           public void setTransparent(int c) {
  103.             transparent = c;
  104.           }
  105.  
  106.           /**
  107.            * Adds next GIF frame. The frame is not written immediately, but is actually
  108.            * deferred until the next frame is received so that timing data can be
  109.            * inserted. Invoking <code>finish()</code> flushes all frames. If
  110.            * <code>setSize</code> was not invoked, the size of the first image is used
  111.            * for all subsequent frames.
  112.            *
  113.            * @param im
  114.            *          BufferedImage containing frame to write.
  115.            * @return true if successful.
  116.            */
  117.           public boolean addFrame(Bitmap im) {
  118.             if ((im == null) || !started) {
  119.               return false;
  120.             }
  121.             boolean ok = true;
  122.             try {
  123.               if (!sizeSet) {
  124.                 // use first frame's size
  125.                 setSize(im.getWidth(), im.getHeight());
  126.               }
  127.               image = im;
  128.               getImagePixels(); // convert to correct format if necessary
  129.               analyzePixels(); // build color table & map pixels
  130.               if (firstFrame) {
  131.                 writeLSD(); // logical screen descriptior
  132.                 writePalette(); // global color table
  133.                 if (repeat >= 0) {
  134.                   // use NS app extension to indicate reps
  135.                   writeNetscapeExt();
  136.                 }
  137.               }
  138.               writeGraphicCtrlExt(); // write graphic control extension
  139.               writeImageDesc(); // image descriptor
  140.               if (!firstFrame) {
  141.                 writePalette(); // local color table
  142.               }
  143.               writePixels(); // encode and write pixel data
  144.               firstFrame = false;
  145.             } catch (IOException e) {
  146.               ok = false;
  147.             }
  148.  
  149.             return ok;
  150.           }
  151.  
  152.           /**
  153.            * Flushes any pending data and closes output file. If writing to an
  154.            * OutputStream, the stream is not closed.
  155.            */
  156.           public boolean finish() {
  157.             if (!started)
  158.               return false;
  159.             boolean ok = true;
  160.             started = false;
  161.             try {
  162.               out.write(0x3b); // gif trailer
  163.               out.flush();
  164.               if (closeStream) {
  165.                 out.close();
  166.               }
  167.             } catch (IOException e) {
  168.               ok = false;
  169.             }
  170.  
  171.             // reset for subsequent use
  172.             transIndex = 0;
  173.             out = null;
  174.             image = null;
  175.             pixels = null;
  176.             indexedPixels = null;
  177.             colorTab = null;
  178.             closeStream = false;
  179.             firstFrame = true;
  180.  
  181.             return ok;
  182.           }
  183.  
  184.           /**
  185.            * Sets frame rate in frames per second. Equivalent to
  186.            * <code>setDelay(1000/fps)</code>.
  187.            *
  188.            * @param fps
  189.            *          float frame rate (frames per second)
  190.            */
  191.           public void setFrameRate(float fps) {
  192.             if (fps != 0f) {
  193.               delay = (int)(100 / fps);
  194.             }
  195.           }
  196.  
  197.           /**
  198.            * Sets quality of color quantization (conversion of images to the maximum 256
  199.            * colors allowed by the GIF specification). Lower values (minimum = 1)
  200.            * produce better colors, but slow processing significantly. 10 is the
  201.            * default, and produces good color mapping at reasonable speeds. Values
  202.            * greater than 20 do not yield significant improvements in speed.
  203.            *
  204.            * @param quality
  205.            *          int greater than 0.
  206.            * @return
  207.            */
  208.           public void setQuality(int quality) {
  209.             if (quality < 1)
  210.               quality = 1;
  211.             sample = quality;
  212.           }
  213.  
  214.           /**
  215.            * Sets the GIF frame size. The default size is the size of the first frame
  216.            * added if this method is not invoked.
  217.            *
  218.            * @param w
  219.            *          int frame width.
  220.            * @param h
  221.            *          int frame width.
  222.            */
  223.           public void setSize(int w, int h) {
  224.             if (started && !firstFrame)
  225.               return;
  226.             width = w;
  227.             height = h;
  228.             if (width < 1)
  229.               width = 320;
  230.             if (height < 1)
  231.               height = 240;
  232.             sizeSet = true;
  233.           }
  234.  
  235.           /**
  236.            * Initiates GIF file creation on the given stream. The stream is not closed
  237.            * automatically.
  238.            *
  239.            * @param os
  240.            *          OutputStream on which GIF images are written.
  241.            * @return false if initial write failed.
  242.            */
  243.           public boolean start(OutputStream os) {
  244.             if (os == null)
  245.               return false;
  246.             boolean ok = true;
  247.             closeStream = false;
  248.             out = os;
  249.             try {
  250.               writeString("GIF89a"); // header
  251.             } catch (IOException e) {
  252.               ok = false;
  253.             }
  254.             return started = ok;
  255.           }
  256.  
  257.           /**
  258.            * Analyzes image colors and creates color map.
  259.            */
  260.           protected void analyzePixels() {
  261.             int len = pixels.length;
  262.             int nPix = len / 3;
  263.             indexedPixels = new byte[nPix];
  264.             NeuQuant nq = new NeuQuant(pixels, len, sample);
  265.             // initialize quantizer
  266.             colorTab = nq.process(); // create reduced palette
  267.             // convert map from BGR to RGB
  268.             for (int i = 0; i < colorTab.length; i += 3) {
  269.               byte temp = colorTab[i];
  270.               colorTab[i] = colorTab[i + 2];
  271.               colorTab[i + 2] = temp;
  272.               usedEntry[i / 3] = false;
  273.             }
  274.             // map image pixels to new palette
  275.             int k = 0;
  276.             for (int i = 0; i < nPix; i++) {
  277.               int index = nq.map(pixels[k++] & 0xff, pixels[k++] & 0xff, pixels[k++] & 0xff);
  278.               usedEntry[index] = true;
  279.               indexedPixels[i] = (byte) index;
  280.             }
  281.             pixels = null;
  282.             colorDepth = 8;
  283.             palSize = 7;
  284.             // get closest match to transparent color if specified
  285.             if (transparent != -1) {
  286.               transIndex = findClosest(transparent);
  287.             }
  288.           }
  289.  
  290.           /**
  291.            * Returns index of palette color closest to c
  292.            *
  293.            */
  294.           protected int findClosest(int c) {
  295.             if (colorTab == null)
  296.               return -1;
  297.             int r = (c >> 16) & 0xff;
  298.             int g = (c >> 8) & 0xff;
  299.             int b = (c >> 0) & 0xff;
  300.             int minpos = 0;
  301.             int dmin = 256 * 256 * 256;
  302.             int len = colorTab.length;
  303.             for (int i = 0; i < len;) {
  304.               int dr = r - (colorTab[i++] & 0xff);
  305.               int dg = g - (colorTab[i++] & 0xff);
  306.               int db = b - (colorTab[i] & 0xff);
  307.               int d = dr * dr + dg * dg + db * db;
  308.               int index = i / 3;
  309.               if (usedEntry[index] && (d < dmin)) {
  310.                 dmin = d;
  311.                 minpos = index;
  312.               }
  313.               i++;
  314.             }
  315.             return minpos;
  316.           }
  317.  
  318.           /**
  319.            * Extracts image pixels into byte array "pixels"
  320.            */
  321.           protected void getImagePixels() {
  322.             int w = image.getWidth();
  323.             int h = image.getHeight();
  324.             if ((w != width) || (h != height)) {
  325.               // create new image with right size/format
  326.               Bitmap temp = Bitmap.createBitmap(width, height, Config.RGB_565);
  327.               Canvas g = new Canvas(temp);
  328.               g.drawBitmap(image, 0, 0, new Paint());
  329.               image = temp;
  330.             }
  331.             int[] data = getImageData(image);
  332.                 pixels = new byte[data.length * 3];
  333.                 for (int i = 0; i < data.length; i++) {
  334.                         int td = data[i];
  335.                         int tind = i * 3;
  336.                         pixels[tind++] = (byte) ((td >> 0) & 0xFF);
  337.                         pixels[tind++] = (byte) ((td >> 8) & 0xFF);
  338.                         pixels[tind] = (byte) ((td >> 16) & 0xFF);
  339.                 }
  340.           }
  341.           protected int[] getImageData(Bitmap img) {
  342.                         int w = img.getWidth();
  343.                         int h = img.getHeight();
  344.  
  345.                         int[] data = new int[w * h];
  346.                         img.getPixels(data, 0, w, 0, 0, w, h);
  347.                         return data;
  348.                 }
  349.  
  350.           /**
  351.            * Writes Graphic Control Extension
  352.            */
  353.           protected void writeGraphicCtrlExt() throws IOException {
  354.             out.write(0x21); // extension introducer
  355.             out.write(0xf9); // GCE label
  356.             out.write(4); // data block size
  357.             int transp, disp;
  358.             if (transparent == -1) {
  359.               transp = 0;
  360.               disp = 0; // dispose = no action
  361.             } else {
  362.               transp = 1;
  363.               disp = 2; // force clear if using transparent color
  364.             }
  365.             if (dispose >= 0) {
  366.               disp = dispose & 7; // user override
  367.             }
  368.             disp <<= 2;
  369.  
  370.             // packed fields
  371.             out.write(0 | // 1:3 reserved
  372.                 disp | // 4:6 disposal
  373.                 0 | // 7 user input - 0 = none
  374.                 transp); // 8 transparency flag
  375.  
  376.             writeShort(delay); // delay x 1/100 sec
  377.             out.write(transIndex); // transparent color index
  378.             out.write(0); // block terminator
  379.           }
  380.  
  381.           /**
  382.            * Writes Image Descriptor
  383.            */
  384.           protected void writeImageDesc() throws IOException {
  385.             out.write(0x2c); // image separator
  386.             writeShort(0); // image position x,y = 0,0
  387.             writeShort(0);
  388.             writeShort(width); // image size
  389.             writeShort(height);
  390.             // packed fields
  391.             if (firstFrame) {
  392.               // no LCT - GCT is used for first (or only) frame
  393.               out.write(0);
  394.             } else {
  395.               // specify normal LCT
  396.               out.write(0x80 | // 1 local color table 1=yes
  397.                   0 | // 2 interlace - 0=no
  398.                   0 | // 3 sorted - 0=no
  399.                   0 | // 4-5 reserved
  400.                   palSize); // 6-8 size of color table
  401.             }
  402.           }
  403.  
  404.           /**
  405.            * Writes Logical Screen Descriptor
  406.            */
  407.           protected void writeLSD() throws IOException {
  408.             // logical screen size
  409.             writeShort(width);
  410.             writeShort(height);
  411.             // packed fields
  412.             out.write((0x80 | // 1 : global color table flag = 1 (gct used)
  413.                 0x70 | // 2-4 : color resolution = 7
  414.                 0x00 | // 5 : gct sort flag = 0
  415.                 palSize)); // 6-8 : gct size
  416.  
  417.             out.write(0); // background color index
  418.             out.write(0); // pixel aspect ratio - assume 1:1
  419.           }
  420.  
  421.           /**
  422.            * Writes Netscape application extension to define repeat count.
  423.            */
  424.           protected void writeNetscapeExt() throws IOException {
  425.             out.write(0x21); // extension introducer
  426.             out.write(0xff); // app extension label
  427.             out.write(11); // block size
  428.             writeString("NETSCAPE" + "2.0"); // app id + auth code
  429.             out.write(3); // sub-block size
  430.             out.write(1); // loop sub-block id
  431.             writeShort(repeat); // loop count (extra iterations, 0=repeat forever)
  432.             out.write(0); // block terminator
  433.           }
  434.  
  435.           /**
  436.            * Writes color table
  437.            */
  438.           protected void writePalette() throws IOException {
  439.             out.write(colorTab, 0, colorTab.length);
  440.             int n = (3 * 256) - colorTab.length;
  441.             for (int i = 0; i < n; i++) {
  442.               out.write(0);
  443.             }
  444.           }
  445.  
  446.           /**
  447.            * Encodes and writes pixel data
  448.            */
  449.           protected void writePixels() throws IOException {
  450.             LZWEncoder encoder = new LZWEncoder(width, height, indexedPixels, colorDepth);
  451.             encoder.encode(out);
  452.           }
  453.  
  454.           /**
  455.            * Write 16-bit value to output stream, LSB first
  456.            */
  457.           protected void writeShort(int value) throws IOException {
  458.             out.write(value & 0xff);
  459.             out.write((value >> 8) & 0xff);
  460.           }
  461.  
  462.           /**
  463.            * Writes string to output stream
  464.            */
  465.           protected void writeString(String s) throws IOException {
  466.             for (int i = 0; i < s.length(); i++) {
  467.               out.write((byte) s.charAt(i));
  468.             }
  469.           }
  470.         }
  471.  
  472.         /*
  473.          * NeuQuant Neural-Net Quantization Algorithm
  474.          * ------------------------------------------
  475.          *
  476.          * Copyright (c) 1994 Anthony Dekker
  477.          *
  478.          * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994. See
  479.          * "Kohonen neural networks for optimal colour quantization" in "Network:
  480.          * Computation in Neural Systems" Vol. 5 (1994) pp 351-367. for a discussion of
  481.          * the algorithm.
  482.          *
  483.          * Any party obtaining a copy of these files from the author, directly or
  484.          * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
  485.          * world-wide, paid up, royalty-free, nonexclusive right and license to deal in
  486.          * this software and documentation files (the "Software"), including without
  487.          * limitation the rights to use, copy, modify, merge, publish, distribute,
  488.          * sublicense, and/or sell copies of the Software, and to permit persons who
  489.          * receive copies from any such party to do so, with the only requirement being
  490.          * that this copyright notice remain intact.
  491.          */
  492.  
  493. //       Ported to Java 12/00 K Weiner
  494.         class NeuQuant {
  495.  
  496.           protected static final int netsize = 256; /* number of colours used */
  497.  
  498.           /* four primes near 500 - assume no image has a length so large */
  499.           /* that it is divisible by all four primes */
  500.           protected static final int prime1 = 499;
  501.  
  502.           protected static final int prime2 = 491;
  503.  
  504.           protected static final int prime3 = 487;
  505.  
  506.           protected static final int prime4 = 503;
  507.  
  508.           protected static final int minpicturebytes = (3 * prime4);
  509.  
  510.           /* minimum size for input image */
  511.  
  512.           /*
  513.            * Program Skeleton ---------------- [select samplefac in range 1..30] [read
  514.            * image from input file] pic = (unsigned char*) malloc(3*width*height);
  515.            * initnet(pic,3*width*height,samplefac); learn(); unbiasnet(); [write output
  516.            * image header, using writecolourmap(f)] inxbuild(); write output image using
  517.            * inxsearch(b,g,r)
  518.            */
  519.  
  520.           /*
  521.            * Network Definitions -------------------
  522.            */
  523.  
  524.           protected static final int maxnetpos = (netsize - 1);
  525.  
  526.           protected static final int netbiasshift = 4; /* bias for colour values */
  527.  
  528.           protected static final int ncycles = 100; /* no. of learning cycles */
  529.  
  530.           /* defs for freq and bias */
  531.           protected static final int intbiasshift = 16; /* bias for fractions */
  532.  
  533.           protected static final int intbias = (((int) 1) << intbiasshift);
  534.  
  535.           protected static final int gammashift = 10; /* gamma = 1024 */
  536.  
  537.           protected static final int gamma = (((int) 1) << gammashift);
  538.  
  539.           protected static final int betashift = 10;
  540.  
  541.           protected static final int beta = (intbias >> betashift); /* beta = 1/1024 */
  542.  
  543.           protected static final int betagamma = (intbias << (gammashift - betashift));
  544.  
  545.           /* defs for decreasing radius factor */
  546.           protected static final int initrad = (netsize >> 3); /*
  547.                                                                  * for 256 cols, radius
  548.                                                                  * starts
  549.                                                                  */
  550.  
  551.           protected static final int radiusbiasshift = 6; /* at 32.0 biased by 6 bits */
  552.  
  553.           protected static final int radiusbias = (((int) 1) << radiusbiasshift);
  554.  
  555.           protected static final int initradius = (initrad * radiusbias); /*
  556.                                                                            * and
  557.                                                                            * decreases
  558.                                                                            * by a
  559.                                                                            */
  560.  
  561.           protected static final int radiusdec = 30; /* factor of 1/30 each cycle */
  562.  
  563.           /* defs for decreasing alpha factor */
  564.           protected static final int alphabiasshift = 10; /* alpha starts at 1.0 */
  565.  
  566.           protected static final int initalpha = (((int) 1) << alphabiasshift);
  567.  
  568.           protected int alphadec; /* biased by 10 bits */
  569.  
  570.           /* radbias and alpharadbias used for radpower calculation */
  571.           protected static final int radbiasshift = 8;
  572.  
  573.           protected static final int radbias = (((int) 1) << radbiasshift);
  574.  
  575.           protected static final int alpharadbshift = (alphabiasshift + radbiasshift);
  576.  
  577.           protected static final int alpharadbias = (((int) 1) << alpharadbshift);
  578.  
  579.           /*
  580.            * Types and Global Variables --------------------------
  581.            */
  582.  
  583.           protected byte[] thepicture; /* the input image itself */
  584.  
  585.           protected int lengthcount; /* lengthcount = H*W*3 */
  586.  
  587.           protected int samplefac; /* sampling factor 1..30 */
  588.  
  589.           // typedef int pixel[4]; /* BGRc */
  590.           protected int[][] network; /* the network itself - [netsize][4] */
  591.  
  592.           protected int[] netindex = new int[256];
  593.  
  594.           /* for network lookup - really 256 */
  595.  
  596.           protected int[] bias = new int[netsize];
  597.  
  598.           /* bias and freq arrays for learning */
  599.           protected int[] freq = new int[netsize];
  600.  
  601.           protected int[] radpower = new int[initrad];
  602.  
  603.           /* radpower for precomputation */
  604.  
  605.           /*
  606.            * Initialise network in range (0,0,0) to (255,255,255) and set parameters
  607.            * -----------------------------------------------------------------------
  608.            */
  609.           public NeuQuant(byte[] thepic, int len, int sample) {
  610.  
  611.             int i;
  612.             int[] p;
  613.  
  614.             thepicture = thepic;
  615.             lengthcount = len;
  616.             samplefac = sample;
  617.  
  618.             network = new int[netsize][];
  619.             for (i = 0; i < netsize; i++) {
  620.               network[i] = new int[4];
  621.               p = network[i];
  622.               p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize;
  623.               freq[i] = intbias / netsize; /* 1/netsize */
  624.               bias[i] = 0;
  625.             }
  626.           }
  627.  
  628.           public byte[] colorMap() {
  629.             byte[] map = new byte[3 * netsize];
  630.             int[] index = new int[netsize];
  631.             for (int i = 0; i < netsize; i++)
  632.               index[network[i][3]] = i;
  633.             int k = 0;
  634.             for (int i = 0; i < netsize; i++) {
  635.               int j = index[i];
  636.               map[k++] = (byte) (network[j][0]);
  637.               map[k++] = (byte) (network[j][1]);
  638.               map[k++] = (byte) (network[j][2]);
  639.             }
  640.             return map;
  641.           }
  642.  
  643.           /*
  644.            * Insertion sort of network and building of netindex[0..255] (to do after
  645.            * unbias)
  646.            * -------------------------------------------------------------------------------
  647.            */
  648.           public void inxbuild() {
  649.  
  650.             int i, j, smallpos, smallval;
  651.             int[] p;
  652.             int[] q;
  653.             int previouscol, startpos;
  654.  
  655.             previouscol = 0;
  656.             startpos = 0;
  657.             for (i = 0; i < netsize; i++) {
  658.               p = network[i];
  659.               smallpos = i;
  660.               smallval = p[1]; /* index on g */
  661.               /* find smallest in i..netsize-1 */
  662.               for (j = i + 1; j < netsize; j++) {
  663.                 q = network[j];
  664.                 if (q[1] < smallval) { /* index on g */
  665.                   smallpos = j;
  666.                   smallval = q[1]; /* index on g */
  667.                 }
  668.               }
  669.               q = network[smallpos];
  670.               /* swap p (i) and q (smallpos) entries */
  671.               if (i != smallpos) {
  672.                 j = q[0];
  673.                 q[0] = p[0];
  674.                 p[0] = j;
  675.                 j = q[1];
  676.                 q[1] = p[1];
  677.                 p[1] = j;
  678.                 j = q[2];
  679.                 q[2] = p[2];
  680.                 p[2] = j;
  681.                 j = q[3];
  682.                 q[3] = p[3];
  683.                 p[3] = j;
  684.               }
  685.               /* smallval entry is now in position i */
  686.               if (smallval != previouscol) {
  687.                 netindex[previouscol] = (startpos + i) >> 1;
  688.                 for (j = previouscol + 1; j < smallval; j++)
  689.                   netindex[j] = i;
  690.                 previouscol = smallval;
  691.                 startpos = i;
  692.               }
  693.             }
  694.             netindex[previouscol] = (startpos + maxnetpos) >> 1;
  695.             for (j = previouscol + 1; j < 256; j++)
  696.               netindex[j] = maxnetpos; /* really 256 */
  697.           }
  698.  
  699.           /*
  700.            * Main Learning Loop ------------------
  701.            */
  702.           public void learn() {
  703.  
  704.             int i, j, b, g, r;
  705.             int radius, rad, alpha, step, delta, samplepixels;
  706.             byte[] p;
  707.             int pix, lim;
  708.  
  709.             if (lengthcount < minpicturebytes)
  710.               samplefac = 1;
  711.             alphadec = 30 + ((samplefac - 1) / 3);
  712.             p = thepicture;
  713.             pix = 0;
  714.             lim = lengthcount;
  715.             samplepixels = lengthcount / (3 * samplefac);
  716.             delta = samplepixels / ncycles;
  717.             alpha = initalpha;
  718.             radius = initradius;
  719.  
  720.             rad = radius >> radiusbiasshift;
  721.             if (rad <= 1)
  722.               rad = 0;
  723.             for (i = 0; i < rad; i++)
  724.               radpower[i] = alpha * (((rad * rad - i * i) * radbias) / (rad * rad));
  725.  
  726.             // fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad);
  727.  
  728.             if (lengthcount < minpicturebytes)
  729.               step = 3;
  730.             else if ((lengthcount % prime1) != 0)
  731.               step = 3 * prime1;
  732.             else {
  733.               if ((lengthcount % prime2) != 0)
  734.                 step = 3 * prime2;
  735.               else {
  736.                 if ((lengthcount % prime3) != 0)
  737.                   step = 3 * prime3;
  738.                 else
  739.                   step = 3 * prime4;
  740.               }
  741.             }
  742.  
  743.             i = 0;
  744.             while (i < samplepixels) {
  745.               b = (p[pix + 0] & 0xff) << netbiasshift;
  746.               g = (p[pix + 1] & 0xff) << netbiasshift;
  747.               r = (p[pix + 2] & 0xff) << netbiasshift;
  748.               j = contest(b, g, r);
  749.  
  750.               altersingle(alpha, j, b, g, r);
  751.               if (rad != 0)
  752.                 alterneigh(rad, j, b, g, r); /* alter neighbours */
  753.  
  754.               pix += step;
  755.               if (pix >= lim)
  756.                 pix -= lengthcount;
  757.  
  758.               i++;
  759.               if (delta == 0)
  760.                 delta = 1;
  761.               if (i % delta == 0) {
  762.                 alpha -= alpha / alphadec;
  763.                 radius -= radius / radiusdec;
  764.                 rad = radius >> radiusbiasshift;
  765.                 if (rad <= 1)
  766.                   rad = 0;
  767.                 for (j = 0; j < rad; j++)
  768.                   radpower[j] = alpha * (((rad * rad - j * j) * radbias) / (rad * rad));
  769.               }
  770.             }
  771.             // fprintf(stderr,"finished 1D learning: final alpha=%f
  772.             // !\n",((float)alpha)/initalpha);
  773.           }
  774.  
  775.           /*
  776.            * Search for BGR values 0..255 (after net is unbiased) and return colour
  777.            * index
  778.            * ----------------------------------------------------------------------------
  779.            */
  780.           public int map(int b, int g, int r) {
  781.  
  782.             int i, j, dist, a, bestd;
  783.             int[] p;
  784.             int best;
  785.  
  786.             bestd = 1000; /* biggest possible dist is 256*3 */
  787.             best = -1;
  788.             i = netindex[g]; /* index on g */
  789.             j = i - 1; /* start at netindex[g] and work outwards */
  790.  
  791.             while ((i < netsize) || (j >= 0)) {
  792.               if (i < netsize) {
  793.                 p = network[i];
  794.                 dist = p[1] - g; /* inx key */
  795.                 if (dist >= bestd)
  796.                   i = netsize; /* stop iter */
  797.                 else {
  798.                   i++;
  799.                   if (dist < 0)
  800.                     dist = -dist;
  801.                   a = p[0] - b;
  802.                   if (a < 0)
  803.                     a = -a;
  804.                   dist += a;
  805.                   if (dist < bestd) {
  806.                     a = p[2] - r;
  807.                     if (a < 0)
  808.                       a = -a;
  809.                     dist += a;
  810.                     if (dist < bestd) {
  811.                       bestd = dist;
  812.                       best = p[3];
  813.                     }
  814.                   }
  815.                 }
  816.               }
  817.               if (j >= 0) {
  818.                 p = network[j];
  819.                 dist = g - p[1]; /* inx key - reverse dif */
  820.                 if (dist >= bestd)
  821.                   j = -1; /* stop iter */
  822.                 else {
  823.                   j--;
  824.                   if (dist < 0)
  825.                     dist = -dist;
  826.                   a = p[0] - b;
  827.                   if (a < 0)
  828.                     a = -a;
  829.                   dist += a;
  830.                   if (dist < bestd) {
  831.                     a = p[2] - r;
  832.                     if (a < 0)
  833.                       a = -a;
  834.                     dist += a;
  835.                     if (dist < bestd) {
  836.                       bestd = dist;
  837.                       best = p[3];
  838.                     }
  839.                   }
  840.                 }
  841.               }
  842.             }
  843.             return (best);
  844.           }
  845.  
  846.           public byte[] process() {
  847.             learn();
  848.             unbiasnet();
  849.             inxbuild();
  850.             return colorMap();
  851.           }
  852.  
  853.           /*
  854.            * Unbias network to give byte values 0..255 and record position i to prepare
  855.            * for sort
  856.            * -----------------------------------------------------------------------------------
  857.            */
  858.           public void unbiasnet() {
  859.  
  860.             int i;
  861.  
  862.             for (i = 0; i < netsize; i++) {
  863.               network[i][0] >>= netbiasshift;
  864.               network[i][1] >>= netbiasshift;
  865.               network[i][2] >>= netbiasshift;
  866.               network[i][3] = i; /* record colour no */
  867.             }
  868.           }
  869.  
  870.           /*
  871.            * Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in
  872.            * radpower[|i-j|]
  873.            * ---------------------------------------------------------------------------------
  874.            */
  875.           protected void alterneigh(int rad, int i, int b, int g, int r) {
  876.  
  877.             int j, k, lo, hi, a, m;
  878.             int[] p;
  879.  
  880.             lo = i - rad;
  881.             if (lo < -1)
  882.               lo = -1;
  883.             hi = i + rad;
  884.             if (hi > netsize)
  885.               hi = netsize;
  886.  
  887.             j = i + 1;
  888.             k = i - 1;
  889.             m = 1;
  890.             while ((j < hi) || (k > lo)) {
  891.               a = radpower[m++];
  892.               if (j < hi) {
  893.                 p = network[j++];
  894.                 try {
  895.                   p[0] -= (a * (p[0] - b)) / alpharadbias;
  896.                   p[1] -= (a * (p[1] - g)) / alpharadbias;
  897.                   p[2] -= (a * (p[2] - r)) / alpharadbias;
  898.                 } catch (Exception e) {
  899.                 } // prevents 1.3 miscompilation
  900.               }
  901.               if (k > lo) {
  902.                 p = network[k--];
  903.                 try {
  904.                   p[0] -= (a * (p[0] - b)) / alpharadbias;
  905.                   p[1] -= (a * (p[1] - g)) / alpharadbias;
  906.                   p[2] -= (a * (p[2] - r)) / alpharadbias;
  907.                 } catch (Exception e) {
  908.                 }
  909.               }
  910.             }
  911.           }
  912.  
  913.           /*
  914.            * Move neuron i towards biased (b,g,r) by factor alpha
  915.            * ----------------------------------------------------
  916.            */
  917.           protected void altersingle(int alpha, int i, int b, int g, int r) {
  918.  
  919.             /* alter hit neuron */
  920.             int[] n = network[i];
  921.             n[0] -= (alpha * (n[0] - b)) / initalpha;
  922.             n[1] -= (alpha * (n[1] - g)) / initalpha;
  923.             n[2] -= (alpha * (n[2] - r)) / initalpha;
  924.           }
  925.  
  926.           /*
  927.            * Search for biased BGR values ----------------------------
  928.            */
  929.           protected int contest(int b, int g, int r) {
  930.  
  931.             /* finds closest neuron (min dist) and updates freq */
  932.             /* finds best neuron (min dist-bias) and returns position */
  933.             /* for frequently chosen neurons, freq[i] is high and bias[i] is negative */
  934.             /* bias[i] = gamma*((1/netsize)-freq[i]) */
  935.  
  936.             int i, dist, a, biasdist, betafreq;
  937.             int bestpos, bestbiaspos, bestd, bestbiasd;
  938.             int[] n;
  939.  
  940.             bestd = ~(((int) 1) << 31);
  941.             bestbiasd = bestd;
  942.             bestpos = -1;
  943.             bestbiaspos = bestpos;
  944.  
  945.             for (i = 0; i < netsize; i++) {
  946.               n = network[i];
  947.               dist = n[0] - b;
  948.               if (dist < 0)
  949.                 dist = -dist;
  950.               a = n[1] - g;
  951.               if (a < 0)
  952.                 a = -a;
  953.               dist += a;
  954.               a = n[2] - r;
  955.               if (a < 0)
  956.                 a = -a;
  957.               dist += a;
  958.               if (dist < bestd) {
  959.                 bestd = dist;
  960.                 bestpos = i;
  961.               }
  962.               biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));
  963.               if (biasdist < bestbiasd) {
  964.                 bestbiasd = biasdist;
  965.                 bestbiaspos = i;
  966.               }
  967.               betafreq = (freq[i] >> betashift);
  968.               freq[i] -= betafreq;
  969.               bias[i] += (betafreq << gammashift);
  970.             }
  971.             freq[bestpos] += beta;
  972.             bias[bestpos] -= betagamma;
  973.             return (bestbiaspos);
  974.           }
  975.         }
  976.  
  977. //       ==============================================================================
  978. //       Adapted from Jef Poskanzer's Java port by way of J. M. G. Elliott.
  979. //       K Weiner 12/00
  980.  
  981.         class LZWEncoder {
  982.  
  983.           private static final int EOF = -1;
  984.  
  985.           private int imgW, imgH;
  986.  
  987.           private byte[] pixAry;
  988.  
  989.           private int initCodeSize;
  990.  
  991.           private int remaining;
  992.  
  993.           private int curPixel;
  994.  
  995.           // GIFCOMPR.C - GIF Image compression routines
  996.           //
  997.           // Lempel-Ziv compression based on 'compress'. GIF modifications by
  998.           // David Rowley (mgardi@watdcsu.waterloo.edu)
  999.  
  1000.           // General DEFINEs
  1001.  
  1002.           static final int BITS = 12;
  1003.  
  1004.           static final int HSIZE = 5003; // 80% occupancy
  1005.  
  1006.           // GIF Image compression - modified 'compress'
  1007.           //
  1008.           // Based on: compress.c - File compression ala IEEE Computer, June 1984.
  1009.           //
  1010.           // By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
  1011.           // Jim McKie (decvax!mcvax!jim)
  1012.           // Steve Davies (decvax!vax135!petsd!peora!srd)
  1013.           // Ken Turkowski (decvax!decwrl!turtlevax!ken)
  1014.           // James A. Woods (decvax!ihnp4!ames!jaw)
  1015.           // Joe Orost (decvax!vax135!petsd!joe)
  1016.  
  1017.           int n_bits; // number of bits/code
  1018.  
  1019.           int maxbits = BITS; // user settable max # bits/code
  1020.  
  1021.           int maxcode; // maximum code, given n_bits
  1022.  
  1023.           int maxmaxcode = 1 << BITS; // should NEVER generate this code
  1024.  
  1025.           int[] htab = new int[HSIZE];
  1026.  
  1027.           int[] codetab = new int[HSIZE];
  1028.  
  1029.           int hsize = HSIZE; // for dynamic table sizing
  1030.  
  1031.           int free_ent = 0; // first unused entry
  1032.  
  1033.           // block compression parameters -- after all codes are used up,
  1034.           // and compression rate changes, start over.
  1035.           boolean clear_flg = false;
  1036.  
  1037.           // Algorithm: use open addressing double hashing (no chaining) on the
  1038.           // prefix code / next character combination. We do a variant of Knuth's
  1039.           // algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  1040.           // secondary probe. Here, the modular division first probe is gives way
  1041.           // to a faster exclusive-or manipulation. Also do block compression with
  1042.           // an adaptive reset, whereby the code table is cleared when the compression
  1043.           // ratio decreases, but after the table fills. The variable-length output
  1044.           // codes are re-sized at this point, and a special CLEAR code is generated
  1045.           // for the decompressor. Late addition: construct the table according to
  1046.           // file size for noticeable speed improvement on small files. Please direct
  1047.           // questions about this implementation to ames!jaw.
  1048.  
  1049.           int g_init_bits;
  1050.  
  1051.           int ClearCode;
  1052.  
  1053.           int EOFCode;
  1054.  
  1055.           // output
  1056.           //
  1057.           // Output the given code.
  1058.           // Inputs:
  1059.           // code: A n_bits-bit integer. If == -1, then EOF. This assumes
  1060.           // that n_bits =< wordsize - 1.
  1061.           // Outputs:
  1062.           // Outputs code to the file.
  1063.           // Assumptions:
  1064.           // Chars are 8 bits long.
  1065.           // Algorithm:
  1066.           // Maintain a BITS character long buffer (so that 8 codes will
  1067.           // fit in it exactly). Use the VAX insv instruction to insert each
  1068.           // code in turn. When the buffer fills up empty it and start over.
  1069.  
  1070.           int cur_accum = 0;
  1071.  
  1072.           int cur_bits = 0;
  1073.  
  1074.           int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF,
  1075.               0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  1076.  
  1077.           // Number of characters so far in this 'packet'
  1078.           int a_count;
  1079.  
  1080.           // Define the storage for the packet accumulator
  1081.           byte[] accum = new byte[256];
  1082.  
  1083.           // ----------------------------------------------------------------------------
  1084.           LZWEncoder(int width, int height, byte[] pixels, int color_depth) {
  1085.             imgW = width;
  1086.             imgH = height;
  1087.             pixAry = pixels;
  1088.             initCodeSize = Math.max(2, color_depth);
  1089.           }
  1090.  
  1091.           // Add a character to the end of the current packet, and if it is 254
  1092.           // characters, flush the packet to disk.
  1093.           void char_out(byte c, OutputStream outs) throws IOException {
  1094.             accum[a_count++] = c;
  1095.             if (a_count >= 254)
  1096.               flush_char(outs);
  1097.           }
  1098.  
  1099.           // Clear out the hash table
  1100.  
  1101.           // table clear for block compress
  1102.           void cl_block(OutputStream outs) throws IOException {
  1103.             cl_hash(hsize);
  1104.             free_ent = ClearCode + 2;
  1105.             clear_flg = true;
  1106.  
  1107.             output(ClearCode, outs);
  1108.           }
  1109.  
  1110.           // reset code table
  1111.           void cl_hash(int hsize) {
  1112.             for (int i = 0; i < hsize; ++i)
  1113.               htab[i] = -1;
  1114.           }
  1115.  
  1116.           void compress(int init_bits, OutputStream outs) throws IOException {
  1117.             int fcode;
  1118.             int i /* = 0 */;
  1119.             int c;
  1120.             int ent;
  1121.             int disp;
  1122.             int hsize_reg;
  1123.             int hshift;
  1124.  
  1125.             // Set up the globals: g_init_bits - initial number of bits
  1126.             g_init_bits = init_bits;
  1127.  
  1128.             // Set up the necessary values
  1129.             clear_flg = false;
  1130.             n_bits = g_init_bits;
  1131.             maxcode = MAXCODE(n_bits);
  1132.  
  1133.             ClearCode = 1 << (init_bits - 1);
  1134.             EOFCode = ClearCode + 1;
  1135.             free_ent = ClearCode + 2;
  1136.  
  1137.             a_count = 0; // clear packet
  1138.  
  1139.             ent = nextPixel();
  1140.  
  1141.             hshift = 0;
  1142.             for (fcode = hsize; fcode < 65536; fcode *= 2)
  1143.               ++hshift;
  1144.             hshift = 8 - hshift; // set hash code range bound
  1145.  
  1146.             hsize_reg = hsize;
  1147.             cl_hash(hsize_reg); // clear hash table
  1148.  
  1149.             output(ClearCode, outs);
  1150.  
  1151.             outer_loop: while ((c = nextPixel()) != EOF) {
  1152.               fcode = (c << maxbits) + ent;
  1153.               i = (c << hshift) ^ ent; // xor hashing
  1154.  
  1155.               if (htab[i] == fcode) {
  1156.                 ent = codetab[i];
  1157.                 continue;
  1158.               } else if (htab[i] >= 0) // non-empty slot
  1159.               {
  1160.                 disp = hsize_reg - i; // secondary hash (after G. Knott)
  1161.                 if (i == 0)
  1162.                   disp = 1;
  1163.                 do {
  1164.                   if ((i -= disp) < 0)
  1165.                     i += hsize_reg;
  1166.  
  1167.                   if (htab[i] == fcode) {
  1168.                     ent = codetab[i];
  1169.                     continue outer_loop;
  1170.                   }
  1171.                 } while (htab[i] >= 0);
  1172.               }
  1173.               output(ent, outs);
  1174.               ent = c;
  1175.               if (free_ent < maxmaxcode) {
  1176.                 codetab[i] = free_ent++; // code -> hashtable
  1177.                 htab[i] = fcode;
  1178.               } else
  1179.                 cl_block(outs);
  1180.             }
  1181.             // Put out the final code.
  1182.             output(ent, outs);
  1183.             output(EOFCode, outs);
  1184.           }
  1185.  
  1186.           // ----------------------------------------------------------------------------
  1187.           void encode(OutputStream os) throws IOException {
  1188.             os.write(initCodeSize); // write "initial code size" byte
  1189.  
  1190.             remaining = imgW * imgH; // reset navigation variables
  1191.             curPixel = 0;
  1192.  
  1193.             compress(initCodeSize + 1, os); // compress and write the pixel data
  1194.  
  1195.             os.write(0); // write block terminator
  1196.           }
  1197.  
  1198.           // Flush the packet to disk, and reset the accumulator
  1199.           void flush_char(OutputStream outs) throws IOException {
  1200.             if (a_count > 0) {
  1201.               outs.write(a_count);
  1202.               outs.write(accum, 0, a_count);
  1203.               a_count = 0;
  1204.             }
  1205.           }
  1206.  
  1207.           final int MAXCODE(int n_bits) {
  1208.             return (1 << n_bits) - 1;
  1209.           }
  1210.  
  1211.           // ----------------------------------------------------------------------------
  1212.           // Return the next pixel from the image
  1213.           // ----------------------------------------------------------------------------
  1214.           private int nextPixel() {
  1215.             if (remaining == 0)
  1216.               return EOF;
  1217.  
  1218.             --remaining;
  1219.  
  1220.             byte pix = pixAry[curPixel++];
  1221.  
  1222.             return pix & 0xff;
  1223.           }
  1224.  
  1225.           void output(int code, OutputStream outs) throws IOException {
  1226.             cur_accum &= masks[cur_bits];
  1227.  
  1228.             if (cur_bits > 0)
  1229.               cur_accum |= (code << cur_bits);
  1230.             else
  1231.               cur_accum = code;
  1232.  
  1233.             cur_bits += n_bits;
  1234.  
  1235.             while (cur_bits >= 8) {
  1236.               char_out((byte) (cur_accum & 0xff), outs);
  1237.               cur_accum >>= 8;
  1238.               cur_bits -= 8;
  1239.             }
  1240.  
  1241.             // If the next entry is going to be too big for the code size,
  1242.             // then increase it, if possible.
  1243.             if (free_ent > maxcode || clear_flg) {
  1244.               if (clear_flg) {
  1245.                 maxcode = MAXCODE(n_bits = g_init_bits);
  1246.                 clear_flg = false;
  1247.               } else {
  1248.                 ++n_bits;
  1249.                 if (n_bits == maxbits)
  1250.                   maxcode = maxmaxcode;
  1251.                 else
  1252.                   maxcode = MAXCODE(n_bits);
  1253.               }
  1254.             }
  1255.  
  1256.             if (code == EOFCode) {
  1257.               // At EOF, write the rest of the buffer.
  1258.               while (cur_bits > 0) {
  1259.                 char_out((byte) (cur_accum & 0xff), outs);
  1260.                 cur_accum >>= 8;
  1261.                 cur_bits -= 8;
  1262.               }
  1263.  
  1264.               flush_char(outs);
  1265.             }
  1266.           }
  1267.         }
clone this paste RAW Paste Data