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]


Information sur la source

Catégorie :Graphique Classé sous : ImAnalyse, traitement image, win32, dithering, filtres Niveau : Débutant Date de création : 30/04/2008 Date de mise à jour : 22/07/2008 10:02:14 Vu / téléchargé: 4 191 / 370

Note :
Aucune note

Commentaire sur cette source (11)
Ajouter un commentaire et/ou une note


Description

Cliquez pour voir la capture en taille normale
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

  • /***********************************************************************************
  • // ImAnalyse : software in image processing and image analysis
  • //
  • // Copyright (C) 10 juillet 2008 <Vincent MORARD>
  • // Version: 2.1
  • // Contact: vincent<POINT>morard<AROBAS>cpe<POINT>fr
  • // Website: http://ImAnalyse.free.fr
  • // Website: http://pistol.petesampras.free.fr
  • //
  • // This program is free software: you can redistribute it and/or modify
  • // it under the terms of the GNU General Public License as published by
  • // the Free Software Foundation, either version 3 of the License, or
  • // (at your option) any later version.
  • //
  • // This program is distributed in the hope that it will be useful,
  • // but WITHOUT ANY WARRANTY; without even the implied warranty of
  • // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  • // GNU General Public License for more details.
  • //
  • // You should have received a copy of the GNU General Public License
  • // along with this program. If not, see <http://www.gnu.org/licenses/
  • **********************************************************************************/
  • #include "Cimage.h"
  • typedef struct TAG_CoefDithering
  • {
  • int Offx,Offy;
  • double Coef;
  • void *Next;
  • }CoefDithering;
  • //******************************************************************************
  • //Add : Ajout d'un élément
  • //
  • //INPUT
  • //-- CD adresse du premier élément
  • //-- Offx,Offy,Coef : Info de l'élément
  • //******************************************************************************
  • 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;
  • }
/*********************************************************************************** 
//    ImAnalyse : software in image processing and image analysis
//	
//    Copyright (C) 10 juillet 2008  <Vincent MORARD>
//	Version: 2.1
//    Contact: vincent<POINT>morard<AROBAS>cpe<POINT>fr
//	Website: http://ImAnalyse.free.fr
//	Website: http://pistol.petesampras.free.fr
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/
**********************************************************************************/

#include "Cimage.h"




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


//******************************************************************************
//Add  : Ajout d'un élément 
//
//INPUT
//-- CD adresse du premier élément
//-- Offx,Offy,Coef : Info de l'élément
//******************************************************************************
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.


Toutes la documentation du programme est disponible en ligne : Presser 'ALT+F1' pendant l'exécution du programme ou 'Menu -> ? -> Aide en ligne'


Ou directement :     http://ImAnalyse.free.fr
 

Fichier Zip

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

Historique

22 juillet 2008 10:02:16 :
Correction d'un bogue et mise en place de l'aide en ligne sur: http://ImAnalyse.free.fr

Commentaires et avis

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+

signaler à un administrateur
Commentaire de Pistol_Pete le 22/07/2008 10:09:32

Salut
Voila le bogue corrigé. (ouverture des images jpeg et gif)

J'en profite pour vous annoncer la mise en place de l'aide en ligne sur
http://ImAnalyse.free.fr

Ou pendant l'exécution du programme ALT+F1 ou menu->?-> Aide en ligne

Vous y retrouverez toutes les possibilités du logiciel ainsi qu'une description détaillé de toutes les fonctions d'ImAnalyse. (un exemple, la description des argument de la fonction et code source)

J'attends vos commentaires...

A+

signaler à un administrateur
Commentaire de fabricelepro le 05/12/2008 20:20:17

salut
s'il te plait tu ne peux pas essayé de le compliler avec dev-c++
parce que ma machine n'est pas trés performante j'ai des problemes lorsque je veux in installer
vc++ sur ma machine.

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Win32(control) [ par NitRic ] Bonjour, pour mon premier prog Win32 en C++ j'ai décider de faire un petit NotPad sauf que la j'ai un problème:J'ai fais des menu et dans le menu Édi Où trouver le Win32 SDK ? [ par PierreP ] ... avec un help ou qqchose de ce genre qui explique comment on utilise les fonctions.Impossible de le trouver sur Le site de Microsoft ! changé curseur dans application Win32 [ par Stoomm ] Bonjour, j'aimerais chargé un curseur autre que celui par défault dans une appli Win32.Quelqu'un peut il me donner la marche à suivre svp.Merci d'avan changé curseur dans application Win32 [ par Stoomm ] Bonjour, j'aimerais chargé un curseur autre que celui par défault dans une appli Win32.Quelqu'un peut il me donner la marche à suivre svp.Merci d'avan demande librairie gtk pour win32 [ par francky ] quelqu'un pourrait-il me donner la librairie gtk.h?ou alors des liens vers des exemples d'interface graphique réaliséemerci d'avance. lien vers librairie glut pour win32 [ par francky ] m'étant fait déja passé pour un con ne sachant pas lire,pour tout ceux qui débutent et ne trouve pas la librairie glut pour windows permettant de cree gtk & win32 & Visual C++ [ par Paisible ] je vais peut être me faire jeter, mais bon...j'ai cherché dans le forum... et impossible de trouver la trace d'un quelconque post concernant la config win32 et sous-classement [ par mozert ] hi.mmm... mwai.. voila mon probleme..le sous-classement (subclassing)..est-il possible de sous-classer une fenetre appartenant à un processus differen Bouton en Win32 [ par punx120 ] J'aimearis savoir comment faire pour faire un bouton avecun bitmap, comme on peut le faire avec CBitmapButton, mais en win32merci @ + Win32 [ par NettoyeurFantome ] Je cherche des cours sur l'API Win32.@+Julien IBARZ alias [Nettoyeur]Fantome


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Comparez les prix Nouvelle version

Photothèque Nouveau !



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
Temps d'éxécution de la page : 0,406 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.