gif文件编码 : 图像互换格式 « 图形用户界面 « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » 图形用户界面 » 图像互换格式屏幕截图 
gif文件编码
 
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;

/**
 * Class GifDecoder - Decodes a GIF file into one or more frames. <br>
 
 * <pre>
 *  Example:
 *     GifDecoder d = new GifDecoder();
 *     d.read(&quot;sample.gif&quot;);
 *     int n = d.getFrameCount();
 *     for (int i = 0; i &lt; n; i++) {
 *        BufferedImage frame = d.getFrame(i);  // frame i
 *        int t = d.getDelay(i);  // display duration of frame in milliseconds
 *        // do something with frame
 *     }
 * </pre>
 
 * No copyright asserted on the source code of this class. May be used for any
 * purpose, however, refer to the Unisys LZW patent for any additional
 * restrictions. Please forward any corrections to kweiner@fmsware.com.
 
 @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's
 *         ImageMagick.
 @version 1.03 November 2003
 
 */

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 = ((GifFrameframes.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 = ((DataBufferIntimage.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 = ((DataBufferIntlastImage.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(0000)// 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 = ((intpixels[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 = ((GifFrameframes.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 = (BufferedInputStreamis;
      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 = << data_size;
    end_of_information = clear + 1;
    available = clear + 2;
    old_code = NullCode;
    code_size = data_size + 1;
    code_mask = (<< code_size1;
    for (code = 0; code < clear; code++) {
      prefix[code0;
      suffix[code(bytecode;
    }

    // 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 += (((intblock[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 = (<< code_size1;
          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++(bytefirst;
          code = old_code;
        }
        while (code > clear) {
          pixelStack[top++= suffix[code];
          code = prefix[code];
        }
        first = ((intsuffix[code]) 0xff;

        // Add a new string to the string table,

        if (available >= MaxStackSize)
          break;
        pixelStack[top++(bytefirst;
        prefix[available(shortold_code;
        suffix[available(bytefirst;
        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[i0// 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 = * 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 = ((intc[j++]) 0xff;
        int g = ((intc[j++]) 0xff;
        int b = ((intc[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 += (charblock[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 += (charread();
    }
    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 = << (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[transIndex0// 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 = << (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 = ((intblock[1]) 0xff;
        int b2 = ((intblock[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;
  }

  /**
   * Skips variable length blocks up to and including next zero length block.
   */
  protected void skip() {
    do {
      readBlock();
    while ((blockSize > 0&& !err());
  }
}

           
         
  
Related examples in the same category
1. Gif图像互换格式
2. 转换为图像, GIF文件
3. 动画GIF编码器
4. 转换GIF成PostScript
5. 隐藏鼠标光标:使用一个透明的GIF的光标
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.