source: liacs/MIR2010/SourceCode/cximage/ximahist.cpp@ 321

Last change on this file since 321 was 95, checked in by Rick van der Zwet, 15 years ago

Bad boy, improper move of directory

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