Android 使用GIFLIB 来加载gif 的流程

1,120 阅读3分钟

     1  首先去官网查找资料: giflib.sourceforge.net   2019年6月25日后面没有更新了,

  • SourceForge project page     源码入口。  源码不是很多,有12个文件,可以直接拷贝到项目里面 main/cpp/giflib.
  • Gif 是什么, 是 GIF89a specification. 属于W3C的标准格式。里面有介绍一个Gif 文件包含的数据,gif 文件格式,看的也不是太懂。
  • LZW ImageData , 串表压缩算法, 意思用较短的代码表示较长的字符串压缩,有点像哈夫曼算法。主要有三个对象: charStream   codeStream  StringTable   数据流 编码流 编译表   原理  提取原始文本文件数据中的不同字符,基于这些字符创建一个编译表,用编译表中的字符的索引来替代原始文本文件数据的响应字符,减少原始数据的大小。

    2  使用GifLib 实现对一张gif 图片解码,并且展示出来的思路。

       第一   java 层的实现, 使用drawable 的 scheduleSelf(Runnable,TimeUpdate) 的方法,在特定时间 执行 Runnable  run 方法, run 方法里面 执行 invalidateSelf() 方法,进而执行 draw() 方法通过 canvas。drawBitmap(bitmap,srcRect,getBounds(),mPaint) 来进行绘制。进而又执行scheduleSelf(Runnable,TimeUpdate) 执行 线程里面的方法。继承drawable 包里面的,Animatable  是为了调用里面的start  stop   isRunning 方法 来 控制方法的执行。TimeUpdate 是执行线程里面方法的绝对时间,一般都是当前时间加上当前帧的显示时间

     第二  Java 层实现,使用jni 调用C++ 的类。 GifFrame 类,通过调用native 方法来调用C++ 里面的方法。主要的局部变量有 nativeHandler (C++ 中具体解码图片类的指针地址),with,height,count。 定义了 nativeDecodeStreamJNI(AssetManager,Path) ,nativeGetFrame(nativeHandle,bitmap,frameIndex). 主要是这两个方法。

   第三  Jni层的处理 。 

           在加载动态库 的时候 JNI 会调用 JNI_OnLoad 方法,在这里可以做一些初始化的操作,通过注册 env->findClass() 获取class, env->RegisterNatives() 来注册方法,通过这种方式可以达到预加载,方法方法复用,方法映射的目的???。 其中 JNINativeMethod 的构成,是由           (native方法调用的字符串, 传入的所有参数+返回参数的签名, 调用的本方法名)    在 JNI_OnUnload 的方法中 执行 env->UnregisterNatives(cl) 的方法反注册。

        nativeDecodeStreamJNI映射到方法  decode_jni 方法。 主要初始化 C++ 的GifFrame,并且把C++ 的GifFrame 转换成nativeHandler ,作为一个参数来构建 Java层GifFrame 的一个参数。 C++ 的GifFrame 初始化, 主要是 打开Asset或者外部存储的Gif图片,把图片信息 和每一张图片的时间信息 封装到GifType 里面,后续的基本信息都是从GifType 里面获取。

       nativeGetFrame(nativeHandle,bitmap,frameIndex) , 解析每一帧的数据,并且把数据存储在 bitmap 里面。 natvieHandler 指针 可以强转为 C++的GifFrame . 调用C++ 的GifFrame 的方法来进行数据的处理。 这个步骤比较复杂。大概如下

      1 借助于AndroidBitmap  luck 一个缓冲像素区 piexes

      2  借助SaveImage  ----> GifImageDesc(记录了所有的像素点,宽高 的像素点)   ColorMapObject     把所有的像素 存到 pixes 也就是间接的更新了Bitmap. 

    3  去掉透明的值,达到 减少图片占用内存的目的。