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相互转换。