Стартовый пул

This commit is contained in:
2024-04-02 08:46:59 +03:00
parent fd57fffd3a
commit 3bb34d000b
5591 changed files with 3291734 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="bgrabitmappack"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="5">
<Unit0>
<Filename Value="aa_demo.lpr"/>
<IsPartOfProject Value="True"/>
<CursorPos Y="15"/>
<UsageCount Value="21"/>
</Unit0>
<Unit1>
<Filename Value="aa_demo_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="aa_demo_main"/>
<TopLine Value="67"/>
<CursorPos X="72" Y="91"/>
<UsageCount Value="21"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\bgrabitmap\bgrapolygon.pas"/>
<UnitName Value="BGRAPolygon"/>
<EditorIndex Value="2"/>
<TopLine Value="244"/>
<CursorPos X="69" Y="259"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\bgrabitmap\bgrafillinfo.pas"/>
<UnitName Value="BGRAFillInfo"/>
<EditorIndex Value="3"/>
<TopLine Value="497"/>
<CursorPos Y="504"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit3>
<Unit4>
<Filename Value="..\bgrabitmap\bgrapixel.inc"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="1"/>
<TopLine Value="326"/>
<CursorPos X="44" Y="330"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit4>
</Units>
<JumpHistory Count="20" HistoryIndex="19">
<Position1>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="55" Column="12" TopLine="39"/>
</Position1>
<Position2>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="42" TopLine="37"/>
</Position2>
<Position3>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="55" Column="23" TopLine="45"/>
</Position3>
<Position4>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="67" Column="36" TopLine="42"/>
</Position4>
<Position5>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="102" Column="3" TopLine="84"/>
</Position5>
<Position6>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="133" Column="30" TopLine="113"/>
</Position6>
<Position7>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="134" TopLine="119"/>
</Position7>
<Position8>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="112" Column="7" TopLine="98"/>
</Position8>
<Position9>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="59" Column="66" TopLine="44"/>
</Position9>
<Position10>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="146" Column="30" TopLine="109"/>
</Position10>
<Position11>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="28" TopLine="17"/>
</Position11>
<Position12>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="102" Column="5" TopLine="82"/>
</Position12>
<Position13>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="76" Column="42" TopLine="55"/>
</Position13>
<Position14>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="77" Column="71" TopLine="61"/>
</Position14>
<Position15>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="78" Column="71" TopLine="62"/>
</Position15>
<Position16>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="80" Column="71" TopLine="64"/>
</Position16>
<Position17>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="125" Column="39" TopLine="118"/>
</Position17>
<Position18>
<Filename Value="aa_demo_main.pas"/>
<Caret Line="103" Column="3" TopLine="81"/>
</Position18>
<Position19>
<Filename Value="..\bgrabitmap\bgrapixel.inc"/>
</Position19>
<Position20>
<Filename Value="..\bgrabitmap\bgrapixel.inc"/>
<Caret Line="371" Column="10" TopLine="362"/>
</Position20>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="aa_demo"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program aa_demo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, aa_demo_main, bgrabitmappack
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,78 @@
object Form1: TForm1
Left = 516
Height = 429
Top = 160
Width = 557
Caption = 'BGRA Antialiasing demo'
ClientHeight = 429
ClientWidth = 557
OnCreate = FormCreate
OnMouseDown = FormMouseDown
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
OnPaint = FormPaint
Position = poDefaultPosOnly
LCLVersion = '1.4.0.4'
object Panel1: TPanel
Left = 88
Height = 55
Top = 374
Width = 469
Anchors = [akLeft, akRight, akBottom]
ClientHeight = 55
ClientWidth = 469
TabOrder = 0
object Label1: TLabel
Left = 4
Height = 15
Top = 2
Width = 46
Caption = 'Pixel size'
ParentColor = False
end
object TrackBar_PixelSize: TTrackBar
Left = 4
Height = 25
Top = 21
Width = 373
Frequency = 4
Max = 100
Min = 8
OnChange = TrackBar_PixelSizeChange
Position = 32
Anchors = [akTop, akLeft, akRight]
TabOrder = 0
end
object Label_PixelSizeValue: TLabel
Left = 56
Height = 15
Top = 2
Width = 16
Caption = '= ?'
ParentColor = False
end
object Label2: TLabel
Left = 383
Height = 15
Top = 2
Width = 76
Anchors = [akTop, akRight]
Caption = 'Gamma factor'
ParentColor = False
end
object SpinEdit_Gamma: TFloatSpinEdit
Left = 392
Height = 23
Top = 22
Width = 66
Anchors = [akTop, akRight]
DecimalPlaces = 1
Increment = 0.1
MaxValue = 3
MinValue = 0.1
OnChange = SpinEdit_GammaChange
TabOrder = 1
Value = 1.7
end
end
end

View File

@@ -0,0 +1,187 @@
unit aa_demo_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
ExtCtrls, StdCtrls, BGRABitmapTypes, BGRABitmap, lmessages, Spin;
type
{ TForm1 }
TForm1 = class(TForm)
SpinEdit_Gamma: TFloatSpinEdit;
Label1: TLabel;
Label2: TLabel;
Label_PixelSizeValue: TLabel;
Panel1: TPanel;
TrackBar_PixelSize: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormPaint(Sender: TObject);
procedure SpinEdit_GammaChange(Sender: TObject);
procedure TrackBar_PixelSizeChange(Sender: TObject);
procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
private
{ private declarations }
public
{ public declarations }
pts: array[0..2] of TPointF;
formLoaded: boolean;
MovingPointIndex: integer;
MovingOrigin: TPointF;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure NicePoint(bmp: TBGRABitmap; x, y: single);
begin
bmp.EllipseAntialias(x,y,4,4,BGRA(0,0,0,192),1);
bmp.EllipseAntialias(x,y,3,3,BGRA(255,255,255,192),1);
bmp.EllipseAntialias(x,y,2,2,BGRA(0,0,0,192),1);
end;
{ TForm1 }
procedure TForm1.FormPaint(Sender: TObject);
var zoomTx,zoomTy,tx,ty,pixSize: integer;
bmp,bmpPreview: TBGRABitmap;
i: Integer;
x,y: integer;
function coordToBmp(pt: TPointF): TPointF;
begin
result := (pt+PointF(0.5,0.5))*(1/pixSize)-PointF(0.5,0.5);
end;
begin
zoomTx := ClientWidth;
zoomTy := Panel1.Top;
pixSize := TrackBar_PixelSize.Position;
tx := (zoomTx+pixSize-1) div pixSize;
ty := (zoomTy+pixSize-1) div pixSize;
//draw triangle
bmp := TBGRABitmap.Create(tx,ty,BGRAWhite);
bmp.FillPolyAntialias([coordToBmp(pts[0]),coordToBmp(pts[1]),coordToBmp(pts[2])],BGRABlack);
//draw lower-left preview
bmpPreview := TBGRABitmap.Create(panel1.left,panel1.height,BGRAWhite);
x := (bmpPreview.Width-bmp.width) div 2;
y := (bmpPreview.Height-bmp.Height) div 2;
if x < 1 then x := 1;
if y < 1 then y := 1;
bmpPreview.Rectangle(x-1,y-1,x+bmp.width+1,y+bmp.height+1,BGRA(255,0,0),dmSet);
bmpPreview.PutImage(x,y,bmp,dmSet);
bmpPreview.Draw(Canvas,0,panel1.top);
bmpPreview.Free;
//zoom
BGRAReplace(bmp,bmp.Resample(tx*pixSize,ty*pixSize,rmSimpleStretch));
bmp.DrawPolygonAntialias(pts,BGRA(0,128,128,192),1);
for i := 0 to 2 do
NicePoint(bmp,pts[i].x,pts[i].y);
BGRAReplace(bmp,bmp.GetPart(rect(0,0,zoomTx,zoomTy)));
bmp.Draw(Canvas,0,0);
bmp.free;
end;
procedure TForm1.SpinEdit_GammaChange(Sender: TObject);
begin
if formLoaded then
begin
BGRASetGamma(SpinEdit_Gamma.Value);
Invalidate;
end;
end;
procedure TForm1.TrackBar_PixelSizeChange(Sender: TObject);
begin
Label_PixelSizeValue.Caption := '= ' + IntToStr(TrackBar_PixelSize.Position);
Invalidate;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
pts[0] := PointF(57,100);
pts[1] := PointF(369,170);
pts[2] := PointF(143,310);
Label_PixelSizeValue.Caption := '= ' + IntToStr(TrackBar_PixelSize.Position);
MovingPointIndex := -1;
SpinEdit_Gamma.Value := BGRAGetGamma;
formLoaded := true;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var maxDist,dist: single;
mousePos,vect: TPointF;
i: Integer;
begin
if Button <> mbLeft then exit;
//select point to move
MovingPointIndex := -1;
maxDist := 10;
mousePos := PointF(X,Y);
MovingOrigin := mousePos;
for i := 0 to high(pts) do
begin
vect := pts[i] - mousePos;
dist := sqrt(vect*vect);
if dist < maxDist then
begin
maxDist := dist;
MovingPointIndex := i;
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mousePos: TPointF;
i: Integer;
begin
if ssLeft in Shift then
begin
mousePos := PointF(X,Y);
if MovingPointIndex <> -1 then
pts[MovingPointIndex].Offset(mousePos-MovingOrigin) else
begin
for i := 0 to high(pts) do
pts[i].Offset(mousePos-MovingOrigin);
end;
Invalidate;
MovingOrigin := mousePos;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then MovingPointIndex := -1;
end;
end.

View File

@@ -0,0 +1,148 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
<ActiveWindowIndexAtStart Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="bgrabitmappack"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="2">
<Unit0>
<Filename Value="alpha_gradient.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="alpha_gradient"/>
<UsageCount Value="20"/>
</Unit0>
<Unit1>
<Filename Value="alpha_gradient_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="alpha_gradient_main"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="0"/>
<WindowIndex Value="0"/>
<TopLine Value="110"/>
<CursorPos X="98" Y="133"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
</Units>
<JumpHistory Count="12" HistoryIndex="11">
<Position1>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="63" Column="24" TopLine="31"/>
</Position1>
<Position2>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="67" Column="11" TopLine="47"/>
</Position2>
<Position3>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="68" Column="20" TopLine="45"/>
</Position3>
<Position4>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="32" Column="26" TopLine="22"/>
</Position4>
<Position5>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="71" Column="22" TopLine="53"/>
</Position5>
<Position6>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="84" Column="20" TopLine="57"/>
</Position6>
<Position7>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="41" Column="57" TopLine="19"/>
</Position7>
<Position8>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="118" Column="31" TopLine="92"/>
</Position8>
<Position9>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="56" Column="13" TopLine="38"/>
</Position9>
<Position10>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="99" Column="84" TopLine="81"/>
</Position10>
<Position11>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="114" Column="47" TopLine="94"/>
</Position11>
<Position12>
<Filename Value="alpha_gradient_main.pas"/>
<Caret Line="34" Column="1" TopLine="22"/>
</Position12>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="alpha_gradient"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program alpha_gradient;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, alpha_gradient_main, bgrabitmappack
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,14 @@
object Form1: TForm1
Left = 541
Height = 389
Top = 140
Width = 564
Caption = 'BGRA Alpha gradient'
OnCreate = FormCreate
OnMouseDown = FormMouseDown
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
OnPaint = FormPaint
Position = poDefaultPosOnly
LCLVersion = '0.9.30'
end

View File

