Alphablend 和透明Blt

2024-03-22

这个问题与我有关先前的问题 https://stackoverflow.com/q/12700165/62576 on SO.

我想组合两个图层,并仅将 alpha 应用于源图层的特定部分。我尝试的一种方法是将 SourceConstantAlpha 设置为 $ff (并让该函数使用源层中的 alpha 通道)。

这种工作方式 - 虽然很慢(我想我可以通过使用 ScanLines 来加快速度),但我无法弄清楚将 alpha 通道设置为什么。文档表明计算是:

st.Red  = Src.Red   + (1 - Src.Alpha) * Dst.Red

我通过猜测尝试了一些不同的值,但我的第一个问题是:如何计算 alpha 值?

在阅读了其他一些SO问题后,我遇到了TransparentBlt函数,它可以很好地(并且快速)进行掩蔽,但不能实现透明度,有没有办法结合起来 这两个调用一起(也许使用第三层)?

unit MainWnd;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, ControlsEx;

type
{------------------------------------------------------------------------------}
  TfrmMain = class(TForm)
    PaintBox1: TPaintBox;
    procedure PaintBox1Paint(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

{..............................................................................}
procedure copyToAlpha(const in_bitmap : TBitmap; const in_transparentColor : TColor;
        const in_transparency : integer);
var
  x : integer;
  y : integer;
  p : integer;
begin
  ASSERT(in_bitmap.PixelFormat = pf32bit);

  for x := 0 to in_bitmap.Width - 1 do
  begin
    for y := 0 to in_bitmap.Height - 1 do
    begin
      p := in_bitmap.Canvas.Pixels[x, y];
      if TColor(p) <> in_transparentColor then
      begin
        in_bitmap.Canvas.Pixels[x, y] := p or (in_transparency shl 24);
      end
      else
        in_bitmap.Canvas.Pixels[x, y] := p or ($ff shl 24);
    end;
  end;  
end;

{..............................................................................}
procedure alphaBlendTest(
        const in_target : TCanvas;
        const in_width : integer;
        const in_height : integer);
const
  BARSIZE = 30;
var
  bitmap  : TBitmap;
  r       : TRect;
  blendFn : BLENDFUNCTION;
  ret     : Boolean;
begin
  blendFn.BlendOp             := AC_SRC_OVER;
  blendFn.SourceConstantAlpha := $ff;
  blendFn.BlendFlags          := 0;
  blendFn.alphaFormat         := AC_SRC_ALPHA;

  bitmap := TBitmap.Create;
  try
    bitmap.Width              := in_width;
    bitmap.Height             := in_height;
    bitmap.PixelFormat        := pf32bit;
    bitmap.HandleType         := bmDIB;
    bitmap.TransparentColor   := clFuchsia;
    bitmap.Transparent        := true;  
    bitmap.Canvas.Brush.Color := clFuchsia;
    bitmap.Canvas.FillRect(Bounds(0, 0, in_width, in_height));
    bitmap.Canvas.Brush.Color := clGreen;

    r := Bounds(
        in_width div 2 - (in_width div 3) div 2,
        0,
        (in_width div 3) + 1,
        BARSIZE          + 1);

   bitmap.Canvas.Rectangle(r);
   // done drawing

   //copyToAlpha(bitmap, clFuchsia, 1);
   ret := Windows.TransparentBlt(
        in_target.Handle,
        0,
        0,
        in_width,
        in_height,
        bitmap.Canvas.Handle,
        0,
        0,
        in_width,
        in_height,
        clFuchsia);
        //blendFn);

    ASSERT(ret);
  finally
    bitmap.Free;
  end;
end;



{..............................................................................}
procedure TfrmMain.PaintBox1Paint(Sender: TObject);
var
  r: TRect;
begin
  PaintBox1.Canvas.Brush.Color := clBlue;
  r := Bounds(0, 0, PaintBox1.ClientWidth, PaintBox1.ClientHeight);
  PaintBox1.Canvas.FillRect(r);
  PaintBox1.Canvas.Brush.Color := clRed;
  PaintBox1.Canvas.Ellipse(0, 0, PaintBox1.ClientWidth, PaintBox1.ClientHeight);

  alphaBlendTest(PaintBox1.Canvas, PaintBox1.ClientWidth, PaintBox1.ClientHeight);
end;

end.

技巧:以任意比例混合相同的颜色会产生相同的颜色。

因此,最简单的方法(也许也是最有效的方法)是首先将透明结果绘制到临时位图,然后在目标画布上对该位图进行 alphablend。

在绘图期间访问目标画布:

procedure TfrmMain.PaintBox1Paint(Sender: TObject);
const
  BarSize = 30;
var
  R: TRect;
  Bmp: TBitmap;
  BlendFunc: TBlendFunction;
begin
  with PaintBox1 do
  begin
    R := ClientRect;
    Canvas.Brush.Color := clBlue;
    Canvas.FillRect(R);
    Canvas.Brush.Color := clRed;
    Canvas.Ellipse(R);
    Bmp := TBitmap.Create;
    try
      Bmp.Width := Width;
      Bmp.Height := Height;
      BitBlt(Bmp.Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, 0, 0,
        SRCCOPY);
      Bmp.Canvas.Brush.Color := clGreen;
      R := Bounds(Width div 3, 0, Width div 3 + 1, BarSize + 1);
      Bmp.Canvas.Rectangle(R);
      BlendFunc.BlendOp := AC_SRC_OVER;
      BlendFunc.BlendFlags := 0;
      BlendFunc.SourceConstantAlpha := 80;
      BlendFunc.AlphaFormat := 0;
      Windows.AlphaBlend(Canvas.Handle, 0, 0, Width, Height, Bmp.Canvas.Handle,
        0, 0, Width, Height, BlendFunc);
    finally
      Bmp.Free;
    end;
  end;
end;

并且在绘制过程中无法访问目标画布:

procedure GetRemoteBitmap(Bmp: TBitmap; Width, Height: Integer);
const
  BarSize = 30;
var
  R: TRect;
begin
  Bmp.Canvas.Brush.Color := clFuchsia;
  Bmp.Width := Width;
  Bmp.Height := Height;
  Bmp.TransparentColor := clFuchsia;
  Bmp.Transparent := True;
  Bmp.Canvas.Brush.Color := clGreen;
  R := Bounds(Width div 3, 0, Width div 3 + 1, BarSize + 1);
  Bmp.Canvas.Rectangle(R);
end;

procedure TfrmMain.PaintBox1Paint(Sender: TObject);
var
  R: TRect;
  Bmp: TBitmap;
  Tmp: TBitmap;
  BlendFunc: TBlendFunction;
begin
  with PaintBox1 do
  begin
    R := ClientRect;
    Canvas.Brush.Color := clBlue;
    Canvas.FillRect(R);
    Canvas.Brush.Color := clRed;
    Canvas.Ellipse(R);
    Bmp := TBitmap.Create;
    Tmp := TBitmap.Create;
    try
      GetRemoteBitmap(Bmp, Width, Height);
      Tmp.Width := Width;
      Tmp.Height := Height;
      BitBlt(Tmp.Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, 0, 0,
        SRCCOPY);
      TransparentBlt(Tmp.Canvas.Handle, 0, 0, Width, Height, Bmp.Canvas.Handle,
        0, 0, Width, Height, ColorToRGB(clFuchsia));
      BlendFunc.BlendOp := AC_SRC_OVER;
      BlendFunc.BlendFlags := 0;
      BlendFunc.SourceConstantAlpha := 80;
      BlendFunc.AlphaFormat := 0;
      Windows.AlphaBlend(Canvas.Handle, 0, 0, Width, Height, Tmp.Canvas.Handle,
        0, 0, Width, Height, BlendFunc);
    finally
      Tmp.Free;
      Bmp.Free;
    end;
  end;
end;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Alphablend 和透明Blt 的相关文章

  • DPI 意识真的需要吗?

    我正在学习如何使用 GDI GDI 绘制 GUI 我发现了这个http msdn microsoft com en us library windows desktop dd756596 v vs 85 aspx step 2 declar
  • 如何通过 TIdHTTP 下载大文件?

    我使用此代码下载小文件 Var ms TMemoryStream begin ms TMemoryStream Create Idhttp1 get http mydomain com myfile zip ms ms SaveToFile
  • 哪些简单的改变对您的 Delphi 程序产生了最大的改进 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个 Delphi 2009 程序 需要处理大量数据 并且需要尽可能快且不使用太多内存 What 小简单您是否对 Delphi 代
  • 在 JavaFX 中使用 MouseEvent 和 MouseClicked 选择并移动 Canvas 图像

    我有一个应用程序的示例 用于绘制图片GraphicsContext并如下图所示工作 问题是select and move只有blue circle水平地与Canvas MouseEvent and MouseClicked public c
  • Delphi - 检测我的应用程序是否打开了模式对话框

    我有一个 Delphi 2006 应用程序 当检测到错误情况时 它会弹出模式警报对话框 由于对错误条件的检查是在空闲处理程序中完成的 因此如果恰好显示了另一个模式对话框 则该对话框可能会在另一个模式对话框的顶部弹出 这可能会导致用户感到困惑
  • 洪水填充算法是否考虑了 alpha 且不会在抗锯齿线周围留下边缘?

    我已经实现了一个典型的洪水填充算法 当使用纯色时 它按预期工作 其中我使用 ARGB 分量之间的欧几里德距离来比较颜色 我的问题是 如果您在透明背景上绘制类似抗锯齿红线的内容 我的洪水填充算法将不会填充大多数半透明像素 从而在对象周围留下条
  • 将 PNG 从预乘 alpha 转换为传统的 alpha 透明度?

    我在处理一些具有预乘 Alpha 的 PNG 格式的源图像时遇到了很大的困难 因为大多数工具根本无法正确支持它 有没有什么可以将 最佳猜测 转换为更传统的PNG 如果 预乘 alpha 指的是 iOS 的 PNG 衍生品 那么您可以将它们转
  • 任何人都可以使用 GetIt!在 Delphi 10.4.1 中安装任何产品?

    自周五 10 月 16 日 以来 我一直在尝试使用 GetIt 安装任何内容 例如组件或其他任何与此相关的内容 当我按下 Icons8 1 0 的安装按钮时 我收到一条错误消息 Loading EULAS Cannot load data
  • 自定义组件和选项卡顺序

    我有一个自定义组件 继承自TCustomPanel 由另外两个组件组成 假设有两个编辑 使用组件时如何获得正确的 Tab 键顺序 在选项卡顺序设计器中 我只能访问组件本身 该组件本身无法获得焦点 因为它是一个面板 在运行时发生的情况是 我可
  • HTML5画布中绘制图像对象的限制区域

    我想限制画布上可以绘制图像的区域 我正在使用 Fabric js 我尝试了以下链接 但它对我不起作用 在 Fabric js 中设置对象拖动限制 https stackoverflow com questions 19979644 set
  • 画布已被跨源数据本地图像污染

    这个问题已经被问了很多次 但我只是不明白为什么这种情况会发生在我身上 基本上 我有一个画布和一个图像 当我尝试这样做时 var canvas document getElementById somecanvas var ctx canvas
  • TVirtualStringTree 中的自动调整列大小

    攀登 TVirtualTreeView 的学习之山 我尝试创建一个自定义后代 以确保在调整控件大小时 最后一列的宽度完全填充控件的宽度 而不需要水平滚动条 我看到许多与 AutoFitColumns 相关的项目 一个方法和许多事件 但没有涵
  • Delphi 2007 中的 AsyncCall

    我基本上想要的是开始异步调用 http andy jgknet de blog bugfix units asynccalls 29 asynchronous function calls 并继续加载我的代码 我的接口部分消耗了大量时间 6
  • 在 Delphi 中实现 MVVM 绑定(View <-> ViewModel)的最佳方法? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 对于使用本机组件的多平台应用程序 标准的 Delphi 方法已不再足够 到目前为止 我们的结构只有几个部分 GUI 表单 和业务逻辑 现在我们需
  • 如何在没有文档的情况下重构一个 10000 行的 Delphi 单元?

    我被分配了重构 Delphi 单元的任务 哇 10000 行代码 没有文档 大量的复制和粘贴代码 有很多用复制和粘贴制作的方法可以重构 无论如何 我迷失在所有这些行中 我有界面部分 我可以在其中 找到我的路 但总的来说 你建议如何处理此类任
  • VB.NET Custom Control(自定义绘图)刷新问题

    我用两个项目创建了一个简单的解决方案 第一个项目 类库 包含一个名为 Container 的自定义控件 它用圆角绘制自身 第二个项目 Windows 窗体 是一个测试应用程序 如果我在第二个项目的主窗体中添加一个容器实例 它会很好地显示圆角
  • 尝试从 Delphi 打开 Excel 或 Word 时出现“接口不受支持”错误

    当使用旧的 Delphi 代码将一些文本输出到 Excel 或 Word 时 我在一台机器上遇到了 接口不支持 错误 我怎样才能解决这个问题 问题是计算机上以前版本的 Excel 未正确卸载 为了修复它 我使用了遵循指示 http soci
  • 移动设备上的全屏画布

    我创建了一个小型画布游戏 希望它能够在 PC 和移动设备上运行 在 PC 上 画布区域可以按预期工作 但在为移动设备设计时就会出现问题 有没有一种方法 CSS 或 javascript 可以让用户双击网站内的画布区域时变成全屏 除非画布足够
  • 如何将 iframe 转换为画布?

    我正在尝试将所有内容作为图像保存到另一个页面中 我已经探索了执行此操作的方法 因此我认为我需要首先将该页面转换为画布 因此 我尝试使用要先将其保存为 iframe 的链接 然后将 iframe 转换为画布 但它不起作用 document r
  • Win32 DrawText 行高

    我正在调用 Win32DrawText函数将一些文本输出到设备上下文中 文本很长 可以很好地换行到第二行 问题是我需要稍微减少行之间的间距 我想减少行高 关于如何做到这一点有什么想法吗 我只想打电话DrawText两次 每行一次 但随后我必

随机推荐

  • 在端口 3000 上对 Node.js 应用程序进行 AWS 负载平衡

    我有一个 Node js Express Web 应用程序 它使用默认端口 3000 并通过弹性 IP 在 Ubuntu EC2 实例上响应良好 我正在尝试设置 AWS 内置的负载平衡 但似乎无法通过良好的运行状况检查 设置 2 个 ubu
  • 本地主机上的 socket.io 出现 404 错误 - XAMPP - Laravel 5.5

    我在本地主机上使用 XAMPP Window 8 1 Laravel 5 5 我使用 Pusher 在 Laravel 中编写了广播代码 并且工作正常 由于 Pusher 非常昂贵 所以我打算转向 socket io 在主刀片中添加了以下链
  • 如何使用批处理文件迭代 .ini 文件中的项目?

    我目前正在尝试循环遍历 a 中的每个项目 ini文件并稍后使用这些值 但我不知道怎么做 我的config ini文件看起来像这样 items item 1 XXXXX item 2 XXXXX item 3 XXXXX item 4 XXX
  • JHipster 微服务 CORS

    有没有一种方法可以通过网关访问微服务API而无需身份验证 例如 如果我有一个公共登录页面需要从微服务 API 读取数据 我启用了 CORS 并通过 Swagger 测试了 API 它在网关应用程序中运行良好 但是 如果我使用 CURL 调用
  • 在 C# 中(可能在不安全模式下)读取锁定文件的侵入性最小的方法是什么?

    我需要读取可能被锁定的 Windows 文件 但我不想创建任何类型的锁来阻止其他进程写入该文件 另外 即使文件被锁定为独占使用 我也想看看里面有什么 尽管这不是我的确切用例 但请考虑如何在使用和安装时读取 SQL Exchange 日志或数
  • 使用hibernate返回查询的计数值

    这是我的 mysql 查询 SELECT count FROM bw jobs WHERE year job date year curdate AND month job date month curdate 如何在休眠中使用它来获取计数
  • 构建带有复选标记的 NSOutline 视图

    我希望使用正确的 Apple 推荐方法向 NSOutlineview 添加复选框 但文档中尚不清楚 如何添加行为以允许用户如果单击父复选框 则它将选择子项 如果我单击它 它将取消选择该项目的子项 编辑 我简化了我的问题并添加了图像以使其更清
  • 如何从 DragEventArgs 确定数据类型

    我已经在我的应用程序中实现了拖放 但在确定被拖动对象的类型时遇到一些困难 我有一个基类Indicator以及从它派生的几个类 拖动的对象可以是这些类型中的任何一种 下面的代码片段看起来不太优雅 并且容易出现维护问题 每次我们添加一个新的派生
  • 为什么首先调用 ShowWindow()?

    首先需要注意的是 我最近才开始学习 WinAPI 我确信这个问题以前已经被问过很多次了 但由于某种原因我在网上找不到它 问题很简单 为什么要费心最初的电话ShowWindow 在体内WinMain 在消息循环执行之前 为什么不简单地通过使用
  • 如何找出 C++ 警告的数量

    我已开启 Wall在我的代码中消除所有警告 然而 有些我想在代码中允许 所以我在代码中禁用这些 在常见的问题中 我可以轻松地在 Google 中找到警告编号并禁用它们 例如 pragma warning disable 4127 但有些 我
  • PyCharm 和外部工具过滤器

    我正在尝试使用 PyCharm 进行 Django 开发 到目前为止我非常高兴 我的团队严格遵循 PEP8 格式 并使用 pep8 命令行程序进行检查以确保我们的代码符合要求 我已经配置了一个外部工具命令来运行 pep8 并且运行良好 我看
  • gsutil:仅列出目录(错误?)

    gsutil ls d gs XXX test gs XXX test gs XXX test 336x280 swf gz 所以它不仅列出目录 以 以及常规文件 以 gz例如 但据我了解 这个命令应该只列出目录 错误在哪里 gsutil
  • 使用 Twitter Bootstrap 导航栏进行导航的正确方法是什么?

    我正在使用 Twitter Bootstrap 3 创建一个网页 我使用导航栏的直觉是让每个项目导航到新的 href 然而 我见过以不同的方式处理这个问题 有些页面确实导航到新的 href 并触发页面加载 可能使用某种模板在所有 html
  • Html Agility - 将解析保存到字符串

    刚刚第一次尝试使用 Html Agility Pack 并遇到了问题 首先 我从字符串变量加载 string NewsText dr Message ToString HtmlAgilityPack HtmlDocument htmlDoc
  • 如何创建堆积线图

    在 R 中创建堆积条形图有多种解决方案 但如何绘制堆积线图呢 可以使用以下命令创建堆积线图ggplot2包裹 一些示例数据 set seed 11 df lt data frame a rlnorm 30 b 1 10 c rep LETT
  • 当报告需要很长时间运行时,如何解决套接字关闭的问题?

    我正在运行用 iReport 制作的 Clarity 报告 我的一份报告非常复杂 有时需要很长时间才能运行 取决于参数 有时 花了太长时间 我收到一条消息说 插座关闭 当报表快速运行时 不会出现此消息 我认为这意味着运行已超时 我目前正在努
  • 单元测试应该如何处理预期和意外的异常?

    当预期的异常发生时 它是否应该通过测试 当出现意外异常时 测试是否会失败 处理异常是否多余 因为它会使测试失败并因此充当测试 测试预期的异常 你必须添加expected属性具有预期的异常 因此如果抛出指定的异常 测试将通过 否则就会失败 例
  • 逐行编写 Lua 脚本

    我使用以下命令将 Lua 脚本添加到我的 C 应用程序中动态Lua http dynamiclua codeplex com 图书馆 它运作得很好 我想实现您获取正在执行的当前行 就像在 Visual Studio 中一样 并突出显示它 目
  • 将 opencv BackgroundSubtractorMOG 保存到文件吗?

    我使用 opencv 进行车辆计数过程 如何将我的BackgroundSubtractorMOG对象 例如BackgroundSubtractorMOG2等 保存到文件中 以便我可以从文件中读取它 再次使用经过训练的背景模型而无需长时间训练
  • Alphablend 和透明Blt

    这个问题与我有关先前的问题 https stackoverflow com q 12700165 62576 on SO 我想组合两个图层 并仅将 alpha 应用于源图层的特定部分 我尝试的一种方法是将 SourceConstantAlp