問題は、PNGが誤ってTBitmap32に変換され、転送中に透明度情報が失われたことである可能性があります。これは、パレット化されたPNG画像の一般的なケースです。それ以外の場合は、「Bitmap.DrawMode:=dmTransparent」と「OuterColor」を使用する必要はありません。PNGからの透明度情報がTBitmpa32に正しく転送された場合、OuterColorを設定しなくても、DrawMode:=dmBlendが機能します。
最も重要なのは、PNGをTBitmap32にどのようにロードしたかです。Vcl.Imaging.pngimageユニット(Delphi XE2以降で実装)のTPngImageは、ビットマップ上に透過的に描画し、そのビットマップ上にあったものを保持したり、PNGアルファレイヤーを使用して色を組み合わせたりすることができますが、さまざまなものを簡単に変換することはできません。 TBitmap32の各ピクセルのアルファコンポーネントへのPNG透明度(パレットを含む)のフォーマット。TPngImageが画像を描画すると、ピクセルごとに結合されたRGBが取得されますが、アルファコンポーネントはターゲットビットマップに転送されません。
PNGを透過性のあるTBitmap32にロードしようとするヘルパールーチンが利用可能ですが、欠点があります。
(1) http://graphics32.org/wiki/FAQ/ImageFormatRelatedの「LoadPNGintoBitmap32」
-透明度を2回適用するため、アルファ値が0または255以外の画像は、他のソフトウェアとは異なって見えます(半透明で最も目立ちます)ガラス効果のある画像)。このコードは、最初にアルファをRGBに適用し、次にアルファを別のレイヤーとして設定するため、ペイントすると、アルファが再度適用されます。この問題の詳細については、こちらをご覧ください:Delphi、GR32 + PngObject:Bitmap32への変換が期待どおりに機能しない
。その上、パレット画像からTBitmap32のアルファレイヤーに透明度を正しく変換しません。RGBにレンダリングする前に、出力ビットマップの特定の色(RGBにレンダリング)のピクセルにアルファ透明度を手動で設定するため、すべての白いピクセルが透明になると、サンプル画像のように実際の透明度が失われます。
(2)gr32exライブラリの「LoadBitmap32FromPNG」:https ://code.google.com/archive/p/gr32ex/-
(1)と同じアルゴリズムのわずかに異なる実装であり、(1)と同じ問題があります。
したがって、解決策は次のとおりです。
- TBitmap32を使用しないでください。Vcl.Imaging.pngimage.TPngImageを使用して、ターゲットのビットマップ(画面など)に直接描画します。これは、さまざまなPNG形式を正しく処理する最も互換性のある方法です。
- ヘルパールーティングを使用して、透明度情報をVcl.Imaging.pngimage.TPngImageからTBitmap32に転送します。
- PNGをTBitmap32にネイティブにロードできるGR32PNGライブラリを使用してくださいhttps://sourceforge.net/projects/gr32pnglibrary/
この問題に関するすべての情報が揃っているので、適切な解決策が得られる可能性があります。
アルファレイヤーを1回のパスでロードする方法
ハインリッヒ・ウルブリヒトは、痛みを感じる前に透明層を取り除き、画像をもう一度読むことを提案しました。画像が2回読み込まれないようにするには、PNGObject.RemoveTransparencyを呼び出す前にアルファレイヤーを保存します。これは、アルファレイヤーを正しく適用し、画像を1回だけロードするコードです。残念ながら、パレット画像では機能しません。パレット画像からTBitmap32のアルファレイヤーを正しく塗りつぶす方法を知っている場合は、Transparent Png to TBitmap32で説明されている効果なしで、私に知らせてください。
procedure LoadPNGintoBitmap32(DstBitmap: TBitmap32; SrcStream: TStream; out AlphaChannelUsed: Boolean);
var
PNGObject: TPngImage;
PixelPtr: PColor32;
AlphaPtr: PByte;
SaveAlpha: PByte;
I, AlphaSize: Integer;
begin
AlphaChannelUsed := False;
PNGObject := TPngImage.Create;
try
PNGObject.LoadFromStream(SrcStream);
AlphaPtr := PByte(PNGObject.AlphaScanline[0]);
if Assigned(AlphaPtr) then
begin
AlphaSize := PNGObject.Width * PNGObject.Height;
if AlphaSize <= 0 then raise Exception.Create('PNG files with zero dimensions are not supported to be loaded to TBitmap32');
GetMem(SaveAlpha, AlphaSize);
try
Move(AlphaPtr^, SaveAlpha^, AlphaSize);
PNGObject.RemoveTransparency;
DstBitmap.Assign(PNGObject);
DstBitmap.ResetAlpha;
PixelPtr := PColor32(@DstBitmap.Bits[0]);
AlphaPtr := SaveAlpha;
for I := 0 to AlphaSize-1 do
begin
PixelPtr^ := (PixelPtr^ and $00FFFFFF) or (TColor32(AlphaPtr^) shl 24);
Inc(PixelPtr);
Inc(AlphaPtr);
end;
finally
FreeMem(SaveAlpha, AlphaSize);
end;
AlphaChannelUsed := True;
end else
if PNGObject.TransparencyMode = ptmNone then
begin
DstBitmap.Assign(PNGObject);
end else
begin
raise Exception.Create('Paletted PNG images are not supported in LoadPNGintoBitmap32, transparency cannot be stored to TBitmap32');
end;
finally
FreeAndNil(PNGObject);
end;
end;