标签:blog   http   ar   sp   for   strong   on   数据   div   
图像放大快速算法实现的原理主要有以下两点:
1、横向缩放与纵向缩放分开,而先后顺序取决于缩放前后的图像比例:
   若SrcHeight/DstWidth>SrcWidth/DstWidth,则先纵向缩放,否则横向缩放。
2、利用整数运算代替浮点运算,由于是分步缩放,以横向缩放为例,利用二次线性插值公式,再变形一下如下:
f(i,j+v) = (1-v)f(i,j) +vf(i,j+1);
其中i为第i行,j为第j列,v表示求得放大后坐标的小数部分。
这里最重要的并没有直接用小数运算,而是通过将小数区间(0,1)映射到整数区间(0,128),    
再利用整数来代替小数运算,最后只需要相应的处理一下就可以了。
 
误差分析:
首先二次线性算法本来就有误差,这里主要讨论利用整数代替小数的误差,可以看到每一个整数能代替的小数范围为1/128,所以误差范围为[-1/256,1/256]之间。
代码实现:
//ImageScale.h
- #define IN  
- #define OUT  
- #define _DWORD int  
- #define _BYTE byte  
- #define _WORD short  
-   
- struct ImageInfo  
- {  
-     byte* pRGBData;  
-     int nHeight;  
-     int nStepValue;  
-     int nWidth;  
-     ImageInfo()  
-     {  
-         pRGBData=NULL;  
-     }  
-     ImageInfo(byte *p,int h,int s,int w)  
-     {  
-     
-         pRGBData = p;  
-         nHeight=h;  
-         nStepValue=s;  
-         nWidth=w;  
-     }  
- };  
-   
- class ImageScale  
- {  
- public:  
-     ImageScale(void);  
-     virtual ~ImageScale(void);  
-     void Run(BYTE* pSrcImage, int nSrcWidth, int nSrcHeight, BYTE* pTagImage, int nTagWidth, int nTagHeight,int nChannels);  
- private:  
-     bool DstInSrcIndex(int large_len, int little_len,  int* a3_pIntValue, byte* a4_pByteValue);  
-     int DoubleToInt(double d);  
-     BOOL HorizontalFill(IN ImageInfo& SrcImageInfo, IN int nTagHeight, IN int nTagWidth, IN int nTagStepValue, IN int bFlag, IN int* pIntValue, IN byte* pByteValue, OUT ImageInfo& DstImageInfo,int nChannels);  
-     BOOL VerticalFill(IN ImageInfo& SrcImageInfo, IN int nTagHeight, IN int nTagWidth, IN int nTagStepValue, IN int bFlag, IN int* pIntValue, IN byte* pByteValue, OUT ImageInfo& DstImageInfo,int nChannels);  
-     void HorizontalScale(byte *a1_pData_Src, byte *a2_pData_Dst, int nHeight, int nWidth, int *a5_pData_Unknow, byte *a6_pData_Unknow, int srcStepValue, int dstStepValue,  short *a10_pData_Unknow,int nChannels);  
-     void VerticalScale(byte *a1_pData_Src, byte *a2_pData_Dst, int a3_nHeight, int a4_nWidth, int *a5_pData_Unknow, byte *a6_pData_Unknow, int a7_nWidth, int a8_nWidthScrible,  short *a10_pData_Unknow,int nChannels);  
- };  
 
//ImageScale.cpp
- #include "StdAfx.h"  
- #include "ImageScale.h"  
-   
- short g_pHSDataByte[]=  
- {  
-     0x4000, 0x0000, 0x3F80, 0x0080, 0x3F00, 0x0100, 0x3E80, 0x0180,  
-     0x3E00, 0x0200, 0x3D80, 0x0280, 0x3D00, 0x0300, 0x3C80, 0x0380,  
-     0x3C00, 0x0400, 0x3B80, 0x0480, 0x3B00, 0x0500, 0x3A80, 0x0580,  
-     0x3A00, 0x0600, 0x3980, 0x0680, 0x3900, 0x0700, 0x3880, 0x0780,  
-     0x3800, 0x0800, 0x3780, 0x0880, 0x3700, 0x0900, 0x3680, 0x0980,  
-     0x3600, 0x0A00, 0x3580, 0x0A80, 0x3500, 0x0B00, 0x3480, 0x0B80,  
-     0x3400, 0x0C00, 0x3380, 0x0C80, 0x3300, 0x0D00, 0x3280, 0x0D80,  
-     0x3200, 0x0E00, 0x3180, 0x0E80, 0x3100, 0x0F00, 0x3080, 0x0F80,  
-     0x3000, 0x1000, 0x2F80, 0x1080, 0x2F00, 0x1100, 0x2E80, 0x1180,  
-     0x2E00, 0x1200, 0x2D80, 0x1280, 0x2D00, 0x1300, 0x2C80, 0x1380,  
-     0x2C00, 0x1400, 0x2B80, 0x1480, 0x2B00, 0x1500, 0x2A80, 0x1580,  
-     0x2A00, 0x1600, 0x2980, 0x1680, 0x2900, 0x1700, 0x2880, 0x1780,  
-     0x2800, 0x1800, 0x2780, 0x1880, 0x2700, 0x1900, 0x2680, 0x1980,  
-     0x2600, 0x1A00, 0x2580, 0x1A80, 0x2500, 0x1B00, 0x2480, 0x1B80,  
-     0x2400, 0x1C00, 0x2380, 0x1C80, 0x2300, 0x1D00, 0x2280, 0x1D80,  
-     0x2200, 0x1E00, 0x2180, 0x1E80, 0x2100, 0x1F00, 0x2080, 0x1F80,  
-     0x2000, 0x2000, 0x1F80, 0x2080, 0x1F00, 0x2100, 0x1E80, 0x2180,  
-     0x1E00, 0x2200, 0x1D80, 0x2280, 0x1D00, 0x2300, 0x1C80, 0x2380,  
-     0x1C00, 0x2400, 0x1B80, 0x2480, 0x1B00, 0x2500, 0x1A80, 0x2580,  
-     0x1A00, 0x2600, 0x1980, 0x2680, 0x1900, 0x2700, 0x1880, 0x2780,  
-     0x1800, 0x2800, 0x1780, 0x2880, 0x1700, 0x2900, 0x1680, 0x2980,  
-     0x1600, 0x2A00, 0x1580, 0x2A80, 0x1500, 0x2B00, 0x1480, 0x2B80,  
-     0x1400, 0x2C00, 0x1380, 0x2C80, 0x1300, 0x2D00, 0x1280, 0x2D80,  
-     0x1200, 0x2E00, 0x1180, 0x2E80, 0x1100, 0x2F00, 0x1080, 0x2F80,  
-     0x1000, 0x3000, 0x0F80, 0x3080, 0x0F00, 0x3100, 0x0E80, 0x3180,  
-     0x0E00, 0x3200, 0x0D80, 0x3280, 0x0D00, 0x3300, 0x0C80, 0x3380,  
-     0x0C00, 0x3400, 0x0B80, 0x3480, 0x0B00, 0x3500, 0x0A80, 0x3580,  
-     0x0A00, 0x3600, 0x0980, 0x3680, 0x0900, 0x3700, 0x0880, 0x3780,  
-     0x0800, 0x3800, 0x0780, 0x3880, 0x0700, 0x3900, 0x0680, 0x3980,  
-     0x0600, 0x3A00, 0x0580, 0x3A80, 0x0500, 0x3B00, 0x0480, 0x3B80,  
-     0x0400, 0x3C00, 0x0380, 0x3C80, 0x0300, 0x3D00, 0x0280, 0x3D80,  
-     0x0200, 0x3E00, 0x0180, 0x3E80, 0x0100, 0x3F00, 0x0080, 0x3F80,  
-     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000  
- };  
-   
-   
- ImageScale::ImageScale(void)  
- {  
- }  
-   
-   
- ImageScale::~ImageScale(void)  
- {  
-   
- }  
-   
- void ImageScale::Run(BYTE* pSrcImage, int nSrcWidth, int nSrcHeight,  BYTE* pTagImage, int nTagWidth, int nTagHeight, int nChannels)  
- {  
-   
-     if (!(nChannels==1||nChannels==4))  
-         return;  
-     if(nSrcWidth<=0 || nSrcHeight<=0 )  
-         return;  
-     if(nTagWidth<nSrcWidth || nTagHeight<nSrcHeight)  
-         return;  
-     int nSrcStepValue=(nSrcWidth+15) & ~15;  
-     int nTagStepValue=nTagWidth;  
-   
-     
-     int* pIntValueTmp_nHeight = (int*)malloc(nTagHeight*sizeof(int));
-     if (pIntValueTmp_nHeight)  
-     {  
-         memset(pIntValueTmp_nHeight, 0,nTagHeight*sizeof(int));  
-     }  
-       
-     byte* pByteValueTmp_nHeight = (byte*)malloc(nTagHeight);
-     if (pByteValueTmp_nHeight)  
-     {  
-         memset(pByteValueTmp_nHeight, 0, nTagHeight);  
-     }  
-   
-     int* pIntValueTmp_nWidth = (int*)malloc(nTagWidth*sizeof(int));
-     if (pIntValueTmp_nWidth)  
-     {  
-         memset(pIntValueTmp_nWidth, 0, nTagWidth*sizeof(int));  
-     }  
-   
-     byte* pByteValueTmp_nWidth = (byte*)malloc(nTagWidth);
-     if (pByteValueTmp_nWidth)  
-     {  
-         memset(pByteValueTmp_nWidth, 0, nTagWidth);  
-     }  
-     DstInSrcIndex(nTagWidth,nSrcWidth, pIntValueTmp_nWidth, pByteValueTmp_nWidth);  
-     DstInSrcIndex(nTagHeight, nSrcHeight, pIntValueTmp_nHeight, pByteValueTmp_nHeight);  
-     int nValueTmp1 = nSrcHeight * nTagWidth;  
-     int nValueTmp2 = nSrcWidth * nTagHeight;  
-   
-     ImageInfo SrcImageInfo(pSrcImage,nSrcHeight,nSrcStepValue,nSrcWidth);  
-     ImageInfo ImageInfo_Tmp1;  
-     ImageInfo ImageInfo_Tmp2;  
-   
-     if (nValueTmp1 > nValueTmp2)  
-     {  
-         VerticalFill(SrcImageInfo, nTagHeight, nTagWidth, nTagStepValue, 0, pIntValueTmp_nHeight, pByteValueTmp_nHeight, ImageInfo_Tmp1,nChannels);  
-   
-         HorizontalFill(ImageInfo_Tmp1, nTagHeight, nTagWidth, nTagStepValue,  0, pIntValueTmp_nWidth , pByteValueTmp_nWidth, ImageInfo_Tmp2,nChannels);  
-     }  
-     else  
-     {  
-         HorizontalFill(SrcImageInfo, nTagHeight, nTagWidth, nTagStepValue, 1, pIntValueTmp_nWidth, pByteValueTmp_nWidth, ImageInfo_Tmp1,nChannels);  
-         VerticalFill(ImageInfo_Tmp1, nTagHeight, nTagWidth, nTagStepValue,  1,pIntValueTmp_nHeight, pByteValueTmp_nHeight, ImageInfo_Tmp2,nChannels);  
-     }  
-     
-    for (int i=0; i<nTagHeight; i++)  
-     {  
-         memcpy(pTagImage +nChannels*i*nTagWidth, ImageInfo_Tmp2.pRGBData+ nChannels*i*nTagWidth, nChannels*nTagWidth);  
-     }  
-   
-   
-     
-     if (pIntValueTmp_nHeight)  
-     {  
-         free(pIntValueTmp_nHeight);  
-         pIntValueTmp_nHeight = NULL;  
-     }  
-   
-     if (pByteValueTmp_nHeight)  
-     {  
-         free(pByteValueTmp_nHeight);  
-         pByteValueTmp_nHeight = NULL;  
-     }  
-   
-     if (pIntValueTmp_nWidth)  
-     {  
-         free(pIntValueTmp_nWidth);  
-         pIntValueTmp_nWidth = NULL;  
-     }  
-   
-     if (pByteValueTmp_nWidth)  
-     {  
-         free(pByteValueTmp_nWidth);  
-         pByteValueTmp_nWidth = NULL;  
-     }  
-   
-     if (ImageInfo_Tmp1.pRGBData)  
-     {  
-         free(ImageInfo_Tmp1.pRGBData);  
-         ImageInfo_Tmp1.pRGBData = NULL;  
-     }  
-   
-     if (ImageInfo_Tmp2.pRGBData)  
-     {  
-         free(ImageInfo_Tmp2.pRGBData);  
-         ImageInfo_Tmp2.pRGBData = NULL;  
-     }  
-   
- }  
-   
- bool ImageScale::DstInSrcIndex(int large_len, int little_len,  int* a3_pIntValue, byte* a4_pByteValue)  
- {  
-     int nValueTmp3 =  (little_len << 7) - 128;  
-   
-     for (int index = 0;  index<large_len;  ++index)  
-     {  
-         float doubleValueTmp3 = ((float)index + 0.5) / ((float)large_len);  
-         int nValueTmp4 = (int)(doubleValueTmp3 * (little_len - 0.5f) * 128.0+0.5f);  
-         int nValueTmp1= nValueTmp3;  
-         if(!(nValueTmp3<nValueTmp4))  
-              nValueTmp1= nValueTmp4;  
-         a3_pIntValue[index] = nValueTmp1 >> 7;  
-         a4_pByteValue[index] = nValueTmp1 & 0x7F;  
-     }  
-     return true;  
- }  
-   
- BOOL ImageScale::HorizontalFill(IN ImageInfo& SrcImageInfo, IN int nTagHeight, IN int nTagWidth, IN int nTagStepValue, IN int bFlag, IN int* pIntValue, IN byte* pByteValue, OUT ImageInfo& DstImageInfo,int nChannels)  
- {  
-     int nHeightTmp1 = 0;  
-     if (bFlag)  
-     {  
-         nHeightTmp1 = SrcImageInfo.nHeight;  
-     }   
-     else  
-     {  
-         nHeightTmp1 = nTagHeight;  
-     }  
-   
-     
-     int StepValueTmp=(SrcImageInfo.nStepValue+15) & ~15;  
-     byte *pSrcImageTmp=(byte*)malloc(nChannels * StepValueTmp * nHeightTmp1);  
-     memset(pSrcImageTmp,0,nChannels * StepValueTmp * nHeightTmp1);  
-     int SumTmp1=nChannels * StepValueTmp,SumTmp2=nChannels * SrcImageInfo.nWidth;  
-     for(int i=0;i<nHeightTmp1;i++)  
-     {  
-         memcpy(pSrcImageTmp+i*SumTmp1,SrcImageInfo.pRGBData+i*SumTmp2,SumTmp2);  
-     }  
-     
-     DstImageInfo.nHeight = nHeightTmp1;  
-     DstImageInfo.nWidth = nTagWidth;  
-     DstImageInfo.nStepValue = nTagStepValue;  
-     DstImageInfo.pRGBData = (byte*)malloc(nChannels * DstImageInfo.nHeight * DstImageInfo.nStepValue);  
-     byte* pDataSrc = SrcImageInfo.pRGBData;  
-     byte* pDataDst = DstImageInfo.pRGBData;  
-     HorizontalScale(pSrcImageTmp, pDataDst, DstImageInfo.nHeight, DstImageInfo.nWidth, pIntValue, pByteValue,   
-         SrcImageInfo.nStepValue, DstImageInfo.nStepValue, g_pHSDataByte,nChannels);  
-   
-     if (pSrcImageTmp)  
-     {  
-         free(pSrcImageTmp);  
-         pSrcImageTmp=NULL;  
-     }  
-     return TRUE;  
- }  
-   
- BOOL ImageScale::VerticalFill(IN ImageInfo& SrcImageInfo, IN int nTagHeight, IN int nTagWidth, IN int nTagStepValue, IN int bFlag, IN int* pIntValue, IN byte* pByteValue, OUT ImageInfo& DstImageInfo,int nChannels)  
- {  
-     int nWidthTmp1 = 0;  
-     int nStepValueTmp1 = 0;  
-     if (bFlag)  
-     {  
-         nWidthTmp1 = nTagWidth;  
-         nStepValueTmp1 = nTagStepValue;  
-     }  
-     else  
-     {  
-         nWidthTmp1 = SrcImageInfo.nWidth;  
-         nStepValueTmp1 = SrcImageInfo.nStepValue;  
-     }  
-   
-     
-     int StepValueTmp=(SrcImageInfo.nStepValue+15) & ~15;  
-     byte *pSrcImageTmp=(byte*)malloc(nChannels * StepValueTmp *( SrcImageInfo.nHeight+1));
-     memset(pSrcImageTmp,0,nChannels * StepValueTmp * (SrcImageInfo.nHeight+1));  
-     int SumTmp1=nChannels * StepValueTmp,SumTmp2=nChannels * SrcImageInfo.nWidth,SumTmp3=nChannels * SrcImageInfo.nStepValue;  
-     for(int i=0;i<SrcImageInfo.nHeight;i++)  
-     {  
-         memcpy(pSrcImageTmp+i*SumTmp1,SrcImageInfo.pRGBData+i*SumTmp3,SumTmp2);  
-     }  
-     
-     memcpy(pSrcImageTmp+SrcImageInfo.nHeight*SumTmp1,SrcImageInfo.pRGBData+(SrcImageInfo.nHeight-1)*SumTmp3,SumTmp2);  
-     DstImageInfo.nHeight = nTagHeight;  
-     DstImageInfo.nWidth = nWidthTmp1;  
-     DstImageInfo.nStepValue = nStepValueTmp1;  
-     DstImageInfo.pRGBData = (byte*)malloc( nChannels * DstImageInfo.nHeight*DstImageInfo.nStepValue);  
-     memset(DstImageInfo.pRGBData, 0,nChannels * DstImageInfo.nHeight*DstImageInfo.nStepValue);  
-   
-     VerticalScale(pSrcImageTmp, DstImageInfo.pRGBData, DstImageInfo.nHeight, DstImageInfo.nWidth,  
-         pIntValue, pByteValue, StepValueTmp, DstImageInfo.nStepValue, g_pHSDataByte,nChannels);  
-     if (pSrcImageTmp)  
-     {  
-         free(pSrcImageTmp);  
-         pSrcImageTmp=NULL;  
-     }  
-     return TRUE;  
- }  
- void ImageScale::HorizontalScale(byte *a1_pData_Src, byte *a2_pData_Dst, int nHeight, int nWidth, int *a5_pData_Unknow, byte *a6_pData_Unknow, int srcStepValue, int dstStepValue,  short *a10_pData_Unknow,int nChannels)  
- {  
-     int v17,v18,v19,v20;  
-     int srcstep,dststep,index1,index2,index3;  
-     if(nChannels==4)  
-     {  
-         srcstep=( dstStepValue<<2);  
-         dststep=(srcStepValue<<2);  
-         for (int i=0;i<nHeight;i++)  
-         {  
-             for(int j=0;j<nWidth;j++)  
-             {  
-                 v17 = a5_pData_Unknow[j];   
-                 v18 = ( a6_pData_Unknow[j]<<1);  
-                 index1=((v17+1)<<2);  
-                 index2=(v17<<2);  
-                 index3=(j<<2);  
-                 
-                 v19 = a1_pData_Src[index1+MT_BLUE] * a10_pData_Unknow[v18 + 1];   
-                 v20 = (v19 + a10_pData_Unknow[v18] * a1_pData_Src[index2+MT_BLUE] + 0x2000) >> 14; 
-                 a2_pData_Dst[index3+MT_BLUE] =v20&0xff;  
-                 
-                 v19 = a1_pData_Src[index1+MT_GREEN] * a10_pData_Unknow[v18 + 1];     
-                 v20 = (v19 + a10_pData_Unknow[v18] * a1_pData_Src[index2+MT_GREEN] + 0x2000) >> 14;   
-                 a2_pData_Dst[index3+MT_GREEN] =v20&0xff;  
-                 
-                 v19 = a1_pData_Src[index1+MT_RED] * a10_pData_Unknow[v18 + 1];    
-                 v20 = (v19 + a10_pData_Unknow[v18] * a1_pData_Src[index2+MT_RED] + 0x2000) >> 14;   
-                 a2_pData_Dst[index3+MT_RED] =v20&0xff;  
-                 a2_pData_Dst[index3+MT_ALPHA] =255;  
-         }  
-         a2_pData_Dst +=srcstep;  
-         a1_pData_Src +=dststep ;  
-      }  
-     }  
-     else  
-     {  
-         for (int i=0;i<nHeight;i++)  
-         {  
-             for(int j=0;j<nWidth;j++)  
-             {  
-                 v17 = a5_pData_Unknow[j];   
-                 v18 = ( a6_pData_Unknow[j]<<1);  
-                 v19 = a1_pData_Src[v17+1] * a10_pData_Unknow[v18 + 1];   
-                 v20 = (v19 + a10_pData_Unknow[v18] * a1_pData_Src[v17] + 0x2000) >> 14; 
-                 a2_pData_Dst[j] = v20&0xff;;  
-         }  
-         a2_pData_Dst += dstStepValue;  
-         a1_pData_Src += srcStepValue;  
-     }  
-     }  
-   
- }  
- void ImageScale::VerticalScale(byte *a1_pData_Src, byte *a2_pData_Dst, int a3_nHeight, int a4_nWidth, int *a5_pData_Unknow, byte *a6_pData_Unknow, int a7_nWidth, int a8_nWidthScrible, short *a10_pData_Unknow,int nChannels)  
- {  
-     byte * pbTmp1;  
-     int nTmp2,nTmp3,nTmp4;  
-     int step,index1,index2,index3;  
-     if(nChannels==4)  
-     {  
-         step=(a8_nWidthScrible<<2);  
-         index1=nChannels*a7_nWidth;  
-         for (int i=0;i<a3_nHeight;i++)  
-         {  
-             pbTmp1= &a1_pData_Src[index1*a5_pData_Unknow[i]];  
-             nTmp2 = a10_pData_Unknow[a6_pData_Unknow[i]<<1];  
-             nTmp3 = a10_pData_Unknow[(a6_pData_Unknow[i]<<1) + 1];  
-             for (int j=0;j<a4_nWidth;j++)  
-             {  
-                index2=((a7_nWidth+j)<<2);  
-                index3=(j<<2);  
-                
-                nTmp4 = (nTmp3 * pbTmp1[index2+MT_BLUE] +nTmp2 * pbTmp1[index3+MT_BLUE] + 0x2000)>>14;  
-                a2_pData_Dst[index3+MT_BLUE] = nTmp4&0xff;  
-                
-                nTmp4 = (nTmp3 * pbTmp1[index2+MT_GREEN] +nTmp2 * pbTmp1[index3+MT_GREEN] + 0x2000)>>14;  
-                a2_pData_Dst[index3+MT_GREEN] = nTmp4&0xff;  
-                
-                nTmp4 = (nTmp3 * pbTmp1[index2+MT_RED] +nTmp2 * pbTmp1[index3+MT_RED] + 0x2000)>>14;  
-                a2_pData_Dst[index3+MT_RED] = nTmp4&0xff;  
-                a2_pData_Dst[index3+MT_ALPHA] = 255;  
-   
-             }  
-             a2_pData_Dst += step;  
-         }  
-           
-     }  
-     else  
-     {  
-         for (int i=0;i<a3_nHeight;i++)  
-         {  
-             pbTmp1= &a1_pData_Src[a7_nWidth*a5_pData_Unknow[i]];  
-             nTmp2 = a10_pData_Unknow[a6_pData_Unknow[i]<<1];  
-             nTmp3 = a10_pData_Unknow[(a6_pData_Unknow[i]<<1) + 1];  
-             for (int j=0;j<a4_nWidth;j++)  
-             {  
-                nTmp4 = (nTmp3 * pbTmp1[a7_nWidth+j] +nTmp2 * pbTmp1[j] + 0x2000)>>14;  
-               a2_pData_Dst[j] = nTmp4&0xff;  
-              }  
-             a2_pData_Dst += a8_nWidthScrible;  
-   
-          }  
-     }  
-   
- }  
 图像放大快速算法
标签:blog   http   ar   sp   for   strong   on   数据   div   
原文地址:http://www.cnblogs.com/yuyanbian/p/4147755.html