java生成gif_Java生成动态GIF图片

这个博客介绍了如何使用Java的 AnimatedGifEncoder 类来创建和编码动态GIF图像。文章提供了一个示例,展示了如何设置延迟时间、透明色、重复次数等参数,并通过添加多个帧来生成动画效果。它还包含了用于编码和写入像素数据的方法。
摘要由CSDN通过智能技术生成

packagecom.yeetrack.selenium.Image;import java.io.*;import java.awt.*;import java.awt.image.*;/*** Class AnimatedGifEncoder - Encodes a GIF file consisting of one or

* more frames.

*

 
 

* Example:

* AnimatedGifEncoder e = new AnimatedGifEncoder();

* e.start(outputFileName);

* e.setDelay(1000); // 1 frame per sec

* e.addFrame(image1);

* e.addFrame(image2);

* e.finish();

*

* No copyright asserted on the source code of this class. May be used

* for any purpose, however, refer to the Unisys LZW patent for restrictions

* on use of the associated LZWEncoder class. Please forward any corrections

* to kweiner@fmsware.com.

*

*@authorKevin Weiner, FM Software

*@version1.03 November 2003

**/

public classAnimatedGifEncoder {protected int width; //image size

protected intheight;protected Color transparent = null; //transparent color if given

protected int transIndex; //transparent index in color table

protected int repeat = -1; //no repeat

protected int delay = 0; //frame delay (hundredths)

protected boolean started = false; //ready to output frames

protectedOutputStream out;protected BufferedImage image; //current frame

protected byte[] pixels; //BGR byte array from frame

protected byte[] indexedPixels; //converted frame indexed to palette

protected int colorDepth; //number of bit planes

protected byte[] colorTab; //RGB palette

protected boolean[] usedEntry = new boolean[256]; //active palette entries

protected int palSize = 7; //color table size (bits-1)

protected int dispose = -1; //disposal code (-1 = use default)

protected boolean closeStream = false; //close stream when finished

protected boolean firstFrame = true;protected boolean sizeSet = false; //if false, get size from first frame

protected int sample = 10; //default sample interval for quantizer

/*** Sets the delay time between each frame, or changes it

* for subsequent frames (applies to last frame added).

*

*@paramms int delay time in milliseconds*/

public void setDelay(intms) {

delay= Math.round(ms / 10.0f);

}/*** Sets the GIF frame disposal code for the last added frame

* and any subsequent frames. Default is 0 if no transparent

* color has been set, otherwise 2.

*@paramcode int disposal code.*/

public void setDispose(intcode) {if (code >= 0) {

dispose=code;

}

}/*** Sets the number of times the set of GIF frames

* should be played. Default is 1; 0 means play

* indefinitely. Must be invoked before the first

* image is added.

*

*@paramiter int number of iterations.

*@return

*/

public void setRepeat(intiter) {if (iter >= 0) {

repeat=iter;

}

}/*** Sets the transparent color for the last added frame

* and any subsequent frames.

* Since all colors are subject to modification

* in the quantization process, the color in the final

* palette for each frame closest to the given color

* becomes the transparent color for that frame.

* May be set to null to indicate no transparent color.

*

*@paramc Color to be treated as transparent on display.*/

public voidsetTransparent(Color c) {

transparent=c;

}/*** Adds next GIF frame. The frame is not written immediately, but is

* actually deferred until the next frame is received so that timing

* data can be inserted. Invoking finish() flushes all

* frames. If setSize was not invoked, the size of the

* first image is used for all subsequent frames.

*

*@paramim BufferedImage containing frame to write.

*@returntrue if successful.*/

public booleanaddFrame(BufferedImage im) {if ((im == null) || !started) {return false;

}boolean ok = true;try{if (!sizeSet) {//use first frame's size

setSize(im.getWidth(), im.getHeight());

}

image=im;

getImagePixels();//convert to correct format if necessary

analyzePixels(); //build color table & map pixels

if(firstFrame) {

writeLSD();//logical screen descriptior

writePalette(); //global color table

if (repeat >= 0) {//use NS app extension to indicate reps

writeNetscapeExt();

}

}

writeGraphicCtrlExt();//write graphic control extension

writeImageDesc(); //image descriptor

if (!firstFrame) {

writePalette();//local color table

}

writePixels();//encode and write pixel data

firstFrame = false;

}catch(IOException e) {

ok= false;

}returnok;

}/*** Flushes any pending data and closes output file.

* If writing to an OutputStream, the stream is not

* closed.*/

public booleanfinish() {if (!started) return false;boolean ok = true;

started= false;try{

out.write(0x3b); //gif trailer

out.flush();if(closeStream) {

out.close();

}

}catch(IOException e) {

ok= false;

}//reset for subsequent use

transIndex = 0;

out= null;

image= null;

pixels= null;

indexedPixels= null;

colorTab= null;

closeStream= false;

firstFrame= true;returnok;

}/*** Sets frame rate in frames per second. Equivalent to

* setDelay(1000/fps).

*

*@paramfps float frame rate (frames per second)*/

public void setFrameRate(floatfps) {if (fps !=0f) {

delay= Math.round(100f /fps);

}

}/*** Sets quality of color quantization (conversion of images

* to the maximum 256 colors allowed by the GIF specification).

* Lower values (minimum = 1) produce better colors, but slow

* processing significantly. 10 is the default, and produces

* good color mapping at reasonable speeds. Values greater

* than 20 do not yield significant improvements in speed.

*

*@paramquality int greater than 0.

*@return

*/

public void setQuality(intquality) {if (quality < 1) quality = 1;

sample=quality;

}/*** Sets the GIF frame size. The default size is the

* size of the first frame added if this method is

* not invoked.

*

*@paramw int frame width.

*@paramh int frame width.*/

public void setSize(int w, inth) {if (started && !firstFrame) return;

width=w;

height=h;if (width < 1) width = 320;if (height < 1) height = 240;

sizeSet= true;

}/*** Initiates GIF file creation on the given stream. The stream

* is not closed automatically.

*

*@paramos OutputStream on which GIF images are written.

*@returnfalse if initial write failed.*/

public booleanstart(OutputStream os) {if (os == null) return false;boolean ok = true;

closeStream= false;

out=os;try{

writeString("GIF89a"); //header

} catch(IOException e) {

ok= false;

}return started =ok;

}/*** Initiates writing of a GIF file with the specified name.

*

*@paramfile String containing output file name.

*@returnfalse if open or initial write failed.*/

public booleanstart(String file) {boolean ok = true;try{

out= new BufferedOutputStream(newFileOutputStream(file));

ok=start(out);

closeStream= true;

}catch(IOException e) {

ok= false;

}return started =ok;

}/*** Analyzes image colors and creates color map.*/

protected voidanalyzePixels() {int len =pixels.length;int nPix = len / 3;

indexedPixels= new byte[nPix];

NeuQuant nq= newNeuQuant(pixels, len, sample);//initialize quantizer

colorTab = nq.process(); //create reduced palette//convert map from BGR to RGB

for (int i = 0; i < colorTab.length; i += 3) {byte temp =colorTab[i];

colorTab[i]= colorTab[i + 2];

colorTab[i+ 2] =temp;

usedEntry[i/ 3] = false;

}//map image pixels to new palette

int k = 0;for (int i = 0; i < nPix; i++) {int index =nq.map(pixels[k++] & 0xff,

pixels[k++] & 0xff,

pixels[k++] & 0xff);

usedEntry[index]= true;

indexedPixels[i]= (byte) index;

}

pixels= null;

colorDepth= 8;

palSize= 7;//get closest match to transparent color if specified

if (transparent != null) {

transIndex=findClosest(transparent);

}

}/*** Returns index of palette color closest to c

**/

protected intfindClosest(Color c) {if (colorTab == null) return -1;int r =c.getRed();int g =c.getGreen();int b =c.getBlue();int minpos = 0;int dmin = 256 * 256 * 256;int len =colorTab.length;for (int i = 0; i

dmin=d;

minpos=index;

}

i++;

}returnminpos;

}/*** Extracts image pixels into byte array "pixels"*/

