簡體   English   中英

從資源文件加載的透明 PNG 圖像,使用 Grapics32 調整大小並在畫布上繪制

[英]Transparent PNG image loaded from resource file, resized with Grapics32 and drawn on the Canvas

我需要一點幫助...

我的應用程序資源中有一個透明的 PNG 圖像。 到目前為止,我將它加載到TPngImage並使用Canvas.Draw(X, Y, PngImage);在屏幕上繪制它Canvas.Draw(X, Y, PngImage); . 而且是透明繪制的。 現在我將我的應用程序更新為 DpiAware,我需要縮放所有圖像。 我需要一個高質量的重采樣器,我選擇使用 Graphics32。 我設法進行了重新采樣,但我不知道如何保持透明度......我嘗試了所有我能想到的......以下代碼的結果是在透明區域用黑色繪制的圖像...... .

Foto32, Buff: TBitmap32;
FotoPng: TPngImage;

constructor TForm.Create(AOwner: TComponent);
const BkgHeight = 380;
var Res: TKernelResampler;
    SRect, DRect: TRect;
    ImgWidth: Integer;
begin
 inherited;
 Buff:= TBitmap32.Create;
 Res:= TKernelResampler.Create;
 Res.Kernel:= TLanczosKernel.Create;

 FotoPng:= TPngImage.Create;
 FotoPng.Transparent:= True;
 FotoPng.TransparentColor:= clBlack;
 FotoPng.LoadFromResourceName(HInstance, 'BKG_FOTO');
 Foto32:= TBitmap32.Create;
 Foto32.DrawMode:= dmBlend;
 Foto32.CombineMode:= cmMerge;
 Foto32.OuterColor:= clBlack;
 Foto32.Canvas.Brush.Style:= bsClear;
 Foto32.SetSize(FotoPng.Width, FotoPng.Height);
 FotoPng.Draw(Foto32.Canvas, Rect(0, 0, FotoPng.Width, FotoPng.Height));

 ImgWidth:= Round(Real(Foto32.Width / Foto32.Height) * BkgHeight);
 SRect:= Rect(0, 0, Foto32.Width, Foto32.Height);
 Buff.DrawMode:= dmBlend;
 Buff.CombineMode:= cmMerge;
 Buff.OuterColor:= clBlack;
 Buff.Canvas.Brush.Style:= bsClear;
 Buff.SetSize(Scale(ImgWidth), Scale(BkgHeight));
 DRect:= Rect(0, 0, Buff.Width, Buff.Height);
 Res.Resample(Buff, DRect, DRect, Foto32, SRect, dmTransparent {dmBlend}, nil);
end;

procedure TForm.Paint;
begin
 // ....
 Buff.DrawTo(Canvas.Handle, X, Y);
end;

這是我編譯成資源的透明PNG圖片: https : //postimg.cc/3yy3wrJB

我在這里發現了一個類似的問題,但我沒有將圖像與TImage一起使用,而是直接在畫布上繪制它。 在唯一的答案中,大衛說:

無論如何,如果是這樣,我會將 TImage 的透明度支持與 TBitmap32 的重采樣能力結合起來,以這種方式構建解決方案。 將原始圖像保存在 TBitmap32 實例中。 每當您需要將其加載到 TImage 組件中時,例如重新調整大小時,請使用 TBitmap32 執行內存中調整大小並加載重新調整大小的圖像。

這正是我想要做的,但我不知道為什么透明度不起作用。 有任何想法嗎 ?

您的問題似乎是將緩沖區繪制到屏幕上的問題。 Bitmap32 使用StretchDIBits進行繪畫,它忽略了 alpha 通道。

您可以使用AlphaBlend函數來繪制圖像:

procedure TForm1.FormPaint(Sender: TObject);
var
  BF: TBlendFunction;
begin
  BF.BlendOp := AC_SRC_OVER;
  BF.BlendFlags := 0;
  BF.SourceConstantAlpha := 255;
  BF.AlphaFormat := AC_SRC_ALPHA;

  Winapi.Windows.AlphaBlend(Canvas.Handle, 0, 0, Buff.Width, Buff.Height,
    Buff.Canvas.Handle, 0, 0, Buff.Width, Buff.Height, BF);
end;

或者將您的 TBitmap32 轉換為 Delphi TBitmap 並使用 VCL 繪制它:

procedure TForm1.FormPaint(Sender: TObject);
var
  Bmp: TBitmap;
  I: Integer;
begin
  Bmp := TBitmap.Create;
  try
    Bmp.PixelFormat := pf32bit;
    Bmp.AlphaFormat := afDefined;
    Bmp.SetSize(Buff.Width, Buff.Height);
    for I := 0 to Buff.Height - 1 do
      Move(Buff.ScanLine[I]^, Bmp.ScanLine[I]^, Buff.Width * 4);
    Canvas.Draw(0, 0, Bmp);
  finally
    Bmp.Free;
  end;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM