| Posledná zmena: 8.10.2002

dvojrozmerné polia, obrázky

## Dvojrozmerné polia

výpis dvojrozmerného čísleného poľa
procedúra vypis, ktorá do textovej plochy vypíše obsah dvojrozmerného poľa celých čísel mxn; druhým parametrom procedúry je premená typu TStrings - aby sme ju mohli volať napr. pre Memo1.Lines - predpokladáme, že Memo - textová plocha má nastavený font "Courier New"

- zarovnaje prvky na šírku 4 znaky, napr.

1 17 106 6 8 100 11 13 2 14 2 106 108 11 104 10 101 106 5 10 14 7 105 8 107 8 103 110 15 107

    const
      m=5; n=6; sirka=4;

    type
      pole = array[1..m,1..n] of integer;

    procedure vypis(const p:pole; t:TStrings);
    var
      i,j:integer;
      s,s1:string;
    begin
      t.Clear;
      for i:=1 to m do begin
        s:='';
        for j:=1 to n do begin
          s1:='       '+IntToStr(p[i,j]);
          s:=s+copy(s1,length(s1)-sirka+1,maxint);
        end;
        t.Add(s);
      end;
    end;

očíslovanie prvkov poľa
zaplňte dvojrozmerné pole mxn postupne po riadkoch číslami 1..m*n

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

    var
      p:pole;
      i,j,k:integer;
    begin
      k:=1;
      for i:=1 to m do
        for j:=1 to n do begin
          p[i,j]:=k; inc(k);
        end;
      vypis(p,Memo1.Lines);
    end;

náhodné hodnoty
zaplňte dvojrozmerné pole mxn náhodne číslami 1..m*n tak, aby v ňom každé číslo bolo práve raz |
    var
      p:pole;
      i,j,k,pocet:integer;
      h:array[1..m*n] of integer;
    begin
      for i:=1 to m*n do h[i]:=i;
      pocet:=m*n;
      for i:=1 to m do
        for j:=1 to n do begin
          k:=random(pocet)+1;
          p[i,j]:=h[k];
          h[k]:=h[pocet]; dec(pocet);
        end;
      vypis(p,Memo1.Lines);
    end;
zapĺňanie šikmo
zaplňte dvojrozmerné pole mxn postupne číslami 1..m*n - šikmo, napr.

1 2 4 7 11 16 3 5 8 12 17 21 6 9 13 18 22 25 10 14 19 23 26 28 15 20 24 27 29 30

    var
      p:pole;
      i,j,k:integer;
    begin
      k:=1;
      for i:=1 to m+n do
        for j:=1 to i do
          if (j<=m) and (i-j+1<=n) then begin
            p[j,i-j+1]:=k; inc(k);
          end;
      vypis(p,Memo1.Lines);
    end;

### Ďalšie úlohy

- zaplňte prvky obdĺžnikovej tabuľky M x N číslami 1..mxn v poradí v akom ležia na špirále vedúcej z ľavého horného rohu do stredu

## Obrázok ako dvojrozmerné pole farebných bodov - pixelov

- vo formulári máme dve grafické plochy Image1 a Image2 - sú rovnako veľké - štvorcové, napr. 250x250
- v Image1 už máme načítanú nejakú bitmapu, napr. pomocou Image1.Picture.LoadFromFile("tiger.bmp")

otočenie vpravo
do Image2 sa prekopíruje Image1 otočený o 90 stupňov vpravo (v smere otáčania hodinových ručičiek) |
    var
      g1,g2:TCanvas;
      x,y,w:integer;
    begin
      g1:=Image1.Canvas; g2:=Image2.Canvas;
      w:=Image1.Width;
      for y:=0 to w-1 do begin
        for x:=0 to w-1 do
          g2.Pixels[w-y-1,x]:=g1.Pixels[x,y];
        //g2.Pixels[y,w-x-1]:=g1.Pixels[x,y];//otoč vľavo
        Image2.Repaint;
      end;
    end;
otáčanie na mieste
otočte Image1 na mieste - bez pomocného Image a bez poľa - obrázok rozdelíme uhlopriečkami na štyri kvadranty - každý `bod z jedného kvadrantu - postupne otočíme o 90 stupňov, t.j. naraz otočíme 4 symetrické body` |
    var
      g:TCanvas;
      x,y,w:integer;
      c:TColor;
    begin
      g:=Image1.Canvas; w:=Image1.Width;
      for y:=0 to w div 2-1 do begin
        for x:=y to w-y-2 do begin
          c:=g.Pixels[x,y];
          g.Pixels[x,y]:=g.Pixels[w-y-1,x];
          g.Pixels[w-y-1,x]:=g.Pixels[w-x-1,w-y-1];
          g.Pixels[w-x-1,w-y-1]:=g.Pixels[y,w-x-1];
          g.Pixels[y,w-x-1]:=c;
        end;
        Image1.Repaint;
      end;
    end;
