Jedną z najprostszych metod ukrycia wiadomości jest zaszycie jej w pliku graficznym. Polega ona na manipulowaniu najmniej znaczącymi bitami poszczególnych pikseli, tak by z jednej strony zawierały pożądaną wiadomość, a z drugiej strony by powodowało to niezauważalną dla postronnego obserwtora zmianę samego obrazka.
Proszę napisać program umożliwiający ukrycie inforamcji w pliku graficznym, a potem jej ponowne odczytanie. Program ma być wywoływany z dwoma lub trzema argumentami. Gdy są trzy argumenty, to wykonywane jest ukrywanie i argumenty oznaczają kolejno: nazwa wejściowego pliku graficznego, nazwa pliku z informacją do ukrycia, nazwa wyjściowego pliku graficznego. Gdy są dwa argumenty, to wykonywane jest odczytywanie ukrytej informacji i argumenty oznaczają: nazwa pliku graficznego z ukrytą informacją, nazwa odtwarzanego pliku informacyjnego. Ukrywanie informacji w pliku graficznym nie powinno zmieniać jego rozmiaru. Po wykonaniu operacji ukrycia i odtworzenia pliki ukrywany i odtworzony muszą być identyczne. Plik z informacją do ukrycia może być dowolnym plikiem, niekoniecznie tekstowym. Zakładamy, że plik ten jest wystarczająco mały, aby dał się rozproszyć w pliku graficznym bez istotnych zmian w jego wyglądzie, ale na tyle duży, aby zadanie nie było trywialne. Ponadto zakładamy, że oba pliki razem mieszczą się w pamięci operacyjnej. Sposób rozproszenia bitów ukrywanej informacji w pliku graficznym jest dowolny.
Program może być napisany w C i/lub asemblerze. Program powinien zaalokować pamięć mieszczącą w całości pliki wejściowe, wczytać zawartość plików wejściowych do pamięci, wykonać na pamięci ukrywanie lub odczytywanie danych, a na koniec zapisać plik wyjściowy. Wszystkie operacje na danych wejściowych i wyjściowych w pamięci powinny być zrealizowane za pomocą instrukcji SIMD (mmx, sse, sse2, ...). Należy też zadbać, aby instrukcje SIMD, odwołując się do pamięci, używały adresów wyrównanych, tzn. będących wielokrotnością 8 dla mmx a 16 dla sse. Używanie instrukcji skalarnych dopuszczalne jest jedynie w celu organizownia pętli, manipulowania argumentami programu, alokowania i zwalniania pamięci oraz do operacji plikowych. Proszę zauważyć, że nie wszystkie instrukcje SIMD asemblera mają swoje odpowiedniki w postaci funkcji wbudowanych.
Ocenie będzie podlegać głównie pomysłowość użycia instrukcji SIMD i będzie to ocena subiektywna.
Można użyć dowolnego formatu graficznego. Trzeba sobie wyszukać jego opis w Internecie. Jeśli komuś nie chce się szukać, to może użyć tego pliku. Jego format jest przedstawiony w poniższej tabli. Program powinien radzić sobie nie tylko z przykładowym plikiem ale też z dowolnym plikiem w tym samym formacie.
liczba bajtów | zawartość |
Nagłówek pliku | |
2 | litery BM |
4 | całkowita długość pliku w bajtach |
4 | zarezerwowane, zawsze 0 |
4 | odległość w bajtach od początku pliku do początku tablicy pikseli (mapy bitowej) |
Definicja formatu | |
4 | rozmiar definicji formatu w bajtach |
4 | szerokość obrazka w pikselach |
4 | wysokość obrazka w pikselach |
2 | liczba płaszczyzn, zawsze 1 |
2 | liczba bitów na piksel (tutaj 24 = True Color) |
4 | rodzaj kompresji, 0 = brak kompresji |
4 | całkowity rozmiar tablicy pikseli w bajtach |
4 | rozdzielczość pozioma w pikselach na metr |
4 | rozdzielczość pionowa w pikselach na metr |
4 | zawsze 0 |
4 | zawsze 0 |
Tablica kolorów (nieobecna, jeśli True Color) | |
Tablica pikseli
Tablica ta zawiera kolejne piksele obrazka, ułożone wierszami.
Wiersz zawiera piksele w kolejności od lewej do prawej i uzupełniony jest
pustymi bajtami, tak aby jego rozmiar był wielokrotnością 4 bajtów.
Wiersze ułożone są w kolejności od dołu do góry.
W formacie True Color pojedynczy piksel opisywany jest za pomocą trzech bajtów,
które określają odpowiednio intensywność składowych kolorów podstawowych RGB. |