Caricare immagini bitmap su microcontrollori AVR

Ecco come fare:

  • Ridimensionare l’immagine alle dimensioni del display applicando una buona interpolazione.
  • Covertirla in bianco e nero possibilmente applicando un metodo di dithering (tipo Floyd-Steinberg).
  • Salvare l’immagine come codice C.

Per fare tutto questo basta usare il famoso programma di grafica open source gratuito Gimp.

Ridimensionamento:
Dai, è facile!

Conversione in bianco e nero con dithering:
Immagine->Modalità->Indicizzata
Nel form che appare seleziona “Usa tavolozza bianco/nero (1bit)” e come Dithering di colore “Floyd-Steinberg (normale)”.
Premi su Conversione.

Partendo da:

Ottieni una cosa così:

Salvataggio come codice C:
File->Salva come…
Poi espandi l’oggetto “Seleziona tipo di file (per estensione)” e scegliere dalla lista “Intestazione codice sorgente C”.
Salva.

Il risultato è un file del tipo immagine.h, aprilo e cancella le cose che vedi in modo che appaia così:

/* GIMP header image file format (INDEXED): C:\….\immagine.h */

static char immagine[] PROGMEM= {
1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,0,0,0,0,0,0,0,0,0,1,0,0,1,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,
0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,
1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,1,
ecc ecc ecc…};

La parola chiave PROGMEM fa in modo che questo enorme array vada ad essere allocato nella memoria del programma, ossia nella flash e non nell’esigua RAM del processore.
Considera che un’immagine di N*M pixel salvata in questo modo occuperà N*M byte di memoria. Ad esempio 96X64=6144 byte.
Solo mediante la funzione di sistema pgm_read_byte() è possibile andare a leggere le variabili risiedenti nella memoria di programma, non è infatti possibile considerare le variabili allocate in flash alla stregua di quelle in RAM. SetPixel() è un’ipotetica funzione di disegno su un lcd grafico.

Il codice C proposto è per AVR-GCC:

#include<avr/pgmspace.h>
#include“immagine.h”

#define HEI 64
#define WID 96

int main()
{

/*Il tuo codice …*/

int i,j;
for(i=0 ; i<HEI ; i++) //Y
{
for(j=0 ; j<WID ; j++)//X
{
SetPixel(j , i , pgm_read_byte( &immagine[j+WID*i] ));
}
}
while(1);
return 0;
}