ダイナミック・ビットマップ
このセクションでは、ダイナミック・ビットマップの使用方法について説明します。 標準のビットマップはアプリケーションにコンパイルされるので、コンパイル時に使用可能でなければならないことを思い出してください。 ビットマップはPNGファイルなどから変換され、サイズおよびフォーマット情報と共に内部フォーマットで保存されます。
実行時にRAM内でビットマップを作成することも可能です。 これはダイナミック・ビットマップと呼ばれます。 ダイナミック・ビットマップは、アプリケーションにコンパイルされるスタティック・ビットマップと同じように使用できます。 つまり、ダイナミック・ビットマップは画像ウィジェットやボタン・ウィジェットなどで使用できます。
ダイナミック・ビットマップの設定
ダイナミック・ビットマップの作成時には、ビットマップ・キャッシュからピクセル・メモリが割り当てられます。 したがって、ダイナミック・ビットマップを作成する前に、ビットマップ・キャッシュを設定する必要があります。 これは手動のプロセスで、TouchGFX DesignerやGeneratorでは実行できません。
設定手順については、「ビットマップ・キャッシュ」を参照してください。
アプリケーション内で使用されるダイナミック・ビットマップの最大数を定義する必要があります。 この最大数は、ビットマップ・キャッシュのアドレスやサイズと共にTouchGFXに渡されます。 ここでは、最大4つのダイナミック・ビットマップを持つビットマップ・キャッシュを設定します。 この設定はアプリケーション内の任意のファイルで行うことができます。 設定を一度だけ行う必要がある場合は、FrontendApplication.cppがよいでしょう。
FrontendApplication.cpp (extract)
#include <gui/common/FrontendApplication.hpp>
#include <touchgfx/Bitmap.hpp>
FrontendApplication::FrontendApplication(Model& m, FrontendHeap& heap)
    : FrontendApplicationBase(m, heap)
{
    // Place cache start address in SDRAM at address 0xC0008000;
    uint16_t* const cacheStartAddr = (uint16_t*)0xC0008000;
    const uint32_t cacheSize = 0x300000; //3 MB, as example
    Bitmap::setCache(cacheStartAddr, cacheSize, 4);
}
Windowsシミュレータを使用する場合には、ここでビットマップ・キャッシュも作成する必要があります。 Windowsで大きな配列を宣言したり、mallocを使用したりするのは簡単です。
FrontendApplication.cpp (extract)
#include <gui/common/FrontendApplication.hpp>
#include <touchgfx/Bitmap.hpp>
FrontendApplication::FrontendApplication(Model& m, FrontendHeap& heap)
    : FrontendApplicationBase(m, heap)
{
#ifdef SIMULATOR
    const uint32_t cacheSize = 0x300000; //3 MB, as example
    uint16_t* const cacheStartAddr = (uint16_t*)malloc(cacheSize);
    Bitmap::setCache(cacheStartAddr, cacheSize, 4);
#else
    // Place cache start address in SDRAM at address 0xC0008000;
    uint16_t* const cacheStartAddr = (uint16_t*)0xC0008000;
    const uint32_t cacheSize = 0x300000; //3 MB, as example
    Bitmap::setCache(cacheStartAddr, cacheSize, 4);
#endif
}
ダイナミック・ビットマップの使用例
ダイナミック・ビットマップを使用するには、それを表示すウィジェットが必要です。 そこで、画像ウィジェットをビューに挿入します(コードまたはDesignerを使用)。
#include <touchgfx/widgets/Image.hpp>
using namespace touchgfx;
class TemplateView : public View
{
private:
    Image image;
}
ダイナミック・ビットマップでこのウィジェットを使用するには、次の3つの手順を実行します。
- ビットマップ・キャッシュ内にダイナミック・ビットマップを作成
- ダイナミック・ビットマップが使用するメモリをクリア
- ビットマップをウィジェットに割当て
ダイナミック・ビットマップはsetupScreenで作成します。 ここでは、16bppフォーマットRGB565を使用します。 フレームバッファが24ビットの場合はRGB888を使用します。 透明なビットマップを作成するには、フォーマットARGB8888を使用します。
ダイナミック・ビットマップ内のピクセルのアドレスは、dynamicBitmapGetAddress関数によって返されます。
#include <touchgfx/Bitmap.hpp>
void TemplateView::setupScreen()
{
    BitmapId bmpId;
    //Create (16bit) dynamic bitmap of size 100x150
    const int width = 100;
    const int height = 150;
    bmpId = Bitmap::dynamicBitmapCreate(100, 150, Bitmap::RGB565);
    //set all pixels white
    if (bmpId != BITMAP_INVALID)
    {
       memset(Bitmap::dynamicBitmapGetAddress(bmpId), 0xFF, width*height*2);
    }
    //Make Image widget show the dynamic bitmap
    image.setBitmap(Bitmap(bmpId));
    //Position image and add to View
    image.setXY(20, 20);
    add(image);
    ...
}
ビットマップ・キャッシュから取得するピクセル・メモリはクリアされないので、これをすぐにクリアまたは上書きすることをお勧めします。
ファイルから画像を読み込む場合には、memsetへの呼び出しをローダのコードに置き換えます。 詳細については、「実行時の画像の読込み」を参照してください。
ダイナミック・ビットマップの操作
ダイナミック・ビットマップの操作はすべてBitmapクラスで実行されます。
ダイナミック・ビットマップの作成
以下のメソッドでは、指定された幅、高さ、ビットマップ形式で、ダイナミック・ビットマップを作成します。 ビットマップが作成されるのは、十分な量の未使用のメモリが使用可能な場合のみです。 ビットマップが作成されなかった場合、このメソッドはBITMAP_INVALIDを返します。
static BitmapId Bitmap::dynamicBitmapCreate(const uint16_t width, const uint16_t height, BitmapFormat format, ClutFormat clutFormat)
ダイナミック・ビットマップの削除
次のメソッドはダイナミック・ビットマップを削除します。
static bool Bitmap::dynamicBitmapDelete(BitmapId id)
ダイナミック・ビットマップ内のピクセルのアドレスを取得
次のメソッドはダイナミック・ビットマップのアドレスを返します。 このメソッドは、ファイル・ローダが画像データをビットマップにコピーするために使用します。
static uint8_t* dynamicBitmapGetAddress(BitmapId id)
ダイナミック・ビットマップの塗りつぶし領域を設定
次のメソッドは、ダイナミック・ビットマップの塗りつぶされた長方形を設定します。
static bool dynamicBitmapSetSolidRect(BitmapId id, const Rect& solidRect)
「塗りつぶし領域」の概念については、「カスタム・ウィジェット」を参照してください。
デフォルトでは、RGB565やRGB888などの不透明なフォーマットでは、塗りつぶし領域がビットマップ全体になるように設定されます。 ARGB8888などの透明なフォーマットでは空に設定されます。
縦向きモードのダイナミック・ビットマップ
TouchGFXは縦向きモードで実行できます。 このモードは、ディスプレイが本来の方向から90度回転した状態でマウントされている状況で使用されます。 このモードでダイナミック・ビットマップを使用する場合、少し注意が必要です。
次に示すのはSTM32F746向けのプロジェクト例です。 ここでは幅が480ピクセル、高さが272ピクセルのディスプレイが使用されています。 フレームバッファは同じ寸法です。
image1の画像ウィジェットにはビットマップは割り当てられていません。 この例ではこれを使用してダイナミック・ビットマップを表示します。
縦向きモードを使用する場合は、座標系が反時計回りに90度回転します。 座標(0, 0)は、左上隅の'D'の近くになります。 フレームバッファの最初のバイト(スクリーン上の最初のピクセルの色を指定)は、右上隅にあります。
したがって、縦向きで実行されるときにフレームバッファは回転しません。 ダイナミック・ビットマップにも同じことが言えます。
しかし、(マウントする)ディスプレイの最初のラインに表示させるピクセルは、フレームバッファの左のエッジに描画する必要があります。
次の関数では、ダイナミック・ビットマップを作成し、上の行を緑色、右のエッジを赤色にしています。
Screen1View.cpp (extract)
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
    BitmapId bmpId;
    bmpId = Bitmap::dynamicBitmapCreate(100, 100, Bitmap::RGB565);
    if (bmpId != BITMAP_INVALID)
    {
        //set all pixels white
        uint16_t* const bitmapPixels = (uint16_t*)Bitmap::dynamicBitmapGetAddress(bmpId);
        memset(bitmapPixels, 0xFF, 100*100*2);
        //first 200 pixels red, => two column on the right on display
        for (int i = 0; i<200; i++) bitmapPixels[i] = 0xF800;
        //first two pixels in all rows green in bitmap => top two rows on display
        for (int i = 0; i<100; i++)
        {
            bitmapPixels[i*100]     = 0x07E0;
            bitmapPixels[i*100 + 1] = 0x07E0;
        }
    }
    image1.setBitmap(bmpId);
}
ディスプレイにダイナミック・ビットマップが表示されます。

