Программно меняйте цвета с небольшого растрового изображения (оригинал), пиксель за пикселем - PullRequest
2 голосов
/ 10 января 2011

Загрузите исходный код скомпилированного исполняемого файла здесь (размер: 161 КБ (165 230 байт)): http://www.eyeClaxton.com/download/delphi/ColorSwap.zip

Исходный размер растрового изображения составляет всего 28x15 пикселей, а цвет - голубой. Я хотел бы иметь возможность щелкнуть любую из цветных панелей справа и изменить исходный цвет растрового изображения со светло-синего на цвет панели.

Если вы нажмете на серую панель, вы увидите это в действии, я просто не могу понять, как сделать это правильно с другими цветами. Любая помощь будет принята с благодарностью. Если вам нужна дополнительная информация, пожалуйста, не стесняйтесь спрашивать.

Я задавал этот вопрос раньше , но я не смог прояснить, что я пытался сделать, поэтому я надеюсь, что этот вопрос немного более ясен.

alt text

unit MainUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TMainFrm = class(TForm)
    Panel1: TPanel;
    Label1: TLabel;
    Panel2: TPanel;
    Label2: TLabel;
    BeforeImage1: TImage;
    AfterImage1: TImage;
    Panel3: TPanel;
    Panel4: TPanel;
    Panel5: TPanel;
    Panel6: TPanel;
    Panel7: TPanel;
    Panel8: TPanel;
    Panel9: TPanel;
    Image1: TImage;
    Label3: TLabel;
    Panel10: TPanel;
    Memo1: TMemo;
    Label4: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Panel4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainFrm: TMainFrm;

implementation

uses
  Math;

{$R *.DFM}
function Min(const A, B, C: Integer): Integer;
begin
  Result := Math.Min(A, Math.Min(B, C));
end;

function Max(const A, B, C: Integer): Integer;
begin
  Result := Math.Max(A, Math.Max(B, C));
end;

function RGBToGray(theRed, theGreen, theBlue: Byte): Byte;
begin
  Result := (Max(theRed, theGreen, theBlue) + Min(theRed, theGreen, theBlue)) div 2;
end;

function BlueToGray(theColor: TColor): TColor;
var
  R, G, B, X: Byte;
begin
  R := (theColor and $FF);
  G := (theColor and $FF00) shr 8;
  B := (theColor and $FF0000) shr 16;

  X := RGBToGray(R, G, B);
  Result := TColor(RGB(X, X, X));
end;

procedure TMainFrm.FormCreate(Sender: TObject);
begin
  Image1.Picture.Graphic := BeforeImage1.Picture.Bitmap;
end;

procedure TMainFrm.Panel4Click(Sender: TObject);
var
  Bitmap: TBitmap;
  I, X: Integer;
  Color: Integer;
begin
  Bitmap := TBitmap.Create;
  try
    Bitmap.Assign(BeforeImage1.Picture.Bitmap);
    Panel4.Caption := '';
    Panel5.Caption := '';
    Panel6.Caption := '';
    Panel7.Caption := '';
    Panel8.Caption := '';
    Panel9.Caption := '';
    (Sender as TPanel).Caption := 'X';

    for X := 0 to (Bitmap.Height - 1) do
    begin
      for I := 0 to (Bitmap.Width - 1) do
      begin
        Color := Bitmap.Canvas.Pixels[I, X];

        case (Sender as TPanel).Tag of
          1: ; // I need a function something like BlueToRed(Color);
          2: ; // I need a function something like BlueToGreen(Color);
          3: ; // I need a function something like BlueToYellow(Color);
          4: ; // I need a function something like BlueToFuchsia(Color);
          5: ; // I need a function something like BlueToCyan(Color);
          6: Bitmap.Canvas.Pixels[I, X] := BlueToGray(Color);
        end;
        Image1.Picture.Graphic := Bitmap;
      end;
      Application.ProcessMessages();
      Sleep(100);
    end;
    AfterImage1.Picture.Graphic := Bitmap;
  finally
    Bitmap.Free;
  end;
end;

end.

1 Ответ

7 голосов
/ 10 января 2011

Вопрос по-прежнему недостаточно четко определен, поскольку серый цвет не работает как любой другой цвет (ни в модели RGB, ни в модели HSV), поэтому не существует единого очевидного способа реализации кнопок других цветов. .

Однако, один естественный способ (может быть, самый естественный) состоит в том, чтобы сделать, как я предложил в моем ответе на предыдущий вопрос, а именно преобразовать каждый пиксель из HSV(h, s, v) в HSV(0, s, v) в красном регистре, HSV(120, s, v) в зеленом корпусе и HSV(240, s, v) в синем корпусе. Числа 0, 120 и 240 являются углами оттенка.

Чтобы сделать это, вам нужны только функции для преобразования между RGB и HSV (и я дал вам их в последнем вопросе).

Я вижу в вашем коде, что вы назвали функции BlueToRed(Color) и т. Д., Что неуместно, поскольку любой цвет станет красным и т. Д., Поэтому более подходящими именами будут ColorToRed и т. Д.

Чтобы сделать это как можно более понятным, я добавил код для красной и зеленой кнопок в вашей программе. Смотрите обновленную версию на

http://privat.rejbrand.se/ColorSwap.zip

(Также обратите внимание, что «ColorSwap» является неподходящим именем. Лучшее имя будет «FixHue».)

Производительность

Кроме того, как вы могли заметить, производительность ужасна ! Цветное изображение занимает несколько секунд!

Это не потому, что процессор медленный (действительно, он чрезвычайно быстрый), а из-за двух ошибок в дизайне:

  1. Никогда не обновляйте растровое изображение на экране. Вместо этого обновите растровое изображение в памяти, а затем, когда закончите, скопируйте растровое изображение на экран.

  2. Не используйте свойство Pixels. Это неловко медленно. Вместо этого используйте Scanline.

Если вы все сделаете правильно, вы сможете делать несколько сотен обновлений в секунду ...

...