begin process at 2010 03 19 20:50:22
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Graphique

 > CONVERTIR UNE IMAGE 16 MILLIONS DE COULEURS EN NIVEAUX DE GRIS [BORLAND C++]

CONVERTIR UNE IMAGE 16 MILLIONS DE COULEURS EN NIVEAUX DE GRIS [BORLAND C++]


 Information sur la source

Note :
8,5 / 10 - par 6 personnes
8,50 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Graphique Niveau :Débutant Date de création :21/06/2003 Date de mise à jour :22/03/2004 19:43:09 Vu :5 798

Auteur : Draven

Ecrire un message privé
Commentaire sur cette source (5)
Ajouter un commentaire et/ou une note

 Description

La convertion en niveau de gris est tres importante lorsque l'on veut faire du traitement d'image.
Ce code permet de convertir un fichier bitmap de 16 millions de couleurs en niveaux de gris. En 16 millions de couleurs un pixel est codé par trois octets(bleu, vert ,rouge). Pour convertir en niveaux de gris on additionne ces trois valeurs  est on les divise par trois.

Pour les images couleurs ayant jusqu a 256 couleurs, l'algo est plus simple car il suffit de modifier la palette de couleurs. Je n ai pas integrer cette fonction pour le moment.

voila comment se deroule le programme
    -Lecture de l'en-tete de l image 16 millions de couleurs
    -Modification de l'en-tete pour obtenir un en-tete d'un fichier de 256 couleurs
    -Création de la platte en niveaux de gris
    -reconstruire l'image en niveaux de gris avec le calcul expliqué plus haut

