zoukankan      html  css  js  c++  java
  • android 开发 解码gif图片,获取每帧bitmap

    环境:android 4.3  (注意对于android4.4版本解码出来不正确,除了第一帧正确外,其余的都是显示不同的地方)  通用版本见: android 开发对gif解码(适配android 4.2、4.3、4.4版本)

    使用方法:

    void showGif2()
        {
            gifDecoder = new GifImageDecoder();
            try {
                gifDecoder.read(this.getResources().openRawResource(R.drawable.b17));  //这是Gif图片资源
                int size =gifDecoder.getFrameCount();
                for(int i=0;i<size;i++)
                {
                    
                    ImageView iv_image = new ImageView(CustomActivity.this);
                    iv_image.setPadding(5, 5, 5, 5);
                    LayoutParams lparams = new LayoutParams(100,100);
                    iv_image.setLayoutParams(lparams);
                    iv_image.setImageBitmap(gifDecoder.getFrame(i));
                    ll_decodeimages.addView(iv_image);
    //                gifFrame.nextFrame();
                }
            } catch (NotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }


    见效果:

    全部代码:

    package com.xlm.testgif;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.app.Activity;
    import android.content.Context;
    import android.content.res.Resources.NotFoundException;
    import android.graphics.Bitmap;
    import android.view.Menu;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.LinearLayout.LayoutParams;
    
    public class CustomActivity extends Activity {
    
        LinearLayout ll_decodeimages;
    //    GifFrame gifFrame = null;
        GifImageDecoder gifDecoder;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_custom);
            ll_decodeimages = (LinearLayout) findViewById(R.id.ll_decodeimages);
            showGif2();
        }
    //    void showGif()
    //    {
    //        // 解析gif动画
    //        gifFrame = GifFrame.createGifImage(fileConnect(this.getResources().openRawResource(R.drawable.b10)));
    //        int size = gifFrame.size();
    //        for(int i=0;i<size;i++)
    //        {
    //            
    //            ImageView iv_image = new ImageView(CustomActivity.this);
    //            iv_image.setPadding(5, 5, 5, 5);
    //            LayoutParams lparams = new LayoutParams(100,100);
    //            iv_image.setLayoutParams(lparams);
    //            iv_image.setImageBitmap(gifFrame.getImage());
    //            ll_decodeimages.addView(iv_image);
    //            gifFrame.nextFrame();
    //        }
    //    }
        void showGif2()
        {
            gifDecoder = new GifImageDecoder();
            try {
                gifDecoder.read(this.getResources().openRawResource(R.drawable.b17));
                int size =gifDecoder.getFrameCount();
                for(int i=0;i<size;i++)
                {
                    
                    ImageView iv_image = new ImageView(CustomActivity.this);
                    iv_image.setPadding(5, 5, 5, 5);
                    LayoutParams lparams = new LayoutParams(100,100);
                    iv_image.setLayoutParams(lparams);
                    iv_image.setImageBitmap(gifDecoder.getFrame(i));
                    ll_decodeimages.addView(iv_image);
    //                gifFrame.nextFrame();
                }
            } catch (NotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    //    Handler handler = new Handler()
    //    {
    //
    //        @Override
    //        public void handleMessage(Message msg) {
    //            switch(msg.what)
    //            {
    //            case 1:
    //                Bitmap bmp = (Bitmap) msg.obj;
    //                if(bmp!=null)
    //                {
    //                    ImageView iv_image = new ImageView(CustomActivity.this);
    //                    iv_image.setImageBitmap(bmp);
    //                    ll_decodeimages.addView(iv_image);
    //                }
    //                break;
    //            }
    //        }
    //        
    //    };
        /**
         * 独立线程解码gif图片
         * @author huqiang
         *
         */
    //    class DecodeGif implements Runnable 
    //    {
    //        Context mContext ;
    //        Handler mHandler;
    //        public DecodeGif(Context context,Handler handler)
    //        {
    //            this.mContext = context;
    //            this.mHandler = handler;
    //        }
    //        @Override
    //        public void run() {
    //            //开始解析gif
    //            // 解析gif动画
    ////            gifFrame = GifFrame.createGifImage(fileConnect(this.getResources().openRawResource(R.drawable.test)));
    //        }
    //        public void start()
    //        {
    //            new Thread(this).start();
    //        }
    //    }
        // 读取文件
            public byte[] fileConnect(InputStream is)
            {
                try
                {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    int ch = 0;
                    while ((ch = is.read()) != -1)
                    {
                        baos.write(ch);
                    }
                    byte[] b = baos.toByteArray();
                    baos.close();
                    baos = null;
                    is.close();
                    is = null;
                    return b;
                } catch (Exception e)
                {
                    return null;
                }
            }
    
    }
    package com.xlm.testgif;
    
    import android.annotation.SuppressLint;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.Canvas;
    
    import java.io.BufferedInputStream;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    
    public class GifImageDecoder {
        private static final String TAG = GifImageDecoder.class.getSimpleName();
        private final GifImageDecoder self = this;
    
        // 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;
        // Trailer
        private static final byte TRR_CODE = (byte) 0x3B;
        // Image Block
        private static final byte IMG_CODE = (byte) 0x2C;
        // Extension
        private static final byte EXT_CODE = (byte) 0x21;
        // Graphic Control Extension
        private static final byte GC_EXT = (byte) 0xF9;
        // Application Extension
        private static final byte APP_EXT = (byte) 0xFF;
        // Comment Extension
        private static final byte CMT_EXT = (byte) 0xFE;
        // Plain Text Extension
        private static final byte TXT_EXT = (byte) 0x01;
    
        private static final int MIN_DELAY = 100;
        private static final int MIN_DELAY_ENFORCE_THRESHOLD = 20;
    
        protected int mStatus;
        protected int mWidth; // full mCurrentImage mWidth
        protected int mHeight; // full mCurrentImage mHeight
        protected Bitmap mCurrentImage; // current frame
        protected Bitmap mLastImage; // previous frame
        protected int mDispose = 0; // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
        protected int mLastDispose = 0;
        protected int mDelay = 0; // mDelay in milliseconds
        protected ArrayList<GifFrame> mGifFrames; // mGifFrames read from current file
        protected int mFrameCount;
    
        private int mOffset = 0;
    
        private GifHeader mGifHeader;
        private GraphicControlExtension mGcExt;
        private ImageBlock mImageBlock;
    
        private static class GifFrame {
            public GifFrame(Bitmap im, int del) {
                image = im;
                delay = del;
            }
    
            public Bitmap 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) {
            mDelay = -1;
            if ((n >= 0) && (n < mFrameCount)) {
                mDelay = mGifFrames.get(n).delay;
                if (mDelay < MIN_DELAY_ENFORCE_THRESHOLD) {
                    mDelay = MIN_DELAY;
                }
            }
            return mDelay;
        }
        /**
         * Gets the number of GifFrames read from file.
         *
         * @return frame count
         */
        public int getFrameCount() {
            return mFrameCount;
        }
    
        /**
         * Gets the first (or only) image read.
         *
         * @return BufferedBitmap containing first frame, or null if none.
         */
        public Bitmap getBitmap() {
            return getFrame(0);
        }
    
        /**
         * Gets the image contents of frame n.
         *
         * @return BufferedBitmap representation of frame, or null if n is invalid.
         */
        public Bitmap getFrame(int n) {
            if (mFrameCount <= 0)
                return null;
            n = n % mFrameCount;
            return (mGifFrames.get(n)).image;
        }
    
        /**
         * Reads GIF image from stream
         *
         * @param is containing GIF file.
         * @return read status code (0 = no errors)
         */
    
        public int read(InputStream is) throws IOException {
            init();
            if (is != null) {
                byte[] buffer = Utils.streamToBytes(is);
                mGifHeader = new GifHeader(buffer, mOffset);
                mOffset += mGifHeader.size;
                mWidth = mGifHeader.getWidth();
                mHeight = mGifHeader.getHeight();
                if (!mGifHeader.getSignature().equals("GIF")) {
                    return STATUS_FORMAT_ERROR;
                }
                while (buffer[mOffset] != TRR_CODE) {
                    if (buffer[mOffset] == IMG_CODE) {
                        // ImageBlock
                        mImageBlock = new ImageBlock(buffer, mOffset);
                        mOffset += mImageBlock.size;
    
                        mFrameCount++;
                        // create new image to receive frame data
                        mCurrentImage = extractImage();
                        if (mLastDispose > 0) {
                            if (mLastDispose == 3) {
                                // use image before last
                                int n = mFrameCount - 2;
                                if (n > 0) {
                                    mLastImage = getFrame(n - 1);
                                } else {
                                    mLastImage = null;
                                }
                            }
                        }
                        mGifFrames.add(new GifFrame(mCurrentImage, mDelay)); // add image to frame
                        resetFrame();
                    } else if (buffer[mOffset] == EXT_CODE) {
                        if (buffer[mOffset + 1] == GC_EXT) {
                            //GraphicControlExtension
                            mGcExt = new GraphicControlExtension(buffer, mOffset);
                            mOffset += mGcExt.size;
                            mDispose = mGcExt.getDisposalMothod(); // disposal method
                            if (mDispose == 0) {
                                mDispose = 1; // elect to keep old image if discretionary
                            }
                            mDelay = mGcExt.getDelayTime() * 10; // delay in milliseconds
                        } else if (buffer[mOffset + 1] == APP_EXT) {
                            //ApplicationExtension
                            ApplicationExtension appExt = new ApplicationExtension(buffer, mOffset);
                            mOffset += appExt.size;
                        } else if (buffer[mOffset + 1] == CMT_EXT) {
                            //CommentExtension
                            CommentExtension cmtExt = new CommentExtension(buffer, mOffset);
                            mOffset += cmtExt.size;
                        } else if (buffer[mOffset + 1] == TXT_EXT) {
                            //PlainTextExtension
                            PlainTextExtension txtExt = new PlainTextExtension(buffer, mOffset);
                            mOffset += txtExt.size;
                        } else {
                            throw new IOException();
                        }
                    } else {
                        throw new IOException();
                    }
                }
            } else {
                mStatus = STATUS_OPEN_ERROR;
            }
            return mStatus;
        }
    
        /**
         * Initializes or re-initializes reader
         */
        protected void init() {
            mStatus = STATUS_OK;
            mFrameCount = 0;
            mGifFrames = new ArrayList<GifFrame>();
        }
    
        /**
         * Resets frame state for reading next image.
         */
        protected void resetFrame() {
            mLastDispose = mDispose;
            mLastImage = mCurrentImage;
            mDispose = 0;
            mDelay = 0;
        }
    
        /**
         * Extract new image
         *
         * @return image
         */
        @SuppressLint("NewApi") private Bitmap extractImage() {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            try {
                outputStream.write(mGifHeader.bytes);
                if (mGcExt != null) {
                    if ((mWidth != mImageBlock.getImageWidth() || mHeight != mImageBlock.getImageHeight()) &&
                            mGcExt.getTransparentColorFlag() == 0) {
                        mGcExt.setTransparentColorFlagTrue();
                    }
                    outputStream.write(mGcExt.bytes);
                }
                outputStream.write(mImageBlock.bytes);
                outputStream.write((byte) 0x3B);
                outputStream.flush();
    
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inMutable = true;
                options.inPreferredConfig = Bitmap.Config.RGB_565;
                Bitmap newBitmap = BitmapFactory.decodeStream(new BufferedInputStream(new ByteArrayInputStream(outputStream.toByteArray())));
                if (newBitmap != null) {
                    if (mLastImage == null) {
                        return newBitmap;
                    } else {
                        Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
                        Canvas canvas = new Canvas(bitmap);
                        canvas.drawBitmap(mLastImage, 0, 0, null);
                        canvas.drawBitmap(newBitmap, 0, 0, null);
                        return bitmap;
                    }
                } else {
                    if (mLastImage != null) {
                        return mLastImage;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
            return null;
        }
    
        private class GifHeader {
            public byte[] bytes;
            public int size;
    
            public GifHeader(byte[] bytes, int offset) {
                boolean globalColorTableFlag = (bytes[offset + 0x0A] & 0x80) != 0x00;
                int globalColorTableSize = (bytes[offset + 0x0A] & 0x07);
    
                // get size
                size = 0x0D;
                if (globalColorTableFlag) {
                    size += Math.pow(2, (globalColorTableSize + 1)) * 3;
                }
    
                this.bytes = new byte[size];
                System.arraycopy(bytes, offset, this.bytes, 0, size);
            }
    
            public String getSignature() {
                return new String(bytes, 0, 3);
            }
    
            public String getVersion() {
                return new String(bytes, 3, 3);
            }
    
            public int getWidth() {
                return (bytes[6] & 0xFF) + ((bytes[7] & 0xFF) << 8);
            }
    
            public int getHeight() {
                return (bytes[8] & 0xFF) + ((bytes[9] & 0xFF) << 8);
            }
    
            public int getGlobalColorTableFlag() {
                return (bytes[10] & 0x80) >> 7;
            }
    
            public int getColorResolution() {
                return (bytes[10] & 0x70) >> 4;
            }
    
            public int getSortFlag() {
                return (bytes[10] & 0x08) >> 3;
            }
    
            public int getSizeOfGlobalColorTable() {
                return (bytes[10] & 0x07);
            }
    
            public int getBackgroundColorIndex() {
                return bytes[11] & 0xFF;
            }
    
            public int getPixelAspectRatio() {
                return bytes[12];
            }
    
            public int[] getGlobalColorTable() {
                if (getGlobalColorTableFlag() == 0) {
                    return new int[0];
                }
                int[] colors = new int[(int) Math.pow(2, getSizeOfGlobalColorTable() + 1)];
                for (int i = 0; i < colors.length; i++) {
                    colors[i] = ((bytes[13 + (i * 3)] & 0xFF) << 16) + ((bytes[13 + (i * 3) + 1] & 0xFF) << 8) + (bytes[13 + (i * 3) + 2] & 0xFF);
                }
                return colors;
            }
        }
    
        private class ImageBlock {
            public byte[] bytes;
            public int size;
    
            public ImageBlock(byte[] bytes, int offset) {
                int blockSize;
                boolean localColorTableFlag = (bytes[offset + 0x09] & 0x80) != 0x00;
                int localColorTableSize = (bytes[offset + 0x09] & 0x07);
    
                //get size
                size = 0x0A;
                if (localColorTableFlag) {
                    size += Math.pow(2, (localColorTableSize + 1)) * 3;
                }
                size += 1; //LZW Minimum Code Size
    
                //ImageData
                blockSize = bytes[offset + size] & 0xFF;
                size += 1;
                while (blockSize != 0x00) {
                    size += blockSize;
                    blockSize = bytes[offset + size] & 0xFF;
                    size += 1;
                }
    
                this.bytes = new byte[size];
                System.arraycopy(bytes, offset, this.bytes, 0, size);
            }
    
            public int getImageSeparator() {
                return bytes[0] & 0xFF;
            }
    
            public int ImageLeftPosition() {
                return (bytes[1] & 0xFF) + ((bytes[2] & 0xFF) << 8);
            }
    
            public int getImageTopPosition() {
                return (bytes[3] & 0xFF) + ((bytes[4] & 0xFF) << 8);
            }
    
            public int getImageWidth() {
                return (bytes[5] & 0xFF) + ((bytes[6] & 0xFF) << 8);
            }
    
            public int getImageHeight() {
                return (bytes[7] & 0xFF) + ((bytes[8] & 0xFF) << 8);
            }
    
            public int getLocalColorTableFlag() {
                return (bytes[9] & 0x80) >> 7;
            }
    
            public int getInterlaceFlag() {
                return (bytes[9] & 0x40) >> 6;
            }
    
            public int getSortFlag() {
                return (bytes[9] & 0x20) >> 5;
            }
    
            public int getReserved() {
                return (bytes[9] & 0x18) >> 2;
            }
    
            public int getSizeOfLocalColorTable() {
                return bytes[9] & 0x03;
            }
    
            public int[] getLocalColorTable() {
                if (getLocalColorTableFlag() == 0) {
                    return new int[0];
                }
                int[] colors = new int[(int) Math.pow(2, getSizeOfLocalColorTable() + 1)];
                for (int i = 0; i < colors.length; i++) {
                    colors[i] = ((bytes[10 + (i * 3)] & 0xFF) << 16) + ((bytes[10 + (i * 3) + 1] & 0xFF) << 8) + (bytes[10 + (i * 3) + 2] & 0xFF);
                }
                return colors;
            }
    
            public int getLZWMinimumCodeSize() {
                if (getLocalColorTableFlag() == 0) {
                    return bytes[10] & 0xFF;
                } else {
                    return bytes[10 + (int) Math.pow(2, getSizeOfLocalColorTable() + 1) * 3] & 0xFF;
                }
            }
        }
    
        private class ApplicationExtension {
            public byte[] bytes;
            public int size;
    
            public ApplicationExtension(byte[] bytes, int offset) {
                int blockSize;
                // get size
                size = 0x0E;
    
                blockSize = bytes[offset + size] & 0xFF;
                size += 1;
                while (blockSize != 0x00) {
                    size += blockSize;
                    blockSize = bytes[offset + size] & 0xFF;
                    size += 1;
                }
    
                this.bytes = new byte[size];
                System.arraycopy(bytes, offset, this.bytes, 0, size);
            }
    
            public int getExtensionIntroducer() {
                return bytes[0] & 0xFF;
            }
    
            public int getExtensionLabel() {
                return bytes[1] & 0xFF;
            }
    
            public int getBlockSize1() {
                return bytes[2] & 0xFF;
            }
    
            public String getApplicationIdentifier() {
                return new String(bytes, 3, 8);
            }
    
            public String getApplicationAuthenticationCode() {
                return new String(bytes, 11, 3);
            }
        }
    
        private class GraphicControlExtension {
            public byte[] bytes;
            public int size;
    
            public GraphicControlExtension(byte[] bytes, int offset) {
                size = 8;
                this.bytes = new byte[size];
                System.arraycopy(bytes, offset, this.bytes, 0, size);
            }
    
            public int getExtensionIntroducer() {
                return bytes[0] & 0xFF;
            }
    
            public int getGraphicControlLabel() {
                return bytes[1] & 0xFF;
            }
    
            public int getBlockSize() {
                return bytes[2] & 0xFF;
            }
    
            public int getReserved() {
                return (bytes[3] & 0xE0) >> 5;
            }
    
            public int getDisposalMothod() {
                return (bytes[3] & 0x1C) >> 2;
            }
    
            public int getUserInputFlag() {
                return (bytes[3] & 0x02) >> 1;
            }
    
            public int getTransparentColorFlag() {
                return (bytes[3] & 0x01);
            }
    
            public int getDelayTime() {
                return (bytes[4] & 0xFF) + ((bytes[5] & 0xFF) << 8);
            }
    
            public int getTransparentColorIndex() {
                return bytes[6];
            }
    
            public void setTransparentColorFlagTrue() {
                int value = getReserved() | getDisposalMothod() | getUserInputFlag() | 0x01;
                bytes[3] = (byte) Integer.parseInt(Utils.toHex(value, 2), 16);
            }
        }
    
        private class CommentExtension {
            public byte[] bytes;
            public int size;
    
            public CommentExtension(byte[] bytes, int offset) {
                int blockSize;
                // get size
                size = 0x02;
    
                blockSize = bytes[offset + size] & 0xFF;
                size += 1;
                while (blockSize != 0x00) {
                    size += blockSize;
                    blockSize = bytes[offset + size] & 0xFF;
                    size += 1;
                }
    
                this.bytes = new byte[size];
                System.arraycopy(bytes, offset, this.bytes, 0, size);
            }
        }
    
        private class PlainTextExtension {
            public byte[] bytes;
            public int size;
    
            public PlainTextExtension(byte[] bytes, int offset) {
                int blockSize;
                // get size
                size = 0x0F;
    
                blockSize = bytes[offset + size] & 0xFF;
                size += 1;
                while (blockSize != 0x00) {
                    size += blockSize;
                    blockSize = bytes[offset + size] & 0xFF;
                    size += 1;
                }
    
                this.bytes = new byte[size];
                System.arraycopy(bytes, offset, this.bytes, 0, size);
            }
        }
    }
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    
    public class Utils {
        public static String toHex(int value, int length) {
            String hex = Integer.toHexString(value);
            hex = hex.toUpperCase();
    
            if (hex.length() < length) {
                while (hex.length() < length)
                    hex = "0" + hex;
            } else if (hex.length() > length) {
                hex = hex.substring(hex.length() - length);
            }
            return hex;
        }
    
        public static byte[] streamToBytes(InputStream stream) throws IOException,
                OutOfMemoryError {
            byte[] buff = new byte[1024];
            int read;
            ByteArrayOutputStream bao = new ByteArrayOutputStream();
            while ((read = stream.read(buff)) != -1) {
                bao.write(buff, 0, read);
            }
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bao.toByteArray();
        }
    }
  • 相关阅读:
    Js五子棋游戏
    换肤
    jqzoom实战
    iphone开发笔记
    腾讯召实习生笔试题
    ajax( 汇率转化)
    20140805&nbsp;17:24
    加载上一级目录下的图片文件并得到加载图片的大小
    精确碰撞检测 bitmapData.hitTest
    buttonMode 与mouseChildren【替换鼠标之后不响应鼠标事件】
  • 原文地址:https://www.cnblogs.com/feijian/p/4495281.html
Copyright © 2011-2022 走看看