【发布时间】:2014-10-24 00:04:42
【问题描述】:
问题
我正在尝试将 32x32 瓷砖从 TBitmap 复制到 TPaintbox 这是我的地图编辑器,但我似乎无法让透明度正常工作。
见下图:
注意:出于演示和测试的目的,我在 TPaintbox 下方放置了一个 TImage,这将有助于查看透明度是否有效。
如您所见,常规图块绘制正确,但应该透明的图块使用白色背景绘制。
我现在正在使用适当的类来管理我的地图和图块,以下是我尝试过的两种绘图方式:
复制矩形:
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 图像格式来制作瓦片集(屏幕截图上的左图)。 bitmap 和 png 之间的唯一区别是 CopyRect 在它是 png 时甚至难以绘制几个图块,但 BitBlt 设法绘制而没有任何明显的缺点。
无论如何,我如何将TBitmap 的一部分复制/绘制到TPaintbox 上而不会失去透明度,或者在我的情况下也不会复制白色背景?
更新 1
从下面的一些 cmets 开始,我尝试调用 AlphaBlend 函数,但这仍然会留下不良结果(注意透明区域周围的蓝色):
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;
谢谢。
【问题讨论】:
-
BitBlt、StretchBlt (CopyRect) 不支持透明度。使用 Canvas.Draw。
-
@Blobby:在 Delphi 中使用
Windows单元时也会出现同样的问题,因为Windows.TBitmap记录与Graphics.TBitmap类不同。 -
@Blobby - 是的,使用临时位图可能会影响性能。
-
我已成功使用
AlphaBlend()进行类似绘图。这也需要一个 BlendFunction 参数。在 MSDN 中有说明。