使用Robot.js截取的截图颜色错乱,如何解决?
问题解决:Robot.js截图转PNG颜色错乱修复
核心原因
Robot.js的captureScreen()返回的原始像素缓冲区是BGRA(蓝、绿、红、透明度)格式,而你指定的PNG颜色类型6要求的是RGBA(红、绿、蓝、透明度)格式,通道顺序不匹配直接导致了颜色错乱。
修复后的完整代码
修改像素数据处理逻辑,交换每个像素的红、蓝通道,同时保留PNG要求的行过滤符(每行开头的0):
const fs = require('fs'); const zlib = require('zlib'); const robot = require("@jitsi/robotjs"); const { width, height } = robot.getScreenSize(); const bitDepth = 8; const colorType = 6; const bytesPerPixel = 4; const rawPixelData = robot.captureScreen().image; // 修复:将BGRA转RGBA,同时添加PNG行过滤符 const filteredData = Buffer.alloc((width * bytesPerPixel + 1) * height); for (let i = 0; i < height; i++) { // 写入行过滤符(固定为0) filteredData[i * (width * bytesPerPixel + 1)] = 0; const rowStart = i * width * bytesPerPixel; const filteredRowStart = i * (width * bytesPerPixel + 1) + 1; // 遍历当前行的每个像素,交换B和R通道 for (let j = 0; j < width; j++) { const pixelIndex = rowStart + j * bytesPerPixel; const filteredIndex = filteredRowStart + j * bytesPerPixel; // BGRA -> RGBA:交换蓝色和红色通道位置 filteredData[filteredIndex] = rawPixelData[pixelIndex + 2]; // 红色通道 filteredData[filteredIndex + 1] = rawPixelData[pixelIndex + 1]; // 绿色通道(不变) filteredData[filteredIndex + 2] = rawPixelData[pixelIndex]; // 蓝色通道 filteredData[filteredIndex + 3] = rawPixelData[pixelIndex + 3]; // 透明度通道(不变) } }; const compressedData = zlib.deflateSync(filteredData); function crc32(buf) { let crc = 0xffffffff; for (let i = 0; i < buf.length; i++) { crc ^= buf[i]; for (let j = 0; j < 8; j++) { if (crc & 1) { crc = (crc >>> 1) ^ 0xedb88320; } else { crc >>>= 1; } } } return Buffer.from([(crc ^ 0xffffffff) >>> 24, (crc ^ 0xffffffff) >>> 16, (crc ^ 0xffffffff) >>> 8, (crc ^ 0xffffffff) & 0xff]); } function createChunk(type, data) { const length = Buffer.alloc(4); length.writeUInt32BE(data.length, 0); const typeBuffer = Buffer.from(type, "ascii"); const crc = crc32(Buffer.concat([typeBuffer, data])); return Buffer.concat([length, typeBuffer, data, crc]); } const pngSignature = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]); const ihdrData = Buffer.alloc(13); ihdrData.writeUInt32BE(width, 0); ihdrData.writeUInt32BE(height, 4); ihdrData.writeUInt8(bitDepth, 8); ihdrData.writeUInt8(colorType, 9); ihdrData.writeUInt8(0, 10); ihdrData.writeUInt8(0, 11); ihdrData.writeUInt8(0, 12); const ihdrChunk = createChunk("IHDR", ihdrData); const idatChunk = createChunk("IDAT", compressedData); const iendChunk = createChunk("IEND", Buffer.alloc(0)); const pngData = Buffer.concat([pngSignature, ihdrChunk, idatChunk, iendChunk]); fs.writeFileSync("./output.png", pngData); console.log("PNG file written: output.png");
关键说明
- 仅修改了像素通道转换部分,其余PNG块生成、CRC校验等逻辑保持不变,完全基于你原有的代码框架。
- 无需引入任何额外依赖,仅使用Node.js内置模块和已安装的Robot.js,符合你不安装大体积包的要求。
内容的提问来源于stack exchange,提问作者Dinoscape Dinoscape
相关产品推荐
相关产品推荐

