zoukankan      html  css  js  c++  java
  • python中提取位图信息(AttributeError: module 'struct' has no attribute 'unstack')

    前言

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


    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位:

     b'x42x4dx38x8cx0ax00x00x00x00x00x36x00x00x00x28x00x00x00x80x02x00x00x68x01x00x00x01x00x18x00'
    

    很容易看出,它们的单位是bytes,也就是说,我们无法直接看懂它们,因此,我们得把它转换成我们能看懂的东西。
    **python有趣的地方就在这里了,Python提供了一个struct模块来解决bytes和数据类型的转换。 **
    例如,我想把一个整数10241024转换为以bytes为单位的字节怎么办?(如果你不懂字节编码,看这里)很简单:

    >>> struct.pack('>I', 10241024)
    b'x00x9cDx00'
    

    稍微解释一下:
    >表示字节顺序是big-endian,也就是网络序,I表示4字节无符号整数。


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

    >>> struct.unpack('>I', b'x00x9cDx00')
    (10241024,)
    

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


    0x01

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

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

    例子:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    import sys
    import struct
    from collections import namedtuple
    
    def bmg_info(weitu):
    	with open(weitu, 'rb') as f:
    		data = f.read(30)
    	info = BMGinfo(*struct.unpack('<ccIIIIIIHH', data))
    	if info.ch1 == b'B' and (info.ch2 == b'M' or info.ch2 == b'A'):
    		return {
    		'width': info.width,
    		'height': info.height,
    		'color': info.colornum
    		}
    	return None
    
    if __name__ == "__main__":
    	BMGinfo = namedtuple('BMGinfo', ('ch1','ch2','size','reserved','offset','headerbits','width','height','num','colornum'))
    	weitu = sys.argv[1]
    	print(bmg_info(weitu))
    

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

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

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

    0x10

    感谢阅读。

  • 相关阅读:
    《Docker容器与容器云》读书笔记
    【Kubernetes】Kubernetes的Service外部访问方式:NodePort和LoadBalancer
    《微服务设计》读书笔记
    什么是Istio
    【Kubernetes】kube-dns 持续重启
    什么是Etcd?
    什么是Service Mesh?
    放假个人总结四
    放假个人总结三
    放假个人总结二
  • 原文地址:https://www.cnblogs.com/busui/p/9351772.html
Copyright © 2011-2022 走看看