Source

  • /*********************************************************************
  • nom: conv_nb
  • programmé par Draven
  • le 18/06/2003
  • **********************************************************************/
  • #include <stdio.h> /* printf(), scanf, fopen() ... */
  • #include <stdlib.h> /* exit() */
  • #include <windows.h> /*BITMAPFILEHEADER et BITMAPINFOHEADER */
  • /* structure comprenant les 2 en-têtes du fichier bitmap (54 octets) */
  • typedef struct
  • {
  • BITMAPFILEHEADER file; /*information sur le fichier (ex type,taille du fichier ) */
  • BITMAPINFOHEADER info; /*information sur la données de l'image (ex nbrcouleur utilise, longueur,largeur, taille de l'image) */
  • }HEADER;
  • typedef struct
  • {
  • BYTE bleu;
  • BYTE vert;
  • BYTE rouge;
  • }PIXEL;
  • HEADER en_tete(FILE*,HEADER,char *);
  • void changer(FILE*,HEADER);
  • void traitement(FILE *,FILE *, HEADER);
  • void main()
  • {
  • char nom_fichier[50];
  • FILE *source;
  • FILE *destination;
  • HEADER header;
  • printf("Entrez le nom du fichier: ");
  • scanf("%s",nom_fichier);
  • if((source=fopen(nom_fichier,"rb"))==NULL)
  • {
  • printf("erreur à l'ouverture du fichier\n");
  • exit(-1);
  • }
  • /* créer un fichier temporaire pour recopier une partie du fichier source*/
  • if((destination=fopen("tempo.bmp","wb"))==NULL)
  • {
  • printf("erreur à l'ouverture du fichier\n");
  • exit(-1);
  • }
  • header=en_tete(source,header,nom_fichier);
  • changer(destination,header);
  • traitement(source,destination, header);
  • printf("FIN");
  • fclose(source);
  • fclose(destination);
  • remove(nom_fichier); /* supprimer le fichier source */
  • rename("tempo.bmp",nom_fichier); /*renommer le fichier temporaire avec le nom du fichier source */
  • }
  • /*********************************************************************
  • nom: en_tete
  • role: lire l'en-tete du fichier bitmap passé en parametre
  • **********************************************************************/
  • HEADER en_tete(FILE* fd,HEADER header,char *nom_fichier)
  • {
  • fread(&header,sizeof(HEADER),1,fd); /* lire les 54 premiers octets qui constitue l'en-tete */
  • /* tester si les 2 premiers octets sont B et M */
  • if(header.file.bfType!=0x4D42)
  • {
  • printf("%s n'est pas un fichier bitmap\n",nom_fichier);
  • fclose(fd);
  • exit(-1);
  • }
  • /* on teste si l'image est en 16 millions de couleurs */
  • if(header.info.biBitCount!=24 || header.info.biBitCount!=0)
  • {
  • printf("Le fichier %s n'est pas en 16 millions de couleurs\n",nom_fichier);
  • fclose(fd);
  • exit(-1);
  • }
  • return header;
  • }
  • /******************************************************************
  • nom: changer
  • role: transforme l'en-tete pour un fichier image de 256 couleurs
  • et créer la palette de niveaux de gris.
  • L'en-tête modifié et la palette seront envoyé dans un nouveau fichier vide.
  • *******************************************************************/
  • void changer(FILE* destination,HEADER header)
  • {
  • int i;
  • RGBQUAD palette; /* description d'un pixel. composé d'une valeur bleu, vert, rouge, et de bourrage */
  • /*modification de l'en-tête*/
  • header.info.biBitCount=8; /* utilisation de 256 couleurs */
  • header.info.biClrUsed=256; /* nbr de couleurs utilisé (256)*/
  • header.info.biClrImportant=256;
  • /* copie de l'entete bmp (54 premiers octets) de le fichier "tempo.bmp" */
  • fwrite(&header,sizeof(HEADER),1,destination);
  • /* création de la palette en niveau de gris*/
  • for(i=0;i<256;i++)
  • {
  • /* la palette se compose d'une composante bleue, verte, rouge, et d'un octet de bourrage*/
  • palette.rgbBlue=i;
  • palette.rgbGreen=i;
  • palette.rgbRed=i;
  • palette.rgbReserved=0x00;
  • /* écrire les quatre octets composant la couleur dans le fichier */
  • fwrite(&palette,sizeof(RGBQUAD),1,destination);
  • }
  • }
  • /*********************************************************************
  • nom: traitement
  • role: reconstitue l'image couleurs en niveaux de gris
  • **********************************************************************/
  • void traitement(FILE *source ,FILE *destination, HEADER header)
  • {
  • int longueur,longueur32,bourrage;
  • int longueur32_nb,bourrage_nb;
  • int cpt,i;
  • int nouveau_pixel;
  • int tempo;
  • PIXEL pixel;
  • longueur=header.info.biWidth;
  • /* la largeur d'une image doit être un multiple de 4 (32 bits)
  • si ce n'est pas le cas des bourrage de 0 seront inserer a la fin */
  • /* Ici on calcule le nombre de bourrage pour chaque largeur de l'image en 16 millions de couleurs*/
  • /* pour le format 16 millions de couleurs*/
  • longueur32=longueur*3;
  • while((longueur32%4)!=0)
  • longueur32++;
  • bourrage=longueur32-(longueur*3);
  • /* Ici on calcule le nombre de bourrage pour chaque largeur de l'image en 256 couleurs*/
  • /* pour le format 256 couleurs*/
  • longueur32_nb=longueur;
  • while((longueur32_nb%4)!=0)
  • longueur32_nb++;
  • bourrage_nb=longueur32_nb-longueur;
  • /* se positionner au debut de la données de l'image pour l'image de 16 millions de couleurs */
  • fseek(source,0x36,SEEK_SET);
  • /* se positionner en fin de fichier, c'est à dire juste après la palette */
  • fseek(destination,0x00,SEEK_END);
  • /* faire autant de fois que la hauteur de l'image*/
  • for(cpt=0;cpt<header.info.biHeight;cpt++)
  • {
  • /* faire cette boucle pour chaque pixel de la largeur de l'image */
  • for(i=0;i<longueur;i++)
  • {
  • /* lire trois octets dans le fichier source qui correspondent aux composantes bleue, verte et rouge*/
  • fread(&pixel,sizeof(pixel),1,source);
  • /* on additionne la valeur des 3 composantes du pixel que l on divise par trois pour obtenir la valeur en niveau de gris */
  • nouveau_pixel=(pixel.bleu+pixel.vert+pixel.rouge)/3;
  • /* ecrire la nouvelle valeur du pixel dans le fichier source*/
  • /* pour une image en 256 couleurs 1 octet suffit pour coder un pixel*/
  • fputc(nouveau_pixel,destination);
  • }
  • /* avancer du nombre de bit de bourrage de l'image en 16 millions de couleurs*/
  • fseek(source,bourrage,SEEK_CUR);
  • /* ecrire le nombre de bourrage nécessaire dans l'image de 256 couleurs*/
  • for(i=0;i<bourrage_nb;i++)
  • fputc(0x00,destination);
  • }
  • }
/*********************************************************************
									nom: conv_nb
                           programmé par Draven
                           le 18/06/2003
**********************************************************************/

#include <stdio.h>      /* printf(), scanf, fopen() ... */
#include <stdlib.h>		/* exit() */
#include <windows.h>		/*BITMAPFILEHEADER et BITMAPINFOHEADER */

