C++影象縮放

pamxy發表於2013-03-23

轉自:http://blog.csdn.net/welcome_xu/article/details/7251316

VC++中自帶的影象縮放函式兩個:

1、

BOOL StretchBlt ( 
int x, 
int y, 
int nWidth, 
int nHeight, 
CDC* pSrcDC, 
int xSrc, 
int ySrc, 
int nSrcWidth, 
int nSrcHeight, 
DWORD dwRop ); 

2、

int StretchDIBits(
  HDC hdc,                      // handle to DC
  int XDest,                    // x-coord of destination upper-left corner
  int YDest,                    // y-coord of destination upper-left corner
  int nDestWidth,               // width of destination rectangle
  int nDestHeight,              // height of destination rectangle
  int XSrc,                     // x-coord of source upper-left corner
  int YSrc,                     // y-coord of source upper-left corner
  int nSrcWidth,                // width of source rectangle
  int nSrcHeight,               // height of source rectangle
  CONST VOID *lpBits,           // bitmap bits
  CONST BITMAPINFO *lpBitsInfo, // bitmap data
  UINT iUsage,                  // usage options
  DWORD dwRop                   // raster operation code
);
這兩個函式的作用是將影象的一部分或全部複製到另一個框架裡面去,如果新框架比原來的部分大,則將影象進行放大,否則縮小。(聽說這兩個函式縮放效果不好,容易引起影象失真)

自己編寫影象縮放程式碼:
 int NewWidth=int(Width*fx+0.5);
int NewHeight=int(Height*fy+0.5);
int NewLineBytes=WIDTHBYTES(NewWidth*8);
HDIB hNewDIB=(HDIB)::GlobalAlloc(GHND,40+4*256+NewLineBytes*NewHeight);//分配控制程式碼空間
if(hNewDIB==NULL) return;
LPBYTE lpDIBnew=(LPBYTE)::GlobalLock((HGLOBAL)hNewDIB);//由新控制程式碼得到第二部分指標
memcpy(lpDIBnew,lpDIB,1064);//複製資訊頭和調色盤
BYTE* lpDIBBitsnew=(BYTE*)(lpDIBnew+40+4*256);//得到第四部分指標
int i0,j0;//影象在原DIB中的座標
int i,j;//影象在新DIB中的座標
float m,n;
for(i=0;i<NewHeight;i++)//雙線性插值
for(j=0;j<NewWidth;j++)
{
i0=(int)(i/fy+0.5);j0=(int)(j/fx+0.5);//計算該象素在原DIB中的座標
if((j0>=0)&&(j0<Width)&&(i0>=0)&&(i0<Height))//判斷是否在原影象範圍內
{
m=(float)(i/fy+0.5)-i0;n=(float)(j/fx+0.5)-(int)j0;
BYTE x1,x2,y1,y2;
x1=*(lpDIBBits+int(LineBytes*(Height-i0-1)+j0));
x2=*(lpDIBBits+int(LineBytes*(Height-i0-1)+j0+1));
y1=*(lpDIBBits+int(LineBytes*(Height-i0)+j0));
y2=*(lpDIBBits+int(LineBytes*(Height-i0)+j0+1));
*(lpDIBBitsnew+NewLineBytes*(NewHeight-i-1)+j)=(BYTE)((1-m)*(1-n)*x1+(1-m)*n*x2+m*(1-n)*y1+m*n*y2);
}
   else 
   *((unsigned char*)(lpDIBBitsnew+NewLineBytes*i+j))=255;//對於原影象中沒有的畫素,直接賦值為255
}

LPBITMAPINFOHEADER h=(LPBITMAPINFOHEADER)lpDIBnew;//獲得指向新影象資訊頭的指標
h->biHeight=NewHeight;//更新資訊頭的資訊
h->biWidth=NewWidth;
h->biSizeImage=NewWidth*NewHeight;
pDoc->hDib=hNewDIB;
pDoc->dWidth=NewWidth;pDoc->dHeight=NewHeight;
OnInitialUpdate();
Invalidate(TRUE);
delete dlg;

裡面用到的是雙線性內插法。(比最鄰近法好,減少失真)


相關文章