如何使用像乘法这样的混合模式来填充矩形,而不仅仅是简单的透明度

How to FillRect using a blend mode like multiply, and not just a simple transparency

我正在使用 Delphi 库 Graphics32 在屏幕上绘制音频图形,然后表示音频中的一系列句点。

图表非常简单:黑色背景,音频波形填充浅灰色。

现在的句点是使用 FillRectTS 绘制的具有半透明颜色的矩形。我正在寻找一种方法(希望是一种简单的方法)使用像乘法这样的混合模式来绘制它,所以音频波形是获得颜色的,背景保持黑色。我没有在 TBitmap32 class(例如,g32_Interface 单元)中找到任何允许我这样做的函数。

这需要在绘制音频波形之后进行,因为按需重新绘制非常耗时,而且周期是用户在运行时定义的,所以直接用颜色绘制音频波形是不行的可能。

这是一个小例子,说明它如何以及我想要它的方式:

现在绘制句点的代码,我需要更改的方面如下:

TColor32 ColorDibujado = Color == 0 ? GetColorDeTipoEvento(PeriodoADibujar->Evento->TipoEvento) : Color;

if (PeriodoADibujar->Habilitado == false)
  ColorDibujado = (ColorDibujado & 0x00ffffff) | 0xAf000000;

Gr32::TRect area;

area.Left   = (PeriodoADibujar->PosicionInicioRelativa * (double)LimitesDestino.Width()) / Proporcion + PosX;
area.Right  = (PeriodoADibujar->PosicionFinRelativa * (double)LimitesDestino.Width()) / Proporcion + PosX;
area.Top    = LimitesDestino.Top;
area.Bottom = LimitesDestino.Bottom;

MapaDestino->FillRectTS(area, ColorDibujado);

ColorDibujado 根据不同的条件(事件是否被选中,以及事件的类型)得到所需的透明度,但最后的想法是一样的。此代码的绘制类似于上图的第一部分。

Delphi 或 C++Builder 中的解决方案(或想法)对我来说很好。

更新

我直接在 Graphics32 代码上实现了这个,使用它已经提供的任何颜色混合例程,它解决了我的需求。它是一组额外的 FillRect 函数,它采用另一个参数供混合模式使用。如果它还活着,我会尝试将其纳入官方项目...

我会在你的地方做的是将你的波形显示分成两个单独的层。一层将用于背景,另一层用于前景。为什么?

通过这样做,您可以重新使用现有代码。只需分两个单独的步骤即可。一个用于背景,一个用于前景。

但另一个可能更好的方法是像 Cool ditor Pro 那样使用不同的颜色简单地渲染选区。

这样您就可以完全摆脱 alpha 渲染,这应该会显着提高渲染性能。

我将以下代码添加到 Graphics32 源代码中,因此我可以使用库提供的多种混合模式之一填充所需的 Rect:

TBlendMode = (bmAdd, bmSub, bmDiv, bmMod, bmMax, bmMin, bmDif, bmAvg, bmExc, bmSca);

procedure TCustomBitmap32.FillRectTB(X1, Y1, X2, Y2: Integer; Value: TColor32; BlendMode: TBlendMode);
var
  i, j: Integer;
  P: PColor32;
  blend: TBlendReg;
begin

  case BlendMode of
    bmAdd: blend := ColorAdd;
    bmSub: blend := ColorSub;
    bmDiv: blend := ColorDiv;
    bmMod: blend := ColorModulate;
    bmMax: blend := ColorMax;
    bmMin: blend := ColorMin;
    bmDif: blend := ColorDifference;
    bmAvg: blend := ColorAverage;
    bmExc: blend := ColorExclusion;
    bmSca: blend := ColorScale;
    else blend := MergeReg;
  end;

  try
    Dec(Y2);
    Dec(X2);
    for j := Y1 to Y2 do
    begin
      P := GetPixelPtr(X1, j);
      for i := X1 to X2 do
      begin
        P^ := blend(Value, P^);
        Inc(P);
      end;
    end;
  finally
    EMMS;
    Changed(MakeRect(X1, Y1, X2 + 1, Y2 + 1));
  end;
end;

还有

procedure FillRectTSB(X1, Y1, X2, Y2: Integer; Value: TColor32; BlendMode: TBlendMode); overload;
procedure FillRectSB(const ARect: TRect; Value: TColor32; BlendMode: TBlendMode); overload;
procedure FillRectTSB(const ARect: TRect; Value: TColor32; BlendMode: TBlendMode); overload;

这是图书馆提供的副本,但在内部调用新的 FillRectTB 程序。我会将此代码提供给库维护人员,以便在对他们有意义的情况下将其合并到官方资源中。

将代码放入官方库似乎并不那么容易,所以我在这里附上完整的补丁,以防其他人发现它有用。

Link to patch file

我也将它发布到 Graphics32.general 新闻组,所以它不会丢失。