node 16位 转24位_同时将24位和32位BMP图像顺时针旋转90度

上一次我们将24位的皮卡丘旋转了90度,但是后来改需求了。。。要求把32位的.bmp文件也能够旋转90度。上次就懵逼的我继续懵逼,只好继续转向CSDN求助。

1d94b55028db531090d62c9f6c0090b4.png

浏览了各种求助帖(还找到了数年前的信科大一学长),终于发现了32位和24位的区别:32位图的每一个像素信息占4个字节,除了RGB三个颜色值以外,还有一个字节存储的是透明度。在读取和写入32位图的时候,每一个像素就要多读(写)一个字节。这就导致了24位和32位的DATA结构体不一样。如果定义两个DATA结构体,之后每次涉及到它的时候都要判断一下图的位数,好像很麻烦的亚子。为了解决这个问题,我们就不得不放弃上一次所用的DATA结构体了 。

//Farewell my DATA~
struct DATA
{BYTE blue;BYTE green;BYTE red;
};

我们转而直接按字节(BYTE)读取,不再将一个像素的信息装在结构体中,而是将其分开读取。需要在原来的代码上做一些改变,先把所有DATA类型的指针改为BYTE类型,分配存储空间的时候把空间大小也调整一下。

//32位就分配size*4,24位就分配size*3
BYTE *imgdata=new BYTE[size * srcInfo.biBitCount / 8];

然后我们把原来代码中的所有数字3改成biBitCount/8:

fread(imgdata + i * w * srcInfo.biBitCount / 8, srcInfo.biBitCount / 8, w, p);

这里因为imgdata的类型已经是unsigned char*了,只占1个字节,所以不用再进行指针类型转换(char*)了。

原先在旋转操作中赋值的时候只用赋值一次,就能将DATA结构体赋值给新的target指针。但现在没有DATA结构体了,我们就需要对每个像素的字节依次赋值:

for (int i=0; i<newH; i++){for (int j=0; j<newW; j++){*(target + (i * newW + j)*newInfo.biBitCount / 8) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 1) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 1);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 2) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 2);if (newInfo.biBitCount == 32) {*(target + (i * newW + j) * newInfo.biBitCount / 8 + 3) =*(src + (j * w + newH - i - 1) * newInfo.biBitCount / 8 + 3);}}}

这样主体就完成了,但是如果只修改这些的话,会发现最终生成的32位图无法打开。原因在于32位图和24位图的信息头有一点点差异:多了一些不知道是啥的内容。我们就把这些东西放在一个新的结构体Plus里吧。在读取和写入的时候判断一下图像位数,如果是32位就把这个Plus也读/写一下。

struct Plus{DWORD        bV5RedMask;DWORD        bV5GreenMask;DWORD        bV5BlueMask;DWORD        bV5AlphaMask;DWORD        bV5CSType;CIEXYZTRIPLE bV5Endpoints;DWORD        bV5GammaRed;DWORD        bV5GammaGreen;DWORD        bV5GammaBlue;DWORD        bV5Intent;DWORD        bV5ProfileData;DWORD        bV5ProfileSize;DWORD        bV5Reserved;
};

Plus的内容来自CSDN,其中那个醒目的CIEXYZTRIPLE是啥...我也不知道 。所以只好开始了漫长的搜索之路,最终找到了他的定义:

c45985dc94bcc0d26f55e266cf378f6b.png
CIEXYZTRIPLE的定义

图中FXPT2DOT30表示它们是带有2位元整数部分和30位元小数部分的定点值,这说的是啥我也不懂,只需要知道FXPT2DOT30其实就和int差不多就好了:

typedef int FXPT2DOT30;

现在就把所有东西全部定义好了,试着转一下这个年代久远的32位图:

ce7171cd979bc6b7d65c49dcf4411c41.png
原图

0d8c5e030fc8a74bd51c3ba7c88446e3.png
顺时针旋转90度

最后附上完整的代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef int FXPT2DOT30;typedef struct tagCIEXYZ
{FXPT2DOT30 ciexyzX ;FXPT2DOT30 ciexyzY ;FXPT2DOT30 ciexyzZ ;
}
CIEXYZ, * LPCIEXYZ ;typedef struct tagCIEXYZTRIPLE {CIEXYZ ciexyzRed ;CIEXYZ ciexyzGreen ;CIEXYZ ciexyzBlue ;
}CIEXYZTRIPLE;//位图文件头定义;
struct  Header{DWORD bfSize;//文件大小WORD bfReserved1;//保留字WORD bfReserved2;//保留字DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数
};//位图信息头定义
struct Info{DWORD biSize;//信息头大小DWORD biWidth;//图像宽度DWORD biHeight;//图像高度WORD biPlanes;//位平面数,必须为1WORD biBitCount;//每像素位数DWORD  biCompression; //压缩类型DWORD  biSizeImage; //压缩图像大小字节数DWORD  biXPelsPerMeter; //水平分辨率DWORD  biYPelsPerMeter; //垂直分辨率DWORD  biClrUsed; //位图实际用到的色彩数DWORD  biClrImportant; //本位图中重要的色彩数
};struct Plus{DWORD        bV5RedMask;DWORD        bV5GreenMask;DWORD        bV5BlueMask;DWORD        bV5AlphaMask;DWORD        bV5CSType;CIEXYZTRIPLE bV5Endpoints;DWORD        bV5GammaRed;DWORD        bV5GammaGreen;DWORD        bV5GammaBlue;DWORD        bV5Intent;DWORD        bV5ProfileData;DWORD        bV5ProfileSize;DWORD        bV5Reserved;
};WORD bfType;//文件类型
Header srcHead;//原文件文件头
Info srcInfo;//原文件信息头
Plus srcPlus;
int h,w,size;//原图像的高度、宽度和尺寸int getDiff(Info & info)
{int DataSizePerline = (info.biWidth * info.biBitCount+31) / 8;DataSizePerline -= DataSizePerline % 4;return DataSizePerline - info.biWidth * info.biBitCount / 8;
}void rotation(const BYTE* src){int newH = w;int newW = h;//图片旋转90度之后宽度、高度互换int newSize = newH * newW;FILE *p;p=fopen("dest.bmp","wb");Header newHead = srcHead;Info newInfo = srcInfo;Plus newPlus = srcPlus;//修改旋转后图片的尺寸、宽度和高度newHead.bfSize = (DWORD)(newHead.bfSize);newInfo.biHeight = (DWORD)newH;newInfo.biWidth = (DWORD)newW;int newdiff = getDiff(newInfo);newInfo.biSizeImage = (DWORD)((newInfo.biWidth * newInfo.biBitCount / 8 + newdiff) * newInfo.biHeight);//将种类、文件头、信息头写入新bmp文件fwrite(&bfType,1, sizeof(WORD),p);fwrite(&newHead,1, sizeof(Header),p);fwrite(&newInfo,1, sizeof(Info),p);if (newInfo.biBitCount == 32){fwrite(&newPlus, 1, sizeof(Plus), p);}BYTE* target = new BYTE[newSize * newInfo.biBitCount / 8];for (int i=0; i<newH; i++){for (int j=0; j<newW; j++){*(target + (i * newW + j)*newInfo.biBitCount / 8) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 1) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 1);*(target + (i * newW + j)*newInfo.biBitCount / 8 + 2) = *(src + (j * w + newH - i - 1)*newInfo.biBitCount / 8 + 2);if (newInfo.biBitCount == 32) {*(target + (i * newW + j) * newInfo.biBitCount / 8 + 3) =*(src + (j * w + newH - i - 1) * newInfo.biBitCount / 8 + 3);}}}for (int i=0; i<newH; i++){fwrite(target + i * newW * (newInfo.biBitCount / 8), newInfo.biBitCount / 8, newW, p);fseek(p, newdiff, SEEK_CUR);}fclose(p);delete []target;
}int main(){FILE* p;p = fopen("src.bmp", "rb");if (p != NULL){//先读取文件类型fread(&bfType, 1, sizeof(WORD), p);//读取bmp文件的文件头和信息头fread(&srcHead,1, sizeof(Header), p);fread(&srcInfo,1, sizeof(Info), p);if (srcInfo.biBitCount == 32){fread(&srcPlus, 1, sizeof(Plus), p);}h=srcInfo.biHeight;w=srcInfo.biWidth;size = w * h;BYTE *imgdata=new BYTE[size * srcInfo.biBitCount / 8];int diff = getDiff(srcInfo);//读取原图片像素信息for (int i=0;i<h;i++){fread(imgdata + i * w * srcInfo.biBitCount / 8, srcInfo.biBitCount / 8, w, p);fseek(p, diff, SEEK_CUR);}fclose(p);rotation(imgdata);delete []imgdata;}else{cout<<"无法打开文件"<<endl;}return 0;
}

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

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

相关文章

这几个关乎我们一生教养的原则,每个人都应该知道。

▲ 点击查看最近刷到这样两条微博&#xff0c;让人心头一暖。一条是杭州一个小男孩给医院捐款千元&#xff0c;还附上了一封感谢信。临走时还给医生敬了个少先队礼。另一条是扬州一名女孩把自己的小黄鸭储蓄罐整个捐到派出所&#xff0c;留下一张写着“武汉加油”的纸条&#x…

怎么提交 checkbox 表单_8. html form表单

“仅供学习&#xff0c;转载请注明出处”form表单表单用于搜集不同类型的用户输入&#xff0c;表单由不同类型的标签组成&#xff0c;相关标签及属性用法如下&#xff1a;1、标签 定义整体的表单区域action属性 定义表单数据提交地址method属性 定义表单提交的方式&#xff0c;…

越来越多的人不刷朋友圈竟然是因为.....

全世界只有3.14 % 的人关注了爆炸吧知识有些人&#xff0c;生活离不开朋友圈朋友圈是他们展示自我、观察世界的一扇窗户而有些人&#xff0c;从来也不点开朋友圈他们更愿意利用地铁上的零散化时间看点有意义、有知识的公众号推送完成对自我知识库的更新今天为大家推荐以下优质订…

Java基础---变量(三)

简单的说&#xff0c;我们可以把变量看作是个盒子&#xff0c;可以将钥匙、手机、饮料等物品存放在这个盒子中&#xff0c;也可以在需要的时候换成我们想存放的新物品。在 Java 中&#xff0c;我们通过三个元素描述变量&#xff1a;变量类型、变量名以及变量值。如果我们把变量…

腾讯,1000 亿!

聊聊腾讯的开源技术大家好&#xff0c;我是鱼皮&#xff0c;最近一则新闻在公司内外闹得沸沸扬扬&#xff0c;就是下面这个&#xff1a;为了履行企业发展使命&#xff0c;促进高质量发展的共同繁荣&#xff0c;腾讯在投资 500 亿元启动 “可持续社会价值创新” 战略后&#xff…

php mysql 执行sql文件_PHP执行SQL文件并将SQL文件导入到数据库_PHP

//读取文件内容$_sql file_get_contents(test.sql);$_arr explode(;, $_sql);$_mysqli new mysqli(DB_HOST,DB_USER,DB_PASS);if (mysqli_connect_errno()) {exit(连接数据库出错);}//执行sql语句foreach ($_arr as $_value) {$_mysqli->query($_value.;);}$_mysqli->…

What?你还搞不懂什么是物体检测?

全世界只有3.14 % 的人关注了爆炸吧知识计算机视觉在上一个世纪60年代脱胎于人工智能与认知神经科学&#xff0c;并旨在通过设计算法来让计算机自动理解图像的内容。于是为了“解决”这类机器视觉的问题&#xff0c;麻省理工在1966年正式将这个问题作为一个夏季项目&#xff0c…

IIS服务器上增加mp4格式MIME 类型映射设置具体步骤

2019独角兽企业重金招聘Python工程师标准>>> 也许你会在纳闷&#xff0c;为什么我上传了flv或MP4文件到服务器&#xff0c;可输入正确地址通过http协议来访问总是出现“无法找到该页”的404错误呢&#xff1f;这就 表明mp4格式文件是服务器无法识别的&#xff0c;其…

WPAD原理介绍暨故障排查:ISA2006系列之三

WPAD的部署原理暨故障排查<?XML:NAMESPACE PREFIX O />WPAD是Web Proxy Auto Discovery的缩写&#xff0c;意思是Web代理服务器自动发现。WPAD的设计目的是让浏览器能自动发现代理服务器&#xff0c;这样用户可以轻松访问互联网而且无需知道哪台计算机是代理服务器。在…

Web服务器HttpServer(嵌入式设备)

HttpServer是一个轻量级Web服务器&#xff0c;用于在嵌入式设备以及客户端环境中提供简单Web服务。HttpServer支持路由映射到匿名委托、WebApi接口、静态文件&#xff0c;以及具有多个接口的控制器类。从简单到复杂&#xff0c;控制权交给开发者。源码&#xff1a;https://gith…

mysql同时查两张表数据库表_如何同时查询两个数据库表?

展开全部 sql多表关联查询跟条件查询大同小异,主要是要知道表与表之前的关系很重e69da5e6ba9062616964757a686964616f31333431353238要; 举例说明:(某数据库中有3张表分别为:userinfo,dep,sex) userinfo(用户信息表)表中有三个字段分别为:user_di(用户编号),user_name(用…

200万年薪,招不到清华姚班毕业生,能上姚班的都是什么人?

全世界只有3.14 % 的人关注了爆炸吧知识清华姚班可能很多人都没有听说过&#xff0c;不是我们孤陋寡闻&#xff0c;而是姚班确实是不一般的存在。即便是在清华&#xff0c;姚班的学霸也是可以碾压其他学霸的。在清华有一句话&#xff0c;半国英才聚清华&#xff0c;清华半英在姚…

分布式拒绝服务攻击(DDoS)原理及防范

转自:http://www.cnblogs.com/rootq/archive/2009/11/06/1597215.html http://www.ibm.com/developerworks/cn/security/se-ddos/ 2002 年 6 月 01 日 分布式拒绝服务攻击&#xff08;DDoS&#xff09;是目前黑客经常采用而难以防范的攻击手段。本文从概念开始详细介绍了这种攻…

Blazor 应用如何使用 Azure Active Directory 认证登录

点击上方蓝字 / 关注“汪宇杰博客”原文&#xff1a;Azure Tips and Tricks翻译&#xff1a;汪宇杰使用 Azure Active Directory 保护您的应用程序您可以使用 Azure Active Directory (AAD) 让用户进行身份验证并授权使用您的应用。AAD 提供了一种智能身份即服务来保护您的应用…

python notebook右侧网页_《Python web开发》笔记 一:网页开发基础

网页基础知识网页的构成网页由html、css和Javascript构成&#xff0c;html是框架&#xff0c;CSS是样式和装饰&#xff0c;JS则是各项功能实现。我们把网页的组成类比成一栋房子&#xff0c;Html相当于房子的结构&#xff0c;CSS相当于房子的装修装饰&#xff0c;JavaScript相当…

推荐几个超有趣的公众号

全世界只有3.14 % 的人关注了爆炸吧知识想要和别人有聊不完的话题&#xff1f;当然是多读书多看新闻了解新鲜有趣的事物啦如果你没有时间去阅读那么关注以下公号将会让你收获更多信息~长按下方二维码选择“识别图中二维码”订阅疯狂历史ID&#xff1a;fkhistory▼ 简介&#xf…

省钱之道--图解域域树域林根域的含义

如图&#xff1a;contoso这家公司的IT环境中有很多类型的IT资源&#xff0c;而目前这些IT资源都处于一个分散管理的状态中&#xff0c;这样无形中增加了contoso这家公司的管理成本&#xff0c;而且管理制度没有办法落实到实际的生产环境中去。那么&#xff0c;如何解决这个问题…

动态表单实现客户端二次过滤及字段汇总统计

最终效果动态表单 1、表格分录首行出现客户端二次过滤行2、表格分录最后一行出现汇总行实现代码转载于:https://www.cnblogs.com/fyq891014/p/4188779.html

SqlBulkCopy只支持SQL Server? EF Core实现支持多数据库类型的Bulk Copy

前言Microsoft SQL Server包含一个名为bcp的命令行实用工具&#xff0c;可以将较大文件快速大容量复制到SQL Server数据库的表或视图中&#xff0c;这种方法被称为Bulk Copy(批量复制)。Bulk Copy相比与循环插入有很大的性能优势&#xff0c;网上有很多测试文章&#xff0c;这里…

让TA们告诉你,疫情当下如何更彪悍的成长

全世界只有3.14 % 的人关注了爆炸吧知识真正决定人与人之间的差距的&#xff0c;其实是我们对事物的见识与内心的格局&#xff0c;见识的深浅决定人生的深浅&#xff0c;格局的大小决定了人生之路是宽是窄。今天给大家推荐几个有深度、有想法的公众号&#xff0c;希望能够给你带…