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++技术内幕,清华大学出版社.
|