跳轉到主要內容

圖像壓縮

從4.22版本開始,TouchGFX支援使用圖像壓縮。 從4.22版本到4.23版本的支援僅限於L8圖像壓縮。 從4.24版本開始支援壓縮RGB565、RGB888和ARGB8888圖像格式。

圖像壓縮是縮減圖像儲存需求的程序。 在專案中縮減圖像尺寸,如果能夠因此使用更小的Flash,就能降低成本。 縮減尺寸也能讓專案使用更多圖像,產生更豐富的UI。

圖像壓縮一般有兩種選擇:無損或有損。 有損圖像壓縮的運作原理是移除圖像的微小細節。 這通常可達到最大的縮減率,但無法完全確切重現原始圖像。 無損壓縮則一定可以重現原始圖像,沒有任何差異。 無損壓縮一般來說尺寸縮減率較低。

對圖形而言,通常會要求繪製的UI元素與當初設計時完全一樣。 因此TouchGFX僅支援無損壓縮。

圖像壓縮的優點在於縮小尺寸,但缺點則是圖像繪製到影像緩衝區時必須進行解壓縮。 相較於繪製未壓縮圖像,解壓縮在許多情況下會增加CPU工作量, 可能結果就是降低效能。

這代表我們必須將減少Flash所獲得的優點,與增加CPU用量的缺點進行比較。

請注意,許多STM32微控制器中的圖形加速器DMA2D及GPU2D (ChromART及NeoChrom GPU)無法直接繪製壓縮圖像。 壓縮圖像會使用軟體和硬體渲染結合的方式繪製,即壓縮資料是由軟體分區塊解壓縮,然後在適用情況下將這些區塊委派給DMA2D。

許多應用程式都不建議壓縮所有圖像,而是僅壓縮效能不會受損且減少Flash至關重要的圖像。 另請參閱下文中關於解壓縮至點陣圖快取的部分,以達成更低的儲存空間要求和出色的效能。

L8壓縮

如前所述,TouchGFX 4.22支援L8圖像壓縮。 回想一下,L8點陣圖格式僅適合用於最多256種色彩的圖像。 每個像素都只是8位元數字,在與圖像一同儲存的色表中用於代表色彩。 L8壓縮只是對像素數進行壓縮。 並沒有動到色表。

請參考以下圖像作為範例。 該圖像是計量應用程式中使用的背景。

L8-ARGB8888

圖像為184 x 184像素, 因此,像素資料的大小為184 x 184 = 33,856位元組。

如果我們對圖像進行壓縮,像素資料將減少到5,735位元組。 壓縮後的圖像資料(包括色表)的總大小不到原始圖像的20%。 因此,壓縮可讓我們在相同的快閃記憶體空間內擁有5個不同的背景,或將快閃記憶體需求減少28,121位元組。

壓縮L8圖像使用時就像是一般的未壓縮點陣圖。 例如您可使用圖像小工具顯示圖像,無需在TouchGFX Designer或程式碼中對專案進行任何修改。 這樣使用壓縮的L8圖像就非常方便。

3種演算法#{three-algorithms}

TouchGFX針對L8格式使用3種不同的壓縮演算法。 圖像轉換器會選擇提供最佳壓縮的演算法,除非使用者強制在設定中使用特定演算法。 使用的演算法如下:

  • L4:以4位元為單位編碼各個像素。 僅適用於最多16種色彩的圖像。
  • RLE:對像素進行長度編碼。 僅適用於最多64種色彩的圖像。
  • LZW9:採用字典型編碼。 適用於所有L8圖像。

RLE演算法的解壓縮速度比LZW9快很多,因此如果LZW9壓縮圖像的效果只稍微好一些,圖像轉換器就會選擇使用RLE。

RGB壓縮

如先前所述,TouchGFX 4.24開始支援對RGB565、RGB888及ARGB8888圖像格式進行圖像壓縮。 若圖像包含超過256種獨特顏色,即無法以精巧的L8圖像格式儲存,而必須採用上述格式之一儲存。 RGB565、RGB888或ARGB8888圖像壓縮是直接壓縮16、24或32位元的像素。

請參考以下圖像作為範例。 它的背景比上面的範例還要複雜和豐富,擁有超過256種獨特顏色。 因此,這張圖像不能以L8格式儲存,而必須以ARGB8888格式儲存,因為它有透明像素(在角落)。

ARGB8888

此圖像是240 x 240像素。 因此,像素資料的大小是240 x 240 x 4 = 230,400位元組,因為在ARGB8888圖像格式中,我們使用4位元組來儲存各像素。

壓縮後的圖像大小減少至32,347位元組。 壓縮後的圖像大小大幅減少,僅占原始圖像大小的14%。 壓縮可讓我們在相同的快閃記憶體空間中擁有多個複雜的背景,或是大幅減少對快閃記憶體的要求, 還能讓受到快閃記憶體限制的裝置採用比L8格式更複雜和豐富的圖形。

壓縮後的RGB圖像可像普通未壓縮的點陣圖一樣使用。 例如您可使用圖像小工具顯示圖像,無需在TouchGFX Designer或程式碼中對專案進行任何修改。 這樣使用壓縮的RGB圖像就非常方便。

