这是我自己写的一个函数,只处理了24位的位图,希望对你有帮助。
BOOL RotateDIB(/* IN */
void *hSource,
float fRadians,
unsigned long ulBackgroundColor,
/* OUT */
void **hDestination){
BITMAPINFO *bmiSource, *bmiDestination;
int iSourceWidth, iSourceHeight, iDestinationWidth, iDestinationHeight;
int iSourceRowLength, iDestinationRowLength;
void *pSourceDIBits, *pDestinationDIBits;
int iSourceBitCount;
int iSourceColors;
unsigned long ulDestinationSize;
unsigned int uiDestinationHeadSize;
unsigned long ulDestinationBackgroundColor;
float dCosine, dSine;
float x1, x2, x3, y1, y2, y3;
int x, y;
/* 获取源图像信息 */
bmiSource = (BITMAPINFO *)(hSource);
iSourceBitCount = bmiSource->bmiHeader.biBitCount;
iSourceColors = bmiSource->bmiHeader.biClrUsed
? (bmiSource->bmiHeader.biClrUsed)
: (1 << iSourceBitCount);
iSourceWidth = bmiSource->bmiHeader.biWidth;
iSourceHeight = bmiSource->bmiHeader.biHeight;
/* 行长度必须按四字节边界对齐 */
iSourceRowLength = ((iSourceWidth * iSourceBitCount + 31) & ~31) / 8;
if (iSourceWidth < 0 ||
iSourceHeight < 0 ||
(bmiSource->bmiHeader.biCompression != BI_RGB &&
bmiSource->bmiHeader.biCompression != BI_BITFIELDS)){
return (FALSE);
}
if (iSourceBitCount > 8){
pSourceDIBits = (void *)((unsigned long *)(bmiSource->bmiColors + bmiSource->bmiHeader.biClrUsed) +
(bmiSource->bmiHeader.biCompression == BI_BITFIELDS ? 3 : 0));
}
else {
pSourceDIBits = (void *)(bmiSource->bmiColors + iSourceColors);
}
/* 计算返回值坐标 */
dCosine = (float)cos(fRadians * 3.14159265358F / 180.0F);
dSine = (float)sin(fRadians * 3.14159265358F / 180.0F);
/* 计算除原点外的其余三个点坐标值 */
x1 = (float)(-iSourceHeight * dSine);
y1 = (float)(iSourceHeight * dCosine);
x2 = (float)(iSourceWidth * dCosine - iSourceHeight * dSine);
y2 = (float)(iSourceWidth * dSine + iSourceHeight * dCosine);
x3 = (float)(iSourceWidth * dCosine);
y3 = (float)(iSourceWidth * dSine);
/* 计算返回图像宽度和长度 */
iDestinationWidth = (int)(max(x1, max(x2, x3)) - min(0, min(x1, min(x2, x3))));
iDestinationHeight = (int)(max(y1, max(y2, y3)) - min(0, min(y1, min(y2, y3))));
/* 创建返回图像 */
iDestinationRowLength = ((iDestinationWidth * iSourceBitCount + 31) & ~31) / 8;
ulDestinationSize = iDestinationRowLength * iDestinationHeight;
uiDestinationHeadSize = (int)((unsigned char *)(pSourceDIBits) - (unsigned char *)(hSource));
*hDestination = (void *)GlobalAlloc(GMEM_FIXED, ulDestinationSize + uiDestinationHeadSize);
if (!*hDestination){
MYX_ERROR
MYX_ASSERT(*hDestination);
return (FALSE);
}
memcpy(*hDestination, hSource, uiDestinationHeadSize);
bmiDestination = (BITMAPINFO *)(*hDestination);
bmiDestination->bmiHeader.biWidth = iDestinationWidth;
bmiDestination->bmiHeader.biHeight = iDestinationHeight;
bmiDestination->bmiHeader.biSizeImage = ulDestinationSize;
pDestinationDIBits = (void *)(((unsigned char *)*hDestination) + uiDestinationHeadSize);
ZeroMemory(pDestinationDIBits, ulDestinationSize);
switch (iSourceBitCount){
int i;
case 1:
if (ulBackgroundColor == RGB(0xFF, 0xFF, 0xFF)){
memset(pDestinationDIBits, 0xFF, ulDestinationSize);
}
break;
case 4:
case 8:
for (i = 0; i < iSourceColors; i++){
if (bmiSource->bmiColors.rgbBlue == GetBValue(ulBackgroundColor) &&
bmiSource->bmiColors.rgbGreen == GetGValue(ulBackgroundColor) &&
bmiSource->bmiColors.rgbRed == GetRValue(ulBackgroundColor)){
if (iSourceBitCount == 4){
i = (i | i << 4);
memset(pDestinationDIBits, i, ulDestinationSize);
break;
}
}
}
break;
case 16:
if (*((unsigned long *)bmiSource->bmiColors) == 0x7C00){
ulDestinationBackgroundColor = ((GetRValue(ulBackgroundColor) >> 3) << 10) +
((GetRValue(ulBackgroundColor) >> 3) << 5) +
( GetBValue(ulBackgroundColor) >> 3);
}
else{
ulDestinationBackgroundColor = ((GetRValue(ulBackgroundColor) >> 3) << 11) +
((GetRValue(ulBackgroundColor) >> 2) << 5) +
( GetBValue(ulBackgroundColor) >> 3);
}
break;
case 24:
case 32:
ulDestinationBackgroundColor = (((unsigned long)GetRValue(ulBackgroundColor)) << 16) |
(((unsigned long)GetGValue(ulBackgroundColor)) << 8) |
( unsigned long)GetBValue(ulBackgroundColor);
break;
}
for (y = 0; y < iDestinationHeight; y++){
for (x = 0; x < iDestinationWidth; x++){
int iX, iY;
//unsigned char ucMask;
unsigned long ulPixel;
iX = (int)((x + min(0, min(x1, min(x2, x3)))) * dCosine +
( y + min(0, min(y1, min(y2, y3)))) * dSine);
iY = (int)((y + min(0, min(y1, min(y2, y3)))) * dCosine -
( x + min(0, min(x1, min(x2, x3)))) * dSine);
if (iX >= 0 && iX < iSourceWidth && iY >= 0 && iY < iSourceHeight){
switch (iSourceBitCount){
case 1:
break;
case 24:
ulPixel = *((unsigned long *)((unsigned char *)pSourceDIBits + iSourceRowLength * iY + iX * 3))
& 0xFFFFFF;
*((unsigned long *)((unsigned char *)pDestinationDIBits + iDestinationRowLength * y + x * 3))
|= ulPixel;
break;
}
}
else{
switch (iSourceBitCount){
case 1:
break;
case 24:
*((unsigned *)((unsigned char *)pDestinationDIBits + iDestinationRowLength * y + x * 3))
|= ulDestinationBackgroundColor;
break;
}
}
}
}
return (TRUE);
}