现在的位置: 首页 > 综合 > 正文

图形图像处理-之-误差扩散 下篇

2012年08月07日 ⁄ 综合 ⁄ 共 4798字 ⁄ 字号 评论关闭
  HouSisong@GMail.com   2008.04.22
 
tag: 误差扩散,真彩色到高彩色转换
  
摘要: 在图像的颜色转换过程中,由于颜色值域的不同,转换过程中可能会产生误差;
误差扩散算法通过将误差传递到周围像素而减轻其造成的视觉误差。
       
正文:
  代码使用C++,编译器:VC2005
  测试平台:(CPU:AMD64x2 4200+(2.37G); 内存:DDR2 677(双通道); 编译器:VC2005)
  
(请先参看文章的上篇)
 
 
E: 将误差扩散的浮点实现改写为一个整数的定点数实现:

    struct TErrorColor{
        
long
 dR;
        
long
 dG;
        
long
 dB;
    };

    inline long getBestRGB16_555Color(const long wantColor){
        
const long rMax=(1<<5)-1
;
        
if (wantColor<=0

            
return 0
;
        
else if (wantColor>=(rMax<<3
))
            
return
 rMax;
        
else

            
return wantColor>>3;
    }
    inline 
long getC8Color(const long
 rColor){
        
return rColor*(((1<<16)*255+30)/31>>16
;
    }
    
void CvsPic32To16_ErrorDiffuse_Line_1(TUInt16* pDst,const TARGB32* pSrc,long width,TErrorColor*
 PHLineErr){
        TErrorColor HErr;
        HErr.dR
=0; HErr.dG=0; HErr.dB=0
;
        PHLineErr[
-1].dB=0; PHLineErr[-1].dG=0; PHLineErr[-1].dR=0

        
for (long x=0;x<width;++
x)
        {
            
long cB=(pSrc[x].b+HErr.dB*2+PHLineErr[x].dB+PHLineErr[x-1
].dB);
            
long cG=(pSrc[x].g+HErr.dG*2+PHLineErr[x].dG+PHLineErr[x-1
].dG);
            
long cR=(pSrc[x].r+HErr.dR*2+PHLineErr[x].dR+PHLineErr[x-1
].dR);
            
long rB=
getBestRGB16_555Color(cB);
            
long rG=
getBestRGB16_555Color(cG);
            
long rR=
getBestRGB16_555Color(cR);
            pDst[x]
= rB|(rG<<5)|(rR<<10
);

            HErr.dB=(cB-getC8Color(rB))>>2;
            HErr.dG
=(cG-getC8Color(rG))>>2
;
            HErr.dR
=(cR-getC8Color(rR))>>2
;

            PHLineErr[x-1].dB+=HErr.dB;
            PHLineErr[x
-1].dG+=
HErr.dG;
            PHLineErr[x
-1].dR+=
HErr.dR;

            PHLineErr[x]=HErr;
        }
    }

void CvsPic32To16_ErrorDiffuse_1(const TPicRegion_RGB16_555& dst,const TPicRegion& src){
    TUInt16
* pDst=(TUInt16*
)dst.pdata;
    
const TARGB32* pSrc=
src.pdata;
    
const long width=
src.width;

    TErrorColor* _HLineErr=new TErrorColor[width+2]; 
    
for (long x=0;x<width+2;++
x){
        _HLineErr[x].dR
=0
;
        _HLineErr[x].dG
=0
;
        _HLineErr[x].dB
=0
;
    }
    TErrorColor
* HLineErr=&_HLineErr[1
];

    for (long y=0;y<src.height;++y){
        CvsPic32To16_ErrorDiffuse_Line_1(pDst,pSrc,width,HLineErr);
        (TUInt8
*&)pDst+=
dst.byte_width;
        (TUInt8
*&)pSrc+=
src.byte_width;
    }

    delete[]_HLineErr;
}

速度测试:
//////////////////////////////////////////////////////////////
//CvsPic32To16_ErrorDiffuse_1     154.4  FPS
//////////////////////////////////////////////////////////////
 
F:继续优化
 getBestRGB16_555Color函数有条件分支,建立一个查找表来代替,完整的实现如下:
 (CvsPic32To16_ErrorDiffuse_Line_2和CvsPic32To16_ErrorDiffuse_Line_1完成的功能一致)

    static TUInt8 _BestRGB16_555Color_Table[256*5];
    
const TUInt8* BestRGB16_555Color_Table=&_BestRGB16_555Color_Table[256*2
];
    
struct
 _TAutoInit_BestRGB16_555Color_Table{
        _TAutoInit_BestRGB16_555Color_Table(){
            
for (long i=0;i<256*5;++
i){
                _BestRGB16_555Color_Table[i]
=getBestRGB16_555Color(i-256*2
);
            }
        }
    };
    
static
 _TAutoInit_BestRGB16_555Color_Table _AutoInit_BestRGB16_555Color_Table;

    void CvsPic32To16_ErrorDiffuse_Line_2(TUInt16* pDst,const TARGB32* pSrc,long width,TErrorColor* PHLineErr){
        TErrorColor HErr;
        HErr.dR
=0; HErr.dG=0; HErr.dB=0
;
        PHLineErr[
-1].dB=0; PHLineErr[-1].dG=0; PHLineErr[-1].dR=0

        
for (long x=0;x<width;++
x)
        {
            
long cB=(pSrc[x].b+HErr.dB*2+PHLineErr[x].dB+PHLineErr[x-1
].dB);
            
long cG=(pSrc[x].g+HErr.dG*2+PHLineErr[x].dG+PHLineErr[x-1
].dG);
            
long cR=(pSrc[x].r+HErr.dR*2+PHLineErr[x].dR+PHLineErr[x-1
].dR);
            
long rB=
BestRGB16_555Color_Table[cB];
            
long rG=
BestRGB16_555Color_Table[cG];
            
long rR=
BestRGB16_555Color_Table[cR];
            pDst[x]
= rB|(rG<<5)|(rR<<10
);

            HErr.dB=(cB-getC8Color(rB))>>2;
            HErr.dG
=(cG-getC8Color(rG))>>2
;
            HErr.dR
=(cR-getC8Color(rR))>>2
;

            PHLineErr[x-1].dB+=HErr.dB;
            PHLineErr[x
-1].dG+=
HErr.dG;
            PHLineErr[x
-1].dR+=
HErr.dR;

            PHLineErr[x]=HErr;
        }
    }
 
void CvsPic32To16_ErrorDiffuse_2(const TPicRegion_RGB16_555& dst,const TPicRegion&
 src){
    TUInt16
* pDst=(TUInt16*
)dst.pdata;
    
const TARGB32* pSrc=
src.pdata;
    
const long width=
src.width;

    TErrorColor* _HLineErr=new TErrorColor[width+2]; 
    
for (long x=0;x<width+2;++
x){
        _HLineErr[x].dR
=0
;
        _HLineErr[x].dG
=0
;
        _HLineErr[x].dB
=0
;
    }
    TErrorColor
* HLineErr=&_HLineErr[1
];

    for (long y=0;y<src.height;++y){
        CvsPic32To16_ErrorDiffuse_Line_2(pDst,pSrc,width,HLineErr);
        (TUInt8
*&)pDst+=
dst.byte_width;
        (TUInt8
*&)pSrc+=
src.byte_width;
    }

    delete[]_HLineErr;
}

 
速度测试:
//////////////////////////////////////////////////////////////
//CvsPic32To16_ErrorDiffuse_2     166.8  FPS
//////////////////////////////////////////////////////////////

函数效果:


抱歉!评论已关闭.