C++圖像縮放

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;

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章