begin process at 2008 07 06 01:01:37
1 205 425 membres
7 nouveaux aujourd'hui
14 119 membres club

Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum.
Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

IMANALYSE : LOGICIEL DE TRAITEMENT DE L'IMAGE + DITHERING [WIN32]




Description

ImAnalyse est un logiciel de traitement de l'image offrant la possibilité à l'utilisateur d'effectuer toute une série de traitement avec juste la souris. L'interface graphique a été complètement repensée et réécrite de A à Z  en pour plus de simplicité. (WIN32)

Ce programme permet l’ouverture d’image au format bmp, jpg et gif et de les sauvegarder au format bmp.
Quant aux traitements voici les principaux :
Seuillage automatique, morphologie mathématique, opération logique sur les images binaires, addition soustraction de 2 images, différents filtres, filtres passe bas, passe haut, détection des contours optimale, LPE, détection de cercle…

Voici toutes les nouveautés : prise en charge des formats jpg et gif, filtre sépia, filtre kuwahara (élimination du bruit), Médian HSL, effet mosaïque, diagramme de Voronoi, statistique de l’image, étirement/ rétrécissement de l’image, flip horizontal et vertical, rotation de l’image avec la possibilité de choisir un angle personnalisé.

Le traitement mis en avant dans ce programme est le dithering. Vous pouvez lancer les 2 scriptes testes directement depuis la barre d’outil.
Les techniques de dithering ont été créées dans les années 1970 pour réduire la taille des images. Il s’agit donc d’une technique de compression. La problématique était de passer d’une image p couleurs en une image n couleurs (avec n<p) sans trop perdre en qualité. La méthode la plus simple est de prendre le niveau de quantification le plus proche pour un pixel donné. Cependant cette méthode donne de mauvais résultats (voir capture d’écran). On a donc introduit une notion d’erreur qui sera répartie sur les pixels suivants. L’information est ici bien mieux conservée.
Voici les méthodes implémentées :
Floyd_Steinberg, Bill_Atkinson, Jarvis_Judice_Ninke, Stucki, Burkes, Sierra, Sierra_Lite et une méthode personnelle.

