ソフトウェア開発 Win32プログラミング

ビットマップの回転

戻る


ビットマップを回転させるコードは以下の通り。

#include <windows.h>
#include <math.h>

HBITMAP CreateRotated32BppBitmap(HBITMAP hbmSrc, double angle, BOOL fGrow)
{
    HDC hdc;
    HBITMAP hbm;
    BITMAP bm;
    BITMAPINFO bi;
    LPBYTE pbBits, pbBitsSrc;
    LONG widthbytes, widthbytesSrc;
    INT cost, sint;
    INT cx, cy, x0, x1, y0, y1, px, py, qx, qy;
    BYTE r0, g0, b0, a0, r1, g1, b1, a1;
    INT mx, my;
    INT x, y, ex0, ey0, ex1, ey1;

    if (!GetObject(hbmSrc, sizeof(BITMAP), &bm))
        return NULL;

    if (fGrow)
    {
        cx = (INT)(fabs(bm.bmWidth * cos(angle)) + fabs(bm.bmHeight * sin(angle)) + 0.5);
        cy = (INT)(fabs(bm.bmWidth * sin(angle)) + fabs(bm.bmHeight * cos(angle)) + 0.5);
    }
    else
    {
        cx = bm.bmWidth;
        cy = bm.bmHeight;
    }

    ZeroMemory(&bi.bmiHeader, sizeof(BITMAPINFOHEADER));
    bi.bmiHeader.biSize     = sizeof(BITMAPINFOHEADER);
    bi.bmiHeader.biWidth    = cx;
    bi.bmiHeader.biHeight   = cy;
    bi.bmiHeader.biPlanes   = 1;
    bi.bmiHeader.biBitCount = 32;

    widthbytesSrc = bm.bmWidth * 4;
    widthbytes = cx * 4;

    hdc = CreateCompatibleDC(NULL);
    if (hdc != NULL)
    {
        hbm = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, (VOID **)&pbBits,
                               NULL, 0);
        if (hbm != NULL)
        {
            pbBitsSrc = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, widthbytesSrc * bm.bmHeight);
            if (pbBitsSrc != NULL)
                goto success;
            DeleteObject(hbm);
        }
        DeleteDC(hdc);
    }
    return NULL;

success:
    px = (bm.bmWidth - 1) << 15;
    py = (bm.bmHeight - 1) << 15;
    qx = (cx - 1) << 7;
    qy = (cy - 1) << 7;
    cost = cos(angle) * 256;
    sint = sin(angle) * 256;
    bi.bmiHeader.biWidth    = bm.bmWidth;
    bi.bmiHeader.biHeight   = bm.bmHeight;
    GetDIBits(hdc, hbmSrc, 0, bm.bmHeight, pbBitsSrc, &bi, DIB_RGB_COLORS);
    if (bm.bmBitsPixel < 32)
    {
        UINT cdw = bm.bmWidth * bm.bmHeight;
        LPBYTE pb = pbBitsSrc;
        while(cdw--)
        {
            pb++;
            pb++;
            pb++;
            *pb++ = 0xFF;
        }
    }
    ZeroMemory(pbBits, widthbytes * cy);

    x = (0 - qx) * cost + (0 - qy) * sint + px;
    y = -(0 - qx) * sint + (0 - qy) * cost + py;
    for(my = 0; my < cy; my++)
    {
        /* x = (0 - qx) * cost + ((my << 8) - qy) * sint + px; */
        /* y = -(0 - qx) * sint + ((my << 8) - qy) * cost + py; */
        for(mx = 0; mx < cx; mx++)
        {
            /* x = ((mx << 8) - qx) * cost + ((my << 8) - qy) * sint + px; */
            /* y = -((mx << 8) - qx) * sint + ((my << 8) - qy) * cost + py; */
            x0 = x >> 16;
            x1 = min(x0 + 1, (INT)bm.bmWidth - 1);
            ex1 = x & 0xFFFF;
            ex0 = 0x10000 - ex1;
            y0 = y >> 16;
            y1 = min(y0 + 1, (INT)bm.bmHeight - 1);
            ey1 = y & 0xFFFF;
            ey0 = 0x10000 - ey1;
            if (0 <= x0 && x0 < bm.bmWidth && 0 <= y0 && y0 < bm.bmHeight)
            {
                DWORD c00 = *(DWORD *)&pbBitsSrc[x0 * 4 + y0 * widthbytesSrc];
                DWORD c01 = *(DWORD *)&pbBitsSrc[x0 * 4 + y1 * widthbytesSrc];
                DWORD c10 = *(DWORD *)&pbBitsSrc[x1 * 4 + y0 * widthbytesSrc];
                DWORD c11 = *(DWORD *)&pbBitsSrc[x1 * 4 + y1 * widthbytesSrc];
                b0 = ((ex0 * (c00 & 0xFF)) + (ex1 * (c10 & 0xFF))) >> 16;
                b1 = ((ex0 * (c01 & 0xFF)) + (ex1 * (c11 & 0xFF))) >> 16;
                g0 = ((ex0 * ((c00 >> 8) & 0xFF)) + (ex1 * ((c10 >> 8) & 0xFF))) >> 16;
                g1 = ((ex0 * ((c01 >> 8) & 0xFF)) + (ex1 * ((c11 >> 8) & 0xFF))) >> 16;
                r0 = ((ex0 * ((c00 >> 16) & 0xFF)) + (ex1 * ((c10 >> 16) & 0xFF))) >> 16;
                r1 = ((ex0 * ((c01 >> 16) & 0xFF)) + (ex1 * ((c11 >> 16) & 0xFF))) >> 16;
                a0 = ((ex0 * ((c00 >> 24) & 0xFF)) + (ex1 * ((c10 >> 24) & 0xFF))) >> 16;
                a1 = ((ex0 * ((c01 >> 24) & 0xFF)) + (ex1 * ((c11 >> 24) & 0xFF))) >> 16;
                b0 = (ey0 * b0 + ey1 * b1) >> 16;
                g0 = (ey0 * g0 + ey1 * g1) >> 16;
                r0 = (ey0 * r0 + ey1 * r1) >> 16;
                a0 = (ey0 * a0 + ey1 * a1) >> 16;
                *(DWORD *)&pbBits[mx * 4 + my * widthbytes] =
                    MAKELONG(MAKEWORD(b0, g0), MAKEWORD(r0, a0));
            }
            x += cost << 8;
            y -= sint << 8;
        }
        x -= cx * cost << 8;
        x += sint << 8;
        y -= -cx * sint << 8;
        y += cost << 8;
    }
    HeapFree(GetProcessHeap(), 0, pbBitsSrc);
    DeleteDC(hdc);
    return hbm;
}

#ifdef UNITTEST
typedef struct tagBITMAPINFOEX
{
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD          bmiColors[256];
} BITMAPINFOEX, FAR * LPBITMAPINFOEX;

BOOL SaveBitmapToFile(LPCTSTR pszFileName, HBITMAP hbm)
{
    ...
}

int main(void)
{
    HBITMAP hbmSrc = (HBITMAP)LoadImage(NULL, "a.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    HBITMAP hbm = CreateRotated32BppBitmap(hbmSrc, 10 * M_PI / 180, TRUE);
    SaveBitmapToFile("b.bmp", hbm);
    DeleteObject(hbm);
    DeleteObject(hbmSrc);
    return 0;
}
#endif  /* def UNITTEST */

ソース: rotate.zip


戻る

©片山博文MZ
katayama.hirofumi.mz@gmail.com

inserted by FC2 system