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…

莫名其妙的主机名 VM_32_234_centos

在腾讯服务器上部署的时候出现的莫名其妙的错误, 我在配置文件上都写 master, node1, 但是运行mapredure的时候的时候老是出现 Job job_1409546978133_0001 failed with state FAILED due to: Application application_1409546978133_0001 failed 2 times due to Error launc…

如何通过提问成为更好的开发人员

如何通过提问成为更好的开发人员这是新的一年的开始&#xff0c;所以我想以一篇我已经计划写了一段时间但从未真正开始创作的帖子开始。我最近开始了一份新工作&#xff0c;加入Elastic[1]&#xff0c;负责开发他们的 .NET 语言客户端。因此&#xff0c;最终将这个主题编写并发…

生活经典名句

&#xff11;&#xff0c;记住该记住的&#xff0c;忘记该忘记的。改变能改变的&#xff0c;接受不能改变的 &#xff12;&#xff0c;能冲刷一切的除了眼泪&#xff0c;就是时间&#xff0c;以时间来推移感情&#xff0c;时间越长&#xff0c;冲突越淡&#xff0c;仿佛不断稀释…

转载 一篇UI规范文件

这是一个UI模板规范&#xff0c;在做B/S版应用程序时比较适用&#xff0c;其实这样的东西算不上什么正规的规范&#xff0c;只是为了适应我们现在面对的开发环境和组织流程做的一些权宜的努力&#xff0c;和解决了一些与程序沟通和接口的问题&#xff0c;尽量避免误会和摩擦。 …

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

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

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

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

Java基础---变量(三)

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

批处理文件总结(三)

三.如何使用组合命令(Compound Command)   1.amp;   Usage&#xff1a;第一条命令 amp; 第二条命令 [amp; 第三条命令...]   用这种方法可以同时执行多条命令&#xff0c;而不管命令是否执行成功   Sample&#xff1a;   C:\>dir z: amp; dir c:\Ex4rch   The s…

腾讯,1000 亿!

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

线打断问题(转)

在处理数据时&#xff0c;我们经常会遇到线打断的问题&#xff0c;比如需要指定在线上某处打断线&#xff0c;或者新建网络数据集时需要在线的交点处打段线等等。现将桌面版中我所遇到的线打断的工具总结如下&#xff1a; 一、手工打断线 Editor工具条中的splittool。 使用该工…

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…

RFileWriteStream 写入汉字

由于用到 RFileWriteStream 写入汉字到文件中&#xff0c;之前没有处理过&#xff0c;等写入文件后才发现是乱码。 问了问群里的朋友也没有解决&#xff0c;后来就上网搜&#xff0c;终于找到一个解决方法&#xff0c;就是用 CCnvCharacterSetConverter 类 这个类是用来转换Uni…

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

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

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

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

[分享]我国食品行业ERP现状及分析解决方案

一。食品行业介绍&#xff1a;  我国食品行业是一个竞争非常激烈的行业&#xff0c;平均利润率很低&#xff0c;但市场空 间巨大&#xff0c;产销均有大幅提高的空间。在今后发展中&#xff0c;食品的消费与需求将完成由追求数量向追求质量、营养、安全、多样和方便型的转…