最近工作中利用MFC實現圖片旋轉的任務,發現網上這個資料比較少,也比較雜。最終自己也是看了好多代碼後,將代碼融合了一下,最終能夠滿足自己的使用要求。
1.旋轉函數
//hBitmap:要旋轉位圖的句柄
//radians : 旋轉的角度(弧度)
//clrBack :旋轉時的背景顏色
//旋轉圖片函數
HBITMAP GetRotatedBitmap(HBITMAP hBitmap, float radians, COLORREF clrBack)
{
// Create a memory DC compatible with the display
CDC sourceDC, destDC;
sourceDC.CreateCompatibleDC(NULL);
destDC.CreateCompatibleDC(NULL);
// Get logical coordinates
BITMAP bm;
::GetObject(hBitmap, sizeof(bm), &bm);
float cosine = (float)cos(radians);
float sine = (float)sin(radians);
int w = bm.bmWidth;
int h = bm.bmHeight;
// Create a bitmap to hold the result
HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);
HBITMAP hbmOldSource = (HBITMAP)::SelectObject(sourceDC.m_hDC, hBitmap);
HBITMAP hbmOldDest = (HBITMAP)::SelectObject(destDC.m_hDC, hbmResult);
// Draw the background color before we change mapping mode
HBRUSH hbrBack = CreateSolidBrush(clrBack);
HBRUSH hbrOld = (HBRUSH)::SelectObject(destDC.m_hDC, hbrBack);
destDC.PatBlt(0, 0, w, h, PATCOPY);
::DeleteObject(::SelectObject(destDC.m_hDC, hbrOld));
// We will use world transform to rotate the bitmap
SetGraphicsMode(destDC.m_hDC, GM_ADVANCED);
XFORM xform;
xform.eM11 = cosine;
xform.eM12 = sine;
xform.eM21 = -sine;
xform.eM22 = cosine;
xform.eDx = (float)(150 - cosine*150 + sine*150);
xform.eDy = (float)(150 - cosine*150- sine*150);
SetWorldTransform(destDC.m_hDC, &xform);
// Now do the actual rotating - a pixel at a time
destDC.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, SRCCOPY);
// Restore DCs
::SelectObject(sourceDC.m_hDC, hbmOldSource);
::SelectObject(destDC.m_hDC, hbmOldDest);
return hbmResult;
}
其中:
1.xform.eDx = (float)(150 - cosine*150 + sine*150); xform.eDy = (float)(150 - cosine*150- sine*150);
中的數字(150,150)指的是整個旋轉過程中的旋轉中心。
2.用於旋轉的核心函數是:SetWorldTransform。
函數原型:BOOL SetWorldTransform(HDChdc, CONST XFORM*lpXform );
hdc:指向設備環境的句柄。
lpxform:指向XFORM結構的指針,此結構含有轉換數據。XFORM中的各項參數可根據二維旋轉矩陣可輕鬆得到。
2.顯示函數
//angle:旋轉的角度
//顯示函數
RotatePicture(int angle)
{
CBitmap bitmap; // CBitmap對象,用於加載位圖
HBITMAP hBitmap1, hBitmap2; // 保存CBitmap加載的位圖的句柄
CDC *pDC = this->GetDC();
//創建一個內存中的顯示設備
CDC MemDc;
if (!MemDc.CreateCompatibleDC(NULL))//創建內存設備環境
return;
//設定旋轉圖片周圍的背景色
COLORREF clrBack = RGB(0, 255,0);
float rad = 3.1415926 *angle / 180;
//加載位圖
hBitmap1 = (HBITMAP)::LoadBitmapW(AfxGetInstanceHandle(), MAKEINTRESOURCEW(IDB_BITMAP3));
//旋轉位圖
hBitmap2 = PictureRotate.GetRotatedBitmapNT1(hBitmap1, rad, clrBack);
bitmap.Attach(hBitmap2); //關聯位圖對象
MemDc.SelectObject(&bitmap); //選取CBitmap對象
pDC->BitBlt(0, 0, 600, 600, &MemDc, 0, 0, SRCCOPY); //顯示
bitmap.DeleteObject();
DeleteObject(hBitmap1);
DeleteObject(hBitmap2);
MemDc.DeleteDC();
ReleaseDC(pDC);
}
其中:
CBitmap、CDC、HBITMAP這些類產生的對象在使用完後都儘可能的釋放或刪除掉。