Access

  MS Access 2010+  |  Bitmapa *.bmp  |   VBA 7.0



• Struktura pliku bitmapy w formacie BMP

Ikona bitmapyBitmapa, a raczej format pliku bitmapy został zdefiniowany wraz z wydaniem w listopadzie 1988 roku stworzonego przez firmy IBM i Microsoft wersji 1.1. systemu operacyjnego OS/2 (ang. Operating System/2). W wersji tej wprowadzono interfejs graficzny obsługiwany przez API (ang. Application Programming Interface), czyli interfejs programowania aplikacji, zapewniające kontrolę grafiki i obsługę myszy.
Bitmapa niezależna od urządzenia (Device Independent Bitmap) w skrócie DIB została wprowadzona w systemie Windows 3.0 jako uniwersalny format pliku. Praktycznie od tego czasu był, i jest, utożsamiany z systemem Windows i tak jak on, bezlitośnie krytykowany.

Popularne formaty plików graficznych

Najczęściej porównuje się plik bitmapy z plikami graficznymi stosującymi schematy kompresowania, takimi jak JPEG, czy GIF. I bezkrytycznie zarzuca się plikowi BMP zbyt dużą wielkość w porównaniu ze skompresowanym  plikiem JPEG lub plikiem GIF. A co w przypadku pliku GIF z ilością zapisanych kolorów w pliku. Czy mały plik formatu GIF zapisze wszystkie 16.7 mln kolorów ? Raczej nie, ponieważ format GIF obsługuje jedynie 256 kolorów na obraz. Odnosi się to do ilości kolorów mogących występować w jednym bloku obrazu, ale nie do całego obrazu. Możemy użyć większej ilości bloków i zastosować format GIF do przechowywania obrazów bez straty jakości (ilości kolorów). Ale, czy wtedy tak zapisany plik GIF jest taki mały i taki prosty w obsłudze, że bije na głowę format BMP ? Jakby format GIF był taki wspaniały, to nie zaistniałby format PNG opracowany w 1995 roku, jako następca formatu GIF, po ogłoszeniu przez Unisys oraz CompuServe roszczeń patentowych dotyczących kompresji LZW używanej w formatach GIF oraz TIFF. (1 października 2006 r. wygasły wszystkie ograniczenia patentowe dotyczące formatu GIF).

Format PNG nie korzysta z  kwestionowanych rozwiązań kompresji LZW. Obsługuje tryby o niskiej ilości kolorów (palety od 2 do 256 kolorów w tym tryb skali szarości), przydatne w sytuacjach, gdy nadmiarowa informacja jest niewskazana (tj. gdy ważniejsza od subiektywnej wierności oryginałowi jest treść obrazu). Obsługuje stopniowaną przezroczystość (tzw. kanał alfa) oraz 48-bitową głębię kolorów, czyli 16 bitów na kanał koloru. Dzięki temu można zapisać bezstratnie dowolny plik graficzny RGB (a nawet RGBA, czyli RGB + Alfa, do 64 bitów na piksel). Obsługuje też osadzone profile kolorów icc, icm i dane exif.

Format bitmapy można porównywać z popularnym formatem TIFF i wtedy dopiero dyskutować o wielkości pliku. Oczywiście format TIFF jest zdecydowanie lepszym formatem, pozwalającym na zapisywanie obrazów w skali szarości oraz w wielu trybach i głębiach bitowych koloru. Przechowuje ścieżki i kanały alfa, profile koloru, komentarze tekstowe. Format TIFF umożliwia stosowanie kompresji bezstratnej typu LZW oraz CCITT Group 4.

