Skip to content

Commit

Permalink
Image: Line,Ellipse,Circle antialiased (with thickness) methods
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Oct 12, 2023
1 parent ccaa8b6 commit 3f6303e
Show file tree
Hide file tree
Showing 9 changed files with 371 additions and 8 deletions.
32 changes: 24 additions & 8 deletions Source/Simba.lpi
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<Libraries Value="../Third-Party/lape/extensions/ffi/bin/win32"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down Expand Up @@ -93,7 +93,7 @@
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<Libraries Value="../Third-Party/lape/extensions/ffi/bin/win64"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down Expand Up @@ -141,7 +141,7 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down Expand Up @@ -184,7 +184,7 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down Expand Up @@ -226,7 +226,7 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down Expand Up @@ -274,7 +274,7 @@
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down Expand Up @@ -340,7 +340,7 @@
<PackageName Value="LCL"/>
</Item5>
</RequiredPackages>
<Units Count="150">
<Units Count="154">
<Unit0>
<Filename Value="Simba.lpr"/>
<IsPartOfProject Value="True"/>
Expand Down Expand Up @@ -1025,6 +1025,22 @@
<Filename Value="script/imports/simba/simba.import_pointbuffer.pas"/>
<IsPartOfProject Value="True"/>
</Unit149>
<Unit150>
<Filename Value="drawlineaa.inc"/>
<IsPartOfProject Value="True"/>
</Unit150>
<Unit151>
<Filename Value="drawellipseaa.inc"/>
<IsPartOfProject Value="True"/>
</Unit151>
<Unit152>
<Filename Value="drawpixelaa.inc"/>
<IsPartOfProject Value="True"/>
</Unit152>
<Unit153>
<Filename Value="clearpixelaa.inc"/>
<IsPartOfProject Value="True"/>
</Unit153>
</Units>
</ProjectOptions>
<CompilerOptions>
Expand All @@ -1035,7 +1051,7 @@
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir);$(LazarusDir)/components/synedit;../Third-Party/lape;editor"/>
<Libraries Value="../Third-Party/lape/extensions/ffi/bin/win64"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components"/>
<OtherUnitFiles Value="$(ProjPath);script;forms;codetools;targets;matchtemplate;algorithms;editor;finders;script/imports/lcl;script/imports/simba;script/imports/simbaclasses;package;../Third-Party;../Third-Party/lape;../Third-Party/lape/extensions/ffi;imagebox;colormath;components;image"/>
<UnitOutputDirectory Value="$(ProjPath)../build/$(BuildMode)/$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Parsing>
Expand Down
6 changes: 6 additions & 0 deletions Source/image/clearpixelaa.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
procedure PixelProc(const X, Y: Integer; const Alpha: Byte); inline;
begin
if (X >= 0) and (Y >= 0) and (X < FWidth) and (Y < FHeight) then
FData[Y*FWidth+X].A := 0;
end;

155 changes: 155 additions & 0 deletions Source/image/drawellipseaa.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// https://zingl.github.io/bresenham.js

procedure DrawEllipseAA(x0, y0, x1, y1: Integer; Thickness: Single);
var
a,b,b1: Integer;
a2,b2: Single;
dx,dy: Single;
err: Single;
dx2,dy2,e2,ed: Single;
i: Single;
Alpha: Byte;
begin
a := Abs(x1 - x0);
b := Abs(y1 - y0);
b1 := b and 1;
a2 := a-2*Thickness;
b2 := b-2*Thickness;
dx := 4*(a-1)*b*b;
dy := 4*(b1-1)*a*a;

i := a+b2;
err := b1*a*a;

if ((Thickness-1) * (2*b-Thickness) > a*a) then
b2 := Sqrt(a*(b-a)*i*a2) / (a-Thickness);

if ((Thickness-1) * (2*a-Thickness) > b*b) then
begin
a2 := Sqrt(b*(a-b)*i*b2) / (b-Thickness);
Thickness := (a-a2) / 2;
end;

if (a = 0) or (b = 0) then
Exit;

if (x0 > x1) then
begin
x0 := x1;
x1 += a;
end;

if (y0 > y1) then
y0 := y1;

if (b2 <= 0) then
Thickness := a;

e2 := Thickness - Floor(Thickness);
Thickness := x0+Thickness-e2;
dx2 := 4*(a2+2*e2-1)*b2*b2;
dy2 := 4*(b1-1)*a2*a2;
e2 := dx2*e2;
y0 += (b+1) shr 1;
y1 := y0-b1;
a := 8*a*a;
b1 := 8*b*b;
a2 := 8*a2*a2;
b2 := 8*b2*b2;

repeat
while True do
begin
if (err < 0) or (x0 > x1) then
begin
i := x0;
Break;
end;

i := Min(dx,dy);
ed := Max(dx,dy);

if ((y0 = y1+1) and (2*err > dx) and (a > b1)) then
ed := a/4
else
ed += 2*ed*i*i/(4*ed*ed+i*i+1)+1;
i := 255*err/ed;

