双线性插值图像放大/缩小算法

 

图像的双线性插值放大算法中,目标图像中新创造的象素值,是由源图像位置在它附近的2*2区域4个邻近象素的值通过加权平均计算得出的。双线性内插值算法放大后的图像质量较高,不会出现像素值不连续的的情况。然而次算法具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。

 

算法中Q12, Q22, Q11, Q21的选取

 

我们以放大两倍为例,说明选取Q12, Q22, Q11, Q21的过程。源图像3*3区域放大为目标区域6*6区域。设以下为目标图像:

A

A

B

B

 

 

A

A

B

B

 

 

 

 

C

C

 

 

 

 

C

C

 

 

 

 

 

 

D

D

 

 

 

 

D

D

图2

目标图像A像素区域对应的Q21Q22Q11Q12,以红色区域为原点向右下方扩展的2*2区域。

Q21

Q22

 

Q11

Q12

 

 

 

 

图3

目标图像B像素区域对应的Q21Q22Q11Q12,以蓝色区域为原点向右下方扩展的2*2区域。

 

Q21

Q22

 

Q11

Q12

 

 

 

图4

目标图像C像素区域对应的Q21Q22Q11Q12,以绿色区域为原点向右下方扩展的2*2区域。

 

 

 

 

Q21

Q22

 

Q11

Q12

图5

目标图像D像素区域对应的Q21Q22Q11Q12,目标图像处于最后两行的边界情况,将Q21Q22Q11Q12这四个点的值设为一样。

 

 

 

 

 

 

 

 

Q11=Q12=Q22=Q21

图6

 

程序流程图

流程图右边虚线框中为相关过程的注解。

 

双线性插值图像放大/缩小算法_第1张图片

双线性插值图像放大/缩小算法_第2张图片

 

源码:

