跳轉到主要內容

圖像壓縮

從4.22版本開始,TouchGFX支援使用圖像壓縮。 The support from version 4.22 to 4.23 inclusive is limited to compression of L8 images. From version 4.24 compression of RGB565, RGB888, and ARGB8888 image formats is supported.

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

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

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

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

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

請注意,許多STM32微控制器中的圖形加速器DMA2D及GPU2D (ChromART及NeoChrom GPU)無法直接繪製壓縮圖像。 Compressed images are drawn using a mix of software and hardware rendering, i.e. the compressed data is decompressed in chunks by software and these chunks are then delegated to the DMA2D where applicable.

許多應用程式都不建議壓縮所有圖像,而是僅壓縮效能不會受損且減少Flash至關重要的圖像。 See also the section below about decompression to the Bitmap cache as a mean to get both lower storage requirement and good performance.

L8壓縮

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

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

L8-ARGB8888

圖像為184 x 184像素, The size of the pixel data is thus 184 x 184 = 33,856 bytes.

If we compress the image the pixel data is reduced to 5,735 bytes. The total size of the compressed image data, including the color table, is less than 20% of the original image. Compression thus allows us to have 5 different backgrounds in the same flash space, or to reduce the flash requirements by 28,121 bytes.

壓縮L8圖像使用時就像是一般的未壓縮點陣圖。 例如您可使用圖像小工具顯示圖像,無需在TouchGFX Designer或程式碼中對專案進行任何修改。 This makes use of compressed L8 images very easy.

3 algorithms #{three-algorithms}

TouchGFX uses 3 different compression algorithms for the L8 format. The image converter selects the algorithm that gives the best compression, unless the user has mandated a specific algorithm in the configuration. The algorithms are:

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

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

RGB Compression

As mentioned earlier, TouchGFX 4.24 introduced image compression support for the RGB565, RGB888, and ARGB8888 image formats. Images which contains more than 256 unique colors cannot be stored in the compact L8 image format and must be stored in one of the aforementioned formats. The compression of an RGB565, RGB888, or ARGB8888 image is directly compressing the 16-, 24-, or 32-bit pixels.

請參考以下圖像作為範例。 It is a more complex and rich background than the above example and has more than 256 unique colors. Therefore, it cannot be stored in L8, and it must be stored in the ARGB8888 format because it has transparent pixels (in the corners).

ARGB8888

The image is 240 x 240 pixels. The size of the pixel data is thus 240 x 240 x 4 = 230.400 bytes because we use 4 bytes to store each pixel in the ARGB8888 image format.

Compressing the image reduces the size to 32.347 bytes. The size of the compressed image is considerably smaller and only 14% of the original image size. Compression allows us to have multiple complex backgrounds in the same flash space, or reduce the flash requirements by a substantial amount. It also enables flash-limited devices to adopt more complex and rich graphics than otherwise possible with the L8 formats.

A compressed RGB image can be used like an ordinary uncompressed bitmap. 例如您可使用圖像小工具顯示圖像,無需在TouchGFX Designer或程式碼中對專案進行任何修改。 This makes use of compressed RGB images very easy.

Caution
Applying any dithering algorithm to an RGB image can in some cases compromise the effectiveness of the RGB compression.

2 algorithms

TouchGFX uses 2 slightly different compression algorithms which are automatically selected based on the image format to be compressed. The algorithms are:

  • QOI, encodes RGB888 and ARGB8888 pixels using a variation of the Quite OK Image format compression algorithm.
  • QOI565, encodes RGB565 pixels using a variation of QOI that is tailored for 16-bit pixel values.

Both variants of the RGB Compression algorithms are optimized for fast decompression speeds to limit the run-time performance penalty when rendering compressed RGB images.

Working with Compressed Images

Enabling the Image Compression Features

Image compression requires extra code in the target application. To avoid this higher space requirements, the compression code is optional on some platforms. You may have to enable the feature for your project.

Click "Config" on the left of the Designer, then click "Framework Features"

Enabling image compression

The image compression features are shown in the bottom. You can enable the specific feature set you need.

The targets has different options for the framework features, and in some cases the target has no optional features as shown below:

No optional framework features

In this case all the features are always enabled.

Caution
Be aware that the Designer does not show an error or warning if you use a feature that is not enabled. If you use image compression and the features is not enabled, the image is not drawn.

L8壓縮

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

設定壓縮用於L8-ARGB8888圖像

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

為小工具選擇壓縮圖像

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

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

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

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

RGB Compression

Compressing RGB565, RGB888, or ARGB8888 images in the TouchGFX Designer follows the same process as L8 compression.

