gembin

          OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

          HBase, Hadoop, ZooKeeper, Cassandra

          Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

          There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

          About Me

           

          GifDecoder.java源碼(處理GIF圖片)

           
           

          import java.net.*;
          import java.io.*;
          import java.util.*;
          import java.awt.*;
          import java.awt.image.*;

          public class GifDecoder {

           /**
            * File read status: No errors.
            */
           public static final int STATUS_OK = 0;

           /**
            * File read status: Error decoding file (may be partially decoded)
            */
           public static final int STATUS_FORMAT_ERROR = 1;

           /**
            * File read status: Unable to open source.
            */
           public static final int STATUS_OPEN_ERROR = 2;

           protected BufferedInputStream in;
           protected int status;

           protected int width; // full image width
           protected int height; // full image height
           protected boolean gctFlag; // global color table used
           protected int gctSize; // size of global color table
           protected int loopCount = 1; // iterations; 0 = repeat forever

           protected int[] gct; // global color table
           protected int[] lct; // local color table
           protected int[] act; // active color table

           protected int bgIndex; // background color index
           protected int bgColor; // background color
           protected int lastBgColor; // previous bg color
           protected int pixelAspect; // pixel aspect ratio

           protected boolean lctFlag; // local color table flag
           protected boolean interlace; // interlace flag
           protected int lctSize; // local color table size

           protected int ix, iy, iw, ih; // current image rectangle
           protected Rectangle lastRect; // last image rect
           protected BufferedImage image; // current frame
           protected BufferedImage lastImage; // previous frame

           protected byte[] block = new byte[256]; // current data block
           protected int blockSize = 0; // block size

           // last graphic control extension info
           protected int dispose = 0;
           // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
           protected int lastDispose = 0;
           protected boolean transparency = false; // use transparent color
           protected int delay = 0; // delay in milliseconds
           protected int transIndex; // transparent color index

           protected static final int MaxStackSize = 4096;
           // max decoder pixel stack size

           // LZW decoder working arrays
           protected short[] prefix;
           protected byte[] suffix;
           protected byte[] pixelStack;
           protected byte[] pixels;

           protected ArrayList frames; // frames read from current file
           protected int frameCount;

           static class GifFrame {
            public GifFrame(BufferedImage im, int del) {
             image = im;
             delay = del;
            }
            public BufferedImage image;
            public int delay;
           }

           /**
            * Gets display duration for specified frame.
            *
            * @param n int index of frame
            * @return delay in milliseconds
            */
           public int getDelay(int n) {
            //
            delay = -1;
            if ((n >= 0) && (n < frameCount)) {
             delay = ((GifFrame) frames.get(n)).delay;
            }
            return delay;
           }

           /**
            * Gets the number of frames read from file.
            * @return frame count
            */
           public int getFrameCount() {
            return frameCount;
           }

           /**
            * Gets the first (or only) image read.
            *
            * @return BufferedImage containing first frame, or null if none.
            */
           public BufferedImage getImage() {
            return getFrame(0);
           }

           /**
            * Gets the "Netscape" iteration count, if any.
            * A count of 0 means repeat indefinitiely.
            *
            * @return iteration count if one was specified, else 1.
            */
           public int getLoopCount() {
            return loopCount;
           }

           /**
            * Creates new frame image from current data (and previous
            * frames as specified by their disposition codes).
            */
           protected void setPixels() {
            // expose destination image's pixels as int array
            int[] dest =
             ((DataBufferInt) image.getRaster().getDataBuffer()).getData();

            // fill in starting image contents based on last image's dispose code
            if (lastDispose > 0) {
             if (lastDispose == 3) {
              // use image before last
              int n = frameCount - 2;
              if (n > 0) {
               lastImage = getFrame(n - 1);
              } else {
               lastImage = null;
              }
             }

             if (lastImage != null) {
              int[] prev =
               ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData();
              System.arraycopy(prev, 0, dest, 0, width * height);
              // copy pixels

              if (lastDispose == 2) {
               // fill last image rect area with background color
               Graphics2D g = image.createGraphics();
               Color c = null;
               if (transparency) {
                c = new Color(0, 0, 0, 0);  // assume background is transparent
               } else {
                c = new Color(lastBgColor); // use given background color
               }
               g.setColor(c);
               g.setComposite(AlphaComposite.Src); // replace area
               g.fill(lastRect);
               g.dispose();
              }
             }
            }

            // copy each source line to the appropriate place in the destination
            int pass = 1;
            int inc = 8;
            int iline = 0;
            for (int i = 0; i < ih; i++) {
             int line = i;
             if (interlace) {
              if (iline >= ih) {
               pass++;
               switch (pass) {
                case 2 :
                 iline = 4;
                 break;
                case 3 :
                 iline = 2;
                 inc = 4;
                 break;
                case 4 :
                 iline = 1;
                 inc = 2;
               }
              }
              line = iline;
              iline += inc;
             }
             line += iy;
             if (line < height) {
              int k = line * width;
              int dx = k + ix; // start of line in dest
              int dlim = dx + iw; // end of dest line
              if ((k + width) < dlim) {
               dlim = k + width; // past dest edge
              }
              int sx = i * iw; // start of line in source
              while (dx < dlim) {
               // map color and insert in destination
               int index = ((int) pixels[sx++]) & 0xff;
               int c = act[index];
               if (c != 0) {
                dest[dx] = c;
               }
               dx++;
              }
             }
            }
           }

           /**
            * Gets the image contents of frame n.
            *
            * @return BufferedImage representation of frame, or null if n is invalid.
            */
           public BufferedImage getFrame(int n) {
            BufferedImage im = null;
            if ((n >= 0) && (n < frameCount)) {
             im = ((GifFrame) frames.get(n)).image;
            }
            return im;
           }

           /**
            * Gets image size.
            *
            * @return GIF image dimensions
            */
           public Dimension getFrameSize() {
            return new Dimension(width, height);
           }

           /**
            * Reads GIF image from stream
            *
            * @param BufferedInputStream containing GIF file.
            * @return read status code (0 = no errors)
            */
           public int read(BufferedInputStream is) {
            init();
            if (is != null) {
             in = is;
             readHeader();
             if (!err()) {
              readContents();
              if (frameCount < 0) {
               status = STATUS_FORMAT_ERROR;
              }
             }
            } else {
             status = STATUS_OPEN_ERROR;
            }
            try {
             is.close();
            } catch (IOException e) {
            }
            return status;
           }

           /**
            * Reads GIF image from stream
            *
            * @param InputStream containing GIF file.
            * @return read status code (0 = no errors)
            */
           public int read(InputStream is) {
            init();
            if (is != null) {
             if (!(is instanceof BufferedInputStream))
              is = new BufferedInputStream(is);
             in = (BufferedInputStream) is;
             readHeader();
             if (!err()) {
              readContents();
              if (frameCount < 0) {
               status = STATUS_FORMAT_ERROR;
              }
             }
            } else {
             status = STATUS_OPEN_ERROR;
            }
            try {
             is.close();
            } catch (IOException e) {
            }
            return status;
           }

           /**
            * Reads GIF file from specified file/URL source  
            * (URL assumed if name contains ":/" or "file:")
            *
            * @param name String containing source
            * @return read status code (0 = no errors)
            */
           public int read(String name) {
            status = STATUS_OK;
            try {
             name = name.trim().toLowerCase();
             if ((name.indexOf("file:") >= 0) ||
              (name.indexOf(":/") > 0)) {
              URL url = new URL(name);
              in = new BufferedInputStream(url.openStream());
             } else {
              in = new BufferedInputStream(new FileInputStream(name));
             }
             status = read(in);
            } catch (IOException e) {
             status = STATUS_OPEN_ERROR;
            }

            return status;
           }

           /**
            * Decodes LZW image data into pixel array.
            * Adapted from John Cristy's ImageMagick.
            */
           protected void decodeImageData() {
            int NullCode = -1;
            int npix = iw * ih;
            int available, 
             clear,
             code_mask,
             code_size,
             end_of_information,
             in_code,
             old_code,
             bits,
             code,
             count,
             i,
             datum,
             data_size,
             first,
             top,
             bi,
             pi;

            if ((pixels == null) || (pixels.length < npix)) {
             pixels = new byte[npix]; // allocate new pixel array
            }
            if (prefix == null) prefix = new short[MaxStackSize];
            if (suffix == null) suffix = new byte[MaxStackSize];
            if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1];

            //  Initialize GIF data stream decoder.

            data_size = read();
            clear = 1 << data_size;
            end_of_information = clear + 1;
            available = clear + 2;
            old_code = NullCode;
            code_size = data_size + 1;
            code_mask = (1 << code_size) - 1;
            for (code = 0; code < clear; code++) {
             prefix[code] = 0;
             suffix[code] = (byte) code;
            }

            //  Decode GIF pixel stream.

            datum = bits = count = first = top = pi = bi = 0;

            for (i = 0; i < npix;) {
             if (top == 0) {
              if (bits < code_size) {
               //  Load bytes until there are enough bits for a code.
               if (count == 0) {
                // Read a new data block.
                count = readBlock();
                if (count <= 0)
                 break;
                bi = 0;
               }
               datum += (((int) block[bi]) & 0xff) << bits;
               bits += 8;
               bi++;
               count--;
               continue;
              }

              //  Get the next code.

              code = datum & code_mask;
              datum >>= code_size;
              bits -= code_size;

              //  Interpret the code

              if ((code > available) || (code == end_of_information))
               break;
              if (code == clear) {
               //  Reset decoder.
               code_size = data_size + 1;
               code_mask = (1 << code_size) - 1;
               available = clear + 2;
               old_code = NullCode;
               continue;
              }
              if (old_code == NullCode) {
               pixelStack[top++] = suffix[code];
               old_code = code;
               first = code;
               continue;
              }
              in_code = code;
              if (code == available) {
               pixelStack[top++] = (byte) first;
               code = old_code;
              }
              while (code > clear) {
               pixelStack[top++] = suffix[code];
               code = prefix[code];
              }
              first = ((int) suffix[code]) & 0xff;

              //  Add a new string to the string table,

              if (available >= MaxStackSize)
               break;
              pixelStack[top++] = (byte) first;
              prefix[available] = (short) old_code;
              suffix[available] = (byte) first;
              available++;
              if (((available & code_mask) == 0)
               && (available < MaxStackSize)) {
               code_size++;
               code_mask += available;
              }
              old_code = in_code;
             }

             //  Pop a pixel off the pixel stack.

             top--;
             pixels[pi++] = pixelStack[top];
             i++;
            }

            for (i = pi; i < npix; i++) {
             pixels[i] = 0; // clear missing pixels
            }

           }

           /**
            * Returns true if an error was encountered during reading/decoding
            */
           protected boolean err() {
            return status != STATUS_OK;
           }

           /**
            * Initializes or re-initializes reader
            */
           protected void init() {
            status = STATUS_OK;
            frameCount = 0;
            frames = new ArrayList();
            gct = null;
            lct = null;
           }

           /**
            * Reads a single byte from the input stream.
            */
           protected int read() {
            int curByte = 0;
            try {
             curByte = in.read();
            } catch (IOException e) {
             status = STATUS_FORMAT_ERROR;
            }
            return curByte;
           }

           /**
            * Reads next variable length block from input.
            *
            * @return number of bytes stored in "buffer"
            */
           protected int readBlock() {
            blockSize = read();
            int n = 0;
            if (blockSize > 0) {
             try {
              int count = 0;
              while (n < blockSize) {
               count = in.read(block, n, blockSize - n);
               if (count == -1) 
                break;
               n += count;
              }
             } catch (IOException e) {
             }

             if (n < blockSize) {
              status = STATUS_FORMAT_ERROR;
             }
            }
            return n;
           }

           /**
            * Reads color table as 256 RGB integer values
            *
            * @param ncolors int number of colors to read
            * @return int array containing 256 colors (packed ARGB with full alpha)
            */
           protected int[] readColorTable(int ncolors) {
            int nbytes = 3 * ncolors;
            int[] tab = null;
            byte[] c = new byte[nbytes];
            int n = 0;
            try {
             n = in.read(c);
            } catch (IOException e) {
            }
            if (n < nbytes) {
             status = STATUS_FORMAT_ERROR;
            } else {
             tab = new int[256]; // max size to avoid bounds checks
             int i = 0;
             int j = 0;
             while (i < ncolors) {
              int r = ((int) c[j++]) & 0xff;
              int g = ((int) c[j++]) & 0xff;
              int b = ((int) c[j++]) & 0xff;
              tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
             }
            }
            return tab;
           }

           /**
            * Main file parser.  Reads GIF content blocks.
            */
           protected void readContents() {
            // read GIF file content blocks
            boolean done = false;
            while (!(done || err())) {
             int code = read();
             switch (code) {

              case 0x2C : // image separator
               readImage();
               break;

              case 0x21 : // extension
               code = read();
               switch (code) {
                case 0xf9 : // graphics control extension
                 readGraphicControlExt();
                 break;

                case 0xff : // application extension
                 readBlock();
                 String app = "";
                 for (int i = 0; i < 11; i++) {
                  app += (char) block[i];
                 }
                 if (app.equals("NETSCAPE2.0")) {
                  readNetscapeExt();
                 }
                 else
                  skip(); // don't care
                 break;

                default : // uninteresting extension
                 skip();
               }
               break;

              case 0x3b : // terminator
               done = true;
               break;

              case 0x00 : // bad byte, but keep going and see what happens
               break;

              default :
               status = STATUS_FORMAT_ERROR;
             }
            }
           }

           /**
            * Reads Graphics Control Extension values
            */
           protected void readGraphicControlExt() {
            read(); // block size
            int packed = read(); // packed fields
            dispose = (packed & 0x1c) >> 2; // disposal method
            if (dispose == 0) {
             dispose = 1; // elect to keep old image if discretionary
            }
            transparency = (packed & 1) != 0;
            delay = readShort() * 10; // delay in milliseconds
            transIndex = read(); // transparent color index
            read(); // block terminator
           }

           /**
            * Reads GIF file header information.
            */
           protected void readHeader() {
            String id = "";
            for (int i = 0; i < 6; i++) {
             id += (char) read();
            }
            if (!id.startsWith("GIF")) {
             status = STATUS_FORMAT_ERROR;
             return;
            }

            readLSD();
            if (gctFlag && !err()) {
             gct = readColorTable(gctSize);
             bgColor = gct[bgIndex];
            }
           }

           /**
            * Reads next frame image
            */
           protected void readImage() {
            ix = readShort(); // (sub)image position & size
            iy = readShort();
            iw = readShort();
            ih = readShort();

            int packed = read();
            lctFlag = (packed & 0x80) != 0; // 1 - local color table flag
            interlace = (packed & 0x40) != 0; // 2 - interlace flag
            // 3 - sort flag
            // 4-5 - reserved
            lctSize = 2 << (packed & 7); // 6-8 - local color table size

            if (lctFlag) {
             lct = readColorTable(lctSize); // read table
             act = lct; // make local table active
            } else {
             act = gct; // make global table active
             if (bgIndex == transIndex)
              bgColor = 0;
            }
            int save = 0;
            if (transparency) {
             save = act[transIndex];
             act[transIndex] = 0; // set transparent color if specified
            }

            if (act == null) {
             status = STATUS_FORMAT_ERROR; // no color table defined
            }

            if (err()) return;

            decodeImageData(); // decode pixel data
            skip();

            if (err()) return;

            frameCount++;

            // create new image to receive frame data
            image =
             new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);

            setPixels(); // transfer pixel data to image

            frames.add(new GifFrame(image, delay)); // add image to frame list

            if (transparency) {
             act[transIndex] = save;
            }
            resetFrame();

           }

           /**
            * Reads Logical Screen Descriptor
            */
           protected void readLSD() {

            // logical screen size
            width = readShort();
            height = readShort();

            // packed fields
            int packed = read();
            gctFlag = (packed & 0x80) != 0; // 1   : global color table flag
            // 2-4 : color resolution
            // 5   : gct sort flag
            gctSize = 2 << (packed & 7); // 6-8 : gct size

            bgIndex = read(); // background color index
            pixelAspect = read(); // pixel aspect ratio
           }

           /**
            * Reads Netscape extenstion to obtain iteration count
            */
           protected void readNetscapeExt() {
            do {
             readBlock();
             if (block[0] == 1) {
              // loop count sub-block
              int b1 = ((int) block[1]) & 0xff;
              int b2 = ((int) block[2]) & 0xff;
              loopCount = (b2 << 8) | b1;
             }
            } while ((blockSize > 0) && !err());
           }

           /**
            * Reads next 16-bit value, LSB first
            */
           protected int readShort() {
            // read 16-bit value, LSB first
            return read() | (read() << 8);
           }

           /**
            * Resets frame state for reading next image.
            */
           protected void resetFrame() {
            lastDispose = dispose;
            lastRect = new Rectangle(ix, iy, iw, ih);
            lastImage = image;
            lastBgColor = bgColor;
            int dispose = 0;
            boolean transparency = false;
            int delay = 0;
            lct = null;
           }


           protected void skip() {
            do {
             readBlock();
            } while ((blockSize > 0) && !err());
           }
          }

          posted on 2007-09-21 11:15 gembin 閱讀(5395) 評論(2)  編輯  收藏

          評論

          # re: GifDecoder.java源碼(處理GIF圖片) 2007-09-22 00:13 千里冰封

          果然很牛,不錯  回復  更多評論   

          # re: GifDecoder.java源碼(處理GIF圖片)[未登錄] 2013-10-22 12:00 xxx

          @千里冰封
          傻逼  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          常用鏈接

          留言簿(6)

          隨筆分類(440)

          隨筆檔案(378)

          文章檔案(6)

          新聞檔案(1)

          相冊

          收藏夾(9)

          Adobe

          Android

          AS3

          Blog-Links

          Build

          Design Pattern

          Eclipse

          Favorite Links

          Flickr

          Game Dev

          HBase

          Identity Management

          IT resources

          JEE

          Language

          OpenID

          OSGi

          SOA

          Version Control

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          free counters
          主站蜘蛛池模板: 封丘县| 六枝特区| 太白县| 通山县| 巴林右旗| 大名县| 古蔺县| 鄂伦春自治旗| 宽城| 于都县| 登封市| 荣成市| 桃源县| 和田市| 尼木县| 海盐县| 五常市| 乌拉特后旗| 太仓市| 栾城县| 米泉市| 昌吉市| 广东省| 樟树市| 饶阳县| 柯坪县| 永泰县| 房山区| 龙里县| 台前县| 红桥区| 罗源县| 神木县| 望奎县| 墨脱县| 洪洞县| 英山县| 江津市| 垫江县| 南宁市| 万全县|