Как FillRect, используя режим смешивания, например, умножение, а не просто прозрачность
Я использую библиотеку Delphi Graphics32, чтобы нарисовать звуковую графику на экране, а затем представить серию периодов в аудио.
График довольно прост: черный фон с аудио-волной, заполненной светло-серым цветом.
Периоды прямо сейчас представляют собой прямоугольники, нарисованные с использованием FillRectTS
с полупрозрачным цветом. Я ищу способ (надеюсь, простой) нарисовать это, используя режим наложения, такой как Multiply, поэтому звуковой сигнал - это тот, кто получает цвет, а фон остается черным. Я не нашел никакой функции в TBitmap32
класс (ни, например, модуль 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, который принимает другой параметр для режима наложения. Я постараюсь внести это в официальный проект, если он еще жив...
2 ответа
Я добавил следующий код к источникам 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.g, чтобы она не потерялась.
Что бы я сделал на вашем месте, это разделил ваш дисплей формы волны на два отдельных слоя. Один слой будет использоваться для фона, а другой для переднего плана. Зачем?
Делая это, вы можете повторно использовать существующий код. Просто сделайте это в два отдельных шага. Один для задних и один для переднего плана.
Но другой, вероятно, лучший способ - просто визуализировать выделение разными цветами, как это делает Cool ditor Pro.
Таким образом, вы можете полностью избавиться от альфа-рендеринга, что должно значительно повысить производительность рендеринга.