MTK平臺圖片文件解析過程簡單分析

MTK平臺圖片文件解析過程簡單分析
      從事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的圖形解碼的流程有了比較深刻的理解了,各位可以自己分析這個過程,我這邊就不贅述了!

     

        以上我自己是對MTK圖形解碼過程的大致分析,有不當之處還希望大家能夠指正。

發佈了8 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章