Source

  • //*********************************************************************************
  • //Auteur : MORARD Vincent
  • //Date : 10 octobre 2007
  • //MAJ : 29 avril 2008
  • //Version: 2.0
  • //Contact: vincent.morard@cpe.fr
  • //Website: http://pistol.petesampras.free.fr
  • //*********************************************************************************
  • #include "Cimage.h"
  • typedef struct TAG_CoefDithering
  • {
  • int Offx,Offy;
  • double Coef;
  • void *Next;
  • }CoefDithering;
  • //******************************************************************************
  • //Add : Ajout d'un element
  • //
  • //INPUT
  • //-- CD adresse du premier element
  • //-- Offx,Offy,Coef : Info de l'element
  • //******************************************************************************
  • void Add(CoefDithering **CD,int Offx,int Offy,double Coef)
  • {
  • CoefDithering *Current=new CoefDithering;
  • Current->Offx=Offx;
  • Current->Offy=Offy;
  • Current->Coef=Coef;
  • Current->Next=NULL;
  • if(*CD==NULL) //First
  • *CD=Current;
  • else {
  • CoefDithering *Search=*CD;
  • while(Search->Next)Search=(CoefDithering*)Search->Next;
  • Search->Next=Current;
  • }
  • }
  • //******************************************************************************************
  • //DitherMethod : Effectue le chainage des coefficients suivant la methode desire
  • //
  • //INPUT
  • //-- Method : Methode desire : Floyd_Steinberg ou Bill_Atkinson ou Stucki ou Burkes ou Morard
  • //-- CD : Adresse du premier element
  • //OUPUT
  • //-- WidthSup: Nombre de pixel qui sortiront de l'image en largeur
  • //-- HeightSup:Nombre de pixel qui sortiront de l'image en haUteur
  • //*******************************************************************************************
  • void DitherMethod(int Method,CoefDithering **CD,int *WidthSup,int *HeightSup)
  • {
  • switch(Method)
  • {
  • //The Floyd-Steinberg filter
  • // * 7
  • // 3 5 1 (1/16)
  • case Floyd_Steinberg:
  • Add(CD,1 ,0 ,7.0/16.0);
  • Add(CD,-1,1 ,3.0/16.0);
  • Add(CD,0 ,1 ,5.0/16.0);
  • Add(CD,1 ,1 ,1.0/16.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 1;
  • *HeightSup= 1;
  • break;
  • //Bill Atkinson dithering
  • // * 1/8 1/8
  • // 1/8 1/8 1/8
  • // 1/8
  • case Bill_Atkinson:
  • Add(CD,1 ,0 ,1.0/8.0);
  • Add(CD,2 ,0 ,1.0/8.0);
  • Add(CD,0,1 ,1.0/8.0);
  • Add(CD,1 ,1 ,1.0/8.0);
  • Add(CD,2 ,1 ,1.0/8.0);
  • Add(CD,1 ,2 ,1.0/8.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 2;
  • *HeightSup= 2;
  • break;
  • //The Jarvis, Judice, and Ninke filter
  • // * 7 5
  • // 3 5 7 5 3
  • // 1 3 5 3 1 (1/48)
  • case Jarvis_Judice_Ninke:
  • Add(CD,1 ,0 , 7.0/48.0);
  • Add(CD,2 ,0 , 5.0/48.0);
  • Add(CD,-2,1 , 3.0/48.0);
  • Add(CD,-1,1 , 5.0/48.0);
  • Add(CD,0 ,1 , 7.0/48.0);
  • Add(CD,1 ,1 , 5.0/48.0);
  • Add(CD,2 ,1 , 3.0/48.0);
  • Add(CD,-2,2 , 1.0/48.0);
  • Add(CD,-1,2 , 3.0/48.0);
  • Add(CD,0 ,2 , 5.0/48.0);
  • Add(CD,1 ,2 , 3.0/48.0);
  • Add(CD,2 ,2 , 1.0/48.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 2;
  • *HeightSup= 2;
  • break;
  • //The Stucki filter
  • // * 8 4
  • // 2 4 8 4 2
  • // 1 2 4 2 1 (1/42)
  • case Stucki:
  • Add(CD,1 ,0 , 8.0/42.0);
  • Add(CD,2 ,0 , 4.0/42.0);
  • Add(CD,-2,1 , 2.0/42.0);
  • Add(CD,-1,1 , 3.0/42.0);
  • Add(CD,0 ,1 , 8.0/42.0);
  • Add(CD,1 ,1 , 4.0/42.0);
  • Add(CD,2 ,1 , 2.0/42.0);
  • Add(CD,-2,2 , 1.0/42.0);
  • Add(CD,-1,2 , 2.0/42.0);
  • Add(CD,0 ,2 , 4.0/42.0);
  • Add(CD,1 ,2 , 2.0/42.0);
  • Add(CD,2 ,2 , 1.0/42.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 2;
  • *HeightSup= 2;
  • break;
  • //The Burkes filter
  • // * 8 4
  • // 2 4 8 4 2 (1/32)
  • case Burkes:
  • Add(CD,1 ,0 , 8.0/32.0);
  • Add(CD,2 ,0 , 4.0/32.0);
  • Add(CD,-2,1 , 2.0/32.0);
  • Add(CD,-1,1 , 3.0/32.0);
  • Add(CD,0 ,1 , 8.0/32.0);
  • Add(CD,1 ,1 , 4.0/32.0);
  • Add(CD,2 ,1 , 2.0/32.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 2;
  • *HeightSup= 1;
  • break;
  • //The Sierra filters
  • // * 5 3 The Sierra3 filter
  • //2 4 5 4 2
  • // 2 3 2 (1/32)
  • case Sierra:
  • Add(CD,1 ,0 , 5.0/32.0);
  • Add(CD,2 ,0 , 3.0/32.0);
  • Add(CD,-2 ,1 , 2.0/32.0);
  • Add(CD,-1 ,1 , 4.0/32.0);
  • Add(CD,0 ,1 , 5.0/32.0);
  • Add(CD,1 ,1 , 4.0/32.0);
  • Add(CD,2 ,1 , 2.0/32.0);
  • Add(CD,-1 ,2 , 2.0/32.0);
  • Add(CD,0 ,2 , 3.0/32.0);
  • Add(CD,1 ,2 , 2.0/32.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 2;
  • *HeightSup= 2;
  • break;
  • // * 2 The Sierra-2-4A filter
  • // 1 1 (1/4)
  • case Sierra_Lite:
  • Add(CD,1 ,0 , 2.0/4.0);
  • Add(CD,0 ,1 , 1.0/32.0);
  • Add(CD,1 ,1 , 1.0/32.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 1;
  • *HeightSup= 1;
  • break;
  • // * 1 2
  • //4 2 1 2 4
  • //8 4 2 4 8 /42
  • case Morard:
  • Add(CD,1 ,0 , 1.0/42.0);
  • Add(CD,2 ,0 , 2.0/42.0);
  • Add(CD,-2 ,1 , 4.0/42.0);
  • Add(CD,-1 ,1 , 3.0/42.0);
  • Add(CD,0 ,1 , 1.0/42.0);
  • Add(CD,1 ,1 , 3.0/42.0);
  • Add(CD,2 ,1 , 4.0/42.0);
  • Add(CD,-2 ,2 , 8.0/42.0);
  • Add(CD,-1 ,2 , 4.0/42.0);
  • Add(CD,0 ,2 , 2.0/42.0);
  • Add(CD,1 ,2 , 4.0/42.0);
  • Add(CD,2 ,2 , 8.0/42.0);
  • //Pour ne pas sortir de l'image.
  • *WidthSup = 2;
  • *HeightSup= 2;
  • break;
  • }
  • }
  • //*********************************************************************************************************************
  • //DITHERING
  • //
  • //INPUT
  • //--Method :Si Method <=0 ou >8 alors il n'y a pas de diffusion d'erreur => on prend la valeur du pixel le plus proche
  • // Floyd_Steinberg ou Bill_Atkinson ou Stucki ou Burkes ou Morard
  • //--Type :si RGBi :On effectuera la diffusion d'erreur sur les 3 canaux de facon independante
  • // GRAY :On convertie l'image en niveau de gris puis on effectue la diffusion d'erreur
  • //--Niveau :tableau de int rassemblant tous les niveaux de sortie de l'image
  • //--NbNiveau:Nombre d'element du tableau niveau
  • //--ImgDest :Image ou sera stoker le traitement. Si 0 sera stoker dans l'image source
  • //
  • //OUTPUT
  • //1 = reussit, 0 = echec
  • //**********************************************************************************************************************
  • bool CImage::Dithering(int Type,int Method,int *Niveau,int NbNiveau,CImage *ImgDest)
  • {
  • if(hBmp==0){
  • MessageBox(NULL,"Dither : L'image source est vide",
  • NULL,MB_OK|MB_ICONWARNING);
  • return 0;
  • }
  • if(ImgDest!=0 && ImgDest!=this)
  • ImgDest->Copy(this);
  • if(ImgDest==0)
  • ImgDest=this;
  • if(ImgType == GRAY)
  • Type=GRAY;
  • //Préparation de la diffusion suivant la méthode retenu.
  • int WidthSup,HeightSup;
  • CoefDithering *CD=NULL,*CurrentCD=NULL;
  • DitherMethod(Method,&CD,&WidthSup,&HeightSup);
  • //recupération des pixels
  • GetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits);
  • int i,j,Error,LastVal,Min,NewVal,k,Diff;
  • int LastValR,LastValG,DiffR,DiffG,NewValR,NewValG,MinR,MinG; //Si RGB
  • for(j=0;j<Height;j++)
  • for(i=0;i<Width;i++)
  • {
  • LastVal=ImgDest->ucBits[(i+j*Width)*4];
  • Min=256;
  • switch(Type)
  • {
  • case RGBi:
  • MinR=256;
  • MinG=256;
  • LastValR=ImgDest->ucBits[(i+j*Width)*4+2];
  • LastValG=ImgDest->ucBits[(i+j*Width)*4+1];
  • for(k=0;k<NbNiveau;k++)
  • {
  • Diff = abs(LastVal-Niveau[k]);
  • DiffG = abs(LastValG-Niveau[k]);
  • DiffR = abs(LastValR-Niveau[k]);
  • if(DiffR < MinR) {
  • MinR=DiffR;
  • NewValR=Niveau[k];
  • }
  • if(DiffG < MinG) {
  • MinG=DiffG;
  • NewValG=Niveau[k];
  • }
  • if(Diff < Min) {
  • Min=Diff;
  • NewVal=Niveau[k];
  • }
  • }
  • ImgDest->ucBits[(i+j*Width)*4]=NewVal;
  • ImgDest->ucBits[(i+j*Width)*4+1]=NewValG;
  • ImgDest->ucBits[(i+j*Width)*4+2]=NewValR;
  • break;
  • default:
  • for(k=0;k<NbNiveau;k++)
  • {
  • Diff = abs(LastVal-Niveau[k]);
  • if(Diff < Min) {
  • Min=Diff;
  • NewVal=Niveau[k];
  • }
  • }
  • ImgDest->ucBits[(i+j*Width)*4]=NewVal;
  • ImgDest->ucBits[(i+j*Width)*4+1]=NewVal;
  • ImgDest->ucBits[(i+j*Width)*4+2]=NewVal;
  • break;
  • }
  • //Gestion des bordures ==> Simple seuillage pas de diffusion de l'erreur
  • if(i>=Width-WidthSup || j>=Height-HeightSup || i<WidthSup)
  • continue;
  • CurrentCD=CD;
  • Error=LastVal-ImgDest->ucBits[(i+j*Width)*4];
  • while(CurrentCD) //BLUE
  • {
  • //On repartie l'erreur sur les pixels suivant:
  • NewVal=Limit((int)(CurrentCD->Coef * Error + ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4]));
  • ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4]=NewVal;
  • CurrentCD=(CoefDithering*)CurrentCD->Next;
  • }
  • if(Type==RGBi)
  • {
  • CurrentCD=CD;
  • Error=LastValG-ImgDest->ucBits[(i+j*Width)*4+1];
  • while(CurrentCD) //GREEN
  • {
  • //On repartie l'erreur sur les pixels suivant:
  • NewVal=Limit((int)(CurrentCD->Coef * Error + ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+1]));
  • ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+1]=NewVal;
  • CurrentCD=(CoefDithering*)CurrentCD->Next;
  • }
  • CurrentCD=CD;
  • Error=LastValR-ImgDest->ucBits[(i+j*Width)*4+2];
  • while(CurrentCD) //RED
  • {
  • //On repartie l'erreur sur les pixels suivant:
  • NewVal=Limit((int)(CurrentCD->Coef * Error + ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+2]));
  • ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+2]=NewVal;
  • CurrentCD=(CoefDithering*)CurrentCD->Next;
  • }
  • }
  • }
  • while(CD) //liberation de la memoire
  • {
  • CurrentCD=(CoefDithering*)CD->Next;
  • delete CD;
  • CD=CurrentCD;
  • }
  • if(Type==GRAY)
  • ImgDest->ImgType=GRAY;
  • if(Type==GRAY && NbNiveau==2 && Niveau[0]==0 && Niveau[1]==255)
  • ImgDest->ImgType=BIN;
  • SetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits);
  • return 1;
  • }
//*********************************************************************************
//Auteur : MORARD Vincent		
//Date   : 10 octobre 2007
//MAJ    : 29  avril    2008
//Version: 2.0
//Contact: vincent.morard@cpe.fr
//Website: http://pistol.petesampras.free.fr
//*********************************************************************************

#include "Cimage.h"




typedef struct TAG_CoefDithering
{
	int Offx,Offy;
	double Coef;
	void *Next;
}CoefDithering;


//******************************************************************************
//Add  : Ajout d'un element 
//
//INPUT
//-- CD adresse du premier element
//-- Offx,Offy,Coef : Info de l'element
//******************************************************************************
void Add(CoefDithering **CD,int Offx,int Offy,double Coef)
{
	CoefDithering *Current=new CoefDithering;
	Current->Offx=Offx;
	Current->Offy=Offy;
	Current->Coef=Coef;
	Current->Next=NULL;
	if(*CD==NULL) 		//First
		*CD=Current;
	else {
		CoefDithering *Search=*CD;
		while(Search->Next)Search=(CoefDithering*)Search->Next;
		Search->Next=Current;
	}
}



//******************************************************************************************
//DitherMethod  : Effectue le chainage des coefficients suivant la methode desire
//
//INPUT
//-- Method : Methode desire : Floyd_Steinberg ou Bill_Atkinson ou Stucki ou Burkes ou Morard
//-- CD     : Adresse du premier element 
//OUPUT
//-- WidthSup: Nombre de pixel qui sortiront de l'image en largeur
//-- HeightSup:Nombre de pixel qui sortiront de l'image en haUteur
//*******************************************************************************************
void DitherMethod(int Method,CoefDithering **CD,int *WidthSup,int *HeightSup)
{
	switch(Method)
	{	
	//The Floyd-Steinberg filter
	//          *   7
	//      3   5   1     (1/16)
	case Floyd_Steinberg:
		Add(CD,1 ,0 ,7.0/16.0);
		Add(CD,-1,1 ,3.0/16.0);
		Add(CD,0 ,1 ,5.0/16.0);
		Add(CD,1 ,1 ,1.0/16.0);
		
		//Pour ne pas sortir de l'image.
		*WidthSup = 1;
		*HeightSup= 1;
	break;

	//Bill Atkinson dithering
	//	*	1/8	1/8
	//	1/8	1/8	1/8
	//		1/8 
	case Bill_Atkinson:
		Add(CD,1 ,0 ,1.0/8.0);
		Add(CD,2 ,0 ,1.0/8.0);
		Add(CD,0,1 ,1.0/8.0);
		Add(CD,1 ,1 ,1.0/8.0);
		Add(CD,2 ,1 ,1.0/8.0);
		Add(CD,1 ,2 ,1.0/8.0);
		
		//Pour ne pas sortir de l'image.
		*WidthSup = 2;
		*HeightSup= 2;
		break;

	//The Jarvis, Judice, and Ninke filter
	//             *   7   5 
	//     3   5   7   5   3
	//     1   3   5   3   1   (1/48)
	case Jarvis_Judice_Ninke:
		Add(CD,1 ,0 ,	7.0/48.0);
		Add(CD,2 ,0 ,	5.0/48.0);
		Add(CD,-2,1 ,	3.0/48.0);
		Add(CD,-1,1 ,	5.0/48.0);
		Add(CD,0 ,1 ,	7.0/48.0);
		Add(CD,1 ,1 ,	5.0/48.0);
		Add(CD,2 ,1 ,	3.0/48.0);
		
		Add(CD,-2,2 ,	1.0/48.0);
		Add(CD,-1,2 ,	3.0/48.0);
		Add(CD,0 ,2 ,	5.0/48.0);
		Add(CD,1 ,2 ,	3.0/48.0);
		Add(CD,2 ,2 ,	1.0/48.0);

		//Pour ne pas sortir de l'image.
		*WidthSup = 2;
		*HeightSup= 2;
		break;


	//The Stucki filter
	//             *   8   4
	//     2   4   8   4   2
	//     1   2   4   2   1   (1/42)
	case Stucki:
		Add(CD,1 ,0 ,	8.0/42.0);
		Add(CD,2 ,0 ,	4.0/42.0);

		Add(CD,-2,1 ,	2.0/42.0);
		Add(CD,-1,1 ,	3.0/42.0);
		Add(CD,0 ,1 ,	8.0/42.0);
		Add(CD,1 ,1 ,	4.0/42.0);
		Add(CD,2 ,1 ,	2.0/42.0);

		Add(CD,-2,2 ,	1.0/42.0);
		Add(CD,-1,2 ,	2.0/42.0);
		Add(CD,0 ,2 ,	4.0/42.0);
		Add(CD,1 ,2 ,	2.0/42.0);
		Add(CD,2 ,2 ,	1.0/42.0);

		//Pour ne pas sortir de l'image.
		*WidthSup = 2;
		*HeightSup= 2;

		break;

	//The Burkes filter
	//             *   8   4
	//     2   4   8   4   2	(1/32)
	case Burkes: 
		Add(CD,1 ,0 ,	8.0/32.0);
		Add(CD,2 ,0 ,	4.0/32.0);

		Add(CD,-2,1 ,	2.0/32.0);
		Add(CD,-1,1 ,	3.0/32.0);
		Add(CD,0 ,1 ,	8.0/32.0);
		Add(CD,1 ,1 ,	4.0/32.0);
		Add(CD,2 ,1 ,	2.0/32.0);

		//Pour ne pas sortir de l'image.
		*WidthSup = 2;
		*HeightSup= 1;

		break;

	//The Sierra filters
    //        *   5   3                  The Sierra3 filter
    //2   4   5   4   2
    //    2   3   2       (1/32)
	case Sierra:
		Add(CD,1 ,0 ,	5.0/32.0);
		Add(CD,2 ,0 ,	3.0/32.0);

		Add(CD,-2 ,1 ,	2.0/32.0);
		Add(CD,-1 ,1 ,	4.0/32.0);
		Add(CD,0 ,1 ,   5.0/32.0);
		Add(CD,1 ,1 ,	4.0/32.0);
		Add(CD,2 ,1 ,	2.0/32.0);

		Add(CD,-1 ,2 ,	2.0/32.0);
		Add(CD,0 ,2 ,	3.0/32.0);
		Add(CD,1 ,2 ,	2.0/32.0);

		//Pour ne pas sortir de l'image.
		*WidthSup = 2;
		*HeightSup= 2;

		break;


	// *   2                          The Sierra-2-4A filter
    // 1   1               (1/4)
	case Sierra_Lite:

		Add(CD,1 ,0 ,	2.0/4.0);

		Add(CD,0 ,1 ,	1.0/32.0);
		Add(CD,1 ,1 ,	1.0/32.0);
	
		//Pour ne pas sortir de l'image.
		*WidthSup = 1;
		*HeightSup= 1;
		break;

		//		 *	 1	 2 
		//4	 2	 1	 2	 4
		//8  4   2	 4	 8			  /42
	case Morard:

		Add(CD,1 ,0 ,	1.0/42.0);
		Add(CD,2 ,0 ,	2.0/42.0);

		Add(CD,-2 ,1 ,	4.0/42.0);
		Add(CD,-1 ,1 ,	3.0/42.0);
		Add(CD,0 ,1 ,   1.0/42.0);
		Add(CD,1 ,1 ,	3.0/42.0);
		Add(CD,2 ,1 ,	4.0/42.0);

		Add(CD,-2 ,2 ,	8.0/42.0);
		Add(CD,-1 ,2 ,	4.0/42.0);
		Add(CD,0 ,2 ,	2.0/42.0);
		Add(CD,1 ,2 ,	4.0/42.0);
		Add(CD,2 ,2 ,	8.0/42.0);

		//Pour ne pas sortir de l'image.
		*WidthSup = 2;
		*HeightSup= 2;
		break;


	}
}


