zoukankan      html  css  js  c++  java
  • windows api(GDI)实现图片旋转

    GDI实现图片旋转,博主在网上找了好多资料,都不太如意。

    并且在尝试中发现,如果先用SetViewportOrgEx将HDC上的坐标原点移动到图片中心;再在HDC上的获取每个点,用三角函数进行变换,算得新坐标进行点绘制。理论可行,但是因为double与int转换的关系,会丢失精度,旋转后图像会很模糊。

    附:三角函数公式

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

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

    笔者兜兜转转找了很多资料,发现有大神利用函数PlgBlt实现图片的旋转,但是用的是VB。根据理解,本人进行了修改,并译成了C++。代码如下,重点在于Rotate函数,并附上使用方法:

    #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);
    
                SelectObject(dcBmp1,hBmp1);
                SelectObject(dcBmp2,hBmp2);
    
                //将dcBmp1以(49,49)为坐标中心旋转angle角度后后画到dcBmp2中
                Rotate(dcBmp2,49,49,angle,dcBmp1,0,0,98,98,0xffffff);
                
                SetTimer(hwnd,ID_TIMER,500,NULL);
                
                break;
            case WM_PAINT:
                hdc=BeginPaint(hwnd,&ps);
                SetBkMode(hdc,TRANSPARENT);
    
                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);
    }
  • 相关阅读:
    Redis基本概念、基本使用与单机集群部署
    Storm安装部署
    HBase单机和集群版部署
    Hive基础概念、安装部署与基本使用
    Hadoop — HDFS的概念、原理及基本操作
    随机森林
    深度学习入门: CNN与LSTM(RNN)
    word修改页眉使本页的页眉与别的页不一样
    几个值得学习的Java博客
    【转】求最短路径长度--简单易懂
  • 原文地址:https://www.cnblogs.com/ddcoder/p/11628116.html
Copyright © 2011-2022 走看看