Advertisement
Guest User

DWIGifEncode

a guest
Dec 24th, 2011
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 36.06 KB | None | 0 0
  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.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement