Sign in Join
Wiki copytemporary

BGRABitmap tutorial 11: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: BGRABitmap tutorial 11

OldNewLine
1+This tutorial shows how to combine transformations. A sample project can be found in [[BGRABitmap AggPas]].
2+
3+### Create a new project
4+
5+Create a new project and add a reference to [[BGRABitmap]], the same way as in [[BGRABitmap tutorial|the first tutorial]].
6+
7+### Affine transformation of a radial gradient
8+
9+Here is an affine transformation applied on a gradient like we did with textures:
10+
11+``` pascal
12+uses BGRAGradientScanner, BGRATransform;
13+
14+procedure TForm1.FormPaint(Sender: TObject);
15+var image: TBGRABitmap;
16+ grad: TBGRAGradientScanner;
17+ affine: TBGRAAffineScannerTransform;
18+begin
19+ image := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRABlack );
20+
21+ grad := TBGRAGradientScanner.Create(BGRA(0,0,255),BGRAWhite,gtRadial,PointF(0,0),PointF(1,0),True,True);
22+
23+ affine := TBGRAAffineScannerTransform.Create(grad);
24+ affine.Scale(150,80);
25+ affine.RotateDeg(-30);
26+ affine.Translate(ClientWidth/2, ClientHeight/2);
27+
28+ image.Fill(affine);
29+
30+ affine.free;
31+ grad.free;
32+
33+ image.Draw(Canvas,0,0,True);
34+ image.free;
35+end;
36+```
37+
38+The base gradient is radial, centered at origin (0,0), of radius 1.
39+
40+The affine transformation does the following:
41+
42+- stretch the gradient to a size of 150x80
43+- rotate 30 degrees in counterclockwise direction
44+- center it in the form
45+
46+The Fill instruction draws the result into the image.
47+
48+### Run the program
49+
50+You should obtain a blue and white ellipse gradient.
51+
52+<figure>
53+<img src="BGRATutorial11a.png" title="BGRATutorial11a.png" />
54+<figcaption>BGRATutorial11a.png</figcaption>
55+</figure>
56+
57+### Combine with a twirl
58+
59+We can add another transformation to it like this:
60+
61+``` pascal
62+var image: TBGRABitmap;
63+ grad: TBGRAGradientScanner;
64+ affine: TBGRAAffineScannerTransform;
65+ twirl: TBGRATwirlScanner;
66+begin
67+ image := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRABlack );
68+
69+ grad := TBGRAGradientScanner.Create(BGRA(0,0,255),BGRAWhite,gtRadial,PointF(0,0),PointF(1,0),True,True);
70+
71+ affine := TBGRAAffineScannerTransform.Create(grad);
72+ affine.Scale(150,80);
73+ affine.RotateDeg(-30);
74+ affine.Translate(ClientWidth/2, ClientHeight/2);
75+
76+ twirl := TBGRATwirlScanner.Create(affine,Point(ClientWidth div 2, ClientHeight div 2),100);
77+ image.Fill(twirl);
78+ twirl.Free;
79+
80+ affine.free;
81+ grad.free;
82+
83+ image.Draw(Canvas,0,0,True);
84+ image.free;
85+end;
86+```
87+
88+Here, we simply create a twirl transformation applied to the previous one, and fill with it.
89+
90+### Run the program
91+
92+Now the center of the gradient is twirled.
93+
94+<figure>
95+<img src="BGRATutorial11b.png" title="BGRATutorial11b.png" />
96+<figcaption>BGRATutorial11b.png</figcaption>
97+</figure>
98+
99+### Use a custom scanner
100+
101+We may want to create our own gradient generator. Here is for example a multiply gradient:
102+
103+``` pascal
104+type
105+ { TBGRAMultiplyScanner }
106+
107+ TBGRAMultiplyScanner = class(TBGRACustomScanner)
108+ function ScanAt(X, Y: Single): TBGRAPixel; override;
109+ end;
110+
111+{ TBGRAMultiplyScanner }
112+
113+function TBGRAMultiplyScanner.ScanAt(X, Y: Single): TBGRAPixel;
114+ function cycle512(value: integer): integer; inline;
115+ begin
116+ result := value and 511;
117+ if result >= 256 then result := 511-result;
118+ end;
119+
120+var
121+ mul: integer;
122+begin
123+ mul := cycle512(round(x*y));
124+ result := BGRA(mul,mul,mul,255);
125+end;
126+```
127+
128+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).
129+
130+Let's draw it on the screen with a simple affine transformation:
131+
132+``` pascal
133+var image: TBGRABitmap;
134+ grad: TBGRAMultiplyScanner;
135+ affine: TBGRAAffineScannerTransform;
136+begin
137+ image := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRABlack );
138+
139+ grad := TBGRAMultiplyScanner.Create;
140+ affine := TBGRAAffineScannerTransform.Create(grad);
141+ affine.Scale(6,4);
142+ affine.Translate(ClientWidth/2, ClientHeight/2);
143+ image.Fill(affine);
144+ affine.free;
145+ grad.free;
146+
147+ image.Draw(Canvas,0,0,True);
148+ image.free;
149+end;
150+```
151+
152+### Run the program
153+
154+It should look like this:
155+
156+<figure>
157+<img src="BGRATutorial11c.png" title="BGRATutorial11c.png" />
158+<figcaption>BGRATutorial11c.png</figcaption>
159+</figure>
160+
161+### Make it beautiful
162+
163+Add some colors by modifying the ScanAt procedure of the multiply gradient:
164+
165+``` pascal
166+var
167+ mul: integer;
168+begin
169+ mul := round(x*y);
170+ result := BGRA(cycle512(round(x*10)),cycle512(mul),cycle512(round(y*10)),255);
171+end;
172+```
173+
174+The red and blue intensities are filled with a cycle of x and y positions.
175+
176+And add some rotation:
177+
178+``` pascal
179+ affine := TBGRAAffineScannerTransform.Create(grad);
180+ affine.Scale(6,4);
181+ affine.RotateDeg(-30);
182+ affine.Translate(ClientWidth/2, ClientHeight/2);
183+```
184+
185+<figure>
186+<img src="BGRATutorial11d.png" title="BGRATutorial11d.png" />
187+<figcaption>BGRATutorial11d.png</figcaption>
188+</figure>
189+
190+[[BGRABitmap tutorial 10|Previous tutorial (texture mapping)]] [[BGRABitmap tutorial 12|Next tutorial (text functions)]]
191+
192+---
193+*From the Free Pascal wiki, page "BGRABitmap tutorial 11", as it stood on 2023-05-20 after a change by Circular, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
194+Category: BGRABitmap
195+Category: Graphics

Back to history