环境: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();        }    }


见效果:

android 开发 解码gif图片,获取每帧bitmap

全部代码:

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();    }}

更多相关文章

  1. android图片压缩质量参数Bitmap.Config RGB_565等的含义
  2. Android怎么让RadioButton图片居中显示
  3. android点击按钮控制图片切换-kotlin
  4. android开机动画bootanimation
  5. 补间动画--缩放动画XML
  6. android 触摸手指动作放大和缩小图片
  7. 直播源码Android实现 曲线路径动画
  8. Android 调用系统相册选择图片并显示
  9. android 自动更新apk版本

随机推荐

  1. Android语音识别
  2. Android(安卓)studio Dialog 弹出式对话
  3. Android自动判定输入的是电话号码还是网
  4. android 处理图片工具类
  5. Android(安卓)AsynTask学习笔记
  6. android 图片缩放
  7. getSystemService
  8. Android(安卓)ListView异步加载图片
  9. Android(安卓)learning Starting!
  10. Android(安卓)drawRect参数