protected voidgetImagePixels() {int w =image.getWidth();int h =image.getHeight();int type =image.getType();if ((w !=width)|| (h !=height)|| (type !=BufferedImage.TYPE_3BYTE_BGR)) {//create new image with right size/format

BufferedImage temp =

newBufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);

Graphics2D g=temp.createGraphics();

g.drawImage(image,0, 0, null);

image=temp;

}

pixels=((DataBufferByte) image.getRaster().getDataBuffer()).getData();

}/*** Writes Graphic Control Extension*/

protected void writeGraphicCtrlExt() throwsIOException {

out.write(0x21); //extension introducer

out.write(0xf9); //GCE label

out.write(4); //data block size

inttransp, disp;if (transparent == null) {

transp= 0;

disp= 0; //dispose = no action

} else{

transp= 1;

disp= 2; //force clear if using transparent color

}if (dispose >= 0) {

disp= dispose & 7; //user override

}

disp<<= 2;//packed fields

out.write(0 | //1:3 reserved

disp | //4:6 disposal

0 | //7 user input - 0 = none

transp); //8 transparency flag

writeShort(delay); //delay x 1/100 sec

out.write(transIndex); //transparent color index

out.write(0); //block terminator

}/*** Writes Image Descriptor*/

protected void writeImageDesc() throwsIOException {

out.write(0x2c); //image separator

writeShort(0); //image position x,y = 0,0

writeShort(0);

writeShort(width);//image size

writeShort(height);//packed fields

if(firstFrame) {//no LCT - GCT is used for first (or only) frame

out.write(0);

}else{//specify normal LCT

out.write(0x80 | //1 local color table 1=yes

0 | //2 interlace - 0=no

0 | //3 sorted - 0=no

0 | //4-5 reserved

palSize); //6-8 size of color table

}

}/*** Writes Logical Screen Descriptor*/

