简体   繁体   English

Delphi:GR32在不清除其内容的情况下将带有Alpha的PNG绘制到TBitmap32上

[英]Delphi: GR32 draw a PNG with alpha onto a TBitmap32 without clearing its content

After going through several other related questions I couldn't come up with a working code for this, so please spare the "duplicate question" tags. 经历了其他几个相关问题之后,我无法为此提供有效的代码,因此请保留“重复问题”标签。

Given a PNG image with either per-pixel alpha channel or single-color transparency, I need code to draw it onto a TBitmap32 which already contains an image (some drawing goes on before the PNG part). 给定具有每个像素Alpha通道或单色透明性的PNG图像,我需要代码将其绘制到已经包含图像的TBitmap32上(在PNG部件之前进行一些绘制)。 So let's say my TBitmap32 is 200x200, I do some drawing on it, then I want to ~insert a smaller transparent PNG image on top of its current content, transparently according to the PNG's alpha channel data or single-color alpha. 假设我的TBitmap32是200x200,我在上面做了一些绘图,然后我想根据其PNG的Alpha通道数据或单色Alpha透明地在其当前内容之上插入一个较小的透明PNG图像。

Uses pngimage, GR32;

procedure TForm1.Button1Click(Sender: TObject);
Var b: TBitmap;
    b32: TBitmap32;
    p: TPngImage;
begin
  b   := TBitmap.Create;
  b32 := TBitmap32.Create;
  p   := TPngImage.Create;

  // 50x50 PNG
  p.LoadFromFile('z:\test2.png');

  b.Width    := 200;
  b.Height   := 200;
  b32.Width  := 200;
  b32.Height := 200;
  // some drawing happens on the b32~

  // insert code here to draw the png onto the b32, on top of
  // what's already drawn, and at specific coordinates i.e 10,10


  /////////////////////////////

  b32.DrawTo(b.Canvas.Handle,0,0);
  Canvas.Draw(0,0,b);

  p.Free;
  b32.Free;
  b.Free;
end;

Original PNG: 原始PNG:

在此处输入图片说明

Results so far: 到目前为止的结果:

在此处输入图片说明

There are two ways of working with transparent PNG files: 有两种使用透明PNG文件的方式:

  1. Load them into intermediary TBitmap32 bitmaps and then manipulate these TBitmap32 bitmaps. 将它们加载到中间的TBitmap32位图中,然后操作这些TBitmap32位图。
  2. Use TPngImage.Draw (implemented in Vcl.Imaging.pngimage with Delphi XE2 and later) directly on target Canvas, as you have pointed out. 如您所指出的,直接在目标Canvas上使用TPngImage.Draw(在Delphi XE2和更高版本的Vcl.Imaging.png图像中实现)。

The second way is preferable when it comes to transparency, because the code that you may find to load a PNG into TBitmap32 may work incorrectly. 关于透明度,第二种方法更可取,因为您可能会发现将PNG加载到TBitmap32中的代码可能无法正常工作。 Here are the two examples of the incorrect code that is used most frequently: 这是两个最常使用的错误代码的示例:

(1) “LoadPNGintoBitmap32” from http://graphics32.org/wiki/FAQ/ImageFormatRelated - it applies the transparency twice, so the images with alpha values other than 0 or 255 will look differently than in other software (most noticeable on translucent images with glass effects). (1)来自http://graphics32.org/wiki/FAQ/ImageFormatRelated的 “ LoadPNGintoBitmap32”-它两次应用透明度,因此alpha值不是0或255的图像看起来与其他软件有所不同(在半透明状态下最明显)具有玻璃效果的图像)。 This code will first apply alpha to RGB and then sets alpha, so when you pain, alpha will be applied again. 该代码将首先将alpha应用于RGB,然后设置alpha,因此当您感到痛苦时,将再次应用alpha。 You can find more information on this issue here: Delphi, GR32 + PngObject: converting to Bitmap32 doesn't work as expected . 您可以在此处找到有关此问题的更多信息: Delphi,GR32 + PngObject:转换为Bitmap32不能正常工作 Besides that, it doesn't convert correctly transparency from paletted images into the alpha layer of TBitmap32, for example, all white pixels become transparent. 除此之外,它不能将调色板图像的透明度正确转换为TBitmap32的alpha层,例如,所有白色像素都变为透明。

(2) “LoadBitmap32FromPNG” from gr32ex library: https://code.google.com/archive/p/gr32ex/ - a slightly different implementation of the same algorithm as (1), and has the same issues as (1). (2)来自gr32ex库的“ LoadBitmap32FromPNG”: https : //code.google.com/archive/p/gr32ex/-与(1)相同算法的实现略有不同,并且与(1)相同。

If you still prefer using TBitmap32, make the following sequence of steps: 如果仍然喜欢使用TBitmap32,请执行以下步骤序列:

  1. Make sure your code correctly converts PNG to TBitmap32. 确保您的代码正确将PNG转换为TBitmap32。
  2. Do not use TBitmap32 with transparent images to draw directly on HDC, Canvas or TBitmap. 请勿将TBitmap32与透明图像一起使用,以直接在HDC,Canvas或TBitmap上绘制。 Use dmBlend and DrawTo or BlockTransfer() to draw on another TBitmap32. 使用dmBlend和DrawTo或BlockTransfer()在另一个TBitmap32上绘制。 For example, to draw transparently on a TBitmap, create an intermediary cache TBitmap32: 例如,要在TBitmap上透明地绘制,请创建一个中间缓存TBitmap32:
    1. Copy the image from TBitmap to the cache TBitmap32; 将图像从TBitmap复制到缓存TBitmap32;
    2. Apply your transparent image to the cache TBitmap32 using DrawTo or BlockTransfer(), avoid using Canvas or HDC to mix two images because they lose alpha layer information; 使用DrawTo或BlockTransfer()将透明图像应用于缓存TBitmap32,避免使用Canvas或HDC混合两个图像,因为它们会丢失alpha层信息;
    3. Copy the image back from the cache TBitmap32 to your TBitmap. 将图像从缓存TBitmap32复制回您的TBitmap。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM