2012-03-17 10:40:23|?次阅读|上传:wustguangh【已有?条评论】发表评论
关键词:C/C++, 图形/图像, MFC|来源:唯设编程网
VC编程实现位图拷贝、切除空白边介绍了VC实现位图图像拷贝,切除二值图空白边,本文继续介绍位图处理类CImageUtility的其它成员方法,着重介绍VC编程实现位图图像自动色阶的功能。
根据互联网搜索的结果,位图图像自动色阶算法主要包含两种方案,一种是拉开LAB色彩空间的L(亮度)分量,使图像的亮度区域拉开,第二种是讲图像的RGB各分量值的区域拉开。第一种方案效果较好,但是计算比较复杂,需要用到前面介绍的色彩空间转换,第二种方案计算简单,但是效果不如前一种方案,下面列出具体的VC实现源码和处理效果,读者可以根据实际需要进行选用。
// 自动色阶 // gType 自动色阶的算法 // darkLimen 暗调阈值 // brightLimen 高光阈值 void CImageUtility::ImageAutoGradationProcess(AutoGradationType gType,double darkLimen,double brightLimen){ // 目前只处理24位以上的位图 if(nPixBytes <3) return; //临时保存像素点的颜色 int nRGB[3]={0,0,0}; switch(gType){ case g_L_VALUE:{ //通过LAB中的L分量自动色阶 //保存每个亮度分量的像素个数 unsigned long gradation[101]; for(size_t i=0;i<101;i++) gradation[i]=0; //保存亮度最多的像素个数 unsigned long maxPixle=0; // 暗调阈值序号 int darkPos=0; // 高光阈值序号 int lightPos=0; double LAB[3]={0.0,0.0,0.0}; for(long nHeight=0; nHeight<bmSrcInfo.bmHeight; nHeight++) { for(long nWidth=0; nWidth<bmSrcInfo.bmWidth; nWidth++) { //获取对应像素点得颜色 getPixelColor(nRGB,nHeight,nWidth); //转换颜色到LAB色彩空间 CColorUtility::_cie_rgb2lab(nRGB,LAB); //对应亮度的像素点个数加1 gradation[(int)(LAB[0]+0.5)]++; //LAB中的L分量【0.0-100.0】 if(maxPixle<gradation[(int)(LAB[0]+0.5)]) maxPixle=gradation[(int)(LAB[0]+0.5)]; } } //分析直方图 // 暗调位置 for(size_t i=0;i<101;i++){ if(((long double)(gradation[i]))/maxPixle>darkLimen){ darkPos=i; break; } } // 高光位置 for(size_t i=100;i>=0;i--){ if(((long double)(gradation[i]))/maxPixle>brightLimen){ lightPos=i; break; } } //对像素进行处理 double offsetLight=(lightPos+darkPos)/2-50.0; //中间亮度偏移 double quotiety=100.0/(lightPos-darkPos); //亮度缩放系数 for(long nHeight=0; nHeight<bmSrcInfo.bmHeight; nHeight++) { for(long nWidth=0; nWidth<bmSrcInfo.bmWidth; nWidth++) { //获取对应像素点得颜色 getPixelColor(nRGB,nHeight,nWidth); //转换颜色到LAB色彩空间 CColorUtility::_cie_rgb2lab(nRGB,LAB); //移动当前亮度的中心到自动色阶后亮度的中心 LAB[0]=LAB[0]-offsetLight; //计算当前亮度与中心的距离 LAB[0]-=50; //将距离乘于系数加上中心位置及时当前亮度最终的位置 LAB[0]=quotiety*LAB[0]+50; //重新给像素点赋值 CColorUtility::_cie_lab2rgb(LAB,nRGB); //设置像素点颜色 setPixelColor(nRGB,nHeight,nWidth); } } break; } // 还有问题,有待研究 case g_RGB:{ //通过RGB自动色阶 //保存每个亮度分量的像素个数 unsigned long gradation[3][256]; for(size_t i=0;i<3;i++) for(size_t j=0;j<256;j++) gradation[i][j]=0; //保存亮度最多的像素个数 unsigned long maxPixle[3]={0,0,0}; // 暗调阈值序号 int darkPos[3]={0,0,0}; // 高光阈值序号 int lightPos[3]={0,0,0}; for(long nHeight=0; nHeight<bmSrcInfo.bmHeight; nHeight++) { for(long nWidth=0; nWidth<bmSrcInfo.bmWidth; nWidth++) { //获取对应像素点得颜色 getPixelColor(nRGB,nHeight,nWidth); for(int i=0;i<3;i++){ //保存每种颜色分量的像素个数 gradation[i][nRGB[i]]++; //保存每种颜色分量最大的像素个数 if(maxPixle[i]<gradation[i][nRGB[i]]) maxPixle[i]=gradation[i][nRGB[i]]; } } } //分析直方图 // 暗调位置 for(size_t i=0;i<3;i++){ for(size_t j=0;j<256;j++){ if(((long double)(gradation[i][j]))/maxPixle[i]>darkLimen){ darkPos[i]=j; break; } } } // 高光位置 for(size_t i=0;i<3;i++){ for(size_t j=255;j>=0;j--){ if(((long double)(gradation[i][j]))/maxPixle[i]>brightLimen){ lightPos[i]=j; break; } } } //对像素进行处理 int offsetLight[3]={0,0,0}; for(int i=0;i<3;i++) offsetLight[i]=(lightPos[i]+darkPos[i])/2-128; //中间亮度偏移 double quotiety[3]={0.0,0.0,0.0}; for(int i=0;i<3;i++) quotiety[i]=255.0/(lightPos[i]-darkPos[i]); //亮度缩放系数 for(long nHeight=0; nHeight<bmSrcInfo.bmHeight; nHeight++) { for(long nWidth=0; nWidth<bmSrcInfo.bmWidth; nWidth++) { //获取对应像素点得颜色 getPixelColor(nRGB,nHeight,nWidth); for(int i=0;i<3;i++){ //移动当前亮度的中心到自动色阶后亮度的中心 nRGB[i]=nRGB[i]-offsetLight[i]; //计算当前亮度与中心的距离 nRGB[i]-=128; //将距离乘于系数加上中心位置及时当前亮度最终的位置 nRGB[i]=(int)(quotiety[i]*nRGB[i])+128; } //设置像素点颜色 setPixelColor(nRGB,nHeight,nWidth); } } break; } } //switch over bmpSrc->SetBitmapBits(dwBmByteSize, pBmBits); }
2.1 LAB亮度分量实现自动色阶:
2.2 RGB实现自动色阶:
对于RGB色彩空间与LAB色彩空间的转换,读者可以参考:VC编程实现色彩空间RGB与XYZ相互转换、VC编程实现色彩空间XYZ与LAB相互转换。