Python读取并解析 bmp 文件

本文详细介绍了如何使用Python读取BMP图片文件,包括文件头、位图信息头的解析,以及图像数据的读取过程。通过具体代码示例,展示了如何分离RGB通道,为后续图像处理奠定基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

由于要开始学习图像方面的知识,读写图片是难免的。对图片的结构有一定的了解对理解图片存储还是很有帮助的。由于实验的代码是用 python 写的,因此读取文件就直接使用 python 了,虽然用 C 来读写文件更有效率,但我个人感觉 python 也没有很慢。下面来看一下bmp 文件结构和读取 bmp 文件的过程。

bmp 文件结构

  • bmp文件头(bmp file header):提供文件的格式、大小等信息

  • 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息

  • 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表

  • 位图数据(bitmap data):就是图像数据

用表格形式可以表示为:

在这里插入图片描述

首先来看文件头的信息(14字节):

在这里插入图片描述

然后是位图信息图(40字节):

在这里插入图片描述

一般情况下,到这里我们就可以得到这个图片的基本信息了。由于调色板是不确定的,而且现在的bmp图片一般都没有调色板信息(因为24位),所以忽略第三个。

所以,思路还是很简单的。先读取 54 字节的头文件,利用读取的图片宽和高信息,对后面的数据进行读取。

注意:由于是以二进制形式进行读取的,因此,需要注意存储方式。bmp 文件的存储方式是小端方式,读取的时候也要使用小端法进行解析

Python 代码

# -*- coding: UTF-8 -*-
from struct import unpack

# 读取并存储 bmp 文件
class ReadBMPFile :
    def __init__(self, filePath) :
        file = open(filePath, "rb")
        # 读取 bmp 文件的文件头    14 字节
        self.bfType = unpack("<h", file.read(2))[0]       # 0x4d42 对应BM 表示这是Windows支持的位图格式
        self.bfSize = unpack("<i", file.read(4))[0]       # 位图文件大小
        self.bfReserved1 = unpack("<h", file.read(2))[0]  # 保留字段 必须设为 0 
        self.bfReserved2 = unpack("<h", file.read(2))[0]  # 保留字段 必须设为 0 
        self.bfOffBits = unpack("<i", file.read(4))[0]    # 偏移量 从文件头到位图数据需偏移多少字节(位图信息头、调色板长度等不是固定的,这时就需要这个参数了)
        # 读取 bmp 文件的位图信息头 40 字节
        self.biSize = unpack("<i", file.read(4))[0]       # 所需要的字节数
        self.biWidth = unpack("<i", file.read(4))[0]      # 图像的宽度 单位 像素
        self.biHeight = unpack("<i", file.read(4))[0]     # 图像的高度 单位 像素
        self.biPlanes = unpack("<h", file.read(2))[0]     # 说明颜色平面数 总设为 1
        self.biBitCount = unpack("<h", file.read(2))[0]   # 说明比特数
        
        self.biCompression = unpack("<i", file.read(4))[0]  # 图像压缩的数据类型
        self.biSizeImage = unpack("<i", file.read(4))[0]    # 图像大小
        self.biXPelsPerMeter = unpack("<i", file.read(4))[0]# 水平分辨率
        self.biYPelsPerMeter = unpack("<i", file.read(4))[0]# 垂直分辨率
        self.biClrUsed = unpack("<i", file.read(4))[0]      # 实际使用的彩色表中的颜色索引数
        self.biClrImportant = unpack("<i", file.read(4))[0] # 对图像显示有重要影响的颜色索引的数目
        self.bmp_data = []

        if self.biBitCount != 24 :
            print("输入的图片比特值为 :" + str(self.biBitCount) + "\t 与程序不匹配")

        for height in range(self.biHeight) :
            bmp_data_row = []
            # 四字节填充位检测
            count = 0
            for width in range(self.biWidth) :
                bmp_data_row.append([unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0], unpack("<B", file.read(1))[0]])
                count = count + 3
            # bmp 四字节对齐原则
            while count % 4 != 0 :
                file.read(1)
                count = count + 1
            self.bmp_data.append(bmp_data_row)
        self.bmp_data.reverse()
        file.close()
        # R, G, B 三个通道
        self.R = []
        self.G = []
        self.B = []

        for row in range(self.biHeight) :
            R_row = []
            G_row = []
            B_row = []
            for col in range(self.biWidth) :
                B_row.append(self.bmp_data[row][col][0])
                G_row.append(self.bmp_data[row][col][1])
                R_row.append(self.bmp_data[row][col][2])
            self.B.append(B_row)
            self.G.append(G_row)
            self.R.append(R_row)