Dyskutować o wyższości jednego formatu nad drugim można długo, ale tak naprawdę ważny jest końcowy efekt. Pliki zawsze przechowujemy na jakimś nośniku, ale w zależności od wielkości nośnika, ilości plików oraz przeznaczenia pliku, musimy wybrać odpowiedni format pliku.

  1. JPEG - najczęściej stosowany format dla przechowywania dużych zbiorów plików graficznych Charakteryzuje się bardzo dobrą kompresją powodującą jedynie minimalną utratę jakości obrazu przy wybraniu niezbyt wysokiego współczynnika kompresji.
  2. TIFF - stosowany do plików graficznych, gdy zależy nam, by zachowane były dodatkowe dane, takie jak poszczególne kanały, profile koloru oraz przestrzeń barw (RGB, CMYK czy LAB). Dodatkowo format ten można skompresować bezstratnym algorytmem typu LZW lub CCITT Group 4.
  3. PNG - stosowany do plików graficznych, gdy przede wszystkim zależy nam na bezstratnej kompresji przechowywanych i by pliki nasze obsługiwane były przez przeglądarki internetowe, aplikacje biurowe i proste programy graficzne.
  4. BMP 24 bit - gdy zależy nam na bardzo szybkim wczytaniu i przetwarzaniu plików graficznych (zwłaszcza bardzo dużych plików). Przy wczytywaniu pliku nie jest wykonywana czasochłonna dekompresja. Zyskujemy na szybkości i komforcie, ponieważ nie musimy martwić się o dodatkowe biblioteki do obsługi skompresowanych plików graficznych.

Struktura 24 bitowej bitmapy w formacie BMP

Ze względów praktycznych i estetycznych tj. „wierności” odwzorowania kolorów oryginalnej bitmapy w porównaniu do „ubogich” w kolory palet kolorów oraz łatwość programowania tj. dostępu do każdego piksela bitmapy ograniczam się tylko do 24 bitowych bitmap z nagłówkiem BITMAPINFOHEADER wielkości 40 bajtów.

• Nagłówki pliku formatu BMP

    BITMAPFILEHEADER - struktura obejmująca parametry nagłówka pliku BMP

Public Type BITMAPFILEHEADER    '14-bajtowy nagłówek pliku
   bfType As Integer            'sygnatura BM (0x4D42) hex. &H424D
   bfSize As Long               'całkowity rozmiar pliku w bajtach
   bfReserved1 As Integer       'zarezerwowany - zazwyczaj równy ZERO
   bfReserved2 As Integer       'zarezerwowany - zazwyczaj równy ZERO
   bfOffBits As Long            'przesunięcie do bajtów obrazu bitmapy
End Type

    BITMAPINFOHEADER - struktura obejmująca parametry bitmapy

Public Type BITMAPINFOHEADER    '40 bajtowy nagłówek informacyjny bitmapy
   biSize As Long               'rozmiar struktury
   biWidth As Long              'szerokość mapy bitowej w pikselach
   biHeight As Long             'wysokość mapy bitowej w pikselach. Dla dodatniej wartość biHeight,
																'bitmapa jest typu „z dołu do góry” i jej punkt początkowy
																'znajduje się w lewym dolnym rogu. Dla ujemnych biHeight bitmapa
																'jest typu „z góry na dół” i jej początek znajduje się
																'w lewym górnym rogu.
   biPlanes As Integer          'liczba warstw koloru, zawsze = 1
   biBitCount As Integer        'liczba bitów koloru na jeden piksel (1,4,8,16,24,32)
   biCompression As Long        'typ kompresji:   BI_RGB = 0 (bez kompresji), BI_RLE8, BI_RLE4,
                                'BI_BITFIELDS, BI_JPEG, BI_PNG
   biSizeImage As Long          'wielkość mapy bitowej w bajtach, jeżeli bitmapa jest
																'nieskompresowana (element biCompression struktury równy
                                'jest BI_RGB) wartość biSizeImage może być ustawiona na ZERO
   biXPelsPerMeter As Long      'rozdzielczość pozioma pixel/metr - zazwyczj ZERO,
                                'wartość 2835 odpowiada rozdzielczości 72 dpi,
                                'wartość 11811 odpowiada rozdzielczości 300 dpi
   biYPelsPerMeter As Long      'rozdzielczość pionowa pixel/metr         ""          ""          
   biClrUsed As Long            'liczba użytych kolorów (liczba pozycji w tablicy kolorów),
                                'dla biClrUsed=0 używana jest maksymalna ilość kolorów
                                'określona przez wartości pola biBitCount
   biClrImportant As Long       'liczba kolorów znaczących, zazwyczaj ZERO tzn. że wszystkie
                                'kolory są potrzebne do wyświetlenia bitmapy
   'biClrUsed - dla 1-bitowych DIB = 0 lub 2
   'biClrUsed - dla 4-bitowych DIB = 0 lub 16, jeżeli 2-15 to wskazuje liczbę pozycji
								'w tablicy kolorów
   'biClrUsed - dla 8-bitowych DIB = 0 lub 256, jeżeli 2-255 to wskazuje liczbę pozycji
								'w tablicy kolorów
   'biClrUsed - dla 16, 24, 32 bitowych DIB zwykle wynosi ZERO
