質問

最近、メモリ内の非圧縮ビットマップの表現に興味がありました。ただし、適切に実装する方法がわからないことの1つは、バイナリ透過性です。たとえば、私は次のようなものから始めます:

struct RGBPixel {
 uint8_t red;
 uint8_t green;
 uint8_t blue;
};

struct bitmap {
 struct RGBPixel *data;
 size_t width;
 size_t height;
 size_t bytesPerPixel;
 size_t bytewidth;
 /* etc. */
};

最も簡単な方法は次のようになります:

struct RGBPixel {
 uint8_t red;
 uint8_t green;
 uint8_t blue;
 bool transparent;
};

しかし、それは少し無駄に思えます(完全なアルファチャネルを追加することもできます)。私が考えることができる他の唯一の可能性は、色の1つを透明として予約することですが、その色を表示する機能を失います。これを行う標準的な方法はありますか?

一般的な形式(GIF、8ビットPNGなど)はこれをどのように表しますか?

役に立ちましたか?

解決

1600万色がありますが、そのうちの1つを透明に指定することは大きな苦労ではありません。画像が16メガピクセルでない限り、16Mのすべての色を使用しないことを確認できます。使用しない色を選択して、透明色にします。それらすべてを使用する巨大なイメージがある場合は、使用頻度が最も低いイメージを選択し、隣接する色に変更して、未使用にします。

ご指摘のとおり、ピクセルRGBデータを使用してピクセルごとに1ビットを保存しようとしても効率的ではありません。 1つのポインターにすべてのRGBピクセルを保存してから、別のポインターに同じHおよびV次元のビットマップを保存するか、クロマキーイングを実行する必要があります。上記のように、R、G、Bおよび透明度ビットマップを使用してデータを別々に保存することもできますが、それを描画することになると、一般的に非常に非効率的です。

他のヒント

Gifは指定された色を透明に使用します。 (例:0xFFFF00が透明だとすると、この色のピクセルはすべて透明として表示されます。)この色はこの画像では使用できません。
Pngにはアルファチャネルがあります。これは、ピクセルのアルファ値を表す別のintを意味します。 (例:0 =完全に透明、255 =不透明、128 =半透明)

通常、透明度を表す4番目のアルファチャネルがあります。

i.e。 RBGの代わりに、RGBAを使用できます。

バイナリ透明度は、クロマキーイングとも呼ばれます。色を透明色として指定し、描画関数で色がクロマキーでない場合はピクセルを描画します(指定された透明色)。

ドロップシャドウなどのマルチレベル透明度を行う場合、ピクセルごとのアルファが使用されます。

透明度を個別のメモリに保存するか、各チャンネルを個別に保存することもできます。例:

struct bitmap {
 uint8_t *red;
 uint8_t *green;
 uint8_t *blue;
 uint8_t *transparency;
 // or packed: uint8_t *RGB, *transparency;
 size_t width;
 size_t height;
};

次に、透明度チャネルに width * height / 8 バイトを割り当てます。カラーチャネルごとに8ビットを想定すると、次のようにビットにアクセスできます。

bool get_transparency( struct bitmap* bmp, size_t x, size_t y ) {
  size_t idx = y * bmp->width + x;
  size_t tidx = idx >> 3; // = idx / 8
  uint8_t t8 = (uint8_t)( idx & 7 ); // = idx % 8
  uint8_t mask = 1 << t8;
  return ( bmp->transparency[tidx] & mask ) != 0;
}

ビットへのアクセスは最適化できます。これは単なる例です。

別の解決策:カラーチャネルの1つをスワイプし、次のように構造体を定義できます。

struct RGBPixel {
 uint8_t red : 7;
 uint8_t transparency : 1;
 uint8_t green;
 uint8_g blue;
};

赤チャネルを保存または読み取る場合、それに応じてスケーリングする必要があります。 red =(uint8_t)(((uint16_t)pix-&gt; red * 8)/ 7);

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top