`

GifEncoder.java源程序

阅读更多

/*
 * @(#)GIFEncoder.java    0.90 4/21/96 Adam Doppelt
 */
import java.io.*;
import java.awt.*;
import java.awt.image.*;

/**
 * GIFEncoder is a class which takes an image and saves it to a stream
 * using the GIF file format (<A
 * HREF="http://www.dcs.ed.ac.uk/%7Emxr/gfx/">Graphics Interchange
 * Format</A>). A GIFEncoder
 * is constructed with either an AWT Image (which must be fully
 * loaded) or a set of RGB arrays. The image can be written out with a
 * call to <CODE>Write</CODE>.<P>
 *
 * Three caveats:
 * <UL>
 *   <LI>GIFEncoder will convert the image to indexed color upon
 *   construction. This will take some time, depending on the size of
 *   the image. Also, actually writing the image out (Write) will take
 *   time.<P>
 *
 *   <LI>The image cannot have more than 256 colors, since GIF is an 8
 *   bit format. For a 24 bit to 8 bit quantization algorithm, see
 *   Graphics Gems II III.2 by Xialoin Wu. Or check out his <A
 *   HREF="http://www.csd.uwo.ca/faculty/wu/cq.c">C source</A>.<P>
 *
 *   <LI>Since the image must be completely loaded into memory,
 *   GIFEncoder may have problems with large images. Attempting to
 *   encode an image which will not fit into memory will probably
 *   result in the following exception:<P>
 *   <CODE>java.awt.AWTException: Grabber returned false: 192</CODE><P>
 * </UL><P>
 *
 * GIFEncoder is based upon gifsave.c, which was written and released
 * by:<P>
 * <CENTER>
 *                                  Sverre H. Huseby<BR>
 *                                   Bjoelsengt. 17<BR>
 *                                     N-0468 Oslo<BR>
 *                                       Norway<P>
 *
 *                                 Phone: +47 2 230539<BR>
 *                                 sverrehu@ifi.uio.no<P>
 * </CENTER>
 * @version 0.90 21 Apr 1996
 * @author <A HREF="http://www.cs.brown.edu/people/amd/">Adam Doppelt</A> */
public class GIFEncoder {
    short width_, height_;
    int numColors_;
    byte pixels_[], colors_[];
   
    ScreenDescriptor sd_;
    ImageDescriptor id_;
   
/**
 * Construct a GIFEncoder. The constructor will convert the image to
 * an indexed color array. <B>This may take some time.</B><P>
 *
 * @param image The image to encode. The image <B>must</B> be
 * completely loaded.
 * @exception AWTException Will be thrown if the pixel grab fails. This
 * can happen if Java runs out of memory. It may also indicate that the image
 * contains more than 256 colors.
 * */
    public GIFEncoder(Image image) throws AWTException {
 width_ = (short)image.getWidth(null);
 height_ = (short)image.getHeight(null);

 int values[] = new int[width_ * height_];
 PixelGrabber grabber = new PixelGrabber(
     image, 0, 0, width_, height_, values, 0, width_);
 
 try {
     if(grabber.grabPixels() != true)
  throw new AWTException("Grabber returned false: " +
           grabber.status());
 }
 catch (InterruptedException e) { ; }
 
 byte r[][] = new byte[width_][height_];
 byte g[][] = new byte[width_][height_];
 byte b[][] = new byte[width_][height_];
 int index = 0;
 for (int y = 0; y < height_; ++y)
     for (int x = 0; x < width_; ++x) {
  r[x][y] = (byte)((values[index] >> 16) & 0xFF);
  g[x][y] = (byte)((values[index] >> 8) & 0xFF);
  b[x][y] = (byte)((values[index]) & 0xFF); 
  ++index;
     }
 ToIndexedColor(r, g, b);
    }

/**
 * Construct a GIFEncoder. The constructor will convert the image to
 * an indexed color array. <B>This may take some time.</B><P>
 *
 * Each array stores intensity values for the image. In other words,
 * r[x][y] refers to the red intensity of the pixel at column x, row
 * y.<P>
 *
 * @param r An array containing the red intensity values.
 * @param g An array containing the green intensity values.
 * @param b An array containing the blue intensity values.
 *
 * @exception AWTException Will be thrown if the image contains more than
 * 256 colors.
 * */
    public GIFEncoder(byte r[][], byte g[][], byte b[][]) throws AWTException {
 width_ = (short)(r.length);
 height_ = (short)(r[0].length);

 ToIndexedColor(r, g, b);
    }

/**
 * Writes the image out to a stream in the GIF file format. This will
 * be a single GIF87a image, non-interlaced, with no background color.
 * <B>This may take some time.</B><P>
 *
 * @param output The stream to output to. This should probably be a
 * buffered stream.
 *
 * @exception IOException Will be thrown if a write operation fails.
 * */
    public void Write(OutputStream output) throws IOException {
 BitUtils.WriteString(output, "GIF87a");
 
 ScreenDescriptor sd = new ScreenDescriptor(width_, height_,
         numColors_);
 sd.Write(output);

 output.write(colors_, 0, colors_.length);

 ImageDescriptor id = new ImageDescriptor(width_, height_, ',');
 id.Write(output);

 byte codesize = BitUtils.BitsNeeded(numColors_);
 if (codesize == 1)
     ++codesize;
 output.write(codesize);

 LZWCompressor.LZWCompress(output, codesize, pixels_);
 output.write(0);

 id = new ImageDescriptor((byte)0, (byte)0, ';');
 id.Write(output);
 output.flush();
    }

    void ToIndexedColor(byte r[][], byte g[][],
   byte b[][]) throws AWTException {
 pixels_ = new byte[width_ * height_];
 colors_ = new byte[256 * 3];
 int colornum = 0;
 for (int x = 0; x < width_; ++x) {
     for (int y = 0; y < height_; ++y) {
  int search;
  for (search = 0; search < colornum; ++search)
      if (colors_[search * 3]     == r[x][y] &&
   colors_[search * 3 + 1] == g[x][y] &&
   colors_[search * 3 + 2] == b[x][y])
   break;
  
  if (search > 255)
      throw new AWTException("Too many colors.");

  pixels_[y * width_ + x] = (byte)search;
  
  if (search == colornum) {
      colors_[search * 3]     = r[x][y];
      colors_[search * 3 + 1] = g[x][y];
      colors_[search * 3 + 2] = b[x][y];
      ++colornum;
  }
     }
 }
 numColors_ = 1 << BitUtils.BitsNeeded(colornum);
 byte copy[] = new byte[numColors_ * 3];
 System.arraycopy(colors_, 0, copy, 0, numColors_ * 3);
 colors_ = copy;
    }
   
}

class BitFile {
    OutputStream output_;
    byte buffer_[];
    int index_, bitsLeft_;

    public BitFile(OutputStream output) {
 output_ = output;
 buffer_ = new byte[256];
 index_ = 0;
 bitsLeft_ = 8;
    }

    public void Flush() throws IOException {
 int numBytes = index_ + (bitsLeft_ == 8 ? 0 : 1);
 if (numBytes > 0) {
     output_.write(numBytes);
     output_.write(buffer_, 0, numBytes);
     buffer_[0] = 0;
     index_ = 0;
     bitsLeft_ = 8;
 }
    }

    public void WriteBits(int bits, int numbits) throws IOException {
 int bitsWritten = 0;
 int numBytes = 255;
 do {
     if ((index_ == 254 && bitsLeft_ == 0) || index_ > 254) {
  output_.write(numBytes);
  output_.write(buffer_, 0, numBytes);

  buffer_[0] = 0;
  index_ = 0;
  bitsLeft_ = 8;
     }

     if (numbits <= bitsLeft_) {
  buffer_[index_] |= (bits & ((1 << numbits) - 1)) <<
      (8 - bitsLeft_);
  bitsWritten += numbits;
  bitsLeft_ -= numbits;
  numbits = 0;
     }
     else {
  buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) <<
      (8 - bitsLeft_);
  bitsWritten += bitsLeft_;
  bits >>= bitsLeft_;
  numbits -= bitsLeft_;
  buffer_[++index_] = 0;
  bitsLeft_ = 8;
     }
 } while (numbits != 0);
    }
}

class LZWStringTable {
    private final static int RES_CODES = 2;
    private final static short HASH_FREE = (short)0xFFFF;
    private final static short NEXT_FIRST = (short)0xFFFF;
    private final static int MAXBITS = 12;
    private final static int MAXSTR = (1 << MAXBITS);
    private final static short HASHSIZE = 9973;
    private final static short HASHSTEP = 2039;

    byte strChr_[];
    short strNxt_[];
    short strHsh_[];
    short numStrings_;

    public LZWStringTable() {
 strChr_ = new byte[MAXSTR];
 strNxt_ = new short[MAXSTR];
 strHsh_ = new short[HASHSIZE];   
    }

    public int AddCharString(short index, byte b) {
 int hshidx;

 if (numStrings_ >= MAXSTR)
     return 0xFFFF;
 
 hshidx = Hash(index, b);
 while (strHsh_[hshidx] != HASH_FREE)
     hshidx = (hshidx + HASHSTEP) % HASHSIZE;
 
 strHsh_[hshidx] = numStrings_;
 strChr_[numStrings_] = b;
 strNxt_[numStrings_] = (index != HASH_FREE) ? index : NEXT_FIRST;

 return numStrings_++;
    }
   
    public short FindCharString(short index, byte b) {
 int hshidx, nxtidx;

 if (index == HASH_FREE)
     return b;

 hshidx = Hash(index, b);
 while ((nxtidx = strHsh_[hshidx]) != HASH_FREE) {
     if (strNxt_[nxtidx] == index && strChr_[nxtidx] == b)
  return (short)nxtidx;
     hshidx = (hshidx + HASHSTEP) % HASHSIZE;
 }

 return (short)0xFFFF;
    }

    public void ClearTable(int codesize) {
 numStrings_ = 0;
 
 for (int q = 0; q < HASHSIZE; q++) {
     strHsh_[q] = HASH_FREE;
 }

 int w = (1 << codesize) + RES_CODES;
 for (int q = 0; q < w; q++)
     AddCharString((short)0xFFFF, (byte)q);
    }
   
    static public int Hash(short index, byte lastbyte) {
 return ((int)((short)(lastbyte << 8) ^ index) & 0xFFFF) % HASHSIZE;
    }
}

class LZWCompressor {

    public static void LZWCompress(OutputStream output, int codesize,
       byte toCompress[]) throws IOException {
 byte c;
 short index;
 int clearcode, endofinfo, numbits, limit, errcode;
 short prefix = (short)0xFFFF;

 BitFile bitFile = new BitFile(output);
 LZWStringTable strings = new LZWStringTable();

 clearcode = 1 << codesize;
 endofinfo = clearcode + 1;
   
 numbits = codesize + 1;
 limit = (1 << numbits) - 1;
 
 strings.ClearTable(codesize);
 bitFile.WriteBits(clearcode, numbits);

 for (int loop = 0; loop < toCompress.length; ++loop) {
     c = toCompress[loop];
     if ((index = strings.FindCharString(prefix, c)) != -1)
  prefix = index;
     else {
  bitFile.WriteBits(prefix, numbits);
  if (strings.AddCharString(prefix, c) > limit) {
      if (++numbits > 12) {
   bitFile.WriteBits(clearcode, numbits - 1);
   strings.ClearTable(codesize);
   numbits = codesize + 1;
      }
      limit = (1 << numbits) - 1;
  }
  
  prefix = (short)((short)c & 0xFF);
     }
 }
 
 if (prefix != -1)
     bitFile.WriteBits(prefix, numbits);
 
 bitFile.WriteBits(endofinfo, numbits);
 bitFile.Flush();
    }
}

class ScreenDescriptor {
    public short localScreenWidth_, localScreenHeight_;
    private byte byte_;
    public byte backgroundColorIndex_, pixelAspectRatio_;

    public ScreenDescriptor(short width, short height, int numColors) {
 localScreenWidth_ = width;
 localScreenHeight_ = height;
 SetGlobalColorTableSize((byte)(BitUtils.BitsNeeded(numColors) - 1));
 SetGlobalColorTableFlag((byte)1);
 SetSortFlag((byte)0);
 SetColorResolution((byte)7);
 backgroundColorIndex_ = 0;
 pixelAspectRatio_ = 0;
    }

    public void Write(OutputStream output) throws IOException {
 BitUtils.WriteWord(output, localScreenWidth_);
 BitUtils.WriteWord(output, localScreenHeight_);
 output.write(byte_);
 output.write(backgroundColorIndex_);
 output.write(pixelAspectRatio_);
    }

    public void SetGlobalColorTableSize(byte num) {
 byte_ |= (num & 7);
    }

    public void SetSortFlag(byte num) {
 byte_ |= (num & 1) << 3;
    }

    public void SetColorResolution(byte num) {
 byte_ |= (num & 7) << 4;
    }
   
    public void SetGlobalColorTableFlag(byte num) {
 byte_ |= (num & 1) << 7;
    }
}

class ImageDescriptor {
    public byte separator_;
    public short leftPosition_, topPosition_, width_, height_;
    private byte byte_;

    public ImageDescriptor(short width, short height, char separator) {
 separator_ = (byte)separator;
 leftPosition_ = 0;
 topPosition_ = 0;
 width_ = width;
 height_ = height;
 SetLocalColorTableSize((byte)0);
 SetReserved((byte)0);
 SetSortFlag((byte)0);
 SetInterlaceFlag((byte)0);
 SetLocalColorTableFlag((byte)0);
    }
   
    public void Write(OutputStream output) throws IOException {
 output.write(separator_);
 BitUtils.WriteWord(output, leftPosition_);
 BitUtils.WriteWord(output, topPosition_);
 BitUtils.WriteWord(output, width_);
 BitUtils.WriteWord(output, height_);  
 output.write(byte_);
    }

    public void SetLocalColorTableSize(byte num) {
 byte_ |= (num & 7);
    }

    public void SetReserved(byte num) {
 byte_ |= (num & 3) << 3;
    }

    public void SetSortFlag(byte num) {
 byte_ |= (num & 1) << 5;
    }
   
    public void SetInterlaceFlag(byte num) {
 byte_ |= (num & 1) << 6;
    }

    public void SetLocalColorTableFlag(byte num) {
 byte_ |= (num & 1) << 7;
    }
}

class BitUtils {
    public static byte BitsNeeded(int n) {
 byte ret = 1;

 if (n-- == 0)
     return 0;

 while ((n >>= 1) != 0)
     ++ret;
 
 return ret;
    }   

    public static void WriteWord(OutputStream output,
     short w) throws IOException {
 output.write(w & 0xFF);
 output.write((w >> 8) & 0xFF);
    }
   
    static void WriteString(OutputStream output,
       String string) throws IOException {
 for (int loop = 0; loop < string.length(); ++loop)
     output.write((byte)(string.charAt(loop)));
    }
}

 

 

来自:http://luohonghong.blog.163.com/blog/static/7831205820095341548326/

分享到:
评论

相关推荐

    as3gif.rar_flex_gifencoder.as

    标题中的“as3gif.rar_flex_gifencoder.as”指的是这个库的核心组件——`GifEncoder.as`源代码文件,它封装了GIF图像编码的功能。Flex是基于ActionScript 3(AS3)的开放源代码框架,主要用于构建富互联网应用程序...

    GIFEncoder.js

    通过js生成GIF动画

    GIFEncoder.swc

    GIFEncoder 很好的GIFswc

    GIFEncoder类库.zip

    介绍了PHP使用的GIFEncoder类库,可以使用这个类库可以进行和生成各种GIF需求操作,供需要的朋友下载参考,小伙伴们如果有更好的类似类库或者更好额类库可以发送到我们PHP中文网供大家一起学习分享。

    我积攒的java工具类 基本满足开发需要的工具类

    D:\002 我的工具类\010 操作图片\整体图片操作\GIF\GifEncoder.java D:\002 我的工具类\010 操作图片\整体图片操作\GIF\Quant.java D:\002 我的工具类\010 操作图片\整体图片操作\GifEncoder.java D:\002 我的工具类...

    gifencoder,实现gif89a规范的纯java库。适合在android上使用。.zip

    《深入理解GifEncoder:基于GIF89a规范的纯Java实现》 在移动开发领域,尤其是在Android平台上,由于其独特的系统架构,许多在Java SE环境下常用的图形处理库并不能直接应用。`gifencoder`正是为了解决这个问题而...

    PHP使用GIFEncoder类处理gif图片实例

    require_once(“gifencoder.php”); //载入编码 文件 $gif = new GIFEncoder(); //实例化gif解码对象 $gif-&gt;load(“test.gif”); //载入要解码的gif图像 for($i=0;$i&lt;sizeof&gt;IMGS[“frames”]);$i++){ //根据 ...

    Java Source codes of GIF Encoder and Decoder

    在Java中,`GifEncoder.java`文件可能包含一个类或多个类,这些类提供了将像素数据编码为GIF文件的逻辑。编码过程通常包括以下步骤: 1. **颜色表创建**:GIF支持最多256种颜色,编码器需要根据输入图像的颜色选择...

    gif图片压缩(纯java实现,不依赖第三方类库)

    本话题聚焦于使用纯Java实现GIF图片的压缩,不依赖任何第三方类库。这样的实现方式对于那些需要在资源有限或者对性能有特殊要求的环境中工作的开发者来说非常有价值。 GIF(Graphics Interchange Format)是一种...

    解决GIF动画缩放 (gif4j.jar GifDecoder)

    `gif4j.jar` 是一个Java库,专门设计用于处理GIF动画,包括缩放和压缩等功能。它内含了一个名为`GifDecoder`的类,该类能够解析GIF文件的结构,保持动画帧的信息完整。通过使用`gif4j.jar`,开发者可以避免将GIF动画...

    as3gif GIFEncoder

    【压缩包子文件的文件名称列表】中,"GIFEncoder.fla"是Flash的源文件,包含着整个项目的AS3代码和舞台元素,开发者可以通过打开这个文件来查看和编辑源代码。"说明.txt"可能是关于如何使用这个库的指导文档,包括...

    GIFEncoder 0.1[as3gif]

    《深入解析GIFEncoder 0.1:AS3GIF在Flash Flex...通过深入研究`GIFEncoder.fla`和`org`目录下的源代码,开发者不仅可以掌握如何使用这个库,还能学习到GIF编码的底层机制,从而提高在图形编程和动画设计上的专业技能。

    IOS开发-仿抖音短视频系统生成webp动图客户端解决方案.docx

    gifEncoder.loopCount = 0; gifEncoder.quality = 0.8; [gifEncoder addImage:img duration:0.1]; [gifEncoder encodeToFile:filePath]; ``` `YYImageEncoder`允许设置循环次数(loopCount)和图片质量(quality),...

    PHP使用GIFEncoder类生成的GIF动态图片验证码

    它具备多种功能,其中包括生成图形验证码的动态图片。动态图片验证码是一种常见的安全...通过理解和应用GIFEncoder类和相关的图像处理函数,开发者可以创建出既安全又有效的动态图片验证码,增强网站的安全防护能力。

    gifencoder:实现GIF89a规范的纯Java库。 适用于Android

    gifencoder是实现的纯Java库。 它不使用AWT的BufferedImage ,因此可以在Android和其他缺少AWT的平台上使用。 当前不支持透明度。 量化和抖动 GIF图像限制为256色。 如果您提供颜色更多的图像,则gifencoder的默认...

    jsGifEncoder:超快速GIF编码器,用于以JavaScript编写的数据URL

    布局标题图像家jsGifEncoder... 编码器由用法调用示例: let encoder = new GifEncoder ( width , height ) ; let data = encoder . encode ( bpp , red , green , blue , pixels ) ; 注入HTML: document . get

    java生成缩略图.pdf

    在修改后的代码中,使用`GifEncoder.encode()`方法替换原先的`ImageIO.write()`,并将输出写入到ByteArrayOutputStream,最后将结果保存为字节数组`imageThumbnail`。 需要注意的是,虽然GIF支持透明度,但它的颜色...

    GIF-JS:JS编写的GIF图片文件decoderencoder

    任何人都可以出于任何目的(商业或非商业目的)以任何方式自由复制、修改、发布、使用、编译、销售或分发本软件,无论是源代码形式还是编译后的二进制文件。 在承认版权法的司法管辖区,本软件的作者或作者将本...

    java生成缩略图.docx

    使用`GifEncoder.encode()`方法来编码和保存缩略图GIF动画。 9. **避免图像失真**: 要减少图像缩放后的失真,可以使用`Image.SCALE_SMOOTH`选项。它使用更平滑的插值算法来提高缩放质量。 ```java tag....

    gifencoder:用于node.js的服务器端动画gif生成

    gifencoder 用于node.js的流式服务器端动画(和非动画)gif生成 安装 该模块通过npm安装: $ npm install gifencoder 流API-具有写入功能的双工管道 您还可以将像素数据(或画布上下文)的写入内容流式传输到编码...

Global site tag (gtag.js) - Google Analytics