zoukankan      html  css  js  c++  java
  • Android 加载.gif格式图片

    在Android中不支持直接加载gif格式的图片,只能

    方法一:通过解码gif图片形成多张静态图,然后通过线程和imageView来实现循环播放,具体如下:

    工具类:CommonUtil.java

    package com.example.playgif;
    
    import java.io.InputStream;
    
    import com.example.playgif.GifHelper.GifFrame;
    
    public class CommonUtil {
        /**
         * 解码GIF图片
         * 
         * @param is
         * @return
         */
        public static GifFrame[] getGif(InputStream is) {
            GifHelper gifHelper = new GifHelper();
            if (GifHelper.STATUS_OK == gifHelper.read(is)) {
                return gifHelper.getFrames();
            }
            return null;
        }
        /**
         * 判断图片是否为GIF格式
         * @param is
         * @return
         */
        public static boolean isGif(InputStream is) {
            GifHelper gifHelper = new GifHelper();
            return gifHelper.isGif(is);
        }
    }
    

    解码类:

    package com.example.playgif;
    
    import java.io.InputStream;
    import java.util.Vector;
    
    import android.graphics.Bitmap;
    import android.graphics.Bitmap.Config;
    
    //Handler for read & extract Bitmap from *.gif
    public class GifHelper {
    
        // to store *.gif data, Bitmap & delay
        public static class GifFrame {
            // to access image & delay w/o interface
            public Bitmap image;
            public int delay;
    
            public GifFrame(Bitmap im, int del) {
                image = im;
                delay = del;
            }
    
        }
    
        // to define some error type
        public static final int STATUS_OK = 0;
        public static final int STATUS_FORMAT_ERROR = 1;
        public static final int STATUS_OPEN_ERROR = 2;
    
        protected int status;
    
        protected InputStream in;
    
        protected int width; // full image width
        protected int height; // full image height
        protected boolean gctFlag; // global color table used
        protected int gctSize; // size of global color table
        protected int loopCount = 1; // iterations; 0 = repeat forever
    
        protected int[] gct; // global color table
        protected int[] lct; // local color table
        protected int[] act; // active color table
    
        protected int bgIndex; // background color index
        protected int bgColor; // background color
        protected int lastBgColor; // previous bg color
        protected int pixelAspect; // pixel aspect ratio
    
        protected boolean lctFlag; // local color table flag
        protected boolean interlace; // interlace flag
        protected int lctSize; // local color table size
    
        protected int ix, iy, iw, ih; // current image rectangle
        protected int lrx, lry, lrw, lrh;
        protected Bitmap image; // current frame
        protected Bitmap lastImage; // previous frame
        protected int frameindex = 0;
    
        public int getFrameindex() {
            return frameindex;
        }
    
        public void setFrameindex(int frameindex) {
            this.frameindex = frameindex;
            if (frameindex > frames.size() - 1) {
                frameindex = 0;
            }
        }
    
        protected byte[] block = new byte[256]; // current data block
        protected int blockSize = 0; // block size
    
        // last graphic control extension info
        protected int dispose = 0;
        // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
        protected int lastDispose = 0;
        protected boolean transparency = false; // use transparent color
        protected int delay = 0; // delay in milliseconds
        protected int transIndex; // transparent color index
    
        protected static final int MaxStackSize = 4096;
        // max decoder pixel stack size
    
        // LZW decoder working arrays
        protected short[] prefix;
        protected byte[] suffix;
        protected byte[] pixelStack;
        protected byte[] pixels;
    
        protected Vector<GifFrame> frames; // frames read from current file
        protected int frameCount;
    
        // to get its Width / Height
        public int getWidth() {
            return width;
        }
    
        public int getHeigh() {
            return height;
        }
    
        /**
         * Gets display duration for specified frame.
         * 
         * @param n
         *            int index of frame
         * @return delay in milliseconds
         */
        public int getDelay(int n) {
            delay = -1;
            if ((n >= 0) && (n < frameCount)) {
                delay = ((GifFrame) frames.elementAt(n)).delay;
            }
            return delay;
        }
    
        public int getFrameCount() {
            return frameCount;
        }
    
        public Bitmap getImage() {
            return getFrame(0);
        }
    
        public int getLoopCount() {
            return loopCount;
        }
    
        protected void setPixels() {
            int[] dest = new int[width * height];
            // fill in starting image contents based on last image's dispose code
            if (lastDispose > 0) {
                if (lastDispose == 3) {
                    // use image before last
                    int n = frameCount - 2;
                    if (n > 0) {
                        lastImage = getFrame(n - 1);
                    } else {
                        lastImage = null;
                    }
                }
                if (lastImage != null) {
                    lastImage.getPixels(dest, 0, width, 0, 0, width, height);
                    // copy pixels
                    if (lastDispose == 2) {
                        // fill last image rect area with background color
                        int c = 0;
                        if (!transparency) {
                            c = lastBgColor;
                        }
                        for (int i = 0; i < lrh; i++) {
                            int n1 = (lry + i) * width + lrx;
                            int n2 = n1 + lrw;
                            for (int k = n1; k < n2; k++) {
                                dest[k] = c;
                            }
                        }
                    }
                }
            }
    
            // copy each source line to the appropriate place in the destination
            int pass = 1;
            int inc = 8;
            int iline = 0;
            for (int i = 0; i < ih; i++) {
                int line = i;
                if (interlace) {
                    if (iline >= ih) {
                        pass++;
                        switch (pass) {
                        case 2:
                            iline = 4;
                            break;
                        case 3:
                            iline = 2;
                            inc = 4;
                            break;
                        case 4:
                            iline = 1;
                            inc = 2;
                        }
                    }
                    line = iline;
                    iline += inc;
                }
                line += iy;
                if (line < height) {
                    int k = line * width;
                    int dx = k + ix; // start of line in dest
                    int dlim = dx + iw; // end of dest line
                    if ((k + width) < dlim) {
                        dlim = k + width; // past dest edge
                    }
                    int sx = i * iw; // start of line in source
                    while (dx < dlim) {
                        // map color and insert in destination
                        int index = ((int) pixels[sx++]) & 0xff;
                        int c = act[index];
                        if (c != 0) {
                            dest[dx] = c;
                        }
                        dx++;
                    }
                }
            }
            image = Bitmap.createBitmap(dest, width, height, Config.RGB_565);
        }
    
        public Bitmap getFrame(int n) {
            Bitmap im = null;
            if ((n >= 0) && (n < frameCount)) {
                im = ((GifFrame) frames.elementAt(n)).image;
            }
            return im;
        }
        
        public GifFrame[] getFrames() {
            if(null != frames) return frames.toArray(new GifFrame[0]);
            return null;
        }
    
        public Bitmap nextBitmap() {
            frameindex++;
            if (frameindex > frames.size() - 1) {
                frameindex = 0;
            }
            return ((GifFrame) frames.elementAt(frameindex)).image;
        }
    
        public int nextDelay() {
            return ((GifFrame) frames.elementAt(frameindex)).delay;
        }
    
        // to read & parse all *.gif stream
        public int read(InputStream is) {
            init();
            if (is != null) {
                in = is;
                readHeader();
                if (!err()) {
                    readContents();
                    if (frameCount < 0) {
                        status = STATUS_FORMAT_ERROR;
                    }
                }
            } else {
                status = STATUS_OPEN_ERROR;
            }
            try {
                is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return status;
        }
        
        public boolean isGif(InputStream is) {
            init();
            if (is != null) {
                in = is;
                String id = "";
                for (int i = 0; i < 6; i++) {
                    id += (char) read();
                }
                if (!id.toUpperCase().startsWith("GIF")) {
                    return false;
                }
            }
            try {
                is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return true;
        }
    
        protected void decodeImageData() {
            int NullCode = -1;
            int npix = iw * ih;
            int available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, count, i, datum, data_size, first, top, bi, pi;
    
            if ((pixels == null) || (pixels.length < npix)) {
                pixels = new byte[npix]; // allocate new pixel array
            }
            if (prefix == null) {
                prefix = new short[MaxStackSize];
            }
            if (suffix == null) {
                suffix = new byte[MaxStackSize];
            }
            if (pixelStack == null) {
                pixelStack = new byte[MaxStackSize + 1];
            }
            // Initialize GIF data stream decoder.
            data_size = read();
            clear = 1 << data_size;
            end_of_information = clear + 1;
            available = clear + 2;
            old_code = NullCode;
            code_size = data_size + 1;
            code_mask = (1 << code_size) - 1;
            for (code = 0; code < clear; code++) {
                prefix[code] = 0;
                suffix[code] = (byte) code;
            }
    
            // Decode GIF pixel stream.
            datum = bits = count = first = top = pi = bi = 0;
            for (i = 0; i < npix;) {
                if (top == 0) {
                    if (bits < code_size) {
                        // Load bytes until there are enough bits for a code.
                        if (count == 0) {
                            // Read a new data block.
                            count = readBlock();
                            if (count <= 0) {
                                break;
                            }
                            bi = 0;
                        }
                        datum += (((int) block[bi]) & 0xff) << bits;
                        bits += 8;
                        bi++;
                        count--;
                        continue;
                    }
                    // Get the next code.
                    code = datum & code_mask;
                    datum >>= code_size;
                    bits -= code_size;
    
                    // Interpret the code
                    if ((code > available) || (code == end_of_information)) {
                        break;
                    }
                    if (code == clear) {
                        // Reset decoder.
                        code_size = data_size + 1;
                        code_mask = (1 << code_size) - 1;
                        available = clear + 2;
                        old_code = NullCode;
                        continue;
                    }
                    if (old_code == NullCode) {
                        pixelStack[top++] = suffix[code];
                        old_code = code;
                        first = code;
                        continue;
                    }
                    in_code = code;
                    if (code == available) {
                        pixelStack[top++] = (byte) first;
                        code = old_code;
                    }
                    while (code > clear) {
                        pixelStack[top++] = suffix[code];
                        code = prefix[code];
                    }
                    first = ((int) suffix[code]) & 0xff;
                    // Add a new string to the string table,
                    if (available >= MaxStackSize) {
                        break;
                    }
                    pixelStack[top++] = (byte) first;
                    prefix[available] = (short) old_code;
                    suffix[available] = (byte) first;
                    available++;
                    if (((available & code_mask) == 0)
                            && (available < MaxStackSize)) {
                        code_size++;
                        code_mask += available;
                    }
                    old_code = in_code;
                }
    
                // Pop a pixel off the pixel stack.
                top--;
                pixels[pi++] = pixelStack[top];
                i++;
            }
            for (i = pi; i < npix; i++) {
                pixels[i] = 0; // clear missing pixels
            }
        }
    
        protected boolean err() {
            return status != STATUS_OK;
        }
    
        // to initia variable
        protected void init() {
            status = STATUS_OK;
            frameCount = 0;
            frames = new Vector<GifFrame>();
            gct = null;
            lct = null;
        }
    
        protected int read() {
            int curByte = 0;
            try {
                curByte = in.read();
            } catch (Exception e) {
                status = STATUS_FORMAT_ERROR;
            }
            return curByte;
        }
    
        protected int readBlock() {
            blockSize = read();
            int n = 0;
            if (blockSize > 0) {
                try {
                    int count = 0;
                    while (n < blockSize) {
                        count = in.read(block, n, blockSize - n);
                        if (count == -1) {
                            break;
                        }
                        n += count;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (n < blockSize) {
                    status = STATUS_FORMAT_ERROR;
                }
            }
            return n;
        }
    
        // Global Color Table
        protected int[] readColorTable(int ncolors) {
            int nbytes = 3 * ncolors;
            int[] tab = null;
            byte[] c = new byte[nbytes];
            int n = 0;
            try {
                n = in.read(c);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (n < nbytes) {
                status = STATUS_FORMAT_ERROR;
            } else {
                tab = new int[256]; // max size to avoid bounds checks
                int i = 0;
                int j = 0;
                while (i < ncolors) {
                    int r = ((int) c[j++]) & 0xff;
                    int g = ((int) c[j++]) & 0xff;
                    int b = ((int) c[j++]) & 0xff;
                    tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
                }
            }
            return tab;
        }
    
        // Image Descriptor
        protected void readContents() {
            // read GIF file content blocks
            boolean done = false;
            while (!(done || err())) {
                int code = read();
                switch (code) {
                case 0x2C: // image separator
                    readImage();
                    break;
                case 0x21: // extension
                    code = read();
                    switch (code) {
                    case 0xf9: // graphics control extension
                        readGraphicControlExt();
                        break;
    
                    case 0xff: // application extension
                        readBlock();
                        String app = "";
                        for (int i = 0; i < 11; i++) {
                            app += (char) block[i];
                        }
                        if (app.equals("NETSCAPE2.0")) {
                            readNetscapeExt();
                        } else {
                            skip(); // don't care
                        }
                        break;
                    default: // uninteresting extension
                        skip();
                    }
                    break;
    
                case 0x3b: // terminator
                    done = true;
                    break;
    
                case 0x00: // bad byte, but keep going and see what happens
                    break;
                default:
                    status = STATUS_FORMAT_ERROR;
                }
            }
        }
    
        protected void readGraphicControlExt() {
            read(); // block size
            int packed = read(); // packed fields
            dispose = (packed & 0x1c) >> 2; // disposal method
            if (dispose == 0) {
                dispose = 1; // elect to keep old image if discretionary
            }
            transparency = (packed & 1) != 0;
            delay = readShort() * 10; // delay in milliseconds
            transIndex = read(); // transparent color index
            read(); // block terminator
        }
    
        // to get Stream - Head
        protected void readHeader() {
            String id = "";
            for (int i = 0; i < 6; i++) {
                id += (char) read();
            }
            if (!id.toUpperCase().startsWith("GIF")) {
                status = STATUS_FORMAT_ERROR;
                return;
            }
            readLSD();
            if (gctFlag && !err()) {
                gct = readColorTable(gctSize);
                bgColor = gct[bgIndex];
            }
        }
    
        protected void readImage() {
            // offset of X
            ix = readShort(); // (sub)image position & size
            // offset of Y
            iy = readShort();
            // width of bitmap
            iw = readShort();
            // height of bitmap
            ih = readShort();
    
            // Local Color Table Flag
            int packed = read();
            lctFlag = (packed & 0x80) != 0; // 1 - local color table flag
    
            // Interlace Flag, to array with interwoven if ENABLE, with order
            // otherwise
            interlace = (packed & 0x40) != 0; // 2 - interlace flag
            // 3 - sort flag
            // 4-5 - reserved
            lctSize = 2 << (packed & 7); // 6-8 - local color table size
            if (lctFlag) {
                lct = readColorTable(lctSize); // read table
                act = lct; // make local table active
            } else {
                act = gct; // make global table active
                if (bgIndex == transIndex) {
                    bgColor = 0;
                }
            }
            int save = 0;
            if (transparency) {
                save = act[transIndex];
                act[transIndex] = 0; // set transparent color if specified
            }
            if (act == null) {
                status = STATUS_FORMAT_ERROR; // no color table defined
            }
            if (err()) {
                return;
            }
            decodeImageData(); // decode pixel data
            skip();
            if (err()) {
                return;
            }
            frameCount++;
            // create new image to receive frame data
            image = Bitmap.createBitmap(width, height, Config.RGB_565);
            // createImage(width, height);
            setPixels(); // transfer pixel data to image
            frames.addElement(new GifFrame(image, delay)); // add image to frame
            // list
            if (transparency) {
                act[transIndex] = save;
            }
            resetFrame();
        }
    
        // Logical Screen Descriptor
        protected void readLSD() {
            // logical screen size
            width = readShort();
            height = readShort();
            // packed fields
            int packed = read();
            gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
            // 2-4 : color resolution
            // 5 : gct sort flag
            gctSize = 2 << (packed & 7); // 6-8 : gct size
            bgIndex = read(); // background color index
            pixelAspect = read(); // pixel aspect ratio
        }
    
        protected void readNetscapeExt() {
            do {
                readBlock();
                if (block[0] == 1) {
                    // loop count sub-block
                    int b1 = ((int) block[1]) & 0xff;
                    int b2 = ((int) block[2]) & 0xff;
                    loopCount = (b2 << 8) | b1;
                }
            } while ((blockSize > 0) && !err());
        }
    
        // read 8 bit data
        protected int readShort() {
            // read 16-bit value, LSB first
            return read() | (read() << 8);
        }
    
        protected void resetFrame() {
            lastDispose = dispose;
            lrx = ix;
            lry = iy;
            lrw = iw;
            lrh = ih;
            lastImage = image;
            lastBgColor = bgColor;
            dispose = 0;
            transparency = false;
            delay = 0;
            lct = null;
        }
    
        /**
         * Skips variable length blocks up to and including next zero length block.
         */
        protected void skip() {
            do {
                readBlock();
            } while ((blockSize > 0) && !err());
        }
    }
    

    Activity显示:

    package com.example.playgif;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.InputStream;
    
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.ImageView;
    import android.widget.ImageView.ScaleType;
    
    import com.example.playgif.GifHelper.GifFrame;
    import com.sample.fun.R;
    
    
    public class AndroidGifActivity extends Activity {
    	
    	private PlayGifTask mGifTask;
    	ImageView iv;
    	GifFrame[] frames;
    	FileInputStream fis=null;
    	
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
          
            iv = new ImageView(this);
            iv.setScaleType(ScaleType.CENTER);
            setContentView(iv, new LayoutParams(LayoutParams.FILL_PARENT,
                    LayoutParams.FILL_PARENT));
            //对Gif图片进行解码
            final InputStream fis = getResources().openRawResource(R.drawable.test);
           
    		/*try {
    			fis = new FileInputStream(new File(Environment.getExternalStorageDirectory()+File.separator+"/tmp/111.gif"));
    		} catch (FileNotFoundException e) {
    			e.printStackTrace();
    		}*/
    	
            frames = CommonUtil.getGif(fis);
    		 mGifTask = new PlayGifTask(iv, frames);
    		 mGifTask.startTask();
    	    Thread th=new Thread(mGifTask);
    	    th.start();
    		
        }
        
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if(null != mGifTask) mGifTask.stopTask();
            
        }
        
       
        //用来循环播放Gif每帧图片
        private class PlayGifTask implements Runnable {
            int i = 0;
            ImageView iv;
            GifFrame[] frames;
            int framelen,oncePlayTime=0;
    
            public PlayGifTask(ImageView iv, GifFrame[] frames) {
                this.iv = iv;
                this.frames = frames;
                
                int n=0;
                framelen=frames.length;
                while(n<framelen){
                	oncePlayTime+=frames[n].delay;
                	n++;
                }
                Log.d("msg", "playTime= "+oncePlayTime);
               
            }
    
            Handler h2=new Handler(){
            	public void handleMessage(Message msg) {
    	        	switch(msg.what){
    	        	 case 1:
    	      			iv.setImageBitmap((Bitmap)msg.obj);
    	      			break;
    	        	}
            	};
            };
            @Override
            public void run() {
                if (!frames[i].image.isRecycled()) {
              //      iv.setImageBitmap(frames[i].image);
                	Message m=Message.obtain(h2, 1, frames[i].image);
                	m.sendToTarget();
                }
                iv.postDelayed(this, frames[i++].delay);
                i %= framelen;  
            }
            
            public void startTask() {
                iv.post(this);
            }
            
            public void stopTask() {
                if(null != iv) iv.removeCallbacks(this);
                iv = null;
                if(null != frames) {
                    for(GifFrame frame : frames) {
                        if(frame.image != null && !frame.image.isRecycled()) {
                            frame.image.recycle();
                            frame.image = null;
                        }
                    }
                    frames = null;
              //      mGifTask=null;
                }
            }
        }
    }
    




  • 相关阅读:
    log4j 使用笔记整理中
    执行bat文件
    excel让每个单元格的宽度随着字体自动变动的两种方式(有更好方法的大神,请忽略,求评论下)
    XML中CDATA及其字符实体的使用
    Java文件读写操作指定编码方式。。。。。
    尾数为0零BigDecimal不能装成正常数
    jquery 自动补全控件(支持IE6)待整理
    $.ajax提交,后台接受到的值总是乱码?明天再总结
    js定义变量需赋予初始值
    存储过程的优缺点
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6818986.html
Copyright © 2011-2022 走看看