BGRABitmap tutorial 5

From Lazarus wiki
Jump to navigationJump to search

This tutorial shows you how to use layers.

Create a new project

Create a new project and add a reference to BGRABitmap, the same way as in the first tutorial.

Add a painting handler

With the object inspector, add an OnPaint handler and write : <delphi>procedure TForm1.FormPaint(Sender: TObject); var image: TBGRABitmap;

   size: single;
 procedure DrawMoon;
 var layer: TBGRABitmap;
 begin
   layer := TBGRABitmap.Create(image.Width,image.Height);
   layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
   layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
   image.PutImage(0,0,layer,dmDrawWithTransparency);
   layer.Free;
 end;

begin

 image := TBGRABitmap.Create(ClientWidth,ClientHeight);
 //Compute available space in both directions
 if image.Height < image.Width then
   size := image.Height
 else
   size := image.Width;
 image.GradientFill(0,0,image.Width,image.Height,
                    BGRA(128,192,255),BGRA(0,0,255),
                    gtLinear,PointF(0,0),PointF(0,image.Height),
                    dmSet);
 DrawMoon;
 image.Draw(Canvas,0,0,True);
 image.free;

end; </delphi>

The procedure creates an image and fill it with a blue gradient. This is the background layer.

The procedure DrawMoon creates a layer, draw a moon in it. First a white disk is drawn, then a smaller disk is substracted. Finally, this layer is merged with the background.

Run the program

You should see a blue sky with a moon. When you resize the form, the image is resized accordingly.

Tutorial5a.png

Add another layer with a sun

In the OnPaint event, add the following subprocedure : <delphi> procedure DrawSun;

 var layer,mask: TBGRABitmap;
 begin
   layer := TBGRABitmap.Create(image.Width,image.Height);
   layer.GradientFill(0,0,layer.Width,layer.Height,
                      BGRA(255,255,0),BGRA(255,0,0),
                      gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
                      dmSet);
   mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
   mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
   layer.ApplyMask(mask);
   mask.Free;
   image.PutImage(0,0,layer,dmDrawWithTransparency);
   layer.Free;
 end;   </delphi>

This procedures creates a radial gradient of red and orange and applies a circular mask to it. This results in a colored disk. Finally, the layer is merged with the background.

Add a call to this procedure to draw it after the moon.

Run the program

You should see a blue sky with a moon and a sun. When you resize the form, the image is resized accordingly.

BGRATutorial5b.png

Add a light layer

Add the following subprocedure in the OnPaint event : <delphi> procedure ApplyLight;

 var layer: TBGRABitmap;
 begin
   layer := TBGRABitmap.Create(image.Width,image.Height);
   layer.GradientFill(0,0,layer.Width,layer.Height,
                      BGRA(255,255,255),BGRA(64,64,64),
                      gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
                      dmSet);
   image.BlendImage(0,0,layer,boMultiply);
   layer.Free;
 end;</delphi>

This procedure draws a layer with a white radial gradient. It is then applied to multiply the image.

Resulting code

<delphi>procedure TForm1.FormPaint(Sender: TObject); var image: TBGRABitmap;

   size: single;
 procedure DrawMoon;
 var layer: TBGRABitmap;
 begin
   layer := TBGRABitmap.Create(image.Width,image.Height);
   layer.FillEllipseAntialias(layer.Width/2,layer.Height/2,size*0.4,size*0.4,BGRA(224,224,224,128));
   layer.EraseEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.3,size*0.3,255);
   image.PutImage(0,0,layer,dmDrawWithTransparency);
   layer.Free;
 end;
 procedure DrawSun;
 var layer,mask: TBGRABitmap;
 begin
   layer := TBGRABitmap.Create(image.Width,image.Height);
   layer.GradientFill(0,0,layer.Width,layer.Height,
                      BGRA(255,255,0),BGRA(255,0,0),
                      gtRadial,PointF(layer.Width/2,layer.Height/2-size*0.15),PointF(layer.Width/2+size*0.45,layer.Height/2-size*0.15),
                      dmSet);
   mask := TBGRABitmap.Create(layer.Width,layer.Height,BGRABlack);
   mask.FillEllipseAntialias(layer.Width/2+size*0.15,layer.Height/2,size*0.25,size*0.25,BGRAWhite);
   layer.ApplyMask(mask);
   mask.Free;
   image.PutImage(0,0,layer,dmDrawWithTransparency);
   layer.Free;
 end;
 procedure ApplyLight;
 var layer: TBGRABitmap;
 begin
   layer := TBGRABitmap.Create(image.Width,image.Height);
   layer.GradientFill(0,0,layer.Width,layer.Height,
                      BGRA(255,255,255),BGRA(64,64,64),
                      gtRadial,PointF(layer.Width*5/6,layer.Height/2),PointF(layer.Width*1/3,layer.Height/4),
                      dmSet);
   image.BlendImage(0,0,layer,boMultiply);
   layer.Free;
 end;

begin

 image := TBGRABitmap.Create(ClientWidth,ClientHeight);
 if image.Height < image.Width then
   size := image.Height
 else
   size := image.Width;
 image.GradientFill(0,0,image.Width,image.Height,
                    BGRA(128,192,255),BGRA(0,0,255),
                    gtLinear,PointF(0,0),PointF(0,image.Height),
                    dmSet);
 DrawMoon;
 DrawSun;
 ApplyLight;
 image.Draw(Canvas,0,0,True);
 image.free;

end;</delphi>

Run the program

You should see a blue sky with a moon and a sun, with a light effect. When you resize the form, the image is resized accordingly.

Tutorial5c.png

Previous tutorial (direct pixel access)