]> Creatis software - clitk.git/blob - utilities/CxImage/ximahist.cpp
2b47d17d5e79eea1bb47610ac5ce84b156368a61
[clitk.git] / utilities / CxImage / ximahist.cpp
1 // xImaHist.cpp : histogram functions\r
2 /* 28/01/2004 v1.00 - www.xdp.it\r
3  * CxImage version 6.0.0 02/Feb/2008\r
4  */\r
5 \r
6 #include "ximage.h"\r
7 \r
8 #if CXIMAGE_SUPPORT_DSP\r
9 \r
10 ////////////////////////////////////////////////////////////////////////////////\r
11 long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace)\r
12 {\r
13         if (!pDib) return 0;\r
14         RGBQUAD color;\r
15 \r
16         if (red) memset(red,0,256*sizeof(long));\r
17         if (green) memset(green,0,256*sizeof(long));\r
18         if (blue) memset(blue,0,256*sizeof(long));\r
19         if (gray) memset(gray,0,256*sizeof(long));\r
20 \r
21         long xmin,xmax,ymin,ymax;\r
22         if (pSelection){\r
23                 xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right;\r
24                 ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top;\r
25         } else {\r
26                 xmin = ymin = 0;\r
27                 xmax = head.biWidth; ymax=head.biHeight;\r
28         }\r
29 \r
30         for(long y=ymin; y<ymax; y++){\r
31                 for(long x=xmin; x<xmax; x++){\r
32 #if CXIMAGE_SUPPORT_SELECTION\r
33                         if (BlindSelectionIsInside(x,y))\r
34 #endif //CXIMAGE_SUPPORT_SELECTION\r
35                         {\r
36                                 switch (colorspace){\r
37                                 case 1:\r
38                                         color = HSLtoRGB(BlindGetPixelColor(x,y));\r
39                                         break;\r
40                                 case 2:\r
41                                         color = YUVtoRGB(BlindGetPixelColor(x,y));\r
42                                         break;\r
43                                 case 3:\r
44                                         color = YIQtoRGB(BlindGetPixelColor(x,y));\r
45                                         break;\r
46                                 case 4:\r
47                                         color = XYZtoRGB(BlindGetPixelColor(x,y));\r
48                                         break;\r
49                                 default:\r
50                                         color = BlindGetPixelColor(x,y);\r
51                                 }\r
52 \r
53                                 if (red) red[color.rgbRed]++;\r
54                                 if (green) green[color.rgbGreen]++;\r
55                                 if (blue) blue[color.rgbBlue]++;\r
56                                 if (gray) gray[(BYTE)RGB2GRAY(color.rgbRed,color.rgbGreen,color.rgbBlue)]++;\r
57                         }\r
58                 }\r
59         }\r
60 \r
61         long n=0;\r
62         for (int i=0; i<256; i++){\r
63                 if (red && red[i]>n) n=red[i];\r
64                 if (green && green[i]>n) n=green[i];\r
65                 if (blue && blue[i]>n) n=blue[i];\r
66                 if (gray && gray[i]>n) n=gray[i];\r
67         }\r
68 \r
69         return n;\r
70 }\r
71 ////////////////////////////////////////////////////////////////////////////////\r
72 /**\r
73  * HistogramStretch\r
74  * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels.\r
75  * \param threshold: minimum percentage level in the histogram to recognize it as meaningful. Range: 0.0 to 1.0; default = 0; typical = 0.005 (0.5%);\r
76  * \return true if everything is ok\r
77  * \author [dave] and [nipper]; changes [DP]\r
78  */\r
79 bool CxImage::HistogramStretch(long method, double threshold)\r
80 {\r
81         if (!pDib) return false;\r
82 \r
83         double dbScaler = 50.0/head.biHeight;\r
84         long x,y;\r
85 \r
86   if ((head.biBitCount==8) && IsGrayScale()){\r
87 \r
88         double p[256];\r
89         memset(p,  0, 256*sizeof(double));\r
90         for (y=0; y<head.biHeight; y++)\r
91         {\r
92                 info.nProgress = (long)(y*dbScaler);\r
93                 if (info.nEscape) break;\r
94                 for (x=0; x<head.biWidth; x++)  {\r
95                         p[BlindGetPixelIndex(x, y)]++;\r
96                 }\r
97         }\r
98 \r
99         double maxh = 0;\r
100         for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];\r
101         threshold *= maxh;\r
102         int minc = 0;\r
103         while (minc<255 && p[minc]<=threshold) minc++;\r
104         int maxc = 255;\r
105         while (maxc>0 && p[maxc]<=threshold) maxc--;\r
106 \r
107         if (minc == 0 && maxc == 255) return true;\r
108         if (minc >= maxc) return true;\r
109 \r
110         // calculate LUT\r
111         BYTE lut[256];\r
112         for (x = 0; x <256; x++){\r
113                 lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));\r
114         }\r
115 \r
116         for (y=0; y<head.biHeight; y++) {\r
117                 if (info.nEscape) break;\r
118                 info.nProgress = (long)(50.0+y*dbScaler);\r
119                 for (x=0; x<head.biWidth; x++)\r
120                 {\r
121                         BlindSetPixelIndex(x, y, lut[BlindGetPixelIndex(x, y)]);\r
122                 }\r
123         }\r
124   } else {\r
125         switch(method){\r
126         case 1:\r
127           { // <nipper>\r
128                 double p[256];\r
129                 memset(p,  0, 256*sizeof(double));\r
130                 for (y=0; y<head.biHeight; y++)\r
131                 {\r
132                         info.nProgress = (long)(y*dbScaler);\r
133                         if (info.nEscape) break;\r
134                         for (x=0; x<head.biWidth; x++)  {\r
135                                 RGBQUAD color = BlindGetPixelColor(x, y);\r
136                                 p[color.rgbRed]++;\r
137                                 p[color.rgbBlue]++;\r
138                                 p[color.rgbGreen]++;\r
139                         }\r
140                 }\r
141                 double maxh = 0;\r
142                 for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];\r
143                 threshold *= maxh;\r
144                 int minc = 0;\r
145                 while (minc<255 && p[minc]<=threshold) minc++;\r
146                 int maxc = 255;\r
147                 while (maxc>0 && p[maxc]<=threshold) maxc--;\r
148 \r
149                 if (minc == 0 && maxc == 255) return true;\r
150                 if (minc >= maxc) return true;\r
151 \r
152                 // calculate LUT\r
153                 BYTE lut[256];\r
154                 for (x = 0; x <256; x++){\r
155                         lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));\r
156                 }\r
157 \r
158                 // normalize image\r
159                 for (y=0; y<head.biHeight; y++) {\r
160                         if (info.nEscape) break;\r
161                         info.nProgress = (long)(50.0+y*dbScaler);\r
162 \r
163                         for (x=0; x<head.biWidth; x++)\r
164                         {\r
165                                 RGBQUAD color = BlindGetPixelColor(x, y);\r
166 \r
167                                 color.rgbRed = lut[color.rgbRed];\r
168                                 color.rgbBlue = lut[color.rgbBlue];\r
169                                 color.rgbGreen = lut[color.rgbGreen];\r
170 \r
171                                 BlindSetPixelColor(x, y, color);\r
172                         }\r
173                 }\r
174           }\r
175                 break;\r
176         case 2:\r
177           { // <nipper>\r
178                 double pR[256];\r
179                 memset(pR,  0, 256*sizeof(double));\r
180                 double pG[256];\r
181                 memset(pG,  0, 256*sizeof(double));\r
182                 double pB[256];\r
183                 memset(pB,  0, 256*sizeof(double));\r
184                 for (y=0; y<head.biHeight; y++)\r
185                 {\r
186                         info.nProgress = (long)(y*dbScaler);\r
187                         if (info.nEscape) break;\r
188                         for (long x=0; x<head.biWidth; x++)     {\r
189                                 RGBQUAD color = BlindGetPixelColor(x, y);\r
190                                 pR[color.rgbRed]++;\r
191                                 pB[color.rgbBlue]++;\r
192                                 pG[color.rgbGreen]++;\r
193                         }\r
194                 }\r
195 \r
196                 double maxh = 0;\r
197                 for (y=0; y<255; y++) if (maxh < pR[y]) maxh = pR[y];\r
198                 double threshold2 = threshold*maxh;\r
199                 int minR = 0;\r
200                 while (minR<255 && pR[minR]<=threshold2) minR++;\r
201                 int maxR = 255;\r
202                 while (maxR>0 && pR[maxR]<=threshold2) maxR--;\r
203 \r
204                 maxh = 0;\r
205                 for (y=0; y<255; y++) if (maxh < pG[y]) maxh = pG[y];\r
206                 threshold2 = threshold*maxh;\r
207                 int minG = 0;\r
208                 while (minG<255 && pG[minG]<=threshold2) minG++;\r
209                 int maxG = 255;\r
210                 while (maxG>0 && pG[maxG]<=threshold2) maxG--;\r
211 \r
212                 maxh = 0;\r
213                 for (y=0; y<255; y++) if (maxh < pB[y]) maxh = pB[y];\r
214                 threshold2 = threshold*maxh;\r
215                 int minB = 0;\r
216                 while (minB<255 && pB[minB]<=threshold2) minB++;\r
217                 int maxB = 255;\r
218                 while (maxB>0 && pB[maxB]<=threshold2) maxB--;\r
219 \r
220                 if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255)\r
221                         return true;\r
222 \r
223                 // calculate LUT\r
224                 BYTE lutR[256];\r
225                 BYTE range = maxR - minR;\r
226                 if (range != 0) {\r
227                         for (x = 0; x <256; x++){\r
228                                 lutR[x] = (BYTE)max(0,min(255,(255 * (x - minR) / range)));\r
229                         }\r
230                 } else lutR[minR] = minR;\r
231 \r
232                 BYTE lutG[256];\r
233                 range = maxG - minG;\r
234                 if (range != 0) {\r
235                         for (x = 0; x <256; x++){\r
236                                 lutG[x] = (BYTE)max(0,min(255,(255 * (x - minG) / range)));\r
237                         }\r
238                 } else lutG[minG] = minG;\r
239                         \r
240                 BYTE lutB[256];\r
241                 range = maxB - minB;\r
242                 if (range != 0) {\r
243                         for (x = 0; x <256; x++){\r
244                                 lutB[x] = (BYTE)max(0,min(255,(255 * (x - minB) / range)));\r
245                         }\r
246                 } else lutB[minB] = minB;\r
247 \r
248                 // normalize image\r
249                 for (y=0; y<head.biHeight; y++)\r
250                 {\r
251                         info.nProgress = (long)(50.0+y*dbScaler);\r
252                         if (info.nEscape) break;\r
253 \r
254                         for (x=0; x<head.biWidth; x++)\r
255                         {\r
256                                 RGBQUAD color = BlindGetPixelColor(x, y);\r
257 \r
258                                 color.rgbRed = lutR[color.rgbRed];\r
259                                 color.rgbBlue = lutB[color.rgbBlue];\r
260                                 color.rgbGreen = lutG[color.rgbGreen];\r
261 \r
262                                 BlindSetPixelColor(x, y, color);\r
263                         }\r
264                 }\r
265           }\r
266                 break;\r
267         default:\r
268           { // <dave>\r
269                 double p[256];\r
270                 memset(p,  0, 256*sizeof(double));\r
271                 for (y=0; y<head.biHeight; y++)\r
272                 {\r
273                         info.nProgress = (long)(y*dbScaler);\r
274                         if (info.nEscape) break;\r
275                         for (x=0; x<head.biWidth; x++)  {\r
276                                 RGBQUAD color = BlindGetPixelColor(x, y);\r
277                                 p[RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue)]++;\r
278                         }\r
279                 }\r
280 \r
281                 double maxh = 0;\r
282                 for (y=0; y<255; y++) if (maxh < p[y]) maxh = p[y];\r
283                 threshold *= maxh;\r
284                 int minc = 0;\r
285                 while (minc<255 && p[minc]<=threshold) minc++;\r
286                 int maxc = 255;\r
287                 while (maxc>0 && p[maxc]<=threshold) maxc--;\r
288 \r
289                 if (minc == 0 && maxc == 255) return true;\r
290                 if (minc >= maxc) return true;\r
291 \r
292                 // calculate LUT\r
293                 BYTE lut[256];\r
294                 for (x = 0; x <256; x++){\r
295                         lut[x] = (BYTE)max(0,min(255,(255 * (x - minc) / (maxc - minc))));\r
296                 }\r
297 \r
298                 for(y=0; y<head.biHeight; y++){\r
299                         info.nProgress = (long)(50.0+y*dbScaler);\r
300                         if (info.nEscape) break;\r
301                         for(x=0; x<head.biWidth; x++){\r
302 \r
303                                 RGBQUAD color = BlindGetPixelColor( x, y );\r
304                                 RGBQUAD yuvClr = RGBtoYUV(color);\r
305                                 yuvClr.rgbRed = lut[yuvClr.rgbRed];\r
306                                 color = YUVtoRGB(yuvClr);\r
307                                 BlindSetPixelColor( x, y, color );\r
308                         }\r
309                 }\r
310           }\r
311         }\r
312   }\r
313   return true;\r
314 }\r
315 ////////////////////////////////////////////////////////////////////////////////\r
316 // HistogramEqualize function by <dave> : dave(at)posortho(dot)com\r
317 bool CxImage::HistogramEqualize()\r
318 {\r
319         if (!pDib) return false;\r
320 \r
321     int histogram[256];\r
322         int map[256];\r
323         int equalize_map[256];\r
324     int x, y, i, j;\r
325         RGBQUAD color;\r
326         RGBQUAD yuvClr;\r
327         unsigned int YVal, high, low;\r
328 \r
329         memset( &histogram, 0, sizeof(int) * 256 );\r
330         memset( &map, 0, sizeof(int) * 256 );\r
331         memset( &equalize_map, 0, sizeof(int) * 256 );\r
332  \r
333      // form histogram\r
334         for(y=0; y < head.biHeight; y++){\r
335                 info.nProgress = (long)(50*y/head.biHeight);\r
336                 if (info.nEscape) break;\r
337                 for(x=0; x < head.biWidth; x++){\r
338                         color = BlindGetPixelColor( x, y );\r
339                         YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
340                         histogram[YVal]++;\r
341                 }\r
342         }\r
343 \r
344         // integrate the histogram to get the equalization map.\r
345         j = 0;\r
346         for(i=0; i <= 255; i++){\r
347                 j += histogram[i];\r
348                 map[i] = j; \r
349         }\r
350 \r
351         // equalize\r
352         low = map[0];\r
353         high = map[255];\r
354         if (low == high) return false;\r
355         for( i = 0; i <= 255; i++ ){\r
356                 equalize_map[i] = (unsigned int)((((double)( map[i] - low ) ) * 255) / ( high - low ) );\r
357         }\r
358 \r
359         // stretch the histogram\r
360         if(head.biClrUsed == 0){ // No Palette\r
361                 for( y = 0; y < head.biHeight; y++ ){\r
362                         info.nProgress = (long)(50+50*y/head.biHeight);\r
363                         if (info.nEscape) break;\r
364                         for( x = 0; x < head.biWidth; x++ ){\r
365 \r
366                                 color = BlindGetPixelColor( x, y );\r
367                                 yuvClr = RGBtoYUV(color);\r
368 \r
369                 yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed];\r
370 \r
371                                 color = YUVtoRGB(yuvClr);\r
372                                 BlindSetPixelColor( x, y, color );\r
373                         }\r
374                 }\r
375         } else { // Palette\r
376                 for( i = 0; i < (int)head.biClrUsed; i++ ){\r
377 \r
378                         color = GetPaletteColor((BYTE)i);\r
379                         yuvClr = RGBtoYUV(color);\r
380 \r
381             yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed];\r
382 \r
383                         color = YUVtoRGB(yuvClr);\r
384                         SetPaletteColor( (BYTE)i, color );\r
385                 }\r
386         }\r
387         return true;\r
388 }\r
389 ////////////////////////////////////////////////////////////////////////////////\r
390 // HistogramNormalize function by <dave> : dave(at)posortho(dot)com\r
391 bool CxImage::HistogramNormalize()\r
392 {\r
393         if (!pDib) return false;\r
394 \r
395         int histogram[256];\r
396         int threshold_intensity, intense;\r
397         int x, y, i;\r
398         unsigned int normalize_map[256];\r
399         unsigned int high, low, YVal;\r
400 \r
401         RGBQUAD color;\r
402         RGBQUAD yuvClr;\r
403 \r
404         memset( &histogram, 0, sizeof( int ) * 256 );\r
405         memset( &normalize_map, 0, sizeof( unsigned int ) * 256 );\r
406  \r
407      // form histogram\r
408         for(y=0; y < head.biHeight; y++){\r
409                 info.nProgress = (long)(50*y/head.biHeight);\r
410                 if (info.nEscape) break;\r
411                 for(x=0; x < head.biWidth; x++){\r
412                         color = BlindGetPixelColor( x, y );\r
413                         YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
414                         histogram[YVal]++;\r
415                 }\r
416         }\r
417 \r
418         // find histogram boundaries by locating the 1 percent levels\r
419         threshold_intensity = ( head.biWidth * head.biHeight) / 100;\r
420 \r
421         intense = 0;\r
422         for( low = 0; low < 255; low++ ){\r
423                 intense += histogram[low];\r
424                 if( intense > threshold_intensity )     break;\r
425         }\r
426 \r
427         intense = 0;\r
428         for( high = 255; high != 0; high--){\r
429                 intense += histogram[ high ];\r
430                 if( intense > threshold_intensity ) break;\r
431         }\r
432 \r
433         if ( low == high ){\r
434                 // Unreasonable contrast;  use zero threshold to determine boundaries.\r
435                 threshold_intensity = 0;\r
436                 intense = 0;\r
437                 for( low = 0; low < 255; low++){\r
438                         intense += histogram[low];\r
439                         if( intense > threshold_intensity )     break;\r
440                 }\r
441                 intense = 0;\r
442                 for( high = 255; high != 0; high-- ){\r
443                         intense += histogram [high ];\r
444                         if( intense > threshold_intensity )     break;\r
445                 }\r
446         }\r
447         if( low == high ) return false;  // zero span bound\r
448 \r
449         // Stretch the histogram to create the normalized image mapping.\r
450         for(i = 0; i <= 255; i++){\r
451                 if ( i < (int) low ){\r
452                         normalize_map[i] = 0;\r
453                 } else {\r
454                         if(i > (int) high)\r
455                                 normalize_map[i] = 255;\r
456                         else\r
457                                 normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low );\r
458                 }\r
459         }\r
460 \r
461         // Normalize\r
462         if( head.biClrUsed == 0 ){\r
463                 for( y = 0; y < head.biHeight; y++ ){\r
464                         info.nProgress = (long)(50+50*y/head.biHeight);\r
465                         if (info.nEscape) break;\r
466                         for( x = 0; x < head.biWidth; x++ ){\r
467 \r
468                                 color = BlindGetPixelColor( x, y );\r
469                                 yuvClr = RGBtoYUV( color );\r
470 \r
471                 yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed];\r
472 \r
473                                 color = YUVtoRGB( yuvClr );\r
474                                 BlindSetPixelColor( x, y, color );\r
475                         }\r
476                 }\r
477         } else {\r
478                 for(i = 0; i < (int)head.biClrUsed; i++){\r
479 \r
480                         color = GetPaletteColor( (BYTE)i );\r
481                         yuvClr = RGBtoYUV( color );\r
482 \r
483             yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed];\r
484 \r
485                         color = YUVtoRGB( yuvClr );\r
486                         SetPaletteColor( (BYTE)i, color );\r
487                 }\r
488         }\r
489         return true;\r
490 }\r
491 ////////////////////////////////////////////////////////////////////////////////\r
492 // HistogramLog function by <dave> : dave(at)posortho(dot)com\r
493 bool CxImage::HistogramLog()\r
494 {\r
495         if (!pDib) return false;\r
496 \r
497         //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|);\r
498     int x, y, i;\r
499         RGBQUAD color;\r
500         RGBQUAD yuvClr;\r
501 \r
502         unsigned int YVal, high = 1;\r
503 \r
504     // Find Highest Luminance Value in the Image\r
505         if( head.biClrUsed == 0 ){ // No Palette\r
506                 for(y=0; y < head.biHeight; y++){\r
507                         info.nProgress = (long)(50*y/head.biHeight);\r
508                         if (info.nEscape) break;\r
509                         for(x=0; x < head.biWidth; x++){\r
510                                 color = BlindGetPixelColor( x, y );\r
511                                 YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
512                                 if (YVal > high ) high = YVal;\r
513                         }\r
514                 }\r
515         } else { // Palette\r
516                 for(i = 0; i < (int)head.biClrUsed; i++){\r
517                         color = GetPaletteColor((BYTE)i);\r
518                         YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
519                         if (YVal > high ) high = YVal;\r
520                 }\r
521         }\r
522 \r
523         // Logarithm Operator\r
524         double k = 255.0 / ::log( 1.0 + (double)high );\r
525         if( head.biClrUsed == 0 ){\r
526                 for( y = 0; y < head.biHeight; y++ ){\r
527                         info.nProgress = (long)(50+50*y/head.biHeight);\r
528                         if (info.nEscape) break;\r
529                         for( x = 0; x < head.biWidth; x++ ){\r
530 \r
531                                 color = BlindGetPixelColor( x, y );\r
532                                 yuvClr = RGBtoYUV( color );\r
533                 \r
534                                 yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );\r
535 \r
536                                 color = YUVtoRGB( yuvClr );\r
537                                 BlindSetPixelColor( x, y, color );\r
538                         }\r
539                 }\r
540         } else {\r
541                 for(i = 0; i < (int)head.biClrUsed; i++){\r
542 \r
543                         color = GetPaletteColor( (BYTE)i );\r
544                         yuvClr = RGBtoYUV( color );\r
545 \r
546             yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) );\r
547                         \r
548                         color = YUVtoRGB( yuvClr );\r
549                         SetPaletteColor( (BYTE)i, color );\r
550                 }\r
551         }\r
552  \r
553         return true;\r
554 }\r
555 \r
556 ////////////////////////////////////////////////////////////////////////////////\r
557 // HistogramRoot function by <dave> : dave(at)posortho(dot)com\r
558 bool CxImage::HistogramRoot()\r
559 {\r
560         if (!pDib) return false;\r
561         //q(i,j) = sqrt(|p(i,j)|);\r
562 \r
563     int x, y, i;\r
564         RGBQUAD color;\r
565         RGBQUAD  yuvClr;\r
566         double  dtmp;\r
567         unsigned int YVal, high = 1;\r
568 \r
569      // Find Highest Luminance Value in the Image\r
570         if( head.biClrUsed == 0 ){ // No Palette\r
571                 for(y=0; y < head.biHeight; y++){\r
572                         info.nProgress = (long)(50*y/head.biHeight);\r
573                         if (info.nEscape) break;\r
574                         for(x=0; x < head.biWidth; x++){\r
575                                 color = BlindGetPixelColor( x, y );\r
576                                 YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
577                                 if (YVal > high ) high = YVal;\r
578                         }\r
579                 }\r
580         } else { // Palette\r
581                 for(i = 0; i < (int)head.biClrUsed; i++){\r
582                         color = GetPaletteColor((BYTE)i);\r
583                         YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue);\r
584                         if (YVal > high ) high = YVal;\r
585                 }\r
586         }\r
587 \r
588         // Root Operator\r
589         double k = 128.0 / ::log( 1.0 + (double)high );\r
590         if( head.biClrUsed == 0 ){\r
591                 for( y = 0; y < head.biHeight; y++ ){\r
592                         info.nProgress = (long)(50+50*y/head.biHeight);\r
593                         if (info.nEscape) break;\r
594                         for( x = 0; x < head.biWidth; x++ ){\r
595 \r
596                                 color = BlindGetPixelColor( x, y );\r
597                                 yuvClr = RGBtoYUV( color );\r
598 \r
599                                 dtmp = k * ::sqrt( (double)yuvClr.rgbRed );\r
600                                 if ( dtmp > 255.0 )     dtmp = 255.0;\r
601                                 if ( dtmp < 0 ) dtmp = 0;\r
602                 yuvClr.rgbRed = (BYTE)dtmp;\r
603 \r
604                                 color = YUVtoRGB( yuvClr );\r
605                                 BlindSetPixelColor( x, y, color );\r
606                         }\r
607                 }\r
608         } else {\r
609                 for(i = 0; i < (int)head.biClrUsed; i++){\r
610 \r
611                         color = GetPaletteColor( (BYTE)i );\r
612                         yuvClr = RGBtoYUV( color );\r
613 \r
614                         dtmp = k * ::sqrt( (double)yuvClr.rgbRed );\r
615                         if ( dtmp > 255.0 )     dtmp = 255.0;\r
616                         if ( dtmp < 0 ) dtmp = 0;\r
617             yuvClr.rgbRed = (BYTE)dtmp;\r
618 \r
619                         color = YUVtoRGB( yuvClr );\r
620                         SetPaletteColor( (BYTE)i, color );\r
621                 }\r
622         }\r
623  \r
624         return true;\r
625 }\r
626 ////////////////////////////////////////////////////////////////////////////////\r
627 #endif\r