//*********************************************************************************************************************
//DITHERING
//
//INPUT
//--Method  :Si Method <=0 ou >8 alors il n'y a pas de diffusion d'erreur => on prend la valeur du pixel le plus proche
//	     Floyd_Steinberg ou Bill_Atkinson ou Stucki	ou Burkes ou Morard
//--Type    :si RGBi	:On effectuera la diffusion d'erreur sur les 3 canaux de facon independante 
//	       GRAY    :On convertie l'image en niveau de gris puis on effectue la diffusion d'erreur
//--Niveau  :tableau de int rassemblant tous les niveaux de sortie de l'image
//--NbNiveau:Nombre d'element du tableau niveau
//--ImgDest :Image ou sera stoker le traitement. Si 0 sera stoker dans l'image source 
//
//OUTPUT 
//1 = reussit, 0 = echec
//**********************************************************************************************************************  
bool CImage::Dithering(int Type,int Method,int *Niveau,int NbNiveau,CImage *ImgDest)
{
	
	
	if(hBmp==0){
		MessageBox(NULL,"Dither : L'image source est vide",
					NULL,MB_OK|MB_ICONWARNING);
		return 0;
	}
	
	if(ImgDest!=0 && ImgDest!=this)
		ImgDest->Copy(this);
	if(ImgDest==0)
		ImgDest=this;

	if(ImgType == GRAY)
		Type=GRAY;
	//Préparation de la diffusion suivant la méthode retenu.
	int WidthSup,HeightSup;
	CoefDithering *CD=NULL,*CurrentCD=NULL;
	DitherMethod(Method,&CD,&WidthSup,&HeightSup);


	//recupération des pixels
	GetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits);
	
	int i,j,Error,LastVal,Min,NewVal,k,Diff;
	
	int LastValR,LastValG,DiffR,DiffG,NewValR,NewValG,MinR,MinG;		//Si RGB

	for(j=0;j<Height;j++)
		for(i=0;i<Width;i++) 
		{	
			LastVal=ImgDest->ucBits[(i+j*Width)*4];
			Min=256;

			switch(Type) 
			{
				case RGBi:
					MinR=256;
					MinG=256;
					LastValR=ImgDest->ucBits[(i+j*Width)*4+2];
					LastValG=ImgDest->ucBits[(i+j*Width)*4+1];
					for(k=0;k<NbNiveau;k++) 
					{	
						Diff = abs(LastVal-Niveau[k]);
						DiffG = abs(LastValG-Niveau[k]);
						DiffR = abs(LastValR-Niveau[k]);
						if(DiffR < MinR) {
							MinR=DiffR;
							NewValR=Niveau[k];
						}
						if(DiffG < MinG) {
							MinG=DiffG;
							NewValG=Niveau[k];
						}
						if(Diff < Min) {
							Min=Diff;
							NewVal=Niveau[k];
						}
					}
					ImgDest->ucBits[(i+j*Width)*4]=NewVal;
					ImgDest->ucBits[(i+j*Width)*4+1]=NewValG;
					ImgDest->ucBits[(i+j*Width)*4+2]=NewValR;
					break;
				default:
					for(k=0;k<NbNiveau;k++) 
					{	
						Diff = abs(LastVal-Niveau[k]);
						if(Diff < Min) {
							Min=Diff;
							NewVal=Niveau[k];
						}
					}
					ImgDest->ucBits[(i+j*Width)*4]=NewVal;
					ImgDest->ucBits[(i+j*Width)*4+1]=NewVal;
					ImgDest->ucBits[(i+j*Width)*4+2]=NewVal;
					break;
			}
			
			
			
			
			

			//Gestion des bordures ==> Simple seuillage pas de diffusion de l'erreur
			if(i>=Width-WidthSup || j>=Height-HeightSup || i<WidthSup) 
				continue;
		


			CurrentCD=CD;
			Error=LastVal-ImgDest->ucBits[(i+j*Width)*4];
			

			while(CurrentCD)			//BLUE
			{
				//On repartie l'erreur sur les pixels suivant:
				NewVal=Limit((int)(CurrentCD->Coef * Error + ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4]));
				ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4]=NewVal;

				CurrentCD=(CoefDithering*)CurrentCD->Next;
			}

			
			
			if(Type==RGBi)
			{
				CurrentCD=CD;
				Error=LastValG-ImgDest->ucBits[(i+j*Width)*4+1];
				while(CurrentCD)			//GREEN
				{
					
					//On repartie l'erreur sur les pixels suivant:
					NewVal=Limit((int)(CurrentCD->Coef * Error + ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+1]));
					ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+1]=NewVal;

					CurrentCD=(CoefDithering*)CurrentCD->Next;
				}

				CurrentCD=CD;
				Error=LastValR-ImgDest->ucBits[(i+j*Width)*4+2];
				while(CurrentCD)			//RED
				{
					
					//On repartie l'erreur sur les pixels suivant:
					NewVal=Limit((int)(CurrentCD->Coef * Error + ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+2]));
					ImgDest->ucBits[(i+CurrentCD->Offx+(j+CurrentCD->Offy)*Width)*4+2]=NewVal;

					CurrentCD=(CoefDithering*)CurrentCD->Next;
				}
			}
		}
	
	
	while(CD)			//liberation de la memoire
	{
		CurrentCD=(CoefDithering*)CD->Next;
		delete CD;
		CD=CurrentCD;
	}
	if(Type==GRAY)
		ImgDest->ImgType=GRAY;
	if(Type==GRAY && NbNiveau==2 && Niveau[0]==0 && Niveau[1]==255)
		ImgDest->ImgType=BIN;
	SetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits);
	return 1;
}

