BITMAPFILEHEADER 確認 "BM" 標誌。BITMAPINFOHEADER 取得寬高、位深。lpSrcBits)。CreateCompatibleBitmap + SelectObject,再 BitBlt 將 DIB 複製至記憶體 DC(dcSrc)。目標座標 (J, I) 對應來源座標:
srcX = (J + minWidth) * cosA + (I + minHeight) * sinA;
srcY = (I + minHeight) * cosA - (J + minWidth) * sinA;
其中 minWidth/minHeight 為旋轉後外接矩形左上角在原圖座標系中的負偏移量,由四個角旋轉後的極值計算得出。
void RotateAnyAngle(HDC dcSrc, int srcW, int srcH, double angle, HDC hdcDest) {
double sinA = sin(angle), cosA = cos(angle);
// 計算四角旋轉後座標
double x1 = -srcH * sinA, y1 = srcH * cosA;
double x2 = srcW * cosA - srcH * sinA, y2 = srcH * cosA + srcW * sinA;
double x3 = srcW * cosA, y3 = srcW * sinA;
// 邊界
double minX = min(0.0, min(x1, min(x2, x3)));
double maxX = max(0.0, max(x1, max(x2, x3)));
double minY = min(0.0, min(y1, min(y2, y3)));
double maxY = max(0.0, max(y1, max(y2, y3)));
int dstW = (int)(maxX - minX), dstH = (int)(maxY - minY);
HDC dcDst = CreateCompatibleDC(dcSrc);
HBITMAP hBmp = CreateCompatibleBitmap(dcSrc, dstW, dstH);
SelectObject(dcDst, hBmp);
for (int I = 0; I < dstH; I++) {
for (int J = 0; J < dstW; J++) {
double srcX = (J + minX) * cosA + (I + minY) * sinA;
double srcY = (I + minY) * cosA - (J + minX) * sinA;
if (srcX >= 0 && srcX < srcW && srcY >= 0 && srcY < srcH)
BitBlt(dcDst, J, I, 1, 1, dcSrc, (int)srcX, (int)srcY, SRCCOPY);
}
}
BitBlt(hdcDest, 200, 200, dstW, dstH, dcDst, 0, 0, SRCCOPY);
DeleteObject(hBmp); DeleteDC(dcDst);
}
double angle = 45.0 * 3.14159 / 180.0; // 45度
RotateAnyAngle(dcSrc, bmpWidth, bmpHeight, angle, hDC);
此法採「逆向映射」(目標→來源),避免漏洞,適合教學與中小尺寸圖片。大圖或高效能需求建議採用雙線性插值或 GPU 加速。