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

カラーフォーマット

色は、ディスプレイ上のピクセルに表示されます。 表示される色は、フレームバッファに保存されている値によって決まります。 元より、グラフィック・システムで描写、使用、表示できる色の数は限定されています。 このことはTouchGFXおよびTouchGFXアプリケーションにも当てはまります。

アプリケーションで使用可能なピクセルのカラーの数は、アプリケーションの多くの部分に影響します。 それは、ディスプレイに表示される見栄えから、フレームバッファとして必要なメモリサイズや全体のパフォーマンスまで多岐にわたります。 このセクションでは、TouchGFXにおける色について詳しく説明し、TouchGFXで使用可能なカラーフォーマットを取り上げて、その利点と欠点にスポットを当てます。

TouchGFXにおける色は、赤、緑、青の3つのコンポーネントの組み合わせで、これはRGBカラーと呼ばれています。 色の各コンポーネントの範囲は0~255です。 0はそのコンポーネントがオフ、255はそのコンポーネントが最大であることを示します。

完全な黒色はRGBカラー(0,0,0)で表され、完全な白色は(255,255,255)です。 明るい緑色は(0,255,0)、やや明るい赤色は(128,0,0)、黒ずんだ紫色は(64,0,64)というふうになります。

いくつかのRGBカラー

グレースケール

グレースケール・アプリケーションでは、すべての色が黒から白までの範囲のグレーなので、RGBカラーではなくグレー濃度で表現されます。 グレースケールは、R = G = BのRGBカラーだと考えることもできます。

不透明度

状況によっては、その色の不透明度を示すコンポーネントを色に含めたい場合があります。 不透明度の範囲は0~255で、色の他のコンポーネントと同じです。 不透明度のある色は、RGBAカラーと呼ばれます。 Aはalpha(アルファ)を表します。これは不透明度のレベルを表すのに使用される従来からの名称です。

この場合、完全に不透明な黒色は(0,0,0,255)、幾分透明な赤色は(255,0,0,128)というふうになります。

白色とグレーの上のいくつかのRGBAカラー

色が完全に不透明でない場合は、すでに表示されている色と混ぜ合わせる必要があります。 こうした色の混合はアルファブレンディングと呼ばれます。

色深度

色深度は、フレームバッファに保存されている各色を描写するために使用されるビット数です。 この数値は、ピクセル当たりのビット数(bpp)で示されます。

使用するビット数が多いほど、描写できる色が増えます。

よく使用される色深度は24 bppです。 各ビットをオン / オフにできるので、224 = 16777216の異なる色を表現できることになります。

それより少しだけ使用頻度の低い色深度が1 bppです。 この色深度は白黒のアプリケーションに適用され、表現できるのは21 = 2の異なる色のみです。

TouchGFXでは、以下の色深度が組込みでサポートされています。

  • 32 bpp - 16777216色とそれに対応する不透明度の値
  • 24 bpp - 16777216色
  • 16 bpp - 65536色
  • 6/8 bpp - 64色
  • 4 bpp - 16のグレースケール色
  • 2 bpp - 4つのグレースケール色
  • 1 bpp - 2つのグレースケール色

色のコンポーネントの範囲については、次の点に注意が必要です。 24 bpp未満の色深度を操作する場合、赤、緑、青の各コンポーネントが直接0~255の範囲を持つことにはなりません。 こうしたコンポーネントでは、たとえば16 bppの赤色であれば、0~31の範囲になります。 31という値は16 bppで表現できる最も赤い色を表すと考えられ、24 bppにおける255に該当します。 16 bppの深度の色は、24 bppで表現可能な色のサブセットのみを表現できると考えることができます。

6/8 bppの色深度では、各ピクセルでカラー情報用に6ビット使用されます(赤、緑、青にそれぞれ2ビット)。 フレームバッファへのアクセスを簡素化するため、各ピクセルが6ビットから8ビット(1バイト)に増やされています。 フレームバッファ内の追加分の2ビットは使用されません。

フォーマット

色を表現するために必要なビット数を決めたら、次はビットの内容について詳しく調べてみます。 1つの色には赤色のコンポーネントを示すビット、緑色を示すビット、青色を示すビットがそれぞれいくらか含まれますが、色深度だけではピクセル内のビットの順序(フォーマット)を指定できません。 たとえば、 青色が最初で、緑色、赤色の順序、または逆の順序の可能性があります。

ピクセル・カラーフォーマット

アプリケーションの色深度に応じて、いくつか特定のカラーフォーマットが使用可能になります。

RGB888

TouchGFXでは、色深度が24 bppの色のカラーフォーマットはRGB888になります。 これは、赤、緑、青の各カラー・コンポーネントに8ビットずつ使用されることを意味しています。

こうした色をコードで表すには、コンポーネントを組み立てて色の値を作成します。次の例は明るい紫色であるrgb(255,0,255)を表しています。

uint32_t brightPurpleRGB888 = 255 << 16 | 0 << 8 | 255 << 0;

このフォーマットでは、赤が最も高い8ビット、次に緑、青は低い8ビットになります。

RGB565

16 bppの色の場合、TouchGFXではRGB565というカラーフォーマットを使用します。 これは、赤に5ビット、緑に6ビット、青に5ビットを割り当てます。 赤に5ビット使用し、フル点灯は31なので、明るい紫色のコードは次のようになります。

uint16_t brightPurpleRGB565 = 31 << 11 | 0 << 5 | 31 << 0;

RGBx2222、xRGB2222、BGRx2222、xBGR2222

6 bppの色に対して、TouchGFXではRGBx2222、xRGB2222、BGRx2222、xBGR222という4つの異なるフォーマットをサポートしています。 6ビットの色はバイトとして保存されるので、これらのフォーマットにはxが付いています。 色は2ビットで埋められ、1バイトになるようになっています。 RGBとBGRが両方あるのは、一部のディスプレイで必要になるためで、そのディスプレイに送信する前にピクセルを変換したくないからです。 RGBx2222の明るい黄色をコードで表すと、次のようになります。

uint8_t brightYellowRGBx2222 = 3 << 6 | 3 << 4 | 0 << 2;

GRAY4、GRAY2、BW

グレースケールの色深度ごとに、TouchGFXでは対応するカラーフォーマットを1つずつサポートしています。 4 bppのカラーフォーマットはGRAY4、2 bppではGRAY2、1 bppではBW(黒と白を表す)と示されます。 4 bppの完全な白色は次のようになります。

uint8_t whiteGRAY4 = 15;

TouchGFXには、正しいカラーフォーマットで色の正しい表現を返すヘルパ関数が含まれています。

#include <touchgfx/Color.hpp>
...
aColor = Color::getColorFromRGB(255,0,128);

画像フォーマット

画像はほとんどのUIアプリケーションにとって重要な部分であり、色で塗りつぶされています。 TouchGFXの画像はメモリ内に保存され、特定のフォーマットの色で塗りつぶされています。 多くの場合、画像はサポートされたピクセル・カラーフォーマットの1つを使用しますが、その他の画像フォーマットも使用できます。 特定の画像カラーフォーマットの画像内のピクセルは、描画の前に適切なピクセル・フォーマットに変換されます。

画像のカラーフォーマット説明
ARGB888832ビット、コンポーネントごとに8ビット
L8_ARGB88888ビットのインデックス・フォーマット、ARGB8888パレット
RGB88824ビット、コンポーネントごとに8ビット
L8_RGB8888ビットのインデックス・フォーマット、RGB888パレット
RGB66624ビット、コンポーネントごとに6ビット
RGB56516ビット、5ビット赤、6ビット緑、5ビット青
L8_RGB5658ビットのインデックス・フォーマット、RGB565パレット
ARGB22228ビット、コンポーネントごとに2ビット
ABGR22228ビット、コンポーネントごとに2ビット
RGBA22228ビット、コンポーネントごとに2ビット
BGRA22228ビット、コンポーネントごとに2ビット
GRAY44ビットのグレースケール
GRAY22ビットのグレースケール
BW1ビットのグレースケール
BW_RLE1ビットのグレースケールでランレングス符号化

