多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 圖像放大快速算法

圖像放大快速算法

來源:程序員人生   發布時間:2014-12-08 08:17:39 閱讀次數:3934次

圖象放大快速算法實現的原理主要有以下兩點:

1、橫向縮放與縱向縮放分開,而前后順序取決于縮放前后的圖象比例:

   若SrcHeight/DstWidth>SrcWidth/DstWidth,則先縱向縮放,否則橫向縮放。

2、利用整數運算代替浮點運算,由因而分步縮放,以橫向縮放為例,利用2次線性插值公式,再變形1下以下:

f(i,j+v) = (1-v)f(i,j) +vf(i,j+1);

其中i為第i行,j為第j列,v表示求得放大后坐標的小數部份。

這里最重要的并沒有直接用小數運算,而是通過將小數區間(0,1)映照到整數區間(0,128),    

再利用整數來代替小數運算,最后只需要相應的處理1下就能夠了。

 

誤差分析:

首先2次線性算法本來就有誤差,這里主要討論利用整數代替小數的誤差,可以看到每個整數能代替的小數范圍為1/128,所以誤差范圍為[⑴/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; // int nFlag; ImageInfo() { pRGBData=NULL; } ImageInfo(byte *p,int h,int s,int w) { // pRGBData = (byte*)malloc(h*s); 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; //申請4個內存空間 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); } //pTagImage=(byte*)malloc(nTagHeight * nTagWidth); 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); } // ImageInfo SrcImageInfo(pSrcImageTmp,SrcImageInfo.nHeight,StepValueTmp,SrcImageInfo.nWidth); //調用HorizontalScale進行水平延伸,結果保存到DstImageInfo中 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));// 多申請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); } // 最后1層用上1層填充 memcpy(pSrcImageTmp+SrcImageInfo.nHeight*SumTmp1,SrcImageInfo.pRGBData+(SrcImageInfo.nHeight⑴)*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]; // 遍歷,順次取得int表數據 v18 = ( a6_pData_Unknow[j]<<1); index1=((v17+1)<<2); index2=(v17<<2); index3=(j<<2); //blue通道 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; //0x2000右移14位為0.5,這里是為了4舍5入; a2_pData_Dst[index3+MT_BLUE] =v20&0xff; //green通道 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; //red通道 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]; // 遍歷,順次取得int表數據 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; //0x2000右移14位為0.5,這里是為了4舍5入; 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); //blue通道 nTmp4 = (nTmp3 * pbTmp1[index2+MT_BLUE] +nTmp2 * pbTmp1[index3+MT_BLUE] + 0x2000)>>14; a2_pData_Dst[index3+MT_BLUE] = nTmp4&0xff; //green通道 nTmp4 = (nTmp3 * pbTmp1[index2+MT_GREEN] +nTmp2 * pbTmp1[index3+MT_GREEN] + 0x2000)>>14; a2_pData_Dst[index3+MT_GREEN] = nTmp4&0xff; //red通道 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; } } }


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 在线中文字幕播放 | 自拍中文字幕 | 午夜成人免费视频 | 福利视频欧美一区二区三区 | 国产 日韩欧美 | 亚洲成a人片在线观看中文动漫 | 涩涩免费播放观看在线视频 | 中文一区在线观看 | 波多野结衣在线一区 | 亚洲一区二区三区久久 | 国产在线a | 国产成人精品一区二区不卡 | 好吊妞精品 | 在线观看一级毛片免费 | 久久国产一级毛片一区二区 | 免费亚洲一区 | 性色a按摩videos| 99干99| 国产高清在线精品二区一 | 国产成人精品日本亚洲语音1 | www.久久精品视频 | 午夜dj影院在线观看免费视频中文 | 老女人做爰免费的视频 | 亚洲v日本 | 亚洲精品综合一区二区三区在线 | 国产未成女年一区二区 | 黄色aa毛片 | 一区二区三区亚洲 | 一区二区视频 | 最近的中文字幕免费完整 | 伊人手机在线观看 | 国产第一福利 | 国产精品高清一区二区三区不卡 | 亚洲精品一区二区三区中文字幕 | 欧美国产精品一区二区免费 | 日本高清在线观看视频www | 午夜 性色 福利视频 | 日韩欧美精品在线观看 | 麻豆19禁国产青草精品 | 日韩精品一区二区三区中文在线 | 午夜精品国产爱在线观看不卡 |