Difference between revisions of "BGRABitmap tutorial 11"
Jwdietrich (talk | contribs) |
m (Fixed syntax highlighting) |
||
Line 11: | Line 11: | ||
=== Affine transformation of a radial gradient === | === Affine transformation of a radial gradient === | ||
− | Here is an affine transformation applied on a gradient like we did with textures : | + | Here is an affine transformation applied on a gradient like we did with textures: |
− | <syntaxhighlight>uses BGRAGradientScanner, BGRATransform; | + | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | uses BGRAGradientScanner, BGRATransform; | ||
procedure TForm1.FormPaint(Sender: TObject); | procedure TForm1.FormPaint(Sender: TObject); | ||
Line 35: | Line 37: | ||
image.Draw(Canvas,0,0,True); | image.Draw(Canvas,0,0,True); | ||
image.free; | image.free; | ||
− | end; </syntaxhighlight> | + | end; |
+ | </syntaxhighlight> | ||
The base gradient is radial, centered at origin (0,0), of radius 1. | The base gradient is radial, centered at origin (0,0), of radius 1. | ||
− | The affine transformation does the following : | + | The affine transformation does the following: |
+ | |||
* stretch the gradient to a size of 150x80 | * stretch the gradient to a size of 150x80 | ||
* rotate 30 degrees in counterclockwise direction | * rotate 30 degrees in counterclockwise direction | ||
Line 54: | Line 58: | ||
=== Combine with a twirl === | === Combine with a twirl === | ||
− | We can add another transformation to it like this : | + | We can add another transformation to it like this: |
− | <syntaxhighlight>var image: TBGRABitmap; | + | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | var image: TBGRABitmap; | ||
grad: TBGRAGradientScanner; | grad: TBGRAGradientScanner; | ||
affine: TBGRAAffineScannerTransform; | affine: TBGRAAffineScannerTransform; | ||
Line 78: | Line 84: | ||
image.Draw(Canvas,0,0,True); | image.Draw(Canvas,0,0,True); | ||
image.free; | image.free; | ||
− | end; </syntaxhighlight> | + | end; |
+ | </syntaxhighlight> | ||
Here, we simply create a twirl transformation applied to the previous one, and fill with it. | Here, we simply create a twirl transformation applied to the previous one, and fill with it. | ||
Line 90: | Line 97: | ||
=== Use a custom scanner === | === Use a custom scanner === | ||
− | We may want to create our own gradient generator. Here is for example a multiply gradient : | + | We may want to create our own gradient generator. Here is for example a multiply gradient: |
− | <syntaxhighlight>type | + | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | type | ||
{ TBGRAMultiplyScanner } | { TBGRAMultiplyScanner } | ||
Line 112: | Line 121: | ||
mul := cycle512(round(x*y)); | mul := cycle512(round(x*y)); | ||
result := BGRA(mul,mul,mul,255); | result := BGRA(mul,mul,mul,255); | ||
− | end; </syntaxhighlight> | + | end; |
+ | </syntaxhighlight> | ||
It is derived from TBGRACustomScanner to be used for filling, and the ScanAt function is overridden. It computes the product of both coordinates and make a cycle of 512 with it (from 0 to 255 and then from 255 down to 0). | It is derived from TBGRACustomScanner to be used for filling, and the ScanAt function is overridden. It computes the product of both coordinates and make a cycle of 512 with it (from 0 to 255 and then from 255 down to 0). | ||
− | Let's draw it on the screen with a simple affine transformation : | + | Let's draw it on the screen with a simple affine transformation: |
− | <syntaxhighlight>var image: TBGRABitmap; | + | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | var image: TBGRABitmap; | ||
grad: TBGRAMultiplyScanner; | grad: TBGRAMultiplyScanner; | ||
affine: TBGRAAffineScannerTransform; | affine: TBGRAAffineScannerTransform; | ||
Line 133: | Line 145: | ||
image.Draw(Canvas,0,0,True); | image.Draw(Canvas,0,0,True); | ||
image.free; | image.free; | ||
− | end; </syntaxhighlight> | + | end; |
+ | </syntaxhighlight> | ||
=== Run the program === | === Run the program === | ||
− | It should look like this : | + | It should look like this: |
[[Image:BGRATutorial11c.png]] | [[Image:BGRATutorial11c.png]] | ||
Line 143: | Line 156: | ||
=== Make it beautiful === | === Make it beautiful === | ||
− | Add some colors by modifying the ScanAt procedure of the multiply gradient : | + | Add some colors by modifying the ScanAt procedure of the multiply gradient: |
− | <syntaxhighlight>var | + | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | var | ||
mul: integer; | mul: integer; | ||
begin | begin | ||
mul := round(x*y); | mul := round(x*y); | ||
result := BGRA(cycle512(round(x*10)),cycle512(mul),cycle512(round(y*10)),255); | result := BGRA(cycle512(round(x*10)),cycle512(mul),cycle512(round(y*10)),255); | ||
− | end; </syntaxhighlight> | + | end; |
+ | </syntaxhighlight> | ||
The red and blue intensities are filled with a cycle of x and y positions. | The red and blue intensities are filled with a cycle of x and y positions. | ||
− | And add some rotation : | + | And add some rotation: |
− | <syntaxhighlight> | + | |
+ | <syntaxhighlight lang="pascal"> | ||
+ | affine := TBGRAAffineScannerTransform.Create(grad); | ||
affine.Scale(6,4); | affine.Scale(6,4); | ||
affine.RotateDeg(-30); | affine.RotateDeg(-30); | ||
− | affine.Translate(ClientWidth/2, ClientHeight/2); </syntaxhighlight> | + | affine.Translate(ClientWidth/2, ClientHeight/2); |
+ | </syntaxhighlight> | ||
[[Image:BGRATutorial11d.png]] | [[Image:BGRATutorial11d.png]] |
Revision as of 14:04, 3 January 2020
│ Deutsch (de) │ English (en) │ español (es) │ français (fr) │
Home | Tutorial 1 | Tutorial 2 | Tutorial 3 | Tutorial 4 | Tutorial 5 | Tutorial 6 | Tutorial 7 | Tutorial 8 | Tutorial 9 | Tutorial 10 | Tutorial 11 | Tutorial 12 | Tutorial 13 | Tutorial 14 | Tutorial 15 | Tutorial 16 | Edit
This tutorial shows how to combine transformations.
Create a new project
Create a new project and add a reference to BGRABitmap, the same way as in the first tutorial.
Affine transformation of a radial gradient
Here is an affine transformation applied on a gradient like we did with textures:
uses BGRAGradientScanner, BGRATransform;
procedure TForm1.FormPaint(Sender: TObject);
var image: TBGRABitmap;
grad: TBGRAGradientScanner;
affine: TBGRAAffineScannerTransform;
begin
image := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRABlack );
grad := TBGRAGradientScanner.Create(BGRA(0,0,255),BGRAWhite,gtRadial,PointF(0,0),PointF(1,0),True,True);
affine := TBGRAAffineScannerTransform.Create(grad);
affine.Scale(150,80);
affine.RotateDeg(-30);
affine.Translate(ClientWidth/2, ClientHeight/2);
image.Fill(affine);
affine.free;
grad.free;
image.Draw(Canvas,0,0,True);
image.free;
end;
The base gradient is radial, centered at origin (0,0), of radius 1.
The affine transformation does the following:
- stretch the gradient to a size of 150x80
- rotate 30 degrees in counterclockwise direction
- center it in the form
The Fill instruction draws the result into the image.
Run the program
You should obtain a blue and white ellipse gradient.
Combine with a twirl
We can add another transformation to it like this:
var image: TBGRABitmap;
grad: TBGRAGradientScanner;
affine: TBGRAAffineScannerTransform;
twirl: TBGRATwirlScanner;
begin
image := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRABlack );
grad := TBGRAGradientScanner.Create(BGRA(0,0,255),BGRAWhite,gtRadial,PointF(0,0),PointF(1,0),True,True);
affine := TBGRAAffineScannerTransform.Create(grad);
affine.Scale(150,80);
affine.RotateDeg(-30);
affine.Translate(ClientWidth/2, ClientHeight/2);
twirl := TBGRATwirlScanner.Create(affine,Point(ClientWidth div 2, ClientHeight div 2),100);
image.Fill(twirl);
twirl.Free;
affine.free;
grad.free;
image.Draw(Canvas,0,0,True);
image.free;
end;
Here, we simply create a twirl transformation applied to the previous one, and fill with it.
Run the program
Now the center of the gradient is twirled.
Use a custom scanner
We may want to create our own gradient generator. Here is for example a multiply gradient:
type
{ TBGRAMultiplyScanner }
TBGRAMultiplyScanner = class(TBGRACustomScanner)
function ScanAt(X, Y: Single): TBGRAPixel; override;
end;
{ TBGRAMultiplyScanner }
function TBGRAMultiplyScanner.ScanAt(X, Y: Single): TBGRAPixel;
function cycle512(value: integer): integer; inline;
begin
result := value and 511;
if result >= 256 then result := 511-result;
end;
var
mul: integer;
begin
mul := cycle512(round(x*y));
result := BGRA(mul,mul,mul,255);
end;
It is derived from TBGRACustomScanner to be used for filling, and the ScanAt function is overridden. It computes the product of both coordinates and make a cycle of 512 with it (from 0 to 255 and then from 255 down to 0).
Let's draw it on the screen with a simple affine transformation:
var image: TBGRABitmap;
grad: TBGRAMultiplyScanner;
affine: TBGRAAffineScannerTransform;
begin
image := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRABlack );
grad := TBGRAMultiplyScanner.Create;
affine := TBGRAAffineScannerTransform.Create(grad);
affine.Scale(6,4);
affine.Translate(ClientWidth/2, ClientHeight/2);
image.Fill(affine);
affine.free;
grad.free;
image.Draw(Canvas,0,0,True);
image.free;
end;
Run the program
It should look like this:
Make it beautiful
Add some colors by modifying the ScanAt procedure of the multiply gradient:
var
mul: integer;
begin
mul := round(x*y);
result := BGRA(cycle512(round(x*10)),cycle512(mul),cycle512(round(y*10)),255);
end;
The red and blue intensities are filled with a cycle of x and y positions.
And add some rotation:
affine := TBGRAAffineScannerTransform.Create(grad);
affine.Scale(6,4);
affine.RotateDeg(-30);
affine.Translate(ClientWidth/2, ClientHeight/2);
Previous tutorial (texture mapping) Next tutorial (text functions)