Mosaique, Voronoi

1  /***********************************************************************************  
2      ImAnalyse : software in image processing and image analysis 
3     
4      Copyright (C) 27 avril 2008  <Vincent MORARD> 
5    Version: 2.0 
6      Contact: vincent<POINT>morard<AROBAS>cpe<POINT>fr 
7    Website: http://pistol.petesampras.free.fr 
8   
9      This program is free software: you can redistribute it and/or modify 
10      it under the terms of the GNU General Public License as published by 
11      the Free Software Foundation, either version 3 of the License, or 
12      (at your option) any later version. 
13   
14      This program is distributed in the hope that it will be useful, 
15      but WITHOUT ANY WARRANTY; without even the implied warranty of 
16      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
17      GNU General Public License for more details. 
18   
19      You should have received a copy of the GNU General Public License 
20      along with this program.  If not, see <http://www.gnu.org/licenses/ 
21  **********************************************************************************/ 
22   
23  #include "CImage.h" 
24   
25  typedef struct tag_Pix 
26  { 
27    int X,Y; 
28    void *Next; 
29   
30  }Pix; 
31   
32   
33  bool CImage::Mosaique(int NbPixel,int Bordure,CImage *ImgDest) 
34  { 
35    if(hBmp==0){ 
36      MessageBox(NULL," Mosaique : L'image source est vide", 
37        NULL,MB_OK|MB_ICONWARNING); 
38      return 0; 
39    } 
40   
41    if(ImgDest!=0 && ImgDest!=this) 
42      ImgDest->Copy(this); 
43    if(ImgDest==0) 
44      ImgDest=this; 
45   
46    if(NbPixel==1)return 1;    //Rien a faire 
47   
48   
49   
50    //recupération des pixels 
51    GetBitmapBits(hBmp,Width*Height*4,ucBits); 
52   
53   
54   
55    int i,j,k,l; 
56    double MoyenneR,MoyenneG,MoyenneB,Nb; 
57   
58   
59    for(i=0;i<Width;i+=NbPixel) 
60    { 
61      for(j=0;j<Height;j+=NbPixel) 
62      { 
63        MoyenneR=0; 
64        MoyenneG=0; 
65        MoyenneB=0; 
66        Nb=0; 
67   
68        //Mean value of the Mosaique 
69        for(k=0;k<NbPixel;k++) 
70        { 
71          for(l=0;l<NbPixel;l++) 
72          { 
73            if(i+k < Width && j+l <Height) 
74            { 
75              MoyenneR+=GetPixel(i+k,j+l,RED); 
76              MoyenneG+=GetPixel(i+k,j+l,GREEN); 
77              MoyenneB+=GetPixel(i+k,j+l,BLUE); 
78              Nb++; 
79            } 
80   
81          } 
82        } 
83        if(Nb==0) 
84          return 0; 
85   
86        MoyenneR/=Nb; 
87        MoyenneG/=Nb; 
88        MoyenneB/=Nb; 
89   
90   
91        //Output without the boundaries 
92        for(k=1;k<NbPixel-1;k++) 
93          for(l=1;l<NbPixel-1;l++) 
94            if(i+k < Width && j+l <Height) 
95              ImgDest->SetPixel(i+k,j+l,(int)MoyenneR,(int)MoyenneG,(int)MoyenneB); 
96   
97        //Compute the boundaries     
98        for(k=0;k<NbPixel;k++) 
99        { 
100          if(i+k < Width ) 
101          { 
102            if(Bordure<0 || Bordure > 255) 
103              ImgDest->SetPixel(i+k,j,(int)MoyenneR,(int)MoyenneG,(int)MoyenneB); 
104            else 
105              ImgDest->SetPixel(i+k,j,Bordure,Bordure,Bordure); 
106          } 
107        } 
108        for(l=0;l<NbPixel;l++) 
109        { 
110          if(j+l < Height) 
111          { 
112            if(Bordure<0 || Bordure > 255) 
113              ImgDest->SetPixel(i,j+l,(int)MoyenneR,(int)MoyenneG,(int)MoyenneB); 
114            else 
115              ImgDest->SetPixel(i,j+l,Bordure,Bordure,Bordure); 
116          } 
117        } 
118   
119        for(k=0;k<NbPixel;k++) 
120        { 
121          if(i+k < Width && j+NbPixel < Height) 
122          { 
123            if(Bordure<0 || Bordure > 255) 
124              ImgDest->SetPixel(i+k,j+NbPixel-1,(int)MoyenneR,(int)MoyenneG,(int)MoyenneB); 
125            else 
126              ImgDest->SetPixel(i+k,j+NbPixel-1,Bordure,Bordure,Bordure); 
127          } 
128        } 
129        for(l=0;l<NbPixel;l++) 
130        { 
131          if(j+l < Height && i+NbPixel < Width) 
132          { 
133            if(Bordure<0 || Bordure > 255) 
134              ImgDest->SetPixel(i+NbPixel-1,j+l,(int)MoyenneR,(int)MoyenneG,(int)MoyenneB); 
135            else 
136              ImgDest->SetPixel(i+NbPixel-1,j+l,Bordure,Bordure,Bordure); 
137          } 
138        } 
139   
140      } 
141   
142    } 
143    SetBitmapBits(ImgDest->hBmp,Width*Height*4,ImgDest->ucBits); 
144    return 1; 
145  } 
146   
147   
148   
149  void Rep(int Repartition,int Width,int Height,int *X,int *Y) 
150  { 
151    bool Fin; 
152    double x,y,P,sigma=2; 
153   
154    if(Repartition==UNIFORME) 
155    { 
156      *X=rand()%Width; 
157      *Y=rand()%Height; 
158    } 
159    else 
160    { 
161      Fin=0; 
162      do 
163      { 
164        x=((rand()%3000)/300.0)-5; //on choisi un x entre -5 et 5 avec un pas faible 
165        P=(exp((-0.5*x*x)/(sigma*sigma)))/(sqrt(2*3.14)*sigma); //on calcule sa fonction de répartition 
166   
167        //on tire au hazard un nombre entre [0 et 1]. Si ce nombre est inférieur a P 
168        //on accepte ce point sinon, on le refuse 
169   
170        //le centre de la fenetre est le point de coord 0,0 
171        if( ((rand()%1000)/1000.0) <= P) 
172        { 
173          Fin=true; 
174          if(x>0) 
175            x=x*Width/10+Width/2; //x[Width/2 , Width] 
176          else 
177            x=Width/2-((-x)*Width/10); //x[0,Width/2] 
178        } 
179      } 
180      while(!Fin); 
181      Fin=0; 
182      do 
183      { 
184        y=((rand()%3000)/300.0)-5; //on choisi un x entre -5 et 5 avec un pas faible 
185        P=(exp((-0.5*y*y)/(sigma*sigma)))/(sqrt(2*3.14)*sigma); //on calcule sa fonction de répartition 
186   
187        //on tire au hazard un nombre entre [0 et 1]. Si ce nombre est inférieur a P 
188        //on accepte ce point sinon, on le refuse 
189   
190        //le centre de la fenetre est le point de coord 0,0 
191        if( ((rand()%1000)/1000.0) <= P) 
192        { 
193          Fin=true; 
194          if(y>0) 
195            y=y*Height/10+Height/2; //x[Width/2 , Width] 
196          else 
197            y=Height/2-((-y)*Height/10); //x[0,Width/2] 
198        } 
199      } 
200      while(!Fin); 
201   
202      *X=(int)x; 
203      *Y=(int)y; 
204   
205    } 
206  } 
207   
208   
209  bool CImage::Voronoi(int Type,int NbRegion,int Distance,int Repartition,CImage *ImgDest) 
210  { 
211    if(hBmp==0){ 
212      MessageBox(NULL,"Voronoi : L'image source est vide", 
213            NULL,MB_OK|MB_ICONWARNING); 
214      return 0; 
215    } 
216   
217    if(ImgDest!=0 && ImgDest!=this) 
218      ImgDest->Copy(this); 
219   
220    if(ImgDest==0) 
221      ImgDest=this; 
222   
223   
224    Pix *AllPix=new Pix[Width*Height]; 
225    Pix **Zone=new Pix*[NbRegion]; 
226   
227    Pix *Region=new Pix[NbRegion]; 
228    Pix *Current; 
229   
230   
231   
232   
233    int i,j,k,Pos,Num,Cpt; 
234    double MinDist,Dist,Moy,MoyG,MoyR; 
235   
236    //recupération des pixels 
237    GetBitmapBits(hBmp,Width*Height*4,ucBits); 
238   
239   
240   
241    for(i=0;i<NbRegion;i++) 
242    { 
243        Zone[i]=0; 
244        Rep(Repartition,Width,Height,&Region[i].X,&Region[i].Y); 
245    } 
246   
247    for(i=0;i<Width;i++) 
248      for(j=0;j<Height;j++) 
249      { 
250        Pos=i+j*Width; 
251        AllPix[Pos].X=i; 
252        AllPix[Pos].Y=j; 
253   
254        if(Distance!=MANHATTAN) 
255          MinDist=sqrt(((Region[0].X-(double)i)*(Region[0].X-(double)i))+((Region[0].Y-(double)j)*(Region[0].Y-(double)j))); 
256        else 
257          MinDist=abs(Region[0].X-(double)i)+abs(Region[0].Y-(double)j); 
258        Num=0; 
259   
260        for(k=1;k<NbRegion;k++) 
261        { 
262          if(Distance!=MANHATTAN) 
263            Dist=sqrt(((Region[k].X-(double)i)*(Region[k].X-(double)i))+((Region[k].Y-(double)j)*(Region[k].Y-(double)j))); 
264          else 
265            Dist=abs(Region[k].X-(double)i)+abs(Region[k].Y-(double)j); 
266   
267          if(Dist<MinDist) 
268          { 
269            MinDist=Dist; 
270            Num=k; 
271          } 
272        } 
273        if(Zone[Num]==0)    //first element of the region 
274          AllPix[Pos].Next=0; 
275        else 
276          AllPix[Pos].Next=Zone[Num]; 
277   
278        Zone[Num]=&AllPix[Pos]; 
279   
280      } 
281   
282   
283      for(k=0;k<NbRegion;k++) 
284      { 
285        Moy=0; 
286        MoyR=0; 
287        MoyG=0; 
288        Cpt=0; 
289        Current=Zone[k]; 
290        while(Current) 
291        { 
292          Pos=(Current->X+Current->Y*Width)*4; 
293          switch(Type) 
294          { 
295          case RED:Moy+=ucBits[Pos+2];break; 
296          case GREEN:Moy+=ucBits[Pos+1];break; 
297          case BLUE:Moy+=ucBits[Pos];break; 
298          case GRAY:Moy+=(int)((ucBits[Pos]+ucBits[Pos+1]+ucBits[Pos]+2)/3);break; 
299          case RGBi: 
300            Moy+=ucBits[Pos]; 
301            MoyG+=ucBits[Pos+1]; 
302            MoyR+=ucBits[Pos+2]; 
303            break; 
304          } 
305          Cpt++; 
306          Current=(Pix*)Current->Next; 
307        } 
308        if(Cpt){ 
309          if(Type==RGBi) 
310          { 
311            Moy/=Cpt; 
312            MoyG/=Cpt; 
313            MoyR/=Cpt; 
314          } 
315          else 
316            Moy/=Cpt; 
317        } 
318        Current=Zone[k]; 
319        while(Current) 
320        { 
321          Pos=(Current->X+Current->Y*Width)*4; 
322          if(Type==RGBi) 
323          { 
324            ImgDest->ucBits[Pos]=(int)Moy; 
325            ImgDest->ucBits[Pos+1]=(int)MoyG; 
326            ImgDest->ucBits[Pos+2]=(int)MoyR; 
327          } 
328          else 
329          { 
330            ImgDest->ucBits[Pos]=(int)Moy; 
331            ImgDest->ucBits[Pos+1]=(int)Moy; 
332            ImgDest->ucBits[Pos+2]=(int)Moy; 
333          } 
334   
335          Current=(Pix*)Current->Next; 
336        } 
337      } 
338   
339    SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); 
340    if(Type!=RGBi) 
341      ImgType=GRAY; 
342    delete []AllPix; 
343    delete []Zone; 
344    delete []Region; 
345   
346    return 1; 
347   
348  } 

lien1 lien2 lien3