protected void writeLSD() throwsIOException {//logical screen size

writeShort(width);

writeShort(height);//packed fields

out.write((0x80 | //1 : global color table flag = 1 (gct used)

0x70 | //2-4 : color resolution = 7

0x00 | //5 : gct sort flag = 0

palSize)); //6-8 : gct size

out.write(0); //background color index

out.write(0); //pixel aspect ratio - assume 1:1

}/*** Writes Netscape application extension to define

* repeat count.*/

protected void writeNetscapeExt() throwsIOException {

out.write(0x21); //extension introducer

out.write(0xff); //app extension label

out.write(11); //block size

writeString("NETSCAPE" + "2.0"); //app id + auth code

out.write(3); //sub-block size

out.write(1); //loop sub-block id

writeShort(repeat); //loop count (extra iterations, 0=repeat forever)

out.write(0); //block terminator

}/*** Writes color table*/

protected void writePalette() throwsIOException {

out.write(colorTab,0, colorTab.length);int n = (3 * 256) -colorTab.length;for (int i = 0; i < n; i++) {

out.write(0);

}

}/*** Encodes and writes pixel data*/

protected void writePixels() throwsIOException {

LZWEncoder encoder=

newLZWEncoder(width, height, indexedPixels, colorDepth);

encoder.encode(out);

}/*** Write 16-bit value to output stream, LSB first*/

protected void writeShort(int value) throwsIOException {

out.write(value& 0xff);

out.write((value>> 8) & 0xff);

}/*** Writes string to output stream*/

protected void writeString(String s) throwsIOException {for (int i = 0; i < s.length(); i++) {

out.write((byte) s.charAt(i));

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值