メイン・コンテンツまでスキップ

画像の圧縮

TouchGFXバージョン4.22から、画像の圧縮がサポートされています。 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が豊かになる可能性もあります。

画像圧縮には、通常、可逆圧縮と非可逆圧縮の2種類があります。 非可逆画像圧縮では、画像の細部が削除されます。 これは多くの場合、最大の削減になりますが、元の画像を正確に再現することはできません。 可逆圧縮は、常に、元の画像を全く同じに再現します。 可逆圧縮は、通常、サイズの削減は小さくなります。

グラフィックスの場合、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やコードでプロジェクトに変更を加えることなく、Imageウィジェットを使用して画像を表示できます。 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 bitにエンコードします。 最大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やコードでプロジェクトに変更を加えることなく、Imageウィジェットを使用して画像を表示できます。 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.

圧縮画像をサポートしないウィジェットは、次のとおりです。

  • TextureMapper
  • ScalableImage
  • 針と円弧を描画するGauge
  • グラフの下の領域を塗りつぶすStaticGraphとDynamicGraph
  • AnalogClockでの針の描画
  • Circle、LineおよびShape
  • CircleProgressおよびLineProgress