/* structure comprenant les 2 en-têtes du fichier bitmap (54 octets) */
typedef struct
{
     BITMAPFILEHEADER file; /*information sur le fichier (ex type,taille du fichier ) */
     BITMAPINFOHEADER info; /*information sur la données de l'image (ex nbrcouleur utilise, longueur,largeur, taille de l'image) */
}HEADER;

typedef struct
{
	BYTE bleu;
   BYTE vert;
   BYTE rouge;
}PIXEL;

HEADER en_tete(FILE*,HEADER,char *);
void changer(FILE*,HEADER);
void traitement(FILE *,FILE *, HEADER);

void main()
{
   char nom_fichier[50];
	FILE *source;
   FILE *destination;
   HEADER header;

   printf("Entrez le nom du fichier: ");
   scanf("%s",nom_fichier);
   if((source=fopen(nom_fichier,"rb"))==NULL)
   {
   	printf("erreur à l'ouverture du fichier\n");
     	exit(-1);
  	}
   /* créer un fichier temporaire pour recopier une partie du fichier source*/
   if((destination=fopen("tempo.bmp","wb"))==NULL)
   {
   	printf("erreur à l'ouverture du fichier\n");
      exit(-1);
   }
   header=en_tete(source,header,nom_fichier);
   changer(destination,header);
 	traitement(source,destination, header);
   printf("FIN");
   fclose(source);
   fclose(destination);

   remove(nom_fichier);  /* supprimer le fichier source */
   rename("tempo.bmp",nom_fichier); /*renommer le fichier temporaire avec le nom du fichier source */
}
/*********************************************************************
								nom:  en_tete
                        role: lire l'en-tete du fichier bitmap passé en parametre
**********************************************************************/
HEADER en_tete(FILE* fd,HEADER header,char *nom_fichier)
{
	fread(&header,sizeof(HEADER),1,fd); /* lire les 54 premiers octets qui constitue l'en-tete */
   /* tester si les 2 premiers octets sont B et M */
   if(header.file.bfType!=0x4D42)
   {
   	printf("%s n'est pas un fichier bitmap\n",nom_fichier);
      fclose(fd);
      exit(-1);
   }
   /* on teste si l'image est en 16 millions de couleurs */
   if(header.info.biBitCount!=24 || header.info.biBitCount!=0)
   {
   	printf("Le fichier %s n'est pas en 16 millions de couleurs\n",nom_fichier);
      fclose(fd);
      exit(-1);
   }
   return header;
}

/******************************************************************
							nom:  changer
                     role: transforme l'en-tete pour un fichier image de 256 couleurs
                       		et créer la palette de niveaux de gris.
                           L'en-tête modifié et la palette seront envoyé dans un nouveau fichier vide.
*******************************************************************/
void changer(FILE* destination,HEADER header)
{
   int i;
   RGBQUAD palette;    /* description d'un pixel. composé d'une valeur bleu, vert, rouge, et de bourrage */
   /*modification de l'en-tête*/
   header.info.biBitCount=8; /* utilisation de 256 couleurs */
   header.info.biClrUsed=256; /* nbr de couleurs utilisé (256)*/
	header.info.biClrImportant=256;
	/* copie de l'entete bmp (54 premiers octets) de le fichier "tempo.bmp" */
   fwrite(&header,sizeof(HEADER),1,destination);

   /* création de la palette en niveau de gris*/
   for(i=0;i<256;i++)
   {
      /* la palette se compose d'une composante bleue, verte, rouge, et d'un octet de bourrage*/
   	palette.rgbBlue=i;
      palette.rgbGreen=i;
      palette.rgbRed=i;
      palette.rgbReserved=0x00;
      /* écrire les quatre octets composant la couleur dans le fichier */
      fwrite(&palette,sizeof(RGBQUAD),1,destination);
   }
}