これらの画像フォーマットの一部(L8で示されるもの)は、当該の画像を色のルックアップ・テーブル(CLUTと呼ばれる)と、このテーブル内へのインデックスによって画像を表しています。 これらのL8画像で可能な色の最大数は28 = 256です。 L8フォーマットは、非L8の同等のフォーマットよりも必要なメモリ領域が少なくなります。例を挙げると、200の異なる色による100x100の画像の場合、ARGB8888フォーマットで保存すると100 x 100 x 32ビット= 40000バイトを占有します。しかし、L8_ARGB8888フォーマットで保存すると100 x 100 x 8ビット+ 200 x 32ビット= 10800バイトのみで済みます。 L8フォーマットの使用方法の詳細については、こちらを参照してください。

BW_RLEの画像フォーマットには、単一のピクセル・カラーではなく、黒と白の連続色が保存されます。 多くの場合、この方がスペース効率も高くなります。

残りのフォーマットは、上記のピクセル・カラーフォーマットと同じです。

フレームバッファのフォーマット

すべての画像フォーマットをフレームバッファのフォーマットとして使用できるわけではありません。 L8フォーマットは、TouchGFXではフレームバッファのフォーマットとして使用できません。 フレームバッファ内で2つの画像にブレンディングするのは現実的ではないからです。

バイトとピクセルの順序

24ビット・フォーマットRGB888と32ビット・フォーマットARGB888には、バイト・ポインタを使用してアクセスすることがよくあります。 その場合、ピクセルはリトル・エンディアン順で保存されていると理解しておくことが必要です。

例として、32ビット・カラー0xFFFF7700(アルファ= 0xFF、赤= 0xFF、緑= 0x77、青= 0x00)について考えてみます。 色が32ビットの変数またはレジスタにある場合、値は0xFFFF7700になります。 色がメモリに保存されている場合、保存されているバイトは{ 0x00, 0x77, 0xFF, 0xFF }です。 これはBGRAという順序に対応します。

同様に、16ビット・フォーマットRGB565は常に16ビット・ポイントからアクセスされるので、バイトの順序は関係なく、メモリ内でスワップされます。

8ビット・フォーマット(ARGB2222など)では色がバイトに適合し(アルファが2つの最高ビットにある)、変更なしで保存されます。

もっと小さいフォーマットのGRAY4、GRAY2、BWは、2つの順序で保存される可能性があります。 低いビットが左端のピクセルまたは右端のピクセルになる可能性があります。 低いビットが左端にある場合はLSBモードと呼ばれ、そうでない場合はMSBモードと呼ばれます。

フレームバッファのフォーマット順序説明
ARGB8888BGRA32ビット、コンポーネントごとに8ビット
XRGB8888BGRX32ビット、コンポーネントごとに8ビット、アルファ・バイトは無視される
RGB888BGR24ビット、コンポーネントごとに8ビット
RGB56516ビット、5ビット赤、6ビット緑、5ビット青
ARGB22228ビット、コンポーネントごとに2ビット
ABGR22228ビット、コンポーネントごとに2ビット
RGBA22228ビット、コンポーネントごとに2ビット
BGRA22228ビット、コンポーネントごとに2ビット
GRAY4LSB4ビットのグレースケール
GRAY2LSB2ビットのグレースケール
BWMSB1ビットのグレースケール

テキスト・フォーマット

テキスト(正確に言うとグリフ)も、特定のカラーフォーマットでメモリ内に保存されます。 TouchGFXで使用可能なテキストのカラーフォーマットは以下のとおりです。

テキストのカラーフォーマット説明
A88ビット、不透明のみ
A44ビット、不透明のみ
A22ビット、不透明のみ
A11ビット、不透明のみ

グリフのフォーマットは小さい画像に相当し、ここでは各カラー・エントリが各ピクセルの不透明度を保持しています。 これにより実際の色(赤、緑、青のコンポーネント)を後で適用できるようになります。たとえば、保存されたグリフ'A'を青色バージョンと赤色バージョンの両方で描画することができます。

各グリフに使用されるビット数が増えるほど、通常は表示がスムーズになり見栄えがよくなります。

視覚品質

