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

画像の圧縮

TouchGFXバージョン4.22から、画像の圧縮がサポートされています。 バージョン4.22~4.23でのサポートは、L8画像圧縮に制限されています。 バージョン4.24以降は、RGB565、RGB888、およびARGB8888フォーマットの画像圧縮がサポートされています。

画像圧縮は、画像のストレージ要件を低減するプロセスです。 より小さなFlashメモリの使用で済むならば、プロジェクトの画像サイズの削減はコスト削減につながります。 また、圧縮することでプロジェクトでより多くの画像を使用できるので、その結果、UIが豊かになる可能性もあります。

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

グラフィックスの場合、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%未満になります。 したがって、圧縮により、同一のFlashメモリ領域に5つの異なるバックグラウンドを格納したり、Flashメモリの使用量を28,121バイト削減したりできます。

圧縮されたL8画像は、通常の非圧縮ビットマップのように使用されます。 たとえば、TouchGFX Designerやコードでプロジェクトに変更を加えることなく、Imageウィジェットを使用して画像を表示できます。 これにより、L8圧縮画像の使用が大変容易になっています。

3つのアルゴリズム#{three-algorithms}

TouchGFXは、L8フォーマットの画像に対して、3つの圧縮アルゴリズムを使用します。 ユーザが設定でアルゴリズムを指定しないかぎり、画像コンバータにより、最適な圧縮を提供するアルゴリズムが選択されます。 アルゴリズムは次のとおりです。

  • L4は、各ピクセルを4 bitにエンコードします。 最大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ピクセルです。 ARGB8888画像フォーマットでは各ピクセルの保存に4バイトを使用するため、ピクセル・データのサイズは240 x 240 x 4 = 230,400バイトになります。

画像の圧縮により、サイズは32,347バイトに削減されます。 圧縮画像のサイズはかなり小さく、元の画像サイズのわずか14%です。 圧縮により、同一のFlashメモリ領域に複数の複雑なバックグラウンドを格納したり、Flashメモリの使用量を十分削減できます。 また、Flashメモリの使用量が制限されたデバイスで、L8フォーマットの場合よりも複雑で豊富なグラフィックスを採用することもできます。

RGB圧縮画像は、通常の非圧縮ビットマップのように使用できます。 たとえば、TouchGFX Designerやコードでプロジェクトに変更を加えることなく、Imageウィジェットを使用して画像を表示できます。 これにより、RGB圧縮画像の使用が大変容易になっています。

Caution
RGB画像にディザリング・アルゴリズムを適用すると、場合によっては、RGB圧縮の効果を損なう可能性があります。

2つのアルゴリズム

TouchGFXでは、圧縮する画像フォーマットに基づいて自動的に選択される、若干異なる2つのアルゴリズムを使用します。 そのアルゴリズムは次のとおりです。

  • QOIは、Quite OK Imageフォーマット圧縮アルゴリズムの一種を使用して、RGB888とARGB8888ピクセルをエンコードします。
  • QOI565は、16ビット・ピクセル値向けにカスタマイズされたQOIの一種を使用して、RGB565ピクセルをエンコードします。

どちらの種類のRGB圧縮アルゴリズムも、RGB圧縮画像を描画する際に実行時のパフォーマンスの低下を制限するために、高速解凍に合わせて最適化されています。

圧縮画像の使用

画像圧縮機能の有効化

画像を圧縮する場合には、対象のアプリケーションに追加のコードが必要です。 この追加コードによる容量要件の増加を回避するため、一部のプラットフォームでは圧縮コードはオプションになっています。 この機能を、あなたのプロジェクトに対して有効にする必要がある場合があります。

Designerの左側にある[Config]をクリックし、次に[Framework Features]をクリックします。

画像圧縮の有効化

画像圧縮機能は下部に表示されます。 必要な圧縮機能を有効化します。

ターゲットにはフレームワーク機能のさまざまなオプションが含まれていますが、下記のようにオプションの機能が含まれていない場合もあります。

オプションのフレームワーク機能なし

この場合、すべての機能は常に有効になっています。

Caution
有効になっていない機能を使用した場合は、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画像の圧縮の設定

[Yes]を選択すると、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%に圧縮されました(圧縮レベルの数値が小さい方が圧縮率が高くなります)。 注! 圧縮率には、カラー・テーブルはカウントされていません。

