You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Deno将BMP图像文件转换为黑白Uint8Array?

在Deno中解析BMP并转换为黑白Uint8Array

要实现需求,需要先解析BMP文件的头信息,提取原始像素数据后再转换为你需要的黑白比特流格式。以下是具体实现方案:

核心思路

BMP文件由文件头、信息头和像素数据三部分组成:

  • 从文件头获取像素数据的起始偏移量
  • 从信息头获取图像宽高、位深度等关键参数
  • 根据位深度处理像素数据:如果是1位黑白图直接提取并修正行顺序;如果是其他位深度(如24位彩色),先转灰度再按阈值生成黑白比特流,最后打包成Uint8Array

完整代码实现

async function processBmp(filePath) {
  const fileData = await Deno.readFile(filePath);
  const view = new DataView(fileData.buffer);

  // 解析BMP关键信息
  const dataOffset = view.getUint32(10, true); // 像素数据起始位置
  const width = view.getUint32(18, true);       // 图像宽度
  const height = view.getUint32(22, true);      // 图像高度
  const bitDepth = view.getUint16(28, true);    // 位深度

  // 处理1位黑白BMP(直接提取像素数据)
  if (bitDepth === 1) {
    const bytesPerRow = Math.ceil(width / 8);
    const reversedRows = [];
    // BMP像素行是倒序存储(从底部到顶部),反转后得到正确顺序
    for (let i = height - 1; i >= 0; i--) {
      const start = dataOffset + i * bytesPerRow;
      reversedRows.push(fileData.slice(start, start + bytesPerRow));
    }
    return new Uint8Array([].concat(...reversedRows.map(row => Array.from(row))));
  }

  // 处理其他位深度(如24位彩色),转换为黑白比特流
  const bytesPerPixel = bitDepth / 8;
  const bytesPerRow = Math.ceil((width * bytesPerPixel + 3) / 4) * 4; // BMP行对齐到4字节
  const resultBytes = [];

  for (let y = height - 1; y >= 0; y--) {
    let currentByte = 0;
    let bitPos = 7; // 从字节的最高位开始填充

    for (let x = 0; x < width; x++) {
      const pixelStart = dataOffset + y * bytesPerRow + x * bytesPerPixel;
      // 计算灰度值(采用加权公式更准确:0.299*R + 0.587*G + 0.114*B)
      const r = fileData[pixelStart + 2];
      const g = fileData[pixelStart + 1];
      const b = fileData[pixelStart];
      const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
      
      // 阈值判断:灰度>127为白(1),否则为黑(0)
      const bit = gray > 127 ? 1 : 0;
      currentByte |= (bit << bitPos);
      bitPos--;

      // 填满一个字节或到行尾时,存入结果
      if (bitPos < 0 || x === width - 1) {
        resultBytes.push(currentByte);
        currentByte = 0;
        bitPos = 7;
      }
    }
  }

  return new Uint8Array(resultBytes);
}

// 使用示例
const blackWhiteData = await processBmp('./path/to/my/image.bmp');
console.log(blackWhiteData); // 对应你示例中的[0x5A, 0x5A]

关键细节说明

  • 行顺序修正:BMP的像素行是从图像底部开始存储的,所以需要反转行才能得到视觉上的正序
  • 字节对齐:BMP的每行数据会对齐到4字节,处理非1位图像时必须考虑这一点,避免读取到补位的空字节
  • 灰度转换:采用加权公式计算灰度比简单平均值更符合人眼对色彩的感知,你也可以根据需求调整阈值

内容的提问来源于stack exchange,提问作者Mqx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 22:00:30