windows api (GDI) to achieve image rotation

GDI achieve image rotation, bloggers on the Internet to find a lot of information, are not smug.

And found in the attempt, if the origin of the coordinate SetViewportOrgEx first with the image moves to the center of HDC; reacquisition each point on the HDC performs trigonometric function conversion, calculated new coordinates are plotted points. Theoretically possible, but because of double and int conversion, it will lose precision, after rotating the image will be blurred.

Attachment: trigonometric formula

逆时针:
x1 = xcos (b) -ysin (b);
y1 = ycos (b) + xsin (b);

顺时针:
x1 xcos = (b) + ysin (b);
y1 = ycos (b) -xsin (b);

 

I find a lot of information going around in circles, we found a large rotating function PlgBlt use God to achieve the picture, but use the VB. According to understand, it was modified and translated into C ++. Code below, Rotate focus function, along with the use of methods:

#include <cmath>
using namespace std;

extern "C"
{
    #include <windows.h>
    #include <tchar.h>
    #include "resource.h"
}

#define ID_TIMER 1

/*
逆时针
x1=xcos(β)-ysin(β); 
y1=ycos(β)+xsin(β);

顺时针
x1=xcos(β)+ysin(β); 
y1=ycos(β)-xsin(β);
*/

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
void Rotate(HDC hdcDest,int xPos,int yPos,int angle,HDC hdcSrc,int xSrc,int ySrc,int srcWidth,int srcHeight);

HWND hwnd;
HINSTANCE hInst;
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
    TCHAR szAppName[]=TEXT("first win");
    
    MSG msg;
    WNDCLASS wndclass;
    hInst=hInstance;

    wndclass.style=CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc=WndProc;
    wndclass.cbClsExtra=0;
    wndclass.cbWndExtra=0;
    wndclass.hInstance=hInstance;
    wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
    wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName=NULL;
    wndclass.lpszClassName=szAppName;

    if(!RegisterClass(&wndclass))
    {
        MessageBox(NULL,TEXT("error"),szAppName,MB_ICONERROR);
        return 0;
    }


    hwnd=CreateWindow(szAppName,
                      TEXT("hello"),
                      WS_OVERLAPPEDWINDOW^WS_MAXIMIZEBOX^WS_THICKFRAME,
                      20,    //CW_USEDEFAULT
                      50,
                      600,    //CW_USEDEFAULT,
                      400,    //CW_USEDEFAULT,
                      NULL,
                      NULL,
                      hInstance,
                      NULL);
    
    ShowWindow(hwnd,nShowCmd);
    UpdateWindow(hwnd);

    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }


    return msg.wParam;
}


HDC hdc;
PAINTSTRUCT ps;

HDC dcWin,dcBmp1,dcBmp2;
HBITMAP hBmp1,hBmp2;

POINT pt;
RECT rect;

int angle=0;

void Rotate(HDC hdcDest,int xPos,int yPos,int angle,HDC hdcSrc,int xSrc,int ySrc,int srcWidth,int srcHeight,COLORREF col)
{
    POINT pt[3];
    POINT defPt[3];
    double notPI=3.14/180;

    double thetS,thetC;
    int ret;

    pt[0].x=-srcWidth * 0.5;
    pt[0].y=-srcHeight * 0.5;

    pt[1].x = pt[0].x + srcWidth;
    pt[1].y = pt[0].y;
    
    pt[2].x = pt[0].x;
    pt[2].y = pt[0].y + srcHeight;

    thetS = sin(angle * notPI);
    thetC = cos(angle * notPI);
    defPt[0].x = (pt[0].x * thetC - pt[0].y * thetS) + xPos;
    defPt[0].y = (pt[0].x * thetS + pt[0].y * thetC) + yPos;
        
    defPt[1].x = (pt[1].x * thetC - pt[1].y * thetS) + xPos;
    defPt[1].y = (pt[1].x * thetS + pt[1].y * thetC) + yPos;
        
    defPt[2].x = (pt[2].x * thetC - pt[2].y * thetS) + xPos;
    defPt[2].y = (pt[2].x * thetS + pt[2].y * thetC) + yPos;

    HBRUSH hBrush=CreateSolidBrush(col);
    RECT rect;
    rect.left=rect.top=0;
    rect.right=rect.left+srcWidth;
    rect.bottom=rect.top+srcHeight;
    FillRect(hdcDest,&rect,hBrush);
    DeleteObject(hBrush);

    PlgBlt(hdcDest, &defPt[0], hdcSrc, xSrc, ySrc, srcWidth, srcHeight, 0, 0, 0);
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    switch(message)
    {
        case WM_CREATE:
            dcWin=GetDC(hwnd);
            dcBmp1=CreateCompatibleDC(dcWin);
            dcBmp2=CreateCompatibleDC(dcWin);

            hBmp1=LoadBitmap(hInst,MAKEINTRESOURCE(IDB_BITMAP1));
            hBmp2=CreateCompatibleBitmap(dcWin,98,98 ); 

            the SelectObject (dcBmp1, hBmp1); 
            the SelectObject (dcBmp2, hBMP2); 

            // The dcBmp1 to (49, 49) of the angle coordinates of the center of rotation angle of the painting into the dcBmp2 
            Rotate (dcBmp2, 49 , 49 , angle, dcBmp1 , 0 , 0 , 98 , 98 , 0xFFFFFF ); 
            
            the SetTimer (HWND, ID_TIMER, 500 , NULL); 
            
            BREAK ;
         Case the WM_PAINT: 
            HDC = the BeginPaint (HWND, & PS); 
            the SetBkMode (HDC, the TRANSPARENT); 

            the BitBlt (HDC, 0 , 0 ,98,98,dcBmp1,0,0,SRCCOPY);
            BitBlt(hdc,100,0,98,98,dcBmp2,0,0,SRCCOPY);

            EndPaint(hwnd,&ps);
            break;
        case WM_TIMER:
            if(wParam==ID_TIMER)
            {
                angle=(angle+15)%360;
                Rotate(dcBmp2,49,49,angle,dcBmp1,0,0,98,98,0xffffff);
                InvalidateRect(hwnd,NULL,true);
                UpdateWindow(hwnd);
            }
            break;
        case WM_DESTROY:
            ReleaseDC(hwnd,dcWin);

            DeleteDC(dcBmp1);
            DeleteDC(dcBmp2);

            DeleteObject(hBmp1);
            DeleteObject(hBmp2);

            KillTimer(hwnd,ID_TIMER);
            PostQuitMessage(0);
            return 0;

    }

    return DefWindowProc(hwnd,message,wParam,lParam);
}

 

Guess you like

Origin www.cnblogs.com/ddcoder/p/11628116.html