|
私の環境では、platformがWin64、透過色に標準色(clWhiteやclRedなど)を指定すると透過GIFの作成方法で示したコードでは透過GIFになりませんでした。正確には、Windows7やFireFoxで透過GIFとして扱ってもらえませんでした(フォトレタッチソフトJTrimでは透過GIFとして表示されました)。これは、TGIFGraphicControlExtensionをCreateする前にTGIFImage.OptimizeColorMapを追記することで正常な透過GIFになります。
USES ・・・, Vcl.ExtCtrls, Vcl.Imaging.GIFImg;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Image1: TImage;
private
・
・
・
procedure TForm1.ReadAndSaveTransGif;
var GIFImage : TGIFImage;
GCE : TGIFGraphicControlExtension;
begin
Image1.Picture.LoadFromFile(イメージファイルのパス);
GIFImage := TGIFImage.Create;
try
GIFImage.Assign(Image1.Picture.Graphic);
GIFImage.OptimizeColorMap; // GIFフレームのカラーマップの最適化
GCE := TGIFGraphicControlExtension.Create(GIFImage.Images[0]);
GCE.Transparent := True;
GCE.TransparentColor := GIFImage.Bitmap.Canvas.Pixels[0,GIFImage.Bitmap.Height-1];
GIFImage.SaveToFile(GIFファイルのパス);
finally
FreeAndNil(GIFImage);
end;
end;
まだ完全に原因をつかめていませんが、上記で解決する理由は次のとおりです。
透過色を設定する際にTGIFGraphicControlExtension.TransparentColorに値を代入すると、内部では代入した値に相当するカラーマップのインデックスをTGIFColorMap.AddUnique関数で検索し、そのインデックスをTransparentColorIndexプロパティに設定します。また、platformがWin64の時、GIFImage.Images[0]フレームのカラーマップに標準色が重複して登録されます。さらに、デフォルト状態ではカラーマップが整列しておらず(OptimizedプロパティがFalse)、この場合、、TGIFColorMap.AddUnique関数のIndexOf関数でインデックスが大きい方から透過色と同じ色を探します。そのため、より若いインデックスに透過色があっても、大きい方のインデックスをTransparentColorIndexに保持してしまいます。どうもこの状態ではWindows7などで透過GIFと認識されないようです。TGIFImage.OptimizeColorMap手続きを実行すると、カラーマップ内で重複する色をマージして整列します。これにより正常な透過GIFと認識されるようです。
上のコードでは、TGIFImageのOptimizeColorMap手続きを呼んでいますが、TGIFImage.Optimize手続きでも同様に機能します。その際、第1引数(Options)にooMergeを指定する必要があります。他に似た手続きにTGIFColorMap.Optimizeがありますが、透過GIFにならないことがありました。
OptimizeColorMap手続きは内部で色のマージや並べ替えなど比較的多くの処理をします。それを避けたいならば、カラーマップが重複し、且つOptimizedプロパティがFalseでも最も若いインデックスをTransparentColorIndexに設定するようにしても解決します。そのためには、以下のような自前でカラーマップを検索する関数を用意すればよいでしょう。
USES ・・・, Vcl.ExtCtrls, Vcl.Imaging.GIFImg;
type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
Image1: TImage;
private
function TransColorIndexOf(TransparentCol:TColor; GIFMapCol:TGIFColorMap):Integer;
・
・
・
function TForm1.TransColorIndexOf(TransparentCol:TColor; GIFMapCol:TGIFColorMap):Integer;
begin
Result := 0;
while Result < GIFMapCol.Count do
begin
if TransparentCol = GIFMapCol[Result] then
break;
Inc(Result);
end;
end;
procedure TForm1.ReadAndSaveTransGif;
var GIFImage : TGIFImage;
GCE : TGIFGraphicControlExtension;
Index: Integer;
begin
Image1.Picture.LoadFromFile(イメージファイルのパス);
GIFImage := TGIFImage.Create;
try
GIFImage.Assign(Image1.Picture.Graphic);
GCE := TGIFGraphicControlExtension.Create(GIFImage.Images[0]);
GCE.Transparent := True;
Index := TransColorIndexOf(GIFImage.Bitmap.Canvas.Pixels[0,GIFImage.Bitmap.Height-1],
GIFImage.Images[0].ColorMap);
if Index < GIFImage.Images[0].ColorMap.Count then
GCE.TransparentColorIndex := Index
else
GIFImage.Images[0].Add(GIFImage.Bitmap.Canvas.Pixels[0,GIFImage.Bitmap.Height-1]); // Indexが見つからない場合の処理
GIFImage.SaveToFile(GIFファイルのパス);
finally
FreeAndNil(GIFImage);
end;
end;
上のコードではIndex変数に一度透過色のインデックスを保存し、もし透過色がカラーマップに見つかれない場合はカラーマップに透過色を追加しています。これはTGIFColorMap.AddUnique関数と同等の処理です。
|