前言

今天这篇博文有点意思,它是从一个例子出发,从而体现出在编程中的种种细节和一些知识点的运用。和从前一样,我是人,离成神还有几十万里,所以无可避免的出现不严谨的地方甚至错误,请酌情阅读。


0x00

首先,题目是:读取一个位图文件(xxx.bmp),然后读取前30个字节,从这前三十个字节中提取一些信息。

这里有一些知识要先知道:一个位图的前30位有什么?

BMP格式采用小端方式存储数据,文件头的结构按顺序如下:

  • 前两个字节:'BM'表示Windows位图,'BA'表示OS/2位图;
  • 一个4字节整数:表示位图大小;
  • 一个4字节整数:保留位,始终为0;
  • 一个4字节整数:实际图像的偏移量;
  • 一个4字节整数:Header的字节数;
  • 一个4字节整数:图像宽度;
  • 一个4字节整数:图像高度;
  • 一个2字节整数:始终为1;
  • 一个2字节整数:颜色数。

你先要知道,读取一个位图的前30位,那么这前30位是什么编码呢?例如,某个位图的前30位:

  1. b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'

很容易看出,它们的单位是bytes,也就是说,我们无法直接看懂它们,因此,我们得把它转换成我们能看懂的东西。

**python有趣的地方就在这里了,Python提供了一个struct模块来解决bytes和数据类型的转换。 **

例如,我想把一个整数10241024转换为以bytes为单位的字节怎么办?(如果你不懂字节编码,看这里)很简单:

  1. >>> struct.pack('>I', 10241024)
  2. b'\x00\x9cD\x00'

稍微解释一下:

>表示字节顺序是big-endian,也就是网络序,I表示4字节无符号整数。


那么我想把以bytes为单位的字节转换回整型怎么办?,也很简单:

  1. >>> struct.unpack('>I', b'\x00\x9cD\x00')
  2. (10241024,)

要注意的地方就是unpack函数的第一个参数:'>I',解释和pack函数的一样。


0x01

到了这里,基本可以看例子了。说明:

  1. 我的执行环境是:python 3.6;
  2. data.bmp是我用Windows自带画图随手画的一个位图图片;
  3. 我把这个程序保存为:struct1.py;
  4. data.bmpstruct1.py同在一个Windows目录下,完整路径:G:\newpython\data.bmpG:\newpython\struct1.py

例子:

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. import struct
  5. from collections import namedtuple
  6. def bmg_info(weitu):
  7. with open(weitu, 'rb') as f:
  8. data = f.read(30)
  9. info = BMGinfo(*struct.unpack('<ccIIIIIIHH', data))
  10. if info.ch1 == b'B' and (info.ch2 == b'M' or info.ch2 == b'A'):
  11. return {
  12. 'width': info.width,
  13. 'height': info.height,
  14. 'color': info.colornum
  15. }
  16. return None
  17. if __name__ == "__main__":
  18. BMGinfo = namedtuple('BMGinfo', ('ch1','ch2','size','reserved','offset','headerbits','width','height','num','colornum'))
  19. weitu = sys.argv[1]
  20. print(bmg_info(weitu))

打开cmd,进入目录G:\newpython,执行命令:python struct1.py "G:\newpython\data.bmp"即可看见惊喜。

这篇博客说到这里,终于到了重要的地方。其实在实践这段代码时,我遇见了几个问题(错误):

  1. 遇到错误(AttributeError: module 'struct' has no attribute 'unpack'),原来是我自己的py文件不要和系统的模块名重名,解决办法,把文件名改掉(我这里把struct.py改为struct1.py);
  2. 灵活运用namedtuple。了解更多请看这里
  3. 灵活运用可变参数技能(*struct.unpack('<ccIIIIIIHH', data)),关于可变参数,看这里

0x10

感谢阅读。

python中提取位图信息(AttributeError: module 'struct' has no attribute 'unstack')的更多相关文章

  1. Windows解决多版本python执行pip3时出错AttributeError: module 'enum' has no attribute 'IntFlag'?

    摘要: 本机装有python2.7和python3.6,执行pip和pip2时没有问题,执行pip3时提示: C:\Users\>pip3 Traceback (most recent call ...

  2. 【Python 脚本报错】AttributeError: 'module 'yyy' has no attribute 'xxx'的解决方法

    先参考这篇记录大概理解了原因, 再深入了解下python的import机制, 发现自己的模块之间存在互相import. 比如,A.py中import B,而B.py中也import A了, 现在执行模 ...

  3. python中引入包的时候报错AttributeError: module 'sys' has no attribute 'setdefaultencoding'解决方法?

    python中引入包的时候报错:import unittestimport smtplibimport timeimport osimport sysimp.reload(sys)sys.setdef ...

  4. Python AttributeError: 'Module' object has no attribute 'STARTF_USESHOWINDOW'

    夫学须志也,才须学也,非学无以广才,非志无以成学.--诸葛亮 生活有度,自得慈铭 --杜锦阳 今天新来的同事安装环境遇到个莫名其妙的问题: AttributeError: 'Module' objec ...

  5. Python脚本报错AttributeError: ‘module’ object has no attribute’xxx’解决方法

    最近在编写Python脚本过程中遇到一个问题比较奇怪:Python脚本完全正常没问题,但执行总报错"AttributeError: 'module' object has no attrib ...

  6. python 脚本运行时报错: AttributeError: 'module' object has no attribute ***

    最近在编写Python脚本过程中遇到一个问题比较奇怪:Python脚本完全正常没问题,但执行总报错"AttributeError: 'module' object has no attrib ...

  7. python文件名不要跟模块名相同,报错AttributeError: 'module' object has no attribute 'Differ'

    python中的文件都会生成pyc文件,包括模块也是这样,所以调用模块的时候,实际上会调用模块.pyc文件:在这个前提下,如果将文件名命名成跟模块名一样,在同一目录下就会生成一个跟模块名一样的pyc文 ...

  8. AttributeError: module 'matplotlib' has no attribute 'verbose' (pycharm中使用matplotlib 2.2.0的坑)

    AttributeError: module 'matplotlib' has no attribute 'verbose' 环境信息 本地系统:win10 本地开发环境:python(3.6.3), ...

  9. 一文教你读懂Python中的异常信息

    正文共:11813 字 2 图 预计阅读时间: 30 分钟 原文:https://realpython.com/python-traceback/ 译者:陈祥安 原文有所改动. 在写 Python 代 ...

随机推荐

  1. Jquery span标签的取值赋值

    //赋值 $("#spanid").html(value) //取值 $("#spanid").text()

  2. iOS开发常用Mac终端命令

    常用命令: 1.grep -lr "prefs:root=" * cd 当某一文件夹下,在当前文件目录下搜索对应的内容(橘色字符串替换为你想要搜索的内容).可以用来搜索工程中在第三 ...

  3. 大端(bigend)与小端(littleend)

                                      大端:是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中: 小端:是指数据的高位保存在内存的高地址中,而数据的高 ...

  4. 计算机基础,Python - Map和Reduce

    例子1. python中实现hashable def __hash__(self): hashes = map(hash, self.components) return functools.redu ...

  5. 彻底解决Spring mvc中时间的转换和序列化等问题

    痛点 在使用Spring mvc 进行开发时我们经常遇到前端传来的某种格式的时间字符串无法用java8的新特性java.time包下的具体类型参数来直接接收. 我们使用含有java.time封装类型的 ...

  6. window下jenkins+allure+邮箱发送

    一.安装allure 1)下载 allure.zip 下载地址:allure-github: https://github.com/allure-framework/allure2 2)解压到本地目录 ...

  7. 19市赛 树状数组 第k个小的糖果

    int find_kth(int k) { , cnt = , i; ; i >= ; i--)/ { ans += ( << i); if (ans >= maxn|| cn ...

  8. 利用 Jenkins 持续集成 iOS 项目,搭建自动化打包环境

    ---恢复内容开始--- jenkins是一个广泛用于持续构建的可视化web工具,持续构建即各种项目的”自动化”编译.打包.分发部署.jenkins可以很好的支持各种语言(比如:Java, c#, P ...

  9. vue项目中vant tab改变标签颜色

    找了几种方法,只有下面这个方法是生效的: <van-tabs v-model="active" sticky title-active-color="#144a9e ...

  10. [原]Java工程打包注意事项

    注意事项(持续增加...): 如果Java工程中用到了注解,在用eclipse打jar包时需要注意一下,勾上“Add directory entries”,否则注解的类会注册不上