Conclusion

J'aimerai si possible avoir des feedback sur l'interface créé. Si vous avez des idées d'amélioration ou autre n'hésiter pas à laisser vos messages.

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

  • signaler à un administrateur
    Commentaire de mustaphaham2005 le 30/04/2008 15:38:25

    Bonjour , je trouve ton deuxième applications riche en information mais je trouve pas ton fichier ImAnalyse.ex_;
    j'ai pas pu voir l'interface exactement sous VC++ comment ça marche .
    A+

  • signaler à un administrateur
    Commentaire de Pistol_Pete le 30/04/2008 18:56:47

    Salut
    Pour tester directement l'application sans recompiler, j'ai mis le fichier ImAnalyse.ex_ à renommer en ImAnalyse.exe pour l'exécuter.
    Si tu veux compiler mon projet, tu as juste a ouvrir le .vcproj et a compiler. Devrait aller tout seul.

    A+

  • signaler à un administrateur
    Commentaire de mustaphaham2005 le 30/04/2008 23:30:37

    Slt ,ton application cette fois elle est parfaite , ce que je te propose est d'ajouté quelque outils de calcul par exemple pouvoir trace des droites sur une image pour déterminer une Angle bien précise sur l'image est d'affiche l'angle comme ta fais pour les coordonnées des pixels .
    A+  

  • signaler à un administrateur
    Commentaire de Pistol_Pete le 01/05/2008 12:34:02

    Merci Mustaphaham pour ton commentaire.

    Malheureusement mon application n'est pas encore parfaite, mais je commence a etre tres fier de ce projet.
    Pour ta proposition, je vais y penser. Ca me parait une tres bonne idees, de mesurer des angles, des distances sur une image.  
    Merci pour la proposition.

    A+

  • signaler à un administrateur
    Commentaire de abtazer le 05/05/2008 18:07:42

    Bonjour,
    Bizard bizard, ton appli ne s'exécute pas chez moi.
    Si je renomme le ex_ en exe il ya un bug.
    Si je compile le source et l'execute il ya aussi un bug à la ligne 99 de main.cpp
             ShowWindow(hwndMain, nCmdShow);
    J'utilise :
    XP sp2
    VC8.00 SP1

  • signaler à un administrateur
    Commentaire de Pistol_Pete le 06/05/2008 13:08:40

    Salut

    J'ai testé mon appli sur Vista et XP et il n'y a eu aucun probleme et ce, sur pas mal de PC.
    Pour la compilation, quel est le message d'erreur qui apparait sur ShowWindow?
    Tu as la version express de VC8 ?

    A+

  • signaler à un administrateur
    Commentaire de hhabla le 17/06/2008 10:52:40

    Slt Pistol_Pete, moi j'ai 17 erreurs en exécutant ImAnalyseBeta2!!!???
    fatal error C1083: Impossible d'ouvrir le fichier include : 'CImage.h' : No such file or directory
    alors qu'il y est avec les autres fichiers entête??

  • signaler à un administrateur
    Commentaire de hhabla le 17/06/2008 11:08:25

    Pb résolu, j'ai rechargé le répertoire, par contre je ne peux ouvrir aucun fichier image autre que bmp?! et ça j'ai essayé plusieurs fois!?

  • signaler à un administrateur
    Commentaire de Pistol_Pete le 17/06/2008 22:56:21

    Salut

    Oui il y a un bogue dans la fonction
    PictureToBitmap()
    Il faut corriger la ligne
    hr = CreateStreamOnHGlobal(hgbl, TRUE, &stream);
    par
    hr = CreateStreamOnHGlobal(hgbl, FALSE, &stream);

    Sinon il y a un problème de libération de la mémoire : le HGLOBAL était libéré en même temps que le stream et je tentait de libérer le HGLOBAL.

    La tu peux ouvrir les JPG et GIF en plus des BMP

    Je ferai une mise à jour de la source dans pas très longtemps.
    Merci
    A+

Ajouter un commentaire