Как 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.

Таким образом, вы можете полностью избавиться от альфа-рендеринга, что должно значительно повысить производительность рендеринга.

Выбор формы волны в Cool Editor Pro

Другие вопросы по тегам