2008年11月5日

双线性内插值法简单实现

图像缩放有几种常见的算法:最邻近插值(近邻取样法)、双线性内插值和三次卷积法,从得到的图像质量来说分别从低到高,从耗费的时间来看是从少到多。

Windows系统的函数StretchDIBits采用的是最邻近插值法,其运算速度最快,不过得到的图像质量也是惨不忍睹,下面是个对比:

frame_3.jpg2.JPG

原始图片为手机拍摄,size为320X240,右边是用windows自带的StretchDIBits放大两倍的结果,左边是采用双线性内插值法缩放的结果,注意观察图像中有斜线条的地方,最邻近插值法明显看到大量锯齿,而双线性内插值法则有效的消除了这些锯齿的产生。下面是转换函数代码,src为输入RGB数据(24位色),width和height为原始宽高,dest为输出的2倍大小的RGB数据。

void resize_rgbbuf(unsigned char * dest,unsigned char * src,int width,int height)
{
int sw = width - 1, sh = height - 1, dw = width*2 - 1, dh = height*2 - 1;

int B, N, x, y;
int nPixelSize = 3; // 24 color,3 bytes each pixel
BYTE * pLinePrev, *pLineNext;
BYTE * pDest;
BYTE * pA, *pB, *pC, *pD;


for ( int i = 0; i <= dh; ++i )
{
pDest = ( BYTE * )dest+i*width*2*3;
y = i * sh / dh;
N = dh - i * sh % dh;

pLinePrev = ( BYTE * )src+y*width*3;
y++;
pLineNext = ( N == dh ) ? pLinePrev : ( BYTE * )src+y*width*3;

for ( int j = 0; j <= dw; ++j )
{
x = j * sw / dw * nPixelSize;
B = dw - j * sw % dw;
pA = pLinePrev + x;
pB = pA + nPixelSize;
pC = pLineNext + x;
pD = pC + nPixelSize;
if ( B == dw )
{
pB = pA;
pD = pC;
}

for ( int k = 0; k < nPixelSize; ++k )
*pDest++ = ( BYTE )( int )(
( B * N * ( *pA++ - *pB - *pC + *pD ) + dw * N * *pB++
+ dh * B * *pC++ + ( dw * dh - dh * B - dw * N ) * *pD++
+ dw * dh / 2 ) / ( dw * dh )
);
}
}
return;

}


Full Text