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

图像的双线性插值放大算法中,目标图像中新创造的象素值,是由源图像位置在它附近的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像素区域对应的Q21,Q22,Q11,Q12,以红色区域为原点向右下方扩展的2*2区域。

Q21

Q22

 

Q11

Q12

 

 

 

 

图3

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

 

Q21

Q22

 

Q11

Q12

 

 

 

图4

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

 

 

 

 

Q21

Q22

 

Q11

Q12

图5

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

 

 

 

 

 

 

 

 

Q11=Q12=Q22=Q21

图6

 

程序流程图

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

 

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

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

 

源码:

[cpp:nogutter]  view plain copy
  1. void ResizeImage(  
  2.                  unsigned char *InImage, // Source image data  
  3.                  unsigned char *OutImage, // Destination image data  
  4.                  unsigned int SWidth, // Source image width  
  5.                  unsigned int SHeight, // Source image height  
  6.                  unsigned int DWidth, // Destination rectangle width  
  7.                  unsigned int DHeight, // Destination rectangle height  
  8.                  unsigned int dstWholeWidth, // Destination image width   
  9.                  unsigned int dstWholeHeight // Destination image height   
  10.                  )    
  11. {  
  12.     unsigned int PtAR = 0, PtBR = 0, PtCR = 0, PtDR = 0, PixelValueR = 0;  
  13.     unsigned int PtAG = 0, PtBG = 0, PtCG = 0, PtDG = 0, PixelValueG = 0;  
  14.     unsigned int PtAB = 0, PtBB = 0, PtCB = 0, PtDB = 0, PixelValueB = 0;  
  15.     register unsigned SpixelColNum = 0, SpixelRowNum = 0, DestCol = 0, DestRow = 0;  
  16.     unsigned int SpixelColAddr = 0, SpixelRowAddr = 0;  
  17.     unsigned int ColDelta = 0, RowDelta = 0, scaleV = 0, scaleH = 0;  
  18.     unsigned int ContribAandBR = 0, ContribCandDR = 0;  
  19.     unsigned int ContribAandBG = 0, ContribCandDG = 0;  
  20.     unsigned int ContribAandBB = 0, ContribCandDB = 0;  
  21.     unsigned int ContribTem[4096 * 3];// max size of image is 4096  
  22.     int i = 0;  
  23.     unsigned int FromLeftX = dstWholeWidth / 4, FromTopY = dstWholeHeight / 8 + DWidth / 8;  
  24.   
  25.     scaleH = (SWidth << 8) / DWidth;  
  26.     scaleV = (SHeight << 8) / DHeight;  
  27.   
  28.     // First line  
  29.     for (DestCol = 0; DestCol < DWidth; DestCol++)  
  30.     {  
  31.         SpixelColAddr = DestCol * scaleH;  
  32.         ColDelta = SpixelColAddr & 255;  
  33.         SpixelColNum = (SpixelColAddr - ColDelta) >> 8;  
  34.   
  35.         PtAB = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum];  
  36.         PtAG = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 1];  
  37.         PtAR = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 2];  
  38.   
  39.         if ((SpixelColNum + 1) < SWidth)  
  40.         {  
  41.             PtBB = InImage[3 * SpixelRowNum * SWidth + 3 * (SpixelColNum + 1)];  
  42.             PtBG = InImage[3 * SpixelRowNum * SWidth + 3 * (SpixelColNum + 1) + 1];  
  43.             PtBR = InImage[3 * SpixelRowNum * SWidth + 3 * (SpixelColNum + 1) + 2];  
  44.   
  45.             PtCB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum];  
  46.             PtCG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 1];  
  47.             PtCR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 2];  
  48.   
  49.             PtDB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1)];  
  50.             PtDG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 1];  
  51.             PtDR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 2];  
  52.         }  
  53.         else  
  54.         {  
  55.             PtBB = PtCB = PtDB = PtAB;  
  56.             PtBG = PtCG = PtDG = PtAG;  
  57.             PtBR = PtCR = PtDR = PtAR;  
  58.         }  
  59.         ContribAandBB = ColDelta * (PtBB - PtAB) + (PtAB << 8);  
  60.         ContribCandDB = ColDelta * (PtDB - PtCB) + (PtCB << 8);  
  61.         ContribTem[i++] = ContribCandDB;  
  62.         PixelValueB = ((ContribAandBB << 8) + (ContribCandDB - ContribAandBB) * RowDelta) >> 16;  
  63.   
  64.         ContribAandBG = ColDelta * (PtBG - PtAG) + (PtAG << 8);  
  65.         ContribCandDG = ColDelta * (PtDG - PtCG) + (PtCG << 8);  
  66.         ContribTem[i++] = ContribCandDG;  
  67.         PixelValueG = ((ContribAandBG << 8) + (ContribCandDG - ContribAandBG) * RowDelta) >> 16;  
  68.   
  69.         ContribAandBR = ColDelta * (PtBR - PtAR) + (PtAR << 8);  
  70.         ContribCandDR = ColDelta * (PtDR - PtCR) + (PtCR << 8);  
  71.         ContribTem[i++] = ContribCandDR;  
  72.         PixelValueR = ((ContribAandBR << 8) + (ContribCandDR - ContribAandBR) * RowDelta) >> 16;  
  73.   
  74.         OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX)] = PixelValueB;  
  75.         OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 1] = PixelValueG;  
  76.         OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 2] = PixelValueR;  
  77.     }  
  78.     // Other line  
  79.     for (DestRow = 1; DestRow < DHeight; DestRow++)  
  80.     {  
  81.         i = 0;  
  82.         SpixelRowAddr = DestRow * scaleV;  
  83.         RowDelta = SpixelRowAddr & 255;  
  84.         SpixelRowNum = (SpixelRowAddr - RowDelta) >> 8;  
  85.   
  86.         for (DestCol = 0; DestCol < DWidth; DestCol++)  
  87.         {  
  88.             SpixelColAddr = DestCol * scaleH;  
  89.             ColDelta = SpixelColAddr & 255;  
  90.             SpixelColNum = (SpixelColAddr - ColDelta) >> 8;  
  91.   
  92.             PtAB = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum];  
  93.             PtAG = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 1];  
  94.             PtAR = InImage[3 * SpixelRowNum * SWidth + 3 * SpixelColNum + 2];  
  95.   
  96.             if (((SpixelColNum + 1) < SWidth) && ((SpixelRowNum + 1) < SHeight))  
  97.             {  
  98.                 PtCB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum];  
  99.                 PtCG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 1];  
  100.                 PtCR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * SpixelColNum + 2];  
  101.   
  102.                 PtDB = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1)];  
  103.                 PtDG = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 1];  
  104.                 PtDR = InImage[3 * (SpixelRowNum + 1) * SWidth + 3 * (SpixelColNum + 1) + 2];  
  105.             }  
  106.             else  
  107.             {  
  108.                 PtBB = PtCB = PtDB = PtAB;  
  109.                 PtBG = PtCG = PtDG = PtAG;  
  110.                 PtBR = PtCR = PtDR = PtAR;  
  111.             }  
  112.   
  113.             ContribAandBB = ContribTem[i];  
  114.             ContribCandDB = ColDelta * (PtDB - PtCB) + (PtCB << 8);  
  115.             ContribTem[i++] = ContribCandDB;  
  116.             PixelValueB = ((ContribAandBB << 8) + (ContribCandDB - ContribAandBB) * RowDelta) >> 16;  
  117.   
  118.             ContribAandBG = ContribTem[i];  
  119.             ContribCandDG = ColDelta * (PtDG - PtCG) + (PtCG << 8);  
  120.             ContribTem[i++] = ContribCandDG;  
  121.             PixelValueG = ((ContribAandBG << 8) + (ContribCandDG - ContribAandBG) * RowDelta) >> 16;  
  122.   
  123.             ContribAandBR = ContribTem[i];  
  124.             ContribCandDR = ColDelta * (PtDR - PtCR) + (PtCR << 8);  
  125.             ContribTem[i++] = ContribCandDR;  
  126.             PixelValueR = ((ContribAandBR << 8) + (ContribCandDR - ContribAandBR) * RowDelta) >> 16;   
  127.   
  128.             OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX)] = PixelValueB;  
  129.             OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 1] = PixelValueG;  
  130.             OutImage[3 * (DestRow + FromTopY) * dstWholeWidth + 3 * (DestCol + FromLeftX) + 2] = PixelValueR;  
  131.         }  
  132.     }  
  133. }  
  134.   
  135. int ResizeBitmapImage(char* szFilenameIn, char *szFilenameOut)  
  136. {  
  137.     int nRes;  
  138.     CImage ImageIn;  
  139.     CImage ImageOut;  
  140.     int dstWholeWidth = 1024, dstWholeHeight = 768;  
  141.   
  142.     if (GetFileAttributes(szFilenameIn) == -1)  
  143.     {  
  144.         printf( "ERROR: file '%s'/n not found", szFilenameIn);  
  145.         return 1;  
  146.     }  
  147.   
  148.     if (ImageIn.Load(szFilenameIn) != 0)  
  149.     {  
  150.         printf( "ERROR: can't load '%s'/n", szFilenameIn);  
  151.         return 1;  
  152.     }  
  153.   
  154.     if (ImageIn.m_BitPerPixel != 24)  
  155.     {  
  156.         if (ImageIn.ConvertTo24() != 0)  
  157.         {  
  158.             printf("ERROR: '%s' conversion to 24 bit failed/n", szFilenameIn);  
  159.         }  
  160.     }  
  161.   
  162.     if (ImageOut.Init(dstWholeWidth, dstWholeHeight, 24) != 0)  
  163.     {  
  164.         printf("ERROR: ImageOut.Init()/n");  
  165.         return 1;  
  166.     };  
  167.   
  168.     ResizeImage(ImageIn.m_pBitmap, ImageOut.m_pBitmap, ImageIn.m_Xres, ImageIn.m_Yres, dstWholeWidth / 2, dstWholeHeight / 2, dstWholeWidth, dstWholeHeight);  
  169.   
  170.     nRes = ImageOut.Save(szFilenameOut);  
  171.     if (nRes != 0)  
  172.     {  
  173.         printf("ERROR %i: ImageOut.Save(/"%s/")/n", nRes, szFilenameOut);  
  174.         return nRes;  
  175.     }  
  176.     
  177.     return 0;  
  178. }  

 

你可能感兴趣的:(双线性插值图像放大/缩小算法)