組込みグラフィックスの作成時には、最高の視覚品質を求めますが、同時にメモリ消費量にも注意する必要があります。

このため、リッチなRGB888ではなく、RGB565カラーフォーマットを選択する方が望ましい場合が多くなります。一般的には、メモリ要件を重視しながら、最高の視覚品質を実現できるカラーフォーマットを決定する必要があります。

ディザリング

TouchGFXでは、さまざまなカラーフォーマットで画像を表現するときの視覚品質を高めるために、ディザリングと呼ばれる手法を採用しています。

ディザリングは、実際に表現しているよりも多くの色で画像を表示するためによく用いられる手法です。 画像の色にわずかなノイズを加えることで、これを実現します。

一例を挙げると、RGB888の画像をRGB565の画像に変換する場合、各カラー・コンポーネントの下位ビットを削るだけではなく、変換プロセスで、結果の各色にいくらかのノイズを加えます。結果として変換後の画像はよりリッチな表示になり、元のRGB888と遜色がないものになります。

言葉ではなく実際の画像で説明するため、元のRGB888の画像といくつかの変換後の画像を以下に示します。 変換後の画像は、RGB565フォーマットでディザリング有 / 無、xRGB2222フォーマットでディザリング有 / 無、GRAY4フォーマットでディザリング有 / 無です。

元のRGB888の画像

変換後のRGB565の画像(ディザリング有 / 無)

変換後のxRGB2222の画像(ディザリング有 / 無)

変換後のGRAY4の画像(ディザリング有 / 無)

これでわかるように、ディザリングによる画像の品質向上はほんのわずかしか認識できません。 RGB565のディザリング有 / 無を間近でよく見てみると、ディザリング有りのバージョンは元の画像とほとんど同じに見えますが、ディザリング無しの方にはカラー・バンディングが明らかな領域があります。 これは、多くの場合に16ビット・カラーが見栄えのよいグラフィックスを十二分に表現することを示すよい例となっています。

グラフィック・アセットに大きなグラデーションが含まれる場合、ディザリングした画像でもカラー・バンディングが発生する可能性があります。 次に2つの例を示します。 1つ目は、RGB888 (64,190,222)から黒色までの範囲の青みがかったグラデーションと、変換後のRGB565の画像のディザリング有りと無しです。

元のRGB888の画像と、変換後のRGB565の画像(ディザリング有 / 無)

2つ目は、(255,0,0)から黒色までの範囲の赤色のグラデーションです。

元のRGB888の画像と、変換後のRGB565の画像(ディザリング有 / 無)

よく見ると、ディザリング有りと無しの両方のRGB565バージョンに、カラー・バンディングが確認されます。 赤色の画像の方が縞模様が目立っています。

変換後の画像とカラーフォーマットには常に細心の注意を払い、必要に応じて元の画像を変更したり、別のカラーフォーマットを選択したりしてください。

パフォーマンス

ここで説明したすべての画像フォーマットは、描画の「容易さ」に関して最適化されています。 つまり、これらの画像は大きな変換を行わなくても、多かれ少なかれフレームバッファにコピーできるということです。

これは意図したものであり、TouchGFXがマイクロコントローラ上で円滑なグラフィックスを達成できる理由の1つになっています。

TouchGFXでUIを設計する際には、ユーザは.png画像を使用し、コンパイル時にこれらの各画像が、上で説明した効率的な画像フォーマットのいずれかに変換されます。

アルファブレンディング

実行時には、通常のCPUでのコピー操作により、あるいはマイクロコントローラの機能を使用して、画像データのコピーが行われます。 完全に透明 / 不透明でないピクセルが画像に含まれている場合、そのピクセルをバックグラウンド上にアルファブレンディングする必要があります。 一部のSTM32マイクロコントローラでは、このブレンディングがハードウェアによってサポートされています。

その他の画像フォーマット

実行時に他の画像フォーマット(たとえば.jpgや.pngなどの圧縮画像フォーマットなど)をサポートする必要がある場合は、TouchGFXによるダイナミック・ビットマップのサポートを利用できます。

Further reading
色深度に関するWikipediaの記事。