Caution
在某些情況下,對RGB圖像套用抖動演算法都會影響RGB壓縮的效果。

2種演算法

TouchGFX使用2種些微不同的壓縮演算法,系統會根據要壓縮的圖像格式自動選擇這些演算法。 使用的演算法如下:

  • QOI,使用 Quite OK Image format壓縮演算法的變化體對RGB888和ARGB8888像素進行編碼。
  • QOI565,使用專為16位元像素值打造的QOI變化體對RGB565像素進行編碼。

RGB壓縮演算法的兩種變化體都針對快速解壓縮速度進行了最佳化,以限制渲染壓縮RGB圖像時的執行階段效能損失。

使用壓縮圖像

啟用圖像壓縮功能

圖像壓縮在目標應用中需要額外的程式碼。 為了避免占用較多空間,在部分平台上壓縮程式碼為選用項目。 您可能需要為您的專案啟用此功能。

按一下TouchGFX Designer左上角的「Config」,然後點擊「架構功能」

啟用圖像壓縮

圖像壓縮功能會顯示在底部。 您可以啟用所需的特定功能集。

目標擁有不同的架構功能選項,在部分情況下,目標沒有可選功能,如下所示:

沒有選用的架構功能

在此情況下,所有功能一律啟用。

Caution
請注意,如果使用未啟用的功能,TouchGFX Designer不會顯示錯誤或警告。 若使用圖像壓縮且該功能未啟用,則不會繪製圖像。

L8壓縮

壓縮圖像的使用方式就和一般圖像一樣。 您可在TouchGFX Designer設定小工具使用點陣圖,或是以程式碼指派點陣圖。

設定壓縮用於L8-ARGB8888圖像

唯一需要進行的設定,就是將Compression(壓縮)值設定為「Auto」(自動)。 接著圖像轉換器將自動選擇最適合的壓縮方法,如果圖像無法壓縮則會選擇不壓縮。

為小工具選擇壓縮圖像

現在我們可以和平常一樣為小工具選擇圖像。 其中與未壓縮圖像之間並沒有不同之處。

在程式碼之中使用圖像也沒有差別。 壓縮點陣圖和平常一樣是以其BitmapID進行參照:

    image1.setXY(148, 148);
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID));

在此進一步瞭解壓縮L8圖像

RGB壓縮

在TouchGFX Designer中壓縮RGB565、RGB888或ARGB8888圖像的過程與L8壓縮相同。

設定壓縮用於L8-ARGB8888圖像

若選擇「是」,TouchGFX Image Converter將會使用符合圖像格式的演算法來壓縮圖像。

與L8壓縮相同,我們可以像往常一樣選擇小工具的圖像,並在程式碼中引用點陣圖。

壓縮程度

圖像轉換器選擇的壓縮演算法,會寫在產生的檔案之中。 我們也可在其中找到壓縮程度。

我們在前面的L8壓縮範例中所使用的圖像是在檔案generated/images/src/image_gauge_background.cpp中所產生。 此檔案的標頭為:

image_gauge_background.cpp (extract)
// 4.22 D0 AN R0 FL8_ARGB8888 U888 N0 SExtFlashSection EExtFlashSection CL8_LZW9

