Difference between revisions of "Developing with Graphics"
Sekelsenmat (talk | contribs) m |
Sekelsenmat (talk | contribs) m (thanks to Andreas Berger about this) |
||
Line 100: | Line 100: | ||
Now we will examine the options we have for drawing on a TCanvas: | Now we will examine the options we have for drawing on a TCanvas: | ||
* Draw to a TImage | * Draw to a TImage | ||
− | * Draw on the OnPaint event of a TPaintBox or another control | + | * Draw on the OnPaint event of the form, a TPaintBox or another control |
− | * Create a custom | + | * Create a custom control witch draws itself |
===Draw to a TImage=== | ===Draw to a TImage=== | ||
+ | Never use the OnPaint event to draw to a TImage. A TImage is buffered so all you need to do is draw to it from anywhere and the change is there forever. However, if you are constantly redrawing, the image will flicker. In this case you can try the other options. | ||
+ | <code> | ||
+ | var | ||
+ | x, y: Integer; | ||
+ | begin | ||
+ | // Draws the backgroun | ||
+ | Image.Canvas.Pen.Color := clWhite; | ||
+ | Image.Canvas.Rectangle(0, 0, Image.Width, Image.Height); | ||
− | + | // Draws squares | |
+ | Bitmap.Canvas.Pen.Color := clBlack; | ||
+ | for x := 1 to 8 do | ||
+ | for y := 1 to 8 do | ||
+ | Image.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8), | ||
+ | Round(x * Image.Width / 8), Round(y * Image.Height / 8)); | ||
</code> | </code> | ||
+ | |||
+ | ===Draw on the OnPaint event=== | ||
+ | |||
+ | ===Create a custom control witch draws itself=== |
Revision as of 14:19, 2 October 2005
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
italiano (it) │
日本語 (ja) │
한국어 (ko) │
Nederlands (nl) │
português (pt) │
русский (ru) │
slovenčina (sk) │
中文(中国大陆) (zh_CN) │
中文(台灣) (zh_TW) │
Overview
This page will be the start for tutorials with regard to manipulating Bitmaps and other graphics in your program. As I'm not a graphics programmer I invite all who are, to share their expertise! Just add a link to the next section, add a page and create your own WiKi article. On this page some general information will be given.
Other graphics tutorials
- Making a Bitmap fade.
Working with TBitmap
The first thing to remember is that Lazarus is meant to be platform independent, so any methods using Windows API functionality are out of the question. So a method like ScanLine is not supported by Lazarus because it is intended for Device Independant Bitmap and uses functions from the GDI32.dll.
Be careful that if you do not specify the width and height of your TBitmap it will have the standard one, witch is quite small.
A fading example
Say you want to make a Fading picture. In Delphi you could do something like:
type
PRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..32767] of TRGBTriple;
procedure TForm1.FadeIn(aBitMap: TBitMap);
var
Bitmap, BaseBitmap: TBitmap;
Row, BaseRow: PRGBTripleArray;
x, y, step: integer;
begin
Bitmap := TBitmap.Create;
try
Bitmap.PixelFormat := pf32bit; // or pf24bit
Bitmap.Assign(aBitMap);
BaseBitmap := TBitmap.Create;
try
BaseBitmap.PixelFormat := pf32bit;
BaseBitmap.Assign(Bitmap);
for step := 0 to 32 do begin
for y := 0 to (Bitmap.Height - 1) do begin
BaseRow := BaseBitmap.Scanline[y];
Row := Bitmap.Scanline[y];
for x := 0 to (Bitmap.Width - 1) do begin
Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;
Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading
Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;
end;
end;
Form1.Canvas.Draw(0, 0, Bitmap);
InvalidateRect(Form1.Handle, nil, False);
RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
end;
finally
BaseBitmap.Free;
end;
finally
Bitmap.Free;
end;
end;
This function in Lazarus could be implemented like:
procedure TForm1.FadeIn(ABitMap: TBitMap);
var
SrcIntfImg, TempIntfImg: TLazIntfImage;
ImgHandle,ImgMaskHandle: HBitmap;
FadeStep: Integer;
px, py: Integer;
CurColor: TFPColor;
TempBitmap: TBitmap;
begin
SrcIntfImg:=TLazIntfImage.Create(0,0);
SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
TempIntfImg:=TLazIntfImage.Create(0,0);
TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
TempBitmap:=TBitmap.Create;
for FadeStep:=1 to 32 do begin
for py:=0 to SrcIntfImg.Height-1 do begin
for px:=0 to SrcIntfImg.Width-1 do begin
CurColor:=SrcIntfImg.Colors[px,py];
CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
TempIntfImg.Colors[px,py]:=CurColor;
end;
end;
TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);
TempBitmap.Handle:=ImgHandle;
TempBitmap.MaskHandle:=ImgMaskHandle;
Canvas.Draw(0,0,TempBitmap);
end;
SrcIntfImg.Free;
TempIntfImg.Free;
TempBitmap.Free;
end;
The Lazarus code on this page has been taken from the $LazarusPath/examples/lazintfimage/fadein1.lpi project. So if you want a flying start with graphics programming take a closer look at this example.
Avoid flickering
Some times there is a need to draw 2D graphics witch are quickly changing. Now there are many options on how to do that. The first choice is about whether you will work with hardware acceleration using something like OpenGL or simply use the Canvas. OpenGL has the best speed on new PCs, specially those with good video cards, but it is quite heavy for simple programs or old computers, so we will be drawing to the standard Canvas here. If you need help with OpenGL, take a look at the example that comes with Lazarus.
Now we will examine the options we have for drawing on a TCanvas:
- Draw to a TImage
- Draw on the OnPaint event of the form, a TPaintBox or another control
- Create a custom control witch draws itself
Draw to a TImage
Never use the OnPaint event to draw to a TImage. A TImage is buffered so all you need to do is draw to it from anywhere and the change is there forever. However, if you are constantly redrawing, the image will flicker. In this case you can try the other options.
var
x, y: Integer;
begin
// Draws the backgroun
Image.Canvas.Pen.Color := clWhite;
Image.Canvas.Rectangle(0, 0, Image.Width, Image.Height);
// Draws squares
Bitmap.Canvas.Pen.Color := clBlack;
for x := 1 to 8 do
for y := 1 to 8 do
Image.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),
Round(x * Image.Width / 8), Round(y * Image.Height / 8));