www.pudn.com > cximage602_full.rar > ximahist.cpp


// xImaHist.cpp : histogram functions 
/* 28/01/2004 v1.00 - www.xdp.it 
 * CxImage version 6.0.0 02/Feb/2008 
 */ 
 
#include "ximage.h" 
 
#if CXIMAGE_SUPPORT_DSP 
 
//////////////////////////////////////////////////////////////////////////////// 
long CxImage::Histogram(long* red, long* green, long* blue, long* gray, long colorspace) 
{ 
	if (!pDib) return 0; 
	RGBQUAD color; 
 
	if (red) memset(red,0,256*sizeof(long)); 
	if (green) memset(green,0,256*sizeof(long)); 
	if (blue) memset(blue,0,256*sizeof(long)); 
	if (gray) memset(gray,0,256*sizeof(long)); 
 
	long 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(long 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(long method, double threshold) 
{ 
	if (!pDib) return false; 
 
	double dbScaler = 50.0/head.biHeight; 
	long 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 
	BYTE lut[256]; 
	for (x = 0; x <256; x++){ 
		lut[x] = (BYTE)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 
		BYTE lut[256]; 
		for (x = 0; x <256; x++){ 
			lut[x] = (BYTE)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; 
		int minG = 0; 
		while (minG<255 && pG[minG]<=threshold2) minG++; 
		int 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; 
		int minB = 0; 
		while (minB<255 && pB[minB]<=threshold2) minB++; 
		int 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 
		BYTE lutR[256]; 
		BYTE range = maxR - minR; 
		if (range != 0)	{ 
			for (x = 0; x <256; x++){ 
				lutR[x] = (BYTE)max(0,min(255,(255 * (x - minR) / range))); 
			} 
		} else lutR[minR] = minR; 
 
		BYTE lutG[256]; 
		range = maxG - minG; 
		if (range != 0)	{ 
			for (x = 0; x <256; x++){ 
				lutG[x] = (BYTE)max(0,min(255,(255 * (x - minG) / range))); 
			} 
		} else lutG[minG] = minG; 
			 
		BYTE lutB[256]; 
		range = maxB - minB; 
		if (range != 0)	{ 
			for (x = 0; x <256; x++){ 
				lutB[x] = (BYTE)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 
		BYTE lut[256]; 
		for (x = 0; x <256; x++){ 
			lut[x] = (BYTE)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; 
 
    int histogram[256]; 
	int map[256]; 
	int equalize_map[256]; 
    int x, y, i, j; 
	RGBQUAD color; 
	RGBQUAD	yuvClr; 
	unsigned int YVal, high, low; 
 
	memset( &histogram, 0, sizeof(int) * 256 ); 
	memset( &map, 0, sizeof(int) * 256 ); 
	memset( &equalize_map, 0, sizeof(int) * 256 ); 
  
     // form histogram 
	for(y=0; y < head.biHeight; y++){ 
		info.nProgress = (long)(50*y/head.biHeight); 
		if (info.nEscape) break; 
		for(x=0; x < head.biWidth; x++){ 
			color = BlindGetPixelColor( x, y ); 
			YVal = (unsigned int)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] = (unsigned int)((((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 = (long)(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 = (BYTE)equalize_map[yuvClr.rgbRed]; 
 
				color = YUVtoRGB(yuvClr); 
				BlindSetPixelColor( x, y, color ); 
			} 
		} 
	} else { // Palette 
		for( i = 0; i < (int)head.biClrUsed; i++ ){ 
 
			color = GetPaletteColor((BYTE)i); 
			yuvClr = RGBtoYUV(color); 
 
            yuvClr.rgbRed = (BYTE)equalize_map[yuvClr.rgbRed]; 
 
			color = YUVtoRGB(yuvClr); 
			SetPaletteColor( (BYTE)i, color ); 
		} 
	} 
	return true; 
} 
//////////////////////////////////////////////////////////////////////////////// 
// HistogramNormalize function by  : dave(at)posortho(dot)com 
bool CxImage::HistogramNormalize() 
{ 
	if (!pDib) return false; 
 
	int histogram[256]; 
	int threshold_intensity, intense; 
	int x, y, i; 
	unsigned int normalize_map[256]; 
	unsigned int high, low, YVal; 
 
	RGBQUAD color; 
	RGBQUAD	yuvClr; 
 
	memset( &histogram, 0, sizeof( int ) * 256 ); 
	memset( &normalize_map, 0, sizeof( unsigned int ) * 256 ); 
  
     // form histogram 
	for(y=0; y < head.biHeight; y++){ 
		info.nProgress = (long)(50*y/head.biHeight); 
		if (info.nEscape) break; 
		for(x=0; x < head.biWidth; x++){ 
			color = BlindGetPixelColor( x, y ); 
			YVal = (unsigned int)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 < (int) low ){ 
			normalize_map[i] = 0; 
		} else { 
			if(i > (int) 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 = (long)(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 = (BYTE)normalize_map[yuvClr.rgbRed]; 
 
				color = YUVtoRGB( yuvClr ); 
				BlindSetPixelColor( x, y, color ); 
			} 
		} 
	} else { 
		for(i = 0; i < (int)head.biClrUsed; i++){ 
 
			color = GetPaletteColor( (BYTE)i ); 
			yuvClr = RGBtoYUV( color ); 
 
            yuvClr.rgbRed = (BYTE)normalize_map[yuvClr.rgbRed]; 
 
			color = YUVtoRGB( yuvClr ); 
 			SetPaletteColor( (BYTE)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)|); 
    int x, y, i; 
	RGBQUAD color; 
	RGBQUAD	yuvClr; 
 
	unsigned int 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 = (long)(50*y/head.biHeight); 
			if (info.nEscape) break; 
			for(x=0; x < head.biWidth; x++){ 
				color = BlindGetPixelColor( x, y ); 
				YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); 
				if (YVal > high ) high = YVal; 
			} 
		} 
	} else { // Palette 
		for(i = 0; i < (int)head.biClrUsed; i++){ 
			color = GetPaletteColor((BYTE)i); 
			YVal = (unsigned int)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 = (long)(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 = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); 
 
				color = YUVtoRGB( yuvClr ); 
				BlindSetPixelColor( x, y, color ); 
			} 
		} 
	} else { 
		for(i = 0; i < (int)head.biClrUsed; i++){ 
 
			color = GetPaletteColor( (BYTE)i ); 
			yuvClr = RGBtoYUV( color ); 
 
            yuvClr.rgbRed = (BYTE)(k * ::log( 1.0 + (double)yuvClr.rgbRed ) ); 
			 
			color = YUVtoRGB( yuvClr ); 
 			SetPaletteColor( (BYTE)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)|); 
 
    int x, y, i; 
	RGBQUAD color; 
	RGBQUAD	 yuvClr; 
	double	dtmp; 
	unsigned int 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 = (long)(50*y/head.biHeight); 
			if (info.nEscape) break; 
			for(x=0; x < head.biWidth; x++){ 
				color = BlindGetPixelColor( x, y ); 
				YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); 
				if (YVal > high ) high = YVal; 
			} 
		} 
	} else { // Palette 
		for(i = 0; i < (int)head.biClrUsed; i++){ 
			color = GetPaletteColor((BYTE)i); 
			YVal = (unsigned int)RGB2GRAY(color.rgbRed, color.rgbGreen, color.rgbBlue); 
			if (YVal > high ) high = YVal; 
		} 
	} 
 
	// Root Operator 
	double k = 128.0 / ::log( 1.0 + (double)high ); 
	if( head.biClrUsed == 0 ){ 
		for( y = 0; y < head.biHeight; y++ ){ 
			info.nProgress = (long)(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 = (BYTE)dtmp; 
 
				color = YUVtoRGB( yuvClr ); 
				BlindSetPixelColor( x, y, color ); 
			} 
		} 
	} else { 
		for(i = 0; i < (int)head.biClrUsed; i++){ 
 
			color = GetPaletteColor( (BYTE)i ); 
			yuvClr = RGBtoYUV( color ); 
 
			dtmp = k * ::sqrt( (double)yuvClr.rgbRed ); 
			if ( dtmp > 255.0 )	dtmp = 255.0; 
			if ( dtmp < 0 ) dtmp = 0; 
            yuvClr.rgbRed = (BYTE)dtmp; 
 
			color = YUVtoRGB( yuvClr ); 
 			SetPaletteColor( (BYTE)i, color ); 
		} 
	} 
  
	return true; 
} 
//////////////////////////////////////////////////////////////////////////////// 
#endif