java生成动态gif格式与png格式的验证码(代码3)

来源:互联网 发布:hash算法的实现原理 编辑:程序博客网 时间:2024/05/01 17:22
Java代码  收藏代码
  1. import java.awt.*;  
  2. import java.awt.image.BufferedImage;  
  3. import java.awt.image.DataBufferByte;  
  4. import java.io.BufferedOutputStream;  
  5. import java.io.ByteArrayOutputStream;  
  6. import java.io.FileOutputStream;  
  7. import java.io.IOException;  
  8. import java.io.OutputStream;  
  9.   
  10. /** 
  11.  * Class AnimatedGifEncoder - Encodes a GIF file consisting of one or more 
  12.  * frames. 
  13.  *  
  14.  * <pre> 
  15.  * Example: 
  16.  *    AnimatedGifEncoder e = new AnimatedGifEncoder(); 
  17.  *    e.start(outputFileName); 
  18.  *    e.setDelay(1000);   // 1 frame per sec 
  19.  *    e.addFrame(image1); 
  20.  *    e.addFrame(image2); 
  21.  *    e.finish(); 
  22.  * </pre> 
  23.  *  
  24.  * No copyright asserted on the source code of this class. May be used for any 
  25.  * purpose, however, refer to the Unisys LZW patent for restrictions on use of 
  26.  * the associated Encoder class. Please forward any corrections to questions at 
  27.  * fmsware.com. 
  28.  *  
  29.  * @author wzztestin 
  30.  *  
  31.  */  
  32. public class GifEncoder {  
  33.     protected int width; // image size  
  34.     protected int height;  
  35.     protected Color transparent = null// transparent color if given  
  36.     protected int transIndex; // transparent index in color table  
  37.     protected int repeat = -1// no repeat  
  38.     protected int delay = 0// frame delay (hundredths)  
  39.     protected boolean started = false// ready to output frames  
  40.     protected OutputStream out;  
  41.     protected BufferedImage image; // current frame  
  42.     protected byte[] pixels; // BGR byte array from frame  
  43.     protected byte[] indexedPixels; // converted frame indexed to palette  
  44.     protected int colorDepth; // number of bit planes  
  45.     protected byte[] colorTab; // RGB palette  
  46.     protected boolean[] usedEntry = new boolean[256]; // active palette entries  
  47.     protected int palSize = 7// color table size (bits-1)  
  48.     protected int dispose = -1// disposal code (-1 = use default)  
  49.     protected boolean closeStream = false// close stream when finished  
  50.     protected boolean firstFrame = true;  
  51.     protected boolean sizeSet = false// if false, get size from first frame  
  52.     protected int sample = 10// default sample interval for quantizer  
  53.   
  54.     /** 
  55.      * Sets the delay time between each frame, or changes it for subsequent 
  56.      * frames (applies to last frame added). 
  57.      *  
  58.      * @param ms 
  59.      *            int delay time in milliseconds 
  60.      */  
  61.     public void setDelay(int ms) {  
  62.         delay = Math.round(ms / 10.0f);  
  63.     }  
  64.   
  65.     /** 
  66.      * Sets the GIF frame disposal code for the last added frame and any 
  67.      * subsequent frames. Default is 0 if no transparent color has been set, 
  68.      * otherwise 2. 
  69.      *  
  70.      * @param code 
  71.      *            int disposal code. 
  72.      */  
  73.     public void setDispose(int code) {  
  74.         if (code >= 0) {  
  75.             dispose = code;  
  76.         }  
  77.     }  
  78.   
  79.     /** 
  80.      * Sets the number of times the set of GIF frames should be played. Default 
  81.      * is 1; 0 means play indefinitely. Must be invoked before the first image 
  82.      * is added. 
  83.      *  
  84.      * @param iter 
  85.      *            int number of iterations. 
  86.      * @return 
  87.      */  
  88.     public void setRepeat(int iter) {  
  89.         if (iter >= 0) {  
  90.             repeat = iter;  
  91.         }  
  92.     }  
  93.   
  94.     /** 
  95.      * Sets the transparent color for the last added frame and any subsequent 
  96.      * frames. Since all colors are subject to modification in the quantization 
  97.      * process, the color in the final palette for each frame closest to the 
  98.      * given color becomes the transparent color for that frame. May be set to 
  99.      * null to indicate no transparent color. 
  100.      *  
  101.      * @param c 
  102.      *            Color to be treated as transparent on display. 
  103.      */  
  104.     public void setTransparent(Color c) {  
  105.         transparent = c;  
  106.     }  
  107.   
  108.     /** 
  109.      * Adds next GIF frame. The frame is not written immediately, but is 
  110.      * actually deferred until the next frame is received so that timing data 
  111.      * can be inserted. Invoking <code>finish()</code> flushes all frames. If 
  112.      * <code>setSize</code> was not invoked, the size of the first image is used 
  113.      * for all subsequent frames. 
  114.      *  
  115.      * @param im 
  116.      *            BufferedImage containing frame to write. 
  117.      * @return true if successful. 
  118.      */  
  119.     public boolean addFrame(BufferedImage im) {  
  120.         if ((im == null) || !started) {  
  121.             return false;  
  122.         }  
  123.         boolean ok = true;  
  124.         try {  
  125.             if (!sizeSet) {  
  126.                 // use first frame's size  
  127.                 setSize(im.getWidth(), im.getHeight());  
  128.             }  
  129.             image = im;  
  130.             getImagePixels(); // convert to correct format if necessary  
  131.             analyzePixels(); // build color table & map pixels  
  132.             if (firstFrame) {  
  133.                 writeLSD(); // logical screen descriptior  
  134.                 writePalette(); // global color table  
  135.                 if (repeat >= 0) {  
  136.                     // use NS app extension to indicate reps  
  137.                     writeNetscapeExt();  
  138.                 }  
  139.             }  
  140.             writeGraphicCtrlExt(); // write graphic control extension  
  141.             writeImageDesc(); // image descriptor  
  142.             if (!firstFrame) {  
  143.                 writePalette(); // local color table  
  144.             }  
  145.             writePixels(); // encode and write pixel data  
  146.             firstFrame = false;  
  147.         } catch (IOException e) {  
  148.             ok = false;  
  149.         }  
  150.   
  151.         return ok;  
  152.     }  
  153.   
  154.     // added by alvaro  
  155.     public boolean outFlush() {  
  156.         boolean ok = true;  
  157.         try {  
  158.             out.flush();  
  159.             return ok;  
  160.         } catch (IOException e) {  
  161.             ok = false;  
  162.         }  
  163.   
  164.         return ok;  
  165.     }  
  166.   
  167.     public byte[] getFrameByteArray() {  
  168.         return ((ByteArrayOutputStream) out).toByteArray();  
  169.     }  
  170.   
  171.     /** 
  172.      * Flushes any pending data and closes output file. If writing to an 
  173.      * OutputStream, the stream is not closed. 
  174.      */  
  175.     public boolean finish() {  
  176.         if (!started)  
  177.             return false;  
  178.         boolean ok = true;  
  179.         started = false;  
  180.         try {  
  181.             out.write(0x3b); // gif trailer  
  182.             out.flush();  
  183.             if (closeStream) {  
  184.                 out.close();  
  185.             }  
  186.         } catch (IOException e) {  
  187.             ok = false;  
  188.         }  
  189.   
  190.         return ok;  
  191.     }  
  192.   
  193.     public void reset() {  
  194.         // reset for subsequent use  
  195.         transIndex = 0;  
  196.         out = null;  
  197.         image = null;  
  198.         pixels = null;  
  199.         indexedPixels = null;  
  200.         colorTab = null;  
  201.         closeStream = false;  
  202.         firstFrame = true;  
  203.     }  
  204.   
  205.     /** 
  206.      * Sets frame rate in frames per second. Equivalent to 
  207.      * <code>setDelay(1000/fps)</code>. 
  208.      *  
  209.      * @param fps 
  210.      *            float frame rate (frames per second) 
  211.      */  
  212.     public void setFrameRate(float fps) {  
  213.         if (fps != 0f) {  
  214.             delay = Math.round(100f / fps);  
  215.         }  
  216.     }  
  217.   
  218.     /** 
  219.      * Sets quality of color quantization (conversion of images to the maximum 
  220.      * 256 colors allowed by the GIF specification). Lower values (minimum = 1) 
  221.      * produce better colors, but slow processing significantly. 10 is the 
  222.      * default, and produces good color mapping at reasonable speeds. Values 
  223.      * greater than 20 do not yield significant improvements in speed. 
  224.      *  
  225.      * @param quality 
  226.      *            int greater than 0. 
  227.      * @return 
  228.      */  
  229.     public void setQuality(int quality) {  
  230.         if (quality < 1)  
  231.             quality = 1;  
  232.         sample = quality;  
  233.     }  
  234.   
  235.     /** 
  236.      * Sets the GIF frame size. The default size is the size of the first frame 
  237.      * added if this method is not invoked. 
  238.      *  
  239.      * @param w 
  240.      *            int frame width. 
  241.      * @param h 
  242.      *            int frame width. 
  243.      */  
  244.     public void setSize(int w, int h) {  
  245.         if (started && !firstFrame)  
  246.             return;  
  247.         width = w;  
  248.         height = h;  
  249.         if (width < 1)  
  250.             width = 320;  
  251.         if (height < 1)  
  252.             height = 240;  
  253.         sizeSet = true;  
  254.     }  
  255.   
  256.     /** 
  257.      * Initiates GIF file creation on the given stream. The stream is not closed 
  258.      * automatically. 
  259.      *  
  260.      * @param os 
  261.      *            OutputStream on which GIF images are written. 
  262.      * @return false if initial write failed. 
  263.      */  
  264.     public boolean start(OutputStream os) {  
  265.         if (os == null)  
  266.             return false;  
  267.         boolean ok = true;  
  268.         closeStream = false;  
  269.         out = os;  
  270.         try {  
  271.             writeString("GIF89a"); // header  
  272.         } catch (IOException e) {  
  273.             ok = false;  
  274.         }  
  275.         return started = ok;  
  276.     }  
  277.   
  278.     /** 
  279.      * Initiates writing of a GIF file with the specified name. 
  280.      *  
  281.      * @param file 
  282.      *            String containing output file name. 
  283.      * @return false if open or initial write failed. 
  284.      */  
  285.     public boolean start(String file) {  
  286.         boolean ok = true;  
  287.         try {  
  288.             out = new BufferedOutputStream(new FileOutputStream(file));  
  289.             ok = start(out);  
  290.             closeStream = true;  
  291.         } catch (IOException e) {  
  292.             ok = false;  
  293.         }  
  294.         return started = ok;  
  295.     }  
  296.   
  297.     /** 
  298.      * Analyzes image colors and creates color map. 
  299.      */  
  300.     protected void analyzePixels() {  
  301.         int len = pixels.length;  
  302.         int nPix = len / 3;  
  303.         indexedPixels = new byte[nPix];  
  304.         Quant nq = new Quant(pixels, len, sample);  
  305.         // initialize quantizer  
  306.         colorTab = nq.process(); // create reduced palette  
  307.         // convert map from BGR to RGB  
  308.         for (int i = 0; i < colorTab.length; i += 3) {  
  309.             byte temp = colorTab[i];  
  310.             colorTab[i] = colorTab[i + 2];  
  311.             colorTab[i + 2] = temp;  
  312.             usedEntry[i / 3] = false;  
  313.         }  
  314.         // map image pixels to new palette  
  315.         int k = 0;  
  316.         for (int i = 0; i < nPix; i++) {  
  317.             int index = nq.map(pixels[k++] & 0xff, pixels[k++] & 0xff,  
  318.                     pixels[k++] & 0xff);  
  319.             usedEntry[index] = true;  
  320.             indexedPixels[i] = (byte) index;  
  321.         }  
  322.         pixels = null;  
  323.         colorDepth = 8;  
  324.         palSize = 7;  
  325.         // get closest match to transparent color if specified  
  326.         if (transparent != null) {  
  327.             transIndex = findClosest(transparent);  
  328.         }  
  329.     }  
  330.   
  331.     /** 
  332.      * Returns index of palette color closest to c 
  333.      *  
  334.      */  
  335.     protected int findClosest(Color c) {  
  336.         if (colorTab == null)  
  337.             return -1;  
  338.         int r = c.getRed();  
  339.         int g = c.getGreen();  
  340.         int b = c.getBlue();  
  341.         int minpos = 0;  
  342.         int dmin = 256 * 256 * 256;  
  343.         int len = colorTab.length;  
  344.         for (int i = 0; i < len;) {  
  345.             int dr = r - (colorTab[i++] & 0xff);  
  346.             int dg = g - (colorTab[i++] & 0xff);  
  347.             int db = b - (colorTab[i] & 0xff);  
  348.             int d = dr * dr + dg * dg + db * db;  
  349.             int index = i / 3;  
  350.             if (usedEntry[index] && (d < dmin)) {  
  351.                 dmin = d;  
  352.                 minpos = index;  
  353.             }  
  354.             i++;  
  355.         }  
  356.         return minpos;  
  357.     }  
  358.   
  359.     /** 
  360.      * Extracts image pixels into byte array "pixels" 
  361.      */  
  362.     protected void getImagePixels() {  
  363.         int w = image.getWidth();  
  364.         int h = image.getHeight();  
  365.         int type = image.getType();  
  366.         if ((w != width) || (h != height)  
  367.                 || (type != BufferedImage.TYPE_3BYTE_BGR)) {  
  368.             // create new image with right size/format  
  369.             BufferedImage temp = new BufferedImage(width, height,  
  370.                     BufferedImage.TYPE_3BYTE_BGR);  
  371.             Graphics2D g = temp.createGraphics();  
  372.             g.drawImage(image, 00null);  
  373.             image = temp;  
  374.         }  
  375.         pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();  
  376.     }  
  377.   
  378.     /** 
  379.      * Writes Graphic Control Extension 
  380.      */  
  381.     protected void writeGraphicCtrlExt() throws IOException {  
  382.         out.write(0x21); // extension introducer  
  383.         out.write(0xf9); // GCE label  
  384.         out.write(4); // data block size  
  385.         int transp, disp;  
  386.         if (transparent == null) {  
  387.             transp = 0;  
  388.             disp = 0// dispose = no action  
  389.         } else {  
  390.             transp = 1;  
  391.             disp = 2// force clear if using transparent color  
  392.         }  
  393.         if (dispose >= 0) {  
  394.             disp = dispose & 7// user override  
  395.         }  
  396.         disp <<= 2;  
  397.   
  398.         // packed fields  
  399.         out.write(0 | // 1:3 reserved  
  400.                 disp | // 4:6 disposal  
  401.                 0 | // 7 user input - 0 = none  
  402.                 transp); // 8 transparency flag  
  403.   
  404.         writeShort(delay); // delay x 1/100 sec  
  405.         out.write(transIndex); // transparent color index  
  406.         out.write(0); // block terminator  
  407.     }  
  408.   
  409.     /** 
  410.      * Writes Image Descriptor 
  411.      */  
  412.     protected void writeImageDesc() throws IOException {  
  413.         out.write(0x2c); // image separator  
  414.         writeShort(0); // image position x,y = 0,0  
  415.         writeShort(0);  
  416.         writeShort(width); // image size  
  417.         writeShort(height);  
  418.         // packed fields  
  419.         if (firstFrame) {  
  420.             // no LCT - GCT is used for first (or only) frame  
  421.             out.write(0);  
  422.         } else {  
  423.             // specify normal LCT  
  424.             out.write(0x80 | // 1 local color table 1=yes  
  425.                     0 | // 2 interlace - 0=no  
  426.                     0 | // 3 sorted - 0=no  
  427.                     0 | // 4-5 reserved  
  428.                     palSize); // 6-8 size of color table  
  429.         }  
  430.     }  
  431.   
  432.     /** 
  433.      * Writes Logical Screen Descriptor 
  434.      */  
  435.     protected void writeLSD() throws IOException {  
  436.         // logical screen size  
  437.         writeShort(width);  
  438.         writeShort(height);  
  439.         // packed fields  
  440.         out.write((0x80 | // 1 : global color table flag = 1 (gct used)  
  441.         0x70 | // 2-4 : color resolution = 7  
  442.         0x00 | // 5 : gct sort flag = 0  
  443.         palSize)); // 6-8 : gct size  
  444.   
  445.         out.write(0); // background color index  
  446.         out.write(0); // pixel aspect ratio - assume 1:1  
  447.     }  
  448.   
  449.     /** 
  450.      * Writes Netscape application extension to define repeat count. 
  451.      */  
  452.     protected void writeNetscapeExt() throws IOException {  
  453.         out.write(0x21); // extension introducer  
  454.         out.write(0xff); // app extension label  
  455.         out.write(11); // block size  
  456.         writeString("NETSCAPE" + "2.0"); // app id + auth code  
  457.         out.write(3); // sub-block size  
  458.         out.write(1); // loop sub-block id  
  459.         writeShort(repeat); // loop count (extra iterations, 0=repeat forever)  
  460.         out.write(0); // block terminator  
  461.     }  
  462.   
  463.     /** 
  464.      * Writes color table 
  465.      */  
  466.     protected void writePalette() throws IOException {  
  467.         out.write(colorTab, 0, colorTab.length);  
  468.         int n = (3 * 256) - colorTab.length;  
  469.         for (int i = 0; i < n; i++) {  
  470.             out.write(0);  
  471.         }  
  472.     }  
  473.   
  474.     /** 
  475.      * Encodes and writes pixel data 
  476.      */  
  477.     protected void writePixels() throws IOException {  
  478.         Encoder encoder = new Encoder(width, height, indexedPixels, colorDepth);  
  479.         encoder.encode(out);  
  480.     }  
  481.   
  482.     /** 
  483.      * Write 16-bit value to output stream, LSB first 
  484.      */  
  485.     protected void writeShort(int value) throws IOException {  
  486.         out.write(value & 0xff);  
  487.         out.write((value >> 8) & 0xff);  
  488.     }  
  489.   
  490.     /** 
  491.      * Writes string to output stream 
  492.      */  
  493.     protected void writeString(String s) throws IOException {  
  494.         for (int i = 0; i < s.length(); i++) {  
  495.             out.write((byte) s.charAt(i));  
  496.         }  
  497.     }  
  498. }  

 