这里,读取完文件后,我又将 R、G、B 三个通道的数值分出来了。主要是为了方便后续的处理,毕竟读取文件的目的是为了后面对图像的处理。

这是一个类,外部代码可以这样调用:

import numpy as np
import sys
from ReadBMPFile import ReadBMPFile
import cv2
# 命令行传入的文件路径
filePath = sys.argv[1]
# 读取 BMP 文件
bmpFile = ReadBMPFile(filePath)
# R, G, B 三个通道 [0, 255]
R = bmpFile.R
G = bmpFile.G
B = bmpFile.B
# 显示图像
b = np.array(B, dtype = np.uint8)
g = np.array(G, dtype = np.uint8)
r = np.array(R, dtype = np.uint8)
merged = cv2.merge([b, g, r]) #合并R、G、B分量 默认顺序为 B、G、R
cv2.imshow("Merged",merged)

参考文献

  1. BMP文件格式详解(BMP fileformat)
  2. 简单bmp图片处理工具——python实现
在数字图像处理领域,正确解析BMP图像文件头和信息头是理解整个图像数据结构的基础。为了帮助你掌握这项技能,推荐参考《BMP图像16位格式解析Python与MATLAB实现》。这份资源将教你如何使用Python和MATLAB两种流行语言来分析BMP图像的关键信息。 参考资源链接:[ BMP图像16位格式解析Python与MATLAB实现 ](https://wenku.youkuaiyun.com/doc/3vgp23uztf?spm=1055.2569.3001.10343) 首先,让我们从BMP图像的文件头开始。文件头共有14字节,其中前两个字节是“424D”,即ASCII码的“BM”,用于标识文件类型。接着的四个字节表示文件的总大小,这对于验证整个文件的完整性很重要。bfReserved1和bfReserved2通常为0,而bfOffBits表示从文件头到图像数据的偏移量,这是定位图像数据的关键。 接下来是信息头,它包含图像的宽度、高度、颜色深度、压缩方式等信息。在16位BMP图像中,颜色深度为16或24位。如果颜色深度是24位,那么每个像素由RGB三个分量组成,每个8位。压缩方式为0表示图像未压缩,如果存在其他值,则代表特定的压缩算法。 在Python中,你可以使用struct模块来解析这些信息,而在MATLAB中,则可以利用imread函数和相应的位操作函数来获取和分析这些信息。以下是一个简化的示例,展示如何在Python解析BMP文件头和信息头的关键数据: ```python import struct def read_bmp_header(file_path): with open(file_path, 'rb') as bmp_*** * 读取文件头14字节 file_header = bmp_file.read(14) # 解析文件头信息 (file_type, file_size, reserved1, reserved2, off_bits) = struct.unpack('<2sIHHI', file_header) # 读取信息头40字节 info_header = bmp_file.read(40) # 解析信息头信息 (info_header_size, width, height, planes, bit_count, compression, image_size, x_pixels_per_meter, y_pixels_per_meter, colors_used, important_colors) = struct.unpack('<IiiHHIIIIII', info_header) return { 'file_type': file_type, 'file_size': file_size, 'off_bits': off_bits, 'width': width, 'height': height, 'bit_count': bit_count, 'compression': compression } # 使用函数解析BMP文件 bmp_info = read_bmp_header('path_to_your_bmp_file.bmp') print(bmp_info) ``` 通过这个示例,你已经能够看到如何使用Python读取解析BMP图像的文件头和信息头。这为处理图像数据和进一步的图像处理操作打下了坚实的基础。 阅读了上述内容后,如果希望更深入地理解和实践BMP图像的解析,包括如何处理图像数据和进行图像处理操作,建议继续研究这份教程:《BMP图像16位格式解析Python与MATLAB实现》。它不仅提供了基础概念的讲解,还包含了详细的操作指导和代码示例,能够帮助你在图像处理领域进一步发展。 参考资源链接:[ BMP图像16位格式解析Python与MATLAB实现 ](https://wenku.youkuaiyun.com/doc/3vgp23uztf?spm=1055.2569.3001.10343)
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值