| 
				 2.核心代码 
//函数名Bilinear 
//参数float k 
//返回值无 
//作用利用双线性插值来实现图像缩放 
void CChildView::Bilinear(float k) 
{    
    int nBpp=m_imPicture .GetBPP ();     
    int widthNew,heightNew;//新图像的宽度和高度  
    float widthScale=(float)(1.0/k),heightScale=(float)(1.0/k); 
    float xx,yy; 
    int a,b; 
    int rr,gg,bb;//保存R、G、B分量 
    //得到新图像的宽度和高度 
    widthNew=(int)(m_imPicture .GetWidth ()*k); 
    heightNew =(int)(m_imPicture .GetHeight ()*k); 
    //利用新图像的宽度和高度来创建新图像 
    m_imNewPicture .Destroy (); 
    m_imNewPicture .Create (widthNew ,heightNew ,nBpp); 
    //得到新、老图像的每行的字节数 
    int nPitch=m_imPicture .GetPitch (); 
    int nPitchNew=m_imNewPicture .GetPitch (); 
    //得到新、老图像的数据指针 
    LPBYTE pBitsNew=(LPBYTE)m_imNewPicture .GetBits (); 
    LPBYTE pBits=(LPBYTE)m_imPicture .GetBits ();    
    if(m_imPicture.GetBPP ()!=24){ 
        MessageBox ("必须是24位图像或8位图像"); 
        m_imNewPicture .Destroy (); 
        Invalidate(); 
        return ; 
    }    
    for(int x=(int)k;x<widthNew -k;x++){ 
        for(int y=(int)k;y<heightNew -k;y++){ 
            xx=x*widthScale ; 
            yy=y*heightScale ; 
            if(xx<=1e-8){ 
                xx=0; 
            } 
            if(xx>m_imPicture .GetWidth ()-2) 
                xx=(float)(m_imPicture .GetWidth ()-2); 
            if(yy<=1e-8) 
                yy=0; 
            if(yy>m_imPicture .GetHeight ()-2) 
                yy=(float)(m_imPicture .GetHeight ()-2); 
            a=(int)xx; 
            b=(int)yy;           
            //分别得到对应像素的R、G、B值并用双线性插值得到新像素的R、G、B值 
            int r11,r12,r21,r22; 
            r11=*(pBits+b*nPitch+3*a+2); 
            r12=*(pBits+b*nPitch+3*(a+1)+2); 
            r21=*(pBits+(b+1)*nPitch+3*a+2); 
            r22=*(pBits+(b+1)*nPitch+3*(a+1)+2); 
            rr=(int)(r11*(a+1-xx)*(b+1-yy)+r12*(a+1-xx)*(yy-b) 
                +r21*(xx-a)*(b+1-yy)+r22*(xx-a)*(yy-b)); 
  
            int g11,g12,g21,g22; 
            g11=*(pBits+b*nPitch+3*a+1); 
            g12=*(pBits+b*nPitch+3*(a+1)+1); 
            g21=*(pBits+(b+1)*nPitch+3*a+1); 
            g22=*(pBits+(b+1)*nPitch+3*(a+1)+1); 
            gg=(int)(g11*(a+1-xx)*(b+1-yy)+g12*(a+1-xx)*(yy-b) 
                +g21*(xx-a)*(b+1-yy)+g22*(xx-a)*(yy-b)); 
  
            int b11,b12,b21,b22; 
            b11=*(pBits+b*nPitch+3*a); 
            b12=*(pBits+b*nPitch+3*(a+1)); 
            b21=*(pBits+(b+1)*nPitch+3*a); 
            b22=*(pBits+(b+1)*nPitch+3*(a+1)); 
            bb=(int)(b11*(a+1-xx)*(b+1-yy)+b12*(a+1-xx)*(yy-b) 
                +b21*(xx-a)*(b+1-yy)+b22*(xx-a)*(yy-b)); 
            //将得到的新R、G、B值写到新图像中            
            *(pBitsNew +y*nPitchNew +x*3)=min(255,bb); 
            *(pBitsNew +y*nPitchNew +x*3+1)=min(255,gg); 
            *(pBitsNew +y*nPitchNew +x*3+2)=min(255,rr); 
        }        
    }        
    m_imPicture .Destroy (); 
    Invalidate (); 
} 
五.结语 
   本文介绍了一种利用双线性插值来实现图像缩放的算法,通过图2左图是利用本文介绍的双线性插值算法缩小一倍得到图像,右图是利用StretchBlt缩小一倍得到图像可以看到这种算法和传统的利用StretchBlt来实现图像缩放相比具有很大的改善。StretchBlt实现的图像具有很大的失真,并且随着缩小的比率越大失真也越严重;而双线性插值算法则很好的解决了这个问题,可以得到很高的清晰度,这种方法可以广泛应用在图像变形、计算机动画、计算机辅助设计等领域。所附源代码在VC++.NET 2003下编译通过。 
 
 
  
图2 
  
参考文献 
  
[1]求是科技. Visual C++数字图像处理典型算法及实现. 人民邮电出版社,2006. 
[2]K.R.Castleman. 数字图像处理. 电子工业出版社,2002. 
[3]Donald Hearn等计算机图形学. 电子工业出版社,2007. [4]Kruglinski D.J. Visual C++技术内幕,清华大学出版社.			
				 |