Siv3D / OpenSiv3D

C++20 framework for creative coding 🎮🎨🎹 / Cross-platform support (Windows, macOS, Linux, and the Web)
https://siv3d.github.io/
MIT License
994 stars 136 forks source link

BMPDecoder の全ビット深度対応と、それにあたっての修正 #1207

Closed Raclamusi closed 6 months ago

Raclamusi commented 6 months ago

1204 の実装です。

BMPDecoder を 1 bit 、4 bit 、および 16 bit のビット深度を持つ BMP に対応させ、すべてのビット深度に対応するようにしました。 それにあたっていくつかの修正、変更を加えました。

各コミットについて、以下で説明します。

バッファの確保に Array を使うよう変更

従来の実装では、バッファの確保に失敗した際に透明な画像を返すようになっています。 これは、よく使われている失敗時に空の Image を返すという仕様と一貫性がなく、また、そもそも std::malloc() を使用するのはナンセンスです。 そのため、バッファの確保に Array を使用するよう変更しました。

パレット用領域を色数に合わせて動的確保するよう変更

従来の実装では、8-bit BMP を読み込む際にパレットの色数を 256 色(最大)として領域をスタックに用意し、パレットデータを読み込んでいます。 しかし、実際には BMPHeader::biClrUsed の値によってパレットの色数は変化するため、常に 256 色読み込もうとすると、色数が 256 色より少ないときに画像データ領域を誤ってパレットデータとして読んでしまうことになります。 そのため、パレット用領域を BMPHeader::biClrUsed などの関連するヘッダの値によって決まる色数の分だけ Array 動的確保し、指定された分だけ読み込むよう修正しました。

BMPHeader::bfOffBits を参照するよう変更

従来の実装では、ヘッダ、パレットデータのすぐ後から画像データを読み込んでいます。 しかし、BMP 画像ファイルではヘッダ、パレットデータの後に追加情報や意味のない領域が挟まることがあります。 実際の画像データの開始位置は BMPHeader::bfOffBits により示されます。 そのため、ヘッダ、パレットデータを読み込んだ後のファイルの読み込み位置が BMPHeader::bfOffBits より小さいとき、BMPHeader::bfOffBits まで読み込み位置を変更するよう修正しました。

1-bit, 4-bit BMP に対応

1-bit, 4-bit BMP に対応しました。

16-bit BMP に対応

16-bit BMP に対応しました。 16-bit BMP は R5G5B5 形式と R5G6B5 形式がありますが、R5G5B5 形式にのみ対応しています。 R5G6B5 形式は従来の実装と同様に以下に示す条件分岐によってはじかれます。

https://github.com/Siv3D/OpenSiv3D/blob/33ec9281b6968592a6835ec1772d7571fc94228f/Siv3D/src/Siv3D/ImageFormat/BMP/BMPDecoder.cpp?ts=4#L93-L97

不正なビット深度に対して失敗ログを出すよう変更

不正なビット深度の BMP を読み込んだとき、失敗ログを出力して空の Image を返すよう変更しました。 このコードに到達した際、既に確保した Image が無駄になりますが、滅多にないことなので目をつぶりました。

末尾の空白を削除

気になったので、末尾の空白を削除しました。

Reputeless commented 6 months ago

ありがとうございます! v0.6.15 での実装に向け確認を進めます。

Reputeless commented 6 months ago

この BMP デコーダ、Siv3D とは独立して、BMP のロードに特化した 1 つの C or C++ ヘッダオンリーライブラリとして公開・メンテすると需要がありそうだなと思いました。

分かりやすい名前と README, ベンチマーク等を用意すれば、長期的に star を稼げるリポジトリになりそうです。

みたいな API が提供されれば、Siv3D から使いたいです。

調べてみると BMP のフォーマットは本当に種類が多いんですね。X4R4G4B4 みたいなのも見かけました。マイナーなものも含めて網羅性を表でアピールすると、使われるライブラリになると思います。

Reputeless commented 6 months ago

Merged. Great job!