From c91847d549cc1c30eb15504a15ea9a6d5aa48165 Mon Sep 17 00:00:00 2001 From: "chirs241097@gmail.com" Date: Sun, 12 Jan 2014 14:43:14 +0000 Subject: --- hge/CxImage/ximahist.cpp | 627 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 627 insertions(+) create mode 100644 hge/CxImage/ximahist.cpp (limited to 'hge/CxImage/ximahist.cpp') diff --git a/hge/CxImage/ximahist.cpp b/hge/CxImage/ximahist.cpp new file mode 100644 index 0000000..830337f --- /dev/null +++ b/hge/CxImage/ximahist.cpp @@ -0,0 +1,627 @@ +// xImaHist.cpp : histogram functions +/* 28/01/2004 v1.00 - www.xdp.it + * CxImage version 7.0.0 31/Dec/2010 + */ + +#include "ximage.h" + +#if CXIMAGE_SUPPORT_DSP + +//////////////////////////////////////////////////////////////////////////////// +int32_t CxImage::Histogram(int32_t* red, int32_t* green, int32_t* blue, int32_t* gray, int32_t colorspace) +{ + if (!pDib) return 0; + RGBQUAD color; + + if (red) memset(red,0,256*sizeof(int32_t)); + if (green) memset(green,0,256*sizeof(int32_t)); + if (blue) memset(blue,0,256*sizeof(int32_t)); + if (gray) memset(gray,0,256*sizeof(int32_t)); + + int32_t xmin,xmax,ymin,ymax; + if (pSelection){ + xmin = info.rSelectionBox.left; xmax = info.rSelectionBox.right; + ymin = info.rSelectionBox.bottom; ymax = info.rSelectionBox.top; + } else { + xmin = ymin = 0; + xmax = head.biWidth; ymax=head.biHeight; + } + + for(int32_t y=ymin; yn) n=red[i]; + if (green && green[i]>n) n=green[i]; + if (blue && blue[i]>n) n=blue[i]; + if (gray && gray[i]>n) n=gray[i]; + } + + return n; +} +//////////////////////////////////////////////////////////////////////////////// +/** + * HistogramStretch + * \param method: 0 = luminance (default), 1 = linked channels , 2 = independent channels. + * \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%); + * \return true if everything is ok + * \author [dave] and [nipper]; changes [DP] + */ +bool CxImage::HistogramStretch(int32_t method, double threshold) +{ + if (!pDib) return false; + + double dbScaler = 50.0/head.biHeight; + int32_t x,y; + + if ((head.biBitCount==8) && IsGrayScale()){ + + double p[256]; + memset(p, 0, 256*sizeof(double)); + for (y=0; y0 && p[maxc]<=threshold) maxc--; + + if (minc == 0 && maxc == 255) return true; + if (minc >= maxc) return true; + + // calculate LUT + uint8_t lut[256]; + for (x = 0; x <256; x++){ + lut[x] = (uint8_t)max(0,min(255,(255 * (x - minc) / (maxc - minc)))); + } + + for (y=0; y + double p[256]; + memset(p, 0, 256*sizeof(double)); + for (y=0; y0 && p[maxc]<=threshold) maxc--; + + if (minc == 0 && maxc == 255) return true; + if (minc >= maxc) return true; + + // calculate LUT + uint8_t lut[256]; + for (x = 0; x <256; x++){ + lut[x] = (uint8_t)max(0,min(255,(255 * (x - minc) / (maxc - minc)))); + } + + // normalize image + for (y=0; y + double pR[256]; + memset(pR, 0, 256*sizeof(double)); + double pG[256]; + memset(pG, 0, 256*sizeof(double)); + double pB[256]; + memset(pB, 0, 256*sizeof(double)); + for (y=0; y0 && pR[maxR]<=threshold2) maxR--; + + maxh = 0; + for (y=0; y<255; y++) if (maxh < pG[y]) maxh = pG[y]; + threshold2 = threshold*maxh; + int32_t minG = 0; + while (minG<255 && pG[minG]<=threshold2) minG++; + int32_t maxG = 255; + while (maxG>0 && pG[maxG]<=threshold2) maxG--; + + maxh = 0; + for (y=0; y<255; y++) if (maxh < pB[y]) maxh = pB[y]; + threshold2 = threshold*maxh; + int32_t minB = 0; + while (minB<255 && pB[minB]<=threshold2) minB++; + int32_t maxB = 255; + while (maxB>0 && pB[maxB]<=threshold2) maxB--; + + if (minR == 0 && maxR == 255 && minG == 0 && maxG == 255 && minB == 0 && maxB == 255) + return true; + + // calculate LUT + uint8_t lutR[256]; + uint8_t range = maxR - minR; + if (range != 0) { + for (x = 0; x <256; x++){ + lutR[x] = (uint8_t)max(0,min(255,(255 * (x - minR) / range))); + } + } else lutR[minR] = minR; + + uint8_t lutG[256]; + range = maxG - minG; + if (range != 0) { + for (x = 0; x <256; x++){ + lutG[x] = (uint8_t)max(0,min(255,(255 * (x - minG) / range))); + } + } else lutG[minG] = minG; + + uint8_t lutB[256]; + range = maxB - minB; + if (range != 0) { + for (x = 0; x <256; x++){ + lutB[x] = (uint8_t)max(0,min(255,(255 * (x - minB) / range))); + } + } else lutB[minB] = minB; + + // normalize image + for (y=0; y + double p[256]; + memset(p, 0, 256*sizeof(double)); + for (y=0; y0 && p[maxc]<=threshold) maxc--; + + if (minc == 0 && maxc == 255) return true; + if (minc >= maxc) return true; + + // calculate LUT + uint8_t lut[256]; + for (x = 0; x <256; x++){ + lut[x] = (uint8_t)max(0,min(255,(255 * (x - minc) / (maxc - minc)))); + } + + for(y=0; y : dave(at)posortho(dot)com +bool CxImage::HistogramEqualize() +{ + if (!pDib) return false; + + int32_t histogram[256]; + int32_t map[256]; + int32_t equalize_map[256]; + int32_t x, y, i, j; + RGBQUAD color; + RGBQUAD yuvClr; + uint32_t YVal, high, low; + + memset( &histogram, 0, sizeof(int32_t) * 256 ); + memset( &map, 0, sizeof(int32_t) * 256 ); + memset( &equalize_map, 0, sizeof(int32_t) * 256 ); + + // form histogram + for(y=0; y < head.biHeight; y++){ + info.nProgress = (int32_t)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = BlindGetPixelColor( x, y ); + YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + histogram[YVal]++; + } + } + + // integrate the histogram to get the equalization map. + j = 0; + for(i=0; i <= 255; i++){ + j += histogram[i]; + map[i] = j; + } + + // equalize + low = map[0]; + high = map[255]; + if (low == high) return false; + for( i = 0; i <= 255; i++ ){ + equalize_map[i] = (uint32_t)((((double)( map[i] - low ) ) * 255) / ( high - low ) ); + } + + // stretch the histogram + if(head.biClrUsed == 0){ // No Palette + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (int32_t)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = BlindGetPixelColor( x, y ); + yuvClr = RGBtoYUV(color); + + yuvClr.rgbRed = (uint8_t)equalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB(yuvClr); + BlindSetPixelColor( x, y, color ); + } + } + } else { // Palette + for( i = 0; i < (int32_t)head.biClrUsed; i++ ){ + + color = GetPaletteColor((uint8_t)i); + yuvClr = RGBtoYUV(color); + + yuvClr.rgbRed = (uint8_t)equalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB(yuvClr); + SetPaletteColor( (uint8_t)i, color ); + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +// HistogramNormalize function by : dave(at)posortho(dot)com +bool CxImage::HistogramNormalize() +{ + if (!pDib) return false; + + int32_t histogram[256]; + int32_t threshold_intensity, intense; + int32_t x, y, i; + uint32_t normalize_map[256]; + uint32_t high, low, YVal; + + RGBQUAD color; + RGBQUAD yuvClr; + + memset( &histogram, 0, sizeof( int32_t ) * 256 ); + memset( &normalize_map, 0, sizeof( uint32_t ) * 256 ); + + // form histogram + for(y=0; y < head.biHeight; y++){ + info.nProgress = (int32_t)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = BlindGetPixelColor( x, y ); + YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + histogram[YVal]++; + } + } + + // find histogram boundaries by locating the 1 percent levels + threshold_intensity = ( head.biWidth * head.biHeight) / 100; + + intense = 0; + for( low = 0; low < 255; low++ ){ + intense += histogram[low]; + if( intense > threshold_intensity ) break; + } + + intense = 0; + for( high = 255; high != 0; high--){ + intense += histogram[ high ]; + if( intense > threshold_intensity ) break; + } + + if ( low == high ){ + // Unreasonable contrast; use zero threshold to determine boundaries. + threshold_intensity = 0; + intense = 0; + for( low = 0; low < 255; low++){ + intense += histogram[low]; + if( intense > threshold_intensity ) break; + } + intense = 0; + for( high = 255; high != 0; high-- ){ + intense += histogram [high ]; + if( intense > threshold_intensity ) break; + } + } + if( low == high ) return false; // zero span bound + + // Stretch the histogram to create the normalized image mapping. + for(i = 0; i <= 255; i++){ + if ( i < (int32_t) low ){ + normalize_map[i] = 0; + } else { + if(i > (int32_t) high) + normalize_map[i] = 255; + else + normalize_map[i] = ( 255 - 1) * ( i - low) / ( high - low ); + } + } + + // Normalize + if( head.biClrUsed == 0 ){ + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (int32_t)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = BlindGetPixelColor( x, y ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (uint8_t)normalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB( yuvClr ); + BlindSetPixelColor( x, y, color ); + } + } + } else { + for(i = 0; i < (int32_t)head.biClrUsed; i++){ + + color = GetPaletteColor( (uint8_t)i ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (uint8_t)normalize_map[yuvClr.rgbRed]; + + color = YUVtoRGB( yuvClr ); + SetPaletteColor( (uint8_t)i, color ); + } + } + return true; +} +//////////////////////////////////////////////////////////////////////////////// +// HistogramLog function by : dave(at)posortho(dot)com +bool CxImage::HistogramLog() +{ + if (!pDib) return false; + + //q(i,j) = 255/log(1 + |high|) * log(1 + |p(i,j)|); + int32_t x, y, i; + RGBQUAD color; + RGBQUAD yuvClr; + + uint32_t YVal, high = 1; + + // Find Highest Luminance Value in the Image + if( head.biClrUsed == 0 ){ // No Palette + for(y=0; y < head.biHeight; y++){ + info.nProgress = (int32_t)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = BlindGetPixelColor( x, y ); + YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + } else { // Palette + for(i = 0; i < (int32_t)head.biClrUsed; i++){ + color = GetPaletteColor((uint8_t)i); + YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + + // Logarithm Operator + double k = 255.0 / ::log( 1.0 + (double)high ); + if( head.biClrUsed == 0 ){ + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (int32_t)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = BlindGetPixelColor( x, y ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (uint8_t)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); + + color = YUVtoRGB( yuvClr ); + BlindSetPixelColor( x, y, color ); + } + } + } else { + for(i = 0; i < (int32_t)head.biClrUsed; i++){ + + color = GetPaletteColor( (uint8_t)i ); + yuvClr = RGBtoYUV( color ); + + yuvClr.rgbRed = (uint8_t)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); + + color = YUVtoRGB( yuvClr ); + SetPaletteColor( (uint8_t)i, color ); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// HistogramRoot function by : dave(at)posortho(dot)com +bool CxImage::HistogramRoot() +{ + if (!pDib) return false; + //q(i,j) = sqrt(|p(i,j)|); + + int32_t x, y, i; + RGBQUAD color; + RGBQUAD yuvClr; + double dtmp; + uint32_t YVal, high = 1; + + // Find Highest Luminance Value in the Image + if( head.biClrUsed == 0 ){ // No Palette + for(y=0; y < head.biHeight; y++){ + info.nProgress = (int32_t)(50*y/head.biHeight); + if (info.nEscape) break; + for(x=0; x < head.biWidth; x++){ + color = BlindGetPixelColor( x, y ); + YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + } else { // Palette + for(i = 0; i < (int32_t)head.biClrUsed; i++){ + color = GetPaletteColor((uint8_t)i); + YVal = (uint32_t)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); + if (YVal > high ) high = YVal; + } + } + + // Root Operator + double k = 256.0 / ::sqrt( 1.0 + (double)high ); + if( head.biClrUsed == 0 ){ + for( y = 0; y < head.biHeight; y++ ){ + info.nProgress = (int32_t)(50+50*y/head.biHeight); + if (info.nEscape) break; + for( x = 0; x < head.biWidth; x++ ){ + + color = BlindGetPixelColor( x, y ); + yuvClr = RGBtoYUV( color ); + + dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); + if ( dtmp > 255.0 ) dtmp = 255.0; + if ( dtmp < 0 ) dtmp = 0; + yuvClr.rgbRed = (uint8_t)dtmp; + + color = YUVtoRGB( yuvClr ); + BlindSetPixelColor( x, y, color ); + } + } + } else { + for(i = 0; i < (int32_t)head.biClrUsed; i++){ + + color = GetPaletteColor( (uint8_t)i ); + yuvClr = RGBtoYUV( color ); + + dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); + if ( dtmp > 255.0 ) dtmp = 255.0; + if ( dtmp < 0 ) dtmp = 0; + yuvClr.rgbRed = (uint8_t)dtmp; + + color = YUVtoRGB( yuvClr ); + SetPaletteColor( (uint8_t)i, color ); + } + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////// +#endif -- cgit v1.2.3