Il formato BITMAP __________________________________________________________________________________________ Il formato BITMAP Introduzione Il Bitmap è il formato di visualizzazione delle immagini dei sistema operativo Windows e, anche se è uno dei formati più vecchi, è ancora molto utilizzato e soprattutto è molto portabile e riconosciuto da qualunque piattaforma. In questo mini-tutorial dopo una prima trattazione generale delle immagini in formato Bitmap, si approfondiranno la risoluzione a 8 bit in scala di grigi e a 16 bit RGB. Il formato BITMAP Le immagini bitmap possono avere una profondità di 1, 4, 8, 16, 24 o 32 bit per pixell. Le bitmap con 1, 4 e 8 bit contengono una tavolozza (palette) per la conversione dei (rispettivamente 2, 16 e 256) possibili indici numerici nei rispettivi colori. Nelle immagini con profondità più alta il colore non è indicizzato bensì codificato direttamente nelle sue componenti cromatiche RGB; con 16 o 32 bit per pixel alcuni bit possono rimanere inutilizzati.Ogni BMP contiene un Bitmap-file header, un Bitmap information header, una palette di colori e un’array di byte che contiene i pixel dell'immagine secondo la seguente struttura: Header del file: BITMAPFILEHEADER Blocco di informazioni: BITMAPINFO Header della Bitmap: BITMAPINFOHEADER Modello di colore (eventuale) Tavolozza (eventuale) Mappa dei pixel 1 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ BITMAPFILEHEADER Questo è l'header della bitmap che contiene informazioni sulla grandezza in byte del file e l'offset dall'inizio del file del primo byte nella mappa dei pixel. BITMAPINFOHEADER Qui sono indicate le dimensioni in pixel dell'immagine e il numero di colori utilizzati. Le informazioni sono relative al dispositivo sul quale la bitmap è stata creata. Sempre in questa struttura sono indicate inoltre la risoluzione orizzontale e verticale del dispositivo di output: questi valori, uniti a quelli della larghezza e dell'altezza in pixel, determinano le dimensioni di stampa dell'immagine in grandezza reale. Modello di colore Qui è possibile definire modelli di colore personalizzati. Nella pratica queste strutture sono poco comuni. Tavolozza (o palette) Questa struttura è un array che fa corrispondere un colore ad ogni indice che può essere assegnato ad un pixel. Nella tavolozza ogni colore è rappresentato da una struttura di 4 byte (RGBQUAD), uno ciascuno per i componenti rosso, verde e blu più un byte non utilizzato. Nel caso di immagini con 16, 24 o 32 colori, questa tabella di colori non è necessaria perché il colore dei pixel non è indicizzato, bensì codificato direttamente nelle sue componenti. Mappa dei pixel Questa struttura di dati costituisce il corpo vero e proprio della bitmap, dove ad ogni pixel si fa corrispondere un colore sotto forma di indice nella tavolozza, oppure nelle sue componenti cromatiche. 2 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ È inoltre importante dire che le immagini bitmap sono memorizzate in modalità bottom-up; cioè la prima riga della mappa dei pixel, in realtà è l’ultima dell’immagine. La seguente tabella contiene la descrizione dettagliata di un file bitmap. Per ogni campo verranno dati l’offset all’interno del file, la dimensione in byte e il contenuto. offset 0 2 6 10 offset 14 18 22 BITMAPFILEHEADER (dimensione:14 bytes) Dim(bytes) nome contenuto 2 bfType la stringa ASCII "BM" (valore decimale 19778, esadecimale 4D42) 4 bfSize dimensione del file 4 bfReserved 0 4 bfOffBits offset del primo byte della mappa dei pixel a partire dall'inizio del file BITMAPINFOHEADER (dimensione:40 bytes) Dim(bytes) nome contenuto 4 biSize dimensione in byte del blocco d'informazioni (valore decimale 40, esadecimale 28) 4 biWidth larghezza dell'immagine in pixel 4 biHeight altezza dell'immagine in pixel (la mappa dei pixel incomincia dalla riga di pixel più in basso e finisce con quella più in alto) 26 28 2 2 biPlanes biBitCount 30 4 biCompression sempre 1 profondità di colore dell'immagine in bit per pixel, dev'essere uno dei seguenti valori: 1, 4, 8, 16, 24 o 32. In caso di 1, 4 o 8 bit per pixel i colori sono indicizzati, nel caso di 16 potrebbe essere necessario introdurre opportune maschere uno dei seguenti valori: 0 (BI_RGB) La mappa dei pixel non è compressa. 1 (BI_RLE8) La mappa dei pixel è compressa con 3 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ 34 4 38 4 42 4 46 4 l'algoritmo RLE per 8 bit per pixel. Valido solo per biBitCount = 8 e biHeight > 0. 2 (BI_RLE4) La mappa dei pixel è compressa con l'algoritmo RLE per 4 bit per pixel. Valido solo per biBitCount = 4 e biHeight > 0. 3 (BI_BITFIELDS) La mappa dei pixel non è compressa ed è codificata secondo maschere di colore personalizzate. Valido solo per biBitCount = 16 o 32 biSizeImage Indica la dimesione in byte del buffer mappa dei pixel. Questo valore può essere lasciato a zero quando biCompression è impostato a BI_RGB biXPelsPerMeter risoluzione orizzontale del dispositivo di output in pixel per metro; 0 se la risoluzione non è specificata biYPelsPerMeter risoluzione verticale del dispositivo di output in pixel per metro; 0 se la risoluzione non è specificata biClrUsed quando biBitCount = 1 0 quando biBitCount = 4 o 8 numero di corrispondenze effettivamente utilizzate nella tavolozza dei colori; 0 indica il numero massimo (16 o 256). altrimenti numero di corrispondenze nella tavolozza dei colori (0 = nessuna tavolozza). Per profondità maggiori di 8 bit per pixel la 4 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ 50 4 biClrImportant 54 N*4 bytes Palette (eventuale) tavolozza non è normalmente necessaria, ma quando c'è può essere usata dal sistema o da alcuni programmi per ottimizzare la rappresentazione dell'immagine quando biBitCount = 1, 4 o 8 numero di colori utilizzati nell'immagine; 0 indica tutti i colori della tavolozza. altrimenti se la tavolozza esiste e contiene tutti i colori utilizzati nell'immagine numero di colori altrimenti 0 Definizione delle palette (tavolozza). Per ogni elemento nelle palette sono usati quattro bytes per descrivere il valore RGB del colore : 1 byte per la componente del blu 1 byte per la componente del verde 1 byte per la componente del rosso 1 byte di riempimento che è sempre 0 Come detto in precedenza, in seguito a questi dati nel file vengono inseriti i bytes che contengono la mappa dei pixel. Si ritiene opportuno spiegare in maniera più esauriente il campo chiamato biBitCount nel quale è indicato quanti bit corrispondono ad un singolo pixel e quindi qual è il massimo numero di colori dell’immagine. Quando il numero di bit per pixel è uguale ad 1, l’immagine è monocromatica e le palette contengono due elementi (8 bytes). Ogni bit dell’immagine rappresenta un pixel e se questo bit è 0 è 5 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ visualizzato con i colori RGB del primo elemento delle palette, se 1 con il secondo. Quando il numero di bit per pixel è uguale ad 4, l’immagine ha un massimo di 16 colori e le palette contengono 16 elementi (64 bytes). Ogni pixel dell’immagine è del colore RGB memorizzato nelle palette nella posizione corrispondente ai suoi 4 bit. Ad esempio se un byte dell’immagine è 2Fh esso rappresenta due pixel: il primo del colore del secondo elemento delle palette e il secondo del sedicesimo. Quando il numero di bit per pixel è uguale ad 8, l’immagine ha un massimo di 256 colori e le palette contengono 256 elementi (1024 bytes). Ogni byte dell’immagine rappresenta un pixel. Quando il numero di bit per pixel è uguale ad 16, l’immagine ha un massimo di 2^16 colori. Se il campo biCompression è settato a 0 (BI_RGB), il campo palette non contiene alcun elemento. In questo caso abbiamo 5 bit per ogni componente di colore e il bit più significativo inutilizzato. Significa che dei 16 bit che rappresentano un pixel i 5 meno significativi sono la componente del blu, i 5 immediatamente successivi quella del verde e i degli ultimi 6 il più significativo è inutilizzato e gli atri 5 sono la componente del rosso. Se invece il campo biCompression è settato a 3 (BI_ BITFIELDS), il campo palette contiene 12 bytes che rappresentano 3 maschere rispettivamente per le componenti del rosso, verde e blu (RGB). Se ad esempio dei 16 bit dell’immagine ne sono utilizzati 5 per il rosso, 6 per il verde e 5 per il blu, la maschera da inserire è: 0000F800h 000007E0h 0000001Fh. Questo significa che dei 16 bit per pixel i 5 meno significativi sono la componente del blu, i 6 immediatamente successivi quella del verde e i 6 più significativi quella del rosso. Quando il numero di bit per pixel è uguale ad 24, l’immagine ha un massimo di 2^24 colori e il campo palette non contiene alcun 6 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ elemento. Ogni pixel è rappresentato con tre bytes e ogni byte rappresenta rispettivamente l’intensita di rosso, verde e blu. Quando il numero di bit per pixel è uguale ad 32, l’immagine ha un massimo di 2^32 colori. Se il campo biCompression è settato a 0 (BI_RGB), il campo palette non contiene alcun elemento. In questo caso abbiamo un byte per ogni componente di colore e il byte meno significativo inutilizzato. Se invece il campo biCompression è settato a 3 (BI_ BITFIELDS), il campo palette contiene 12 bytes che rappresentano 3 maschere rispettivamente per le componenti del rosso, verde e blu (RGB). È il caso analogo a quello spiegato per le immagini a 16 bit per pixel solo che, ovviamente, ogni maschera è composta da 4 bytes. Intestazione per immagini ad 8 bit in scala di grigi Nella figura sottostante si osserva parte dell’intestazione BITMAP di un’immagine di dimensione 640x480 con risoluzione 8 bit in scala di grigi. Offset 0 16 32 48 Bytes 42 4d 36 b4 04 00 00 00 00 00 36 04 00 00 28 00 00 00 80 02 00 00 e0 01 00 00 01 00 08 00 00 00 00 00 00 b0 04 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 Come spiegato nella tabella precedente, i primi 2 bytes sono la stringa “BM” in hex 424d, la dimensione del file è 640x480 pixel ognuno dei quali rappresentato da un byte (8 bit in scala di grigi) quindi abbiamo 307200 bytes per la mappa dei pixel + 54 bytes di intestazione + 1024 bytes per le palette per un totale di 308278 bytes che in hex 04b436 che infatti è il valore memorizzato nel campo bfSize. Notare che l’ordinamento dei byte è little-endian (dal byte meno significativo a quello più significativo) quindi nel file troviamo il numero 04b436 in modo 36b404. L’offset dell’inizio della mappa dei pixel in hex è 0436 in quanto abbiamo, come detto prima, 54 bytes di intestazione + 1024 bytes per le palette per un totale di 1078 7 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ bytes che in hex 0436. Si notano poi, con gli opportuni offset, la dimensione dell’immagine 0280x01e0 (640x480), il numero di piani (1), il numero di bit per pixel (8), la dimensione della mappa dei pixel (04b000 hex 307200 dec) e il numero di colori significativi (100 hex 256 dec). Tra questa intestazione e la mappa di pixel devono essere inserite le palette, che, come spiegato prima, stabiliscono la corrispondenza tra il bytes che rappresenta il pixel e il corrispondente colore in RGB. Ogni elemento delle palette è composto da 4 bytes: 1 per la componente del rosso, uno per la componente del verde, uno per la componente del blu e uno inutilizzato settato a zero. Dato che vogliamo ottenere immagini in scala di grigi, per ogni elemento delle palette l’intensità dei tre colori sarà la stessa in quanto la scala di grigi è sulla diagonale del cubo RGB. Ciò significa che se un pixel, ad esempio, è rappresentato con il byte 1a, esso farà riferimento all’elemento 1a delle palette che avrà memorizzati i seguenti 4 bytes: 1a1a1a00 cioè intensità 1a per tutte e tre le componenti più il quarto byte settato a zero. In seguito sono riportati i 1024 bytes per le palette nel caso della risoluzione ad 8 bit in scala di grigio. 00 00 00 00 01 01 01 00 02 02 02 00 03 03 03 00 04 04 04 00 05 05 05 00 06 06 06 00 07 07 07 00 08 08 08 00 09 09 09 00 0a 0a 0a 00 0b 0b 0b 00 0c 0c 0c 00 0d 0d 0d 00 0e 0e 0e 00 0f 0f 0f 00 10 10 10 00 11 11 11 00 12 12 12 00 13 13 13 00 14 14 14 00 15 15 15 00 16 16 16 00 17 17 17 00 18 18 18 00 19 19 19 00 1a 1a 1a 00 1b 1b 1b 00 1c 1c 1c 00 1d 1d 1d 00 1e 1e 1e 00 1f 1f 1f 00 20 20 20 00 21 21 21 00 22 22 22 00 23 23 23 00 24 24 24 00 25 25 25 00 26 26 26 00 27 27 27 00 28 28 28 00 29 29 29 00 2a 2a 2a 00 2b 2b 2b 00 2c 2c 2c 00 2d 2d 2d 00 2e 2e 2e 00 2f 2f 2f 00 30 30 30 00 31 31 31 00 32 32 32 00 33 33 33 00 34 34 34 00 35 35 35 00 36 36 36 00 37 37 37 00 38 38 38 00 39 39 39 00 3a 3a 3a 00 3b 3b 3b 00 3c 3c 3c 00 3d 3d 3d 00 3e 3e 3e 00 3f 3f 3f 00 40 40 40 00 41 41 41 00 42 42 42 00 43 43 43 00 44 44 44 00 45 45 45 00 46 46 46 00 47 47 47 00 48 48 48 00 49 49 49 00 4a 4a 4a 00 4b 4b 4b 00 4c 4c 4c 00 4d 4d 4d 00 4e 4e 4e 00 4f 4f 4f 00 50 50 50 00 51 51 51 00 52 52 52 00 53 53 53 00 54 54 54 00 55 55 55 00 56 56 56 00 57 57 57 00 58 58 58 00 59 59 59 00 5a 5a 5a 00 5b 5b 5b 00 5c 5c 5c 00 5d 5d 5d 00 5e 5e 5e 00 5f 5f 5f 00 60 60 60 00 61 61 61 00 62 62 62 00 63 63 63 00 64 64 64 00 65 65 65 00 66 66 66 00 67 67 67 00 68 68 68 00 69 69 69 00 6a 6a 6a 00 6b 6b 6b 00 6c 6c 6c 00 6d 6d 6d 00 6e 6e 6e 00 6f 6f 6f 00 70 70 70 00 71 71 71 00 72 72 72 00 73 73 73 00 74 74 74 00 75 75 75 00 76 76 76 00 77 77 77 00 78 78 78 00 79 79 79 00 7a 7a 7a 00 7b 7b 7b 00 7c 7c 7c 00 7d 7d 7d 00 7e 7e 7e 00 7f 7f 7f 00 80 80 80 00 81 81 81 00 82 82 82 00 83 83 83 00 84 84 84 00 85 85 85 00 86 86 86 00 87 87 87 00 88 88 88 00 89 89 89 00 8a 8a 8a 00 8b 8b 8b 00 8c 8c 8c 00 8d 8d 8d 00 8e 8e 8e 00 8f 8f 8f 00 90 90 90 00 91 91 91 00 92 92 92 00 93 93 93 00 94 94 94 00 95 95 95 00 96 96 96 00 97 97 97 00 98 98 98 00 99 99 99 00 9a 9a 9a 00 9b 9b 9b 00 9c 9c 9c 00 9d 9d 9d 00 9e 9e 9e 00 9f 9f 9f 00 a0 a0 a0 00 a1 a1 a1 00 a2 a2 a2 00 a3 a3 a3 00 a4 a4 a4 00 a5 a5 a5 00 a6 a6 a6 00 a7 a7 a7 00 a8 a8 a8 00 a9 a9 a9 00 aa aa aa 00 ab ab ab 00 ac ac ac 00 ad ad ad 00 ae ae ae 00 af af af 00 b0 b0 b0 00 b1 b1 b1 00 b2 b2 b2 00 b3 b3 b3 00 b4 b4 b4 00 b5 b5 b5 00 b6 b6 8 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ b6 00 b7 b7 b7 00 b8 b8 b8 00 b9 b9 b9 00 ba ba ba 00 bb bb bb 00 bc bc bc 00 bd bd bd 00 be be be 00 bf bf bf 00 c0 c0 c0 00 c1 c1 c1 00 c2 c2 c2 00 c3 c3 c3 00 c4 c4 c4 00 c5 c5 c5 00 c6 c6 c6 00 c7 c7 c7 00 c8 c8 c8 00 c9 c9 c9 00 ca ca ca 00 cb cb cb 00 cc cc cc 00 cd cd cd 00 ce ce ce 00 cf cf cf 00 d0 d0 d0 00 d1 d1 d1 00 d2 d2 d2 00 d3 d3 d3 00 d4 d4 d4 00 d5 d5 d5 00 d6 d6 d6 00 d7 d7 d7 00 d8 d8 d8 00 d9 d9 d9 00 da da da 00 db db db 00 dc dc dc 00 dd dd dd 00 de de de 00 df df df 00 e0 e0 e0 00 e1 e1 e1 00 e2 e2 e2 00 e3 e3 e3 00 e4 e4 e4 00 e5 e5 e5 00 e6 e6 e6 00 e7 e7 e7 00 e8 e8 e8 00 e9 e9 e9 00 ea ea ea 00 eb eb eb 00 ec ec ec 00 ed ed ed 00 ee ee ee 00 ef ef ef 00 f0 f0 f0 00 f1 f1 f1 00 f2 f2 f2 00 f3 f3 f3 00 f4 f4 f4 00 f5 f5 f5 00 f6 f6 f6 00 f7 f7 f7 00 f8 f8 f8 00 f9 f9 f9 00 fa fa fa 00 fb fb fb 00 fc fc fc 00 fd fd fd 00 fe fe fe 00 ff ff ff 00 Il caso spiegato è quello di dimensione 640x480. Nel caso di altre dimensioni dell’immagine si ragiona in maniera analoga e gran parte dell’intestazione è la stessa tranne i campi che riguardano le dimensioni ai quali, con accortezza, bisogneranno sostituire i valori opportuni. Intestazione per immagini a 16 bit RGB Nella figura sottostante si osserva l’intestazione BITMAP completa di un’immagine di dimensione 640x480 con risoluzione 16 bit RGB. Offset 0 16 32 48 64 Bytes 42 4d 42 60 09 00 00 00 00 00 42 00 00 00 28 00 00 00 80 02 00 00 e0 01 00 00 01 00 10 00 03 00 00 00 00 60 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f8 00 00 e0 07 00 00 1f 00 00 00 Con un discorso analogo a quello effettuato per immagini in scala di grigi, i primi 2 bytes sono la stringa “BM” in hex 424d, la dimensione del file è 640x480 pixel ognuno dei quali rappresentato da 2 bytes (16 bit RGB) quindi abbiamo 614400 bytes per la mappa dei pixel + 54 bytes di intestazione + 12 bytes per le maschere di colore per un totale di 614466 bytes che in hex 096042 che infatti è il valore memorizzato nel campo bfSize sempre in modalità little-endian. L’offset dell’inizio della mappa dei pixel in hex è 42 in quanto abbiamo, come detto prima, 54 bytes di intestazione + 12 bytes per le palette per un totale di 66 bytes che in hex è appunto 42. Si notano poi, con gli opportuni offset, la dimensione dell’immagine 0280x01e0 (640x480), il numero di piani (1), il numero di bit per pixel (10 hex 16 dec), il campo biCompression(3 cioè 9 ____________________________________________________________ Il formato BITMAP __________________________________________________________________________________________ BI_BITFIELDS cioè la mappa dei pixel non è compressa ed è codificata secondo maschere di colore personalizzate), la dimensione della mappa dei pixel (096000 hex 614400 dec) e gli ultimi 12 bytes che rappresentano le maschere di colore. Il valore delle maschere è stato spiegato nel capitolo precedente. Anche in questo caso, per formati diversi l’intestazione è grossomodo la stessa tranne i campi dedicati alle dimensioni. 10 ____________________________________________________________