LOCATION_PRAGMA("ExtFlashSection")
KEEP extern const unsigned char image_gauge_background[] LOCATION_ATTRIBUTE("ExtFlashSection") = {
// 184x184 L8_ARGB8888 pixels. Compression [output/input x 100]: 5735/33856 x 100 = 16.9%
0x00, 0x26, 0x50, 0xa8, 0x60, 0xe1, 0x02, 0x86, 0x0c, 0x1a, 0x36, 0x70,
....

第一行註釋結尾顯示壓縮演算法。 我們可以在此發現圖像轉換器已選取LZW9演算法。 第5行結尾顯示我們目前有5735位元組的像素資料,原始像素則為33856位元組, 產生16.9%的壓縮率(壓縮程度越小越好)。 注意! 壓縮百分比並沒有計入色表。

壓縮失敗

在部分情況下,TouchGFX Image Converter會在壓縮圖像時發出警告或錯誤。 如果圖像與所選的演算法不相容,或壓縮圖像的大小未低於原始圖像的90%,就會發生這種情況。 這只會在極少數的情況下發生。 例如,一張5 x 5的小圖像使用了25種不同的獨特顏色。 由於圖像中沒有重複或冗餘,因此壓縮時不可能減少資料。

L8圖像

以L8圖像來說,若選擇的特定演算法與給定的圖像不相符,就會發生這種情況。 例如,如果圖像中包含17種以上的顏色,並選擇使用L4壓縮,則圖像可能不會使用所選演算法進行壓縮。 TouchGFX Image Converter會在您產生程式碼時印出錯誤訊息,而TouchGFX Designer將會顯示錯誤訊息:

特定演算法的壓縮錯誤

這個問題的解決方法就是使用另一個演算法。 建議方法是針對L8圖像選擇「自動」。 然後,圖像轉換器將會嘗試所有演算法,並在最適用的選項中選擇最佳演算法。

在部分少數情況下,圖像不會壓縮到原始大小的90%以下。 在此情況下,TouchGFX Image Converter不會壓縮圖像,且會發出警告文字,如下所示:

壓縮警告

不壓縮的原因在於,節省快閃記憶體的大小不足以抵銷降低的渲染效能。 可以不使用「自動」,而是選擇任一種演算法(「L4」、「RLE」或「LZW」)來強制壓縮。

警告訊息僅供參考。 程式碼會繼續產生,專案也會如預期繼續運作。

RGB圖像

針對RGB圖像格式,您無法選擇「自動」,因為只有一種壓縮演算法。 如果您選擇「是」,則影像無法壓縮到原始大小的90%以下,TouchGFX Image Converter將會產生錯誤:

RGB圖像的壓縮錯誤

這裡的解決方法是對圖像的壓縮方式選擇「無」。

將圖像解壓縮至點陣圖快取

繪製的壓縮圖像在大部分情況下,效能都不如繪製的未壓縮圖像。 此外,如簡介所述,STM32微控制器(DMA2D及GPU2D)之中的圖形加速器無法直接繪製壓縮圖像。 因此壓縮圖像一定是由軟體和硬體組合繪製,導致效能較低,而且會增加CPU負載。

基於以上各種原因,TouchGFX也有功能可在執行階段將壓縮圖像解壓縮至RAM之中的點陣圖快取。

將圖像解壓縮至RAM可讓繪製效能類似於使用未壓縮圖像,而且可利用加速器繪製圖像。

為了能夠解壓縮,我們首先需要設定點陣圖快取。 請在此參閱使用點陣圖快取的更多資訊。

設定點陣圖快取後,我們可以使用Bitmap::decompress函數解壓縮圖像。 以下是完整的程式碼:

// Define an array for the bitmap cache
uint16_t cache[20*1024]; //40 KB cache
// Define an array for the decompression temporary buffer
uint16_t lzwBuffer[1024];

void TemplateView::setupScreen()
{
...
Bitmap::setCache(cache, sizeof(cache)); // 註冊點陣圖快取
bool r = Bitmap::decompress(BITMAP_GAUGE_BACKGROUND_ID, lzwBuffer); // 解壓縮點陣圖
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID)); // 將點陣圖做一般使用
image1.setXY(148, 148); // 圖像小工具位置
}

在此範例中,我們要將上述L8壓縮範例中的184 x 184圖像解壓縮到點陣圖快取。 點陣圖快取必須足以容納未壓縮圖像。 圖像是184 x 184像素,外加含有207 ARGB8888色彩的色表, 因此總大小為34,688位元組。

在此範例中,我們使用LZW9演算法。 解壓縮器在解壓縮LZW9壓縮圖像時(用於建構字典),會使用2048位元組的緩衝區。 解壓縮之後就不需要緩衝區,可重新用於其他用途。 解壓縮L4、RLE、QOI或QOI565壓縮圖像不需要使用緩衝區。

解壓縮圖像不再需要使用時,可利用Bitmap::cacheRemoveBitmap方法從點陣圖快取中移除。

限制演算法大小

如果將圖像解壓縮至點陣圖快取中,您有幾個選項可以限制演算法的大小。 如上所述,共有兩個圖像壓縮類型:L8和RGB。 使用 Bitmap::decompress時,您的程式將同時包含解壓縮L8和RGB圖像的程式碼。 如果只使用RGB圖像壓縮,可使用專門方法將RGB圖像解壓縮至點陣圖快取,即Bitmap::decompressRGB,這樣您的程式就僅會包含解壓縮RGB圖像所需的程式碼。 若只使用L8壓縮也同樣適用,方法是Bitmap::decompressL8。 請參閱以下範例。

void TemplateView::setupScreen()
{
...
// Decompress the bitmap (RGB using QOI)
bool r = Bitmap::decompressRGB(BITMAP_GAUGE_BACKGROUND_ID);
...
}
void TemplateView::setupScreen()
{
...
// Decompress the bitmap (L8 using RLE, no buffer required)
bool r = Bitmap::decompressL8(BITMAP_GAUGE_BACKGROUND_ID);
...
}

限制

使用壓縮圖像時有一些限制。 壓縮圖像不能與縮放或旋轉圖像的小工具、填滿區域的小工具或畫布小工具搭配使用。

壓縮圖像搭配使用不相容的小工具。

Caution
壓縮圖像無法搭配使用所有小工具。 Designer會顯示警告圖示。

前述限制是考量效能因素所訂定。 TouchGFX Designer不會讓您選擇壓縮圖像。

如果您要使用特定圖像搭配前述小工具,我們建議不要啟用圖像壓縮。 或者您可以在執行階段解壓縮圖像。

不支援壓縮圖像的小工具如下:

  • 紋理映射器
  • ScalableImage
  • 用於指標及弧線的Gauge
  • 用於填充繪圖下方區域的Static-及DynamicGraph
  • 用於時鐘指針的AnalogClock
  • Circle、Line及Shape
  • Circle-及LineProgress