如何将 Base64 转换为 BMP
- 粘贴 Base64 或完整的
data:image/bmp;base64,...URI,或者打开存有该字符串的.txt文件。位图的字符串动辄几 MB,这很正常,在这里没有问题。 - 状态行中的 检测结果 应为 BMP。预览会显示图片及其像素尺寸;大小 给出解码后文件的字节数。
- 点击 下载文件 保存
.bmp。
浏览器可以在 <img> 中解码 BMP,包括 1 位单色、8 位调色板、24 位以及大多数 32 位文件。
根据宽高计算 BMP 文件大小
BMP 由 14 字节的文件头、信息头(常见版本为 40 字节)、可选的调色板和像素行组成。每一行都会补齐到 4 字节的倍数。对于没有调色板的 24 位图像:
file size = 54 + height × (width × 3, rounded up to a multiple of 4)
| 图像 | 行大小 | BMP 文件 | Base64 长度 |
|---|---|---|---|
| 33×10,24 位 | 99 → 100 字节 | 1,054 字节 | 1,408 个字符 |
| 100×100,24 位 | 300 字节 | 30,054 字节 | 40,072 个字符 |
| 800×600,24 位 | 2,400 字节 | 1,440,054 字节 | 1,920,072 个字符 |
| 1920×1080,24 位 | 5,760 字节 | 6,220,854 字节 | 8,294,472 个字符 |
| 1920×1080,1 位 | 240 字节 | 259,262 字节 | 345,684 个字符 |
1 位图像那一行额外加上了 8 字节的双色调色板。由于这些数字是固定的,位图很容易校验:文件头的第 2 到 5 个字节保存了总大小。在 100×100 示例的 hex 转储中,这几个字节是 66 75 00 00,按小端序读作 0x7566 = 30,054。如果 大小 显示的值比这小,说明 Base64 被截断了。BMP 的像素行默认自下而上存储,所以被截断的位图丢失的是图片的上部。
BMP 的 Base64 长什么样
每个 BMP 都以字母 BM 开头,所以 Base64 以 Qk 开头。第三个字符取决于文件大小,是 0、1、2 或 3;Qk02 和 Qk1m 很常见。检测器还会检查第 14 个字节处的信息头大小,所以恰好以 BM 开头的随机数据不会被误认为位图。
无文件头的位图(DIB)
有些来源给你的位图没有 BM 文件头。这就是 DIB,它是 Windows 剪贴板(CF_DIB)、ICO 文件内部图像以及某些设备 SDK 使用的格式。它的 Base64 以 KAAAA 开头,这是 40 字节信息头大小 28 00 00 00 的编码。
工具无法预览它,因为没有文件头,这些字节就不是有效的图像文件,工具会将其报告为二进制数据。解决方法是在前面补上缺失的 14 个字节:
import base64, struct
def dib_to_bmp(dib: bytes) -> bytes:
header_size, = struct.unpack_from("<I", dib, 0)
bpp, = struct.unpack_from("<H", dib, 14)
compression, colors = struct.unpack_from("<I", dib, 16)[0], struct.unpack_from("<I", dib, 32)[0]
if bpp <= 8 and colors == 0:
colors = 1 << bpp
masks = 12 if header_size == 40 and compression == 3 else 0
offset = 14 + header_size + masks + colors * 4
return b"BM" + struct.pack("<IHHI", 14 + len(dib), 0, 0, offset) + dib
b64 = open("dib.txt").read()
with open("image.bmp", "wb") as f:
f.write(dib_to_bmp(base64.b64decode(b64)))
文件头需要文件总大小和像素数据的偏移量;像素数据位于信息头、16 位和 32 位位域图像的颜色掩码以及调色板之后。如果需要文本形式,可以用 BMP 转 Base64 再次编码结果,或者在这里检查。来自 ICO 文件的 DIB 是特例:它们的高度被加倍,用来容纳透明度掩码。Python 中的 Base64 有更多关于解码二进制数据的内容。
常见问题
- “这看起来是 PNG,而不是 BMP”。 发送方已经转换过图片,或者系统只是把它称作位图。用 下载为 .png 保存为 PNG 即可;PNG 更小,所有程序都能读取。
- 在其他程序中颜色看起来颠倒了,或者图像上下倒置。 BMP 以蓝、绿、红的顺序存储像素,并且通常自下而上。文件头中的高度为负数时表示像素行自上而下排列。浏览器能处理所有这些情况,一些简单的自制读取器则不一定。
- 设备拒绝解码后的文件。 先把它的 SHA-256 与设备收到的文件对比,再在 hex 转储中检查位深度和文件头版本。较旧的读取器要求 40 字节的信息头(偏移 14 处为
28 00 00 00),并且不能有 alpha 通道。
常见问题
为什么我的位图 Base64 字符串这么长?
BMP 存储的是未经压缩的原始像素。一张 1920×1080 的 24 位位图有 6,220,854 字节,也就是 8,294,472 个 Base64 字符,跟图片内容无关。
我的 Base64 以 KAAAA 开头,而不是 Qk,这是什么?
这是去掉了 14 字节文件头的位图,称为 DIB。它来自 Windows 剪贴板、某些设备 SDK 以及 ICO 文件。用本页的 Python 代码片段补上文件头,它就成了普通的 .bmp。
怎么判断 BMP 字符串是否完整?
文件的第 2 到 5 个字节保存了文件总大小。打开 显示 hex 转储,按小端序读出这个数,再与 大小 一行对比。如果解码后的大小更小,说明字符串被截断了。
能得到 PNG 而不是 BMP 吗?
本页按原样保存位图。要转换格式,请下载后拖入 BMP 转 Base64,在 转换为 中选择 PNG;PNG 是无损格式,通常小得多。