如何使用像乘法这样的混合模式来填充矩形,而不仅仅是简单的透明度
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
程序。我会将此代码提供给库维护人员,以便在对他们有意义的情况下将其合并到官方资源中。
将代码放入官方库似乎并不那么容易,所以我在这里附上完整的补丁,以防其他人发现它有用。
我也将它发布到 Graphics32.general 新闻组,所以它不会丢失。
我正在使用 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
程序。我会将此代码提供给库维护人员,以便在对他们有意义的情况下将其合并到官方资源中。
将代码放入官方库似乎并不那么容易,所以我在这里附上完整的补丁,以防其他人发现它有用。
我也将它发布到 Graphics32.general 新闻组,所以它不会丢失。