`
louis_cuti
  • 浏览: 13001 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

网上收集的GIF操作的三个类AnimatedGifEncoder,NeuQuant,LZWE(三)

    博客分类:
  • java
阅读更多

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));
            }
        }
    }
 
分享到:
评论

相关推荐

    AnimatedGifEncoder NeuQuant LZWEncoder源码(图片处理)

    在给定的压缩包文件中,我们关注的是三个关键组件:`AnimatedGifEncoder`、`NeuQuant`和`LZWEncoder`,这些都是与处理GIF动图密切相关的类。以下是这些组件的详细解释和它们在图片处理中的应用。 1. ** ...

    AnimatedGifEncoder、LZWEncoder、GifDecoder、NeuQuant

    java处理gif的几个类(AnimatedGifEncoder、LZWEncoder、GifDecoder、NeuQuant),网上搜集的打成jar包方便使用

    AnimatedGifEncoder 类 c# 制作 gif 用到

    c# 使用图片制作 gif 的时候,需要用到一个类,那就是 AnimatedGifEncoder,使用的时候,把这个类复制进工程中,就可以使用相关类了。

    AnimatedGifEncoder

    本文将聚焦于一个Java库—— AnimatedGifEncoder,它专门用于创建和编码动态GIF图像。这个库包含了LZWEncoder和NeuQuant算法的实现,使得开发者能够方便地在Java程序中生成高质量的动画GIF。 首先,我们来了解一下 ...

    gif的四个java类

    在Java编程环境中,处理图像文件,特别是动画GIF文件时,常常会涉及到四个核心类:`AnimatedGifEncoder`、`GifDecoder`、`LZWEncoder`和`NeuQuant`。这些类分别用于创建、解码和优化GIF图像。下面将详细解释每个类的...

    NGif.包含AnimatedGifEncoder、GifDecoder、GifEncoder、LZWEncoder、NeuQuant

    "NGif"是一个专为处理GIF文件而设计的类库,它包含了多种核心组件,如 AnimatedGifEncoder、GifDecoder、GifEncoder、LZWEncoder 和 NeuQuant,这些组件对于理解和操作GIF文件至关重要。 **AnimatedGifEncoder** 是...

    GIF解码和编码操作库源码

    该库包括四个类文件:AnimatedGifEncoder.java、GifDecoder.java、LZWEncoder.java 和 NeuQuant.java。 AnimatedGifEncoder.java 类文件用于编码 GIF 图像,提供了对 GIF 图像的编码和压缩功能。GifDecoder.java ...

    c#Gif操作类,能处理GIF图片

    1. **GifHelper.cs**:这是一个核心的辅助类,它封装了对GIF图像进行读取、写入和修改的基本操作。它可能包含如打开GIF文件、创建新GIF、合并GIF帧等方法。GifHelper可能是整个类库的入口点,允许开发者通过简单的...

    AnimatedGifEncoder.java源码(处理GIF图片)

    AnimatedGifEncoder.java源码(处理GIF图片)AnimatedGifEncoder.java源码(处理GIF图片)AnimatedGifEncoder.java源码(处理GIF图片)

    C# 操作gif 合成类

    在C#编程环境中,处理GIF图像文件时,我们经常需要进行合成操作,例如将多个静态图片(如JPG、GIF或PNG)合并成一个动态的GIF文件。这在开发各种应用,如社交媒体分享工具、动画制作软件或者数据分析可视化界面时...

    C#gif相关操作

    C#gif 相关操作 在 C# 中生成 GIF 文件时,遇到了一个棘手的问题,即 Graphics.Clear(Color.Transparent) 无法生成透明的 GIF 文件。同时,使用 Bitmap.MakeTransparent 方法也不能使 GIF 文件透明。这两个问题都是...

    GIF图片生成器(C#)

    在IT领域,C#是一种广泛...总的来说,“GIF图片生成器(C#)”项目涵盖了C#编程、图像处理、GUI设计、文件操作、动画制作等多个方面的知识,对于想要深入学习C#开发或者图形处理技术的开发者来说,是一个很好的实践项目。

    vc++显示动态gif图片的PictureEx类

    `PictureEx`类是专门为在VC++应用程序中显示动态GIF而设计的一个自定义控件,它使得在MFC(Microsoft Foundation Classes)框架下处理动态GIF变得简单易行。 动态GIF图片是一种支持多帧的图像格式,每帧可以有各自...

    java 合成 gif

    Java 合成 GIF 是一种利用编程技术将多张静态图片(如JPG)组合成一个动态GIF图像的过程。在Java中,这个过程涉及到多个关键概念和技术,包括图像处理、编码算法以及文件格式理解。以下是对这些知识点的详细说明: ...

    Gif-Animation.zip_GIF 动画_GIF类 C++_GifAnimation _gif

    "Gif-Animation.zip"这个压缩包提供了一个名为"GIF Animation"的C++类,专门用于处理和创建GIF动画。这个类可能包含了解析GIF文件格式、管理帧序列、控制动画播放速度以及合成和输出新动画等功能。通过这样的类库,...

    gif操作的jar包gif4j

    GIF4J是一个Java库,专门用于处理GIF(Graphics Interchange Format)动态图像。它提供了丰富的API,允许开发者在Java应用程序中进行各种GIF图片的编辑和操作。以下是一些关于GIF4J的关键知识点: 1. **GIF读取与...

    Gif.Components.dll

    gif处理,图像处理,Gif.Components.dll,AnimatedGifEncoder

    关于Gif解析的java代码

    这里提到的四个源代码文件——`AnimatedGifEncoder.java`、`GifHelper.java`、`LZWencoder.java`和`NeuQuant.java`,它们分别扮演了不同的角色,共同构建了一个完整的GIF编码解决方案。 1. ** AnimatedGifEncoder....

Global site tag (gtag.js) - Google Analytics