如何将二进制缓冲区保存到nodejs中的png文件?

时间:2017-05-09 23:57:36

标签: javascript node.js buffer

我有二进制nodejs包含位图信息的Buffer对象。如何从缓冲区制作图像并将其保存到文件?

编辑:

我尝试使用文件系统包,如@herchu所说,但如果我这样做:

let robot = require("robotjs")
let fs = require('fs')

let size = 200
let img = robot.screen.capture(0, 0, size, size)


let path = 'myfile.png'
let buffer = img.image

fs.open(path, 'w', function (err, fd) {
  if (err) {
    // Something wrong creating the file
  }

  fs.write(fd, buffer, 0, buffer.length, null, function (err) {
    // Something wrong writing contents!
  })
})

我得到了

enter image description here

4 个答案:

答案 0 :(得分:4)

注意:我正在根据您上次编辑

编辑我的答案

如果您使用的是Robotjs,请检查其Bitmap object是否包含缓冲区原始像素数据 - 不是PNG或任何其他文件格式内容,只是彼此相邻的像素(在您的情况下恰好200 x 200个元素。)

我还没有找到任何在Robotjs库中以其他格式写内容的功能(不是我也知道),所以在这个答案中我使用了不同的库Jimp来进行图像处理。

let robot = require("robotjs")
let fs = require('fs')
let Jimp = require('jimp')

let size = 200
let rimg = robot.screen.capture(0, 0, size, size)
let path = 'myfile.png'

// Create a new blank image, same size as Robotjs' one
let jimg = new Jimp(size, size);
for (var x=0; x<size; x++) {
        for (var y=0; y<size; y++) {
                // hex is a string, rrggbb format
                var hex = rimg.colorAt(x, y);
                // Jimp expects an Int, with RGBA data,
                // so add FF as 'full opaque' to RGB color
                var num = parseInt(hex+"ff", 16)
                // Set pixel manually
                jimg.setPixelColor(num, x, y);
        }
    }
jimg.write(path)

请注意,转换是通过手动迭代所有像素完成的;这在JS中很慢。还有一些关于每个库如何处理其像素格式的细节,因此循环中需要一些操作 - 从嵌入的注释中应该清楚。

答案 1 :(得分:2)

将此作为@herchu接受的答案的附录添加,此代码示例处理/转换原始字节的速度更快(对于我来说,全屏显示为1秒)。希望这对某人有帮助。

SELECT * 
    FROM  post_project 
    INNER JOIN  post_proposal ON post_proposal.post_project_id = post_project.post_project_id 
    INNER JOIN hireuser_info ON hireuser_info.user_id = post_proposal.post_project_user_id 
    WHERE $prid=post_user id 

答案 2 :(得分:1)

尽管@herchu和@Jake的解决方案很有效,但它们的速度非常慢(以我的经验为10-15秒)。


Jimp supports converting Raw Pixel Buffer into PNG开箱即用,工作速度更快(亚秒级)。

const img = robot.screen.capture(0, 0, width, height).image;
new Jimp({data: img, width, height}, (err, image) => {
    image.write(fileName);
});

答案 3 :(得分:1)

快四倍! 如果使用此脚本,则全屏1920x1080约为280ms和550Kb。 当我将每个字节的2个字节的线程与额头进行比较时,我发现了这种模式。

const robotjs = require('robotjs');
const Jimp = require('jimp');
const app = require('express').Router();

app.get('/screenCapture', (req, res)=>{
  let image = robotjs.screen.capture();
  for(let i=0; i < image.image.length; i++){
      if(i%4 == 0){
          [image.image[i], image.image[i+2]] = [image.image[i+2], image.image[i]];
      }
  }

  var jimg = new Jimp(image.width, image.height);
  jimg.bitmap.data = image.image;
  jimg.getBuffer(Jimp.MIME_PNG, (err, result)=>{
      res.set('Content-Type', Jimp.MIME_PNG);
      res.send(result);
  });
});

如果您在jimp.getBuffer之前添加此代码,则全屏显示时间约为210ms和320Kb

  jimg.rgba(true);
  jimg.filterType(1); 
  jimg.deflateLevel(5);
  jimg.deflateStrategy(1);