Stahnete si z http://pasky.or.cz/vyuka/2012-DMI074/aim-kit.tar.bz2 "AIM kit" - framework pro manipulaci s bitmapovymi obrazky; v jeho ramci se budeme pohybovat po vetsinu semestru. Framework se sklada z "hlavniho programu" aim-run.c, do ktereho typicky nebudete zasahovat, spolecneho hlavickoveho souboru aim.h s popisem datove struktury obrazku a souboru exercise.c, v jehoz ramci budete implementovat funkci exercise(), ktera vezme vstupni obrazek a po provedeni vhodne transformace svuj vystup ulozi do vystupniho obrazku. V README naleznete zakladni dokumentaci a navod k pouziti. Po jeho prostudovani zkuste kit zkompilovat a vysledny program spustit na nejmensim obrazku test64.pbm - vystup srovnejte s predimplementovanou funkci exercise.c. Pak si prohlednete vsechny soubory v ramci aimkitu a zkuste jim porozumet. (i) Cim se lisi aim-opt a aim-dbg? (ii) Co vraci funkce get_timer() a co vypise program na vystupu za cislo? (iii) Zkuste se zamyslet nad smyslem teto pozoruhodne konstrukce: while (get_timer() - t0 < 500000); (iv) Funkce image_init() pouziva tento zpusob inicializace: img->bitmap = malloc(img->rows * image_rowbytes(img)); Napadaji vas nejake zajimave dusledky pouziti funkce malloc()? (Na zreteli je dobre mit alespon dva.) Soucasti popisu datove struktury v aim.h je i nekolik pomocnych funkci. Jejich smyslem je spise nastinit zpusob ulozeni dat a pomoci vam s prvnimi prototypy - nebojte se radeji manipulovat primo se samotnou bitmapou. Snadno tak dosahnete az 100x (!) zrychleni. Take az na jednu domaci ulohu pri praci s obrazkem muzete vzdy predpokladat, ze delka kazde hrany je nasobkem 64, abychom zbytecne netristili sily na osetrovani specialnich pripadu. (v) Jakym zpusobem jsou pixely obrazku ulozene v poli bitmap? (vi) Jste si jisti, jakym zpusobem jsou pixely orientovane v ramci jednoho bajtu? (vii) Co obecne vzato dela konstrukce ci idiom (img->cols + 7) / 8? (viii) Proc jsou funkce definovane v aim.h kvalifikovane jako static? (ix) Co znamena kvalifikator restrict v parametrech funkce exercise()? Pro benchmarkovani je vhodne si stahnout i _velky_ obrazek: http://pasky.or.cz/vyuka/2012-DMI074/test16384.pbm.bz2 Pozor, po rozbaleni bude mit mnoho megabajtu, napr. v labu jej nerozbalujte do ~, ktere ma jednak quotove omezeni a druhak bude prace pres sitovy disk pomala - pouzijte radeji adresar /tmp. Pro prohlizeni nejvetsich obrazku nepouzivejte prikaz display (alokuje mnoho gigabajtu pameti), ale radeji napr. eog nebo jiny inteligentnejsi nastroj. (x) Proc se funkce exercise() pousti nekolikrat? (xi) `make benchmark` vypisuje i tzv. "smerodatnou odchylku". Jak je tato velicina definovana a jak jeji konkretni hodnotu mame interpretovat? Zkuste si naimplementovat dve vlastni trivialni transformace; nejdrive treba primocare pomoci getpixel a putpixel, pak optimalneji pomoci bitovych operaci. Pozor, transformujte obrazek, nikoliv pouze vypisovani ASCII artu - to ze vzorove implementace rovnou vymazte. (xii) Inverze obrazku - bilou nahradte cernou a naopak. (xiii) "Vezeni" - pres obrazek nakreslete svisle cerne nebo bile pruhy (zkuste ruzne sirky pruhu). ---- Hinty a reseni (iv) Funkce malloc() jednak neinicializuje svoji pamet, pokud tedy nezapisete "na kazdy pixel" vystupniho obrazku, zbytek jeho obsahu bude nedefinovany. Zaroven funkce malloc() alokuje neprilis zarovnanou pamet; vyznamny dusledek zminime na prednasce o cachich. (viii) Pripomenme, ze kvalifikator static u funkce omezuje jeji viditelnost v ramci programu na danou kompilacni jednotku (objekt). V nasem AIM programu mame dva objekty, aim-run.o a exercise.o, a zdrojaky obou includuji aim.h a tedy i definice funkci. Je tedy nutne omezit viditelnost, aby se vicenasobne kopie funkci vzajemne nepraly. To je dobrym zvykem delat vzdy, kdyz v hlavickovem souboru uvadime i definice inline funkce. (xi) Zkuste si precist neco o normalnim rozdeleni a tzv. "kvantilech". Velmi strucne a bez spousty technikalii (mozna nejdulezitejsi vzkaz celeho zakladniho kurzu Pravdepodobnost a statistika): Pri dostatecnem poctu vzorku bude 95% jejich hodnot v rozsahu +- 2*SD kolem prumerne hodnoty. (xii) Pro seznameni je fajn nejdrive zkusit naimplementovat cyklus s getpixel a putpixel, prepsani na primy pristup do pole bitmap ale muze znamenat az 100x zrychleni. Dalsi snadne rozsireni je misto iteraci po bytech rovnou po celych intech: #include #include "aim.h" void exercise(struct image * restrict in, struct image * restrict out) { /* Do your image transformation here. Delete the code below * first, especially when testing with large images! Modify * the image, not just the printing code. */ int rowl = image_rowbytes(in)/sizeof(unsigned int); for (int y = 0; y < in->rows; y++) { for (int x = 0; x < rowl; x++) { ((unsigned int*)out->bitmap)[x + y * rowl] = ~((unsigned int*)in->bitmap)[x + y * rowl]; } } } Musime davat pozor, ze [] ted take adresuje nikoliv bytovy offset, ale po intech.