End Type

Dane obrazu.

biBitCount - element struktury BITMAPINFOHEADER określa ile kolejnych bitów z obszaru danych opisuje kolor jednego punktu bitmapy. Jednocześnie informuje ono, ile maksymalnie kolorów zawiera paleta kolorów.

  • biBitCount = 1
    każdy bajt danych obrazu (8 jego bitów) zawiera informację o ośmiu indeksach koloru w palecie kolorów dla ośmiu kolejnych pikseli. Bit wartości 0 odpowiada pierwszemu elementowi tablicy kolorów, bit wartości 1 odpowiada drugiemu elementowi palety kolorów.
  • biBitCount = 4
    każdy bajt danych obrazu (4 starsze i 4 młodsze jego bity) zawiera informację o dwóch indeksach koloru w palecie kolorów dla dwóch kolejnych pikseli.
  • biBitCount = 8
    każdy bajt danych obrazu określa indeks koloru w palecie kolorów dla jednego piksela.
  • biBitCount = 16 - bitmapa (High Color)

    W 16-bitowej bitmapie nie jest zdefiniowana paleta kolorów. Bezpośrednio po nagłówku BITMAPINFOHEADER w pliku BMP zapisane są dane obrazu.

    Każde dwa kolejne bajty (16 bitów) określają kolejno kolory trzech składowych (RGB) jednego piksela. Każdy składowa koloru piksela określana jest przez 5 kolejnych bitów. Składowa Blue to pięć najmniej znaczących bitów pierwszego bajtu. Składowa Green to dwa mniej znaczące bity drugiego bajtu i trzy najbardziej znaczące bity pierwszego bajtu. Składowa Red to 5 bitów ostatniego bajtu począwszy od drugiego najbardziej znaczącego bitu.

    Pierwszy najbardziej znaczący bit drugiego bajtu nie jest wykorzystywany i wynosi Zero. Jest on dopełnieniem koloru piksela do 16 bitów. Bit ten może być używany jako kanał ALPHA do przekazania informacji o przezroczystości.
  • Bity 16 bitowego piksela
    Ponieważ najmniej znaczące bajty wielobajtowych wartości zapisywane są na początku, to słowo piksela ma następującą postać:
    Bity 16 bitowego piksela
    Każda składowa koloru reprezentowana jest przez 5 bitów, co daje 2^5 = 32 możliwych poziomów intensywności każdej składowej koloru. Całkowita ilość możliwych kolorów piksela wynosi 32*32*32 = 32 768 dla każdego piksela. Możemy użyć wszystkie 16 bitów przeznaczonych na piksel i przydzielić jednej ze składowych (zazwyczaj składowej zielonej) dodatkowy bit.
    Bity 16 bitowego piksela
    Dzięki temu bitowi składowa ta może przyjmować 64 poziomy intensywności, co w sumie daje 32*64*32 = 65 536 możliwych kolorów dla każdego piksela.
  • biBitCount = 24 - bitmapa (True Color)
    W 24-bitowej bitmapie nie jest zdefiniowana paleta kolorów, więc bezpośrednio po nagłówku BITMAPINFOHEADER w pliku BMP zapisane są dane obrazu. Kolejne wiersze obrazu zapisane są (zazwyczaj) w odwrotnej kolejności, niż są wyświetlane na obrazie, tj. „z dołu do góry”. Trzy kolejne bajty (w sumie 24 bitów) określają kolor piksela. Kolor piksela zapisywane jest w kolejności B (blue), G (green), R (red).
  • biBitCount = 32
    trzy kolejne bajty (tak jak w bitmapie 24 bit) określają kolory kolejnych trzech składowych (RGB) jednego piksela, czwarty bajt zazwyczaj przyjmuje wartość zero. Bajt ten nie jest wykorzystywana przez większość programów. Może on jednak zawierać informację o skali przenikania (alphablendingu) każdego piksela.