これを行う最も速い方法は、シェーダーを使用することです。そのためには OpenGL ES 2 を使用する必要があります (一部の Android は ES 1 のみをサポートしています)。変更したい画像と同じサイズの一時的なビットマップが必要です。ターゲットとして設定します。シェーダーで、変更するイメージにバインドされているサンプラーからピクセルを取得します。変更したい色の小さな許容範囲内にある場合は、gl_FragColor を新しい色に設定します。それ以外の場合は、gl_FragColor をサンプラーから取得した色に設定します。目的の色と新しい色を vec4s としてシェーダーに渡す必要がありますal_set_shader_float_vector
。これを行う最も速い方法は、2 つのビットマップを保持し、色が変わるたびに使用している「メインのビットマップ」としてそれらを交換することです。
シェーダーを使用できない場合は、ビットマップをロックして色を置き換える必要があります。を使用al_lock_bitmap
してロックし、 と を使用al_get_pixel
しal_put_pixel
て色を変更できます。それからal_unlock_bitmap
あなたが終わったら。また、al_get_pixel/al_put_pixel の使用を避けて、手動でメモリにアクセスすることもできます。これにより高速になります。フォーマットでビットマップをロックするとALLEGRO_PIXEL_FORMAT_ABGR_8888_LE
、メモリは次のように配置されます。
int w = al_get_bitmap_width(bitmap);
int h = al_get_bitmap_height(bitmap);
for (int y = 0; y < h; y++) {
unsigned char *p = locked_region->data + locked_region->pitch * y;
for (int x = 0; x < w; x++) {
unsigned char r = p[0];
unsigned char g = p[1];
unsigned char b = p[2];
unsigned char a = p[3];
/* change r, g, b, a here if they match */
p[0] = r;
p[1] = g;
p[2] = b;
p[3] = a;
p += 4;
}
}
イメージを作成したときの形式でロックすることをお勧めします。つまり、私が言及したような簡単なものを選択することを意味します。そうしないと、ループの内側の部分がより複雑になります。ピクセル形式の ABGR_8888 部分は、データのレイアウトを記述します。ABGR はコンポーネントの順序を示します。ピクセルを単一のストレージ ユニット (この場合は int ですが、short でも同じように機能します) に読み込む場合、ビット パターンはAAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR
. ただし、一度に 1 バイトずつ読み取る場合、ほとんどのマシンはリトル エンディアンであるため、スモール エンドが最初に来ることを意味します。そのため、私のサンプル コードでは p[0] が赤になっています。8888 の部分は、コンポーネントあたりのビット数を示します。