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)实现图片旋转的更多相关文章

  1. Windows API 函数列表 附帮助手册

    所有Windows API函数列表,为了方便查询,也为了大家查找,所以整理一下贡献出来了. 帮助手册:700多个Windows API的函数手册 免费下载 API之网络函数 API之消息函数 API之 ...

  2. Windows API Finishing

    input { font-size: 14px; height: 26px } td { border-style: none; border-color: inherit; border-width ...

  3. Windows API函数大全(完整)

    Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...

  4. [windows菜鸟]Windows API函数大全(完整)

    Windows API函数大全,从事软件开发的朋友可以参考下 1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一 ...

  5. WINDOWS API 大全(一)

    1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同 ...

  6. 在VBA中使用Windows API

    VBA是一种强大的编程语言,可用于自定义Microsoft Office解决方案.通过使用VBA处理一个或多个Office应用程序对象模型,可以容易地修改Office应用程序的功能或者能够使两个或多个 ...

  7. 学习之路三十九:新手学习 - Windows API

    来到了新公司,一开始就要做个程序去获取另外一个程序里的数据,哇,挑战性很大. 经过两周的学习,终于搞定,主要还是对Windows API有了更多的了解. 文中所有的消息常量,API,结构体都整理出来了 ...

  8. windows API 开发飞机订票系统 图形化界面 (二)

    首先,用到的数据结构的定义.以及全局变量和函数的声明如下: // Flight.c : 定义应用程序的入口点. // #include "stdafx.h" //订单 typede ...

  9. C#中调用Windows API的要点 .

    介绍 API(Application Programming Interface),我想大家不会陌生,它是我们Windows编程的常客,虽然基于.Net平台的C#有了强大的类库,但是,我们还是不能否认 ...

随机推荐

  1. js实现正则判断手机号

    //判断是否为手机号的正则表达式 function phoneFun(phones){ var myreg = /^[1][3,4,5,7,8,9][0-9]{9}$/; if (!myreg.tes ...

  2. 【安装】Mac rabbitMQ

    安装 brew install rabbitmq 目录  cd /usr/local/Cellar/rabbitmq/3.7.4/sbin 插件 sudo ./rabbitmq-plugins ena ...

  3. 【重磅来袭】阿里小程序IDE上线8大功能

    时隔两个月,10月10日阿里小程序IDE上线了uni-app 跨平台研发支持.预览和真机调试交互优化.预检测新增代码扫描等8项功能,进一步完善了阿里小程序IDE的功能池,给大家更好的开发体验和环境. ...

  4. nginx、php-fpm安装mongodb及驱动扩展

    1.安装mongodb linux下安装mongodb很简单,执行如下命令完成安装 wget http://downloads.mongodb.org/linux/mongodb-linux-i686 ...

  5. RN书签

    Bookmarks 书签栏 门户 配置reactNative(RN)过程中 出现react-native:command not... - 简书 * React-NativeChannel - sma ...

  6. 牛客练习赛43B Tachibana Kanade Loves Probability

    题目链接:https://ac.nowcoder.com/acm/contest/548/C 题目大意 略 分析 利用快速幂先移到 k1 位,然后开始一个一个取余数. 代码如下 #include &l ...

  7. jdbc出现中文乱码的解决办法

  8. cms系统视频分享

    cms_001-CMS系统功能需求简介-1.avicms_002-如何采用用例分析方法来理解需求-1.avicms_003-后台管理系统用例-1.avicms_004-实现验证码的初步思路-1.avi ...

  9. Spring Cloud高级视频

    Spring Cloud高级视频 第一章 微服务架构概述 第二章 开始使用Spring Cloud实战微服务 第三章 服务提供者与服务消费者 第四章 服务发现与服务注册 第五章 使用Hystrix保护 ...

  10. Spring-Boot中如何使用多线程处理任务

    看到这个标题,相信不少人会感到疑惑,回忆你们自己的场景会发现,在Spring的项目中很少有使用多线程处理任务的,没错,大多数时候我们都是使用Spring MVC开发的web项目,默认的Controll ...