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#有了强大的类库,但是,我们还是不能否认 ...
随机推荐
- requests中text和content的区别
# -*- coding: utf-8 -*- __author__ = "nixinxin" import re img_url = "https://f11.baid ...
- vs2010用iis5作为调试服务器从而允许非本机电脑访问项目网站
工作的时候经常遇见这2种情况 1,和设备端的同事调程序,但是他们却不能访问vs自带的web服务器 2,写好的程序在vs中运行一点问题都没有,一发布到iis就问题一大堆 后来在终于有了一个比较好的解决办 ...
- Mysql添加用户和数据库
先创建数据库 创建用户并赋予一个数据库的所有权限 use mysql; create database databaseName character set utf8; grant all privi ...
- -bash: docker-compose: command not found、linux 安装 docker-compose
方式1:https://blog.csdn.net/qq_32447321/article/details/76512137 方式2: curl -L https://get.daocloud.io/ ...
- Nginx的静态代理
Nginx的静态代理 Nginx的web请求的处理机制 Nginx结合多进程和异步机制对外提供服务,异步机制使用的是异步非阻塞机制,即AIO,Nginx的master进程会生成多个worker进程,m ...
- 将map转为Object,支持 Date/Boolean
import lombok.extern.log4j.Log4j2; import java.lang.reflect.Field; import java.lang.reflect.Method; ...
- Struts功能详解——ValidatorForm
ActionForm和ValidatorForm区别: 一个Form继承了ValidatorForm 就不用写具体的验证,但是需要提供:validation-rules.xml 和 val ...
- jdk 动态代理和 cglib 动态代理
原理区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 而cglib动态代理是利用asm开源包,对代理对象类的class文件加载 ...
- 反射Reflection
using System; using System.Collections.Generic; using System.Linq; using System.Reflection;// <-- ...
- AsyncAwait
using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namesp ...