MFF UK / Ústav teoretické fyziky / Tomáš Ledvinka
Přednášky
. . . . . . . . . . . . . . . . . . . . . . . . . .
Programování pro fyziky (1.r)
  Úvod
  Programy a algoritmy
  Píšeme program
  Píšeme program II
  Procedury a funkce
  Malujeme funkce
  Chyby. Typy I.
  Typy II. Pole a Záznamy
  Pole II.Řetězce.Soubory.
  Gnuplot.Interpolace...
  Matice. Velké O...
  Fronta,Zásobník. Postscript
  Bin. soubory, ...
    Neúplné vyh. log. výrazů
    Parametr typu funkce
    Otypované soubory
    Binární soubory
    Dyn. datové struktury
  Ukazatele,Objekty, ...
Počítačová algebra
Klasická elektrodynamika (2.r)
Vybrané partie OTR

Cvičení
. . . . . . . . . . . . . . . . . . . . . . . . . .
Programování pro fyziky (1.r)
Teoretická mechanika (2.r)
Klasická elektrodynamika (2.r)


Věda
. . . . . . . . . . . . . . . . . . . . . . . . . .
Diskové zdroje v OTR
Hyperbolické systémy v OTR


Kontakt
. . . . . . . . . . . . . . . . . . . . . . . . . .
Email
Konzultační hodiny


Ostatní
. . . . . . . . . . . . . . . . . . . . . . . . .
Mallorca
Ze společnosti

Binární soubory

Metoda Udělěj si sám, není optimální strategií pro tvorbu složitějšího programu. Víme, že nalezení dobrého algoritmu dá práci, a víme, že se vyplatí použít hotový modul, pokud implemetuje dobrý algoritmus a je v něm méně chyb, než v novorozeném programu. Podobně jsme zjistili, že spíše, než bychom se snažli poroučet inkoustovým kapičkám, chceme-li v nejvyšší kvalitě malovat na papír hezké obrázky, použijeme dobře definovaný jazyk pro popis obrázků (Postscript). To bylo obzvlášť jednoduché, protože postscriptový soubor byl běžný textový soubor.

Často se ale stává, že dohodnutý formát pro uložení toho, či onoho druhu dat má podobu řady bytů, a nikoli textu. Takovému souboru říkáme binární.

Jako příklad nám poslouží nekomprimovaný obrázek. Ten má povahu matice hodnot, které popisují barvu toho kterého bodu matice. Bohužel nestačí do souboru např. zapsat jen 1200 hodnot barvy, protože je ješte potřeba dodat, zda je to obrázek 30x40 nebo 40x30 nebo 20x60 atp. Proto vlastním datům předchází hlavička, kde je uvedeno vše, co je potřeba vědět pro správné zobrazení obrázku.

Podrobnosti o struktuře hlavičky, způsobu ukládání barev atp. lze samozřejmě nalézt, my ale použijeme trik, který nám umožní soustředit se na demonstraci práce s binárním souborem a nikoli na detaily vnitřností jednoho primitivního grafického formátu.

Trik bude spočívat v tom, že nejdříve pomocí programu pro práci s obrázky vytvoříme prázdný obrázek požadovaného formátu a velikosti. Program pak bude do nového souboru zapíše kopii hlavičky původního obrázku a za ní zapíše svá vlastní data (puntíky obrázku).

program Fraktal;
uses Windows;

const N = 600;
      BmpNxX = 'Blank600x600.bmp';

type tPixel = packed record b,g,r:byte; end;
     tBmpArr= packed array [1..N,1..N] of tPixel;

procedure WrBmp(const X : tBmpArr; const Name: string);
{Procedura vezme bitmapovy soubor velikosti NxN
 a vytvori jeho kopii ale s obrazkem X, (toto je ukazka techniky quick & dirty)}
const NN = 3*N*N+10000;
var A:array of byte; {bohuzel tak velke lokalni pole musi byt dynamicke}
    F : file;
    Nacteno,VelHlavicky : integer;

