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=;
wndclass.cbWndExtra=;
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 ;
} hwnd=CreateWindow(szAppName,
TEXT("hello"),
WS_OVERLAPPEDWINDOW^WS_MAXIMIZEBOX^WS_THICKFRAME,
, //CW_USEDEFAULT
,
, //CW_USEDEFAULT,
, //CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL); ShowWindow(hwnd,nShowCmd);
UpdateWindow(hwnd); while(GetMessage(&msg,NULL,,))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
} return msg.wParam;
} HDC hdc;
PAINTSTRUCT ps; HDC dcWin,dcBmp1,dcBmp2;
HBITMAP hBmp1,hBmp2; POINT pt;
RECT rect; int angle=; void Rotate(HDC hdcDest,int xPos,int yPos,int angle,HDC hdcSrc,int xSrc,int ySrc,int srcWidth,int srcHeight,COLORREF col)
{
POINT pt[];
POINT defPt[];
double notPI=3.14/; double thetS,thetC;
int ret; pt[].x=-srcWidth * 0.5;
pt[].y=-srcHeight * 0.5; pt[].x = pt[].x + srcWidth;
pt[].y = pt[].y; pt[].x = pt[].x;
pt[].y = pt[].y + srcHeight; thetS = sin(angle * notPI);
thetC = cos(angle * notPI);
defPt[].x = (pt[].x * thetC - pt[].y * thetS) + xPos;
defPt[].y = (pt[].x * thetS + pt[].y * thetC) + yPos; defPt[].x = (pt[].x * thetC - pt[].y * thetS) + xPos;
defPt[].y = (pt[].x * thetS + pt[].y * thetC) + yPos; defPt[].x = (pt[].x * thetC - pt[].y * thetS) + xPos;
defPt[].y = (pt[].x * thetS + pt[].y * thetC) + yPos; HBRUSH hBrush=CreateSolidBrush(col);
RECT rect;
rect.left=rect.top=;
rect.right=rect.left+srcWidth;
rect.bottom=rect.top+srcHeight;
FillRect(hdcDest,&rect,hBrush);
DeleteObject(hBrush); PlgBlt(hdcDest, &defPt[], hdcSrc, xSrc, ySrc, srcWidth, srcHeight, , , );
} 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,,); SelectObject(dcBmp1,hBmp1);
SelectObject(dcBmp2,hBmp2); //将dcBmp1以(49,49)为坐标中心旋转angle角度后后画到dcBmp2中
Rotate(dcBmp2,,,angle,dcBmp1,,,,,0xffffff); SetTimer(hwnd,ID_TIMER,,NULL); break;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
SetBkMode(hdc,TRANSPARENT); BitBlt(hdc,,,,,dcBmp1,,,SRCCOPY);
BitBlt(hdc,,,,,dcBmp2,,,SRCCOPY); EndPaint(hwnd,&ps);
break;
case WM_TIMER:
if(wParam==ID_TIMER)
{
angle=(angle+)%;
Rotate(dcBmp2,,,angle,dcBmp1,,,,,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();
return ; } return DefWindowProc(hwnd,message,wParam,lParam);
}
windows api(GDI)实现图片旋转的更多相关文章
- Windows API 函数列表 附帮助手册
所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...
- Windows API Finishing
input { font-size: 14px; height: 26px } td { border-style: none; border-color: inherit; border-width ...
- Windows API函数大全(完整)
Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...
- [windows菜鸟]Windows API函数大全(完整)
Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...
- WINDOWS API 大全(一)
1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同 ...
- 在VBA中使用Windows API
VBA是一种强大的编程语言,可用于自定义Microsoft Office解决方案.通过使用VBA处理一个或多个Office应用程序对象模型,可以容易地修改Office应用程序的功能或者能够使两个或多个 ...
- 学习之路三十九:新手学习 - Windows API
来到了新公司,一开始就要做个程序去获取另外一个程序里的数据,哇,挑战性很大. 经过两周的学习,终于搞定,主要还是对Windows API有了更多的了解. 文中所有的消息常量,API,结构体都整理出来了 ...
- windows API 开发飞机订票系统 图形化界面 (二)
首先,用到的数据结构的定义.以及全局变量和函数的声明如下: // Flight.c : 定义应用程序的入口点. // #include "stdafx.h" //订单 typede ...
- C#中调用Windows API的要点 .
介绍 API(Application Programming Interface),我想大家不会陌生,它是我们Windows编程的常客,虽然基于.Net平台的C#有了强大的类库,但是,我们还是不能否认 ...
随机推荐
- CSIC_716_20191203【 socket网络编程,以及沾包问题的高级解决方式】
AF_UNIX(本机通信) AF_INET(TCP/IP – IPv4) AF_INET6(TCP/IP – IPv6) SOCK_STREAM(TCP流) SOCK_DGRAM(UDP数据报) 远程 ...
- WPS Office for Mac如何修改Word文档文字排列?WPS office修改Word文档文字排列方向教程
Word文档如何改变文字的排列方向?最新版WPS Office for Mac修复了文字排版相关的细节问题,可以更快捷的进行Word编辑,WPS Office在苹果电脑中如何修改Word文档文字排列方 ...
- 脚本启动SpringBoot(jar)
#!/bin/sh RESOURCE_NAME=springbsit-api.jar tpid=`ps -ef|grep $RESOURCE_NAME|grep -v grep|grep -v kil ...
- 深入浅出的Object.defineProperty()
vue的原理 观察者模式和订阅-发布者模式. Vue实例被创建时,会遍历data属性,并通过Object.defineProperty将 这些属性转化为getter/setter,并进行追踪依赖.每当 ...
- FontFamily 和Font 的区别
GDI+ 将字样相同但字形不同的字体分组为字体系列.例如,下面是同一个字样(Arial),不同的字形 : ----------------------------------------------- ...
- NX二次开发-打开文件夹,并同时选中指定文件
NX9+VS2012 #include <uf.h> #include <uf_ui.h> #include <uf_part.h> #include <at ...
- mac 安装配置使用 mongoldb
mac 安装配置使用 mongoldb 安装和配置 brew install mongos brew install mongo # 密码就是用户的密码 # 配置数据文件 //如果不配置会出现错误62 ...
- Java 并发总结(三)
锁优化及注意事项 有助于提高锁的性能 减小所持有时间:例如不要对方法直接加锁,而是在方法中对具体访问临界资源的代码加锁 减小锁粒度:如ConcurrentHashMap 用读写锁代替独占锁 锁分离:如 ...
- 剑指offer——09青蛙跳台阶
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 题解: 说俗一点,就是找规律: 不不,首先,我们分析一下,青蛙第一 ...
- 干货:Java正确获取客户端真实IP方法整理
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...