Linux使用vi或vim查看图片文件二进制数据,通过读取BMP头文件数据获取图片宽高

Linux使用vi或vim查看图片文件二进制数据,通过读取BMP头文件数据获取图片宽高

使用vi或vim查看图片二进制数据

首先放一张没有问题的图片到虚拟机中,图片格式我只测试了jpg和bmp,都可以,然后输入指令:

vi -b image.bmp
或
vim -b image.bmp

然后就出现如下界面,也可能你的系统没有装vi或vim而报错
在这里插入图片描述
然后输入:%!xxd,回车,就能转换成十六进制了
在这里插入图片描述
我也是找了很久方法才见到了自己“梦寐以求”的十六进制数据

通过读取BMP头文件数据获取图片宽高

我们知道BMP图片的数据是十分完美的,他大致分为两个部分(这只是大致,还有更加详细的划分),一部分是54字节的头文件,里面存了一些这个图片的信息,还有一部分就是存的图片颜色数据,我们需要的宽高数据就在头文件中
在这里插入图片描述
看了别人的博客,了解到如果以2个字节为一个单位,那么宽就是第10-11,高是第12-13,分别是图中的:
宽(2003 0000):
在这里插入图片描述
高(e001 0000):
在这里插入图片描述
但是将这个数值转化为十进制后得到的并不是实际的图片宽高数据(我这个张是800 * 480),所以并没有这么简单
实际上我们要把这个数据转换一下,比如2003 0000转换成0000 0320,这样再转换成十进制就是800了,我记得有学过这种每次读两位然后置于低位,再这样那样的,忘了叫什么了
同样的把e001 0000转换成0000 01e0就能算出480
知道原理后就能通过代码来实现想要的功能了:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, const char *argv[]) {
	
	int bmp_fd = open(argv[1], O_RDWR);
	if (bmp_fd == -1) {
		printf("打开失败\n");
		return -1;
	}

	char header[54]; //储存头文件数据
	read(bmp_fd, header, 54); //读取头文件数据
	
	int w, h; //定义宽、高变量
	
	//因为char占1字节,宽的4个字节数据应该在header数组的18, 19, 20, 21 
	printf("%x %x %x %x\n", header[18], header[19], header[20], header[21]);
	w = header[18] & 0xff;
	w |= (header[19]<<8);
	w |= (header[20]<<16);
	w |= (header[21]<<24);
	printf("宽度%d\n", w);

	//同理 22 23 24 25 
	printf("%x %x %x %x\n", header[22], header[23], header[24], header[25]);
	h = 0 | (header[22] & 0xff) | (header[23]<<8) | (header[24]<<16) | (header[25]<<24);
	printf("高度%d\n", h);

	close(bmp_fd);	

	return 0;
}

效果:
在这里插入图片描述
在这里插入图片描述
但是有时候会出现正常数据里多了ffffff在前面,我也不是很懂,所以还要使用&运算来清除掉前面这些数据保留后八位,这就是为什么我代码中要header[18] & 0xffheader[22] & 0xff,获得了宽高后就可以通过传参的形式来选择LCD显示的图片了,这才是我的初衷。。。可能还有别的方法,但我第一反应就是这个

补充

之前忘了高宽出现这种存储格式的原理,现在又查了一下原来时之前学单片机时候学到的大端/小端存储模式

大端模式:数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;

小端模式:数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

显然BMP头文件中的宽高数据存储时使用的是小端模式,所以2003 0000的真实数据为0000 0320
在这里插入图片描述
本人也只是半桶水,无法讲清楚,大家可以去搜一下相关的知识文章
http://www.elecfans.com/consume/803544.html

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1594231563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值