首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我在打电话给BitBlt或CopyRect时失去了透明度?

为什么我在打电话给BitBlt或CopyRect时失去了透明度?
EN

Stack Overflow用户
提问于 2014-08-29 23:11:40
回答 1查看 2.9K关注 0票数 5

问题

我正在尝试将32x32块从TBitmap复制到TPaintbox中,这是我的地图编辑器,但我似乎无法使透明度正常工作。

见下图:

注意:为了演示和测试的目的,我在TPaintbox下面放置了一个TPaintbox,这将有助于查看透明度是否有效。

正如您所看到的,常规瓷砖的绘制是正确的,但是应该透明的瓷砖是用白色的背景绘制的。

我现在正在使用适当的类来管理我的地图和瓷砖,下面是我尝试绘制的两种方法:

CopyRect:

代码语言:javascript
复制
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

代码语言:javascript
复制
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图像格式的tileset (屏幕截图上的左图像)。位图和png之间唯一的区别是,当CopyRect是png时,它甚至很难画出几块瓷砖,但是BitBlt设法画的没有任何明显的缺点。

无论如何,如何在不丢失透明度的情况下将TBitmap的一部分复制/绘制到TPaintbox上,或者在我的情况下不复制白色背景?

更新1

根据下面的一些注释,我尝试调用了AlphaBlend函数,但这仍然留下了不理想的结果(请注意透明区域周围的蓝色):

代码语言:javascript
复制
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;

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2016-12-07 22:36:28

有三种常用的使用透明位图的方法,前两种使用标准Delphi工具,第三种需要第三方库:

如果使用两种标准方法之一,则不要使用BitBlt或CopyRect。使用透明图像保持架的绘制方法在目标画布上绘制。

  1. 将透明位图保存在TImageList中,并使用TImageList.Draw直接在目标画布上绘制(不要在中间位图上绘制,因为这里会丢失透明度)。若要在设计时将图像添加到图像列表中,请右击并选择“图像列表编辑器”。列表中的图像可能是位图、图标、PNG、GIF和JPEG图像: TImage支持的任何图像类型。ImageLists还支持32位格式,因此alpha混合位图和PNG文件工作正常.您还可以在运行时加载图像。如果位图以非透明形式存储,但存在透明颜色,则可以使用TImageList.AddMasked(Bitmap: TBitmap;MaskColor: TColor)方法。您可以自己在第二个参数中传递透明颜色,也可以通过clDefault让图像列表获取左下角像素的颜色。
  2. 将图像保存在PNG文件或资源中,并将它们加载到Vcl.Imaging.pngimage.TpngImage中,然后调用TpngImage.Draw在目标画布上直接绘制PNG。如前所述,不要在中间位图上涂鸦,因为你在这里会失去透明度。
  3. 使用TBitmap32来自GR32,一个第三方库.在这种情况下,不要使用带有透明图像的TBitmap32直接在HDC、画布或TBitmap上绘图。使用dmBlend和DrawTo或BlockTransfer()来绘制另一个TBitmap32。例如,要在TBitmap上透明地绘制,创建一个中间缓存TBitmap32:(1)将图像从TBitmap复制到缓存TBitmap32;(2)使用DrawTo或BlockTransfer()将透明图像应用到缓存TBitmap32,避免使用画布或HDC混合两个图像,因为它们丢失了alpha层信息;(3)将图像从缓存TBitmap32复制回TBitmap。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25577387

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档