Definizione del formato immagine pbm

In questa pagina vediamo come è possibile, con un programma C, scrivere un file che contiene una immagine. Per prima cosa, i file immagini sono file come tutti gli altri, per cui possono venire aperti (in lettura oppure in scrittura) come un qualsiasi altro file. Quello che li rende diversi è solo il modo in cui sono organizzati, ossia il tipo di informazioni che contengono. Esistono numerosi modi di rappresentare una immagine su file, e ognuno di questi dà luogo a un differente formato. Formati esistenti sono per esempio: JPEG, GIF, BMP, PCX, PNG, TIFF, TGA, RAS/SUN, ICO, PBM, PPM, ecc.

In questa pagina vediamo il solo formato ``plain pbm'', che è il più facile da realizzare usando un programma C. Cominciamo quindi a leggere la specifica del formato pbm.

Per prima cosa, si tratta di un formato raster, ossia rappresenta una immagine pixel per pixel. Inoltre, si tratta di un formato per rappresentare solo immagini in bianco e nero. È quindi chiaro che, per ogni pixel dell'immagine che si va a rappresentare, il pixel può essere solo bianco o nero. In particolare, un file pbm è fatto come segue:

  1. Il formato specifica che il file deve cominciare con la stringa P1. Se quindi vogliamo realizzare un programma che scrive un file in formato pbm, occorre aprire un file in scrittura, e scrivere subito la stringa P1.
  2. La seconda cosa che il file deve contenere è la sua dimensione. In altre parole, per scrivere un file pbm, dobbiamo scrvivere larghezza e altezza di seguito alla stringa P1, tutti separati da spazi.
  3. La cosa che segue nel file è la sequenza dei pixel della immagine. Come si è detto, ogni pixel può essere colorato solo in nero oppure in bianco. In particolare, il nero si rappresenta come 1, mentre il bianco è 0. Una cosa importante da tenere conto è la disposizione di questi numeri su file. Infatti, si deve partire dalla posizione in alto a sinistra, spostandosi ogni volta a destra fino alla fine della riga e poi in basso.

I primi due punti sono facili da interpretare: si scrive su file la stringa P1, poi la larghezza dell'immagine e poi l'altezza. Il terzo punto risulta subito chiaro se si disegna la griglia dei pixel, con le corrispondenti coordinate:

Il terzo punto della specifica dice semplicemente che i pixel devono apparire sul file come se venissero letti normalmente da sinistra a destra e dall'alto in basso. In altre parole, il file si ottiene leggendo i valori dei pixel come se fossero parole di un testo.

È quindi chiaro che si deve partire dal pixel in alto a sinistra, leggendo una riga per volta. Si deve quindi stampare prima il pixel di coordinate 0,h-1 poi 1,h-1 poi 2.h-2, ecc e solo quando la riga è finita si può passare alla coordinata y=h-2.

Supponiamo quindi di voler stampare una matrice in cui tutti i punti siano bianchi tranne quelli all'interno del rettangolo compreso fra i punti (10,10) e (40,20). Dal momento che dobbiamo stampare una riga per volta, e che il valore della coordinata y che indica la riga deve andare da h-1 a 0, il ciclo più esterno sarà:

  for(y=h-1; y>=0; y--)

Per ogni riga, vanno stampati tutti i suoi punti, quindi occorre fare un secondo ciclo sulla coordinata x:

    for(x=0; x<=w-1; x++)

Per ogni pixel, possiamo decidere se deve essere bianco o nero a seconda se si trova o meno all'interno del rettangolo. In particolare, il punto è nero solo se la sue coordinata x è compresa fra le x dei due punti estremi del rettangolo, e lo stesso per la y. Quindi, per ogni punto facciamo:

      if( x>=10 && x<=40 && y>=10 && y<=20 )
        fprintf(fd, "1\n");
      else
        fprintf(fd, "0\n");

Il programma completo di stampa del rettangolo rettangolo.c è riportato qui sotto.

/*
  Scrive un rettangolo su file.
*/

#include<stdlib.h>
#include<stdio.h>

int main() {
  int w=200, h=100;
  FILE *fd;
  int x, y;

		/* apre il file */
  fd=fopen("rettangolo.pbm", "w");
  if( fd==NULL ) {
    perror("Errore in apertura del file");
    exit(1);
  }


		/* scrive il rettangolo */
  fprintf(fd, "P1\n");
  fprintf(fd, "%d %d\n", w, h);

  for(y=h-1; y>=0; y--)
    for(x=0; x<=w-1; x++)
      if( x>=10 && x<=40 && y>=10 && y<=20 )
        fprintf(fd, "1\n");
      else
        fprintf(fd, "0\n");


		/* chiude il file */
  fclose(fd);

  return 0;
}


L'immagine che viene prodotta da questo programma è riportata qui sotto.