Convertir une image 16 millions de couleurs en niveaux de gris [borland c++]

Contenu du snippet

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 / Exemple :


/*********************************************************************
									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.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.