Zadanie 2 (v1.0.1) ============ Wstęp -------- Należy napisać prosty program graficzny przetwarzający obrazy. Program wczytuje plik graficzny (lub pliki), przetwarza je i zapisuje serię obrazów wynikowych. Program ma być napisany w C i łączony z asemblerem poprzez dolinkowanie pliku .o oraz wstawki asemblerowe. W C ma być napisany główny program (funkcja main), procedury wczytywania i wypisywania. Algorytmy przetwarzające obrazy mają być w asemblerze zgodnie z poniższymi wytycznymi. Parametry programu -------------------------- Wywołanie programu: imgasm -t nazwa_filtru opcje_filtru -o plik_wyjsciowy plik_wejsciowy1 Gdzie: - nazwa_filtru - określa rodzaj przetwarzania (patrz niżej) - opcje_filtru - opcje filtru (o ile filtr je ma) - plik_wyjsciowy - nazwa bazowa pliku wyjściowego - plik_wejsciowy1 - nazwa pliku wejściowego (obowiązkowa) - plik_wejsciowy2 - nazwa drugiego pliku wejściowego (o ile filtr działa na 2 plikach) Filtry ------ Należy zaimplementować następujące filtry w programie. = Rozmycie w pionie (nazwa "vblur") = Każdy piksel zostaje uśredniony z pikselem znajdującym się pod nim (dla każdej składowej koloru oddzielnie) w taki sposób, że piksel w wierszu i otrzymuje wartość uśrednioną ze swojej pierwotnej wartości oraz pierwotnej wartości piksela w wierszu i+1. Filtr na wejściu bierze jeden obrazek i na wyjściu generuje jeden obrazek wyjściowy o nazwie podanej w parametrze "-o". Parametry filtru: -r liczba_powtorzen - powtarza wykonanie filtru tyle razy, tzn. aplikuje filtr do całego obrazu i powtarza całą operację liczba_powtorzen razy Sposób implementacji: - algorytm ma być zaimplementowany jako wstawka asemblerowa inline w formacie stosowanym w gcc - musi używać zestawu instrukcji MMX = Rozmycie w poziomie (nazwa "hblur") = Tak samo jak vblur, ale rozmycie jest w poziomie, czyli bierzemy i-tą kolumnę zamiast i-tego wiersza = Przenikanie (nazwa "blend") = Filtr bierze na wejściu 2 obrazki oraz liczbę kroków (k) i tworzy efekt przeniknięcia jednego obrazu w drugi, czyli generuje ciąg k+2 obrazków (obrazek 0 to pierwszy obrazek wejściowym czyli początkowy, k+1 to drugi obrazek wejściowy, czyli końcowy) w których każdy piksel jest liniowo rosnącą wartością pośrednią między pikselem obrazka początkowego i końcowego (w sensie, że jego każda składowa koloru jest oddzielnie traktowana). Filtr na wyjściu generuje jeden ciąg obrazków o nazwie podanej w parametrze "-o" z sufiksem ".k", gdzie k to numer kroku od 0 do k+1. Parametry filtru: -k liczba_kroków - liczba kroków,czyli "k" w powyższym opisie Sposób implementacji: - algorytm ma być zaimplementowany jako funkcja zgodna z konwencją języka C w oddzielnym pliku asemblerowym NASM, dołączana do głównego programu w C w czasie linkowania - musi używać instrukcji SSE (rejestry XMM) = Maska (nazwa "mask") = Wczytuje 2 obrazki i dzieli je na obszary 8x8 pikseli. Dla każdego takiego obszaru wylicza sumę odległości między pikselami w obszarze liczoną jako suma wartości absolutnych różnicy między odpowiadającymi sobie składowymi koloru w obu obrazkach. Następnie wylicza średnią wartość odległości poprzez podzielenie tej sumy przez liczbę składowych kolorów w obszarze (czyli 8 pikseli * 8 pikseli * 3 składowe). Kolejnym etapem jest przejście po wszystkich pikselach obszaru i wygenerowanie 2 obrazków wynikowych - jeśli średnia różnicy dla danego piksela w pierwszym i drugim obrazku wejściowym (liczona tak jak wyżej) jest mniejsza lub równa średniej, to piksel (z pierwszego obrazka wejściowego) trafia do pierwszego obrazka, w przeciwnym wypadku do drugiego obrazka. Nieobecne piksele są zerowane (0, 0, 0 czyli kolor czarny). Intuicyjnie: do pierwszego obrazka wynikowego trafiają piksele z pierwszego wejścia, które są podobne do drugiego wejścia (w danym obszarze), a do drugiego te, które są mniej podobne, czyli tworzymy maskę i według niej rozdzielamy obrazek na dwa pod względem podobnieństwa do drugiego. W szczególności dla dwóch takich samych obrazków powinniśmy otrzymać pierwszy obrazek wyjściowy zawierający cały pierwszy obrazek wejściowy, a drugi zupełnie czarny (bo obrazek jest podobny sam do siebie). Filtr na wyjściu generuje 2 obrazki o nazwie podanej w parametrze "-o" z sufiksem ".0" dla pierwszego obrazka wyjściowego i ".1" dla drugiego. Parametry filtru: brak Sposób implementacji: - wstawka inline w gcc lub oddzielny plik .asm (do wyboru) - może używać instrukcji MMX lub SSE (do wyboru) Format plików wejściowych ----------------------------------- Plik wejściowe są zapisane w formacie PPM, ale mogą być zapisane w formacie binarnym (zwanym "raw") lub tekstowym ("plain)- patrz http://netpbm.sourceforge.net/doc/ppm.html) W obu przypadkach kolory są 8-bitowe i jest tylko jeden obrazek w pliku. Program powinien automatycznie wykrywać, jaki format ma plik i odpowiednio wczytywać. Do wczytywania nie można używać zewnętrznych bibliotek. Format plików wyjściowych ----------------------------------- Plik wyjściowe są zapisane w formacie PPM w formacie binarnym, 8-bitowym. Uwagi: - Do konwersji obrazków w innym formacie na PPM można użyć programu "convert" (do celów testowych, nie w programie). W razie wątpliwości co do treści zadania proszę o kontakt. Uzupełnienia treści ------------------- - W przypadku filtrów, które działają na dwóch obrazkach, rozmiar obu obrazków jest taki sam. - W filtrze "blend" można założyć, że k+1 jest potęgą dwójki. - W filtrze "mask" operację dzielenia (przy wyliczaniu średniej dla danego obszaru) można zrobić na zwykłych rejestrach, ponieważ jest to operacja stosunkowo rzadka. Autor: Krzysztof Lichota