孔祥焰 羅桂娥
摘 要:JPEG 2000是新一代的靜態(tài)圖像壓縮標準,而Kakadu是JPEG 2000官方建議的實現(xiàn)代碼之一,也是目前效率最高的JPEG 2000開源代碼,然而Kakadu代碼的復(fù)雜性和移植高難度性制約了JPEG 2000代碼的實現(xiàn)。為了實現(xiàn)Kakadu代碼在不同平臺的移植,針對Kakadu代碼結(jié)構(gòu)的高復(fù)雜性,在分析Kakadu系統(tǒng)結(jié)構(gòu)以及參考程序參數(shù)的基礎(chǔ)上,以Kakadu標準的編碼工程Kducompress對代碼的具體結(jié)構(gòu)進行剖析,闡明了代碼運行效率高的原因。最后以KakaduV2.2.3移植到TI TMS320DM642為例,對代碼進行移植性分析及實現(xiàn),對可能需要的修改給出了方向,為代碼在不同平臺的實現(xiàn)進行了有益的探索。
關(guān)鍵詞:JPEG 2000;Kakadu;代碼分析;DM642
中圖分類號:TP31111文獻標識碼:A
文章編號:1004-373X(2009)12-064-04
Analysis of Kakadu′s Structure and Portability Based on JPEG 2000
KONG Xiangyan,LUO Gui′e
(School of Information Science and Engineering,Central South University,Changsha,410083,China)
Abstract:JPEG 2000 is the next generation of static image compression standard.Kakadu is one of the JPEG 2000 implemental codes of which the official proposed,and is also the most efficient codes around the world.However the difficulty and complexity of Kakadu′s portability restricts code′s realization of JPE2000.In order to implement Kakadu′s portability on different platforms,aiming at the highly complexity of JPEG 2000 and its implemental codes-Kakadu,and a detailed analysis is given on Kakadu′s architecture,referential appreciation′s parameter and the code′s specific structure based on the standard coding project-Kducompress.An analysis on the reason why it has high efficiency is proposed.In the end,an analysis on portability and implementation of KakaduV2.2.3,so as to give an beneficial research on different platforms.All the analysis and implementation of portability based on TI TMS320DM642.
Keywords:JPEG 2000;Kakadu;code analysis;DM642
0 引 言
JPEG 2000與傳統(tǒng)的JPEG標準有很大的不同[1],由于其卓越的圖像壓縮性能和很高的靈活性,在各個領(lǐng)域有著廣闊的應(yīng)用前景[2,3]。JPEG 2000的這些特性主要來源于小波變換[4]、比特平面編碼和算術(shù)編碼技術(shù)。由于這些技術(shù)的引入,JPEG 2000的算法復(fù)雜度也相應(yīng)提高,且在一定程度上限制了JPEG 2000的應(yīng)用[5]。
Kakadu作為JPEG 2000開源代碼的“開山鼻祖”,其作者David Taubman正是JPEG 2000核心編碼EBCOT[6]的發(fā)明者。由此可見,Kakadu在JPEG 2000實現(xiàn)代碼中的地位。但由于Kakadu是使用標準C++ 編寫的程序,并加入一些JPEG 2000標準所沒有的特性,因此其代碼復(fù)雜性非常高[7],而且標準C++并不像C語言那樣受到各嵌入式系統(tǒng)的廣泛支持。以上種種原因表明,Kakadu代碼的入門和移植都非常困難。因此對Kakadu代碼和移植性的分析就顯得非常必要。
1 JPEG 2000標準的概述
JPEG 2000即ISO/ITU15444,是由國際標準化組織ISO和國際電信標準化聯(lián)盟ITU-T于2000年底聯(lián)合頒布的新一代圖像壓縮國際標準。JPEG 2000的編、解碼流程[8]如圖1所示。
圖1 JPEG 2000的編、解碼流程
在JPEG 2000編碼中,圖像的預(yù)處理為顏色空間的轉(zhuǎn)換和對圖像分切片的處理。小波變換采用的小波基在JPEG 2000標準中統(tǒng)一為Le Gall 5/3小波和Daubechies 9/7小波。JPEG 2000的量化與JPEG的量化過程基本一致。熵編碼是整個JPEG 2000編碼過程的核心,在JPEG 2000中采用David Taubman教授的EBCOT算法。JPEG 2000的解碼過程僅是編碼過程的逆過程而已。
2 Kakadu的系統(tǒng)結(jié)構(gòu)
這里所用Kakadu版本為KakaduV2.2.3。Kakadu核心代碼由3個子系統(tǒng)組成:編碼參數(shù)子系統(tǒng)、壓縮數(shù)據(jù)和結(jié)構(gòu)子系統(tǒng)、處理引擎子系統(tǒng)[9]。Kakadu系統(tǒng)結(jié)構(gòu)如圖2所示。
其中,編碼參數(shù)子系統(tǒng)處理用于編解碼時需要的各種參數(shù)。應(yīng)用程序把編解碼參數(shù)傳送到壓縮數(shù)據(jù)和結(jié)構(gòu)子系統(tǒng),形成切片、分量切片、分辨率、編碼塊等JPEG 2000的數(shù)據(jù)塊,再傳送到處理引擎子系統(tǒng)。處理引擎子系統(tǒng)處理完輸入數(shù)據(jù)后,可選擇把數(shù)據(jù)流保存在內(nèi)存中或者把輸出保存到文件里。
圖2 Kakadu系統(tǒng)結(jié)構(gòu)圖
如圖2所示,這3個子系統(tǒng)的通信是通過一系列的類完成的,如kduparams,kducodestream,kdutile等。在Kakadu里,這些相互通信的類都是接口類,即它僅是3個子系統(tǒng)內(nèi)部對象的接口。因此,這些接口類并沒有標準的析構(gòu)函數(shù)——銷毀接口對于內(nèi)部對象沒有任何意義。這種處理方式可以使開發(fā)人員隨意調(diào)用這些接口類對象,而又不會使內(nèi)部數(shù)據(jù)結(jié)構(gòu)受到破壞性影響,有利于整個編解碼系統(tǒng)的穩(wěn)定性。
3 Kakadu代碼分析
下面以Kakadu標準的編碼工程Kducompress來對Kakadu代碼進行剖析。
3.1 數(shù)據(jù)的讀入和存放
(1) 在棧(Stack)內(nèi)建立存放警告和錯誤信息的緩存空間,并定義當(dāng)警告和錯誤發(fā)生時,程序的回調(diào)函數(shù)。它是通過kducustomizewarnings和kducustomizeerrors這兩個函數(shù)來定義的。在默認情況下,當(dāng)警告發(fā)生時,程序會記錄警告信息并繼續(xù)運行;當(dāng)錯誤發(fā)生時,程序記錄錯誤信息并停止運行。
(2) 程序?qū)嵗粋€叫kduargs類的對象來保存命令行參數(shù),并通過kduargs的成員函數(shù)kduargs::getfirst,kduargs::find,kduargs::advance來分析該命令行參數(shù),以獲取輸入文件路徑、輸出文件路徑和一些基本的編解碼參數(shù)。這些基本參數(shù)包括質(zhì)量層數(shù)量、質(zhì)量層碼率及切片大小等。
(3) 程序?qū)⒗蒙厦娴玫降妮敵鑫募窂?實例化2個空的輸出文件類對象:kdusimplefiletarget和jp2target。然而,最后的代碼流將保存到哪個對象,取決于輸出文件設(shè)定為原始代碼流格式,還是標準的jp2格式文件。
(4) 程序繼續(xù)實例化kduimagein類的對象,并通過kduimagein對象的構(gòu)造函數(shù)kduimagein::kduimagein()把輸入文件保存在系統(tǒng)堆(heap)中,并通過kduimagein對象內(nèi)部私有的in指針返回原始數(shù)據(jù)地址。
(5) 系統(tǒng)在分析完命令行參數(shù)和讀取輸入文件的文件頭信息后,把這些編解碼參數(shù)放到sizparams的對象所連接的棧中。由于JPEG 2000的參數(shù)眾多,還有一些默認的參數(shù)沒有設(shè)定,此時程序需要調(diào)用sizparams:: finalize()完成整個編碼參數(shù)子系統(tǒng)的構(gòu)造。
3.2 數(shù)據(jù)的壓縮編碼
(1) 程序首先實例化kducodestream類的對象。kducodestream的對象是整個程序的核心對象。如前所述,kducodestream類是一個接口類,所有的壓縮編解碼和中間數(shù)據(jù)都由對象連接,而且由于kducodestream僅是接口類,在初始化時不能調(diào)用其對象的構(gòu)造函數(shù),此時程序必須調(diào)用成員函數(shù)kducodestream::create完成初始化工作。在初始化時,程序已經(jīng)把sizparams指向的數(shù)據(jù)自動保存到kducodestream指向的內(nèi)存中。因此,此時可以銷毀sizparams內(nèi)部對象,以節(jié)省內(nèi)存空間。
(2) 計算各質(zhì)量層輸出的字節(jié)數(shù)大小。程序根據(jù)給定的質(zhì)量層碼率rate[i](由命令行參數(shù)給定)、原始圖像每像素所占用的位數(shù)b及原始圖像的像素總數(shù)num進行計算。計算公式為:
byte[i]=rate[i]×num(b/64)
式中:i為質(zhì)量層的索引號。若沒有給定碼率,即在無損壓縮的情況下,質(zhì)量層的字節(jié)數(shù)為0。
(3) 判斷是否需要率預(yù)測。率預(yù)測并不是JPEG 2000中原有的功能,而是Kakadu中為了加速編解碼速度而引入的機制。這是個非常實用且強大的功能,其原理是把壓縮后率失真優(yōu)化算法(PCRD-opt)中丟棄數(shù)據(jù)流的操作提前到位平面編碼中進行,既降低了內(nèi)存,又加快了速度。只有當(dāng)率預(yù)測標記allowrateprediction和最高質(zhì)量層字節(jié)數(shù)byte[max]同時大于零時,程序才會調(diào)用kducodestream::setmaxbytes使能率預(yù)測。
(4) 對kducodestream對象進行預(yù)處理。預(yù)處理工作包含2個部分。首先,判斷圖像是否需要翻轉(zhuǎn)。翻轉(zhuǎn)因子包括transpose,vflip和hflip,它在上述命令行分析過程中獲得。程序通過調(diào)用kducodestream::changeappearance(transpose,vflip,hflip)來對圖像進行翻轉(zhuǎn)。若transpose,vflip,hflip均為零,圖像不翻轉(zhuǎn)。其次,根據(jù)命令行參數(shù)生成感興趣區(qū)域(roi)信息。它通過實例化類createroisource和kduroiimage的對象完成。注意,這兩步預(yù)處理工作僅是對坐標的表示方式做了改變。
(5) 創(chuàng)建數(shù)據(jù)處理引擎。它是通過實例化kdcflowcontrol類的對象和調(diào)用kdcflowcontrol的構(gòu)造函數(shù)實現(xiàn)的。程序在調(diào)用kdcflowcontrol::kdcflowcontrol()時會自動調(diào)用上述kducodestream對象的信息和保存在內(nèi)存中的原始圖像數(shù)據(jù)信息,以判斷小波變化的層數(shù)、位平面編碼的精度等,以及創(chuàng)建最小、最合適的處理引擎。由于處理引擎的數(shù)據(jù)量很大,因此程序必須用new操作符在系統(tǒng)堆里面創(chuàng)建。
(6) 數(shù)據(jù)編碼。由于圖像大多是彩色圖像,既包含了多個圖像分量,又包含了多切片。在進行數(shù)據(jù)編碼時,各個切片分量需要獨立進行。切片之間是相互獨立的,因此有多少個切片,就必須創(chuàng)建多少個處理引擎kduflowcontrol。在分量間切換時,必須調(diào)用各個處理引擎的成員函數(shù)kduflowcontrol::advancecomponents()。最后的數(shù)據(jù)處理是調(diào)用kduflowcontrol:: processcomponents()進行的。這個成員函數(shù)kduflowcontrol:: processcomponents()包括了數(shù)據(jù)的顏色空間轉(zhuǎn)換、小波變換、量化、位平面編碼、MQ,即JPEG 2000里面的tier1過程。由此可見,Kakadu把大部分的編碼操作都封裝起來,這對于從事實際產(chǎn)品開發(fā)的研發(fā)人員來說非常方便。
(7) tier2的操作。在上述的(6)中,應(yīng)用程序已經(jīng)把數(shù)據(jù)編碼成碼流,并保存到kducodestream對象所連接的內(nèi)部緩存中。tier2的過程是把這些碼流通過壓縮后率失真優(yōu)化算法截斷,形成最終的壓縮碼流。通過調(diào)用kducodestream::flush,使應(yīng)用程序?qū)崿F(xiàn)這個非常復(fù)雜的算法。對于工程人員來說,只需調(diào)用成員函數(shù)kducodestream::flush,而不用去理會其內(nèi)部機制。
(8) 最后應(yīng)用程序把代碼流輸出到文件中,并清理使用過的各種緩存、內(nèi)部對象。如前所述,在Kakadu里面提供給用戶的類都是接口類,即沒有給出明確的析構(gòu)函數(shù),因此需要調(diào)用kducodestream::destroy()來銷毀內(nèi)部對象。由于kducodestream對象在內(nèi)部連接到其他各級對象中,因此kducodestream::destroy()將銷毀所有在棧中建立的對象。但對于質(zhì)量層字節(jié)數(shù)等在堆中創(chuàng)建的數(shù)組或?qū)ο?必須通過delete[]刪除。
縱上分析,Kakadu應(yīng)用程序的壓縮編碼操作并不像其他編碼程序。它通過把數(shù)據(jù)順序地遞交到不用的子系統(tǒng)中進行編碼。Kakadu創(chuàng)造性地構(gòu)造了“處理引擎”,把數(shù)據(jù)壓縮到這個引擎。這個“處理引擎”是可以按需求裁剪的,因此可以最大限度地降低運行時內(nèi)存的使用率。然而Kakadu創(chuàng)造性的率預(yù)測機制,大大減少了編碼時間。
4 移植性分析
原始的Kakadu代碼是基于PC平臺的,而越來越多的應(yīng)用需要把代碼移植到嵌入式設(shè)備中。因此,這里以KakaduV 2.2.3移植到TI TMS320DM642為例,對代碼進行移植性分析。TMS320DM642是TI公司的第2代高性能超長指令字DSP,其自帶的編譯器支持標準C語言的全部特性,但并不支持C++的所有特性,如不支持異常處理(Exection Handling);不支持模板參數(shù);不支持標準的輸入輸出流對象(ostream和istream等)。但在Kakadu中,剛好大量使用了異常處理,如ostream和istream類。DM642編譯器支持的C++頭文件與VC編譯環(huán)境的頭文件也不一致,也需要用戶去手動修改。具體的修改如下:
在原工程的頭文件中,string.h,assert.h,stdio.h和math.h要分別用CSTRING,CASSERT,CSTDIO,CMATH來代替。但是,由于fstream,iostream這一類的C++頭文件中,istream、ostream已經(jīng)被改寫了,所以可以直接去掉。
在Kakadu中,對基本輸入/輸出流的使用主要在原始數(shù)據(jù)的讀入和錯誤、警告信息的輸出上。其中,對原始數(shù)據(jù)的讀入,使用了子函數(shù)ifstream::read。對于這一部分的ifstream對象,可用File類型的文件指針來改寫。而在讀入圖像數(shù)據(jù)操作時,則直接用std::fopen和std::fseek進行改寫。對于由ostream的對象所保存的錯誤、警告信息,最簡單的方法是把相關(guān)的ostream類代碼屏蔽,這雖然不影響程序的運行,但不利于調(diào)試。處理這個問題的最有效方法是使用TI公司實時操作系統(tǒng)DSP/BIOS[10]中的LOG模塊來帶代替ostream對象的相關(guān)成員函數(shù)。LOG模塊是基于實時操作系統(tǒng)的,運行起來更有效率。
對于C++標準的異常處理函數(shù),如try,catch,也可以使用屏蔽的方法處理,其前提是需要用戶仔細檢查代碼,確保程序在運行期間不發(fā)生任何意外。此外,最高效的方法是使用DSP/BIOS系統(tǒng)所帶的軟件中斷模塊。CCS里面使用軟件中斷非常方便,在C++代碼里面設(shè)置了中斷入口函數(shù),在DSP/BIOS設(shè)置工具中只需設(shè)置其中斷優(yōu)先級。
可見,盡管DM642的編碼器對C++的支持度不是很好(這也是目前嵌入式編譯器的通病),但只要按照具體的硬件對Kakadu做相應(yīng)修改,仍然能很好地將其移植到非PC平臺上。
5 結(jié) 語
目前,JPEG 2000因其獨特的優(yōu)勢受到了業(yè)界的關(guān)注。JPEG 2000在醫(yī)療圖像、網(wǎng)絡(luò)傳輸、保密性方面對JPEG有無可比擬的優(yōu)勢,幾乎可以確定會取代JPEG。由于獨立開發(fā)編解碼器所需人力、物力很大,開發(fā)周期也很長,大部分公司都選擇了代碼移植來縮短研發(fā)周期,降低成本。然而目前可選的JPEG 2000開源代碼不多,Kakadu幾乎是惟一的選擇。
現(xiàn)階段雖然對JPEG 2000的研究很多,但大多停留在理論水平,沒有涉及到真正的代碼實現(xiàn)。即使涉及到代碼實現(xiàn),也沒有涉及到最有效率的Kakadu代碼。給出Kakadu 標準C++代碼的分析流程和在DM642上的移植性分析,對希望從事Kakadu圖像處理平臺開發(fā)的研發(fā)人員有指導(dǎo)意義。
參考文獻
[1]Acharya T,Tsai P S.JPEG 2000 Standard for Image Compression: Concepts,Algorithms and VLSI Architectures[M].Wiley-Interscience,2004.
[2]焦曉,朱光喜,馬明罡.JPEG 2000的編碼技術(shù)[J].計算機仿真,2003,20(9):112-114.
[3]趙錦,邢長征.JPEG 2000的編碼原理及其優(yōu)缺點[J].遼寧工程技術(shù)大學(xué)學(xué)報,2004(23):192-193.
[4]Acharya T.A Survey on Lifting-based Discrete Wavelet Transform Architectures[J].Journal of VLSI Signal Processing Systems,2006,42(3):321-339.
[5]沈蘭蓀,卓力.小波編碼與網(wǎng)絡(luò)視頻傳輸[M].北京:科學(xué)出版社,2005.
[6]Taubman D.High Performance Scalable Image Compression with EBCOT[J].IEEE Trans.on Image Processing,2000,19(7):1 158-1 170.
[7]Hong M,Alen D,Faouzi K.Performance Analysis of the JPEG 2000 Image Coding Standard[J].Multimedia Tools and Applications,2005,26(1):27-57.
[8]Skodras A,Christopoulos C,Ebrahimi T.The JPEG 2000 Still Image Compression Standard[J].IEEE Signal Processing Magazine,2001,18(5):36-58.
[9]David Taubman.Kakadu Survey Documentation[Z].2001.
[10]李進.實時操作系統(tǒng)DSP/BIOS在DSP開發(fā)中的應(yīng)用[J].微電子技術(shù),2003(4):63-65.