zvlnený obrázok
prekopírujte obrázok z Image1 do Image2 tak, že každý riadok je posunutý o upravenú funkciu sínus, napr. |
    var
      g1,g2:TCanvas;
      x,y,posun,w:integer;
    begin
      g1:=Image1.Canvas; g2:=Image2.Canvas;
      w:=Image1.Width;
      for y:=0 to w-1 do begin
        posun:=round(10*sin(y*pi/30));
        for x:=0 to w-1 do
          g2.Pixels[x+posun,y]:=g1.Pixels[x,y];
        Image2.Repaint;
      end;
    end;
obrázok do textového súboru
vytvorte textový súbor, ktorý bude v každom riadku obsahovať farby bodov riadka obrázku (TColor sú vlastne integer) |
    var
      g:TCanvas;
      x,y:integer;
      t:TextFile;
    begin
      g:=Image1.Canvas;
      AssignFile(t,'tiger.txt'); Rewrite(t);
      for y:=0 to Image1.Height-1 do begin
        for x:=0 to Image1.Width-1 do
          write(t,g.Pixels[x,y],' ');
        writeln(t);
      end;
      CloseFile(t);
    end;
obrázok z textového súboru
zobrazte obrázok uložený v textovom súbore |
    var
      g:TCanvas;
      x,y,f:integer;
      t:TextFile;
    begin
      AssignFile(t,'tiger.txt'); Reset(t);
      g:=Image2.Canvas; y:=0;
      while not seekeof(t) do begin
        x:=0;
        while not seekeoln(t) do begin
          read(t,f); g.Pixels[x,y]:=f; inc(x);
        end;
        readln(t); Image2.Repaint; inc(y);
      end;
      CloseFile(t);
    end;
rozštvrtenie obrázka
obrázok z Image1 zmenšíme na štvrtinu a štyrikrát prekopírujeme do Image2; každá takáto štvrtina bude obsahovať iné bodky z pôvodného obrázka, t.j. z pôvodného obrázka zoberieme štvorice bodov 2x2 a každú z týchto bodiek rozdelíme do inej štvrtiny, napr.

    var
      g1,g2:TCanvas;
      x,y,xx,yy,w,w2:integer;
    begin
      g1:=Image1.Canvas; g2:=Image2.Canvas;
      w:=Image1.Width; w2:=w div 2;
      for y:=0 to w-1 do begin
        for x:=0 to w-1 do begin
          xx:=x div 2+x mod 2*w2;
          yy:=y div 2+y mod 2*w2;
          g2.Pixels[xx,yy]:=g1.Pixels[x,y];
        end;
        Image2.Repaint;
      end;
    end;

úprava RGB
prekopírujte obrázok z Image1 do Image2 tak, že pritom sa z farby každej bodky najprv vyrobí trojica zložiek RGB a potom sa v každej zložke vynulujú spodné 4 bity (napr. r div 16*16) vizuálne porovnajte oba obrázky |
    var
      g1,g2:TCanvas;
      x,y,w:integer;
      r,g,b:byte;
      f:TColor;
    begin
      g1:=Image1.Canvas; g2:=Image2.Canvas;
      w:=Image1.Width;
      for y:=0 to w-1 do begin
        for x:=0 to w-1 do begin
          f:=g1.Pixels[x,y]; r:=GetRValue(f);
          g:=GetGValue(f); b:=GetBValue(f);
          r:=r div 16*16; g:=g div 16*16; b:=b div 16*16;
          g2.Pixels[x,y]:=RGB(r,g,b);
        end;
        Image2.Repaint;
      end;
    end;

### Ďalšie úlohy

- posledný príklad môžete využiť tak, že do obrázka zakódujete nejaký textový súbor: v každej zložke RGB najprv vynulujete 4 spodné bity a potom sem vložíte 4 bity z textového súboru - každý bajt súboru sa postupne rozdelí na dva polbajty (4 bajty): bajt div 16 a bajt mod 16
- podobne sa dá zakódovať do voľných polbajtov aj úplne iný obrázok: do každého RGB (do jeho spodných polbajtov) každého pixelu vložíme horné 4 bity obrázka - najlepšie rovnakého rozmeru (pokúste sa touto metódou odhaliť, aký obrázok je ukrytý v tiger2.bmp)
- aj ideu rozštvrtenia obrázka niekedy môžeme považovať za zakódovanie: naprogramujte opačnú metódu k rozštvrťovaniu - z každej štvrtiny sa postupne skladajú zodpovedajúce pixely; ak by sme ale nemali rozštvrtený jeden obrázok, ale napr. štyri rôzne, tak takéto skladanie štvrtín nám tieto štvrtinové obrázky pomieša (pozrite napr. súbor styri.bmp) - obyčajné rozštvrťovanie nám teraz vráti pôvodný stav

© 2002 AB, KVI
blaho@fmph.uniba.sk