圧縮エラー

場合によっては、画像圧縮の際にImage Converterから警告やエラーが出力されます。 これは、画像が選択したアルゴリズムに対応していないか、圧縮画像のサイズが元の画像の90%未満にならない場合に発生する可能性があります。 これが発生するのは非常にまれです。 たとえば、5 x 5の小さい画像が25種類の異なる色を使用している場合などです。 画像に繰り返しや冗長性はないため、圧縮でデータが削減される可能性はありません。

L8画像

L8画像の場合、これは、指定の画像に適合しないアルゴリズムが選択された場合に発生する可能性があります。 たとえば、画像に17色以上の色が使用されていて、L4圧縮が選択されている場合、選択したアルゴリズムを使用してこの画像を圧縮することはできません。 コードを生成すると、Image Converterからエラー・メッセージが出力され、Designerで次のようなエラー・メッセージが表示されます。

特定のアルゴリズムで発生した圧縮エラー

この問題の解決法は別のアルゴリズムを使用することです。 推奨される方法は、L8画像に[Auto]を選択することです。 すると、Image Converterはすべてのアルゴリズムを試し、適用可能なものの中から最適なアルゴリズムが選択されます。

まれに、画像を圧縮しても元のサイズの90%未満にならないことがあります。 そのような場合、Image Converterは画像の圧縮を行わず、以下のような警告メッセージを出力します。

圧縮に関する警告

圧縮しない理由は、Flashサイズの節約が描画パフォーマンスの低下を埋め合わせできないからです。 [Auto]を使用せずに、いずれかのアルゴリズム("L4"、"RLE"、または"LZW")を選択することで、強制的に圧縮を実行できます。

警告メッセージは情報提供のみです。 コード生成は続行され、プロジェクトは期待通りに動作します。

RGB画像

RGB画像フォーマットには、圧縮アルゴリズムが1つしかないため、[Auto]を選択することはできません。 [Yes]を選択したときに画像が元のサイズの90%未満に圧縮できない場合は、Image Converterからエラーが出力されます。

RGB画像の圧縮エラー

この場合の解決法は、画像の圧縮に[None]を選択することです。

ビットマップ・キャッシュへの画像の解凍

圧縮画像の描画は、ほとんどの場合、非圧縮画像の描画よりも性能が低下します。 そのうえ、冒頭で述べたように、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)); // 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
}

この例では、上記のL8圧縮の例の184 x 184画像をビットマップ・キャッシュに解凍します。 ビットマップ・キャッシュは、解凍された画像を保持できる十分な大きさがある必要があります。 画像は184 x 184ピクセルで、カラー・テーブルではARGB8888の色を207個保持しています。 したがって、全体サイズは34,688バイトになります。

この例では、LZW9アルゴリズムを使用します。 LZW9圧縮画像の解凍時には、デコンプレッサにより、2,048バイトのバッファが使用されます(ディクショナリ作成のため)。 バッファは、解凍後には不要になるため、別の目的で再利用できます。 バッファはL4、RLE、QOI、またはQOI565圧縮画像の解凍には必要ありません。

解凍された画像をこれ以上使用しない場合は、Bitmap::cacheRemoveBitmapメソッドを使用して、ビットマップ・キャッシュから削除できます。

プログラムサイズの制限

ビットマップ・キャッシュへの解凍を使用する場合、プログラムのサイズを制限するためのオプションがいくつかあります。 前述したように、L8とRGBの2種類の画像圧縮があります。 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);
...
}

制限

圧縮画像で作業する場合には、いくつかの制限があります。 圧縮画像は、画像を拡大したり回転するウィジェット、領域を塗りつぶすウィジェット、またはCanvasウィジェットでは使用できません。

圧縮画像を適合しないウィジェットで使用

Caution
圧縮画像はすべてのウィジェットで使用できるわけではありません。 できないときは、Designerから警告アイコンが表示されます。

こうした制限は、性能上の理由で設けられています。 TouchGFX Designerでは、圧縮画像を選択できません。

特定の画像をこれらのウィジェットで使用したい場合は、画像の圧縮を有効にしないことをお勧めします。 または、画像を実行時に解凍できます。

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

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