Java代码  收藏代码
  1. /** 
  2.  *  
  3.  * @author wzztestin 
  4.  * 
  5.  */  
  6. public class Quant {  
  7.     protected static final int netsize = 256/* number of colours used */  
  8.   
  9.     /* four primes near 500 - assume no image has a length so large */  
  10.     /* that it is divisible by all four primes */  
  11.     protected static final int prime1 = 499;  
  12.     protected static final int prime2 = 491;  
  13.     protected static final int prime3 = 487;  
  14.     protected static final int prime4 = 503;  
  15.   
  16.     protected static final int minpicturebytes = (3 * prime4);  
  17.     /* minimum size for input image */  
  18.   
  19.     /* 
  20.      * Program Skeleton ---------------- [select samplefac in range 1..30] [read 
  21.      * image from input file] pic = (unsigned char*) malloc(3*width*height); 
  22.      * initnet(pic,3*width*height,samplefac); learn(); unbiasnet(); [write 
  23.      * output image header, using writecolourmap(f)] inxbuild(); write output 
  24.      * image using inxsearch(b,g,r) 
  25.      */  
  26.   
  27.     /* 
  28.      * Network Definitions ------------------- 
  29.      */  
  30.   
  31.     protected static final int maxnetpos = (netsize - 1);  
  32.     protected static final int netbiasshift = 4/* bias for colour values */  
  33.     protected static final int ncycles = 100/* no. of learning cycles */  
  34.   
  35.     /* defs for freq and bias */  
  36.     protected static final int intbiasshift = 16/* bias for fractions */  
  37.     protected static final int intbias = (((int1) << intbiasshift);  
  38.     protected static final int gammashift = 10/* gamma = 1024 */  
  39.     protected static final int gamma = (((int1) << gammashift);  
  40.     protected static final int betashift = 10;  
  41.     protected static final int beta = (intbias >> betashift); /* beta = 1/1024 */  
  42.     protected static final int betagamma = (intbias << (gammashift - betashift));  
  43.   
  44.     /* defs for decreasing radius factor */  
  45.     protected static final int initrad = (netsize >> 3); /* 
  46.                                                          * for 256 cols, radius 
  47.                                                          * starts 
  48.                                                          */  
  49.     protected static final int radiusbiasshift = 6/* at 32.0 biased by 6 bits */  
  50.     protected static final int radiusbias = (((int1) << radiusbiasshift);  
  51.     protected static final int initradius = (initrad * radiusbias); /* 
  52.                                                                      * and 
  53.                                                                      * decreases 
  54.                                                                      * by a 
  55.                                                                      */  
  56.     protected static final int radiusdec = 30/* factor of 1/30 each cycle */  
  57.   
  58.     /* defs for decreasing alpha factor */  
  59.     protected static final int alphabiasshift = 10/* alpha starts at 1.0 */  
  60.     protected static final int initalpha = (((int1) << alphabiasshift);  
  61.   
  62.     protected int alphadec; /* biased by 10 bits */  
  63.   
  64.     /* radbias and alpharadbias used for radpower calculation */  
  65.     protected static final int radbiasshift = 8;  
  66.     protected static final int radbias = (((int1) << radbiasshift);  
  67.     protected static final int alpharadbshift = (alphabiasshift + radbiasshift);  
  68.     protected static final int alpharadbias = (((int1) << alpharadbshift);  
  69.   
  70.     /* 
  71.      * Types and Global Variables -------------------------- 
  72.      */  
  73.   
  74.     protected byte[] thepicture; /* the input image itself */  
  75.     protected int lengthcount; /* lengthcount = H*W*3 */  
  76.   
  77.     protected int samplefac; /* sampling factor 1..30 */  
  78.   
  79.     // typedef int pixel[4]; /* BGRc */  
  80.     protected int[][] network; /* the network itself - [netsize][4] */  
  81.   
  82.     protected int[] netindex = new int[256];  
  83.     /* for network lookup - really 256 */  
  84.   
  85.     protected int[] bias = new int[netsize];  
  86.     /* bias and freq arrays for learning */  
  87.     protected int[] freq = new int[netsize];  
  88.     protected int[] radpower = new int[initrad];  
  89.   
  90.     /* radpower for precomputation */  
  91.   
  92.     /* 
  93.      * Initialise network in range (0,0,0) to (255,255,255) and set parameters 
  94.      * ----------------------------------------------------------------------- 
  95.      */  
  96.     public Quant(byte[] thepic, int len, int sample) {  
  97.   
  98.         int i;  
  99.         int[] p;  
  100.   
  101.         thepicture = thepic;  
  102.         lengthcount = len;  
  103.         samplefac = sample;  
  104.   
  105.         network = new int[netsize][];  
  106.         for (i = 0; i < netsize; i++) {  
  107.             network[i] = new int[4];  
  108.             p = network[i];  
  109.             p[0] = p[1] = p[2] = (i << (netbiasshift + 8)) / netsize;  
  110.             freq[i] = intbias / netsize; /* 1/netsize */  
  111.             bias[i] = 0;  
  112.         }  
  113.     }  
  114.   
  115.     public byte[] colorMap() {  
  116.         byte[] map = new byte[3 * netsize];  
  117.         int[] index = new int[netsize];  
  118.         for (int i = 0; i < netsize; i++)  
  119.             index[network[i][3]] = i;  
  120.         int k = 0;  
  121.         for (int i = 0; i < netsize; i++) {  
  122.             int j = index[i];  
  123.             map[k++] = (byte) (network[j][0]);  
  124.             map[k++] = (byte) (network[j][1]);  
  125.             map[k++] = (byte) (network[j][2]);  
  126.         }  
  127.         return map;  
  128.     }  
  129.   
  130.     /* 
  131.      * Insertion sort of network and building of netindex[0..255] (to do after 
  132.      * unbias) 
  133.      * ------------------------------------------------------------------ 
  134.      * ------------- 
  135.      */  
  136.     public void inxbuild() {  
  137.   
  138.         int i, j, smallpos, smallval;  
  139.         int[] p;  
  140.         int[] q;  
  141.         int previouscol, startpos;  
  142.   
  143.         previouscol = 0;  
  144.         startpos = 0;  
  145.         for (i = 0; i < netsize; i++) {  
  146.             p = network[i];  
  147.             smallpos = i;  
  148.             smallval = p[1]; /* index on g */  
  149.             /* find smallest in i..netsize-1 */  
  150.             for (j = i + 1; j < netsize; j++) {  
  151.                 q = network[j];  
  152.                 if (q[1] < smallval) { /* index on g */  
  153.                     smallpos = j;  
  154.                     smallval = q[1]; /* index on g */  
  155.                 }  
  156.             }  
  157.             q = network[smallpos];  
  158.             /* swap p (i) and q (smallpos) entries */  
  159.             if (i != smallpos) {  
  160.                 j = q[0];  
  161.                 q[0] = p[0];  
  162.                 p[0] = j;  
  163.                 j = q[1];  
  164.                 q[1] = p[1];  
  165.                 p[1] = j;  
  166.                 j = q[2];  
  167.                 q[2] = p[2];  
  168.                 p[2] = j;  
  169.                 j = q[3];  
  170.                 q[3] = p[3];  
  171.                 p[3] = j;  
  172.             }  
  173.             /* smallval entry is now in position i */  
  174.             if (smallval != previouscol) {  
  175.                 netindex[previouscol] = (startpos + i) >> 1;  
  176.                 for (j = previouscol + 1; j < smallval; j++)  
  177.                     netindex[j] = i;  
  178.                 previouscol = smallval;  
  179.                 startpos = i;  
  180.             }  
  181.         }  
  182.         netindex[previouscol] = (startpos + maxnetpos) >> 1;  
  183.         for (j = previouscol + 1; j < 256; j++)  
  184.             netindex[j] = maxnetpos; /* really 256 */  
  185.     }  
  186.   
  187.     /* 
  188.      * Main Learning Loop ------------------ 
  189.      */  
  190.     public void learn() {  
  191.   
  192.         int i, j, b, g, r;  
  193.         int radius, rad, alpha, step, delta, samplepixels;  
  194.         byte[] p;  
  195.         int pix, lim;  
  196.   
  197.         if (lengthcount < minpicturebytes)  
  198.             samplefac = 1;  
  199.         alphadec = 30 + ((samplefac - 1) / 3);  
  200.         p = thepicture;  
  201.         pix = 0;  
  202.         lim = lengthcount;  
  203.         samplepixels = lengthcount / (3 * samplefac);  
  204.         delta = samplepixels / ncycles;  
  205.         alpha = initalpha;  
  206.         radius = initradius;  
  207.   
  208.         rad = radius >> radiusbiasshift;  
  209.         if (rad <= 1)  
  210.             rad = 0;  
  211.         for (i = 0; i < rad; i++)  
  212.             radpower[i] = alpha  
  213.                     * (((rad * rad - i * i) * radbias) / (rad * rad));  
  214.   
  215.         // fprintf(stderr,"beginning 1D learning: initial radius=%d\n", rad);  
  216.   
  217.         if (lengthcount < minpicturebytes)  
  218.             step = 3;  
  219.         else if ((lengthcount % prime1) != 0)  
  220.             step = 3 * prime1;  
  221.         else {  
  222.             if ((lengthcount % prime2) != 0)  
  223.                 step = 3 * prime2;  
  224.             else {  
  225.                 if ((lengthcount % prime3) != 0)  
  226.                     step = 3 * prime3;  
  227.                 else  
  228.                     step = 3 * prime4;  
  229.             }  
  230.         }  
  231.   
  232.         i = 0;  
  233.         while (i < samplepixels) {  
  234.             b = (p[pix + 0] & 0xff) << netbiasshift;  
  235.             g = (p[pix + 1] & 0xff) << netbiasshift;  
  236.             r = (p[pix + 2] & 0xff) << netbiasshift;  
  237.             j = contest(b, g, r);  
  238.   
  239.             altersingle(alpha, j, b, g, r);  
  240.             if (rad != 0)  
  241.                 alterneigh(rad, j, b, g, r); /* alter neighbours */  
  242.   
  243.             pix += step;  
  244.             if (pix >= lim)  
  245.                 pix -= lengthcount;  
  246.   
  247.             i++;  
  248.             if (delta == 0)  
  249.                 delta = 1;  
  250.             if (i % delta == 0) {  
  251.                 alpha -= alpha / alphadec;  
  252.                 radius -= radius / radiusdec;  
  253.                 rad = radius >> radiusbiasshift;  
  254.                 if (rad <= 1)  
  255.                     rad = 0;  
  256.                 for (j = 0; j < rad; j++)  
  257.                     radpower[j] = alpha  
  258.                             * (((rad * rad - j * j) * radbias) / (rad * rad));  
  259.             }  
  260.         }  
  261.         // fprintf(stderr,"finished 1D learning: final alpha=%f !\n",((float)alpha)/initalpha);  
  262.     }  
  263.   
  264.     /* 
  265.      * Search for BGR values 0..255 (after net is unbiased) and return colour 
  266.      * index 
  267.      * -------------------------------------------------------------------- 
  268.      * -------- 
  269.      */  
  270.     public int map(int b, int g, int r) {  
  271.   
  272.         int i, j, dist, a, bestd;  
  273.         int[] p;  
  274.         int best;  
  275.   
  276.         bestd = 1000/* biggest possible dist is 256*3 */  
  277.         best = -1;  
  278.         i = netindex[g]; /* index on g */  
  279.         j = i - 1/* start at netindex[g] and work outwards */  
  280.   
  281.         while ((i < netsize) || (j >= 0)) {  
  282.             if (i < netsize) {  
  283.                 p = network[i];  
  284.                 dist = p[1] - g; /* inx key */  
  285.                 if (dist >= bestd)  
  286.                     i = netsize; /* stop iter */  
  287.                 else {  
  288.                     i++;  
  289.                     if (dist < 0)  
  290.                         dist = -dist;  
  291.                     a = p[0] - b;  
  292.                     if (a < 0)  
  293.                         a = -a;  
  294.                     dist += a;  
  295.                     if (dist < bestd) {  
  296.                         a = p[2] - r;  
  297.                         if (a < 0)  
  298.                             a = -a;  
  299.                         dist += a;  
  300.                         if (dist < bestd) {  
  301.                             bestd = dist;  
  302.                             best = p[3];  
  303.                         }  
  304.                     }  
  305.                 }  
  306.             }  
  307.             if (j >= 0) {  
  308.                 p = network[j];  
  309.                 dist = g - p[1]; /* inx key - reverse dif */  
  310.                 if (dist >= bestd)  
  311.                     j = -1/* stop iter */  
  312.                 else {  
  313.                     j--;  
  314.                     if (dist < 0)  
  315.                         dist = -dist;  
  316.                     a = p[0] - b;  
  317.                     if (a < 0)  
  318.                         a = -a;  
  319.                     dist += a;  
  320.                     if (dist < bestd) {  
  321.                         a = p[2] - r;  
  322.                         if (a < 0)  
  323.                             a = -a;  
  324.                         dist += a;  
  325.                         if (dist < bestd) {  
  326.                             bestd = dist;  
  327.                             best = p[3];  
  328.                         }  
  329.                     }  
  330.                 }  
  331.             }  
  332.         }  
  333.         return (best);  
  334.     }  
  335.   
  336.     public byte[] process() {  
  337.         learn();  
  338.         unbiasnet();  
  339.         inxbuild();  
  340.         return colorMap();  
  341.     }  
  342.   
  343.     /* 
  344.      * Unbias network to give byte values 0..255 and record position i to 
  345.      * prepare for sort 
  346.      * ---------------------------------------------------------- 
  347.      * ------------------------- 
  348.      */  
  349.     @SuppressWarnings("unused")  
  350.     public void unbiasnet() {  
  351.   
  352.         int i, j;  
  353.   
  354.         for (i = 0; i < netsize; i++) {  
  355.             network[i][0] >>= netbiasshift;  
  356.             network[i][1] >>= netbiasshift;  
  357.             network[i][2] >>= netbiasshift;  
  358.             network[i][3] = i; /* record colour no */  
  359.         }  
  360.     }  
  361.   
  362.     /* 
  363.      * Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in 
  364.      * radpower[|i-j|] 
  365.      * ---------------------------------------------------------- 
  366.      * ----------------------- 
  367.      */  
  368.     protected void alterneigh(int rad, int i, int b, int g, int r) {  
  369.   
  370.         int j, k, lo, hi, a, m;  
  371.         int[] p;  
  372.   
  373.         lo = i - rad;  
  374.         if (lo < -1)  
  375.             lo = -1;  
  376.         hi = i + rad;  
  377.         if (hi > netsize)  
  378.             hi = netsize;  
  379.   
  380.         j = i + 1;  
  381.         k = i - 1;  
  382.         m = 1;  
  383.         while ((j < hi) || (k > lo)) {  
  384.             a = radpower[m++];  
  385.             if (j < hi) {  
  386.                 p = network[j++];  
  387.                 try {  
  388.                     p[0] -= (a * (p[0] - b)) / alpharadbias;  
  389.                     p[1] -= (a * (p[1] - g)) / alpharadbias;  
  390.                     p[2] -= (a * (p[2] - r)) / alpharadbias;  
  391.                 } catch (Exception e) {  
  392.                 } // prevents 1.3 miscompilation  
  393.             }  
  394.             if (k > lo) {  
  395.                 p = network[k--];  
  396.                 try {  
  397.                     p[0] -= (a * (p[0] - b)) / alpharadbias;  
  398.                     p[1] -= (a * (p[1] - g)) / alpharadbias;  
  399.                     p[2] -= (a * (p[2] - r)) / alpharadbias;  
  400.                 } catch (Exception e) {  
  401.                 }  
  402.             }  
  403.         }  
  404.     }  
  405.   
  406.     /* 
  407.      * Move neuron i towards biased (b,g,r) by factor alpha 
  408.      * ---------------------------------------------------- 
  409.      */  
  410.     protected void altersingle(int alpha, int i, int b, int g, int r) {  
  411.   
  412.         /* alter hit neuron */  
  413.         int[] n = network[i];  
  414.         n[0] -= (alpha * (n[0] - b)) / initalpha;  
  415.         n[1] -= (alpha * (n[1] - g)) / initalpha;  
  416.         n[2] -= (alpha * (n[2] - r)) / initalpha;  
  417.     }  
  418.   
  419.     /* 
  420.      * Search for biased BGR values ---------------------------- 
  421.      */  
  422.     protected int contest(int b, int g, int r) {  
  423.   
  424.         /* finds closest neuron (min dist) and updates freq */  
  425.         /* finds best neuron (min dist-bias) and returns position */  
  426.         /* 
  427.          * for frequently chosen neurons, freq[i] is high and bias[i] is 
  428.          * negative 
  429.          */  
  430.         /* bias[i] = gamma*((1/netsize)-freq[i]) */  
  431.   
  432.         int i, dist, a, biasdist, betafreq;  
  433.         int bestpos, bestbiaspos, bestd, bestbiasd;  
  434.         int[] n;  
  435.   
  436.         bestd = ~(((int1) << 31);  
  437.         bestbiasd = bestd;  
  438.         bestpos = -1;  
  439.         bestbiaspos = bestpos;  
  440.   
  441.         for (i = 0; i < netsize; i++) {  
  442.             n = network[i];  
  443.             dist = n[0] - b;  
  444.             if (dist < 0)  
  445.                 dist = -dist;  
  446.             a = n[1] - g;  
  447.             if (a < 0)  
  448.                 a = -a;  
  449.             dist += a;  
  450.             a = n[2] - r;  
  451.             if (a < 0)  
  452.                 a = -a;  
  453.             dist += a;  
  454.             if (dist < bestd) {  
  455.                 bestd = dist;  
  456.                 bestpos = i;  
  457.             }  
  458.             biasdist = dist - ((bias[i]) >> (intbiasshift - netbiasshift));  
  459.             if (biasdist < bestbiasd) {  
  460.                 bestbiasd = biasdist;  
  461.                 bestbiaspos = i;  
  462.             }  
  463.             betafreq = (freq[i] >> betashift);  
  464.             freq[i] -= betafreq;  
  465.             bias[i] += (betafreq << gammashift);  
  466.         }  
  467.         freq[bestpos] += beta;  
  468.         bias[bestpos] -= betagamma;  
  469.         return (bestbiaspos);  
  470.     }  
  471. }  
0 0