MTK图片解码流程及png图片详解

从事MTK平台的工作者很多,做高仿机的人也很多,MTK的界面变得越来越花哨,但是对于MTK平台实现进行研究的文章并不多,希望这篇文章和以后的几篇BLOG能为MTK的初学者带来一些帮助。

      怎么使用MTK的函数显示图片相信大家都会,但是图片的解码过程就不是人人都去研究了,由于我们做JVM移植层的需要,最近对MTK的图形解码进行了一些研究。

      MTK在绘制图形的时候使用的是gdi_image_codec_draw这个函数,在这个函数中,MTK会根据img_type这个参数从gdi_image_codecs这个全局数据结构数组中取得相应绘制回调函数。gdi_image_codecs全局变量在gdi_image.c文件中定义。

      (1)BMP解析过程

      当img_type为GDI_IMAGE_TYPE_BMP_FILE_OFFSET的时候,MTK会调用gdi_image_bmp_draw_handler作为BMP文件解析的处理函数。在这个函数中,MTK会根据程序员指定的显示大小对bmp文件进行放大或者缩小,由于这里我们只是简单研究一下,就不以图片的放大或者缩小为例子了,如果要研究图片的放大或者缩小,请各位自己研究。我们只研究不对bmp进行放大或者缩小的过程——gdi_image_bmp_draw_file函数。

      gdi_image_bmp_draw_file这个函数在gdi_image_bmp.c文件中。这个函数一开始首先建立了一个比特流,在我看来就是把这个BMP文件打开,并把BMP的文件的数据放到gdi_bytestream_buffer这个全局数组中,为以后的解码做准备。接下来大家可能就要迷糊了,MTK使用的是gdi_image_bmp_draw_internal_from_file这样一个函数,这个函数是什么呢!说出来下一条,这个函数是个宏!确切的说这个曾经是函数调用的语句实际上被GDI_IMAGE_BMP_DRAW_INTERNAL这个宏所替代,而这个宏在gdi_image_bmp_codec.h中有一个同名函数,这样gdi_image_bmp_draw_internal_from_file就被指示成了GDI_IMAGE_BMP_DRAW_INTERNAL。我第一次就晕菜了,搞不懂为什么MTK要费这么大劲,绕这么多弯。

      GDI_IMAGE_BMP_DRAW_INTERNAL就是解码过程,我们可以看到这里面有1,4,8,16,24,32位BMP的解码函数,如果我们解码的不是这些标准的BMP呢!对不起,MTK会重启!

      (2)静态GIF图片的解码过程

      当img_type为GDI_IMAGE_TYPE_GIF_FILE_OFFSET的时候,MTK会调用gdi_image_gif_draw_handler函数进行解码。在这个函数中同样分为可变大小和不可变大小,数据来源于文件还是来源与内存资源,这4种情况,我们还是只讨论数据来源于文件而且不进行缩放操作的情况——gdi_image_gif_draw_file。

      gdi_image_gif_draw_file这个函数有两个分支。在整个函数的实现中,会有一个do{}while(0)的循环,在定义了硬件解码宏之后,在硬件解码结束以后使用一个break;语句跳出循环。软解码的代码在硬解码的代码后面,没有宏控制。当硬解码宏打开后,完全靠硬解码结束后的break来区分软硬解码。这样,如果硬解码出现问题,可能会造成严重的后果。我不清楚MTK为什么这样做,可能是他们认为硬解码的所有返回都已经处理过了,所以才使用这种方式的吧!

      在6226,6228等高端的MTKCPU上,图像都是硬解码的。在这些CPU内部有一组专门的解码电路来对图形进行解码。在硬解码的时候,MTK最终会调用gif_decode_hw这个函数对CPU内部的寄存器进行相关的设置,最后调用GIF_START这个宏函数开始对GIF图形进行解码。

      在6225以下的CPU中,所有的图像都是软解码的,这时MTK使用了ret = gdi_image_gif_draw_file_decoders[gdi_act_layer->cf] 这个语句。gdi_image_gif_draw_file_decoders是一个函数指针数组。这个数组定义在gdi_image_gif.c中,这个数组中的元素(例如gdi_image_gif_draw_internal_from_file_8等)其实都指向GDI_IMAGE_GIF_DRAW_INTERNAL这个宏,这个宏又在Gdi_image_gif_codec.h中对应一个同名函数。好像在哪里见过哈!对!BMP就是这样指来指去的。MTK的风格就是这样奇怪而统一。

      GDI_IMAGE_GIF_DRAW_INTERNAL就是GIF的解码过程。 一开始,MTK向我们展示了一个catch机制,MTK把最后的2张GIF图片保存在一个gdi_gif_cache的数据结构中,首先检查程序员需要的是不是这两张图片。如果是就不用解析了,不是就要重新解析。解析的算法我们就不讨论了,喜欢研究的可以看看GDI_IMAGE_GIF_CODEC这个函数的实现,GIF由于有动画的设定,所以解析起来要比BMP复杂多了!

      (3)JPEG图片解码过程

      当img_type为GDI_IMAGE_TYPE_JPG_FILE_OFFSET的时候,MTK会调用gdi_image_jpeg_draw_handler函数进行解码。这个函数最终会调用gdi_image_hwjpeg_draw_internal。MTK把JPEG的软解码和硬解码的接口在这个函数层次统一了起来,gdi_image_hwjpeg_draw_internal会调用gdi_image_hwjpeg_start_decode,gdi_image_hwjpeg_start_decode再调用jpeg_decode_process函数。jpeg_decode_process函数再负责调用JPEG解码核心对JPEG图片进行解码。最后的解码函数为decode_jpeg_file这个函数。无论是软解码还是硬解码都要调用decode_jpeg_file这个函数。在JPEG图形解码这部分,MTK做的还是比较符合中国工程师习惯的。

      还有一点,如果我们只想取得JPEG图像的数据,那么我们只要调用gdi_image_jpeg_draw_file_to_buffer或者gdi_image_jpeg_draw_to_buffer这两个函数好了。我们测试过,MTK对这两个函数的封装,封装的比较好。这样就给了我们一个通过JPEG图像传递某种信息的渠道。哦!搞的想干坏事一样,不说了,不说了!

       (4)PNG图片解码过程

        当img_type为GDI_IMAGE_TYPE_PNG_FILE_OFFSET的时候,MTK会对PNG进行解码,经过了上面的分析,我相信大家都能对MTK的图形解码的流程有了比较深刻的理解了,各位可以自己分析这个过程,我这边就不赘述了!

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kok202/archive/2010/03/13/5377534.aspx

