2012-03-17 110 views
1

我有一个BitMap(一个小精灵),我必须以特定角度旋转。我发现了这个代码,并且试图将它适用于我的应用程序,但它似乎不起作用。精灵根本不旋转,而是稍微移动一点。winapi中的位图旋转

这里的功能代码:

void Sprite::Rotate(float radians, const char* szImageFile) 
{ 
    // Create a memory DC compatible with the display 
HDC sourceDC, destDC; 
sourceDC = CreateCompatibleDC(mpBackBuffer->getDC()); 
destDC = CreateCompatibleDC(mpBackBuffer->getDC()); 

// Get logical coordinates 
HBITMAP hBitmap = (HBITMAP)LoadImage(g_hInst, szImageFile, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE); 
BITMAP bm; 
::GetObject(hBitmap, sizeof(bm), &bm); 

float cosine = (float)cos(radians); 
float sine = (float)sin(radians); 

// Compute dimensions of the resulting bitmap 
// First get the coordinates of the 3 corners other than origin 
int x1 = (int)(bm.bmHeight * sine); 
int y1 = (int)(bm.bmHeight * cosine); 
int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine); 
int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine); 
int x3 = (int)(bm.bmWidth * cosine); 
int y3 = (int)(-bm.bmWidth * sine); 

int minx = min(0,min(x1, min(x2,x3))); 
int miny = min(0,min(y1, min(y2,y3))); 
int maxx = max(0,max(x1, max(x2,x3))); 
int maxy = max(0,max(y1, max(y2,y3))); 

int w = maxx - minx; 
int h = maxy - miny; 

// Create a bitmap to hold the result 
HBITMAP hbmResult = ::CreateCompatibleBitmap(mpBackBuffer->getDC(), w, h); 

HBITMAP hbmOldSource = (HBITMAP)::SelectObject(sourceDC, hBitmap); 
HBITMAP hbmOldDest = (HBITMAP)::SelectObject(destDC, hbmResult); 

// Draw the background color before we change mapping mode 
HBRUSH hbrBack = CreateSolidBrush(mcTransparentColor); 
HBRUSH hbrOld = (HBRUSH)::SelectObject(destDC, hbrBack); 
PatBlt(destDC, 0, 0, w, h, PATCOPY); 
::DeleteObject(::SelectObject(destDC, hbrOld)); 




// We will use world transform to rotate the bitmap 
SetGraphicsMode(destDC, GM_ADVANCED); 
XFORM xform; 
xform.eM11 = cosine; 
xform.eM12 = -sine; 
xform.eM21 = sine; 
xform.eM22 = cosine; 
xform.eDx = (float)-minx; 
xform.eDy = (float)-miny; 

SetWorldTransform(destDC, &xform); 

// Now do the actual rotating - a pixel at a time 
BitBlt(destDC, 0, 0, w, h, sourceDC, 0, 0, SRCCOPY); 
// Restore DCs 
::SelectObject(sourceDC, hbmOldSource); 
::SelectObject(destDC, hbmOldDest); 

BITMAP btm; 
::GetObject(hbmResult, sizeof(mImageBM), &mImageBM); 

} 

我想不通为什么它不旋转图像,而是它移动它。此外,如果你知道另一种方法来做到这一点,我愿意提供建议,但请记住,我只能使用winapi,没有额外的库,我是Windows编程的初学者。

编辑:这里是我得到的代码:http://www.codeguru.com/cpp/g-m/bitmap/specialeffects/article.php/c1743/。我不得不改变它,但我不认为这是因为这个原因,我只是将CDC改为HDC。我忽略的一件重要事情是(0,0)坐标。因为代码中的图像被认为是在角落,但在我的应用程序中,它位于精灵的中心。即使这是一个问题,我认为这是一个计算位图的新维度的问题,我没有看到与旋转的连接。

+0

请你检查SetWorldTransform是成功还是失败。即,返回TRUE或FALSE。 – Robinson 2012-03-17 23:13:22

+0

它返回TRUE。 – Andrei 2012-03-17 23:17:05

回答

2

如果位图在移动,在我看来世界变换和blit都起作用了。
由于变换的eDx/eDy参数,它移动的量是多少?
只是硬编码“旋转”示例中的值here有什么不同?正弦通过相反的符号。所以它可能只是忽略了转换的旋转部分,只做了翻译。

+0

即使我把示例中的值放在一起,它也没有什么区别。在XFORM结构的任何值处,它都以相同的方向和相同的距离移动。当我改变角度(我传递给函数的弧度数)时,方向改变。 – Andrei 2012-03-17 23:34:22

+0

必须是DC或bitblt本身的问题。为了Drawrect而改变bitblit? – 2012-03-17 23:45:19

+0

什么都没有。我试着改变 'sourceDC = CreateCompatibleDC(mpBackBuffer-> getDC());我们可以通过下面的例子来说明如何使用DCDC的方法来创建一个DCDC。 destDC = CreateCompatibleDC(NULL);' 并且它做同样的事情。 – Andrei 2012-03-18 00:02:12