为什么在调用BitBlt或CopyRect时会失去透明度? [英] Why am I losing transparency when calling BitBlt or CopyRect?

查看:173
本文介绍了为什么在调用BitBlt或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.

  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. 使用第三方库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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