設定壓縮用於L8-ARGB8888圖像

If selecting "Yes" the Image Converter will compress the image with the algorithm that matches the image format.

As with the L8 Compression, we can select the image for a widget as normal and reference the bitmap in code as usual.

壓縮程度

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

The image we used above in the L8 Compression example is generated into the file generated/images/src/image_gauge_background.cpp. The header of this file reads:

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,
....

The end of the comment in the first line shows the compression algorithm. 我們可以在此發現圖像轉換器已選取LZW9演算法。 第5行結尾顯示我們目前有5735位元組的像素資料,原始像素則為33856位元組, 產生16.9%的壓縮率(壓縮程度越小越好)。 注意! The compression percentage does not count the color table.

Compression Failure

In some cases the Image Converter gives a warning or error when compressing images. This can happen if the image is not compatible with the selected algorithm, or if the size of the compressed image is not below 90% of the original image. This will only happen in very rare coincidences. For example if a small image of 5 x 5 uses 25 different and distinct colors. Since there is no repetition or redundancy in the image, there is no possibilities for the compression to reduce the data.

L8 Images

For L8 images this can happen if a specific algorithm was selected that does not match the given image. For example if an image contains 17 colors or more, and and L4 compression is selected, the image can not be compressed using the selected algorithm. The Image Converter will print an error message when you generate code, and the Designer will show an error message:

Compression error with specific algorithm

The solution to the problem is to use another algorithm. The preferred way is to select "Auto" for L8 images. Then the image converter will try all algorithms, and select the best algorithm of those who are applicable.

In some rare cases the image does not compress below 90% of the original size. The Image Converter does not compress the image in that case and issues a warning text as shown below:

Compression warning

The reason for not compressing is that the saving in flash size does not outweigh the lower rendering performance. It is possible to force the compression by not using "Auto" but selecting one of the algorithms ("L4", "RLE", or "LZW").

The warning message is only informational. The code generation continues and the project will work as expected.

RGB Images

For RGB image formats you can not select the "Auto", as there is only one compression algorithm. If you select "Yes" and the image is not compressible below 90% of the original size, the Image Converter will generate an error:

Compression error with RGB image

The solution here is to select "None" for Compression for the image.

Decompressing Images to the Bitmap Cache

繪製的壓縮圖像在大部分情況下,效能都不如繪製的未壓縮圖像。 Further more, as mentioned in the introduction, the graphics accelerators in STM32 micro-controllers (DMA2D and GPU2D) cannot draw the compressed images directly. Therefore, compressed images are drawn by a mix of software and hardware, resulting in lower performance and higher cpu-load.

基於以上各種原因,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)); // Register the bitmap cache
bool r = Bitmap::decompress(BITMAP_GAUGE_BACKGROUND_ID, lzwBuffer); // Decompress the bitmap
image1.setBitmap(touchgfx::Bitmap(BITMAP_GAUGE_BACKGROUND_ID)); // Use the bitmap as normal
image1.setXY(148, 148); // Position Image widget
}

In this example we want to decompress the 184 x 184 image from the L8 Compression example above into the bitmap cache. The bitmap cache must be big enough to the hold uncompressed image. The 184 x 184 pixels plus the color table holding 207 ARGB8888 colors. The total size is therefore 34,688 bytes.

In this example we use the LZW9 algorithm. A 2048 bytes buffer is used by the decompresser during the decompression of an LZW9 compressed image (for building a dictionary). The buffer is not required after the decompression and can be reused for other purposes. The buffer is not required for decompression of L4, RLE, QOI, or QOI565 compressed images.

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

Limit program size

If you use decompression into the bitmap cache you have a few options to limit the size of your program. As mentioned above there are two types of image compression; L8 and RGB. When using Bitmap::decompress your program will contain the code for both decompressing L8 and RGB images. If you only use the RGB image compression, you can use the dedicated method for decompressing RGB images into the bitmap cache, which is Bitmap::decompressRGB, that way your program will only contain the required code for decompressing RGB images. The same applies if you only use L8 compression, here the method is called Bitmap::decompressL8. See examples below.

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);
...
}

限制

There are a few limitations when working with compressed images. Compressed images cannot be used with Widgets that scales or rotates the image, or with Widgets that fills an area, or with the Canvas widgets.

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

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

These limitations are made for performance reasons. TouchGFX Designer不會讓您選擇壓縮圖像。

If you want to use a specific image with any of these Widgets we suggest to not enable compression for the image. Alternatively, you can decompress the image at runtime.

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

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