|
1
16th October 22:43
External User
|
Magnetic Lasso or Intelligent Scissors Tool ?
Dear ladies and gentlemen,
I want to make such tool for my application which called Magnetic Lasso
Tool in Photoshop or Intelligent Scissors Tool in GIMP, although they are
not absolutely same in the both applications.
I have been checked out the source code of the Intelligent Scissors of
GIMP 2.2.10 . But the amount of routines related to this technique is so
huge, and the pointer operations in C is so complex, until now, I couldn't
understand the code in GIMP which related to this tool, and translate it to
Pascal.
I have tried to make it by myself. But in vain. My code is in the
following (could only manipulate the absolute vertical line):
///////////////////////////
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, ComCtrls, StdCtrls, ExtDlgs;
type
TfrmMain = class(TForm)
Panel1: TPanel;
StatusBar: TStatusBar;
ScrollBox1: TScrollBox;
imgDrawingArea: TImage;
OpenPictureDialog: TOpenPictureDialog;
btnOpenImage: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btnOpenImageClick(Sender: TObject);
procedure imgDrawingAreaMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedure imgDrawingAreaMouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
procedure imgDrawingAreaMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
FOriginalBitmap: TBitmap;
FDrawing : Boolean;
FStart, FEnd : TPoint;
FPoints : array of TPoint;
procedure CalculatePoints(const SampleBitmap: TBitmap;
const PointA, PointB: TPoint; const Radius, Fuzziness: Integer);
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
uses
Math;
{$R *.dfm}
procedure TfrmMain.CalculatePoints(const SampleBitmap: TBitmap;
const PointA, PointB: TPoint; const Radius, Fuzziness: Integer);
var
BaseColor, CurColor, NearColor: TColor;
sx, sy, ex, ey, ix, iy : Integer;
Slope : Extended;
i, j, x, y, Length : Integer;
begin
BaseColor := SampleBitmap.Canvas.Pixels[PointA.X, PointA.Y];
sx := MinIntValue([PointA.X, PointB.X]);
sy := MinIntValue([PointA.Y, PointB.Y]);
ex := MaxIntValue([PointA.X, PointB.X]);
ey := MaxIntValue([PointA.Y, PointB.Y]);
SetLength(FPoints, 0);
SetLength( FPoints, High(FPoints) + 2 );
FPoints[High(FPoints)] := Point(sx, sy);
if (ex - sx) = 0 then
begin
for i := 1 to (ey - sy - 1) do
begin
ix := sx;
NearColor := SampleBitmap.Canvas.Pixels[sx, sy + i];
for j := (sx - Radius) to (sx + Radius) do
begin
if j = sx
then Continue;
CurColor := SampleBitmap.Canvas.Pixels[j, sy + i];
if Abs(CurColor - BaseColor) < Abs(NearColor - BaseColor) then
begin
NearColor := CurColor;
ix := j;
end;
end;
SetLength( FPoints, High(FPoints) + 2 );
FPoints[High(FPoints)] := Point(ix, sy + i);
end;
end;
SetLength( FPoints, High(FPoints) + 2 );
FPoints[High(FPoints)] := Point(ex, ey);
end; { CalculatePoints }
procedure TfrmMain.FormCreate(Sender: TObject);
begin
FOriginalBitmap := nil;
FStart := Point(0, 0);
FEnd := Point(0, 0);
FDrawing := False;
FPoints := nil;
end; { FormCreate }
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
FOriginalBitmap.Free;
end; { FormDestroy }
procedure TfrmMain.btnOpenImageClick(Sender: TObject);
var
Picture: TPicture;
begin
if OpenPictureDialog.Execute then
begin
if Assigned(FOriginalBitmap) then
begin
FOriginalBitmap.Free;
FOriginalBitmap := nil;
end;
FOriginalBitmap := TBitmap.Create;
Picture := TPicture.Create;
try
Picture.LoadFromFile(OpenPictureDialog.FileName);
try
FOriginalBitmap.Assign(Picture.Graphic);
FOriginalBitmap.PixelFormat := pf24bit;
except
FOriginalBitmap.Width := Picture.Graphic.Width;
FOriginalBitmap.Height := Picture.Graphic.Height;
FOriginalBitmap.PixelFormat := pf24bit;
FOriginalBitmap.Canvas.Draw(0, 0, Picture.Graphic);
end;
imgDrawingArea.Picture.Graphic := FOriginalBitmap;
finally
Picture.Free;
end;
end;
end; { btnOpenImageClick }
procedure TfrmMain.imgDrawingAreaMouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
imgDrawingArea.Picture.Graphic := FOriginalBitmap;
FStart := Point(X, Y);
FEnd := Point(X, Y);
imgDrawingArea.Canvas.Pen.Mode := pmNotXor;
FDrawing := True;
end; { imgDrawingAreaMouseDown }
procedure TfrmMain.imgDrawingAreaMouseMove(Sender: TObject;
Shift: TShiftState; X, Y: Integer);
begin
if FDrawing then
begin
with imgDrawingArea.Canvas do
begin
MoveTo(FStart.X, FStart.Y);
LineTo(FEnd.X, FEnd.Y);
FEnd := Point(X, Y);
MoveTo(FStart.X, FStart.Y);
LineTo(FEnd.X, FEnd.Y);
end;
end;
StatusBar.Panels[0].Text := Format('X: %d, Y: %d', [X, Y]);
end; { imgDrawingAreaMouseMove }
procedure TfrmMain.imgDrawingAreaMouseUp(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
FDrawing := False;
imgDrawingArea.Picture.Graphic := FOriginalBitmap;
imgDrawingArea.Canvas.Pen.Mode := pmNotXor;
FEnd := Point(X, Y);
CalculatePoints(FOriginalBitmap, FStart, FEnd, 10, 0);
imgDrawingArea.Canvas.Polyline(FPoints);
imgDrawingArea.Canvas.Pen.Mode := pmCopy;
end; { imgDrawingAreaMouseUp }
end.
///////////////////
Could you please give me some suggestions on how to achieve this tool?
Help me, please. Thank you very much.
Best regards.
Xiaoguang
|