gifdecoder.java_GIFDecoder源码分析

run()

public void run(){

if(in != null){

readStream();

}else if(gifData != null){

readByte();

}

}

private int readByte(){

in = new ByteArrayInputStream(gifData);

gifData = null;

return readStream();

}

GifDecoder的入口是run函数,里面包含了readStream()和readByte()两个方法,但是readByte()里也返回了一个readStream(),所以从readStream()方法进行分析。

readStream

private int readStream(){

init();

if(in != null){

readHeader();

if(!err()){

readContents();

if(frameCount < 0){

status = STATUS_FORMAT_ERROR;

action.parseOk(false,-1);

}else{

status = STATUS_FINISH;

action.parseOk(true,-1);

}

}

try {

in.close();

} catch (Exception e) {

e.printStackTrace();

}

}else {

status = STATUS_OPEN_ERROR;

action.parseOk(false,-1);

}

return status;

}

readStream()里先进行一些参数的初始化,然后读取Gif头文件。

private void readHeader() {

String id = "";

for (int i = 0; i < 6; i++) {

id += (char) read();

}

if (!id.startsWith("GIF")) {

status = STATUS_FORMAT_ERROR;

return;

}

readLSD();

if (gctFlag && !err()) {

gct = readColorTable(gctSize);

bgColor = gct[bgIndex];

}

}

private 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

}

private 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;

}

readHeader()里主要是判断是否是Gif文件,如果是的话,则在readLSD()里获得Gif的一些基本信息。readLSD()读取的信息包括长宽,颜色和颜色索引等。之后通过readColorTable(int ncolors)读取颜色表单。之后就是通过readContents()来获取Gif的内容了。

readContents()

private 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;

}

}

}

在readContents()里,只要没有发生错误,就会一直读取下去,直到读取完成。这里面的readImage()方法是用来获取图片信息的。通过decodeImageData()方法来获取各个像素点的数据,之后新建一个bitmap,通过setPixels()来设置像素点的信息。然后根据此bitmap生成一个GifFrame的对象,并通过action.parseOk(true, frameCount)返回解析成功以及解析成功的帧数。全部解析完成后,帧数为-1。

private void readImage() {

ix = readShort(); // (sub)image position & size

iy = readShort();

iw = readShort();

ih = readShort();

int packed = read();

lctFlag = (packed & 0x80) != 0; // 1 - local color table flag

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, Bitmap.Config.ARGB_4444);

// createImage(width, height);

setPixels(); // transfer pixel data to image

if (gifFrame == null) {

gifFrame = new GifFrame(image, delay);

currentFrame = gifFrame;

} else {

GifFrame f = gifFrame;

while(f.nextFrame != null){

f = f.nextFrame;

}

f.nextFrame = new GifFrame(image, delay);

}

// frames.addElement(new GifFrame(image, delay)); // add image to frame

// list

if (transparency) {

act[transIndex] = save;

}

resetFrame();

action.parseOk(true, frameCount);

}

readContents()里还有读取其他信息的函数,比如readGraphicControlExt(),readBlock()和readNetscapeExt()。这些都是获取一些信息用的函数。

使用方法

GIFDecoder里有很多方法,可以获取Gif的信息。先构造一个GifDecoder,然后调用gifDecoder.run()方法,就可以得到一个完整的GIFDecoder对象,之后便能通过GIFDecoder里的各种方法去获得Gif图片的信息了。

//解析gif图片

gifDecoder = new GifDecoder(fileInputStream, new GifAction() {

@Override

public void parseOk(boolean parseStatus, int frameIndex) {

Logger.d(parseStatus + " " + frameIndex);

}

});

gifDecoder.run();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值