Difference between revisions of "BGRABitmap tutorial 11"

From Free Pascal wiki
Jump to navigationJump to search
m (→‎Combine with a twirl: TBGRATwirlScanner name changed)
(link to AggPas sample)
 
(6 intermediate revisions by 5 users not shown)
Line 3: Line 3:
 
{{BGRABitmap_tutorial_index}}
 
{{BGRABitmap_tutorial_index}}
  
This tutorial shows how to combine transformations.
+
This tutorial shows how to combine transformations. A sample project can be found in [[BGRABitmap AggPas#Alpha gradient|BGRABitmap AggPas]].
  
 
=== Create a new project ===
 
=== Create a new project ===
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:
<delphi>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;  </delphi>
+
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 transformations 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:
<delphi>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; </delphi>
+
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 one 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:
<delphi>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; </delphi>
+
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 overriden. 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 lang="pascal">
<delphi>var image: TBGRABitmap;
+
var image: TBGRABitmap;
 
     grad: TBGRAMultiplyScanner;
 
     grad: TBGRAMultiplyScanner;
 
     affine: TBGRAAffineScannerTransform;
 
     affine: TBGRAAffineScannerTransform;
Line 126: Line 138:
 
   affine := TBGRAAffineScannerTransform.Create(grad);
 
   affine := TBGRAAffineScannerTransform.Create(grad);
 
   affine.Scale(6,4);
 
   affine.Scale(6,4);
  affine.RotateDeg(-30);
 
 
   affine.Translate(ClientWidth/2, ClientHeight/2);
 
   affine.Translate(ClientWidth/2, ClientHeight/2);
 
   image.Fill(affine);
 
   image.Fill(affine);
Line 134: Line 145:
 
   image.Draw(Canvas,0,0,True);
 
   image.Draw(Canvas,0,0,True);
 
   image.free;
 
   image.free;
end; </delphi>
+
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 144: 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:
<delphi>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;  </delphi>
+
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:
<delphi> affine := TBGRAAffineScannerTransform.Create(grad);
+
 
 +
<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); </delphi>
+
   affine.Translate(ClientWidth/2, ClientHeight/2);  
 +
</syntaxhighlight>
  
 
[[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]]
 +
[[Category: BGRABitmap]]

Latest revision as of 11:48, 20 May 2023

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. A sample project can be found in BGRABitmap AggPas.

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.

BGRATutorial11a.png

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.

BGRATutorial11b.png

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:

BGRATutorial11c.png

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);

BGRATutorial11d.png

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