Median_cpp
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 |
#include "../CImage.h" |
23 |
|
24 |
int Tri(int *t,int Size,int NumPixel) |
25 |
{ |
26 |
|
27 |
int i,j; |
28 |
int tmp = 0; |
29 |
bool en_desordre = TRUE; |
30 |
|
31 |
for(i = 0 ; (i < Size) && en_desordre; i++) |
32 |
{ |
33 |
en_desordre = FALSE; |
34 |
for(j = 1 ; j < Size - i ; j++) |
35 |
{ |
36 |
if(t[j] < t[j-1]) |
37 |
{ |
38 |
tmp = t[j-1]; |
39 |
t[j-1] = t[j]; |
40 |
t[j] = tmp; |
41 |
en_desordre = TRUE; |
42 |
} |
43 |
} |
44 |
} |
45 |
return t[NumPixel]; |
46 |
} |
47 |
double Tri(double *t,int Size,int NumPixel) |
48 |
{ |
49 |
|
50 |
int i,j; |
51 |
double tmp = 0; |
52 |
bool en_desordre = TRUE; |
53 |
|
54 |
for(i = 0 ; (i < Size) && en_desordre; i++) |
55 |
{ |
56 |
en_desordre = FALSE; |
57 |
for(j = 1 ; j < Size - i ; j++) |
58 |
{ |
59 |
if(t[j] < t[j-1]) |
60 |
{ |
61 |
tmp = t[j-1]; |
62 |
t[j-1] = t[j]; |
63 |
t[j] = tmp; |
64 |
en_desordre = TRUE; |
65 |
} |
66 |
} |
67 |
} |
68 |
return t[NumPixel]; |
69 |
} |
70 |
|
71 |
|
72 |
bool CImage::Median(int Type,int n,int Pourcentage,CImage *ImgDest) |
73 |
{ |
74 |
if(hBmp==0){ |
75 |
MessageBox(NULL,"Median : L'image source est vide", |
76 |
NULL,MB_OK|MB_ICONWARNING); |
77 |
return 0; |
78 |
} |
79 |
int NumPixel = n*n*Pourcentage/100; |
80 |
if(NumPixel<0 ||NumPixel > n*n){ |
81 |
MessageBox(NULL,"Median : On doit recuperer le ième pixel: i compris entre 1 et 9", |
82 |
NULL,MB_OK|MB_ICONWARNING); |
83 |
return 0; |
84 |
} |
85 |
if(n!=3 && n!=5 && n!=7 && n!=9 && n!=11 && n!=13 && n!=15){ |
86 |
MessageBox(NULL,"Median : Taille du noyau invalide", |
87 |
NULL,MB_OK|MB_ICONWARNING); |
88 |
return 0; |
89 |
} |
90 |
|
91 |
if(ImgDest!=0 && ImgDest!=this) |
92 |
ImgDest->Copy(this); |
93 |
if(ImgDest==0) |
94 |
ImgDest=this; |
95 |
|
96 |
int i,j,k,l,*Tab; |
97 |
Tab=new int[n*n]; |
98 |
|
99 |
|
100 |
|
101 |
double *MED=new double[Width*Height]; |
102 |
|
103 |
|
104 |
double *MED_Red,*MED_Green; |
105 |
if(Type==RGBi) |
106 |
{ |
107 |
MED_Red=new double[Width*Height]; |
108 |
MED_Green=new double[Width*Height]; |
109 |
} |
110 |
|
111 |
//recupération des pixels |
112 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
113 |
|
114 |
for(i=n/2;i<Width-n/2;i++) |
115 |
for(j=n/2;j<Height-n/2;j++) |
116 |
{ |
117 |
switch(Type) |
118 |
{ |
119 |
case RGBi: |
120 |
for(k=-n/2;k<=n/2;k++) |
121 |
for(l=-n/2;l<=n/2;l++) |
122 |
Tab[l+n/2+(k+n/2)*n]=(int)GetPixel(i+k,j+l,RED); |
123 |
MED_Red[(i+j*Width)]=Tri(Tab,n*n,NumPixel); |
124 |
|
125 |
for(k=-n/2;k<=n/2;k++) |
126 |
for(l=-n/2;l<=n/2;l++) |
127 |
Tab[l+n/2+(k+n/2)*n]=(int)GetPixel(i+k,j+l,GREEN); |
128 |
MED_Green[(i+j*Width)]=Tri(Tab,n*n,NumPixel); |
129 |
|
130 |
for(k=-n/2;k<=n/2;k++) |
131 |
for(l=-n/2;l<=n/2;l++) |
132 |
Tab[l+n/2+(k+n/2)*n]=(int)GetPixel(i+k,j+l,BLUE); |
133 |
MED[(i+j*Width)]=Tri(Tab,n*n,NumPixel); |
134 |
|
135 |
|
136 |
break; |
137 |
default: |
138 |
for(k=-n/2;k<=n/2;k++) |
139 |
for(l=-n/2;l<=n/2;l++) |
140 |
Tab[l+n/2+(k+n/2)*n]=(int)GetPixel(i+k,j+l,Type); |
141 |
MED[(i+j*Width)]=Tri(Tab,n*n,NumPixel); |
142 |
break; |
143 |
} |
144 |
} |
145 |
|
146 |
switch(Type) |
147 |
{ |
148 |
case RGBi: |
149 |
ImgDest->ImgType=RGBi; |
150 |
for(i=0,j=0;i<Width*Height*4;i+=4,j++) |
151 |
{ |
152 |
ImgDest->ucBits[i]=(UCHAR)MED[j]; |
153 |
ImgDest->ucBits[i+1]=(UCHAR)MED_Green[j]; |
154 |
ImgDest->ucBits[i+2]=(UCHAR)MED_Red[j]; |
155 |
|
156 |
} |
157 |
delete []MED_Red; |
158 |
delete []MED_Green; |
159 |
|
160 |
break; |
161 |
|
162 |
default: |
163 |
ImgDest->ImgType=GRAY; |
164 |
for(i=0,j=0;i<Width*Height*4;i+=4,j++) |
165 |
{ |
166 |
ImgDest->ucBits[i]=(UCHAR)MED[j]; |
167 |
ImgDest->ucBits[i+1]=ImgDest->ucBits[i]; |
168 |
ImgDest->ucBits[i+2]=ImgDest->ucBits[i]; |
169 |
|
170 |
} |
171 |
break; |
172 |
|
173 |
|
174 |
} |
175 |
|
176 |
delete []MED; |
177 |
delete []Tab; |
178 |
|
179 |
SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); |
180 |
|
181 |
return 1; |
182 |
} |
183 |
|
184 |
|
185 |
|
186 |
bool CImage::MedianHSL(int n,int Pourcentage,CImage *ImgDest) |
187 |
{ |
188 |
|
189 |
|
190 |
if(hBmp==0){ |
191 |
MessageBox(NULL,"MedianHSL : L'image source est vide", |
192 |
NULL,MB_OK|MB_ICONWARNING); |
193 |
return 0; |
194 |
} |
195 |
if(ImgType != RGBi){ |
196 |
MessageBox(NULL,"MedianHSL : L'image doit etre une image couleur", |
197 |
NULL,MB_OK|MB_ICONWARNING); |
198 |
return 0; |
199 |
} |
200 |
|
201 |
int NumPixel = n*n*Pourcentage/100; |
202 |
if(NumPixel<0 ||NumPixel > n*n){ |
203 |
MessageBox(NULL,"Median HSL: On doit recuperer le ième pixel: i compris entre 1 et 9", |
204 |
NULL,MB_OK|MB_ICONWARNING); |
205 |
return 0; |
206 |
} |
207 |
if(n!=3 && n!=5 && n!=7 && n!=9 && n!=11 && n!=13 && n!=15){ |
208 |
MessageBox(NULL,"Median HSL: Taille du noyau invalide", |
209 |
NULL,MB_OK|MB_ICONWARNING); |
210 |
return 0; |
211 |
} |
212 |
|
213 |
if(ImgDest!=0 && ImgDest!=this) |
214 |
ImgDest->Copy(this); |
215 |
if(ImgDest==0) |
216 |
ImgDest=this; |
217 |
|
218 |
int i,j,k,l; |
219 |
double *Tab; |
220 |
|
221 |
Tab=new double[n*n]; |
222 |
double *HSL=this->RGB_to_HSL(); |
223 |
|
224 |
if(HSL==0 || Tab==0){ |
225 |
MessageBox(NULL,"Median HSL: Erreur allocation", |
226 |
NULL,MB_OK|MB_ICONWARNING); |
227 |
return 0; |
228 |
} |
229 |
//recupération des pixels |
230 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
231 |
|
232 |
for(i=n/2;i<Width-n/2;i++) { |
233 |
for(j=n/2;j<Height-n/2;j++) |
234 |
{ |
235 |
for(k=-n/2;k<=n/2;k++) |
236 |
for(l=-n/2;l<=n/2;l++) |
237 |
Tab[l+n/2+(k+n/2)*n]=(int)HSL[4*(i+k+(j+l)*Width)+2]; |
238 |
|
239 |
HSL[4*(i+j*Width)+2]=Tri(Tab,n*n,NumPixel); |
240 |
|
241 |
|
242 |
} |
243 |
} |
244 |
|
245 |
|
246 |
ImgDest->HSL_to_RGB(HSL,n/2); |
247 |
|
248 |
|
249 |
delete []Tab; |
250 |
delete []HSL; |
251 |
SetBitmapBits (ImgDest->hBmp,(Width*Height)*4,ImgDest->ucBits); |
252 |
|
253 |
return 1; |
254 |
} |
255 |
double Abs(double x) {return ((x<0)?(-x):(x));} |
256 |
|
257 |
void RGB_to_HSL2(double R,double G,double B,double *H,double *S,double *L) |
258 |
{ |
259 |
//Normalisation |
260 |
R/=255;G/=255;B/=255; |
261 |
|
262 |
double Min=min(R,min(G,B)); |
263 |
double Max=max(R,max(G,B)); |
264 |
|
265 |
*L=(Min+Max)/2; |
266 |
|
267 |
if(Abs(Max-Min) < 0.000001) { //achromatic |
268 |
*H=0;*S=0; |
269 |
} |
270 |
else |
271 |
{ |
272 |
double Delta=Max-Min; |
273 |
*S = (( *L > 0.5 ) ? ( Delta/(2-Min-Max )) : (Delta/(Max+Min))); |
274 |
|
275 |
if(Abs(R-Max)<0.000001) |
276 |
*H = (G - B) / Delta + (G < B ? 6 : 0); |
277 |
else if(Abs(G-Max)<0.000001) |
278 |
*H = (B - R) / Delta + 2; |
279 |
else if(Abs(B-Max)<0.000001) |
280 |
*H = (R - G) / Delta + 4; |
281 |
*H/=6; |
282 |
} |
283 |
*H *= 240; |
284 |
*S *= 240; |
285 |
*L *= 240; |
286 |
} |
287 |
|
288 |
double Hue_2_RGB(double v1,double v2,double vH ) //Function Hue_2_RGB |
289 |
{ |
290 |
if ( vH < 0 ) vH += 1; |
291 |
if ( vH > 1 ) vH -= 1; |
292 |
if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH ); |
293 |
if ( ( 2 * vH ) < 1 ) return ( v2 ); |
294 |
if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 0.666666 ) - vH ) * 6 ); |
295 |
return v1; |
296 |
} |
297 |
|
298 |
|
299 |
void HSL_to_RGB2(double H,double S,double L,double *R,double *G,double*B) |
300 |
{ |
301 |
double tmp1,tmp2; |
302 |
H=(double)H/239; //h,s,l compris entre 0 et 1 |
303 |
S=(double)S/240; |
304 |
L=(double)L/240; |
305 |
|
306 |
if(S==0) |
307 |
{ |
308 |
*R = 255 * L; |
309 |
*G = 255 * L; |
310 |
*B = 255 * L; |
311 |
} |
312 |
else |
313 |
{ |
314 |
if(L<0.5)tmp2 = L * (1 + S); |
315 |
else tmp2 = (L + S) - (L * S); |
316 |
tmp1=2 * L - tmp2; |
317 |
|
318 |
*R = 255 * Hue_2_RGB( tmp1, tmp2, H + ( 0.333333 ) ); |
319 |
*G = 255 * Hue_2_RGB( tmp1, tmp2, H ); |
320 |
*B = 255 * Hue_2_RGB( tmp1, tmp2, H - ( 0.333333) ); |
321 |
|
322 |
} |
323 |
} |
324 |
|
325 |
|
326 |
|
327 |
|
328 |
double *CImage::RGB_to_HSL() |
329 |
{ |
330 |
double *Tab=0; |
331 |
int i; |
332 |
double H,S,L; |
333 |
Tab=new double[Width*Height*4]; |
334 |
if(Tab==0)return NULL; |
335 |
|
336 |
//recupération des pixels |
337 |
GetBitmapBits(hBmp,Width*Height*4,ucBits); |
338 |
|
339 |
for(i=0;i<Width*Height*4;i+=4) |
340 |
{ |
341 |
RGB_to_HSL2((double)ucBits[i+2],(double)ucBits[i+1],(double)ucBits[i],&H,&S,&L); |
342 |
Tab[i]=H; |
343 |
Tab[i+1]=S; |
344 |
Tab[i+2]=L; |
345 |
|
346 |
} |
347 |
return Tab; |
348 |
|
349 |
} |
350 |
|
351 |
|
352 |
|
353 |
|
354 |
void CImage::HSL_to_RGB(double *HSL,int Boundaries) |
355 |
{ |
356 |
int i,j,Pos; |
357 |
double R,G,B; |
358 |
|
359 |
|
360 |
for(i=Boundaries;i<Width-Boundaries;i++) { |
361 |
for(j=Boundaries;j<Height-Boundaries;j++) |
362 |
{ |
363 |
Pos=4*(i+j*Width); |
364 |
HSL_to_RGB2(HSL[Pos],HSL[Pos+1],HSL[Pos+2],&R,&G,&B); |
365 |
ucBits[i]=(UCHAR)B; |
366 |
ucBits[i+1]=(UCHAR)G; |
367 |
ucBits[i+2]=(UCHAR)R; |
368 |
|
369 |
} |
370 |
} |
371 |
} |
372 |
|
373 |
|
374 |
//http://mjijackson.com/2008/02/10/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript/ |
lien1 lien2 lien3