GLG Programs fa uso di cookie per migliorare l'esperienza di navigazione degli utenti, ma non per tracciarne un profilo. Proseguendo nella navigazione, si accetta implicitamente l'utilizzo dei cookie.
[OK]Note legaliNon mi importa
Logo GLGPrograms Logo GLGPrograms

Immagini bitmap bit a bit

Preambolo

Oggigiorno esiste una grande varietà di formati per memorizzare le immagini in digitale. Tutti abbiamo scattato una foto JPEG, navigando su Internet avremo incontrato molte PNG, e chi non si è mai soffermato a vedere una GIF animata?
Il formato trattato in questa pagina è il Bitmap, uno dei primi formati ideati per memorizzare immagini: si tratta di un formato piuttosto anziano, progettato per essere elaborato con computer poco potenti, e non fa uso di particolari algoritmi per la compressione dell'informazione. Ne segue che l'algoritmo per leggere o scrivere un'immagine bitmap, è estremamente semplice.

Indice generale

  1. Introduzione
  2. Intestazione
  3. Codifica RGB a 24bit
  4. Tavolozza
  5. Bitmap
  6. Esempi

Introduzione

Il file contente un'immagine bitmap può essere scomposto in tre parti principali:

Come già accennato, il formato fu progettato per macchine con processori x86 con limitate (rispetto ad oggi) risorse hardware, perciò, per semplificare il caricamento in memoria delle informazioni, i byte sono in ordine little endian.

Intestazione

L'intestazione di un file Bitmap occupa sempre uno spazio fisso, i primi 54byte del file, ed è così composta:

OffsetDimensione (bit)Default HEXDescrizione
0-12 (16)42 4DIn codifica ASCII 42 4D corrisponde a "BM" e sta per bitmap. È il magic number che identifica il tipo di immagine
2-54 (32)Dimensione totale del file, espressa in bytes (per esempio 00 01 00 00 = 256bytes)
6-94 (32)00 00 00 00Sono posti sempre tutti e quattro a zero, non hanno significato
10-134 (32)Offset al quale iniziano i pixel della bitmap (la terza sezione del file).
14-174 (32) 
18-214 (32)Larghezza dell'immagine, espressa in pixel
22-254 (32)Altezza dell'immagine, espressa in pixel
26-272 (16)01 00Numero di livelli (in genere 1 solo)
28-292 (16)Profondità di colore in numero di bit. Può valere 1 (0x01), 4 (0x0400), 8 (0x0800), 16 (0x1000), 24 (0x1800) oppure 32 (0x2000). Le più frequenti sono 24, 8 e 1. Per immagini a profondità di colore di 8 bit o meno, viene utilizzata una tavolozza.
30-334 (32)00 00 00 00Tipo di compressione RLE dell'immagine (se 0, allora non c'è compressione)
34-374 (32)Dimensione in bytes della bitmap (l'immagine vera e propria, nella terza sezione del file)
38-414 (32)00 00 00 00Risoluzione orizzontale ottimale del dispositivo di output, espressa in Pixel Per Metro. 0 non indica un valore specifico.
42-454 (32)00 00 00 00Risoluzione verticale ottimale del dispositivo di output, espressa in Pixel Per Metro. 0 non indica un valore specifico.
46-494 (32)00 00 00 00Numero dei colori realmente utilizzati nella tavolozza: per esempio, può capitare di dover codificare 150 colori, perciò 4bit sono pochi, mentre 8bit sono troppi: in tal caso, si approssima per eccesso (8bit) e si specifica il numero di colori realmente utilizzati in questa locazione. Se vale 0, allora, se l'immagine ha una tavolozza, tutti i colori vengono utilizzati, altrimenti la tavolozza non è presente.
50-534 (32)00 00 00 00Informazioni accessorie sui colori (normalmente 00 00 00 00)

Codifica RGB a 24bit

Ogni colore della realtà può essere descritto come una miscela dei tre colori primari: rosso, verde e blu (Red, Green and Blue). Ogni colore viene quantizzato, cioè codificato in maniera finita e approssimata all'interno del computer, attraverso la quantizzazione delle sue singole componenti. Per ingannare l'occhio umano, un ragionevole compromesso di qualità/spazio, è quello di codificare ogni colore primario su un byte (8 bit = 28 = 256 sfumature). Ogni colore, quindi, occupa in memoria 3byte, uno per componente, per un totale di 23 × 8 = 24 = 16.777.216 colori diversi codificabili (sarà capitato di incontrare, qualche volta, l'espressione immagine a 16 milioni di colori).

Per comodità, dato che i processori erano a 8/16bit (successivamente a 32bit e oggi anche a 64bit, ma mai a 24bit), un colore viene codificato su 32bit, cioè 4bytes. Gli 8 bit che rimangono, nelle immagini Bitmap sono posti tutti a 0 e vengono ignorati.

Codifiche più recenti, come RGBA, utilizzano questi 8bit rimanenti per il canale alfa, cioè la trasparenza. Si noti che un'immagine opaca (come una bitmap), in questa codifica avrebbe trasparenza 0xFF, ma, nel suo formato originale, in cui il canale alfa viene comunque ignorato, è 0x00.

Per esempio, questa combinazione RGB di A0 00 BB genera questa particolare sfumatura di viola.

La tavolozza

Quando si trattano immagini con pochi colori, è conveniente utilizzare una tavolozza, che contiene informazioni sui colori dell'immagine. Attraverso di essa, si può associare un nome a un insieme più piccolo dei 16 milioni di colori, in maniera tale da utilizzare solo il nome simbolico per la sua rappresentazione, e risparmiare memoria. Naturalmente, anche i nomi simbolici sono numeri, ma, essendo pochi, sono rappresentabile su un minor numero di bit (8, 4 o addirittura 1).

Dal punto di vista pratico, la tavolozza non è altro che un array, di dimensioni pari a numero di colori × 4 bytes. Si trova appena dopo l'intestazione del file, a partire dall'offset 54. La tabella chiarirà le idee:

OffsetCaratteristicaN° ColoreDescrizione
53......Ultimo byte dell'header
54Blu0Componente Blu del primo colore (0)
55Verde0Componente Verde del primo colore (0)
56Rosso0Componente Rossa del primo colore (0)
570Componente Alpha (0) del primo colore (0)
58Blu1Componente Blu del secondo colore (1)
59Verde1Componente Verde del secondo colore (1)
60Rosso1Componente Rossa del secondo colore (1)
611Componente Alpha (0) del secondo colore (1)
62Blu2Componente Blu del terzo colore (2)

e così via...

Una tavolozza completa per immagini a 8bit inizia all'offset 54 e termina all'offset 1077, per una dimensione totale di 1024bytes (4 × 256 colori). Si osservi che, seguendo l'ordinamento little endian, si tratta più di una codifica BGR che RGB.

La Bitmap

Errore comune L'immagine mostra un comune errore di codifica/decodifica di un file che non rispetta il vincolo delle linee multiple di 32bit

Il formato immagine Bitmap possiede questo nome in quanto, una volta definite tutte le informazioni sull'immagine, creata cioè la mappa, l'immagine è costituita semplicemente da un flusso di bit, continuo, che può essere interpretato solo avendo acquisito le informazioni dell'intestazione e dell'eventuale tavolozza.

In caso di immagini con tavolozza, il flusso di bit inizia all'offset 1078; invece, in un'immagine senza tavolozza ad alta profondità di colore, il flusso inizia subito dopo l'intestazione, in sostituzione della tavolozza (offset 54). Se l'immagine è stata codificata correttamente, il preciso offset è leggibile direttamente dall'intestazione, rendendo superflue queste considerazioni.

Da questa posizione in poi, ogni gruppo di bit (da 1 a 32, a seconda della profondità di colore dell'immagine), rappresenterà il colore di un pixel, cioè un singolo punto dell'immagine, dal basso verso l'alto, da sinistra verso destra.

Per velocizzare la fase di lettura e scrittura dell'immagine, i primi software di codifica leggevano e scrivevano 32 bit alla volta (4 byte), perciò, ogni riga di pixel, deve essere rappresentata con un numero di bit multiplo di 32. Se l'immagine non ha una risoluzione orizzontale ed una profondità di colore che le permettano di rientrare in questo limite, i bit in eccesso vengono posti a 0.

Per esempio, in una Bitmap a 8bit di 37x25, tutte le righe terminano con 3 bytes posti a 0.

Esempi

Steganografia nelle bitmap in C++: Mr Hyde

L'idea che sta alla base dell'algoritmo di Mr Hyde è molto semplice. Nella codifica RGB si "miscelano" le tre componenti primarie di ogni colore su 8bit. Cambiando opportunamente il bit meno significativo di ogni componente, è possibile alterare leggermente l'immagine in maniera tale da farle contenere un messaggio a nostro piacere. Cambiando questa tonalità si genera, al massimo, una variazione percentuale di colore dell'ordine di 10-4, ampiamente sufficiente a nascodere un messaggio senza che nessuno si accorga della sua presenza.

Il programma dimostrativo mrhyde.tar.gz è interattivo e assume che il flusso dati sia una stringa C (terminata da NULL).

Queste due immagini Bitmap, apparentemente identiche, in realtà differiscono leggermente in alcuni pixel: quella di destra, infatti, contiene un messaggio nascosto:

Fotografia originale Fotografia con messaggio

Ad esempio, si assuma di avere un'immagine completamente bianca, cioè nella quale tutte le componenti sono poste a 0xFF = 11111111. Si nasconda la lettera A (ASCII 0x40 = 01000001) nell'immagine: si prende il primo bit di 0x40, che è 0, e lo si sostituisce con l'ultimo bit del primo componente; si prende il secondo bit di 0x40, che è 1, e lo si sostituisce all'ultimo bit del secondo componente. E così via, per ogni bit di 0x40, e poi ancora, per ogni bit dei caratteri successivi. Questo algoritmo è piuttosto avido di memoria, in quanto l'informazione viene espansa di 8 volte!

         11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 Prima
         11111110 11111111 11111110 11111110 11111110 11111110 11111110 11111111 Dopo
                ^        ^        ^        ^        ^        ^        ^        ^
         0 -----+        |        |        |        |        |        |        |
         1 --------------+        |        |        |        |        |        |
         0 -----------------------+        |        |        |        |        |
A (0x40) 0 --------------------------------+        |        |        |        |
         0 -----------------------------------------+        |        |        |
         0 --------------------------------------------------+        |        |
         0 -----------------------------------------------------------+        |
         1 --------------------------------------------------------------------+

Si osservi che le parole Prima e Dopo sono state opportunamente colorate (basandosi sui cambiamenti dei primi 3 byte) per evidenziare quanto sia insignificante la variazione di colore.

Leggere una Bitmap in MS-DOS QBasic

Il seguente codice descrive una funzione in QBasic originale, ed è in grado di caricare sullo schermo un'immagine a 256 colori con risoluzione orizzontale multipla di 4 pixel: BASImmagine test

Pagina scritta da

Hai una domanda? Scrivici!
Questa pagina ti è piaciuta? Condividila!
Share on Facebook Share on Google+ Share on linkedin