Android for GIF playback (decoding)

Source: Internet
Author: User
Tags transparent color

The implementation of the principle is very simple, first GIF animation decoding into multiple bitmap pictures, and then put into the animationdrawable inside to play each one.

Gifhelper Code:

Package Com.android.view;import Java.io.inputstream;import Java.util.vector;import android.graphics.bitmap;import  Android.graphics.bitmap.config;//handler for Read & extract Bitmap from *.gifpublic class Gifhelper {//To define some Error typepublic static final int status_ok = 0;public static final int status_format_error = 1;public static final int S Tatus_open_error = 2;protected int status;protected inputstream in;protected int width; Full image widthprotected int height; Full Image heightprotected Boolean gctflag; Global color table usedprotected int gctsize; Size of global color tableprotected int loopcount = 1; iterations; 0 = repeat foreverprotected int[] GCT; Global color tableprotected int[] LCT; Local color tableprotected int[] Act; Active color tableprotected int bgindex; Background color indexprotected int bgColor; Background colorprotected int lastbgcolor; Previous BG colorprotected int pixelaspect; Pixel Aspect ratioprotected Boolean Lctflag; Local Color Table flagprotected Boolean interlace; interlace flagprotected int lctsize; Local color table sizeprotected int IX, IY, IW, IH; Current image rectangleprotected int LRx, lry, LRW, lrh;protected Bitmap image; Current frameprotected Bitmap lastimage; Previous frameprotected 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 blockprotected int blockSize = 0; Block size//last graphic control extension infoprotected int dispose = 0;//0=no action; 1=leave in place; 2=restore to BG; 3=restore to prevprotected int lastdispose = 0;protected Boolean transparency = false; Use transparent colorprotected int delay = 0; Delay in millisecondsprotected int transindex; Transparent color indexprotected static final int maxstacksize = 4096;//Max decoder Pixel stack size//LZW decoder working arraysprotected short[] prefix;protected byte[] suffix;protected byte[] PixelStack ;p rotected byte[] pixels;protected vector<gifframe> frames; Frames read from the fileprotected int framecount;//to get its width/heightpublic 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 Codeif (Lastdispose > 0) {if (Lastdispose = = 3) {//Use image before Lastint n = framecount-2;if (N &Gt 0) {lastimage = GetFrame (n-1);} else {lastimage = null;}} if (lastimage! = null) {lastimage.getpixels (dest, 0, width, 0, 0, width, height);//Copy pixelsif (lastdispose = = 2) {//F Ill last image, rect area with background colorint 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++) {des T[K] = C;}}}}  Copy each of the source line to the appropriate place in the Destinationint 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 destint Dlim = dx + IW;//End of Dest Lineif ((k + width) < Dlim) {Dlim = k + width;//past dest Edge}int SX = i * IW; Start of line in Sourcewhile (DX < Dlim) {// Map color and insert in Destinationint index = ((int) pixels[sx++]) & 0xff;int C = act[index];if (c! = 0) {DEST[DX] = C;} dx++;}}} Image = Bitmap.createbitmap (dest, width, height, config.argb_4444);} Public Bitmap getframe (int n) {Bitmap im = Null;if ((n >= 0) && (n < framecount)) {im = ((gifframe) FRAMES.E Lementat (n)). Image; return im;} 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 streampublic int read (InputStream is) {init (), if (is! = null) {in = Is;readheader (); Err ()) {readcontents (); if (Framecount < 0) {status = Status_format_error;}}} else {status = Status_open_error;} try {is.close ();} catch (Exception e) {e.printstacktrace ();} return status;} 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 ((pixel s = = 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;avail Able = 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 is 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 Codeif (CO De > 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--;p ixels[pi++] = pixelstack[top];i++;} for (i = pi; i < Npix; i++) {pixels[i] = 0;//Clear Missing pixels}}protected Boolean err () {return status! = Status_o K;} To Initia variablepublic void init () {status = Status_ok;framecount = 0;frames = new vector<gifframe> (); GCT = nul L;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 tableprotected 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 checksint i = 0;i NT 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 descriptorprotected void ReadContents () {//Read GIF file content Blocksboolean done = False;while (! ( Done | | Err ())) {int code = read (); switch (code) {case 0x2C://Image Separatorreadimage (); Break;case 0x21://Extensioncode = Rea D (); switch (code) {case 0XF9://Graphics control Extensionreadgraphiccontrolext (); Break;case 0xFF://Application Extens Ionreadblock (); 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 Extensionskip ();} Break;case 0x3b://Terminatordone = TRUe;break;case 0x00://Bad Byte, but keep going and see what happensbreak;default:status = Status_format_error;}}} protected void Readgraphiccontrolext () {read ();//block Sizeint packed = read ();//Packed Fieldsdispose = (Packed & 0x1c) >> 2;  Disposal Methodif (Dispose = = 0) {dispose = 1;//elect to keep old image if Discretionary}transparency = (Packed & 1)! = 0;delay = Readshort () * 10; Delay in Millisecondstransindex = Read (); Transparent color indexread (); Block terminator}//to get stream-headprotected void Readheader () {StringBuffer id = new StringBuffer (); for (int i = 0; I < 6; i++) {id.append (char) read ());} if (!id.tostring (). StartsWith ("GIF")) {status = Status_format_error;return;} READLSD (); if (Gctflag &&!err ()) {GCT = readcolortable (gctsize); bgColor = Gct[bgindex];}} protected void Readimage () {//offset of Xix = Readshort ();//(sub) image position & size//offset of yiy = Readshort ( );//width of bitmapiw = Readshort ();//Height OF bitmapih = Readshort ();//Local Color Table Flagint packed = read (); Lctflag = (Packed & 0x80)! = 0; 1-local Color Table flag//interlace flag, to array with interwoven if ENABLE, with order//otherwiseinterlace = (PAC Ked & 0x40)! = 0; 2-interlace flag//3-sort flag//4-5-reservedlctsize = 2 << (packed & 7); 6-8-Local color table Sizeif (lctflag) {LCT = readcolortable (lctsize);//Read tableact = LCT;//make local table AC tive} else {act = GCT;//Make Global table activeif (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 dataskip (); if (err ()) {return;} framecount++;//Create new image to receive frame Dataimage = bitmap.createbitmap (width, height, config.argb_4444);//Crea Teimage (width, height); setPixels (); Transfer Pixel data to Imageframes.addelement (new Gifframe (image, delay)); Add image to frame//listif (transparency) {Act[transindex] = save;} Resetframe ();} Logical screen descriptorprotected void Readlsd () {//Logical-screen sizewidth = Readshort (); height = Readshort ();//PA cked Fieldsint packed = read (); Gctflag = (Packed & 0x80)! = 0; 1:global Color Table flag//2-4: Color resolution//5:gct Sort flaggctsize = 2 << (packed & 7); 6-8: GCT sizebgindex = read (); Background color indexpixelaspect = Read (); Pixel aspect ratio}protected void Readnetscapeext () {do {readblock (); if (block[0] = = 1) {//Loop count Sub-blockint B1 = ((int) block[1]) & 0xff;int b2 = ((int) block[2]) & 0xff;loopcount = (b2 << 8) | B1;}} while ((BlockSize > 0) &&!err ());} Read 8 bit dataprotected int Readshort () {//Read 16-bit value, LSB firstreturn 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 ());} public void Recycle () {for (int i = 0; i < frames.size (); i++) {Frames.get (i). Image.recycle ();}} To store *.gif data, Bitmap & Delayprivate class Gifframe {//To access image & delay w/o Interfacepublic BITMA P image;public int delay;public gifframe (Bitmap im, int del) {image = Im;delay = del;}}}

  

