如何在Office Script中将RGB像素二维数组转换为可插入图片?
在Office Script中将RGB像素数组转换为可插入的图片
由于Office Script不支持Canvas或外部图像处理库,我们可以通过手动构造BMP格式的二进制数据来实现转换,再将其转为Base64后使用addImage插入。以下是具体实现方案:
核心思路
BMP(位图)是一种无压缩的图像格式,结构清晰,可通过拼接二进制数据手动生成。我们需要构建BMP的文件头、信息头,再将像素数据按BMP的要求(倒序行、补位对齐)整理后拼接,最终转成Base64编码。
完整实现代码
async function main(workbook: ExcelScript.Workbook) { // 示例RGB像素数组(2行2列) const pixelArray: number[][][] = [ [[255,255,255],[0,0,0]], [[255,255,255],[0,0,0]] ]; // 将像素数组转换为BMP的ArrayBuffer const bmpBuffer = convertPixelsToBmp(pixelArray); // 转换为Base64编码 const base64Image = convertToBase64(bmpBuffer); // 插入到工作表 workbook.getWorksheet("ExampleSheet").addImage(base64Image); } /** * 将RGB像素数组转换为BMP格式的ArrayBuffer * @param pixels 二维RGB像素数组,格式为[[[R,G,B], [R,G,B]], ...] */ function convertPixelsToBmp(pixels: number[][][]): ArrayBuffer { const width = pixels[0].length; const height = pixels.length; // 每个像素3字节(RGB),每行需要补位到4字节的倍数 const bytesPerPixel = 3; const rowSize = Math.ceil((width * bytesPerPixel) / 4) * 4; const pixelDataSize = rowSize * height; const fileSize = 54 + pixelDataSize; // BMP文件头(14) + 信息头(40) + 像素数据 // 创建ArrayBuffer并写入数据 const buffer = new ArrayBuffer(fileSize); const view = new DataView(buffer); // 写入BMP文件头(14字节) view.setUint8(0, 0x42); // 'B' view.setUint8(1, 0x4D); // 'M' view.setUint32(2, fileSize, true); // 文件大小(小端序) view.setUint32(6, 0, true); // 保留字段 view.setUint32(10, 54, true); // 像素数据起始位置 // 写入BMP信息头(40字节) view.setUint32(14, 40, true); // 信息头大小 view.setUint32(18, width, true); // 图像宽度 view.setUint32(22, height, true); // 图像高度 view.setUint16(26, 1, true); // 平面数 view.setUint16(28, 24, true); // 位深度(24位RGB) view.setUint32(30, 0, true); // 压缩方式(无压缩) view.setUint32(34, pixelDataSize, true); // 像素数据大小 view.setUint32(38, 2835, true); // 水平分辨率(像素/米,默认值) view.setUint32(42, 2835, true); // 垂直分辨率 view.setUint32(46, 0, true); // 调色板颜色数 view.setUint32(50, 0, true); // 重要颜色数 // 写入像素数据(BMP要求行倒序,且每行补位) let offset = 54; for (let y = height - 1; y >= 0; y--) { // 从最后一行开始写 const row = pixels[y]; for (let x = 0; x < width; x++) { const [r, g, b] = row[x]; view.setUint8(offset++, b); // BMP是BGR顺序 view.setUint8(offset++, g); view.setUint8(offset++, r); } // 补位到4字节倍数 const padding = rowSize - width * bytesPerPixel; for (let i = 0; i < padding; i++) { view.setUint8(offset++, 0); } } return buffer; } /** * 将ArrayBuffer转换为Base64编码 * @param buffer 待转换的ArrayBuffer */ function convertToBase64(buffer: ArrayBuffer): string { const bytes = new Uint8Array(buffer); let binary = ''; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return `data:image/bmp;base64,${btoa(binary)}`; }
代码说明
convertPixelsToBmp函数:- 先计算BMP文件的各项参数(宽度、高度、行大小、文件总大小)
- 依次写入BMP的文件头和信息头,严格遵循BMP格式规范
- 按BMP要求的BGR顺序、倒序行、行补位规则写入像素数据
convertToBase64函数:将ArrayBuffer转为二进制字符串,再用btoa编码为Base64,同时加上BMP的MIME前缀- 主函数:使用示例像素数组完成转换并插入到指定工作表
注意事项
- 该实现仅支持24位RGB像素(无Alpha通道),如果需要透明通道可调整为32位BMP格式
- 像素数组需保证每行长度一致(即图片宽度固定)
- 大尺寸图片可能会因Office Script的内存限制影响性能,建议用于小图标或简单图形
内容的提问来源于stack exchange,提问作者FeddeHasQuestion
相关产品推荐
相关产品推荐

