Imanalyse : logiciel de traitement de l'image + dithering [win32]

Soyez le premier à donner votre avis sur cette source.

Vue 11 760 fois - Téléchargée 1 164 fois

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

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

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Salut
Pour la version "express", il faut que tu installes le SDK win32
http://www.cppfrance.com/codes/PROGRAMMER-WIN32-AVEC-VISUAL-CPLUSPLUS-EXPRESS-TUTORIAL_38359.aspx

Puis tu compiles le programme.
A+
Messages postés
1
Date d'inscription
mercredi 20 avril 2011
Statut
Membre
Dernière intervention
21 avril 2011

bonjour tous le monde
j'ai un problème: j'ai téléchargée le file zip et j'ai exécutée ce projet sur la microsoft visual c++ 2010 express et un msg apparaitre me demande de la conversion et j'ai fait la conversion et normalement cava mais j'ai aucune idée sur l'exécution comment sa marche ?
slp j'ai cherche une information
Messages postés
1
Date d'inscription
jeudi 17 juin 2010
Statut
Membre
Dernière intervention
17 juin 2010

bonjours
je cherhce l'algorithme qui transforme la temperature en une image couleur, parceque le capteur bolometre donne une temperatue et comment on peut convrtie cette tempertaure en image (algorithme)
Messages postés
21
Date d'inscription
vendredi 7 décembre 2012
Statut
Membre
Dernière intervention
3 janvier 2009

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.
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
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+
Afficher les 14 commentaires

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.