VC编程实现对位图图像自动色阶处理

2012-03-17 10:40:23|?次阅读|上传:wustguangh【已有?条评论】发表评论

关键词:C/C++, 图形/图像, MFC|来源:唯设编程网

VC编程实现位图拷贝、切除空白边介绍了VC实现位图图像拷贝,切除二值图空白边,本文继续介绍位图处理类CImageUtility的其它成员方法,着重介绍VC编程实现位图图像自动色阶的功能。

根据互联网搜索的结果,位图图像自动色阶算法主要包含两种方案,一种是拉开LAB色彩空间的L(亮度)分量,使图像的亮度区域拉开,第二种是讲图像的RGB各分量值的区域拉开。第一种方案效果较好,但是计算比较复杂,需要用到前面介绍的色彩空间转换,第二种方案计算简单,但是效果不如前一种方案,下面列出具体的VC实现源码和处理效果,读者可以根据实际需要进行选用。

1. 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. 效果对比

2.1 LAB亮度分量实现自动色阶:

VC实现位图自动色阶算法

2.2 RGB实现自动色阶:

VC实现位图自动色阶功能

对于RGB色彩空间与LAB色彩空间的转换,读者可以参考:VC编程实现色彩空间RGB与XYZ相互转换VC编程实现色彩空间XYZ与LAB相互转换

发表评论0条 】
网友评论(共?条评论)..
VC编程实现对位图图像自动色阶处理