[VC]旋转位图图片的算法函数

网上有很多关于位图旋转的资料,但是讲得很清楚的不多(我没有仔细查找).于是我也写了一个,希望能给向我这样的初学者一点帮助.

第一步,你必须知道位图即BMP格式的文件的结构.

位图(bmp)文件由以下几个部分组成:

1.BITMAPFILEHEADER,它的定义如下:

typedef struct tagBITMAPFILEHEADER {
               WORD  bfType;     //必须为'BM'
               DWORD  bfSize;     //文件大小
               WORD  bfReserved1; //必须为0
               WORD  bfReserved2; //必须为0
               DWORD  bfOffBits;  //从ITMAPFILEHEADER到存放bmp数据的偏移量                 
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

2.BITMAPINFOHEADER,它的定义如下:

typedef struct tagBITMAPINFOHEADER{
                  DWORD biSize; //此结构的大小,可用sizeof(BITMAPINFOHEAER)得到
                  LONG  biWidth; //位图宽度,以象素为单位
                     LONG  biHeight; //位图高度,以象素为单位
                  WORD  biPlanes; //必须为1
                  WORD  biBitCount;//位图象素位数,可为0,1,4,8,24,32
                  DWORD biCompression;
                  DWORD biSizeImage; //(仅用于压缩)
                     LONG  biXPelsPerMeter; //一米横向象素数
                  LONG  biYPelsPerMeter; //一米纵向象素数
                     DWORD biClrUsed;// (非零用语短颜色表)
                  DWORD biClrImportant;
            } BITMAPINFOHEADER, *PBITMAPINFOHEADER;

由于以上信息可以直接从MSDN上查到,所以只做简单介绍,你可以自己查看NSDN帮助,上面有很详细的介绍.

3.DIB位图像.这里放的是真正的位图数据.

知道了位图的存放格式,下面我们就可以很容易的把它读如内存.

第二步,读入bmp图像

LPCTSTR lpszFileName4="untitled.bmp";  //文件路径
    CFile file;                   //用于读取BMP文件
    BITMAPFILEHEADER bfhHeader;//bmp文件头
BITMAPINFOHEADER bmiHeader; //bmp格式头
LPBITMAPINFO lpBitmapInfo;  //bmp格式具体信息
    int bmpWidth=0;             //图片宽度
    int bmpHeight = 0;           //图片高度      
if(!file.Open(lpszFileName,CFile::modeRead))
        return ;               //打开文件
    file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));//读取文件头
    if(bfhHeader.bfType!=((WORD) ('M'<<8)|'B'))      //判断是否是"BM"
          return ;
    if(bfhHeader.bfSize!=file.GetLength())
        return ;
                 
   if (file.Read((LPSTR)&bmiHeader, sizeof(bmiHeader)) != sizeof(bmiHeader))
        return ;
   bmpHeight = bmiHeader.biHeight;//得到高度和宽度
   bmpWidth = bmiHeader.biWidth;
   file.SeekToBegin();
   file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));
   UINT uBmpInfoLen=(UINT) bfhHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
   lpBitmapInfo=(LPBITMAPINFO) new BYTE[uBmpInfoLen];
   file.Read((LPVOID) lpBitmapInfo,uBmpInfoLen);
   if((* (LPDWORD)(lpBitmapInfo))!=sizeof(BITMAPINFOHEADER))
        return ;
   DWORD dwBitlen=bfhHeader.bfSize - bfhHeader.bfOffBits;
   LPVOID lpSrcBits=new BYTE[dwBitlen];     //将数据读入lpSrcBits数组
   file.ReadHuge(lpSrcBits,dwBitlen);
   file.Close();                           //关闭文件

下面我们将图片显示在屏幕上:

第三步,显示图片

CClientDC hDC(this);

StretchDIBits(hDC,0,0,bmpWidth,bmpHeight,0,0,bmpWidth,bmpHeight,

lpSrcBits,lpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);

第四步,将图片读入内存设备环境

HDC dcSrc;

HBITMAP bitmap;

dcSrc=CreateCompatibleDC(hDC);//得到一个内存设备环境

bitmap = CreateCompatibleBitmap(hDC,bmpWidth,bmpHeight);

SelectObject(dcSrc,bitmap);

BitBlt(dcSrc,0,0,bmpWidth,bmpHeight,hDC,0,0,SRCCOPY);//这一步很重要

第五步,实现位图旋转

我们假设旋转位图的函数原形如下:

void RotateBitmap(HDC dcSrc,int SrcWidth,int SrcHeight,double angle,HDC pDC);

/*参数解释如下:/

HDC dcSrc:要旋转的位图的内存设备环境,就是第四步创建的

int SrcWidth:要旋转位图的宽度

int SrcHeight:要旋转位图的高度

double angle:所要旋转的角度,以弧度为单位 

HDC pDC:第三步得到的当前屏幕设备环境

*///

//以下是函数实现细节

void RotateAnyAngle(HDC dcSrc,int SrcWidth,int SrcHeight,double angle)
{
double x1,x2,x3;
double y1,y2,y3;
double maxWidth,maxHeight,minWidth,minHeight;
double srcX,srcY;
double sinA,cosA;
double DstWidth;
double DstHeight;
HDC dcDst;//旋转后的内存设备环境
HBITMAP newBitmap;
sinA = sin(angle);
cosA = cos(angle);
x1 = -SrcHeight * sinA;
   y1 = SrcHeight * cosA;
   x2 = SrcWidth * cosA - SrcHeight * sinA;
   y2 = SrcHeight * cosA + SrcWidth * sinA;
   x3 = SrcWidth * cosA;
   y3 = SrcWidth * sinA;
minWidth = x3>(x1>x2?x2:x1)?(x1>x2?x2:x1):x3;
minWidth = minWidth>0?0:minWidth;
minHeight = y3>(y1>y2?y2:y1)?(y1>y2?y2:y1):y3;
minHeight = minHeight>0?0:minHeight;
maxWidth = x3>(x1>x2?x1:x2)?x3:(x1>x2?x1:x2);
maxWidth = maxWidth>0?maxWidth:0;
maxHeight = y3>(y1>y2?y1:y2)?y3:(y1>y2?y1:y2);
maxHeight = maxHeight>0?maxHeight:0;
DstWidth = maxWidth - minWidth;
   DstHeight = maxHeight - minHeight;
dcDst = CreateCompatibleDC(dcSrc);
newBitmap = CreateCompatibleBitmap(dcSrc,(int)DstWidth,(int)DstHeight);
SelectObject(dcDst,newBitmap);
for( int I = 0 ;I<DstHeight;I++)
{
   for(int J = 0 ;J< DstWidth;J++)
   {
       srcX = (J + minWidth) * cosA + (I + minHeight) * sinA;
       srcY = (I + minHeight) * cosA - (J + minWidth) * sinA;
       if( (srcX >= 0) && (srcX <= SrcWidth) &&(srcY >= 0) && (srcY <= SrcHeight))
    {
        BitBlt(dcDst, J, I, 1, 1, dcSrc,(int)srcX, (int)srcY, SRCCOPY);
    }
     }
}
//显示旋转后的位图
BitBlt(hDC,200,200,(int)DstWidth,(int)DstHeight,dcDst,0,0,SRCCOPY);
  DeleteObject(newBitmap);
DeleteDC(dcDst);
}

最后我们调用就可以了:

double angle = (45/180.0)*3.14159;//旋转45Degree,可为任意角度

RotateAnyAngle(dcSrc,bmpWidth,bmpHeight,angle,);

到这里就大功告成了

转载于:https://www.cnblogs.com/gakusei/articles/1582162.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/476156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 836. 矩形重叠

1. 题目 矩形以列表 [x1, y1, x2, y2] 的形式表示&#xff0c;其中 (x1, y1) 为左下角的坐标&#xff0c;(x2, y2) 是右上角的坐标。 如果相交的面积为正&#xff0c;则称两矩形重叠。 需要明确的是&#xff0c;只在角或边接触的两个矩形不构成重叠。 给出两个矩形&#xff…

推荐系统和知识图谱论文推荐

KDD2020 Graph-based Recommendation&#xff08;基于图&#xff0c;不是知识图谱&#xff09; 1. A Framework for Recommending Accurate and Diverse Items Using Bayesian Graph Convolutional Neural Networks 【华为诺亚】 2. An Efficient Neighborhood-based Intera…

cmd执行python 环境变量应该怎么写_python怎么运行py文件?.py文件cmd命令方法及环境变量配置教程...

python是一款应用非常广泛的脚本程序语言&#xff0c;谷歌公司的网页就是用python编写。python在生物信息、统计、网页制作、计算等多个领域都体现出了强大的功能。python和其他脚本语言如java、R、Perl 一样&#xff0c;都可以直接在命令行里运行脚本程序。那么python怎么运行…

ASP.NET中的Eval()和DataBinder.Eval()方法

Eval( " ")和Bind( " ") 这两种一个单向绑定&#xff0c;一个双向绑定 bind是双向绑定,但需数据源可更改才能用 ASP.NET 2.0改善了模板中的数据绑定操作&#xff0c;把v1.x中的数据绑定语法DataBinder.Eval(Container.DataItem, fieldname)简化为Eval(fie…

知识图谱论文阅读(九)【转】推荐系统遇到知识图谱之MKR模型

文哥的学习笔记&#xff1a; https://www.jianshu.com/p/af5226c7fbbb 知识图谱特征学习在推荐系统中的应用步骤大致有以下三种方式&#xff1a; 依次训练的方法主要有&#xff1a;Deep knowledge-aware Network&#xff08;DKN&#xff09; 联合训练的方法有&#xff1a; Rip…

LeetCode 883. 三维形体投影面积

1. 题目 在 N * N 的网格中&#xff0c;我们放置了一些与 x&#xff0c;y&#xff0c;z 三轴对齐的 1 * 1 * 1 立方体。 每个值 v grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上。 现在&#xff0c;我们查看这些立方体在 xy、yz 和 zx 平面上的投影。 投影就像影子&a…

asoc linux设备驱动_Linux驱动分析之I2C设备

内核&#xff1a;4.20芯片&#xff1a;HYM8563 RTC下面的代码分析主要都在注释中&#xff0c;会按照驱动中函数的执行顺序分析。(1) 加载和卸载函数static const struct i2c_device_id hym8563_id[] {{ "hym8563", 0 },{}, }; MODULE_DEVICE_TABLE(i2c, hym8563_id)…

诚邀参加微软.NET俱乐部10月24日Windows 7社区发布会

为了配合微软下一代桌面操作系统—Windows7的发布&#xff0c;微软.NET俱乐部联合ZDNET至顶网社区特地组织了“让社区激情随Win 7 一同绽放”—Windows 7 社区发布会。10月24日13点半&#xff0c;将在北京&#xff0c;微软亚洲研究院地下一层阶梯会议中心举行&#xff0c;欢迎当…

知识图谱论文阅读【十二】【KDD2020】 使用贝叶斯图卷积神经网络推荐精确和多样化项目的框架【看不懂,待续】

题目&#xff1a; A Framework for Recommending Accurate and Diverse Items Using Bayesian Graph Convolutional Neural Networks 作者&#xff1a; 原文链接&#xff1a; https://www.researchgate.net/publication/343780326_A_Framework_for_Recommending_Accurate_and…

LeetCode 884. 两句话中的不常见单词

1. 题目 给定两个句子 A 和 B 。 &#xff08;句子是一串由空格分隔的单词。每个单词仅由小写字母组成。&#xff09; 如果一个单词在其中一个句子中只出现一次&#xff0c;在另一个句子中却没有出现&#xff0c;那么这个单词就是不常见的。 返回所有不常用单词的列表。 您…

bigdecimal如何做除法_二胎家庭如何平衡两个孩子的关系?聪明的父母都懂这四个法则...

治愈系慢综艺《朋友请听好》上段时间一直霸榜热搜。其中有一集&#xff0c;一位二胎妈妈来电探讨两个孩子的相处问题&#xff0c;引发了网友热议。弹幕里有人说&#xff1a;“别人家的孩子兄友弟恭&#xff0c;其乐融融&#xff0c;我们家永远是你来我往的大型武斗场景。”对此…

操作注册表

操作注册表 Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\MyKey"); RegistryKey rk Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\MyKey", true); rk.SetValue("姓名", "小芳"); …

LeetCode 893. 特殊等价字符串组

1. 题目 你将得到一个字符串数组 A。 如果经过任意次数的移动&#xff0c;S T&#xff0c;那么两个字符串 S 和 T 是特殊等价的。 一次移动包括选择两个索引 i 和 j&#xff0c;且 i &#xff05; 2 j &#xff05; 2&#xff0c;交换 S[j] 和 S [i]。 现在规定&#xff…

知识图谱论文阅读(十三)【2020 arXiv】Attentive Knowledge Graph Embedding for Personalized Recommendation

题目&#xff1a; Attentive Knowledge Graph Embedding for Personalized Recommendation 论文链接&#xff1a; 代码链接&#xff1a; 知识图谱特征学习在推荐系统中的应用步骤大致有以下三种方式&#xff1a; BPThrough Time 【5】Backpropagation: theory, architecture…

ad批量走线_AD PCB直角布线批量改为圆角,怎么批量修改呢?

1.拖动器件不让连接线跟着一起走&#xff0c;怎么设置呢&#xff1f;答&#xff1a;执行快捷键OP&#xff0c;将Always Drag选项的勾掉即可&#xff0c;如图所示&#xff1a;2.如图中所示&#xff0c;有很多元件位号重复或者位号需要重新编辑命名&#xff0c;请哪位大神有什么快…

[转帖]Mootools源码分析-02 -- Utils

原帖地址&#xff1a;http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-400118 原作者&#xff1a;我佛山人 //检查对象是否已经定义或者已经赋值function$chk(obj) { return!!(obj ||ōbj 0);};//通用清除计时器的方法,即能清setTimeout,又能清setIn…

ios realm 文件_iOS Realm数据库使用

Realm 是 SQLite 和 Core Data 的替代者&#xff0c;得益于其零拷贝的设计&#xff0c;Realm 比任何 ORM 都要快很多。Objective‑C版本的 Realm 能够让您以一种安全、耐用以及迅捷的方式来高效地编写应用的数据模型层&#xff0c;如下例所示&#xff1a;Dog.hinterface Dog : …

李宏毅机器学习(十一)meta-learning和ML一样是三个步骤

Meta-learning就是教会它怎么学&#xff01; 大家以为AI都是很牛&#xff0c;但其实就是在调参&#xff0c;在工业界怎么样子调参呢&#xff1f; 使用1000GPUs&#xff0c;而学业界只有一张&#xff01; 我们知道Machine learning可以学出来&#xff0c;那么hyperparameters是…

教育的真谛

湖畔疑云 大学将是你人生最重要的时光&#xff0c;在大学里你会发现学习的真谛。你以前经常会问到 “这个课程有什么用”&#xff0c;这是个好问题&#xff0c;但是我希望你理解&#xff1a;“教育的真谛就是当你忘记一切所学到的东西之后所剩下的东西。”我的意思是&#xff0…

LeetCode 748. 最短完整词

1. 题目 如果单词列表&#xff08;words&#xff09;中的一个单词包含牌照&#xff08;licensePlate&#xff09;中所有的字母&#xff0c;那么我们称之为完整词。 在所有完整词中&#xff0c;最短的单词我们称之为最短完整词。 单词在匹配牌照中的字母时不区分大小写&#x…