Delphi GFX
f65d50f6

Серые Маски. Этот способ основан


Серые Маски. Этот способ основан на сложении цветов по логическим схемам И, ИЛИ ( AND,OR ). Давайте посмотрим, что получается, когда мы складываем по логическим схемам И, ИЛИ черный и серый цвета с цветовыми масками. Ну во-первых, что такое цветовая маска? Грубо говоря это цвет и есть, а на самом деле это некая битовая последовательность, где единичные биты указывают на биты принадлежащие конкретному цвету.
Ну например для красного цвета цветовая маска будет выглядеть следующим образом :



000000000000000011111111 это есть максимальная интенсивность чисто красного цвета, единички - это биты красного цвета, нули - биты других цветов. Соответственно существуют еще пять цветов.
000000001111111100000000 зеленый
111111110000000000000000 синий
000000001111111111111111 желтый
111111111111111100000000 морская волна
111111110000000011111111 темно-сиреневый
Вот такие цветовые маски могут быть использованы нами для создания кланов. В стандартном графическом интерфейсе Windows (GDI) им соответствуют цвета : clRed, clLime, clBlue, clYellow, clAqua, clFuchsia.

Теперь, если мы сложим черный цвет с какой-нибудь из маской, по системе ИЛИ, то получим ту же самую маску в качестве результата:

000000000000000000000000 OR 000000000000000011111111 = 000000000000000011111111, это неинтересно.

Гораздо интереснее если мы сложим таким же образом маску с серым цветом, в этом случае мы получим оттенок цвета маски, но немного светлее, и чем светлее серый цвет, тем светлее будет результирующий цвет вплоть до белого. Стало быть, если у нас к примеру картинка выполнена в оттенках серого цвета, то сложив каждый пиксель с маской красного цвета по системе OR, мы сделаем картинку розового цвета не исказив ее содержания. Сложим с маской синего цвета - получим голубоватую и так далее. Есть одна неприятность - черный цвет становится цветом маски, а это не всегда приемлемо. Однако в этом случае можно складывать по схеме И, при этом черный цвет как был черным так им и останется, с чем бы его ни складывали, а вот серый приобретет оттенок маски.





Эти рисунки иллюстрируют изменеие серого цвета после сложения его с маской красного цвета по системе ИЛИ и И. При этом заметно что, при сложении по системе OR результирующий цвет светлее по тону, чем исходный, а при сложении по системе AND наоборот - темнее. Как с этим справлятся я поясню дальше, а сейчас расскажу о том, каким образом данный материал может нам помочь.

Итак, предполжим у нас есть спрайт ( Рисунок слева )

Некоторые части этого спрайта должны изменять свой цвет так, чтобы определять его принадлежность к некоторому клану. Делаем серую маску тех частей, которые подвержены изменению ( Рисунок справа )

Вот так она должна выглядеть. Подобную операцию можно осуществить, практически, в любом графическом редакторе. Например: Photoshop'e. Теперь, если мы сложим данную маску по системе И (AND) с маской нужного нам цвета, маска станет не серой, а именно того цвета, который нам нужен. После этого мы можем вывести маску на спрайт, а спрайт в свою очередь вывести на экран.

Код демонстрационной программы:

type
...
ColorBox: TComboBox;// Список выбора цвета
...
end;

var
MainForm: TMainForm;
  RoboSprite : TBitmap; // Картинка спрайта
  RoboMask : TBitmap; // Картинка серой маски
  MaskColor : TColor; // Цветовая маска

...

procedure TMainForm.FormCreate(Sender: TObject);
begin
  RoboSprite := TBitmap.Create; // Загружаем картинки
  RoboMask := TBitmap.Create;
  RoboSprite.LoadFromFile('Sprite.bmp');
  RoboMask.LoadFromFile('Maska.bmp');

  // Устанавливаем прзрачный цвет спрайта в черный
  RoboSprite.Transparent := True;
  RoboSprite.TransparentColor := clBlack;
end;

procedure TMainForm.ColorBoxChange(Sender: TObject);
Var
  W,H : Integer;
  X,Y : Integer;
begin
  W := RoboSprite.Width;
  H := RoboMask.Width;

  // Получаем цвет маски из ComboBox'a выбора цвета
  MaskColor := StringToColor(ColorBox.Text);

  // В цикле осуществляем сложение по системе И
  for Y := 0 to H-1 do
    for X := 0 to W-1 do
      begin
        // Если пиксель в спрайте не равен черному
        if RoboMask.Canvas.Pixels[X,Y] <> clBlack Then
        // Складываем пиксель маски с цветовой маской и результат кладем на спрайт
        RoboSprite.Canvas.Pixels[x,y] := RoboMask.Canvas.Pixels[X,Y] AND MaskColor;
      end;
  Self.Canvas.Draw(0,0,RoboSprite);// Отрисовываем спрайт
end;

end.
Вот собственно и вся премудрость. Выглядит это следующим образом:

Да, как я уже говорил, при сложении по системе И результирующий цвет выглядит немного темнее, чем исходный цвет. Проблема решается просто: в том же PhotoShop'e просто повысьте яркость маски. На сколько ее повысить следует определит путем подбора. Все.

Это была первая часть статьи. Во второй части я опишу, как провернуть то же самое работая с DirectX, и под различными режимами.


Содержание раздела