begin
   SetLength(A,NN);

   {1. cteni z binarniho souboru}
   Assign(F,BmpNxX);
   Reset(F,1);
   nacteno := 0;
   BlockRead(F,A[0],NN,nacteno);{musi byt A[0] pro dyn. pole !!}
   Close(F);

   {2. nevim jak presne ma byt velka hlavicka souboru}
   VelHlavicky := nacteno-3*N*N;
   assert( (VelHlavicky>30) and (VelHlavicky<1000) );

   {3. Zapis do souboru}
   Assign(F,Name);
   Rewrite(F,1);
   BlockWrite(F,A[0],VelHlavicky); {Puvodni hlavicka}
   BlockWrite(F,X,3*N*N); {Novy obrazek}
   Close(F);
end;

type tPixArr = packed array[0..2] of byte;

{$I firestorm.inc}

function Barva(a,b : real):tPixel;
var x,y,x1,x2,y2    : real;
            Index,s    : integer;
const   N = 1;
        M = 1;
{Konstanty M a N určují způsob, jímž se počet iterací z rozsahu 0..256*N 
 převede do rozsahu indexu barev 0..255.
 N=M odpovídá lineárnímu vztahu, 
 M=1 naopak zachová rozlišení za cenu recyklace barev.}
begin
     s:=256*N;
     x := 0;
     y := 0;
     repeat
       s:=s-1;
       x1 := x; {schovam si to}
       x2 := x*x;
       y2 := y*y;
       x  := x2 - y2   + a;
       y  := 2*x1*y    + b;
     until (x2+y2>4) or (s=0) ;

     Index:=(s div M) mod 256;

     Barva.R := ColorMap[Index,0];
     Barva.G := ColorMap[Index,1];
     Barva.B := ColorMap[Index,2];
end;


var i,j:integer;
    X : tBmpArr;

const sx = 0.053;
      sy = 0.621;   {poloha stredu obrazku}
      dxy = 0.05;   {velikost obrazku}
begin
  {Pro x=-dxy..dxy a y = -dxy..dxy opakuj spocibarvu....}
  for i:=1 to N do
    for j := 1 to N do
      X[j,i] := Barva( (2*i-N)/N*dxy+sx , (2*j-N)/N*dxy+sy );

  WrBmp(X,'obr.bmp');
  {pozor pod win95 a win98 je potreba pouzit misto cmd.exe prikaz command.com}
  WinExec('cmd.exe /C start obr.bmp',1);
end.

Pomocí vkládací direktivy {$I ...} je do programu vložen následující soubor s defnicí převodní tabulky
(počet iterací) --> (barva).

{Colormap by Mark Peterson}
const ColorMap : array [0..255] of tPixArr = ( 
( 0 , 0 , 0 ),( 144 , 10 , 229),(147,9,227),(150,8,225),(153,6,223),(156,6,221),(159,5,218),(162,4,216),(165,3,214),
(168,2,212),(171,2,209),(174,1,207),(177,1,204),(180,1,202),(183,0,199),(186,0,197),(189,0,194),(191,0,191),(194,0,189),(197,0,186),(199,0,183),(202,1,180),
(204,1,177),(207,1,174),(209,2,171),(212,2,168),(214,3,165),(216,4,162),(218,5,159),(221,6,156),(223,6,153),(225,8,150),(227,9,147),(229,10,144),(231,11,141),
(232,12,138),(234,14,135),(236,15,131),(238,17,128),(239,18,125),(241,20,122),(242,22,119),(243,23,116),(245,25,113),(246,27,109),(247,29,106),(248,31,103),
(249,33,100),(250,35,97),(251,38,94),(252,40,91),(252,42,88),(253,45,85),(253,47,82),(254,49,79),(254,52,76),(255,54,73),(255,57,71),(255,60,68),(255,62,65),
(255,65,62),(255,68,60),(255,71,57),(255,73,54),(254,76,52),(254,79,49),(253,82,47),(253,85,45),(252,88,42),(252,91,40),(251,94,38),(250,97,35),(249,100,33),
(248,103,31),(247,106,29),(246,109,27),(245,113,25),(243,116,23),(242,119,22),(241,122,20),(239,125,18),(238,128,17),(236,131,15),(234,135,14),(232,138,12),
(231,141,11),(229,144,10),(227,147,9),(225,150,8),(223,153,6),(221,156,6),(218,159,5),(216,162,4),(214,165,3),(212,168,2),(209,171,2),(207,174,1),(204,177,1),
(202,180,1),(199,183,0),(197,186,0),(194,189,0),(191,191,0),(189,194,0),(186,197,0),(183,199,0),(180,202,1),(177,204,1),(174,207,1),(171,209,2),(168,212,2),
(165,214,3),(162,216,4),(159,218,5),(156,221,6),(153,223,6),(150,225,8),(147,227,9),(144,229,10),(141,231,11),(138,232,12),(135,234,14),(131,236,15),
(128,238,17),(125,239,18),(122,241,20),(119,242,22),(116,243,23),(113,245,25),(109,246,27),(106,247,29),(103,248,31),(100,249,33),(97,250,35),(94,251,38),
(91,252,40),(88,252,42),(85,253,45),(82,253,47),(79,254,49),(76,254,52),(73,255,54),(71,255,57),(68,255,60),(65,255,62),(62,255,65),(60,255,68),(57,255,71),
(54,255,73),(52,254,76),(49,254,79),(47,253,82),(45,253,85),(42,252,88),(40,252,91),(38,251,94),(35,250,97),(33,249,100),(31,248,103),(29,247,106),(27,246,109),
(25,245,113),(23,243,116),(22,242,119),(20,241,122),(18,239,125),(17,238,128),(15,236,131),(14,234,135),(12,232,138),(11,231,141),(10,229,144),(9,227,147),
(8,225,150),(6,223,153),(6,221,156),(5,218,159),(4,216,162),(3,214,165),(2,212,168),(2,209,171),(1,207,174),(1,204,177),(1,202,180),(0,199,183),(0,197,186),
(0,194,189),(0,191,191),(0,189,194),(0,186,197),(0,183,199),(1,180,202),(1,177,204),(1,174,207),(2,171,209),(2,168,212),(3,165,214),(4,162,216),(5,159,218),
(6,156,221),(6,153,223),(8,150,225),(9,147,227),(10,144,229),(11,141,231),(12,138,232),(14,135,234),(15,131,236),(17,128,238),(18,125,239),(20,122,241),
(22,119,242),(23,116,243),(25,113,245),(27,109,246),(29,106,247),(31,103,248),(33,100,249),(35,97,250),(38,94,251),(40,91,252),(42,88,252),(45,85,253),
(47,82,253),(49,79,254),(52,76,254),(54,73,255),(57,71,255),(60,68,255),(62,65,255),(65,62,255),(68,60,255),(71,57,255),(73,54,255),(76,52,254),
(79,49,254),(82,47,253),(85,45,253),(88,42,252),(91,40,252),(94,38,251),(97,35,250),(100,33,249),(103,31,248),(106,29,247),(109,27,246),(113,25,245),
(116,23,243),(119,22,242),(122,20,241),(125,18,239),(128,17,238),(131,15,236),(135,14,234),(138,12,232),(141,11,230) 
);

 

Z hlediska přednášky je těžiště programu v proceduře WrBmp, která používá procedury pro čtení z a zápis do binárních souborů. Jak je vidět, operace s binárními soubory se v několika ohledech odlišují od textových i otypovaných souborů.

1. U operací Reset a Rewrite musíme dodat jak velká je základní nedělitelná jednotka dat. Pokud tento údaj zapomeneme uvést, volí ObjectPascal automaticky prehistorickou jednotku o velikosti 128 byte, místo aby si stěžoval !

2. Operace pro čtení se teď jmenuje BlockRead
BlockRead( var BinarniSoubor : file; var PromennaDoNizChcemeNacistData; KolikJednotek : integer; var KolikSePovedloNacist : integer)

3. Operace pro psaní se teď jmenuje BlockWrite
BlockWrite( var BinarniSoubor : file; var PromennaZNizChcemeZapsatData; KolikJednotek : integer; var KolikSePovedloZapsat : integer)

Cvičení: Změňte v minulém programu rozlišení z 600x600 na víc/míň podle schopností vašeho počítače. Nezaponeňte program také spustit a vyzkoušet, že funguje. Až budete vytvářet novou prázdnou bitmapu, zvolte způsob uložení barev jako barevný, 24-bit (tzv. TrueColor).

Cvičení: Nakreslete rovnostranný trojúhelník barev pro které platí r+g+b=1 (využívá vlastností rovnostranného trojúhelníka, že součet všech třech výšek je konstantní, pro ty, co nemají rádi analytickou geometrii r := y;g := (sqrt(3)*x-y)/2;b := (2-sqrt(3)*x-y)/2, ale ješte je třeba zkontroovat, že jsou všechny kladné.)

 

.