Użycie grafik w formacie BMP w aplikacjach STM32

W każdym systemie związanym z rejestracją i przetwarzaniem obrazu należy znaleźć sposób na przechowywanie i udostępnianie danych. Zazwyczaj w systemach z mikrokontrolerem zasoby pamięci są ograniczone co dodatkowo komplikuje sprawę. Jeżeli dane zarejestrowanego obrazka mają być przeznaczone do wyświetlenia na zewnętrznym komputerze dobrym rozwiązaniem może być zapisanie ich na wymiennym nośniku np. karcie SD jako plik graficzny w którymś z powszechnie obsługiwanych formatów. Format .BMP jest obsługiwany przez chyba wszystkie programy graficzne. Ma prostą strukturę a jego popularność gwarantuje wsteczną kompatybilność czyli zdolność wyświetlenia plików zapisanych w starszej wersji formatu przez nowe wersje programów graficznych. Opisane w artykule procedury zostały opracowane specjalnie z myślą o wykorzystaniu w układach z mikrokontrolerem i przetestowane dla rodziny STM32. Procedury operują na danych surowych obrazu zapisanych w jednym buforze, które po konwersji już jako plik .BMP zapisywane są w drugim buforze. Przyjęto, że dane surowe obrazu dla każdego piksela zapisane są w formacie RGB565 tak jak pokazuje to rysunek 1.

Rys. 1. Format ramki opisu koloru piksela RGB565

Dane pikseli zapisane są w buforze kolejno tworząc poziome linie obrazu a liczba pikseli w każdej linii określa jego szerokość. Jako pierwsze w buforze zapisane są dane piksela wyświetlanego z lewej strony na pierwszej od góry linii obrazu. Jako kolejne zapisane są dane piksela następnego z prawej i tak dalej. Wszystkie linie obrazu których dane zapisane są w buforze po kolei począwszy od pierwszej linii wyświetlanej na górze do ostatniej wyświetlanej na dole tworzą obrazek. Ilość linii określa jego wysokość. Dane pikseli ułożonych w kolejne linie tworzą całość, którą w skrócie można nazwać ramką obrazu. Surowe dane obrazu w takim stanie otrzymuje się np. z modułów kamer cyfrowych. Żeby mogły być wyświetlone przez program graficzny muszą zostać przekształcone do obsługiwanego formatu pliku graficznego takiego chociażby jak BMP.

Opisywane procedury umożliwiają otrzymanie pliku w najprostszej postaci. Jest to format obrazu bez kompresji danych, palety kolorów, animacji ale prawidłowo wyświetlany przez wszystkie testowane do tej pory programy graficzne. Procedury tworzą plik .BMP składający się z:

  • nagłówka,
  • danych obrazu (tabeli pikseli).

W nagłówku zostaną zapisane informacje niezbędne do właściwego wyświetlenia tabeli pikseli jako obrazu na ekranie komputera. Każdy bajt nagłówka ma jednoznacznie zdefiniowaną pozycję i znaczenie. W tabeli 1 pokazano strukturę bajtów nagłówka.

 

Tab. 1. Funkcje bajtów nagłówka pliku BMP

Offset względem początku pliku Rozmiar w bajtach Nazwa Opis
0 2 bfType Sygnatura pliku, wynosi 0x42 0x4D w systemie szesnastkowym, odpowiada to znakom BM w kodzie ASCII
2 4 bfSize Rozmiar całego pliku w bajtach
4 2 bfReserved1 Zarezerwowany
8 2 bfReserved2 Zarezerwowany
10 4 bfOffBits Ofset, tzn. początkowy adres bitów w tablicy pikseli
14 4 biSize Wielkość nagłówka informacyjnego. Długość stąd do końca nagłówka – 40, czasem mniej
18 4 biWidth Szerokość obrazu w pikselach
22 4 biHeight Wysokość obrazu w pikselach (lub liniach)
26 2 biPlanes Liczba warstw kolorów, zwykle 1
28 2 biBitCount Liczba bitów na piksel (dla obrazu w formacie BMP)
30 4 biCompression Algorytm kompresji
34 4 biSizeImage Rozmiar samego rysunku
38 4 biXpelsPerMeter Rozdzielczość pozioma
42 4 biYpelsPerMeter Rozdzielczość pionowa
46 4 biClrUsed Liczba kolorów w palecie
50 1 biClrImportant Liczba ważnych kolorów w palecie (gdy 0 to wszystkie są ważne), pole to stosuje się przy animacji bitmap poprzez rotację kolorów
51 1 biClrRotation Flaga sygnalizująca czy ma następować rotacja palety (domyślnie 0-brak rotacji)
52 2 biReserved Zarezerwowany

 

Po nagłówku zapisane zostają dane pikseli obrazu. Prezentowane procedury zapisują kolor każdego piksela (a jednocześnie jego jasność) przy pomocy 3 bajtów. Każdy z bajtów określa intensywność jednej z podstawowych składowych koloru: BGR. Pierwszy bajt określa intensywność składowej niebieskiej (B), drugi składowej zielonej (G) a trzeci składowej czerwonej (R).

Wartości kolorów zapisywane są po kolei dla następnych pikseli od lewej do prawej. Dane pikseli tworzą linię obrazu. Należy pamiętać aby ilość bajtów linii była liczbą podzielną przez 4. Jeżeli tak nie jest należy dane obrazu linii uzupełnić bajtami o wartości 0 do ilości równej najbliższej liczbie podzielnej przez 4. (Np. dla obrazu o szerokości 159 pikseli na końcu danych każdej linii po konwersji należy dopisać 3 bajty o wartości 0 za którymi znajdą się bajty pikseli kolejnej linii).

W odróżnieniu od surowych danych obrazu, w formacie .BMP dane linii zapisywane są od dołu do góry. I tak jako pierwsze w tabeli pikseli znajdą się dane piksela z lewego dolnego rogu obrazu a jako ostatnie piksela z prawego górnego rogu obrazu.

Procedura konwersji składa się z 3 funkcji. Wykorzystana jest także struktura zawierająca zmienne przechowujące parametry niezbędne podczas konwersji. Strukturę należy zadeklarować na początku np. tak:

Główna procedura konwersji wygląda następująco:

Parametrami wywołania procedury są dane informujące o wymiarach obrazka oraz wskaźniki do buforów wejściowego z danymi surowymi i wyjściowego dla pliku .BMP. Na początku procedura uzupełnia pola struktury. Następnie wywoływana jest procedura tworząca nagłówek pliku .BMP. Po jego utworzeniu wywoływana jest procedura konwertująca dane surowe kolejnych pikseli na tabelę pikseli pliku .BMP. Konwersja wykonywana jest w dwóch pętlach ‘i’ i ‘j’. Dane każdej linii do konwersji pobierane są od ostatniej do pierwszej. Po przekształceniu z RGB565 na BGR888 dane pikseli zapisywane są do bufora wyjściowego. Jeśli bufor wyjściowy okaże się za mały na konwertowany plik .BMP, główna procedura zwróci 0, każda inna wartość będzie oznaczać sukces konwersji.

Ryszard Szymaniak

www.arskam.com

Przy pisaniu tego tekstu wykorzystano materiały z polskiej i angielskiej wersji Wikipedii.

Do pobrania

Autor: admin

Admin