JudicatorMX
Birželis 5, 2007

GDI grafika

(graphics device interface) – operacinės sistemos Windows pagrindas. lietuvių kalba reiškia „grafinio prietaiso sąsaja“. Tai sąsaja, kurią Windows sistema naudoja dvimačių objektų vaizdavimui. Žinoma, tikrai nesilygina su OpenGL ir DirectDraw (ypač greičiu), tačiau tai gali būti naudinga paprastose programose. Šiame straipsnyje aš aptarsiu kai kurias galimybes.

Kaip jau minėjau, vienas didžiausių minusų – greitis, tačiau ši sąsaja yra vis tobulinama (jau atsirado patobulinta versija – +). komandų pagalba yra visai nesunku pavaizduoti paprastus objektus. Čia vėlgi bus piešimas ir koordinatės (kurios buvo naudojamos straipsnyje „Laužom standartus“).

Su neatsiejamas yra DC (Device Context) terminas (apie jį šiek tiek buvo užsiminta straipsniuose apie OpenGL programavimą). DC – tai, ant ko piešiame. kalboje jis vadinamas TCanvas. Piešime TCanvas mums leidžia naudotis tam tikrais įrankiais, kaip pieštukas (pen), teptukas (brush), tekstas (text) ir regionas (region). Pradėkime nuo paprasčiausių linijų.

procedure TForm1.Button1Click(Sender: TObject);
begin
  Canvas.LineTo(50, 50);
end;

– mūsų formos DC (prietaiso kontekstas). Komanda LineTo piešia liniją nuo esamo taško iki kito, nurodyto koordinačių pagalba. Iš pradžių pradinio taško koordinatės yra (0, 0), o galutinio (mes nustatėme) (50, 50). Norint nubrėžti liniją šalia, reikia pastumti pieštuką į kitą vietą, t.y. nurodyti jam kitas pradines koordinates. Šiuo atveju pieštukas pajudėjo įstrižai ir ten pasiliko, taigi naujoji linija jau bus piešiama nuo naujųjų koordinačių. Jeigu kas nesuprato, štai pavyzdys:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Canvas.LineTo(50, 50);
  Canvas.LineTo(100, 60);
  Canvas.LineTo(150, 60);
  Canvas.LineTo(200, 50);
  Canvas.LineTo(250, 0);
end;

Čia viskas turėtų būti savaime suprantama. Galima pieštuką pajudinti iš vietos ir nieko nepiešiant. Tam egzistuoja funkcija MoveTo.

procedure TForm1.Button1Click(Sender: TObject);
const i = 50;
begin
  Canvas.LineTo(i, i);
  Canvas.LineTo(i*2, i+10);
  Canvas.LineTo(i*3, i+10);
  Canvas.LineTo(i*4, i);
  Canvas.LineTo(i*5, i-i);
 
  Canvas.MoveTo(i-i, i*2); // Piestuko poslinkis
 
  Canvas.LineTo(i, i);
  Canvas.LineTo(i*2, i-10);
  Canvas.LineTo(i*3, i-10);
  Canvas.LineTo(i*4, i);
  Canvas.LineTo(i*5, i+i);
end;

Štai gavome mielą nesamonę. Gal kas pamenat programą “Logo”? Viskas vyksta gan panašiai, tik vėžliuko nėra :)

Pridėkime šiek tiek spalvų (pavyzdys patriotams).

procedure TForm1.Button1Click(Sender: TObject);
var i, j: Integer;
begin
  j:= 0;
  Canvas.Pen.Color:= clYellow;
  for i:= 0 to 30
    do
      begin
        Canvas.LineTo(500, j);
        j:= j+1;
        Canvas.MoveTo(0, j);
      end;
 
  Canvas.Pen.Color:= clGreen;
  for i:= 0 to 30
    do
      begin
        Canvas.LineTo(500, j);
        j:= j+1;
        Canvas.MoveTo(0, j);
      end;
 
  Canvas.Pen.Color:= clRed;
  for i:= 0 to 30
    do
      begin
        Canvas.LineTo(500, j);
        j:= j+1;
        Canvas.MoveTo(0, j);
      end;
end;

Štai tiek. Nieko per daug sudėtingo. Kaip jau turėjote suprasti, spalvą galima pakeisti naudojant .Pen.Color.

Žinoma, galima piešti ne tik linijas.

