Copyright 2021 Moddable Tech, Inc.
更新日: 2021年4月11日
アニメーションGIF画像形式は人気があり、マイクロコントローラーでも実装可能です。Commodettoグラフィックスライブラリは、スムーズなアニメーションを提供する製品のために、マイクロコントローラー上で高品質、高性能なレンダリングを提供します。
ほとんどのマイクロコントローラー向けのGIF実装は、メモリ使用量を最小限に抑えるためにフレームバッファに直接デコードします。これは一部のアニメーションGIFには有効ですが、他のものではちらつきやブロックノイズを引き起こすことがあります。CommodettoのアニメーションGIFデコーダーは異なるアプローチを取ります: 完全にデコードされた画像のためのメモリバッファを必要とします。これにより、メモリが厳しい場合には適していません。しかし、動作するデバイスでは、正確で高性能、ちらつきのないアニメーションを提供することができます。デコーダーの出力がCommodettoビットマップであるため、Pocoレンダラーを使用して他のグラフィカル要素と合成することができます。
CommodettoのアニメーションGIFデコーダーには、多くのアニメーションGIFシーケンスをデコードするために必要なメモリ量を大幅に削減するためのいくつかの特別なデコードモードがあります。 メモリ要件が増加したため、CommodettoのアニメーションGIFデコーダーはすべてのマイクロコントローラーで実用的ではありません。ESP32(外部RAMなし)およびPico(RP2040)では、約200ピクセルの画像に対して非常にうまく機能します。
モジュールを使用するには、まずインポートします:
import ReadGIF from "commodetto/ReadGIF";
モジュールはリソースからGIFデータを読み取ります。リソースをコンストラクタに渡します:
let reader = new ReadGIF(new Resource("moddable.gif"));
ReadGIFはデコード状態を保存するためのメモリと、デコードされた画像を保存するためのメモリを必要とします。メモリが不足している場合、ReadGIF
は例外をスローします。
デコード状態はアプリケーションヒープにあります。アプリケーションヒープのデフォルト構成はこれには小さすぎるため、約48 KBに増やす必要があります。プロジェクトマニフェストでこれを行うことができます:
"creation": {
"static": 49152
}
デコードされた画像はシステムメモリに保存されます。ReadGIF
を呼び出すときにシステムメモリがどれだけ空いているかを確認するには、xsbugの計測タブを確認してください。
リーダーインスタンスの width
と height
プロパティは、デコードされた画像のサイズを提供します。
duration
プロパティはアニメーションの総長さをミリ秒単位で示します。frameCount
はアニメーションの総フレーム数です。
画像をデコードするには、next
を呼び出します。アニメーションフレームシーケンスの終わりに達すると、デコーダーは自動的に最初に戻ります。
reader.next();
next
関数はリーダーの状態を次のフレームに更新します。リーダー自体はデコードされた画像を含むビットマップとして使用できます。画像をレンダリングするために便利な他のプロパティも持っています。next
によって最後にデコードされたフレームの番号は frameNumber
プロパティから取得できます。
注意: リーダーインスタンスの
ready
プロパティは、少なくとも1フレームのGIFが描画可能である場合にtrue
になります。画像をダウンロードする際には、reader.ready
をチェックしてリーダーが最初のフレームを返す準備ができているかどうかを確認してください。
next
を呼び出すと、リーダーのビットマップが次のフレームに更新されます。通常通りにビットマップを描画するためにPocoを使用します。以下は、画面の左上隅に画像を描画します。
import Poco from "commodetto/Poco";
poco.begin(0, 0, reader.width, reader.height);
poco.drawBitmapWithKeyColor(reader, 0, 0);
poco.end();
多くの場合、アニメーションはフレーム全体ではなく、ピクセルの一部のみを更新します。この場合、ディスプレイ上のすべてのピクセルを更新する必要はなく、より効率的です。リーダーはその frameX
、frameY
、frameWidth
、および frameHeight
プロパティで更新領域を提供します。
次の例では、更新領域を使用して描画を最小限に抑えながら、毎秒10フレームでアニメーションを連続的に実行します。
Timer.repeat(() => {
reader.next();
poco.begin(reader.frameX, reader.frameY, reader.frameWidth, reader.frameHeight);
poco.drawBitmapWithKeyColor(reader, 0, 0);
poco.end();
}, 100);
アニメーションGIFの各フレームにはそれぞれの持続時間があります。デコードされたフレームの持続時間は、リーダーインスタンスの frameDuration
プロパティでミリ秒単位で取得できます。
let frameDuration = reader.frameDuration;
この例は、描画領域を最適化し、各フレームの持続時間を適用する典型的な描画ループを示しています。
const reader = new ReadGIF(new Resource("moddable.gif"));
Timer.repeat(id => {
reader.next();
Timer.schedule(id, reader.frameDuration, 1);
poco.begin(reader.frameX, reader.frameY, reader.frameWidth, reader.frameHeight);
poco.drawBitmapWithKeyColor(bitmap, 0, 0);
poco.end();
}, 1);
一部のアニメーションGIF画像には、背景が透けて見えるように設計された透明な領域があります。これは、非矩形の形状を持つアニメーションに使用されます。透明性は二値的で、ピクセルは完全に不透明か完全に見えないかのどちらかです。アルファブレンディングはありません。
リーダーインスタンスの transparent
プロパティは、画像に透明なピクセルが含まれているかどうかを示します。
真の透過性を実現するにはいくつかのステップが必要です。まず、アプリケーションは画像の背後にある背景ピクセルを塗りつぶす必要があります。以下の例では、背景を赤で塗りつぶしています。次に、drawBitmapWithKeyColor
を使用して画像をレンダリングし、アニメーションGIFから透明色を提供します。drawBitmapWithKeyColor
関数は drawBitmap
と似ていますが、指定されたキー色と一致するピクセルをスキップします。
const red = poco.makeColor(255, 0, 0);
poco.fillRectangle(red, 0, 0, reader.width, reader.height);
poco.drawBitmapWithKeyColor(reader, 0, 0, reader.transparentColor);
fillRectangle
呼び出しがアニメーションGIFの背後に描画されることに注意してください。コードは、パターンやロゴ、さらには別のアニメーションなど、GIFの背後に何でも描画できます。drawBitmapWithKeyColor
を使用するのは安全です。
GIF画像には2色から約1600万色まで含まれています。多くの色を持つ画像は、ピクセルあたり16ビットで保存する必要があり、かなりのメモリを使用します。Commodetto GIFデコーダーは、GIF画像を8ビット、4ビット、および1ビットピクセルにデコードすることもできます。デコーダーは、完全な色忠実度を維持しながら、最も少ないメモリを使用するフォーマットを自動的に決定します。使用されるビットマップフォーマットは常に poco.drawBitmapWithKeyColor
を使用して描画できます。使用されるビットマップのフォーマットは、GIFリーダーインスタンスの pixelFormat
プロパティから取得できます。
一部のアプリケーションでは、自動フォーマット検出を無効にして特定のフォーマットにデコードを強制することを希望する場合があります。これにより、正しくレンダリングされない画像が生成されることがありますが、クラッシュすることはありません。特定のフォーマットにデコードを強制するには、オプションの引数の一部としてピクセルフォーマットを ReadGIF
コンストラクタに渡します。以下の例は、RGB565リトルエンディアンフォーマットでピクセルを要求する方法を示しています:
const reader = new ReadGIF(
new Resource("moddable.gif"),
{
pixelFormat: Bitmap.RGB565LE
}
);
1、4、および8ビットパーピクセルにデコードを強制するには、それぞれ Bitmap.Monochrome
、Bitmap.Gray16
、および Bitmap.CLUT256
を使用します。
以下の表は、GIFリーダーインスタンスで利用可能なプロパティを説明しています。GIFアニメーションはキャンバスに描画されます。アニメーションの各フレームには、キャンバスを更新する画像が含まれています。画像はキャンバス全体を更新する場合もあれば、その一部のみを更新する場合もあります。
プロパティ | 説明 |
---|---|
width |
アニメーションキャンバスの幅 |
height |
アニメーションキャンバスの高さ |
duration |
アニメーションの総持続時間(ミリ秒) |
frameBounds |
現在のフレームの更新領域を含む矩形オブジェクト |
frameCount |
アニメーションの総フレーム数 |
frameDuration |
現在のフレームの持続時間(ミリ秒) |
frameNumber |
現在のフレームのインデックス番号 |
frameX |
前のフレームから更新された領域のキャンバス内の水平オフセット |
frameY |
前のフレームから更新された領域のキャンバス内の垂直オフセット |
frameWidth |
現在のフレームで更新された領域の幅 |
frameHeight |
現在のフレームで更新された領域の高さ |
transparent |
キャンバスに透明な背景ピクセルが含まれている場合は true |
transparentColor |
透明な背景ピクセルを埋めるために使用されるピクセル値。画像が透明性を使用していない場合は未定義 |
ready |
アニメーションGIFリーダーが少なくとも1フレームを解析できる場合は true 。GIF画像をダウンロードする際に最初のフレームが利用可能かどうかを検出するために使用されます |
コアのGIFデコーダーは、BitBank Software の Larry Bank による GIF Animator です。