windows api(GDI)实现图片旋转
发布时间:2021-01-08 06:30:05 所属栏目:系统 来源:网络整理
导读:GDI实现图片旋转,博主在网上找了好多资料,都不太如意。 并且在尝试中发现,如果先用SetViewportOrgEx将HDC上的坐标原点移动到图片中心;再在HDC上的获取每个点,用三角函数进行变换,算得新坐标进行点绘制。理论可行,但是因为double与int转换的关系,会丢
GDI实现图片旋转,博主在网上找了好多资料,都不太如意。 并且在尝试中发现,如果先用SetViewportOrgEx将HDC上的坐标原点移动到图片中心;再在HDC上的获取每个点,用三角函数进行变换,算得新坐标进行点绘制。理论可行,但是因为double与int转换的关系,会丢失精度,旋转后图像会很模糊。 附:三角函数公式 逆时针: 顺时针: ? 笔者兜兜转转找了很多资料,发现有大神利用函数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, NULL,NULL,hInstance,NULL); ShowWindow(hwnd,nShowCmd); UpdateWindow(hwnd); while(GetMessage(&msg,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 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); } LRESULT CALLBACK WndProc(HWND hwnd,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,angle,0xffffff); SetTimer(hwnd,ID_TIMER,500,NULL); break; case WM_PAINT: hdc=BeginPaint(hwnd,&ps); SetBkMode(hdc,TRANSPARENT); BitBlt(hdc,0,0,SRCCOPY); BitBlt(hdc,100,dcBmp2,SRCCOPY); EndPaint(hwnd,&ps); break; case WM_TIMER: if(wParam==ID_TIMER) { angle=(angle+15)%360; Rotate(dcBmp2,49,0xffffff); InvalidateRect(hwnd,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); } (编辑:焦作站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |