|
Trouver une ressource
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
- /***********************************************************************************
- // 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
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
Sources du même auteur
Sources de la même categorie
Sources en rapport avec celle ci
Commentaires et avis
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
|
Téléchargements
Logiciels à télécharger sur le même thème :
Comparez les prix Nouvelle version
|