procedure TForm1.Button1Click(Sender: TObject);
begin
  Canvas.Pen.Color:= clRed;
  Canvas.Brush.Color:= clYellow;
  Canvas.Ellipse(300, 150, 500, 300);
end;

Pirmoji procedūra jau žinoma. Antroji nustato teptuko spalvą. Jei jis liks nenustatytas, nupiešta figūra nebus nuspalvinta. Trečioji procedūra piešia elipsę. Naudojant OpenGL tokiai elipsei nupiešt reikėtų sinusų ir kosinusų :)

Galima piešti ir kitokias figūras, kaip Rectangle, RoundRect ir pan. Dar vienas svarbus dalykas – teksto vaizdavimas.

procedure TForm1.Button1Click(Sender: TObject);
begin
  Canvas.Brush.Color:= clAqua;
  Canvas.Brush.Style:= bsDiagCross;
  Canvas.Pen.Color:= clBlue;
  Canvas.RoundRect(10, 10, 210, 58, 45, 45);
 
  Canvas.Pen.Color:= clWhite;
  Canvas.Font.Color:= clRed;
  Canvas.Font.Size:= 14;
  Canvas.TextOut(45, 22, 'Kazkoks tekstas');
end;

Neturėtų būti sunku išsiaiškinti, ką daro kiekviena eilutė, nes komandų pavadinimai jau žinomi. TextOut išveda tekstą, o Brush.Style nurodo spalvinimo stilių. Pasinaudoję šiomis žiniomis jau galime parašyti parodiją Paint programai.

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  Randomize;
  Canvas.Pen.Width:= Random(10) + 1;
  Canvas.Pen.Color:= RGB(Random(256),
                         Random(256),
                         Random(256));
  Canvas.LineTo(X, Y);
end;

Paleidus programą tereikia skirtingose lango vietose spaudinėt pelės mygtuką. Šiek tiek paredagavus kodą galima išties parašyti neblogą programą, neatsiliekančią nuo Paint. Spalvą parinkti galima leisti vartotojui. Spalvų inversiją padaryti visai paprasta: tereikia iš RGB (255, 255, 255) atimti esamą spalvos reikšmę. Tarkim buvo spalva (0, 0, 255) (mėlyna), o atėmus gausis (255, 255, 0), t.y. geltona (taip iš tikrųjų ir yra).

Nors ši grafika yra labai paprasta, ją naudojant galima gauti labai realistiškus paveikslus, lyg būtų dirbama su Photoshop programa, bet tai jau reikalauja nemažų pastangų ir noro. Viską, ką pavaizdavot ant savo lango, galima taip pat išsaugoti į atskirą failą. Dar vienas pliusas – nesunku sukurti gradientų arba fraktalų generatorių, kadangi komandos labai paprastos. Tereikia matematinių žinių.

Beliko pridurti dar vieną svarbų dalyką. Visus piešimus reikia vykdyti formos OnPaint funkcijoje, kad keičiant lango dydį arba jį stumdant, piešinys neišsitrintų.

Panašūs straipsniai


“GDI grafika” komentarų: 2

  1. » Savaitgalio skaitiniai #28 Archyvas » Pixel.lt

    […] Sveiki, štai ir pirma praėjusi savaitė antraisiais Pixel.lt gyvavimo metais (tikimės jų bus dar daug). Ačiū Pawkai už jo įdomų straipsnį, kaip perkelti įrašus iš blogas.lt sistemos į Wordpress. Taip pat ačiū neseniai prisijungusiam prie Pixel.lt JudicatorMX už aktyvų straipsnių rašymą. Šią savaitę buvo publikuotas jo straipsnis “GDI grafika“. Šio savaitgalio skaitiniai: Six ways to write more comprehensible code How to build a Firefox extension Optimizing Apache and PHP 10 Things That Would Have Been Nice to Know When Starting My Facebook Application Dar kartą ačiū visiems prisidedantiems prie Pixel.lt veiklos, gero savaitgalio! Susiję straipsniai:Savaitgalio skaitiniai #25Savaitgalio skaitiniai #24Savaitgalio skaitiniai #22 […]

  2. OggyH

    GDI grafiką galima stipriai pagreitinti pasinaudojant scanline. Tik tada reikia truputį daugiau matematikos ir kodo. Bet piešimas vyktų žymiai greičiau.

Rašyti komentarą

Jūs privalote prisijungti jeigu norite rašyti komentarą.