Difference between revisions of "BGRABitmap tutorial 11"

From Free Pascal wiki
Jump to navigationJump to search
m (typos)
Line 162: Line 162:
 
[[Image:BGRATutorial11d.png]]
 
[[Image:BGRATutorial11d.png]]
  
[[BGRABitmap tutorial 10|Previous tutorial (texture mapping)]]
+
[[BGRABitmap tutorial 10|Previous tutorial (texture mapping)]] [[BGRABitmap tutorial 12|Next tutorial (text functions)]]
  
 
[[Category:Graphics]]
 
[[Category:Graphics]]

Revision as of 17:13, 16 April 2011

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 : <delphi>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; </delphi>

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.

BGRATutorial11a.png

Combine with a twirl

We can add another transformation to it like this : <delphi>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; </delphi>

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.

BGRATutorial11b.png

Use a custom scanner

We may want to create our own gradient generator. Here is for example a multiply gradient : <delphi>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; </delphi>

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 : <delphi>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.RotateDeg(-30);
 affine.Translate(ClientWidth/2, ClientHeight/2);
 image.Fill(affine);
 affine.free;
 grad.free;
 image.Draw(Canvas,0,0,True);
 image.free;

end; </delphi>

Run the program

It should look like this :

BGRATutorial11c.png

Make it beautiful

Add some colors by modifying the ScanAt procedure of the multiply gradient : <delphi>var

 mul: integer;

begin

 mul := round(x*y);
 result := BGRA(cycle512(round(x*10)),cycle512(mul),cycle512(round(y*10)),255);

end; </delphi>

The red and blue intensities are filled with a cycle of x and y positions.

And add some rotation : <delphi> affine := TBGRAAffineScannerTransform.Create(grad);

 affine.Scale(6,4);
 affine.RotateDeg(-30);
 affine.Translate(ClientWidth/2, ClientHeight/2); </delphi>

BGRATutorial11d.png

Previous tutorial (texture mapping) Next tutorial (text functions)