256色以下のビットマップをTBitmapで読み込み/保存を行うと、ビットマップが破損することがある

提供: Support
移動先: 案内検索

対象となるIDE製品

  • Delphi/C++Builder/RAD Studio 10 Seattle以降

問題

256色以下のビットマップファイルをTBitmapで読み込んで、PixelFormatプロバティを32ビット(フルカラー)に変更し、ファイルを保存すると、ビットマップが破損することがあります。


ビットマップが破損する症状が再現するコード例は、以下の通りです。

procedure TForm1.Button1Click(Sender: TObject);
var
  Bitmap : TBitmap;
begin
  Bitmap := TBitmap.Create;
  Bitmap.LoadFromFile('test.Bitmap'); // 256色のビッドマップを読み込む

  Bitmap.PixelFormat := pf32bit; // フルカラーに変更
  Bitmap.SaveToFile('test1.Bitmap'); 

  Bitmap.LoadFromFile('test1.Bitmap'); 
  Bitmap.SaveToFile('test2.Bitmap');
  Bitmap.LoadFromFile('test2.Bitmap');
  image1.Picture.Assign(Bitmap);
  Bitmap.Free;
end;

解決

10 Seattle以降でVcl.GraphicsユニットのTBitmap.ReadDIBメソッドが変更されており、修正箇所に不具合があり、適切にカラーパレットが適用されません。


本件の回避策としては、主に2つの方法があります。

  1. 256色以下の元の画像ファイルを24ビット以上のビットマップへ変換する
    TBitmapで読み込むオリジナルの画像ファイル(256色以下)を、ペイントツールなどを利用して事前に24ビット以上のビットマップ形式に変換しておくと、同じ手順でTBitmapを利用して読み込み/保存を行ってもビットマップは破損しません。
  2. Vcl.GraphicsユニットのTBitmap.ReadDIBメソッドの実装コードを修正する
    Vcl.Graphics.pasのソースコードをエディタで開いて、以下の箇所を直接修正してください。
    <修正前>
    procedure TBitmap.ReadDIB(Stream: TStream; ImageSize: LongWord; bmf: PBitmapFileHeader);
    ..
    ..
    if (bmiHeader.biBitCount > 8) and (bmiHeader.biBitCount <= 16) and 
    (bmiHeader.biClrUsed > 0) and (Pal = 0)then
    ..
    
    <修正後>
    procedure TBitmap.ReadDIB(Stream: TStream; ImageSize: LongWord; bmf: PBitmapFileHeader);
    ..
    ..
    if ((bmiHeader.biBitCount > 8) and (bmiHeader.biBitCount <= 16) or (bmiHeader.biBitCount = 32)) and  
    (bmiHeader.biClrUsed > 0) and (Pal = 0)then
    ..
    
    修正したVcl.Graphics.pasの適用方法は、以下のドキュメントを参照してください。
    <注意点>:2の方法でVcl.Graphicsのソースコードを修正した場合、その修正が反映されるのアプリケーションの実行時のみです。もしRAD Studio IDEのVCLフォームデザイナで設計時にビットマップの割り当てを行っている場合はこの修正は反映されませんので、ご注意ください。


本件の修正は、RAD Studio 11.1(11 Update1)を予定しております。