/*********************************************************************
								nom:  traitement
                        role: reconstitue l'image couleurs en niveaux de gris
**********************************************************************/
void traitement(FILE *source ,FILE *destination, HEADER header)
{
	int longueur,longueur32,bourrage;
   int longueur32_nb,bourrage_nb;
   int cpt,i;
   int nouveau_pixel;
   int tempo;
   PIXEL pixel;
   longueur=header.info.biWidth;
   /* la largeur d'une image doit être un multiple de 4 (32 bits)
      si ce n'est pas le cas des bourrage de 0 seront inserer a la fin */

   /* Ici on calcule le nombre de bourrage pour chaque largeur de l'image en 16 millions de couleurs*/
   /* pour le format 16 millions de couleurs*/
   longueur32=longueur*3;
   while((longueur32%4)!=0)
   	longueur32++;
   bourrage=longueur32-(longueur*3);

   /* Ici on calcule le nombre de bourrage pour chaque largeur de l'image en 256 couleurs*/
   /* pour le format 256 couleurs*/
   longueur32_nb=longueur;
   while((longueur32_nb%4)!=0)
   	longueur32_nb++;
   bourrage_nb=longueur32_nb-longueur;

   /* se positionner au debut de la données de l'image pour l'image de 16 millions de couleurs */
   fseek(source,0x36,SEEK_SET);
   /* se positionner en fin de fichier, c'est à dire juste après la palette */
   fseek(destination,0x00,SEEK_END);

   /* faire autant de fois que la hauteur de l'image*/
   for(cpt=0;cpt<header.info.biHeight;cpt++)
   {
      /* faire cette boucle pour chaque pixel de la largeur de l'image */
      for(i=0;i<longueur;i++)
      {
         /* lire trois octets dans le fichier source qui correspondent aux composantes bleue, verte et rouge*/
			fread(&pixel,sizeof(pixel),1,source);
         /* on additionne la valeur des 3 composantes du pixel que l on divise par trois pour obtenir la valeur en niveau de gris */
         nouveau_pixel=(pixel.bleu+pixel.vert+pixel.rouge)/3;
         /* ecrire la nouvelle valeur du pixel dans le fichier source*/
         /* pour une image en 256 couleurs 1 octet suffit pour coder un pixel*/
         fputc(nouveau_pixel,destination);
      }
      /* avancer du nombre de bit de bourrage de l'image en 16 millions de couleurs*/
      fseek(source,bourrage,SEEK_CUR);

      /* ecrire le nombre de bourrage nécessaire dans l'image de 256 couleurs*/
      for(i=0;i<bourrage_nb;i++)
      	fputc(0x00,destination);
   }
} 

 Conclusion

Petit bug: Avec paint l'image en niveau de gris est parfaite, mais dès que je la passe sur un logiciel de retouche d'image l'image se decale. Si quelqu un pouvait m'aider à rectifier se bug ca serait sympa.


 Sources du même auteur

Source avec Zip Source avec une capture TESTER VOTRE RAPIDITÉ À CLIQUER [BUILDER]
Source avec Zip APPLIQUER UN FILTRE À UNE IMAGE
Source avec Zip THREADS SOUS BUILDER
STÉGANOGRAPHIE [BORLAND C++]
Source avec Zip MARCHEZ LEMMINGS MARCHEZ... [BORLAND C++]

 Sources de la même categorie

Source avec Zip Source avec une capture VISUALISATION DES IMAGES EN 3D SANS OPENGL par Pistol_Pete
Source avec Zip Source avec une capture ANALYSE DE LA TEXTURE D'UNE IMAGE : FILTRE DE GABOR par Pistol_Pete
Source avec Zip Source avec une capture MONPPM : UN AFFICHEUR .PPM par pgl10
Source avec Zip Source avec une capture MOTEUR 3D : CASTOR3D par dragonjoker59
Source avec Zip Source avec une capture VIEWER COMPLET POUR LE TRAITEMENT DE L'IMAGE : IMANALYSE par Pistol_Pete

Commentaires et avis

Commentaire de MoDDiB le 21/06/2003 13:21:30

allez hop 10 ca fait bien longtemps que j'avais pas vu d'algo et ici on en voit jamais :(
D'ailleur si tu sais convertir du jpg en bmp je crois qu'on serait tous intéressé ^^

Commentaire de Draven le 21/06/2003 17:55:09

moi le premier

Commentaire de betchou le 19/01/2005 06:35:37

Nickel!
J'avais un petit projet à réaliser sur la compression d'images et on devait appliquer çà aux Bitmap. Le "bourrage" est très peu explicité sur internet.... Tu sais pourquoi il faut un multiple de 32?

Merci.

Commentaire de vychnou le 02/07/2005 15:46:30

    if(header.info.biBitCount!=24 || header.info.biBitCount!=0)
    {
        printf("Le fichier %s n'est pas en 16 millions de couleurs\n",nom_fichier);
       fclose(fd);
       exit(-1);
    }
Ce test est toujours vrai, non?

Commentaire de speletux le 14/09/2005 19:34:51

Pour convertir en niveaux de gris, vu que tu as 2**24 couleurs codées en RGB,

essaie la formule suivante:

Pour chaque pixel,

Gris = 0.30 * Rouge + 0.59 * Vert + 0.11 * Bleu

(norme NTSC)

 Ajouter un commentaire




Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,577 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales