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))//判斷是否在原圖像範圍內
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);
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;
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;
裏面用到的是雙線性內插法。(比最鄰近法好,減少失真)