Alpha := Byte(Round(i));
PixelProc(x0,y0, Alpha);
PixelProc(x0,y1, Alpha);
PixelProc(x1,y0, Alpha);
PixelProc(x1,y1, Alpha);

if (err+dy+a < dx) then
begin
i := x0+1;
Break;
end;

x0 += 1;
x1 -= 1;
err -= dx;
dx -= b1;
end;

while (i < Thickness) and (2*i <= x0+x1) do
begin
PixelProc(Round(i), y0, 0);
PixelProc(Round(x0+x1-i), y0, 0);
PixelProc(Round(i), y1, 0);
PixelProc(Round(x0+x1-i), y1, 0);

i += 1.0;
end;

while ((e2 > 0) and (x0+x1 >= 2*Thickness)) do
begin
i := Min(dx2,dy2);
ed := Max(dx2,dy2);

if (y0 = y1+1) and (2*e2 > dx2) and (a2 > b2) then
ed := a2/4
else
ed += 2*ed*i*i/(4*ed*ed+i*i);

Alpha := Byte(Round(255-255*e2/ed));
PixelProc(Round(Thickness), y0, Alpha);
PixelProc(Round(x0+x1-Thickness), y0, Alpha);
PixelProc(Round(Thickness), y1, Alpha);
PixelProc(Round(x0+x1-Thickness), y1, Alpha);

if (e2+dy2+a2 < dx2) then
Break;

Thickness += 1;
e2 -= dx2;
dx2 -= b2;
end;

dy2 += a2;
e2 += dy2;
y0 += 1;
y1 -= 1;
dy += a;
err += dy;
until (x0 >= x1);

while (y0-y1 <= b) do
begin
Alpha := Byte(Round(255*4*err/b1));

PixelProc(x0, y0, Alpha);
PixelProc(x1, y0, Alpha);

y0 += 1;

PixelProc(x0, y1, Alpha);
PixelProc(x1, y1, Alpha);

y1 -= 1;
dy += a;
err += dy;
end;
end;

64 changes: 64 additions & 0 deletions Source/image/drawlineaa.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// https://zingl.github.io/bresenham.js

procedure DrawLineAA(x0, y0, x1, y1: Integer; Thickness: Single);
var
dx, dy, err: Integer;
e2, x2, y2: Integer;
ed: Single;
sx, sy: Integer;
begin
dx := Abs(x1 - x0);
dy := Abs(y1 - y0);

if (x0 < x1) then sx := 1 else sx := -1;
if (y0 < y1) then sy := 1 else sy := -1;

err := dx-dy;
if (dx+dy = 0) then
ed := 1
else
ed := Sqrt(Double(dx*dx) + Double(dy*dy));

Thickness := (Thickness + 1) / 2;
while True do
begin
PixelProc(x0, y0, Round(Max(0, 255 * (Abs(err-dx+dy)/ed-Thickness+1))));

e2 := err;
x2 := x0;
if (2*e2 >= -dx) then
begin
e2 += dy;
y2 := y0;
while (e2 < ed*Thickness) and ((y1 <> y2) or (dx > dy)) do
begin
y2 += sy;
PixelProc(x0, y2, Round(Max(0, 255 * (Abs(e2)/ed-Thickness+1))));
e2 += dx;
end;
if (x0 = x1) then
Break;

e2 := err;
err -= dy;
x0 += sx;
end;

if (2*e2 <= dy) then
begin
e2 := dx-e2;
while (e2 < ed*Thickness) and ((x1 <> x2) or (dx < dy)) do
begin
x2 += sx;
PixelProc(x2, y0, Round(Max(0, 255 * (Abs(e2)/ed-Thickness+1))));
e2 += dy;
end;
if (y0 = y1) then
Break;

err += dx;
y0 += sy;
end;
end;
end;

26 changes: 26 additions & 0 deletions Source/image/drawpixelaa.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
procedure PixelProc(const X, Y: Integer; const Alpha: Byte); inline;
var
Pixel: PColorBGRA;
APlus1, APlus1Inv: UInt32;
begin
if (X >= 0) and (Y >= 0) and (X < FWidth) and (Y < FHeight) then
begin
Pixel := @FData[Y*FWidth+X];

if (Alpha > 0) then
begin
if (Pixel^.A > 0) then // dont blend again
Exit;

APlus1 := Alpha + 1;
APlus1Inv := 255 - Alpha + 1;

Pixel^.R := (BGRA.R * APlus1Inv) shr 8 + Pixel^.R * APlus1 shr 8;
Pixel^.G := (BGRA.G * APlus1Inv) shr 8 + Pixel^.G * APlus1 shr 8;
Pixel^.B := (BGRA.B * APlus1Inv) shr 8 + Pixel^.B * APlus1 shr 8;
Pixel^.A := Alpha;
end else
Pixel^ := BGRA;
end;
end;

Loading

0 comments on commit 3f6303e

Please sign in to comment.