Sign in Join
Wiki copytemporary

Developing with Graphics/sk: what changed

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

Title: Developing with Graphics/sk

OldNewLine
1+Táto stránky má byť počiatočný postup s ohľadom na manipuláciu s bitmapami a inou grafikou. Keďže nie som programátor grafiky, pozývam všetkých na zdieľanie ich skúseností! Jednoducho pridajte odkaz na ďalšiu sekciu, pridajte stránku a vytvorte svoj vlastný článok WiKi.
2+
3+Na tejto stránke budú poskytnuté niektoré všeobecné informácie.
4+
5+## Ďalšie grafické články
6+
7+- [[GLScene|GLScene (en)]] - Port vizuálnej OpenGL grafickej knižnice [GLScene](http://www.glscene.org)
8+- [[TAChart|TAChart (en)]] - Diagramový komponent pre Lazarus
9+- [[PascalMagick|PascalMagick (en)]] - jednoducho použiteľné API pre prepojenie s [ImageMagick](http://www.imagemagick.org), viacplatformová slobodná sada programov pre vytváranie, úpravu a kompozíciu bitmapových obrázkov.
10+- [[PlotPanel|PlotPanel (en)]] - Zapisovací a kresliaci komponent pre animované grafy.
11+- [[LazRGBGraphics|LazRGBGraphics (en)]] - Balíček pre pre rýchle spracovanie a manipuláciu s obrázkami v pamäti (ako scan line).
12+- [[Perlin Noise|Perlin Noise (en)]] - Článok o používaní Perlin Noise v LCL aplikáciách.
13+
14+## Práca s TBitmap
15+
16+Prvá vec, na ktrorú treba pamätať je, že Lazarus je zamýšľaný ako platformovo nezávislý, tak všetky metódy používajúce funkcie Windows API sú mimo. Takže metóda ako ScanLine nie je v Lazarus podporovaná, pretože je určená pre Device Independant Bitmap a používa funkcie z GDI32.dll.
17+
18+Zapamätajte si, že ak nezadáte výšku a šírku svojho [[doc:lcl/graphics/tbitmap.html|TBitmap]], bude mať štandardnú veľkosť, ktorá je celkom malá.
19+
20+### Príklad miznutia
21+
22+Predstavte si, že chcete vytvoriť miznúci obrázok. V Delphi môžete urobiť niečo také:
23+
24+``` pascal
25+ type
26+ PRGBTripleArray = ^TRGBTripleArray;
27+ TRGBTripleArray = array[0..32767] of TRGBTriple;
28+
29+ procedure TForm1.FadeIn(aBitMap: TBitMap);
30+ var
31+ Bitmap, BaseBitmap: TBitmap;
32+ Row, BaseRow: PRGBTripleArray;
33+ x, y, step: integer;
34+ begin
35+ Bitmap := TBitmap.Create;
36+ try
37+ Bitmap.PixelFormat := pf32bit; // or pf24bit
38+ Bitmap.Assign(aBitMap);
39+ BaseBitmap := TBitmap.Create;
40+ try
41+ BaseBitmap.PixelFormat := pf32bit;
42+ BaseBitmap.Assign(Bitmap);
43+ for step := 0 to 32 do begin
44+ for y := 0 to (Bitmap.Height - 1) do begin
45+ BaseRow := BaseBitmap.Scanline[y];
46+ Row := Bitmap.Scanline[y];
47+ for x := 0 to (Bitmap.Width - 1) do begin
48+ Row[x].rgbtRed := (step * BaseRow[x].rgbtRed) shr 5;
49+ Row[x].rgbtGreen := (step * BaseRow[x].rgbtGreen) shr 5; // Fading
50+ Row[x].rgbtBlue := (step * BaseRow[x].rgbtBlue) shr 5;
51+ end;
52+ end;
53+ Form1.Canvas.Draw(0, 0, Bitmap);
54+ InvalidateRect(Form1.Handle, nil, False);
55+ RedrawWindow(Form1.Handle, nil, 0, RDW_UPDATENOW);
56+ end;
57+ finally
58+ BaseBitmap.Free;
59+ end;
60+ finally
61+ Bitmap.Free;
62+ end;
63+ end;
64+```
65+
66+V Lazarus môže byť táto funkcia implementovaná takto:
67+
68+``` pascal
69+uses LCLType, // HBitmap type
70+ IntfGraphics, // TLazIntfImage type
71+ fpImage; // TFPColor type
72+...
73+ procedure TForm1.FadeIn(ABitMap: TBitMap);
74+ var
75+ SrcIntfImg, TempIntfImg: TLazIntfImage;
76+ ImgHandle,ImgMaskHandle: HBitmap;
77+ FadeStep: Integer;
78+ px, py: Integer;
79+ CurColor: TFPColor;
80+ TempBitmap: TBitmap;
81+ begin
82+ SrcIntfImg:=TLazIntfImage.Create(0,0);
83+ SrcIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
84+ TempIntfImg:=TLazIntfImage.Create(0,0);
85+ TempIntfImg.LoadFromBitmap(ABitmap.Handle,ABitmap.MaskHandle);
86+ TempBitmap:=TBitmap.Create;
87+ for FadeStep:=1 to 32 do begin
88+ for py:=0 to SrcIntfImg.Height-1 do begin
89+ for px:=0 to SrcIntfImg.Width-1 do begin
90+ CurColor:=SrcIntfImg.Colors[px,py];
91+ CurColor.Red:=(CurColor.Red*FadeStep) shr 5;
92+ CurColor.Green:=(CurColor.Green*FadeStep) shr 5;
93+ CurColor.Blue:=(CurColor.Blue*FadeStep) shr 5;
94+ TempIntfImg.Colors[px,py]:=CurColor;
95+ end;
96+ end;
97+ TempIntfImg.CreateBitmap(ImgHandle,ImgMaskHandle,false);
98+ TempBitmap.Handle:=ImgHandle;
99+ TempBitmap.MaskHandle:=ImgMaskHandle;
100+ Canvas.Draw(0,0,TempBitmap);
101+ end;
102+ SrcIntfImg.Free;
103+ TempIntfImg.Free;
104+ TempBitmap.Free;
105+ end;
106+```
107+
108+Lazarus kód na tejto stránke bol prevzatý z projektu \$LazarusPath/examples/lazintfimage/fadein1.lpi, takže ak chcete letmý štart s grafickým programovaním pozrite sa na tento príklad.
109+
110+### Kreslenie bitmáp transparentnou farbou
111+
112+Nová vlastnosť, implementovaná od Lazarus 0.9.11, sú farebne transparentné bitmapy. Bitmapové súbory (*.BMP) neuchovávajú žiadnu informáciu o priehľadnosti, ale môžu takto pracovať, ak im zvolíte farbu, ktorá bude reprezenzovať priesvitnú oblasť. To je bežný trik používaný v programoch Win32.
113+
114+Nasledujúci príklad načíta bitmapu zo zdroja Windows, vyberie farbu pre priehľadnosť (clFuchsia) a potom ho nakreslí na plátno.
115+
116+``` pascal
117+procedure MyForm.MyButtonOnClick(Sender: TObject);
118+var
119+ buffer: THandle;
120+ bmp: TBitmap;
121+ memstream: TMemoryStream;
122+begin
123+ bmp := TBitmap.Create;
124+
125+ buffer := Windows.LoadBitmap(hInstance, MAKEINTRESOURCE(ResourceID));
126+
127+ if (buffer = 0) then exit; // Error loading the bitmap
128+
129+ bmp.Handle := buffer;
130+ memstream := TMemoryStream.create;
131+ try
132+ bmp.SaveToStream(memstream);
133+ memstream.position := 0;
134+ bmp.LoadFromStream(memstream);
135+ finally
136+ memstream.free;
137+ end;
138+
139+ bmp.Transparent := True;
140+ bmp.TransparentColor := clFuchsia;
141+
142+ MyCanvas.Draw(0, 0, bmp);
143+
144+ bmp.Free; // Release allocated resource
145+end;
146+```
147+
148+Všimnite si pamäťové operácie robené pomocou [[doc:rtl/classes/tmemorystream.html|TMemoryStream]], ktoré sú potrebné na zaistenie správne načítania obrázku.
149+
150+### Zachytenie snímky obrazovky
151+
152+Od Lazarus 0.9.16 môžete použiť LCL pre zachytenie snímku obrazovky platformovo nezávislým spôsobom. Nasledujúci príklad kódu to robí (pracuej na gtk2 a win32, ale nie na gtk1):
153+
154+``` pascal
155+ uses LCLIntf, LCLType;
156+
157+ ...
158+
159+var
160+ MyBitmap: TBitmap;
161+ ScreenDC: HDC;
162+begin
163+ MyBitmap := TBitmap.Create;
164+ ScreenDC := GetDC(0);
165+ MyBitmap.LoadFromDevice(ScreenDC);
166+ ReleaseDC(ScreenDC);
167+
168+ ...
169+```
170+
171+## Pohyblivá grafika - Ako sa vyhnúť blikaniu
172+
173+Mnoho programov kreslí svoj výstup do GUI ako 2D obrázky. Ak sa majú tieto obrázky rýchlo zmeniť, stretnete sa s problémom: rýchla zmena obrázkov často na obrazovke bliká. Tak sa stáva, že používatelia niekedy vidia celé obrázky a niekedy len ich čiastočné vykreslenie. To nastávapretože proces vykreslenia vyžaduje čas.
174+
175+Ale ako predísť blikaniu a získať vyššiu rýchlosť kreslenia? Sasmozrejme môžete pracovať s hardvérovou akceleráciou pomocou OpenGL, ale tento prístup je úplne ťažký pre malé programy alebo staré počítače. Tu sa zameriame na kreslenie do **TCanvas**. Ak potebujetepomôcť s OpenGL, pozrite si príklad, ktorý je v Lazarus. Môžete tiež použiť A.J. Ventersov gamepack, ktorý poskytuje dvojito buferované kresliace plátno a malý komponent.
176+
177+Teraz môžme preskúmať voľby, ktroé máme pre kreslenie do Canvas:
178+
179+- Kreslenie do TImage
180+- Kreslenie počas udalosti OnPaint
181+- Tvorba vlastného prvku, ktorý kreslí sám seba
182+- Použitie A.J.Venterovho gamepack
183+
184+### Kreslenie do TImage
185+
186+TImage pozostáva z dvoch častí: TGraphic, zvyčajne TBitmap, uchováva trvalý obrázok a viditeľnú oblasť, ktorá je prekreslená pri každom OnPaint. Zmena veľkosti TImage **nemení** veľkosť bitmapy.
187+
188+Obrázok (alebo bitmapa) je dostupná cez Image1.Picture.Graphic (alebo Image1.Picture.Bitmap). Plátno je Image1.Picture.Bitmap.Canvas. Plátno viditeľnej oblasti TImage je prístupné len počas Image1.OnPaint cez Image1.Canvas.
189+
190+
191+**Dôležité**: Nikdy nepoužívajte udalosť OnPaint prvku Image1 pre kreslenie grafiky/bitmapy TImage. Obrázok z TImage je buferovaný, takže potrebujete len nakresliť ho z hcikade a zmena je tam navždy. Avšak, ak ho trvalo prekresľujete, obrázok bude blikať. V tomto prípade treba skúsiť iné vlastnosti. Kreslenie do TImage je považované za pomalšie ako iné prístupy.
192+
193+#### Zmena veľkosti bitmapy z TImage
194+
195+
196+**Poznámka**: Nepoužívajte to počas OnPaint.
197+
198+``` pascal
199+ with Image1.Picture.Bitmap do begin
200+ Width:=100;
201+ Height:=120;
202+ end;
203+```
204+
205+#### Kreslenie na bitmapu z TImage
206+
207+
208+**Poznámka**: Nepoužívajte to počas OnPaint.
209+
210+``` pascal
211+ with Image1.Picture.Bitmap.Canvas do begin
212+ // fill the entire bitmap with red
213+ Brush.Color:=clRed;
214+ FillRect(0,0,Width,Height);
215+ end;
216+```
217+
218+Poznámka: Vo vnútri Image1.OnPaint ukazuje Image1.Canvas na nestálu viditeľnú oblasť. Na rozdiel od Image1.OnPaint, prvok Image1.Canvas ukazuje na Image1.Picture.Bitmap.Canvas.
219+
220+Iný príklad:
221+
222+``` pascal
223+ procedure TForm1.BitBtn1Click(Sender: TObject);
224+ var
225+ x, y: Integer;
226+ begin
227+ // Draws the backgroung
228+ MyImage.Canvas.Pen.Color := clWhite;
229+ MyImage.Canvas.Rectangle(0, 0, Image.Width, Image.Height);
230+
231+ // Draws squares
232+ MyImage.Canvas.Pen.Color := clBlack;
233+ for x := 1 to 8 do
234+ for y := 1 to 8 do
235+ MyImage.Canvas.Rectangle(Round((x - 1) * Image.Width / 8), Round((y - 1) * Image.Height / 8),
236+ Round(x * Image.Width / 8), Round(y * Image.Height / 8));
237+ end;
238+```
239+
240+#### Kreslenie na premenlivú vizuálnu oblasť TImage
241+
242+Do tejto oblasti možno kresli len počas OnPaint. OnPaint je volaná automaticky z LCL, keď sa oblasť stane neplatnou. Manuálne môžete zneplatniť oblasť pomocou Image1.Invalidate, ale toto nezavolá OnPaint okamžite a môžete ho volať koľkokrát chcete.
243+
244+``` pascal
245+ procedure TForm.Image1Paint(Sender: TObject);
246+ begin
247+ with Image1.Canvas do begin
248+ // paint a line
249+ Pen.Color:=clRed;
250+ Line(0,0,Width,Height);
251+ end;
252+ end;
253+```
254+
255+### Kreslenie počas udalosti OnPaint
256+
257+V tomto prípade bude celé kreslenie urobené počas udalosti OnPaint formulára. Nezostáva v buferi, ako pri TImage.
258+
259+### Tvorba vlastného prvku, ktorý kreslí sám seba
260+
261+Vytvorenie vlastného ovládacieho prvku má výhodu v štruktúrovaní svojho kódu a v opakvanom použití prvku. Toto riešenie je veľmi rýchle, ale stále môže generovať blikanie, ak nenakreslíte najprv do TBitmap a až potom nevykreslíte do plátna. v tomto prípade nie je potrebné použitie udalosti OnPaint prvku.
262+
263+Príklad vlastného prvku:
264+
265+``` pascal
266+ uses
267+ Classes, SysUtils, Controls, Graphics, LCLType;
268+
269+ type
270+ TMyDrawingControl = class(TCustomControl)
271+ public
272+ procedure EraseBackground(DC: HDC); override;
273+ procedure Paint; override;
274+ end;
275+
276+ implementation
277+
278+ procedure TMyDrawingControl.EraseBackground(DC: HDC);
279+ begin
280+ // Uncomment this to enable default background erasing
281+ //inherited EraseBackground(DC);
282+ end;
283+
284+ procedure TMyDrawingControl.Paint;
285+ var
286+ x, y: Integer;
287+ Bitmap: TBitmap;
288+ begin
289+ Bitmap := TBitmap.Create;
290+ try
291+ // Initializes the Bitmap Size
292+ Bitmap.Height := Height;
293+ Bitmap.Width := Width;
294+
295+ // Draws the background
296+ Bitmap.Canvas.Pen.Color := clWhite;
297+ Bitmap.Canvas.Rectangle(0, 0, Width, Height);
298+
299+ // Draws squares
300+ Bitmap.Canvas.Pen.Color := clBlack;
301+ for x := 1 to 8 do
302+ for y := 1 to 8 do
303+ Bitmap.Canvas.Rectangle(Round((x - 1) * Width / 8), Round((y - 1) * Height / 8),
304+ Round(x * Width / 8), Round(y * Height / 8));
305+
306+ Canvas.Draw(0, 0, Bitmap);
307+ finally
308+ Bitmap.Free;
309+ end;
310+
311+ inherited Paint;
312+ end;
313+```
314+
315+a ako ho vytvoríme na formulári:
316+
317+``` pascal
318+ procedure TMyForm.FormCreate(Sender: TObject);
319+ begin
320+ MyDrawingControl:= TMyDrawingControl.Create(Self);
321+ MyDrawingControl.Height := 400;
322+ MyDrawingControl.Width := 500;
323+ MyDrawingControl.Top := 0;
324+ MyDrawingControl.Left := 0;
325+ MyDrawingControl.Parent := Self;
326+ MyDrawingControl.DoubleBuffered := True;
327+ end;
328+```
329+
330+len ho nezabudnite zničiť:
331+
332+``` pascal
333+ procedure TMyForm.FormDestroy(Sender: TObject);
334+ begin
335+ MyDrawingControl.Free;
336+ end;
337+```
338+
339+nastvenie vlastností Top a Left na nulu nie je potrebné, pretože to je štandardná pozícia, ale je urobené aby zdôraznenie umiestneniaprvku.
340+
341+"MyDrawingControl.Parent := Self;" je veľmi dôležité a neuvidíte svoj prvok ak to nenastavíte.
342+
343+"MyDrawingControl.DoubleBuffered := True;" je vyžadované na predídenie blikania vo Windows. V gtk nemá vplyv.
344+
345+### Použitie A.J.Venterovho gamepack
346+
347+Prístup v gamepack je kreslenie všetkého do dvojito buferovaného plátna, ktoré len berie aktualizácie viditeľného plátna, keď sme pripravení. To zaberá kúsok kódu, ale má to výhodu v schopnosti veľkej rýchlosti zmien scien s viacnásobnými škriatkami na ňom. Ak chcete použiť toto riešenie, asi Vás bude zaujímať A.J. Venterov gamepack, skupina komponentov pre vývoj hier v Lazarus, ktoré poskytujú dvojito buferovanú zobrazovaciu oblasť komponentu ako aj vnorené komponenty, navrhnuté pre dobré integrovanie s inými. gamepack môžete získať pomocou SVN:
348+
349+`svn co `[`svn://silentcoder.co.za/lazarus/gamepack`](svn://silentcoder.co.za/lazarus/gamepack)
350+
351+## Spolupracovníci a zmeny
352+
353+- Preložil --Komunista 22:01, 26 December 2007 (CET)
354+
355+---
356+*From the Free Pascal wiki, page "Developing with Graphics/sk", as it stood on 2020-02-13 after a change by Trev, 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).*

Back to history