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