Trouver une ressource (Nouvelle version du moteur, plus rapide & pertinent, essayez le !)
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
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.
Sources de la même categorie
Commentaires
Discussions en rapport avec ce code source
|