- 浏览: 13001 次
- 性别:
- 来自: 西安
文章分类
最新评论
public class AnimatedGifEncoder { protected int width; // image size protected int height; 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 protected OutputStream 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). * * @param ms int delay time in milliseconds */ public void setDelay(int ms) { 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. * @param code int disposal code. */ public void setDispose(int code) { 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. * * @param iter int number of iterations. * @return */ public void setRepeat(int iter) { 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. * * @param c Color to be treated as transparent on display. */ public void setTransparent(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 <code>finish()</code> flushes all * frames. If <code>setSize</code> was not invoked, the size of the * first image is used for all subsequent frames. * * @param im BufferedImage containing frame to write. * @return true if successful. */ public boolean addFrame(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; } return ok; } /** * Flushes any pending data and closes output file. * If writing to an OutputStream, the stream is not * closed. */ public boolean finish() { 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; return ok; } /** * Sets frame rate in frames per second. Equivalent to * <code>setDelay(1000/fps)</code>. * * @param fps float frame rate (frames per second) */ public void setFrameRate(float fps) { 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. * * @param quality int greater than 0. * @return */ public void setQuality(int quality) { 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. * * @param w int frame width. * @param h int frame width. */ public void setSize(int w, int h) { 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. * * @param os OutputStream on which GIF images are written. * @return false if initial write failed. */ public boolean start(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. * * @param file String containing output file name. * @return false if open or initial write failed. */ public boolean start(String file) { boolean ok = true; try { out = new BufferedOutputStream(new FileOutputStream(file)); ok = start(out); closeStream = true; } catch (IOException e) { ok = false; } return started = ok; } /** * Analyzes image colors and creates color map. */ protected void analyzePixels() { int len = pixels.length; int nPix = len / 3; indexedPixels = new byte[nPix]; NeuQuant nq = new NeuQuant(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 int findClosest(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 < len;) { int dr = r - (colorTab[i++] & 0xff); int dg = g - (colorTab[i++] & 0xff); int db = b - (colorTab[i] & 0xff); int d = dr * dr + dg * dg + db * db; int index = i / 3; if (usedEntry[index] && (d < dmin)) { dmin = d; minpos = index; } i++; } return minpos; } /** * Extracts image pixels into byte array "pixels" */ protected void getImagePixels() { 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 = new BufferedImage(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() throws IOException { out.write(0x21); // extension introducer out.write(0xf9); // GCE label out.write(4); // data block size int transp, 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() throws IOException { 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() throws IOException { // 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() throws IOException { 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() throws IOException { 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() throws IOException { LZWEncoder encoder = new LZWEncoder(width, height, indexedPixels, colorDepth); encoder.encode(out); } /** * Write 16-bit value to output stream, LSB first */ protected void writeShort(int value) throws IOException { out.write(value & 0xff); out.write((value >> 8) & 0xff); } /** * Writes string to output stream */ protected void writeString(String s) throws IOException { for (int i = 0; i < s.length(); i++) { out.write((byte) s.charAt(i)); } } }
发表评论
-
利用HttpClient使得Openlayers3能够访问跨域访问arcgis for server
2016-07-12 13:11 919最近做一个WebGIS的项目,使用的是Openlayers ... -
好用的LookAndFeel——TinyLaF
2012-10-10 09:21 847仔细阅读readme,就可以发现,tinycp.jar含有调试 ... -
用Tomcat搭建GSP服务器,IDEA开发GSP
2010-10-29 10:57 1601新建一个Web项目 (一)将antlr、asm、gro ... -
网上收集的GIF操作的三个类AnimatedGifEncoder,NeuQuant,LZWE(二)
2010-10-29 10:36 2210public class NeuQuant { ... -
网上收集的GIF操作的三个类AnimatedGifEncoder,NeuQuant,LZWE(一)
2010-10-29 10:33 2437class LZWEncoder { ...
相关推荐
在给定的压缩包文件中,我们关注的是三个关键组件:`AnimatedGifEncoder`、`NeuQuant`和`LZWEncoder`,这些都是与处理GIF动图密切相关的类。以下是这些组件的详细解释和它们在图片处理中的应用。 1. ** ...
java处理gif的几个类(AnimatedGifEncoder、LZWEncoder、GifDecoder、NeuQuant),网上搜集的打成jar包方便使用
c# 使用图片制作 gif 的时候,需要用到一个类,那就是 AnimatedGifEncoder,使用的时候,把这个类复制进工程中,就可以使用相关类了。
本文将聚焦于一个Java库—— AnimatedGifEncoder,它专门用于创建和编码动态GIF图像。这个库包含了LZWEncoder和NeuQuant算法的实现,使得开发者能够方便地在Java程序中生成高质量的动画GIF。 首先,我们来了解一下 ...
在Java编程环境中,处理图像文件,特别是动画GIF文件时,常常会涉及到四个核心类:`AnimatedGifEncoder`、`GifDecoder`、`LZWEncoder`和`NeuQuant`。这些类分别用于创建、解码和优化GIF图像。下面将详细解释每个类的...
"NGif"是一个专为处理GIF文件而设计的类库,它包含了多种核心组件,如 AnimatedGifEncoder、GifDecoder、GifEncoder、LZWEncoder 和 NeuQuant,这些组件对于理解和操作GIF文件至关重要。 **AnimatedGifEncoder** 是...
该库包括四个类文件:AnimatedGifEncoder.java、GifDecoder.java、LZWEncoder.java 和 NeuQuant.java。 AnimatedGifEncoder.java 类文件用于编码 GIF 图像,提供了对 GIF 图像的编码和压缩功能。GifDecoder.java ...
1. **GifHelper.cs**:这是一个核心的辅助类,它封装了对GIF图像进行读取、写入和修改的基本操作。它可能包含如打开GIF文件、创建新GIF、合并GIF帧等方法。GifHelper可能是整个类库的入口点,允许开发者通过简单的...
AnimatedGifEncoder.java源码(处理GIF图片)AnimatedGifEncoder.java源码(处理GIF图片)AnimatedGifEncoder.java源码(处理GIF图片)
在C#编程环境中,处理GIF图像文件时,我们经常需要进行合成操作,例如将多个静态图片(如JPG、GIF或PNG)合并成一个动态的GIF文件。这在开发各种应用,如社交媒体分享工具、动画制作软件或者数据分析可视化界面时...
C#gif 相关操作 在 C# 中生成 GIF 文件时,遇到了一个棘手的问题,即 Graphics.Clear(Color.Transparent) 无法生成透明的 GIF 文件。同时,使用 Bitmap.MakeTransparent 方法也不能使 GIF 文件透明。这两个问题都是...
在IT领域,C#是一种广泛...总的来说,“GIF图片生成器(C#)”项目涵盖了C#编程、图像处理、GUI设计、文件操作、动画制作等多个方面的知识,对于想要深入学习C#开发或者图形处理技术的开发者来说,是一个很好的实践项目。
`PictureEx`类是专门为在VC++应用程序中显示动态GIF而设计的一个自定义控件,它使得在MFC(Microsoft Foundation Classes)框架下处理动态GIF变得简单易行。 动态GIF图片是一种支持多帧的图像格式,每帧可以有各自...
Java 合成 GIF 是一种利用编程技术将多张静态图片(如JPG)组合成一个动态GIF图像的过程。在Java中,这个过程涉及到多个关键概念和技术,包括图像处理、编码算法以及文件格式理解。以下是对这些知识点的详细说明: ...
"Gif-Animation.zip"这个压缩包提供了一个名为"GIF Animation"的C++类,专门用于处理和创建GIF动画。这个类可能包含了解析GIF文件格式、管理帧序列、控制动画播放速度以及合成和输出新动画等功能。通过这样的类库,...
GIF4J是一个Java库,专门用于处理GIF(Graphics Interchange Format)动态图像。它提供了丰富的API,允许开发者在Java应用程序中进行各种GIF图片的编辑和操作。以下是一些关于GIF4J的关键知识点: 1. **GIF读取与...
gif处理,图像处理,Gif.Components.dll,AnimatedGifEncoder
这里提到的四个源代码文件——`AnimatedGifEncoder.java`、`GifHelper.java`、`LZWencoder.java`和`NeuQuant.java`,它们分别扮演了不同的角色,共同构建了一个完整的GIF编码解决方案。 1. ** AnimatedGifEncoder....