Control code:

Package Com.android.view;import Android.content.context;import Android.content.res.typedarray;import Android.graphics.drawable.animationdrawable;import Android.graphics.drawable.bitmapdrawable;import Android.util.attributeset;import Android.view.view;import Com.gifdemo.r;public class GifView extends View {private Gifhelper ghelper;private animationdrawable animdrawable;public Gifview (context context, AttributeSet Attrs) {super ( context, attrs);//TODO auto-generated constructor stubghelper = new Gifhelper (); TypedArray ta = context.obtainstyledattributes (attrs,r.styleable.gifview); animdrawable = new animationdrawable (); int ResID = Ta.getresourceid (r.styleable.gifview_src,-1); Ghelper.read (Getresources (). Openrawresource (ResID)); for (int i = 0; I < Ghelper.getframecount (); i++) {int delay = Ghelper.getdelay (i), if (i = = 0) animdrawable.addframe (new bitmapdrawable (Ghelper.getframe (i)), delay); Elseanimdrawable.addframe (New Bitmapdrawable (Ghelper.nextbitmap ()), delay);} Animdrawable.setbounds (0, 0, Ghelper.getimage (). GetWidth (), Ghelper.getimage (). GetHeight ()); setbackgrounddrawable (animdrawable); Ta.recycle (); Animdrawable.setoneshot (false); Animdrawable.start ();} public void Recycle () {ghelper.recycle ();}}

  

Attrs.xml Source:

<?xml version= "1.0" encoding= "Utf-8"?><resources> <declare-styleable    name= "Gifview" >        <attr name= "src" format= "integer"/>    </declare-styleable></resources>

  

Android for GIF playback (decoding)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.