Structure Image

La structure

Le logiciel manipulant des images, une structure de manipulation doit être définie. Il existe différentes façon de faire. Le choix qui suit provient d'une volonté de maitriser une structure et que cette structure soit minimum et adpater aux seuls besoins de l'application. Les informations de ces images seront rassemblées dans une structure C pour faciliter leur utilisation.

struct image
{
  uint32 width;
  uint32 height;
  int sampleParPixel;
  int bps;
  float exposure;
  unsigned char *buffer;
  unsigned long bufferSize;
};

Les champs width et height donnent les dimensions de l'image en pixel.

Le champs sampleParPixel donne la taille de l'échantillonnage, soit 8 ou 16 bits. Ce champs contient soit la valeur 8, soit la valeur 16.

Le champs bps vaut 1 pour une image brut ou noir et blanc ou 3 pour une image couleur. En effet, pour définir une image en niveau de gris, une seule valeur (0 à 255 en 8 bits et 0 à 65535 en 16 bits) par pixel. Pour une image couleur, en informatique ou utilise la norme RGB, soit l'intensité de trois couleurs : le rouge, le vert et le bleu. Le mélange de ces trois couleurs permet de reconstituer les couleurs. Par convention, le zéro est l'absence d'une couleur et la valeur maximum de l'échantillonnage (255 ou 65535) la couleur la plus intense.

Exemple :

sampleParPixel Bps Description
8 1 Gris qui va de 0 pour le noir et 255 pour le blanc, en croissant, on va du gris presque noir vers le blanc
8 3 (0,0,0) pour le noir, (255,255,255) pour le blanc, (255,0,0) pour le rouge
16 3 (0,0,0) pour le noir, (65535,65535,65535) pour le blanc, (65535,0,0) pour le rouge

Le champs exposure n'est pas encore utilisé mais il est destiné à recevoir le temps d'exposition pour une brute ou la somme des temps des bruts pour une image compositée.

Le champs buffer contient un pointeur vers les données de l'image. C'est un tableau d'octet (un octet est un nombre formé de 8bits qui va de 0 à 255).

Le champs bufferSize donne la taille du buffer. Il doit contenir le résultat de la multiplication des champs suivant:

width * height * bps (*2 si sampleParPixel = 16).

Accès aux pixels

Pour obtenir les valeurs d'un pixel situé à l'emplacement (x,y) de l'image, nous pouvons utiliser la formule suivante :

count = y*im.width+ x;

Count contient alors un “pointeur” vers le buffer. Ce pointeur est donné par la multiplication de la largeur d'une ligne par le nombre de ligne avec l'addition de la colonne souhaitée.

Maintenant, en fonction du nombre d'octets utilisés par l'image on peut reconstituer la valeur par :

Pour une image en 8 bits, un seul plan :

v = im.buffer[count];

Pour une image en 8 bits et trois couleurs :

R = im.buffer[count*3];
G = im.buffer[count*3+1];
B = im.buffer[count*3+2];

Pour une image en 16 bits, un seul plan :

v = im.buffer[count*2]+256*im.buffer[count*2+1];

Pour une image en 16 bits et trois couleurs :

R = im.buffer[count*6]+256*im.buffer[count*6+1];
G = im.buffer[count*6+2]+256*im.buffer[count*6+3];
B = im.buffer[count*6+4]+256*im.buffer[count*6+5];

Amélioration

Dans le cadre d'un langage objet, avec la structure d'image définie comme ci-dessus, nous aurions une série de méthode pour accéder aux données de cette image.

Avec le langage C qui n'est pas a priori un langage orienté objet, il est possible de définir des pointeurs vers des fonctions. Il est alors possible de simuler ces méthodes d'accès. Donc l'objectif est de créer une méthode générique (c'est à dire sans analyser le type de l'image) qui renvoi les valeurs d'un point.

Nous définissons une fonction virtuelle ImVal qui a pour arguments un pointeur vers l'image, les coordonnées (x,y) du point. Cette fonction nous renvoi les valeurs R,G,B du point.

Pour que cette fonction soit utilisable des les quatre cas de figures, il faut que la fonction retourne trois valeurs pour le cas R,G,B sachant que dans le cas d'une image mono-plan, la variable R contient la valeur du pixel et les variables G et B ne sont pas touchées. Les variables R,G et B seront au format entier sur 16 bits non-signé soit uint16.

Pour écrire cette fonction, le premier réflexe est de regarder dans les valeurs de la structure, le nombre de plan et si cette image est 16 bits ou 8bits. En fonction de ces deux valeurs, il est possible d'appliquer une des méthodes décrites dans le paragraphe précédent.

La majorité du temps, cette fonction sera appelé dans une boucle qui parcourt l'ensemble des points de l'image. Donc cette recherche sera redondante et sera consommatrice de temps.

L'idée proposé est donc d'appelé une seule fois avant le premier appel de la fonction ImVal, une fonction d'initialisation qui fera une seule fois l'aiguillage. Cette fonction retournera un pointeur de fonction vers une des quatre possibilités :

_ImVal  DefImVal(struct image * im)
{
  if (im->bps==8)
    {
      if (im->sampleParPixel==3)
	return &ImValRGB8;
      if (im->sampleParPixel==1)
	return &ImValI8;
    }
  if (im->bps==16)
    {
      if (im->sampleParPixel==3)
	return &ImValRGB16;
      if (im->sampleParPixel==1)
	return &ImValI16;
    }
  return NULL;
}

Quatre fonctions seront définis pour chacune des possibilités:

Voici un exemple d'une des fonctions :

 
void ImValRGB16(struct image * im,unsigned long x,unsigned long y,
		uint16 *R, uint16 *G, uint16 *B)
{
 
  unsigned long count;
  count = (y*im->width+ x)*6;
 
  *R=im->buffer[count]+256*im->buffer[++count];
  *G=im->buffer[++count]+256*im->buffer[++count];
  *B=im->buffer[++count]+256*im->buffer[++count];
 
}

Exemple d'utilisation dans un code :

 
  // Recherche de la fonction de recherche d'une valeur d'un pixel
  _ImVal ImVal  = DefImVal(&im);
  uint16 R,G,B;
  R=0;
  G=0;
  B=0;
  for (y=0;y<im.height;y++)
    for (x=0;x<im.width;x++)
	{
           // Recupération des valeurs du pixel
	   (ImVal)(&im,x,y,&R,&G,&B);
           .../...

A noter:

  • Une fonction C ne retourne qu'une valeur. On aurait pu utiliser un tableau de valeurs mais il me semble plus simple d'utiliser les passages d'arguments par adresse.
  • L'initialisation avec 0 des valeurs R,G et B permet d'éviter un segmentation fault même si on peut penser que l'initialisation se fera par la fonction ImVal

Évidement, il est possible de définir le même type de code pour l'écriture d'un pixel dans une image.

 
apa/theorie/structure_d_image.txt · Dernière modification: 2007/12/30 22:37 par davidl
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki