unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Graphics, Dialogs, StdCtrls, ExtCtrls, LCLType,
Spin;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
Image2: TImage;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
OpenDialog1: TOpenDialog;
Shape1: TShape;
SpinEdit1: TSpinEdit;
procedure Button1Click(Sender: TObject);
procedure Button1KeyPress(Sender: TObject; var Key: char);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer
);
public
procedure ChangeColor(oldColor, newColor: TColor; Tolerance: Byte);
end;
var
Form1: TForm1;
implementation
const
SelectedColor: TColor = clWhite;
TargetColor = clGreen; // Change target color here
{$R *.lfm}
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
AJpg: TJPEGImage;
begin
if not(OpenDialog1.Execute) then Exit;
AJpg := TJpegImage.Create;
AJpg.LoadFromFile(OpenDialog1.FileName);
Image1.Picture.Bitmap.Assign(AJpg);
AJpg.Free;
Image1.Enabled := True;
Image2.Enabled := True;
end;
procedure TForm1.Button1KeyPress(Sender: TObject; var Key: char);
begin
if (Key = 'c') or (Key = 'C') then
ChangeColor(SelectedColor, TargetColor, SpinEdit1.Value);
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
ScanData: PRGBQuad;
ValR, ValG, ValB: Byte;
begin
// Point to the pixel's data location
ScanData := Image1.Picture.Bitmap.ScanLine[Y];
Inc(ScanData, X);
// Get RGB values of the pixel
ValR := ScanData^.rgbRed;
ValG := ScanData^.rgbGreen;
ValB := ScanData^.rgbBlue;
SelectedColor := RGBToColor(ValR, ValG, ValB);
// Show information of the pixel
Shape1.Brush.Color := RGBToColor(ValR, ValG, ValB);
Label1.Caption := 'x'+IntToStr(X)+':y'+IntToStr(Y)+' = r'+
IntToStr(ValR)+', g'+IntToStr(ValG)+', b'+IntToStr(ValB);
end;
procedure TForm1.ChangeColor(oldColor, newColor: TColor; Tolerance: Byte);
var
ScanData, ResultData: PRGBQuad;
CurR, CurG, CurB: Byte; // Current pixels' RGB
ReqR, ReqG, ReqB: Byte; // Required RGB
TarR, TarG, TarB: Byte; // Target RGB
X, Y: Integer;
begin
ReqR := Red(oldColor);
ReqG := Green(oldColor);
ReqB := Blue(oldColor);
TarR := Red(newColor);
TarG := Green(newColor);
TarB := Blue(newColor);
// Don't use assign to avoid sharing same data location
Image2.Picture.Bitmap := TBitmap.Create;
Image2.Picture.Bitmap.Height := Image1.Picture.Bitmap.Height;
Image2.Picture.Bitmap.Width := Image1.Picture.Bitmap.Width;
for Y := 0 to (Image1.Picture.Bitmap.Height-1) do
begin
ScanData := Image1.Picture.Bitmap.ScanLine[Y];
ResultData := Image2.Picture.Bitmap.ScanLine[Y];
for X:= 0 to (Image1.Picture.Bitmap.Width-1) do
begin
ResultData^ := ScanData^;
CurR := ScanData^.rgbRed;
CurG := ScanData^.rgbGreen;
CurB := ScanData^.rgbBlue;
if (abs(CurR-ReqR) < Tolerance) and
(abs(CurG-ReqG) < Tolerance) and
(abs(CurB-ReqB) < Tolerance) then
begin
ResultData^.rgbRed := TarR;
ResultData^.rgbGreen := TarG;
ResultData^.rgbBlue := TarB;
end;
Inc(ScanData);
Inc(ResultData);
end;
end;
end;
end.