--------------------------------------------------------------------------------

顺便提一下常用资源中的PNG和PBM文件,PNG图片有许多优点,最突出的优点的是能够设计更漂亮的UI,但一个最明显的缺点却是需要的空间比较大,PNG在使用时,MTK默认会把其转化为一种BMPA的文件,全部使用PNG设计手机,最终是以牺牲空间为代价的,对于一个靠SP来打价格战的方案公司来说,是一个两难的选择。而且PNG在使用过程中也会遇到一些问题,这一点可以参考我以前的文章。PBM其实是BMP改了扩展名后得来的,是MTK推荐的文件类型,而MTK默认会把一些经常调用的BMP图片直接转为PBM,虽然在文件上看来他还是BMP,但在编译时MTK会修改生成的数组BUFFER,使其变为PBM,比如SI_ALARM.bmp,在文件夹里看时是SI_ALARM.bmp,到custimgdatahw.h看时,发现他被默认的改成了PBM格式。这可以从图片数组__MAINLCD__IDLESCREEN__STATUSICONS__SI_ALARM_BMP里的元素中看到,该BUFFER第一个元素说明的是文件的类型,BMP文件类型是1,PBM类型为28,各种文件类型的对应的值都在文件gdi_const.h中定义。虽然他本质上PBM和BMP没有什么不同,但在显示时,速度上却比BMP快上了许多,由于MTK对PBM的特殊处理,使其在使用时省掉了对BMP解析时间,可以直接拷贝到LCD的BUFFER中显示。想研究详细转化过程的朋友可以研究一下bmploader.c文件。

对文件custimgdatahw.h的研究,可以使我们更深入的了解MTK的图片资源的使用过程,以助于我们解决各种各样的问题。同时也可以自己写程序把图片转为数组BUFFER,减轻我们在编绎资源时漫长的等待过程,这在程序调试阶段是十分有用的。而节约时间和当前许多公司低成本快速出货的理念也是符合的

--------------------------------------------------------------------------------

自从接触MTK以来,发现很多图片都是采用png格式的,一开始很迷惑,后来发现png图片具有自身的一些优点:

1.png图片的背景可以透明;

2.png格式可以作出无锯齿的圆角类型的图片;

3.png图片的体积相较于BMP的小.

  可能是基于以上原因吧,使得很多的UI工程师更愿意做png格式的图片.可是,对于一个MTK的开发人员来说,png图片自身也存在一些问题:首先是在MTK平台上,png会被转化为一种BMPA的中间格式,该格式并不比同样效果的BMP小,有时还会大上许多,这对存储空间相对有限的项目来说,不是什么好事情.其次是在两个png图片叠加显示的时候会出现透到底图和出现蓝边的问题,而具有透明效果的BMP图片就不会出现这种问题.

  对于PNG图片占空间较大的问题,我们是没什么办法解决了.而对于PNG图片显示时会透到底图和出现蓝边的问题,我们还是有办法解决的:

  首先PNG图片实现透明的原理是这样的:PNG图片可以定义alpha通道,有了alpha通道,可以定义每个像素点的透明度,能做出很炫的图片效果来。当前MTK平台的PNG解码器用的是一个开源的PNG解码器:libpng,但是mtk对libpng进行了封装,在解码的时候需要传入blending层,mtk解码的时候,会跟据图片的alpha通道值,自动把解码出来的像素的和blending层的像素进去混合叠加,然后把混合叠加后的效果输出。gdi_push_and_set_alpha_blending_source_layer()是设置blending层,也就是png解码时用来当作背景的层。

  明白了这些,解决问题的方法就出来了:

...

gdi_handle active_layer;

...

gdi_layer_get_active(&active_layer);//获取当前的激活层

gdi_push_and_set_alpha_blending_source_layer(active_layer);//设置当前激活层为blending层

gdi_image_draw_id(x, y, IMG_IDLE_TIME_BG); //绘制png图片(也就是出问题的图片)

gdi_pop_and_restore_alpha_blending_source_layer();    //恢复原来的blending层

 

...

--------------------------------------------------------------------------------

各种格式的图片解码速度比较?PNG,JPG,BMP,GIF,...

hjq0904 Post at 2010-10-9 14:22:54
BMP>jpg(gif)>png
-----------
oosky Post at 2010-10-11 23:40:38
mtk上,
bmp->gif->png-jpg.
本文来自:我爱研发网(52RD.com) - R&D大本营
详细出处:http://www.52rd.com/bbs/Archive_Thread.asp?SID=192900&TID=3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值