BMP
BMP 采用位映射储存格式,除了图像深度可选外,不采用其他任何压缩,因此 BMP 文件占用的空间很大
格式
- 位图头文件数据结构:它包含BMP图像文件的类型、显示内容等信息;
- 位图信息数据结构:它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
- 调色板:这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;
- 位图数据:这部分的内容根据BMP位图使用的位数不同而不同,在 24 位图中直接使用RGB,而其他的小于 24 位的使用调色板中颜色索引值
特点
由于采用的位映射形式,对应数据只能在对应的位置上,所以没法对它进行压缩。这导致 BMP 格式图片的体积都很大,传输加载过于耗时,不适用于 Web 场景
创建一个 BMP 文件
BMP 的格式很简单,所以在 NodeJs 中,可以直接通过 Buffer 对象来创建缓冲区,并且写入我们的数据
下面是一个创建颜色为 #2CA688,宽高为 100 的纯色 BMP 图片的例子:
import fs from 'node:fs'
// 图像宽度和高度
const width = 100;
const height = 100;
// 创建一个Buffer用于存储BMP文件头
const bmpHeader = Buffer.alloc(14);
// BMP文件标识符
bmpHeader.write('BM', 0);
// 文件大小(包括文件头和图像数据)
bmpHeader.writeUInt32LE(14 + 40 + (width * height * 3), 2);
// 保留字段
bmpHeader.writeUInt16LE(0, 6);
bmpHeader.writeUInt16LE(0, 8);
// 图像数据偏移量
bmpHeader.writeUInt32LE(14 + 40, 10);
const bmpInfoHeader = Buffer.alloc(40);
// 信息头大小
bmpInfoHeader.writeUInt32LE(40, 0);
// 图像宽度和高度
bmpInfoHeader.writeUInt32LE(width, 4);
bmpInfoHeader.writeUInt32LE(height, 8);
// 颜色平面数(必须为1)
bmpInfoHeader.writeUInt16LE(1, 12);
// 位深(每像素的位数),这是设置成 3 * 8 = 24位
bmpInfoHeader.writeUInt16LE(24, 14);
// 压缩类型(0表示不压缩)
bmpInfoHeader.writeUInt32LE(0, 16);
// 图像数据大小
bmpInfoHeader.writeUInt32LE(width * height * 3, 20);
// 水平和垂直分辨率(像素/米)
bmpInfoHeader.writeUInt32LE(0, 24);
bmpInfoHeader.writeUInt32LE(0, 28);
// 使用的调色板颜色数和重要颜色数
bmpInfoHeader.writeUInt32LE(0, 32);
bmpInfoHeader.writeUInt32LE(0, 36);
const bmpData = Buffer.alloc(width * height * 3);
// 填充图像数据
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const offset = (y * width + x) * 3;
bmpData.writeUInt8(0x2C, offset); // 红色分量
bmpData.writeUInt8(0xA6, offset + 1); // 绿色分量
bmpData.writeUInt8(0x88, offset + 2); // 蓝色分量
}
}
const bmpBuffer = Buffer.concat([bmpHeader, bmpInfoHeader, bmpData]);
// 将Buffer写入BMP文件
fs.writeFileSync('output.bmp', bmpBuffer);执行完毕后,我们将看到当前目录产生了一个 output.bmp 文件,就是我们生成的位图文件