void ResizeImage( unsigned char *InImage, // Source image data unsigned char *OutImage, // Destination image data unsigned int SWidth, // Source image width unsigned int SHeight, // Source image height unsigned int DWidth, // Destination rectangle width unsigned int DHeight, // Destination rectangle height unsigned int dstWholeWidth, // Destination image width unsigned int dstWholeHeight // Destination image height ) { unsigned int PtAR = 0, PtBR = 0, PtCR = 0, PtDR = 0, PixelValueR = 0; unsigned int PtAG = 0, PtBG = 0, PtCG = 0, PtDG = 0, PixelValueG = 0; unsigned int PtAB = 0, PtBB = 0, PtCB = 0, PtDB = 0, PixelValueB = 0; register unsigned SpixelColNum = 0, SpixelRowNum = 0, DestCol = 0, DestRow = 0; unsigned int SpixelColAddr = 0, SpixelRowAddr = 0; unsigned int ColDelta = 0, RowDelta = 0, scaleV = 0, scaleH = 0; unsigned int ContribAandBR = 0, ContribCandDR = 0; unsigned int ContribAandBG = 0, ContribCandDG = 0; unsigned int ContribAandBB = 0, ContribCandDB = 0; unsigned int ContribTem[4096 * 3];// max size of image is 4096 int i = 0; unsigned int FromLeftX = dstWholeWidth / 4, FromTopY = dstWholeHeight / 8 + DWidth / 8; scaleH = (SWidth << 8) / DWidth; scaleV = (SHeight << 8) / DHeight; // First line for (DestCol = 0; DestCol < DWidth; DestCol++) { SpixelColAddr = DestCol * scaleH; ColDelta = SpixelColAddr & 255; SpixelColNum = (SpixelColAddr - ColDelta) >> 8; PtAB = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum]; PtAG = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 1]; PtAR = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 2]; if ((SpixelColNum + 1) < SWidth) { PtBB = InImage[3 * SpixelRowNum * SWidth + 3 * (SpixelColNum + 1)]; PtBG = InImage[3 * SpixelRowNum * SWidth + 3 * (SpixelColNum + 1) + 1]; PtBR = InImage[3 * SpixelRowNum * SWidth + 3 * (SpixelColNum + 1) + 2]; PtCB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum]; PtCG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 1]; PtCR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 2]; PtDB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1)]; PtDG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 1]; PtDR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 2]; } else { PtBB = PtCB = PtDB = PtAB; PtBG = PtCG = PtDG = PtAG; PtBR = PtCR = PtDR = PtAR; } ContribAandBB = ColDelta * (PtBB - PtAB) + (PtAB << 8); ContribCandDB = ColDelta * (PtDB - PtCB) + (PtCB << 8); ContribTem[i++] = ContribCandDB; PixelValueB = ((ContribAandBB << 8) + (ContribCandDB - ContribAandBB) * RowDelta) >> 16; ContribAandBG = ColDelta * (PtBG - PtAG) + (PtAG << 8); ContribCandDG = ColDelta * (PtDG - PtCG) + (PtCG << 8); ContribTem[i++] = ContribCandDG; PixelValueG = ((ContribAandBG << 8) + (ContribCandDG - ContribAandBG) * RowDelta) >> 16; ContribAandBR = ColDelta * (PtBR - PtAR) + (PtAR << 8); ContribCandDR = ColDelta * (PtDR - PtCR) + (PtCR << 8); ContribTem[i++] = ContribCandDR; PixelValueR = ((ContribAandBR << 8) + (ContribCandDR - ContribAandBR) * RowDelta) >> 16; OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX)] = PixelValueB; OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 1] = PixelValueG; OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 2] = PixelValueR; } // Other line for (DestRow = 1; DestRow < DHeight; DestRow++) { i = 0; SpixelRowAddr = DestRow * scaleV; RowDelta = SpixelRowAddr & 255; SpixelRowNum = (SpixelRowAddr - RowDelta) >> 8; for (DestCol = 0; DestCol < DWidth; DestCol++) { SpixelColAddr = DestCol * scaleH; ColDelta = SpixelColAddr & 255; SpixelColNum = (SpixelColAddr - ColDelta) >> 8; PtAB = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum]; PtAG = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 1]; PtAR = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 2]; if (((SpixelColNum + 1) < SWidth) && ((SpixelRowNum + 1) < SHeight)) { PtCB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum]; PtCG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 1]; PtCR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 2]; PtDB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1)]; PtDG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 1]; PtDR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 2]; } else { PtBB = PtCB = PtDB = PtAB; PtBG = PtCG = PtDG = PtAG; PtBR = PtCR = PtDR = PtAR; } ContribAandBB = ContribTem[i]; ContribCandDB = ColDelta * (PtDB - PtCB) + (PtCB << 8); ContribTem[i++] = ContribCandDB; PixelValueB = ((ContribAandBB << 8) + (ContribCandDB - ContribAandBB) * RowDelta) >> 16; ContribAandBG = ContribTem[i]; ContribCandDG = ColDelta * (PtDG - PtCG) + (PtCG << 8); ContribTem[i++] = ContribCandDG; PixelValueG = ((ContribAandBG << 8) + (ContribCandDG - ContribAandBG) * RowDelta) >> 16; ContribAandBR = ContribTem[i]; ContribCandDR = ColDelta * (PtDR - PtCR) + (PtCR << 8); ContribTem[i++] = ContribCandDR; PixelValueR = ((ContribAandBR << 8) + (ContribCandDR - ContribAandBR) * RowDelta) >> 16; OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX)] = PixelValueB; OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 1] = PixelValueG; OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 2] = PixelValueR; } } } int ResizeBitmapImage(char* szFilenameIn, char *szFilenameOut) { int nRes; CImage ImageIn; CImage ImageOut; int dstWholeWidth = 1024, dstWholeHeight = 768; if (GetFileAttributes(szFilenameIn) == -1) { printf( "ERROR: file '%s'/n not found", szFilenameIn); return 1; } if (ImageIn.Load(szFilenameIn) != 0) { printf( "ERROR: can't load '%s'/n", szFilenameIn); return 1; } if (ImageIn.m_BitPerPixel != 24) { if (ImageIn.ConvertTo24() != 0) { printf("ERROR: '%s' conversion to 24 bit failed/n", szFilenameIn); } } if (ImageOut.Init(dstWholeWidth, dstWholeHeight, 24) != 0) { printf("ERROR: ImageOut.Init()/n"); return 1; }; ResizeImage(ImageIn.m_pBitmap, ImageOut.m_pBitmap, ImageIn.m_Xres, ImageIn.m_Yres, dstWholeWidth / 2, dstWholeHeight / 2, dstWholeWidth, dstWholeHeight); nRes = ImageOut.Save(szFilenameOut); if (nRes != 0) { printf("ERROR %i: ImageOut.Save(/"%s/")/n", nRes, szFilenameOut); return nRes; } return 0; }

 

你可能感兴趣的:(c,算法,image,File,扩展)