@@ -0,0 +1,215 @@
unit alpha_gradient_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics,
Dialogs, BGRABitmapTypes, BGRABitmap, LMessages;
type
{ TForm1 }
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormPaint(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
ellipses: array of record
x,y,w,h: integer;
c: TBGRAPixel;
end;
pts: array[0..2] of TPointF;
MovingPointIndex: integer;
MovingOrigin: TPointF;
procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
end;
var
Form1: TForm1;
implementation
uses BGRAGradientScanner, BGRATransform;
procedure NicePoint(bmp: TBGRABitmap; x, y: single);
begin
bmp.EllipseAntialias(x,y,4,4,BGRA(0,0,0,192),1);
bmp.EllipseAntialias(x,y,3,3,BGRA(255,255,255,192),1);
bmp.EllipseAntialias(x,y,2,2,BGRA(0,0,0,192),1);
end;
{$R *.lfm}
type
{ TMultiplyGradient }
TMultiplyGradient = class(TBGRACustomScanner)
function ScanAt(X, Y: Single): TBGRAPixel; override;
end;
{ TMultiplyGradient }
function TMultiplyGradient.ScanAt(X, Y: Single): TBGRAPixel;
var fvalue: single;
value: integer;
begin
fvalue := abs(x*y*255);
if fvalue > 255 then
value := 255
else
value := round(fvalue);
result := BGRA(value,value,value,255);
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
setlength(ellipses,100);
for i := 0 to high(ellipses) do
with ellipses[i] do
begin
x := random(65536);
y := random(65536);
w := random(100)+5;
h := random(100)+5;
c := BGRA(random(256),random(256),random(256),random(128)+64);
end;
pts[0] := PointF(250,200);
pts[1] := PointF(300,150);
pts[2] := PointF(300,250);
MovingPointIndex := -1;
end;
procedure TForm1.FormPaint(Sender: TObject);
const ellipseRadius = 160;
var bmp: TBGRABitmap;
tx,ty: integer;
i: Integer;
ellipseLayer: TBGRABitmap;
gradient: TBGRAGradientScanner;
multigrad: TBGRAMultiGradient;
affine: TBGRAAffineScannerTransform;
multiply: TMultiplyGradient;
mask: TBGRABitmap;
ellipseLayerOffset: TPointF;
begin
tx := ClientWidth;
ty := ClientHeight;
if (tx=0) or (ty=0) then exit;
//create background
bmp := TBGRABitmap.Create(tx,ty, BGRAWhite);
for i := 0 to high(ellipses) do
with ellipses[i] do
bmp.FillEllipseAntialias(x mod tx,y mod ty,w/2,h/2,c);
//create center red-yellow ellipse
ellipseLayerOffset := PointF((tx-(2*ellipseRadius+1))/2,(ty-(2*ellipseRadius+1))/2);
ellipseLayer := TBGRABitmap.Create(2*ellipseRadius +1 + 1,2*ellipseRadius +1 +1);
multiGrad := TBGRAMultiGradient.Create([BGRA(0,64,0),BGRA(160,160,0),BGRA(128,0,0)],[0,1/2,1],True);
gradient := TBGRAGradientScanner.Create(multiGrad,gtRadial,PointF(0,0),PointF(1,0));
affine := TBGRAAffineScannerTransform.Create(gradient);
affine.Scale(ellipseRadius*1.2,ellipseRadius*0.8);
affine.RotateDeg(30);
affine.Translate(ellipseRadius+frac(ellipseLayerOffset.X),ellipseRadius+frac(ellipseLayerOffset.Y));
ellipseLayer.FillEllipseAntialias(ellipseRadius+frac(ellipseLayerOffset.X),ellipseRadius+frac(ellipseLayerOffset.Y),
ellipseRadius,ellipseRadius,BGRA(192,128,0));
ellipseLayer.FillEllipseAntialias(ellipseRadius+frac(ellipseLayerOffset.X),ellipseRadius+frac(ellipseLayerOffset.Y),
ellipseRadius,ellipseRadius,affine);
affine.Free;
gradient.Free;
multiGrad.Free;
//apply multiply mask
multiply := TMultiplyGradient.Create;
affine := TBGRAAffineScannerTransform.Create(multiply);
affine.Fit(pts[0],pts[1],pts[2]);
affine.Translate(-trunc(ellipseLayerOffset.X),-trunc(ellipseLayerOffset.Y));
mask := TBGRABitmap.Create(ellipseLayer.Width,ellipseLayer.Height);
mask.Fill(affine);
ellipseLayer.ApplyMask(mask);
mask.Free;
affine.Free;
multiply.Free;
bmp.PutImage(trunc(ellipseLayerOffset.X),trunc(ellipseLayerOffset.Y),ellipseLayer,dmDrawWithTransparency);
ellipseLayer.Free;
for i := 0 to 2 do
NicePoint(bmp,pts[i].x,pts[i].y);
bmp.Draw(Canvas,0,0);
bmp.Free;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var maxDist,dist: single;
mousePos,vect: TPointF;
i: Integer;
begin
if Button <> mbLeft then exit;
//select point to move
MovingPointIndex := -1;
maxDist := 10;
mousePos := PointF(X,Y);
for i := 0 to 2 do
begin
vect := pts[i] - mousePos;
dist := sqrt(vect*vect);
if dist < maxDist then
begin
maxDist := dist;
MovingPointIndex := i;
MovingOrigin := mousePos;
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mousePos: TPointF;
begin
if MovingPointIndex <> -1 then
begin
mousePos := PointF(X,Y);
pts[MovingPointIndex].Offset(mousePos-MovingOrigin);
Invalidate;
MovingOrigin := mousePos;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then MovingPointIndex := -1;
end;
end.

View File

@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="etpackage"/>
</Item1>
<Item2>
<PackageName Value="bgrabitmappack"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="6">
<Unit0>
<Filename Value="blur.lpr"/>
<IsPartOfProject Value="True"/>
<UsageCount Value="23"/>
</Unit0>
<Unit1>
<Filename Value="blur_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="blur_main"/>
<IsVisibleTab Value="True"/>
<TopLine Value="70"/>
<CursorPos X="24" Y="72"/>
<UsageCount Value="23"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<UnitName Value="BGRADefaultBitmap"/>
<EditorIndex Value="1"/>
<TopLine Value="3215"/>
<CursorPos X="32" Y="3218"/>
<UsageCount Value="12"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<UnitName Value="BGRAFilters"/>
<EditorIndex Value="3"/>
<TopLine Value="36"/>
<CursorPos X="10" Y="47"/>
<UsageCount Value="12"/>
<Loaded Value="True"/>
</Unit3>
<Unit4>
<Filename Value="..\bgrabitmap\blurfast.inc"/>
<EditorIndex Value="4"/>
<TopLine Value="78"/>
<CursorPos X="32" Y="121"/>
<UsageCount Value="12"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\bgrabitmap\blurnormal.inc"/>
<EditorIndex Value="2"/>
<TopLine Value="215"/>
<CursorPos X="73" Y="234"/>
<UsageCount Value="12"/>
<Loaded Value="True"/>
</Unit5>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="368" TopLine="356"/>
</Position1>
<Position2>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="369" TopLine="356"/>
</Position2>
<Position3>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="370" TopLine="356"/>
</Position3>
<Position4>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="371" TopLine="356"/>
</Position4>
<Position5>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="372" TopLine="356"/>
</Position5>
<Position6>
<Filename Value="..\bgrabitmap\blurfast.inc"/>
<Caret Line="124" Column="24" TopLine="113"/>
</Position6>
<Position7>
<Filename Value="..\bgrabitmap\blurfast.inc"/>
<Caret Line="95" Column="36" TopLine="72"/>
</Position7>
<Position8>
<Filename Value="..\bgrabitmap\blurfast.inc"/>
<Caret Line="105" Column="42" TopLine="102"/>
</Position8>
<Position9>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="513" Column="24" TopLine="493"/>
</Position9>
<Position10>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="520" Column="23" TopLine="501"/>
</Position10>
<Position11>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="522" Column="53" TopLine="501"/>
</Position11>
<Position12>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="520" Column="46" TopLine="502"/>
</Position12>
<Position13>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="527" Column="27" TopLine="509"/>
</Position13>
<Position14>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="559" Column="30" TopLine="502"/>
</Position14>
<Position15>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="527" Column="38" TopLine="509"/>
</Position15>
<Position16>
<Filename Value="..\bgrabitmap\blurnormal.inc"/>
<Caret Line="218" Column="17" TopLine="209"/>
</Position16>
<Position17>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="527" Column="16" TopLine="514"/>
</Position17>
<Position18>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="484" TopLine="471"/>
</Position18>
<Position19>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="578" Column="35" TopLine="569"/>
</Position19>
<Position20>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="581" Column="45" TopLine="494"/>
</Position20>
<Position21>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="519" Column="23" TopLine="506"/>
</Position21>
<Position22>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="518" Column="16" TopLine="506"/>
</Position22>
<Position23>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="519" TopLine="506"/>
</Position23>
<Position24>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="521" TopLine="506"/>
</Position24>
<Position25>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="523" TopLine="506"/>
</Position25>
<Position26>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="516" Column="12" TopLine="506"/>
</Position26>
<Position27>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="520" TopLine="506"/>
</Position27>
<Position28>
<Filename Value="..\bgrabitmap\bgrafilters.pas"/>
<Caret Line="524" TopLine="506"/>
</Position28>
<Position29>
<Filename Value="blur_main.pas"/>
<Caret Line="36" TopLine="30"/>
</Position29>
<Position30>
<Filename Value="blur_main.pas"/>
<Caret Line="9" Column="72" TopLine="5"/>
</Position30>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="blur"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program blur;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, blur_main, bgrabitmappack, etpackage
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,153 @@
object Form1: TForm1
Left = 657
Height = 348
Top = 144
Width = 536
Caption = 'BGRA Blur'
ClientHeight = 348
ClientWidth = 536
OnCreate = FormCreate
OnDestroy = FormDestroy
OnMouseDown = FormMouseDown
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
OnPaint = FormPaint
Position = poDefaultPosOnly
LCLVersion = '1.4.0.4'
object Panel1: TPanel
Left = 0
Height = 100
Top = 248
Width = 536
Anchors = [akLeft, akRight, akBottom]
ClientHeight = 100
ClientWidth = 536
Color = clForm
ParentColor = False
TabOrder = 0
object TrackBar_BlurRadiusX: TTrackBar
Left = 152
Height = 25
Top = 24
Width = 353
Frequency = 10
Max = 400
OnChange = TrackBar_BlurRadiusChange
Position = 150
Anchors = [akTop, akLeft, akRight]
TabOrder = 0
end
object Label_RadiusX: TLabel
Left = 160
Height = 15
Top = 8
Width = 66
Caption = 'Blur radius X'
end
object Label2: TLabel
Left = 8
Height = 15
Top = 8
Width = 47
Caption = 'Blur type'
end
object Radio_Fast: TRadioButton
Left = 8
Height = 19
Top = 41
Width = 41
Caption = 'Fast'
Checked = True
OnChange = Radio_Change
TabOrder = 1
TabStop = True
end
object Radio_Corona: TRadioButton
Left = 72
Height = 19
Top = 24
Width = 59
Caption = 'Corona'
OnChange = Radio_Change
TabOrder = 3
end
object Radio_Disk: TRadioButton
Left = 72
Height = 19
Top = 41
Width = 42
Caption = 'Disk'
OnChange = Radio_Change
TabOrder = 4
end
object Radio_Motion: TRadioButton
Left = 72
Height = 19
Top = 58
Width = 59
Caption = 'Motion'
OnChange = Radio_Change
TabOrder = 5
end
object Radio_Radial: TRadioButton
Left = 8
Height = 19
Top = 58
Width = 52
Caption = 'Radial'
OnChange = Radio_Change
TabOrder = 6
end
object Label_RadiusValueX: TLabel
Left = 235
Height = 15
Top = 8
Width = 16
Caption = '= ?'
end
object Radio_Box: TRadioButton
Left = 8
Height = 19
Top = 24
Width = 40
Caption = 'Box'
OnChange = Radio_Change
TabOrder = 2
end
object TrackBar_BlurRadiusY: TTrackBar
Left = 152
Height = 25
Top = 72
Width = 353
Frequency = 10
Max = 400
OnChange = TrackBar_BlurRadiusChange
Position = 150
Anchors = [akTop, akLeft, akRight]
TabOrder = 7
end
object Label_RadiusY: TLabel
Left = 160
Height = 15
Top = 56
Width = 66
Caption = 'Blur radius Y'
end
object Label_RadiusValueY: TLabel
Left = 235
Height = 15
Top = 56
Width = 16
Caption = '= ?'
end
object Radio_OrientedMotion: TRadioButton
Left = 72
Height = 19
Top = 75
Width = 66
Caption = 'Oriented'
OnChange = Radio_Change
TabOrder = 8
end
end
end

View File

@@ -0,0 +1,201 @@
unit blur_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
ExtCtrls, StdCtrls, BGRABitmap, BGRABitmapTypes, EpikTimer, LMessages,
BGRAGrayscaleMask;
type
{ TForm1 }
TForm1 = class(TForm)
Label_RadiusValueY: TLabel;
Label_RadiusX: TLabel;
Label2: TLabel;
Label_RadiusY: TLabel;
Label_RadiusValueX: TLabel;
Panel1: TPanel;
Radio_Box: TRadioButton;
Radio_Motion: TRadioButton;
Radio_Fast: TRadioButton;
Radio_Corona: TRadioButton;
Radio_Disk: TRadioButton;
Radio_OrientedMotion: TRadioButton;
Radio_Radial: TRadioButton;
TrackBar_BlurRadiusX: TTrackBar;
TrackBar_BlurRadiusY: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
procedure FormPaint(Sender: TObject);
procedure Radio_Change(Sender: TObject);
procedure TrackBar_BlurRadiusChange(Sender: TObject);
procedure WMEraseBkgnd(var {%H-}Message: TLMEraseBkgnd); message LM_ERASEBKGND;
private
{ private declarations }
procedure UpdateLabelRadius;
public
{ public declarations }
image: TBGRABitmap;
shadowBase: TGrayscaleMask;
timer : TEpikTimer;
movingShadow: boolean;
movingOrigin,shadowOfs: TPoint;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
function ComputeAngle(dx, dy: single): single;
begin
if dy = 0 then
begin
if dx < 0 then result := 180 else result := 0;
end else
if dx = 0 then
begin
if dy < 0 then result := -90 else result := 90;
end else
begin
result := ArcTan(dy/dx)*180/Pi;
if dx < 0 then result += 180;
end;
end;
{ TForm1 }
procedure TForm1.FormPaint(Sender: TObject);
var bmp: TBGRABitmap;
ombre: TGrayscaleMask;
x,y,tx,ty: integer;
blurType: TRadialBlurType;
radiusX,radiusY,len: single;
begin
tx := clientWidth;
ty := Panel1.Top;
bmp := TBGRABitmap.Create(tx,ty,BGRAWhite);
x := (tx-image.Width) div 2;
y := (ty-image.Height) div 2;
radiusX := TrackBar_BlurRadiusX.Position/10;
radiusY := TrackBar_BlurRadiusY.Position/10;
timer.Clear;
timer.Start;
if Radio_Motion.Checked or Radio_OrientedMotion.Checked then
begin
len := sqrt(sqr(radiusX)+sqr(radiusY));
ombre := shadowBase.FilterBlurMotion(len*2,ComputeAngle(radiusX,radiusY),Radio_OrientedMotion.Checked) as TGrayscaleMask;
end else
begin
if Radio_Box.Checked then
begin
blurType := rbBox;
ombre := shadowBase.FilterBlurRadial(radiusX,radiusY,blurType) as TGrayscaleMask;
end else
begin
if Radio_Fast.Checked then blurType := rbFast else
if Radio_Corona.Checked then blurType := rbCorona else
if Radio_Disk.Checked then blurType := rbDisk else
if Radio_Radial.Checked then blurType := rbNormal;
ombre := shadowBase.FilterBlurRadial(radiusX,radiusY,blurType) as TGrayscaleMask;
end;
end;
timer.Stop;
ombre.Rectangle(0,0,ombre.width,ombre.height,TByteMask.New(128));
bmp.FillMask(x+shadowOfs.x,y+shadowOfs.y,ombre,BGRA(64,128,64), dmDrawWithTransparency);
ombre.free;
bmp.PutImage(x,y,image,dmDrawWithTransparency);
bmp.TextOut(0,0,inttostr(round(timer.Elapsed*1000))+' ms',BGRABlack);
bmp.Draw(Canvas,0,0);
bmp.Free;
end;
procedure TForm1.Radio_Change(Sender: TObject);
begin
Invalidate;
end;
procedure TForm1.TrackBar_BlurRadiusChange(Sender: TObject);
begin
UpdateLabelRadius;
Repaint;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.UpdateLabelRadius;
begin
Label_RadiusValueX.Caption := '= '+FloatToStrF(TrackBar_BlurRadiusX.Position/10,ffFixed,7,1);
Label_RadiusValueY.Caption := '= '+FloatToStrF(TrackBar_BlurRadiusY.Position/10,ffFixed,7,1);
Label_RadiusValueX.Update;
Label_RadiusValueY.Update;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
image := TBGRABitmap.Create(160,200);
image.FontName := 'Times New Roman';
image.FontHeight := 300;
image.FontAntialias:= true;
image.TextOut(image.Width div 2,-100,'a',BGRA(128,192,128,255),taCenter);
shadowBase := TGrayscaleMask.Create(image, cAlpha);
UpdateLabelRadius;
timer := TEpikTimer.Create(Self);
shadowOfs := Point(10,10);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
image.free;
shadowBase.free;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
begin
movingOrigin := Point(X,Y);
movingShadow := true;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if movingShadow then
begin
inc(shadowOfs.x, X-movingOrigin.X);
inc(shadowOfs.y, Y-movingOrigin.Y);
movingOrigin := Point(X,Y);
Invalidate;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
movingShadow:= false;
end;
end.

View File

@@ -0,0 +1,542 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="bgrabitmappack"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="50">
<Unit0>
<Filename Value="bspline.lpr"/>
<IsPartOfProject Value="True"/>
<UsageCount Value="85"/>
</Unit0>
<Unit1>
<Filename Value="bspline_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<IsVisibleTab Value="True"/>
<TopLine Value="132"/>
<CursorPos X="31" Y="150"/>
<UsageCount Value="85"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<UnitName Value="BGRADefaultBitmap"/>
<EditorIndex Value="-1"/>
<TopLine Value="568"/>
<CursorPos X="18" Y="589"/>
<UsageCount Value="40"/>
</Unit2>
<Unit3>
<Filename Value="..\bgrabitmap\bgrapolygon.pas"/>
<UnitName Value="BGRAPolygon"/>
<EditorIndex Value="-1"/>
<TopLine Value="930"/>
<CursorPos X="46" Y="949"/>
<UsageCount Value="42"/>
</Unit3>
<Unit4>
<Filename Value="..\bgrabitmap\bgraresample.pas"/>
<UnitName Value="BGRAResample"/>
<EditorIndex Value="-1"/>
<TopLine Value="68"/>
<CursorPos X="10" Y="87"/>
<UsageCount Value="42"/>
</Unit4>
<Unit5>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<UnitName Value="BGRABitmapTypes"/>
<EditorIndex Value="-1"/>
<UsageCount Value="23"/>
</Unit5>
<Unit6>
<Filename Value="..\bgrabitmap\bgrapen.pas"/>
<UnitName Value="BGRAPen"/>
<EditorIndex Value="-1"/>
<TopLine Value="732"/>
<CursorPos Y="753"/>
<UsageCount Value="38"/>
</Unit6>
<Unit7>
<Filename Value="D:\lazarus\lcl\graphics.pp"/>
<TopLine Value="82"/>
<CursorPos X="3" Y="95"/>
<UsageCount Value="6"/>
</Unit7>
<Unit8>
<Filename Value="..\bgrabitmap\bgrapath.pas"/>
<UnitName Value="BGRAPath"/>
<EditorIndex Value="-1"/>
<TopLine Value="2560"/>
<CursorPos X="21" Y="2570"/>
<UsageCount Value="39"/>
</Unit8>
<Unit9>
<Filename Value="C:\lazarus\fpc\2.6.2\source\rtl\objpas\math.pp"/>
<TopLine Value="175"/>
<CursorPos X="10" Y="193"/>
<UsageCount Value="15"/>
</Unit9>
<Unit10>
<Filename Value="..\bgrabitmap\bgrafillinfo.pas"/>
<UnitName Value="BGRAFillInfo"/>
<EditorIndex Value="-1"/>
<TopLine Value="234"/>
<CursorPos X="20" Y="253"/>
<UsageCount Value="15"/>
</Unit10>
<Unit11>
<Filename Value="..\bgrabitmap\csscolorconst.inc"/>
<EditorIndex Value="-1"/>
<UsageCount Value="14"/>
</Unit11>
<Unit12>
<Filename Value="..\bgrabitmap\geometrytypes.inc"/>
<EditorIndex Value="-1"/>
<UsageCount Value="29"/>
</Unit12>
<Unit13>
<Filename Value="..\bgrabitmap\bgragraphics.pas"/>
<UnitName Value="BGRAGraphics"/>
<EditorIndex Value="-1"/>
<TopLine Value="39"/>
<CursorPos X="3" Y="58"/>
<UsageCount Value="13"/>
</Unit13>
<Unit14>
<Filename Value="..\bgrabitmap\bgratransform.pas"/>
<UnitName Value="BGRATransform"/>
<EditorIndex Value="-1"/>
<CursorPos X="3" Y="14"/>
<UsageCount Value="15"/>
</Unit14>
<Unit15>
<Filename Value="C:\lazarus\lcl\graphtype.pp"/>
<TopLine Value="23"/>
<CursorPos X="5" Y="42"/>
<UsageCount Value="11"/>
</Unit15>
<Unit16>
<Filename Value="C:\lazarus\lcl\graphics.pp"/>
<TopLine Value="153"/>
<CursorPos X="3" Y="172"/>
<UsageCount Value="11"/>
</Unit16>
<Unit17>
<Filename Value="C:\lazarus\fpc\2.6.2\source\rtl\objpas\types.pp"/>
<TopLine Value="276"/>
<CursorPos X="10" Y="295"/>
<UsageCount Value="11"/>
</Unit17>
<Unit18>
<Filename Value="C:\lazarus\lcl\include\customcontrol.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="65"/>
<CursorPos Y="79"/>
<UsageCount Value="30"/>
</Unit18>
<Unit19>
<Filename Value="..\bgrabitmap\bgragifformat.pas"/>
<CursorPos X="26" Y="8"/>
<UsageCount Value="10"/>
</Unit19>
<Unit20>
<Filename Value="..\bgrabitmap\bgracustombitmap.inc"/>
<EditorIndex Value="-1"/>
<CursorPos X="62"/>
<UsageCount Value="27"/>
</Unit20>
<Unit21>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpwritepcx.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="60"/>
<CursorPos X="79" Y="78"/>
<UsageCount Value="12"/>
</Unit21>
<Unit22>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpimage.pp"/>
<TopLine Value="530"/>
<CursorPos X="11" Y="549"/>
<UsageCount Value="9"/>
</Unit22>
<Unit23>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpreadpcx.pas"/>
<CursorPos Y="2"/>
<UsageCount Value="9"/>
</Unit23>
<Unit24>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpwritexpm.pp"/>
<TopLine Value="5"/>
<CursorPos X="3" Y="24"/>
<UsageCount Value="9"/>
</Unit24>
<Unit25>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fphandler.inc"/>
<TopLine Value="88"/>
<CursorPos X="3" Y="92"/>
<UsageCount Value="9"/>
</Unit25>
<Unit26>
<Filename Value="..\bgrabitmap\bgrareadpcx.pas"/>
<UsageCount Value="9"/>
</Unit26>
<Unit27>
<Filename Value="..\bgrabitmap\bgrareadxpm.pas"/>
<UsageCount Value="9"/>
</Unit27>
<Unit28>
<Filename Value="..\bgrabitmap\bgracanvas2d.pas"/>
<UnitName Value="BGRACanvas2D"/>
<EditorIndex Value="-1"/>
<TopLine Value="248"/>
<CursorPos X="3" Y="263"/>
<UsageCount Value="15"/>
</Unit28>
<Unit29>
<Filename Value="..\bgrabitmap\bgrapixel.inc"/>
<EditorIndex Value="-1"/>
<UsageCount Value="12"/>
</Unit29>
<Unit30>
<Filename Value="..\bgrabitmap\bgrapolygonaliased.pas"/>
<UnitName Value="BGRAPolygonAliased"/>
<EditorIndex Value="-1"/>
<TopLine Value="719"/>
<CursorPos X="42" Y="737"/>
<UsageCount Value="12"/>
</Unit30>
<Unit31>
<Filename Value="..\bgrabitmap\polyaliaspersp.inc"/>
<EditorIndex Value="-1"/>
<TopLine Value="345"/>
<CursorPos X="42" Y="363"/>
<UsageCount Value="12"/>
</Unit31>
<Unit32>
<Filename Value="..\bgrabitmap\bgragradients.pas"/>
<UnitName Value="BGRAGradients"/>
<EditorIndex Value="-1"/>
<UsageCount Value="12"/>
</Unit32>
<Unit33>
<Filename Value="..\bgrabitmap\bgragradientscanner.pas"/>
<UnitName Value="BGRAGradientScanner"/>
<EditorIndex Value="-1"/>
<CursorPos X="14" Y="20"/>
<UsageCount Value="12"/>
</Unit33>
<Unit34>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpwritetga.pp"/>
<EditorIndex Value="-1"/>
<TopLine Value="6"/>
<CursorPos X="3" Y="37"/>
<UsageCount Value="12"/>
</Unit34>
<Unit35>
<Filename Value="..\bgrabitmap\bgrareadtga.pas"/>
<UnitName Value="BGRAReadTGA"/>
<EditorIndex Value="-1"/>
<TopLine Value="67"/>
<CursorPos X="70" Y="84"/>
<UsageCount Value="12"/>
</Unit35>
<Unit36>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpwritetiff.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="399"/>
<CursorPos X="51" Y="430"/>
<UsageCount Value="12"/>
</Unit36>
<Unit37>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fptiffcmn.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="24"/>
<CursorPos X="3" Y="43"/>
<UsageCount Value="12"/>
</Unit37>
<Unit38>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpreadtiff.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="1461"/>
<CursorPos X="3" Y="1469"/>
<UsageCount Value="12"/>
</Unit38>
<Unit39>
<Filename Value="C:\lazarus\fpc\2.6.2\source\packages\fcl-image\src\fpreadxwd.pas"/>
<EditorIndex Value="-1"/>
<TopLine Value="218"/>
<CursorPos X="3" Y="255"/>
<UsageCount Value="12"/>
</Unit39>
<Unit40>
<Filename Value="..\bgrabitmap\bgratext.pas"/>
<UnitName Value="BGRAText"/>
<EditorIndex Value="-1"/>
<TopLine Value="44"/>
<CursorPos X="10" Y="63"/>
<UsageCount Value="12"/>
</Unit40>
<Unit41>
<Filename Value="..\bgrabitmap\bgravectorize.pas"/>
<UnitName Value="BGRAVectorize"/>
<EditorIndex Value="-1"/>
<TopLine Value="1267"/>
<CursorPos X="40" Y="1286"/>
<UsageCount Value="10"/>
</Unit41>
<Unit42>
<Filename Value="..\bgrabitmap\bgratextfx.pas"/>
<UnitName Value="BGRATextFX"/>
<EditorIndex Value="-1"/>
<TopLine Value="653"/>
<CursorPos X="49" Y="672"/>
<UsageCount Value="10"/>
</Unit42>
<Unit43>
<Filename Value="C:\lazarus\lcl\lclproc.pas"/>
<UnitName Value="LCLProc"/>
<EditorIndex Value="-1"/>
<TopLine Value="2661"/>
<CursorPos X="3" Y="2678"/>
<UsageCount Value="10"/>
</Unit43>
<Unit44>
<Filename Value="C:\lazarus\components\lazutils\lazutf8.pas"/>
<UnitName Value="LazUTF8"/>
<EditorIndex Value="-1"/>
<CursorPos X="71" Y="18"/>
<UsageCount Value="10"/>
</Unit44>
<Unit45>
<Filename Value="..\bgrabitmap\bgrautf8.pas"/>
<UnitName Value="BGRAUTF8"/>
<EditorIndex Value="-1"/>
<TopLine Value="270"/>
<CursorPos X="60" Y="279"/>
<UsageCount Value="10"/>
</Unit45>
<Unit46>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<EditorIndex Value="1"/>
<TopLine Value="1238"/>
<CursorPos X="62" Y="1250"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit46>
<Unit47>
<Filename Value="..\..\bgrabitmap\bgraresample.pas"/>
<UnitName Value="BGRAResample"/>
<EditorIndex Value="3"/>
<TopLine Value="1186"/>
<CursorPos X="10" Y="1197"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit47>
<Unit48>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<UnitName Value="BGRAPath"/>
<EditorIndex Value="4"/>
<TopLine Value="599"/>
<CursorPos X="61" Y="616"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit48>
<Unit49>
<Filename Value="..\..\bgrabitmap\bgrabitmaptypes.pas"/>
<UnitName Value="BGRABitmapTypes"/>
<EditorIndex Value="2"/>
<CursorPos X="66" Y="13"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit49>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="473" Column="10" TopLine="455"/>
</Position1>
<Position2>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="529" Column="62" TopLine="508"/>
</Position2>
<Position3>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="602" Column="10" TopLine="597"/>
</Position3>
<Position4>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2313" Column="39" TopLine="2295"/>
</Position4>
<Position5>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="613" Column="69" TopLine="602"/>
</Position5>
<Position6>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="574" Column="63" TopLine="550"/>
</Position6>
<Position7>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1293" Column="66" TopLine="1276"/>
</Position7>
<Position8>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="613" Column="69" TopLine="602"/>
</Position8>
<Position9>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2388" Column="45" TopLine="2388"/>
</Position9>
<Position10>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1298" TopLine="1279"/>
</Position10>
<Position11>
<Filename Value="bspline_main.pas"/>
<Caret Line="135" Column="61" TopLine="122"/>
</Position11>
<Position12>
<Filename Value="bspline_main.pas"/>
<Caret Line="141" Column="32" TopLine="122"/>
</Position12>
<Position13>
<Filename Value="bspline_main.pas"/>
<Caret Line="143" TopLine="132"/>
</Position13>
<Position14>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2292" TopLine="2277"/>
</Position14>
<Position15>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2297" TopLine="2286"/>
</Position15>
<Position16>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2298" TopLine="2286"/>
</Position16>
<Position17>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2299" TopLine="2286"/>
</Position17>
<Position18>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2300" TopLine="2286"/>
</Position18>
<Position19>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2301" TopLine="2286"/>
</Position19>
<Position20>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="2302" TopLine="2286"/>
</Position20>
<Position21>
<Filename Value="..\..\bgrabitmap\bgrapath.pas"/>
<Caret Line="527" TopLine="509"/>
</Position21>
<Position22>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1111" TopLine="1096"/>
</Position22>
<Position23>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1112" TopLine="1096"/>
</Position23>
<Position24>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1113" TopLine="1096"/>
</Position24>
<Position25>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1253" TopLine="1238"/>
</Position25>
<Position26>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1254" TopLine="1238"/>
</Position26>
<Position27>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1255" TopLine="1238"/>
</Position27>
<Position28>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1257" TopLine="1238"/>
</Position28>
<Position29>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1258" TopLine="1238"/>
</Position29>
<Position30>
<Filename Value="..\..\bgrabitmap\geometrytypes.inc"/>
<Caret Line="1255" TopLine="1238"/>
</Position30>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="bspline"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program bspline;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, bspline_main, bgrabitmappack
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,129 @@
object Form1: TForm1
Left = 540
Height = 595
Top = 37
Width = 647
Caption = 'BGRA Spline interpolation'
ClientHeight = 595
ClientWidth = 647
OnCreate = FormCreate
OnDestroy = FormDestroy
OnMouseDown = FormMouseDown
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
OnPaint = FormPaint
OnResize = FormResize
Position = poDefaultPosOnly
LCLVersion = '1.6.0.4'
object Panel1: TPanel
Left = 0
Height = 51
Top = 544
Width = 647
Align = alBottom
ClientHeight = 51
ClientWidth = 647
Color = clForm
ParentColor = False
TabOrder = 0
object CheckBox_Closed: TCheckBox
Left = 400
Height = 19
Top = 24
Width = 56
Caption = 'Closed'
OnChange = CheckBox_Change
TabOrder = 0
end
object Radio_Inside: TRadioButton
Left = 88
Height = 19
Top = 4
Width = 51
Caption = 'Inside'
OnChange = Radio_Change
TabOrder = 1
end
object Radio_Crossing: TRadioButton
Left = 192
Height = 19
Top = 4
Width = 66
Caption = 'Crossing'
OnChange = Radio_Change
TabOrder = 2
end
object Radio_Outside: TRadioButton
Left = 192
Height = 19
Top = 24
Width = 61
Caption = 'Outside'
OnChange = Radio_Change
TabOrder = 3
end
object Radio_Rounded: TRadioButton
Left = 280
Height = 19
Top = 4
Width = 68
Caption = 'Rounded'
Checked = True
OnChange = Radio_Change
TabOrder = 4
TabStop = True
end
object Radio_VertexToSide: TRadioButton
Left = 280
Height = 19
Top = 24
Width = 91
Caption = 'Vertex to side'
OnChange = Radio_Change
TabOrder = 6
end
object Radio_Bezier2: TRadioButton
Left = 8
Height = 19
Top = 4
Width = 57
Caption = 'Bezier2'
OnChange = Radio_Change
TabOrder = 7
end
object Radio_Bezier3: TRadioButton
Left = 8
Height = 19
Top = 24
Width = 57
Caption = 'Bezier3'
OnChange = Radio_Change
TabOrder = 8
end
object CheckBox_CanJump: TCheckBox
Left = 400
Height = 19
Top = 4
Width = 72
Caption = 'Can jump'
Checked = True
State = cbChecked
TabOrder = 9
end
object Radio_EasyBezier: TRadioButton
Left = 88
Height = 19
Top = 24
Width = 77
Caption = 'Easy Bezier'
OnChange = Radio_Change
TabOrder = 5
end
end
object Timer1: TTimer
Interval = 40
OnTimer = Timer1Timer
Left = 97
Top = 184
end
end

View File

@@ -0,0 +1,305 @@
unit bspline_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
BGRABitmap, BGRABitmapTypes, LMessages, ExtCtrls, BGRAPath;
type
{ TForm1 }
TForm1 = class(TForm)
CheckBox_CanJump: TCheckBox;
CheckBox_Closed: TCheckBox;
Panel1: TPanel;
Radio_Bezier2: TRadioButton;
Radio_Bezier3: TRadioButton;
Radio_Crossing: TRadioButton;
Radio_Inside: TRadioButton;
Radio_Outside: TRadioButton;
Radio_Rounded: TRadioButton;
Radio_EasyBezier: TRadioButton;
Radio_VertexToSide: TRadioButton;
Timer1: TTimer;
procedure CheckBox_Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
procedure FormResize(Sender: TObject);
procedure Radio_Change(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure WMEraseBkgnd(var {%H-}Message: TLMEraseBkgnd); message LM_ERASEBKGND;
public
{ public declarations }
pts: array of TPointF;
MovingPointIndex: Integer;
MovingOrigin: TPointF;
PreviousSize: TPointF;
FPath: TBGRAPath;
FPathCursor: TBGRAPathCursor;
FPathThumbnail: TBGRAPath;
FPathSpeed: single;
FPathPos: single;
procedure PathChange;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses math;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
h: Integer;
begin
h := clientheight-Panel1.Height;
setlength(pts,7);
pts[1] := PointF(clientwidth/2,h/2);
pts[0] := pts[1] + pointF(0,75);
pts[2] := PointF(100,100);
pts[3] := pointF(clientwidth-100,100);
pts[4] := pointF(clientwidth-100,h-100);
pts[5] := pointF(100,h-100);
pts[6] := pointF(100,pts[0].y);
MovingPointIndex := -1;
FPathSpeed := 4;
FPathPos := 0;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(FPathCursor);
FreeAndNil(FPath);
end;
procedure TForm1.CheckBox_Change(Sender: TObject);
begin
PathChange;
end;
procedure TForm1.FormPaint(Sender: TObject);
var bmp: TBGRABitmap;
i: Integer;
style: TSplineStyle;
nbPoints: integer;
pt,tangent: TPointF;
closed: boolean;
thumbRect: TRect;
begin
PreviousSize := PointF(ClientWidth,clientheight);
bmp := TBGRABitmap.Create(clientwidth,panel1.top,BGRAWhite);
closed := CheckBox_Closed.Checked;
if Radio_Bezier2.Checked then
nbPoints := ((length(pts)-1+integer(closed)) div 2)*2+1-integer(closed)
else if Radio_Bezier3.Checked then
nbPoints := ((length(pts)-1+integer(closed)) div 3)*3+1-integer(closed)
else
nbPoints := length(pts);
if FPath = nil then
begin
FPath := TBGRAPath.Create;
if Radio_Bezier2.Checked then
begin
FPath.moveTo(pts[0]);
for i := 1 to (nbPoints-1+integer(closed)) div 2 do
FPath.quadraticCurveTo(pts[2*(i-1)+1],pts[(2*(i-1)+2) mod nbPoints]);
if closed then FPath.closePath;
end
else
if Radio_Bezier3.Checked then
begin
FPath.moveTo(pts[0]);
for i := 1 to (nbPoints-1+integer(closed)) div 3 do
FPath.bezierCurveTo(pts[3*(i-1)+1],pts[3*(i-1)+2],pts[(3*(i-1)+3) mod nbPoints]);
if closed then FPath.closePath;
end
else
begin
if Radio_Inside.Checked then style := ssInsideWithEnds else
if Radio_Crossing.Checked then style := ssCrossingWithEnds else
if Radio_Outside.checked then style := ssOutside else
if Radio_Rounded.Checked then style := ssRoundOutside else
if Radio_EasyBezier.Checked then style := ssEasyBezier else
style := ssVertexToSide;
if closed then
FPath.closedSpline(slice(pts,nbPoints), style)
else
FPath.openedSpline(slice(pts,nbPoints), style);
end;
end;
if Assigned(FPath) then
begin
FPath.fill(bmp, BGRA(250,250,230));
if closed then
bmp.DrawPolygonAntialias(slice(pts,nbPoints),BGRA(102,148,179),1)
else
bmp.DrawPolyLineAntialias(slice(pts,nbPoints),BGRA(102,148,179),1);
for i := 0 to nbPoints-1 do
bmp.FillEllipseAntialias(pts[i].x,pts[i].y,5,5,BGRA(102,148,179));
FPath.stroke(bmp, BGRABlack, 2);
if FPathCursor = nil then
begin
FPathCursor := FPath.CreateCursor;
FPathCursor.LoopPath:= true;
FPathCursor.Position := FPathPos*FPathCursor.PathLength;
end;
thumbRect := recT(bmp.Width-128,0,bmp.Width,128);
if FPathThumbnail = nil then
begin
FPathThumbnail := TBGRAPath.Create;
FPath.FitInto(FPathThumbnail, RectF(0,0,thumbRect.Right-thumbRect.Left-1,thumbRect.Bottom-thumbRect.Top-1));
end;
bmp.FillRect(thumbRect, BGRA(102,148,179,128), dmDrawWithTransparency);
FPathThumbnail.stroke(bmp, thumbRect.Left, thumbRect.Top, BGRABlack, 1);
with FPathCursor.Bounds do
bmp.RectangleAntialias(Left,Top,Right,Bottom,CSSFireBrick,1.5);
//bmp.TextOut(0,bmp.FontFullHeight, IntToStr(length(comp_pts))+' points', BGRABlack);
//bmp.DrawPolyLineAntialiasAutocycle(FPath.ToPoints(0.1),BGRABlack,1);
bmp.ArrowEndAsClassic;
pt := FPathCursor.CurrentCoordinate;
tangent := FPathCursor.CurrentTangent;
bmp.DrawLineAntialias(pt.x,pt.y,pt.x+tangent.x*40*Sign(FPathSpeed),pt.y+tangent.y*40*Sign(FPathSpeed),CSSFireBrick,3);
bmp.DrawLineAntialias(pt.x,pt.y,pt.x-tangent.y*40*Sign(FPathSpeed),pt.y+tangent.x*40*Sign(FPathSpeed),CSSFireBrick,3);
bmp.ArrowEndAsNone;
bmp.TextOut(0,0, 'Length: ' + IntToStr(round(FPathCursor.PathLength)), BGRABlack);
if FPathCursor.PathLength > 0 then
bmp.TextOut(0,bmp.FontFullHeight, IntToStr(round(FPathCursor.Position / FPathCursor.PathLength*100))+'%', BGRABlack);
end;
bmp.draw(Canvas,0,0);
bmp.Free;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var maxDist,dist: single;
mousePos,vect: TPointF;
i: Integer;
begin
if Button <> mbLeft then exit;
//select point to move
MovingPointIndex := -1;
maxDist := 10;
mousePos := PointF(X,Y);
MovingOrigin := mousePos;
for i := 0 to high(pts) do
begin
vect := pts[i] - mousePos;
dist := sqrt(vect*vect);
if dist < maxDist then
begin
maxDist := dist;
MovingPointIndex := i;
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mousePos: TPointF;
i: Integer;
begin
if ssLeft in Shift then
begin
mousePos := PointF(X,Y);
if MovingPointIndex <> -1 then
pts[MovingPointIndex].Offset(mousePos-MovingOrigin) else
begin
for i := 0 to high(pts) do
pts[i].Offset(mousePos-MovingOrigin);
end;
PathChange;
MovingOrigin := mousePos;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then MovingPointIndex := -1;
end;
procedure TForm1.FormResize(Sender: TObject);
var factor: TPointF;
i,ph: Integer;
begin
ph := Panel1.Height;
if (clientWidth > 0) and (clientheight-ph > 0) and
(previousSize.X > 0) and (previousSize.Y-ph > 0) then
begin
factor.X := clientWidth/PreviousSize.X;
factor.Y := (clientheight-ph)/(PreviousSize.Y-ph);
for i := 0 to high(pts) do
begin
pts[i].x *= factor.X;
pts[i].y *= factor.y;
end;
PreviousSize := PointF(ClientWidth,clientheight);
PathChange;
end;
end;
procedure TForm1.Radio_Change(Sender: TObject);
begin
PathChange;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Assigned(FPathCursor) then
begin
if FPathCursor.MoveForward(FPathSpeed, CheckBox_CanJump.Checked) <> FPathSpeed then
FPathSpeed:= -FPathSpeed;
if FPathCursor.PathLength > 0 then
FPathPos := FPathCursor.Position/FPathCursor.PathLength;
invalidate;
end;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.PathChange;
begin
FreeAndNil(FPathCursor);
FreeAndNil(FPathThumbnail);
FreeAndNil(FPath);
Invalidate;
end;
end.

View File

@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="etpackage"/>
</Item1>
<Item2>
<PackageName Value="bgrabitmappack"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="5">
<Unit0>
<Filename Value="distortions.lpr"/>
<IsPartOfProject Value="True"/>
<UsageCount Value="20"/>
</Unit0>
<Unit1>
<Filename Value="distortions_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="distortions_main"/>
<IsVisibleTab Value="True"/>
<TopLine Value="135"/>
<CursorPos X="43" Y="150"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\bgrabitmap\bgragradientscanner.pas"/>
<UnitName Value="BGRAGradientScanner"/>
<EditorIndex Value="2"/>
<CursorPos X="47" Y="10"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<UnitName Value="BGRABitmapTypes"/>
<EditorIndex Value="1"/>
<TopLine Value="427"/>
<CursorPos X="3" Y="484"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit3>
<Unit4>
<Filename Value="..\bgrabitmap\bgratransform.pas"/>
<UnitName Value="BGRATransform"/>
<EditorIndex Value="3"/>
<TopLine Value="40"/>
<CursorPos X="3" Y="25"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit4>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="distortions_main.pas"/>
<Caret Line="38" Column="7" TopLine="7"/>
</Position1>
<Position2>
<Filename Value="distortions_main.pas"/>
<Caret Line="41" Column="53" TopLine="11"/>
</Position2>
<Position3>
<Filename Value="distortions_main.pas"/>
<Caret Line="22" Column="24" TopLine="22"/>
</Position3>
<Position4>
<Filename Value="distortions_main.pas"/>
<Caret Line="42" Column="61" TopLine="22"/>
</Position4>
<Position5>
<Filename Value="distortions_main.pas"/>
<Caret Line="48" Column="63" TopLine="40"/>
</Position5>
<Position6>
<Filename Value="distortions_main.pas"/>
<Caret Line="25" Column="19"/>
</Position6>
<Position7>
<Filename Value="distortions_main.pas"/>
<Caret Line="12" Column="34"/>
</Position7>
<Position8>
<Filename Value="distortions_main.pas"/>
<Caret Line="17" Column="15"/>
</Position8>
<Position9>
<Filename Value="distortions_main.pas"/>
<Caret Line="18" Column="45" TopLine="4"/>
</Position9>
<Position10>
<Filename Value="distortions_main.pas"/>
<Caret Line="94" Column="62" TopLine="73"/>
</Position10>
<Position11>
<Filename Value="distortions_main.pas"/>
<Caret Line="39" Column="19" TopLine="17"/>
</Position11>
<Position12>
<Filename Value="distortions_main.pas"/>
<Caret Line="41" Column="19" TopLine="21"/>
</Position12>
<Position13>
<Filename Value="distortions_main.pas"/>
<Caret Line="96" Column="17" TopLine="78"/>
</Position13>
<Position14>
<Filename Value="distortions_main.pas"/>
<Caret Line="88" Column="7" TopLine="72"/>
</Position14>
<Position15>
<Filename Value="distortions_main.pas"/>
<Caret Line="89" Column="7" TopLine="73"/>
</Position15>
<Position16>
<Filename Value="distortions_main.pas"/>
<Caret Line="91" Column="7" TopLine="75"/>
</Position16>
<Position17>
<Filename Value="distortions_main.pas"/>
<Caret Line="93" Column="45" TopLine="74"/>
</Position17>
<Position18>
<Filename Value="distortions_main.pas"/>
<Caret Line="41" Column="29" TopLine="19"/>
</Position18>
<Position19>
<Filename Value="distortions_main.pas"/>
<Caret Line="42" Column="29" TopLine="22"/>
</Position19>
<Position20>
<Filename Value="distortions_main.pas"/>
<Caret Line="43" Column="29" TopLine="23"/>
</Position20>
<Position21>
<Filename Value="distortions_main.pas"/>
<Caret Line="42" Column="29" TopLine="23"/>
</Position21>
<Position22>
<Filename Value="distortions_main.pas"/>
<Caret Line="43" Column="29" TopLine="23"/>
</Position22>
<Position23>
<Filename Value="distortions_main.pas"/>
<Caret Line="42" Column="29" TopLine="23"/>
</Position23>
<Position24>
<Filename Value="distortions_main.pas"/>
<Caret Line="39" Column="79" TopLine="20"/>
</Position24>
<Position25>
<Filename Value="distortions_main.pas"/>
<Caret Line="16" Column="38" TopLine="13"/>
</Position25>
<Position26>
<Filename Value="..\bgrabitmap\bgragradientscanner.pas"/>
<Caret Line="10" Column="47"/>
</Position26>
<Position27>
<Filename Value="distortions_main.pas"/>
<Caret Line="96" Column="29" TopLine="85"/>
</Position27>
<Position28>
<Filename Value="distortions_main.pas"/>
<Caret Line="124" Column="5" TopLine="100"/>
</Position28>
<Position29>
<Filename Value="distortions_main.pas"/>
<Caret Line="152" Column="120" TopLine="126"/>
</Position29>
<Position30>
<Filename Value="distortions_main.pas"/>
<Caret Line="129" Column="39" TopLine="127"/>
</Position30>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="distortions"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program distortions;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, distortions_main, bgrabitmappack, etpackage
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,69 @@
object Form1: TForm1
Left = 307
Height = 387
Top = 220
Width = 622
Caption = 'BGRA Image and gradient distortions'
ClientHeight = 387
ClientWidth = 622
OnCreate = FormCreate
OnDestroy = FormDestroy
OnPaint = FormPaint
LCLVersion = '1.4.0.4'
object Panel1: TPanel
Left = 0
Height = 59
Top = 328
Width = 622
Align = alBottom
ClientHeight = 59
ClientWidth = 622
TabOrder = 0
object TrackBar_Angle: TTrackBar
Left = 0
Height = 25
Top = 24
Width = 320
Frequency = 30
Max = 360
Position = 20
Anchors = [akTop, akLeft, akRight]
TabOrder = 0
end
object Label1: TLabel
Left = 8
Height = 15
Top = 8
Width = 31
Caption = 'Angle'
ParentColor = False
end
object Label2: TLabel
Left = 337
Height = 15
Top = 8
Width = 27
Anchors = [akTop, akRight]
Caption = 'Scale'
ParentColor = False
end
object TrackBar_Scale: TTrackBar
Left = 328
Height = 25
Top = 24
Width = 288
Frequency = 10
Max = 50
Min = 1
Position = 10
Anchors = [akTop, akRight]
TabOrder = 1
end
end
object Timer1: TTimer
Interval = 16
OnTimer = Timer1Timer
left = 65
top = 139
end
end

View File

@@ -0,0 +1,162 @@
unit distortions_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
ComCtrls, StdCtrls, BGRABitmap, BGRABitmapTypes, BGRAGradientScanner,
LMessages, EpikTimer;
type
{ TWaveDistortion }
TWaveDistortion = class(TBGRACustomScanner)
private
FSource : IBGRAScanner;
FCenter : TPointF;
FRadius, FAmplitude: Single;
public
Delta: single;
constructor Create(source : IBGRAScanner; center : TPointF; radius, amplitude: single);
function ScanAt(X, Y: Single): TBGRAPixel; override;
end;
{ TForm1 }
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Panel1: TPanel;
Timer1: TTimer;
TrackBar_Angle: TTrackBar;
TrackBar_Scale: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
private
{ private declarations }
public
{ public declarations }
image: TBGRABitmap;
grad: TBGRAGradientScanner;
multigrad: TBGRAMultiGradient;
delta: single;
timer: TEpikTimer;
end;
var
Form1: TForm1;
implementation
uses BGRATransform;
{ TWaveDistortion }
constructor TWaveDistortion.Create(source: IBGRAScanner; center : TPointF; radius, amplitude: single);
begin
FSource := Source;
FCenter := center;
FRadius := radius;
FAmplitude := amplitude;
Delta := 0;
end;
function TWaveDistortion.ScanAt(X, Y: Single): TBGRAPixel;
var d: single;
p,v: TPointF;
begin
p := PointF(X,Y);
v := p-FCenter;
d := sqrt(v*v);
if d <> 0 then v.Scale(1/d);
p.Offset( v*(sin(d*2*Pi/FRadius+Delta)*FAmplitude) );
result := FSource.ScanAt(p.X,p.Y);
end;
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormPaint(Sender: TObject);
const ampl = 10;
var bmp: TBGRABitmap;
tx,ty: integer;
x,y,rx,ry,scale :single;
procedure DrawEllipse(source: IBGRAScanner);
var
disto: TWaveDistortion;
affine: TBGRAAffineScannerTransform;
begin
affine := TBGRAAffineScannerTransform.Create(source);
affine.RotateDeg(TrackBar_Angle.Position);
affine.Scale(scale,scale);
affine.Translate(x,y);
disto := TWaveDistortion.Create(affine,PointF(x,y),(rx+ry)/2*0.6,ampl);
disto.Delta := Delta;
bmp.FillEllipseAntialias(x,y,rx,ry,disto);
disto.Free;
affine.free;
end;
begin
timer.Clear;
timer.start;
tx := ClientWidth;
ty := Panel1.Top;
scale := TrackBar_Scale.Position/10;
bmp := TBGRABitmap.Create(tx,ty, BGRAWhite);
x := tx/4;
y := ty/2;
rx := tx/4*0.8;
ry := ty/2*0.8;
image.ScanOffset := Point(round(image.width/2),round(image.Height/2));
DrawEllipse(image);
x := 3*tx/4;
y := ty/2;
bmp.FillEllipseAntialias(x,y,rx,ry,BGRABlack);
grad := TBGRAGradientScanner.Create(multigrad,gtRadial,PointF(0.4*rx/scale,-0.4*ry/scale),PointF(0.4*rx/scale+rx,-0.4*ry/scale),False);
DrawEllipse(grad);
grad.free;
timer.Stop;
bmp.TextOut(0,0,inttostr(round(timer.Elapsed*1000))+ ' ms',BGRABlack);
bmp.Draw(Canvas,0,0);
bmp.Free;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := false;
Delta -= 10*Pi/180;
Repaint;
Timer1.Enabled := true;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
image := TBGRABitmap.Create('spheres.png');
timer := TEpikTimer.Create(self);
multigrad := TBGRAMultiGradient.Create([BGRAWhite,BGRA(255,235,96),BGRA(255,160,0),BGRA(140,0,0),BGRA(64,0,0),BGRA(160,64,0)],[0,0.2,0.4,0.8,0.9,1],True);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
image.free;
multigrad.Free;
end;
end.

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="2">
<Item1>
<PackageName Value="bgrabitmappack"/>
</Item1>
<Item2>
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="3">
<Unit0>
<Filename Value="gouraud.lpr"/>
<IsPartOfProject Value="True"/>
<UsageCount Value="20"/>
</Unit0>
<Unit1>
<Filename Value="gouraud_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="gouraud_main"/>
<IsVisibleTab Value="True"/>
<CursorPos X="55" Y="9"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\bgrabitmap\bgrapolygon.pas"/>
<UnitName Value="BGRAPolygon"/>
<EditorIndex Value="1"/>
<TopLine Value="19"/>
<CursorPos X="30" Y="250"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit2>
</Units>
<JumpHistory Count="6" HistoryIndex="5">
<Position1>
<Filename Value="gouraud_main.pas"/>
<Caret Line="65" Column="50" TopLine="45"/>
</Position1>
<Position2>
<Filename Value="gouraud_main.pas"/>
<Caret Line="8" Column="78"/>
</Position2>
<Position3>
<Filename Value="gouraud_main.pas"/>
<Caret Line="24" Column="15" TopLine="6"/>
</Position3>
<Position4>
<Filename Value="gouraud_main.pas"/>
<Caret Line="126" TopLine="91"/>
</Position4>
<Position5>
<Filename Value="gouraud_main.pas"/>
<Caret Line="42" Column="12" TopLine="39"/>
</Position5>
<Position6>
<Filename Value="gouraud_main.pas"/>
<Caret Line="28" Column="79" TopLine="19"/>
</Position6>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="gouraud"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program gouraud;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, gouraud_main, bgrabitmappack
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,45 @@
object Form1: TForm1
Left = 298
Height = 319
Top = 215
Width = 404
Caption = 'Gouraud shading'
ClientHeight = 319
ClientWidth = 404
OnCreate = FormCreate
OnMouseDown = FormMouseDown
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
OnPaint = FormPaint
LCLVersion = '0.9.30'
object Panel1: TPanel
Left = 0
Height = 42
Top = 277
Width = 404
Align = alBottom
ClientHeight = 42
ClientWidth = 404
TabOrder = 0
object Label1: TLabel
Left = 8
Height = 16
Top = 11
Width = 42
Caption = 'Opacity'
ParentColor = False
end
object TrackBar1: TTrackBar
Left = 64
Height = 25
Top = 11
Width = 328
Frequency = 16
Max = 255
OnChange = TrackBar1Change
Position = 255
Anchors = [akTop, akLeft, akRight]
TabOrder = 0
end
end
end

View File

@@ -0,0 +1,156 @@
unit gouraud_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, ComCtrls, BGRABitmap, BGRABitmapTypes, LMessages;
type
{ TForm1 }
TForm1 = class(TForm)
Label1: TLabel;
Panel1: TPanel;
TrackBar1: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
{ private declarations }
procedure FormPaint(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure WMEraseBkgnd(var Message: TLMEraseBkgnd); message LM_ERASEBKGND;
public
{ public declarations }
MovingPointIndex: Integer;
MovingOrigin: TPointF;
pts: array[0..2] of TPointF;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses BGRAPolygon;
procedure NicePoint(bmp: TBGRABitmap; x, y: single);
begin
bmp.EllipseAntialias(x,y,4,4,BGRA(0,0,0,192),1);
bmp.EllipseAntialias(x,y,3,3,BGRA(255,255,255,192),1);
bmp.EllipseAntialias(x,y,2,2,BGRA(0,0,0,192),1);
end;
{ TForm1 }
procedure TForm1.FormPaint(Sender: TObject);
var bmp: TBGRABitmap;
tx,ty,i: Integer;
c: TPointF;
multi: TBGRAMultishapeFiller;
opacity: byte;
begin
tx := ClientWidth;
ty := Panel1.Top;
bmp := TBGRABitmap.Create(tx,ty,BGRAWhite);
opacity := TrackBar1.Position;
c := (pts[0]+pts[1]+pts[2])*(1/3);
multi := TBGRAMultishapeFiller.Create;
multi.AddQuadLinearColor(pts[0],c,pts[2],pts[2]+(pts[0]-c),
BGRA(0,0,255,opacity),BGRA(255,255,255,opacity),BGRA(255,0,0,opacity),BGRA(0,0,0,opacity));
multi.AddQuadLinearColor(pts[0],c,pts[1],pts[1]+(pts[0]-c),
BGRA(0,0,255,opacity),BGRA(255,255,255,opacity),BGRA(0,255,0,opacity),BGRA(0,0,0,opacity));
multi.AddQuadLinearColor(pts[2],c,pts[1],pts[1]+(pts[2]-c),
BGRA(255,0,0,opacity),BGRA(255,255,255,opacity),BGRA(0,255,0,opacity),BGRA(0,0,0,opacity));
multi.Draw(bmp);
multi.free;
for i := 0 to 2 do
NicePoint(bmp,pts[i].x,pts[i].y);
bmp.Draw(Canvas,0,0);
bmp.free;
end;
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
Invalidate;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
pts[0] := PointF(150,10);
pts[1] := PointF(370,140);
pts[2] := PointF(50,260);
MovingPointIndex := -1;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var maxDist,dist: single;
mousePos,vect: TPointF;
i: Integer;
begin
if Button <> mbLeft then exit;
//select point to move
MovingPointIndex := -1;
maxDist := 10;
mousePos := PointF(X,Y);
MovingOrigin := mousePos;
for i := 0 to high(pts) do
begin
vect := pts[i] - mousePos;
dist := sqrt(vect*vect);
if dist < maxDist then
begin
maxDist := dist;
MovingPointIndex := i;
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mousePos: TPointF;
i: Integer;
begin
if ssLeft in Shift then
begin
mousePos := PointF(X,Y);
if MovingPointIndex <> -1 then
pts[MovingPointIndex].Offset(mousePos-MovingOrigin) else
begin
for i := 0 to high(pts) do
pts[i].Offset(mousePos-MovingOrigin);
end;
Invalidate;
MovingOrigin := mousePos;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then MovingPointIndex := -1;
end;
end.

View File

@@ -0,0 +1,268 @@
<?xml version="1.0"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
<ActiveWindowIndexAtStart Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="etpackage"/>
</Item1>
<Item2>
<PackageName Value="bgrabitmappack"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="6">
<Unit0>
<Filename Value="image_filters2.lpr"/>
<IsPartOfProject Value="True"/>
<UnitName Value="image_filters2"/>
<EditorIndex Value="1"/>
<WindowIndex Value="0"/>
<TopLine Value="1"/>
<CursorPos X="30" Y="10"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="image_filters2_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="image_filters2_main"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="0"/>
<WindowIndex Value="0"/>
<TopLine Value="148"/>
<CursorPos X="76" Y="171"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="D:\lazarus\lcl\graphics.pp"/>
<UnitName Value="Graphics"/>
<EditorIndex Value="5"/>
<WindowIndex Value="0"/>
<TopLine Value="242"/>
<CursorPos X="3" Y="252"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<UnitName Value="BGRABitmapTypes"/>
<EditorIndex Value="4"/>
<WindowIndex Value="0"/>
<TopLine Value="62"/>
<CursorPos X="59" Y="86"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit3>
<Unit4>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<UnitName Value="BGRADefaultBitmap"/>
<EditorIndex Value="2"/>
<WindowIndex Value="0"/>
<TopLine Value="3330"/>
<CursorPos X="33" Y="3333"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\bgrabitmap\bgraresample.pas"/>
<UnitName Value="BGRAResample"/>
<EditorIndex Value="3"/>
<WindowIndex Value="0"/>
<TopLine Value="825"/>
<CursorPos X="1" Y="834"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit5>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="75" Column="1" TopLine="55"/>
</Position1>
<Position2>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="74" Column="18" TopLine="56"/>
</Position2>
<Position3>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="68" Column="42" TopLine="57"/>
</Position3>
<Position4>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="69" Column="42" TopLine="58"/>
</Position4>
<Position5>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="70" Column="42" TopLine="59"/>
</Position5>
<Position6>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="71" Column="42" TopLine="60"/>
</Position6>
<Position7>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="72" Column="42" TopLine="61"/>
</Position7>
<Position8>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="70" Column="15" TopLine="62"/>
</Position8>
<Position9>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="71" Column="15" TopLine="63"/>
</Position9>
<Position10>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="72" Column="15" TopLine="64"/>
</Position10>
<Position11>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="73" Column="17" TopLine="49"/>
</Position11>
<Position12>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="78" Column="30" TopLine="65"/>
</Position12>
<Position13>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="3346" Column="38" TopLine="3342"/>
</Position13>
<Position14>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="3333" Column="33" TopLine="3330"/>
</Position14>
<Position15>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="79" Column="1" TopLine="65"/>
</Position15>
<Position16>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="92" Column="14" TopLine="76"/>
</Position16>
<Position17>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="91" Column="14" TopLine="75"/>
</Position17>
<Position18>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="90" Column="14" TopLine="74"/>
</Position18>
<Position19>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="91" Column="14" TopLine="75"/>
</Position19>
<Position20>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="73" Column="51" TopLine="73"/>
</Position20>
<Position21>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="52" Column="28" TopLine="45"/>
</Position21>
<Position22>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="86" Column="9" TopLine="65"/>
</Position22>
<Position23>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="95" Column="68" TopLine="67"/>
</Position23>
<Position24>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="33" Column="76" TopLine="11"/>
</Position24>
<Position25>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="100" Column="10" TopLine="70"/>
</Position25>
<Position26>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="33" Column="59" TopLine="15"/>
</Position26>
<Position27>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="115" Column="1" TopLine="95"/>
</Position27>
<Position28>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="149" Column="50" TopLine="107"/>
</Position28>
<Position29>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="160" Column="64" TopLine="137"/>
</Position29>
<Position30>
<Filename Value="image_filters2_main.pas"/>
<Caret Line="166" Column="83" TopLine="144"/>
</Position30>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="image_filters2"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,20 @@
program image_filters2;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, image_filters2_main, bgrabitmappack, etpackage
{ you can add units after this };
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,122 @@
object Form1: TForm1
Left = 213
Height = 301
Top = 213
Width = 583
Caption = 'BGRA Image resample filters'
ClientHeight = 301
ClientWidth = 583
OnCreate = FormCreate
OnDestroy = FormDestroy
OnPaint = FormPaint
LCLVersion = '1.0.10.0'
object Panel1: TPanel
Left = 0
Height = 301
Top = 0
Width = 194
Align = alLeft
ClientHeight = 301
ClientWidth = 194
TabOrder = 0
object Radio_Linear: TRadioButton
Left = 11
Height = 19
Top = 64
Width = 52
Caption = 'Linear'
OnChange = Radio_Change
TabOrder = 1
end
object Label1: TLabel
Left = 5
Height = 16
Top = 8
Width = 27
Caption = 'Filter'
ParentColor = False
end
object Radio_None: TRadioButton
Left = 11
Height = 19
Top = 32
Width = 96
Caption = 'None (stretch)'
OnChange = Radio_Change
TabOrder = 0
end
object Radio_HalfCosine: TRadioButton
Left = 11
Height = 19
Top = 80
Width = 81
Caption = 'Half-cosine'
OnChange = Radio_Change
TabOrder = 2
end
object Radio_Cosine: TRadioButton
Left = 11
Height = 19
Top = 96
Width = 56
Caption = 'Cosine'
OnChange = Radio_Change
TabOrder = 3
end
object Radio_Bicubic: TRadioButton
Left = 11
Height = 19
Top = 112
Width = 91
Caption = 'Bicubic (blur)'
OnChange = Radio_Change
TabOrder = 4
end
object Radio_Mitchell: TRadioButton
Left = 11
Height = 19
Top = 128
Width = 63
Caption = 'Mitchell'
OnChange = Radio_Change
TabOrder = 5
end
object Radio_Spline: TRadioButton
Left = 11
Height = 19
Top = 144
Width = 75
Caption = 'Spline (16)'
OnChange = Radio_Change
TabOrder = 6
end
object Label_Ms: TLabel
Left = 88
Height = 16
Top = 8
Width = 97
Alignment = taRightJustify
AutoSize = False
Caption = 'ms'
ParentColor = False
end
object PaintBox1: TPaintBox
Left = 21
Height = 112
Top = 168
Width = 151
OnPaint = PaintBox1Paint
end
object Radio_BoxFilter: TRadioButton
Left = 11
Height = 19
Top = 48
Width = 66
Caption = 'Box filter'
Checked = True
OnChange = Radio_Change
TabOrder = 7
TabStop = True
end
end
end

View File

@@ -0,0 +1,194 @@
unit image_filters2_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, BGRABitmap, BGRABitmapTypes, EpikTimer;
type
{ TForm1 }
TForm1 = class(TForm)
Label1: TLabel;
Label_Ms: TLabel;
PaintBox1: TPaintBox;
Panel1: TPanel;
Radio_Linear: TRadioButton;
Radio_Mitchell: TRadioButton;
Radio_None: TRadioButton;
Radio_HalfCosine: TRadioButton;
Radio_Cosine: TRadioButton;
Radio_Bicubic: TRadioButton;
Radio_BoxFilter: TRadioButton;
Radio_Spline: TRadioButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
procedure Radio_Change(Sender: TObject);
private
{ private declarations }
procedure GetFilter(out filter : TResampleFilter; out noFilter: boolean);
public
{ public declarations }
image: TBGRABitmap;
stopwatch : TEpikTimer;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
uses BGRAResample;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
image := TBGRABitmap.Create(4,4,BGRAWhite);
image.SetPixel(0,0,clRed);
image.SetPixel(2,0,clBlack);
image.SetPixel(3,0,clLime);
image.SetPixel(2,1,clRed);
image.SetPixel(3,1,clBlue);
image.SetPixel(0,2,clBlue);
image.SetPixel(1,2,clBlack);
image.SetPixel(0,3,clLime);
image.SetPixel(1,3,clRed);
image.SetPixel(3,3,clBlue);
stopwatch := TEpikTimer.Create(self);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
image.Free;
end;
procedure TForm1.FormPaint(Sender: TObject);
var resampled: TBGRABitmap;
tx,ty: integer;
filter : TResampleFilter;
noFilter: boolean;
begin
tx := ClientWidth-Panel1.Width;
ty := ClientHeight;
if tx > ty then tx := ty else ty := tx;
GetFilter(filter, noFilter);
stopwatch.Clear;
stopwatch.Start;
if noFilter then
resampled := image.Resample(tx,ty,rmSimpleStretch) else
begin
image.ResampleFilter := filter;
resampled := image.Resample(tx,ty);
end;
stopwatch.stop;
Label_Ms.Caption := IntToStr(round(stopwatch.Elapsed*1000))+' ms';
resampled.Draw(Canvas,Panel1.width,0);
resampled.Free;
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
const
minx = -3;
maxx = 3;
miny = -1;
maxy = 2;
var
graph: TBGRABitmap;
curve: array of TPointF;
tx,ty,precision: integer;
filter : TResampleFilter;
noFilter: boolean;
i,numPt: integer;
filterPos,filterValue: single;
kernel: TWideKernelFilter;
function XToGraph(value: single): single;
begin
result := (value-minx)/(maxx-minx)*(tx-1);
end;
function YToGraph(value: single): single;
begin
result := ty-1-(value-miny)/(maxy-miny)*(ty-1);
end;
begin
tx := paintbox1.width;
ty := paintbox1.height;
if (tx=0) or (ty=0) then exit;
graph := TBGRABitmap.Create(tx,ty,BGRAWhite);
precision := tx div (maxx-minx)+1;
setlength(curve,precision*(maxx-minx)+1);
GetFilter(filter, noFilter);
numPt := 0;
case filter of
rfBicubic: kernel := TCubicKernel.Create;
rfSpline: kernel := TSplineKernel.Create;
rfMitchell: kernel := TMitchellKernel.Create;
else
kernel := nil;
end;
for i := minx*precision to maxx*precision do
begin
filterPos := i/precision;
if noFilter then
begin
if (filterPos >= 0) and (filterPos < 1) then
filterValue := 1
else
filterValue := 0;
end else
begin
if kernel = nil then
begin
if abs(filterPos) > 1 then
filterValue := 0
else
filterValue := 1-FineInterpolation(abs(filterPos),filter);
end
else
filterValue := kernel.Interpolation(filterPos);
end;
curve[numPt] := PointF(XToGraph(filterPos),YToGraph(filterValue));
inc(numPt);
end;
kernel.Free;
graph.DrawHorizLine(0,round(YToGraph(0)),tx-1,BGRA(0,0,0,96));
graph.DrawVertLine(round(XToGraph(0)),0,ty-1,BGRA(0,0,0,96));
graph.DrawLineAntialias(XToGraph(0)-8,YToGraph(1),XToGraph(0)+8,YToGraph(1),BGRA(0,0,0,96),1);
graph.DrawLineAntialias(XToGraph(-1),YToGraph(0)-8,XToGraph(-1),YToGraph(0)+8,BGRA(0,0,0,96),1);
graph.DrawLineAntialias(XToGraph(1),YToGraph(0)-8,XToGraph(1),YToGraph(0)+8,BGRA(0,0,0,96),1);
graph.DrawPolyLineAntialias(curve,BGRA(192,0,0),1);
graph.Draw(paintbox1.Canvas,0,0);
graph.free;
end;
procedure TForm1.Radio_Change(Sender: TObject);
begin
Invalidate;
PaintBox1.Invalidate;
end;
procedure TForm1.GetFilter(out filter: TResampleFilter; out noFilter: boolean);
begin
noFilter := Radio_None.Checked;
if Radio_BoxFilter.Checked then filter := rfBox else
if Radio_Bicubic.Checked then filter := rfBicubic else
if Radio_Cosine.Checked then filter := rfCosine else
if Radio_HalfCosine.Checked then filter := rfHalfCosine else
if Radio_Mitchell.Checked then filter := rfMitchell else
if Radio_Spline.Checked then filter := rfSpline else
filter := rfLinear;
end;
end.

View File

@@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
<PathDelim Value="\"/>
<General>
<MainUnit Value="0"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
</General>
<i18n>
<EnableI18N LFM="False"/>
</i18n>
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1" Active="Default">
<Item1 Name="Default" Default="True"/>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
<ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
</PublishOptions>
<RunParams>
<local>
<FormatVersion Value="1"/>
</local>
</RunParams>
<RequiredPackages Count="3">
<Item1>
<PackageName Value="etpackage"/>
</Item1>
<Item2>
<PackageName Value="bgrabitmappack"/>
</Item2>
<Item3>
<PackageName Value="LCL"/>
</Item3>
</RequiredPackages>
<Units Count="7">
<Unit0>
<Filename Value="image_perspective.lpr"/>
<IsPartOfProject Value="True"/>
<EditorIndex Value="4"/>
<CursorPos Y="14"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
<Filename Value="image_perspective_main.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Form1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="image_perspective_main"/>
<IsVisibleTab Value="True"/>
<TopLine Value="113"/>
<CursorPos X="43" Y="135"/>
<UsageCount Value="20"/>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="gouraud_main.pas"/>
<UnitName Value="gouraud_main"/>
<EditorIndex Value="5"/>
<TopLine Value="120"/>
<CursorPos Y="156"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="uperspective.pas"/>
<TopLine Value="363"/>
<CursorPos X="18" Y="368"/>
<UsageCount Value="20"/>
</Unit3>
<Unit4>
<Filename Value="..\bgrabitmap\bgratransform.pas"/>
<UnitName Value="BGRATransform"/>
<EditorIndex Value="2"/>
<TopLine Value="433"/>
<CursorPos X="56" Y="471"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit4>
<Unit5>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<UnitName Value="BGRABitmapTypes"/>
<EditorIndex Value="3"/>
<TopLine Value="992"/>
<CursorPos X="7" Y="991"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit5>
<Unit6>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<UnitName Value="BGRADefaultBitmap"/>
<EditorIndex Value="1"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit6>
</Units>
<JumpHistory Count="17" HistoryIndex="16">
<Position1>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<Caret Line="557" Column="27" TopLine="539"/>
</Position1>
<Position2>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<Caret Line="556" Column="48" TopLine="538"/>
</Position2>
<Position3>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<Caret Line="1664" Column="30" TopLine="1636"/>
</Position3>
<Position4>
<Filename Value="image_perspective_main.pas"/>
<Caret Line="84" Column="16" TopLine="71"/>
</Position4>
<Position5>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="243" Column="27" TopLine="225"/>
</Position5>
<Position6>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="246" Column="28" TopLine="225"/>
</Position6>
<Position7>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1798" Column="29" TopLine="1780"/>
</Position7>
<Position8>
<Filename Value="..\bgrabitmap\bgratransform.pas"/>
<Caret Line="134" Column="66" TopLine="115"/>
</Position8>
<Position9>
<Filename Value="image_perspective_main.pas"/>
<Caret Line="80" Column="22" TopLine="71"/>
</Position9>
<Position10>
<Filename Value="..\bgrabitmap\bgrabitmaptypes.pas"/>
<Caret Line="541" Column="63" TopLine="522"/>
</Position10>
<Position11>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1801" TopLine="1780"/>
</Position11>
<Position12>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1792" Column="6" TopLine="1774"/>
</Position12>
<Position13>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1798" Column="83" TopLine="1774"/>
</Position13>
<Position14>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1792" Column="7" TopLine="1774"/>
</Position14>
<Position15>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1804" Column="5" TopLine="1774"/>
</Position15>
<Position16>
<Filename Value="..\bgrabitmap\bgradefaultbitmap.pas"/>
<Caret Line="1780" Column="38" TopLine="1778"/>
</Position16>
<Position17>
<Filename Value="image_perspective_main.pas"/>
<Caret Line="50" Column="19" TopLine="32"/>
</Position17>
</JumpHistory>
</ProjectOptions>
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="image_perspective"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
<Debugging>
<Exceptions Count="3">
<Item1>
<Name Value="EAbort"/>
</Item1>
<Item2>
<Name Value="ECodetoolError"/>
</Item2>
<Item3>
<Name Value="EFOpenError"/>
</Item3>
</Exceptions>
</Debugging>
</CONFIG>

View File

@@ -0,0 +1,19 @@
program image_perspective;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
Interfaces, // this includes the LCL widgetset
Forms, image_perspective_main, bgrabitmappack, etpackage;
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

View File

@@ -0,0 +1,146 @@
object Form1: TForm1
Left = 627
Height = 490
Top = 220
Width = 514
Caption = 'Texture mapping'
ClientHeight = 490
ClientWidth = 514
OnCreate = FormCreate
OnDestroy = FormDestroy
OnMouseDown = FormMouseDown
OnMouseMove = FormMouseMove
OnMouseUp = FormMouseUp
OnPaint = FormPaint
Position = poDefaultPosOnly
LCLVersion = '1.4.0.4'
object Panel1: TPanel
Left = 376
Height = 130
Top = 360
Width = 138
Anchors = [akRight, akBottom]
ClientHeight = 130
ClientWidth = 138
TabOrder = 0
object Radio_Perspective: TRadioButton
Left = 8
Height = 19
Top = 40
Width = 80
Caption = 'Perspective'
OnChange = RadioButtonChange
TabOrder = 4
end
object Label1: TLabel
Left = 8
Height = 15
Top = 7
Width = 48
Caption = 'Mapping'
ParentColor = False
end
object Radio_LinearAntialias: TRadioButton
Left = 8
Height = 19
Top = 56
Width = 98
Caption = 'Linear antialias'
OnChange = RadioButtonChange
TabOrder = 0
end
object Radio_Linear: TRadioButton
Left = 8
Height = 19
Top = 72
Width = 52
Caption = 'Linear'
OnChange = RadioButtonChange
TabOrder = 1
end
object Radio_AffineAntialias: TRadioButton
Left = 8
Height = 19
Top = 88
Width = 98
Caption = 'Affine antialias'
OnChange = RadioButtonChange
TabOrder = 2
end
object Radio_Affine: TRadioButton
Left = 8
Height = 19
Top = 104
Width = 52
Caption = 'Affine'
OnChange = RadioButtonChange
TabOrder = 3
end
object Radio_PerspectiveAntialias: TRadioButton
Left = 8
Height = 19
Top = 24
Width = 126
Caption = 'Perspective antialias'
Checked = True
OnChange = RadioButtonChange
TabOrder = 5
TabStop = True
end
end
object Panel2: TPanel
Left = 240
Height = 130
Top = 360
Width = 136
Anchors = [akRight, akBottom]
ClientHeight = 130
ClientWidth = 136
TabOrder = 1
object Label2: TLabel
Left = 8
Height = 15
Top = 7
Width = 68
Caption = 'Interpolation'
ParentColor = False
end
object Radio_InterpBox: TRadioButton
Left = 15
Height = 19
Top = 32
Width = 39
Caption = 'Box'
Checked = True
OnChange = RadioButtonChange
TabOrder = 3
TabStop = True
end
object Radio_InterpLinear: TRadioButton
Left = 15
Height = 19
Top = 48
Width = 52
Caption = 'Linear'
OnChange = RadioButtonChange
TabOrder = 0
end
object Radio_InterpHalfCosine: TRadioButton
Left = 15
Height = 19
Top = 64
Width = 81
Caption = 'Half-cosine'
OnChange = RadioButtonChange
TabOrder = 1
end
object Radio_InterpCosine: TRadioButton
Left = 15
Height = 19
Top = 80
Width = 56
Caption = 'Cosine'
TabOrder = 2
end
end
end

View File

@@ -0,0 +1,220 @@
unit image_perspective_main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
StdCtrls, ComCtrls, BGRABitmap, BGRABitmapTypes, LMessages, EpikTimer;
type
{ TForm1 }
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Panel1: TPanel;
Panel2: TPanel;
Radio_InterpBox: TRadioButton;
Radio_InterpLinear: TRadioButton;
Radio_InterpHalfCosine: TRadioButton;
Radio_InterpCosine: TRadioButton;
Radio_Perspective: TRadioButton;
Radio_LinearAntialias: TRadioButton;
Radio_Linear: TRadioButton;
Radio_AffineAntialias: TRadioButton;
Radio_Affine: TRadioButton;
Radio_PerspectiveAntialias: TRadioButton;
TrackBar1: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
{%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
{ private declarations }
procedure FormPaint(Sender: TObject);
procedure RadioButtonChange(Sender: TObject);
procedure WMEraseBkgnd(var {%H-}Message: TLMEraseBkgnd); message LM_ERASEBKGND;
public
{ public declarations }
MovingPointIndex: Integer;
MovingOrigin: TPointF;
pts: array[0..3] of TPointF;
image: TBGRABitmap;
stopwatch: TEpikTimer;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure NicePoint(bmp: TBGRABitmap; x, y: single; scale: single = 1);
begin
bmp.EllipseAntialias(x,y,4*scale,4*scale,BGRA(0,0,0,192),scale);
bmp.EllipseAntialias(x,y,3*scale,3*scale,BGRA(255,255,255,192),scale);
bmp.EllipseAntialias(x,y,2*scale,2*scale,BGRA(0,0,0,192),scale);
end;
{ TForm1 }
procedure TForm1.FormPaint(Sender: TObject);
var bmp: TBGRABitmap;
tx,ty,i: Integer;
texPos, scaledPts: array of TPointF;
scale: double;
begin
tx := ClientWidth;
ty := clientHeight;
if Radio_InterpBox.Checked then
image.ScanInterpolationFilter := rfBox else
if Radio_InterpLinear.Checked then
image.ScanInterpolationFilter := rfLinear else
if Radio_InterpHalfCosine.Checked then
image.ScanInterpolationFilter := rfHalfCosine else
if Radio_InterpCosine.Checked then
image.ScanInterpolationFilter := rfCosine;
If Radio_Affine.Checked or Radio_AffineAntialias.Checked then
pts[2] := pts[1]+(pts[3]-pts[0]);
scale := GetCanvasScaleFactor;
bmp := TBGRABitmap.Create(round(tx*scale),round(ty*scale),BGRAWhite);
setLength({%H-}scaledPts, length(pts));
for i := 0 to high(pts) do scaledPts[i] := scale*pts[i];
stopwatch.clear;
stopwatch.start;
texPos := PointsF([PointF(0,0),PointF(image.width-1,0),
PointF(image.width-1,image.Height-1),PointF(0,image.Height-1)]);
if Radio_Perspective.Checked or Radio_PerspectiveAntialias.Checked then
begin
if Radio_PerspectiveAntialias.Checked then
bmp.FillQuadPerspectiveMappingAntialias(scaledPts[0],scaledPts[1],scaledPts[2],scaledPts[3], image,
texPos[0],texPos[1],texPos[2],texPos[3])
else
bmp.FillQuadPerspectiveMapping(scaledPts[0],scaledPts[1],scaledPts[2],scaledPts[3], image,
texPos[0],texPos[1],texPos[2],texPos[3]);
end else
if Radio_LinearAntialias.Checked then
begin
bmp.FillQuadLinearMappingAntialias(scaledPts[0],scaledPts[1],scaledPts[2],scaledPts[3], image,
texPos[0],texPos[1],texPos[2],texPos[3]);
end
else if Radio_Linear.Checked then
begin
bmp.FillQuadLinearMapping(scaledPts[0],scaledPts[1],scaledPts[2],scaledPts[3], image,
texPos[0],texPos[1],texPos[2],texPos[3], true, fcNone, false);
end
else if Radio_Affine.Checked then
begin
bmp.FillQuadAffineMapping(scaledPts[0],scaledPts[1],scaledPts[3],image);
end
else if Radio_AffineAntialias.checked then
begin
bmp.FillQuadAffineMappingAntialias(scaledPts[0],scaledPts[1],scaledPts[3],image);
end;
stopwatch.stop;
//bmp.DrawPolygonAntialias(scaledPts,BGRA(0,0,0,64),scale);
bmp.FontHeight:= round(bmp.FontHeight*scale);
bmp.textOut(0,0,inttostr(round(stopwatch.Elapsed*1000))+' ms',BGRABlack);
for i := 0 to 3 do
NicePoint(bmp,scaledPts[i].x,scaledPts[i].y, scale);
bmp.Draw(Canvas,rect(0,0,tx,ty));
bmp.free;
end;
procedure TForm1.RadioButtonChange(Sender: TObject);
begin
invalidate;
end;
procedure TForm1.WMEraseBkgnd(var Message: TLMEraseBkgnd);
begin
//
end;
procedure TForm1.FormCreate(Sender: TObject);
var
appPath: String;
begin
pts[0] := PointF(50,50);
pts[1] := PointF(clientwidth-150,50);
pts[2] := PointF(clientwidth-150,clientheight-150);
pts[3] := PointF(120,clientheight-200);
MovingPointIndex := -1;
appPath := ExtractFilePath(ParamStr(0));
image := TBGRABitmap.Create(appPath+'spheres.png');
stopwatch := TEpikTimer.Create(Self);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
image.free;
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var maxDist,dist: single;
mousePos,vect: TPointF;
i: Integer;
begin
if Button <> mbLeft then exit;
//select point to move
MovingPointIndex := -1;
maxDist := 10;
mousePos := PointF(X,Y);
MovingOrigin := mousePos;
for i := 0 to high(pts) do
begin
vect := pts[i] - mousePos;
dist := sqrt(vect*vect);
if dist < maxDist then
begin
maxDist := dist;
MovingPointIndex := i;
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var
mousePos: TPointF;
i: Integer;
begin
if ssLeft in Shift then
begin
mousePos := PointF(X,Y);
if MovingPointIndex <> -1 then
pts[MovingPointIndex].Offset(mousePos-MovingOrigin) else
begin
for i := 0 to high(pts) do
pts[i].Offset(mousePos-MovingOrigin);
end;
Invalidate;
MovingOrigin := mousePos;
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then MovingPointIndex := -1;
end;
end.

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB