Obrazek zamiast Enigmy

Zapewne słyszeli Państwo o możliwości ukrywania pewnych danych między pikselami map bitowych. Przyjrzyjmy się algorytmom tego interesującego zagadnienia.

Zapewne słyszeli Państwo o możliwości ukrywania pewnych danych między pikselami map bitowych. Przyjrzyjmy się algorytmom tego interesującego zagadnienia.

Czy w jednym obrazie można ukryć drugi tak, żeby nikt tego nie zauważył? A może nie obraz, a inne dane, np. przekazy tekstowe, tajne wiadomości, jakieś klucze i hasła?

Mamy wiele formatów map bitowych, ale najważniejszy jest ten, w którym każda z trzech składowych barwy zajmuje osiem bitów pamięci i w związku z tym może przyjmować jeden z 256 dostępnych stanów nasycenia. Format ten zazwyczaj jest nazywany TrueColor i szczególnie nadaje się do naszych potrzeb.

Mamy wiele formatów map bitowych, ale najważniejszy jest ten, w którym każda z trzech składowych barwy zajmuje osiem bitów pamięci i w związku z tym może przyjmować jeden z 256 dostępnych stanów nasycenia. Format ten zazwyczaj jest nazywany TrueColor i szczególnie nadaje się do naszych potrzeb.

Przyjrzyjmy się strukturze map bitowych i poszukajmy w nich takich schowków, w które można coś wpisać, nie psując samego obrazu. Oszacujemy również pojemność takich skrytek. Potem przygotujemy dwie aplikacje - jedna będzie umieszczać w nich nasze dane, a druga - wyciągać je stamtąd.

Prawdziwy Kolor

Mamy wiele formatów map bitowych, ale najważniejszy jest ten, w którym każda z trzech składowych barwy zajmuje osiem bitów pamięci i w związku z tym może przyjmować jeden z 256 dostępnych stanów nasycenia. Format ten zazwyczaj jest nazywany TrueColor i szczególnie nadaje się do naszych potrzeb.

Zajmiemy się jednym typem map bitowych, w których każdy piksel jest opisany czterema bajtami. Trzy z tych bajtów mają największe znaczenie, bo opisują amplitudy czerwieni, zieleni i błękitu piksela. Czwarty bajt jest niewykorzystany, ale nie nadaje się do naszych potrzeb z dwóch powodów: niektóre systemy jednak go wykorzystują, a w dodatku jest za słabo ukryty w strukturze obrazu. Umieszczenie w nim informacji nie byłoby dostatecznie finezyjnym szyfrowaniem danych.

Przypomnijmy proste spostrzeżenie z dziedziny arytmetyki binarnej. Otóż modyfikowanie ciągu zer i jedynek ma bardzo duży wpływ na wartość, gdy zmieniane bity znajdują się z prawej strony, i bardzo mały, gdy zmieniane są bity z lewego końca . Nawet wprowadzono nazwy: bity starsze (bardziej z prawej strony) i młodsze (te z lewej) albo bardziej i mniej znaczące.

Napiszemy program, który odczyta plik mapy bitowej, wyświetli obraz i umożliwi uszkodzenie określonej liczby bitów młodszych w kanałach R, G, B. Tak spreparowany obraz ponownie wyświetlimy i ocenimy jego jakość. Mamy nadzieję, że będzie można w ten sposób określać, ile bitów wolno wykradać amplitudom barw bez szkody dla jakości.

Klasyczny interfejs programu do obsługi map bitowych składa się z dwóch pól ScrollBox, które dostarczą suwaków przewijania dużych obrazów. Na tych polach znajdują się najważniejsze tutaj obrazy Image. U góry, w Panelu, który tylko rezerwuje miejsce na inne elementy interfejsu, znajdują się niezbędne przyciski oraz urządzenia do określania liczby uszkadzanych bitów młodszych. Programem takim zajmowaliśmy się już wielokrotnie i nie będę przypominać, jak się odczytuje i wyświetla mapę bitową z pliku dyskowego. Zainteresowanych Czytelników zapraszam do materiałów źródłowych, a my skoncentrujmy się na algorytmie uszkadzania:

int il_r = Edit1 -> Text.ToInt()

il_g = Edit2 -> Text.ToInt()

il_b = Edit3 -> Text.ToInt();

int i, j, n, szer, wys;

TColor k;

unsigned char r, g, b;

szer = Image2 -> Picture -> Bitmap -> Width;

wys = Image2 -> Picture -> Bitmap -> Height;

for( i = 0; i < szer; ++i) {

for( j = 0; j < wys; ++j) {

k = Image1 -> Picture ->

Bitmap -> Canvas -> Pixels[ i][ j];

r = GetRValue( k);

g = GetGValue( k);

b = GetBValue( k);

for( n = 0; n < il_r; ++n)

r = ustaw_bit( r, n, 0);

for( n = 0; n < il_g; ++n)

g = ustaw_bit( g, n, 0);

for( n = 0; n < il_b; ++n)

b = ustaw_bit( b, n, 0);

k = RGB( r, g, b);

Image2 -> Picture ->

Bitmap -> Canvas -> Pixels[ i][ j] = k;

}

}