Objective
Today this blog is a bit of a point, it is from an example, so as to reflect the various details of programming and some of the use of knowledge points. As before, I am a human being, hundreds of thousands of miles from becoming God, so there is no place to be avoided or even wrong, please read it as appropriate.
0x00
First, the title is: Read a bitmap file (xxx.bmp), and then read the first 30 bytes, extracting some information from the first 30 bytes.
Here are some things to know first: what is the first 30 bits of a bitmap?
BMP format uses a small-end way to store data, the structure of the file header in order as follows:
- The first two bytes: ' BM ' represents the Windows Bitmap, ' BA ' represents the OS/2 bitmap;
- A 4-byte integer: Represents the bitmap size;
- A 4-byte integer: Reserved bit, always 0;
- A 4-byte integer: The offset of the actual image;
- A 4-byte integer: The number of bytes in the header;
- A 4-byte integer: Image width;
- A 4-byte integer: Image height;
- A 2-byte integer: Always 1;
- A 2-byte integer: The number of colors.
First you need to know, read the first 30 bits of a bitmap, then what is the first 30 bits encoded? For example, the first 30 bits of a bitmap:
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‘
It's easy to see that their units are bytes
, in other words, we can't read them directly, so we have to convert them into something we can read.
Python's interesting place is here, and Python provides a struct
module to resolve bytes
and convert data types.
For example, what if I want to convert an integer to a 10241024
bytes
byte in units? (If you don't understand byte coding, look here) it's simple:
>>> struct.pack(‘>I‘, 10241024)b‘\x00\x9cD\x00‘
A little explanation:
>
Indicates that the byte order is Big-endian, which is the network order, which I
represents a 4-byte unsigned integer.
So what if I want to bytes
convert the bytes in units back to integral type? , but also very simple:
>>> struct.unpack(‘>I‘, b‘\x00\x9cD\x00‘)(10241024,)
The point to note is the unpack
first parameter of the function: ‘>I‘
, the interpretation is pack
the same as the function.
0x01
Here, the basic can be seen examples. Description
- My execution environment is: Python 3.6;
data.bmp
It is a bitmap picture that I draw with my own drawing in windows;
- I save this program as:
struct1.py
;
data.bmp
And the struct1.py
same in a Windows directory, full path: G:\newpython\data.bmp
andG:\newpython\struct1.py
Example:
#!/usr/bin/env python# -*- coding: utf-8 -*-import sysimport structfrom collections import namedtupledef 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 Noneif __name__ == "__main__": BMGinfo = namedtuple(‘BMGinfo‘, (‘ch1‘,‘ch2‘,‘size‘,‘reserved‘,‘offset‘,‘headerbits‘,‘width‘,‘height‘,‘num‘,‘colornum‘)) weitu = sys.argv[1] print(bmg_info(weitu))
Open cmd
, enter the directory G:\newpython
, execute the command: python struct1.py "G:\newpython\data.bmp"
you can see the surprise.
This blog is here, and finally it's important. In fact, in the practice of this Code, I met a few questions (error):
- Encountered an error (Attributeerror:module ' struct ' has no attribute ' unpack '), it turns out that my own py file does not have the same name as the system module, the solution, change the file name (I
struct.py
changed here struct1.py
) ;
- Flexible use of namedtuple. See here for more information
- Flexible use of variable parameter skills (*struct.unpack (' <cciiiiiihh ', data)), about variable parameters, see here
0x10
Thanks for reading.
Extracting bitmap information in Python (attributeerror:module ' struct ' has no attribute ' unstack ')