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. vagrant ssh try

    Vagrantfile add Vagrant.configure("2") do |config| config.vm.network "private_network ...

  2. Python with语句的概率,不多说了直接上代码!

    python中的with语句用于访问资源.它确保执行指定的__exit__(“清理”)操作,而不管释放被访问资源的处理过程中的错误或异常,例如读取和写入文件后自动关闭.线程中锁的自动获取和释放等. p ...

  3. flyway 管理数据库版本

    Flyway 和 Liquibase 都是 Java 项目中常用的 DB migration 工具, 从使用简便性看,Flyway 比 Liquibase 更简单, 从 github 的 star 数 ...

  4. 语音识别(Web Speech API)

    近期看了一个语音识别的dome-----Web Speech API 本api为js调用云端接口识别 个人测试了一下,响应速度还是比较快的 注意:本API与官网需翻墙使用和访问 展示效果: 页面代码如 ...

  5. NX二次开发-清除信息窗口中的内容,退出信息窗口UF_UI_exit_listing_window

    #include <uf.h> #include <uf_ui.h> UF_initialize(); //打开信息窗口 UF_UI_open_listing_window() ...

  6. 笨办法学Python记录--习题18 变量 函数 help的由来;if语句,循环和列表,冒泡排序,判断输入字符串的方法

    20140414 记录 习题17 - 33 函数可以做3件事: 1. 给代码片段命名,,就跟“变量”给字符串和数字命名一样. 2. 可以接受参数,就跟你的脚本接受argv 一样. 3. 通过使用#1 ...

  7. 【题解】P1440 求m区间内的最小值

    求m区间内的最小值 题目描述: 一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值.若前面的数不足m项则从第1个数开始,若前面没有数则输出0. 分析: 读题之 ...

  8. Linux上 安装Sorl4.7 中间件用tomcat

    最近需要用到solr,公司内部搭建了一个solr测试环境. 版本:solr4.7.2 ,tomcat 7.0.55 jdk:1.7_051 解压 solr 和tomcat  这里就不详说. 1.启动t ...

  9. 16-MySQL-Ubuntu-数据表的查询-分组与聚合(五)

    分组(group by)一般与聚合结合使用 (1)查询按性别分组 select gender from students group by gender; (2)查询按性别分组并统计每组的数量sele ...

  10. [CERC2017]Gambling Guide

    题目 看起来非常随机游走,但是由于我们可以停在原地,所以变得不是非常一样 设\(f_x\)表示从\(x\)到\(n\)的期望距离 如果我们提前知道了\(f\),那么我们随机到了一张到\(y\)的车票, ...