为什么在调用BitBlt或CopyRect时会失去透明度? [英] Why am I losing transparency when calling BitBlt or CopyRect?
问题描述
问题
我正在尝试将32x32瓦片从TBitmap
复制到TPaintbox
,这是我的地图编辑器,但是我似乎无法使透明度正常工作.
I am trying to copy 32x32 tiles from a TBitmap
into a TPaintbox
which is my map editor, but I cannot seem to get the transparency working correctly.
查看下图:
注意:出于演示和测试的目的,我在TPaintbox下方放置了一个TImage,这将有助于查看透明度是否正常工作.
如您所见,常规图块可以正确绘制,但是应该透明的图块是用白色背景绘制的.
As you can see, regular tiles draw correctly, but the tiles that should be transparent are drawn with a white background.
我现在正在使用适当的类来管理地图和图块,下面是尝试绘制的两种方法:
I am now using proper classes to manage my maps and tiles, and below is two ways I have tried drawing:
CopyRect:
procedure TMap.DrawTile(Tileset: TBitmap; MapX, MapY, TileX, TileY: Integer;
MapCanvas: TCanvas);
begin
if TileIsFree(MapX, MapY) then
begin
MapCanvas.CopyRect(
Rect(MapX, MapY, MapX + fTileWidth, MapY + fTileHeight),
Tileset.Canvas,
Rect(TileX, TileY, TileX + fTileWidth, TileY + fTileHeight));
end;
end;
BitBlt
procedure TMap.DrawTile(Tileset: TBitmap; MapX, MapY, TileX, TileY: Integer;
MapCanvas: TCanvas);
begin
if TileIsFree(MapX, MapY) then
begin
BitBlt(
MapCanvas.Handle,
MapX,
MapY,
fTileWidth,
fTileHeight,
Tileset.Canvas.Handle,
TileX,
TileY,
SRCCOPY);
end;
end;
我已经尝试过使用图块集的位图和png图像格式(屏幕截图中的左图).位图和png之间的唯一区别是CopyRect
在为png时甚至很难绘制几个图块,但是BitBlt
设法绘制时没有任何明显的缺点.
I have tried using bitmap and png image formats for the tileset (left image on the screenshot). The only difference between bitmap and png is that CopyRect
struggles to draw even a few tiles when it is a png, but BitBlt
manages to draw without any obvious drawbacks.
无论如何,如何在不丢失透明度的情况下将TBitmap
的一部分复制/绘制到TPaintbox
上,或者在我的情况下也没有复制白色背景?
Anyway, how do I copy/draw part of a TBitmap
onto a TPaintbox
without losing transparency, or in my case without also copying the white background?
更新1
在下面的一些评论之后,我尝试调用AlphaBlend
函数,但这仍然留下不良的结果(请注意透明区域周围的蓝色):
Following on from some of the comments below I have tried calling the AlphaBlend
function but this still leaves undesirable results (note the blue colors around the transparent areas):
procedure TMap.DrawTile(Tileset: Graphics.TBitmap; MapX, MapY, TileX, TileY: Integer;
MapCanvas: TCanvas);
var
BlendFn: TBlendFunction;
begin
if TileIsFree(MapX, MapY) then
begin
BlendFn.BlendOp := AC_SRC_OVER;
BlendFn.BlendFlags := 0;
BlendFn.SourceConstantAlpha := 255;
BlendFn.AlphaFormat := AC_SRC_ALPHA;
AlphaBlend(
MapCanvas.Handle,
MapX,
MapY,
fTileWidth,
fTileHeight,
Tileset.Canvas.Handle,
TileX,
TileY,
fTileWidth,
fTileHeight,
BlendFn);
end;
end;
谢谢.
推荐答案
有3种流行的方法可用于透明位图,前两种使用标准的Delphi工具,第三种需要第三方库:
There are 3 popular ways to work with transparent bitmaps, first two use standard Delphi tools and the third one requires a third-party library:
如果您使用两种标准方法之一,请不要使用BitBlt或CopyRect.使用透明图像固定器的Draw方法在目标画布上绘制.
If you use one of the two standard methods, don’t use BitBlt or CopyRect. Use the Draw method of the transparent image holder to draw on destination canvas.
- 将透明位图保留在TImageList中,并使用TImageList.Draw直接在目标画布上绘制(不要在中间位图上绘制,因为您将在此处失去透明度).要在设计时将图像添加到图像列表,请右键单击并选择图像列表编辑器".列表中的图像可能是位图,图标,PNG,GIF和JPEG图像:TImage支持的任何图像类型. ImageLists还支持32位格式,因此Alpha混合位图和PNG文件可以正常工作.您也可以在运行时加载图像.如果您的位图以非透明形式存储,但是有透明颜色,则可以使用TImageList.AddMasked(Bitmap:TBitmap; MaskColor:TColor)方法.您可以自己在第二个参数中传递透明颜色,也可以通过clDefault来使图像列表采用左下像素的颜色.
- 将图像保留在PNG文件或资源中,并将其加载到Vcl.Imaging.pngimage.TpngImage中,然后调用TpngImage.Draw将PNG直接绘制在目标画布上.如上所述,请勿在中间位图上绘画,因为您将在此处失去透明度.
- 使用第三方库GR32中的TBitmap32.在这种情况下,请勿将TBitmap32与透明图像一起直接在HDC,Canvas或TBitmap上绘制.使用dmBlend和DrawTo或BlockTransfer()在另一个TBitmap32上绘制.例如,要在TBitmap上透明地绘制,请创建一个中间缓存TBitmap32:(1)将图像从TBitmap复制到缓存TBitmap32; (2)使用DrawTo或BlockTransfer()将透明图像应用于缓存TBitmap32,避免使用Canvas或HDC混合两个图像,因为它们会丢失alpha层信息; (3)将图像从缓存TBitmap32复制回TBitmap.
这篇关于为什么在调用BitBlt或CopyRect时会失去透明度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!