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

浏览了各种求助帖(还找到了数年前的信科大一学长),终于发现了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是啥...我也不知道 。所以只好开始了漫长的搜索之路,最终找到了他的定义:

CIEXYZTRIPLE的定义

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

typedef int FXPT2DOT30;

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

原图
顺时针旋转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;
}

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

  1. 32位java 最大内存_【答疑系列】为什么32位系统只支持最大4G内存?

    这个问题一直都有同学问到,算是提问次数最多的问题之一了. 32位是什么 现在主流的操作系统都是64位的,早期存在32位操作系统,相信大家也都有所听闻,其实,在更早之前,还有16位.8位的,这里就不展开 ...

  2. 为什么在64位系统中指针的大小是8,而32位系统中却是4?

    为什么在64位系统中指针的大小是8,而32位的却是4? 64位系统,这个位数指的是CPU 里面的通用寄存器的数据宽度为64位,也就是说一个地址占二进制位数是64,所以: sizeof(double * ...

  3. 七日杀16.1 服务器修改器,七日杀三十二项32位修改器_七日杀 a16.1b1多功能三十二项修改器-66街机网...

    资源说明: 七日杀 a16.1b1多功能三十二项修改器32位[潇潇蓝龙],由"潇潇蓝龙"制作,一款全功能修改器,基本上是全能力开关,支持任意调整生物伤害.方块距离.生物距离.体力消 ...

  4. 网站服务器 64位,如何将win7系统从32位升级到64位_网站服务器运行维护,win7,32位,64位...

    win10如何重置此电脑_网站服务器运行维护 win10重置此电脑的方法是:1.点击[开始]按钮,进入设置:2.进入[更新和安全]选项,点击[恢复]:3.找到[重置此电脑],点击[开始]:4.选择[保 ...

  5. python安装方法32位_【Python】pycharm安装32位win7出现的问题解决办法。

    1.安装 PyCharm 是一款功能强大的 Python 编辑器,具有跨平台性,鉴于目前最新版 PyCharm 使用教程较少,为了节约时间,来介绍一下 PyCharm 在 Windows下是如何安装的 ...

  6. mysql只有32位的吗_#金鸡奖##星辰大海演员计划#32位青年演员曝光,并非只有周冬雨斩获过金马奖...

    昨日,电影频道公布了#星辰大海演员计划#,即由32位资深影人推荐了32位青年演员,并一同见证中国电影的前进. 这32位青年演员分别是:周冬雨.王俊凯.易烊千玺.刘昊然.陈飞宇.许魏洲.宋祖儿.陈学冬. ...

  7. 在64位的Linux系统使用gcc的-m32选项编译32位的程序得到了多余的代码(多余指令call和add)、有多余的.text.__x86.get_pc_thunk.ax

    问题解决于该网站 首先讲一下问题是怎么发生的: 最近在学计算机系统,用到的教材是32位的Linux系统,而在我的64位的Ubuntu上,我想以gcc编译出32位的程序并查看其汇编代码,于是百度查了下, ...

  8. 计算机32位操作系统最大识别到内存,win7 32位系统可以支持多大的内存_win7 的32位系统最大支持多少g的内存...

    大家都知道win7系统有32位和64位之分,而两者的安装配置是不一样的,一般4G内存的我们安装64位的系统,但是很多用户不知道win7 32位系统可以支持多大的内存,这就给大家分享一下win7 的32 ...

  9. 32位 shell.efi x86_Ubuntu 20.04 LTS或不再支持32位x86 (i386)

    Ubuntu 17.10放弃了i386/32位x86安装程序映像,而i386架构仍然是软件包存档的一部分.其他Ubuntu衍生产品在过去一年中也放弃了32位安装程序映像,而Lubuntu/Xubunt ...

最新文章

  1. 小样本学习 few-shot learning
  2. 使用 netfilter 处理IPv6报文
  3. linux进程号转换成16进制,Shell脚本中不同进制数据转换的例子(二进制、八进制、十六进制、base64)...
  4. windows 下启动zookeeper的zkServer.cmd服务闪退
  5. 配置SQL Server的身份验证方式
  6. ImportError: libSM.so.6: cannot open shared object file: No such file or dir
  7. 异常详细信息: System.Data.SqlClient.SqlException:用户 ‘IIS APPPOOL\DefaultAppPool‘ 登录失败解决办法
  8. 带女朋友回家家里人一共给了她3500我拿走了真的有错吗?
  9. linux slf4j找不到,slf4j+log4j2在tomcat8 下无日志输出
  10. shell脚本中的逻辑判断、文件目录属性判断、if特殊用法、case判断
  11. 设计模式--模板方法(Template Method)
  12. CLOCs: Camera-LiDAR Object Candidates Fusion for 3D Object Detection(论文阅读笔记)
  13. 微信朋友圈卖葡萄经验分享
  14. app里面的h5的定位方式(夜神模拟器篇)
  15. Android Native层
  16. Unity Content Size Fitter 刷新不及时
  17. 海思SD3403开发板学习(三)
  18. 平台sdk和项目sdk的理解
  19. python国内下载地址_python下载链接
  20. Kotlin 基础语法(《第一行代码(第三版)》第二章读书笔记)

热门文章

  1. 江湖召集:.NET开发者们看过来,这场长沙的开发者技术大会正是为你精心准备的大餐...
  2. 如何撰写较受欢迎的技术文章
  3. asp.net core集成CAP(分布式事务总线)
  4. 微软发布Azure Pipelines,开源项目可无限制使用CI/CD
  5. netcore编程之后面对不习惯的xshell黑屏部署,是时候使用jenkins自动化发布工具了...
  6. g4e基础篇#5 创建分支和保存代码
  7. SQL Server 2017 RC1 现已实现 Linux 功能扩展
  8. 异步广度优先搜索算法
  9. 使用CoreProfiler/NanoProfiler实现跨平台amp;应用的整合性能调试
  10. .Net Core 系列:1、环境搭建