Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 7 commits into from
Feb 24, 2024

Conversation

Raclamusi
Copy link
Member

#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 形式は従来の実装と同様に以下に示す条件分岐によってはじかれます。

if (header.biCompression)
{
LOG_FAIL(U"❌ BMPDecoder::decode(): Compressed BMP is not supported");
return{};
}

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

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

末尾の空白を削除

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

@Reputeless
Copy link
Member

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

@Reputeless
Copy link
Member

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

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

  • LoadInfoFromMemory(const unsigned char* memory)
  • LoadImageFromMemory(const unsigned char* memory, unsigned char* pixels)

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

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

@Reputeless Reputeless merged commit a5a6d7b into Siv3D:v6_develop Feb 24, 2024
2 checks passed
@Reputeless
Copy link
Member

Merged. Great job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

2 participants