I'm using the Delphi library Graphics32 to draw an audio graphic on the screen, and then represent a series of periods in the audio.
The graph is quite simple: a black background, with the audio waveform filled with a light gray color.
The periods right now are rectangles drawn using FillRectTS
with a semitransparent color. I am looking for a way (hopefully a simple one) to draw this using a blend mode like Multiply, so the audio waveform is the one who gets the color, and the background remains black. I haven't found any function in the TBitmap32
class (nor, for instance, the g32_Interface unit) that allows me to do this.
This needs to be done after the audio waveform is painted, as redrawing this on-demand is very time-expensive, and the periods are user-defined on runtime, so drawing the audio waveform directly with the colors is not possible.
Here is a little example of how is it, and how I would like it:
The code right now that draws the periods, the aspect I need to change, is the following:
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
get's the transparency needed depending on different conditions (if the event is selected or not, and the type of event), but the idea at the end is the same. This code draws like the first part of the graphic above.
Solutions (or ideas) in Delphi or C++Builder are fine by me.
Update
I have implemented this directly on the Graphics32 code, using any of the color blend routines it already provides, and it solves my needs. It's an extra set of FillRect functions that takes another parameter for the blend mode to use. I will try to get this into the official project, if it's still alive...
I added the following code to the Graphics32 sources, so I can fill the required Rect using one of the several blend modes that the library provides:
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;
There are also
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;
Which are a copy of the ones provided by the Library, but internally call the new FillRectTB
procedure. I will get this code into the library maintainers, so it can be incorporated in the official sources, if it makes sense for them.
It doesn't appear to be that easy to get the code into the official library, so I'm attaching here the full patch, in case somebody else finds this usefull.
I also posted this into the Graphics32.general newsgroup, so it doesn't get lost.