//获取一个标准的Gif解码器,用于读取Gif帧并且将其绘制为Bitmap,供外界使用
return new StandardGifDecoder(provider, header, data, sampleSize);
}
}
小小的总结一下:
- 首先通过ByteBufferDecoder提取Gif的头部信息
- 根据Gif的头部信息获取其背景颜色,好设置Bitmap的Config选项
- 依然还是根据头信息计算出采样率
- 获取GIF的解码器StandardGifDecoder用于构建GIF帧输出为Bitmap供外界使用
- 构建GifDrawable(用于播放Gif动画)
- 构建GifDrawableResource(用于管理GifDrawable)
2)其次看Gif图像帧获取以及如何将图像帧注入到Bitmap中
下面来看看Gif图像帧是如何被解码到Bitmap中的,请看StandardGifDecoder
public class StandardGifDecoder implements GifDecoder {
private static final String TAG = StandardGifDecoder.class.getSimpleName();
//…
// 由ByteBufferGifDecoder的decode方法可知,通过StandardGifDecoder获取Gif的下一帧数据,用于转换为Bitmap.
@Nullable
@Override
public synchronized Bitmap getNextFrame() {
//…
// 根据Gif的头信息获取GIF当前帧的帧数据
GifFrame currentFrame = header.frames.get(framePointer);
GifFrame previousFrame = null;
int previousIndex = framePointer - 1;
if (previousIndex >= 0) {
previousFrame = header.frames.get(previousIndex);
}
// Set the appropriate color table.
// 设置色表:用于设置像素透明度 lct == local color table ; gct == global color table;这里告诉我们的就是先局部后全局
act = currentFrame.lct != null ? currentFrame.lct : header.gct;
if (act == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, “No valid color table found for frame #” + framePointer);
}
// No color table defined.
status = STATUS_FORMAT_ERROR;
return null;
}
// Reset the transparent pixel in the color table
// 重置色表中的像素的透明度
if (currentFrame.transparency) {
// Prepare local copy of color table (“pct = act”), see #1068
System.arraycopy(act, 0, pct, 0, act.length);
// Forget about act reference from shared header object, use copied version
act = pct;
// Set transparent color if specified.
// 这里默认为黑色透明度
act[currentFrame.transIndex] = COLOR_TRANSPARENT_BLACK;
}
// Transfer pixel data to image.
// 将像素数据转换为图像
return setPixels(currentFrame, previousFrame);
}
//…
private Bitmap setPixels(GifFrame currentFrame, GifFrame previousFrame) {
// Final location of blended pixels.
// 存储上一帧的Bitmap像素数据
final int[] dest = mainScratch;
// clear all pixels when meet first frame and drop prev image from last loop
if (previousFrame == null) {
if (previousImage != null) {
// 回收上一帧的Bitmap
bitmapProvider.release(previousImage);
}
previousImage = null;
// 并且将Bitmap的像素填充黑色
Arrays.fill(dest, COLOR_TRANSPARENT_BLACK);
}
if (previousFrame != null && previousFrame.dispose == DISPOSAL_PREVIOUS
&& previousImage == null) {
//上一帧数据为被废弃了,清空
Arrays.fill(dest, COLOR_TRANSPARENT_BLACK);
}
// fill in starting image contents based on last image’s dispose code
//1. 将上一帧的 数据注入到dest数组中
if (previousFrame != null && previousFrame.dispose > DISPOSAL_UNSPECIFIED) {
if (previousFrame.dispose == DISPOSAL_BACKGR