24ビットのrgbビットマップファイルで、サイズが画像の幅に依存するパディングを追加する必要がある理由を誰かが説明してくれませんか? 何のために ?
つまり、このコードを自分のプログラムに (C で) 追加する必要があります。
if( read % 4 != 0 ) {
read = 4 - (read%4);
printf( "Padding: %d bytes\n", read );
fread( pixel, read, 1, inFile );
}
24 ビットは奇数のバイト (3) であり、さまざまな理由から、すべてのイメージ行は 4 バイトの倍数であるアドレスから開始する必要があるためです。
Wikipediaによると、ビットマップ ファイル形式は次のように指定されています。
ビットマップ ピクセルを表すビットは、行にパックされます。各行のサイズは、パディングによって 4 バイト (32 ビット DWORD) の倍数に切り上げられます。行の長さを 4 バイトの倍数にするために、パディング バイト (必ずしも 0 ではない) を行の末尾に追加する必要があります。ピクセル配列がメモリにロードされるとき、各行は 4 の倍数であるメモリ アドレスで開始する必要があります。このアドレス/オフセットの制限は、メモリにロードされたピクセル配列に対してのみ必須です。ファイル ストレージの目的で、各行のサイズのみが 4 バイトの倍数である必要がありますが、ファイル オフセットは任意に設定できます。Width=1 の 24 ビット ビットマップには、行ごとに 3 バイトのデータ (青、緑、赤) と 1 バイトのパディングがあり、Width=2 の場合は 2 バイトのパディングがあり、Width=3 の場合は 3 バイトのパディングがあります。パディング、および Width=4 にはパディングがまったくありません。
Data Structure Paddingに関するウィキペディアの記事も興味深い読み物であり、コンピュータ サイエンスで一般的にパディングが使用される理由を説明しています。
これは、それほど多くのスペースを無駄にせずに、より良いメモリパターンに合わせるための設計上の決定であったと思います (319px 幅の画像の場合、3 バイトまたは 0.25% を無駄にすることになります)。
奇数行に直接アクセスする必要があるとします。次のようにして、n 番目の行の最初の 4 ピクセルにアクセスできます。
uint8_t *startRow = bmp + n * width * 3; //3 bytes per pixel
uint8_t r1 = startRow[0];
uint8_t g1 = startRow[1];
//... Repeat
uint8_t b4 = startRow[11];
nとwidthが奇数 (およびbmpが偶数) の場合、startRowは奇数になることに注意してください。
次の高速化を試みた場合:
uint32_t *startRow = (uint32_t *) (bmp + n * width * 3);
uint32_t a = startRow[0]; //Loading register at a time is MUCH faster
uint32_t b = startRow[1]; //but only if address is aligned
uint32_t c = startRow[2]; //else code can hit bus errors!
uint8_t r1 = (a & 0xFF000000) >> 24;
uint8_t g1 = (a & 0x00FF0000) >> 16;
//... Repeat
uint8_t b4 = (c & 0x000000FF) >> 0;
あなたは多くの問題に遭遇するでしょう。最良のシナリオ (インテル CPU)では、 startRow は 4 で割り切れないため、 a 、 b 、および c のすべてのロードを 2 つのロードに分割する必要があります。最悪のシナリオ (例: sun sparc) では、プログラムがクラッシュします。「バスエラー」。
新しい設計では、行を少なくとも L1 キャッシュ ライン サイズ (intel では 64 バイト、nvidia gpus では 128 バイト) に揃えるのが一般的です。
各行の最後にパディングがあるかどうかは、フォーマットによって異なります。
とにかく I/O はバイト指向であるため、3 x 8 ビット チャネル イメージを使用する理由はあまりありません。ピクセルが 1 バイト未満 (たとえば 1 ビット/ピクセル) にパックされたイメージの場合、各行がバイト オフセットで始まるようにパディングが役立ちます。