How to Save Binary Buffer to Png File in Nodejs

How to save binary buffer to png file in nodejs?

Note: I am editing my answer according to your last edits

If you are using Robotjs, check that its Bitmap object contains a Buffer to raw pixels data -- not a PNG or any other file format contents, just pixels next to each other (exactly 200 x 200 elements in your case).

I have not found any function to write contents in other format in the Robotjs library (not that I know it either), so in this answer I am using a different library, Jimp, for the image manipulation.

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)

Note that the conversion is done by manually iterating through all pixels; this is slow in JS. Also there are some details on how each library handles their pixel format, so some manipulation was needed in the loop -- it should be clear from the embedded comments.

Writing binary data using node.js fs.writeFile to create an image file

JavaScript language had no mechanism for reading or manipulating streams of binary data. The Buffer class was introduced as part of the Node.js API to make it possible to interact with octet streams in the context of things like TCP streams and file system operations.

Pure JavaScript, while great with Unicode encoded strings, does not handle straight binary data very well.

When writing large amounts of data to a socket it's much more efficient to have that data in binary format vs having to convert from Unicode.

var fs = require('fs');
// string generated by canvas.toDataURL()
var img = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0"
+ "NAAAAKElEQVQ4jWNgYGD4Twzu6FhFFGYYNXDUwGFpIAk2E4dHDRw1cDgaCAASFOffhEIO"
+ "3gAAAABJRU5ErkJggg==";
// strip off the data: url prefix to get just the base64-encoded bytes
var data = img.replace(/^data:image\/\w+;base64,/, "");
var buf = Buffer.from(data, 'base64');
fs.writeFile('image.png', buf, /* callback will go here */);

Reference

How to Convert buffer into image using nodejs?

TLDR;

/**
* FINAL/WORKING SOLUTION
*/

// ...
app.get('/', (req, res) => {
const s3 = new AWS.S3({
accessKeyId: '-',
secretAccessKey: '-',
region: '-',
});

const params = {
Bucket: '-',
Key: '-',
};

s3.getObject(params, (err, rest) => {
if (err) throw err;

const b64 = Buffer.from(rest.Body).toString('base64');
// CHANGE THIS IF THE IMAGE YOU ARE WORKING WITH IS .jpg OR WHATEVER
const mimeType = 'image/png'; // e.g., image/png

res.send(`<img src="data:${mimeType};base64,${b64}" />`);
});
});
// ...

ORIGINAL ANSWER

You will need to use node to 'render' the image.. aka just send the response as an <img /> tag..

// ...
app.get('/', (req, res) => {
const s3 = new AWS.S3({
accessKeyId: '-',
secretAccessKey: '-',
region: '-',
});

const params = {
Bucket: '-',
Key: '-',
};

s3.getObject(params, (err, rest) => {
if (err) throw err;

const b64 = Buffer.from(rest).toString('base64');
// NOTE:
// Because 'rest' appears to be a buffer, you might not
// need to do `Buffer.from(...)`,you may have to do something like:
/** const b64 = rest.toString('base64'); **/
const mimeType = 'image/png'; // e.g., image/png

res.send(`<img src="data:${mimeType};base64,${b64}" />`);
});
});
// ...

EDIT 1:

I believe the issue has something to do with how the data is returned to you from S3.. You may have to do something like rest.Body or rest.body - I am not sure what the object from S3 looks like.

With that being said, I saved this image locally as sample.png, and used the code below to load it - it worked just fine. This is proof the issue has something to do with how S3 is returning that data to you.

const fs = require('fs');
const express = require('express');
const app = express();

app.get('/', (req, res) => {
// Simulate getting data from S3 (aka data as buffer)
const rest = Buffer.from(fs.readFileSync('./sample.png'));

console.log('typeof rest = ' + typeof rest + '\r\n\r\n', rest);
// typeof rest = object
//
// <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 01 34 00 00 00 a4 08 03 00 00 00 2e 4e 22 5a 00 00 00 a2 50 4c 54 45 f7 f7 f7 cd 00 00 d1 00 00 ... 6360 more bytes>


const b64 = rest.toString('base64');
const mimeType = 'image/png'; // e.g., image/png

res.send(`<img src="data:${mimeType};base64,${b64}" />`);
});

app.listen(3000);

EDIT 2:

It looks like you'll need to do this:

// ...
app.get('/', (req, res) => {
const s3 = new AWS.S3({
accessKeyId: '-',
secretAccessKey: '-',
region: '-',
});

const params = {
Bucket: '-',
Key: '-',
};

s3.getObject(params, (err, rest) => {
if (err) throw err;

const b64 = Buffer.from(rest.Body).toString('base64');
// IF THE ABOVE LINE DOES NOT WORK, TRY THIS:
// const b64 = rest.Body.toString('base64');

// CHANGE THIS IF THE IMAGE YOU ARE WORKING WITH IS .jpg OR WHATEVER
const mimeType = 'image/png'; // e.g., image/png

res.send(`<img src="data:${mimeType};base64,${b64}" />`);
});
});
// ...

How to convert image.png to binary in NodeJS?

To base 64:

const file = fs.readFileSync('/some/place/image.png')
const base64String = Buffer.from(file).toString('base64')

Then pass the base64String to Azure

If you want just a BLOB so a binary file, you can do this

const file = fs.readFileSync('/some/place/image.png')
const blob = Buffer.from(file)

MongoDB & Multer - How do I convert a buffer binary to an image?

Instead of sending the image with the .json() method, you'll want to set the appropriate content type so that the browser knows that it's an image, then just .send() the buffer:

app.get("/filestorageone/:id", (req, res) => {
fileStorageOneModel.findOne({}, (err, data) => {
if (err) {
console.log(err);
} else {
return res.type(data.img.contentType).send(data.img.data);
}
});
});

Here I'm using .type() which can also look up the correct mime type from a file extension, but you could just as well use .header('Content-Type', data.img.contentType).

I've also left out the new Buffer() call since it's already a Buffer.

As a side-note, assuming you're using multer and DiskStorage, you don't need to construct the path with path.join() and req.file.filename, as the full path can be found from req.file.path. You can also use req.file.mimetype so that you get the correct content type for also non-PNG images.

How to save Binary Data as a jpg image in NodeJS

You may use request module something like following

const fs = require('fs');
const request = require('request');

request
.get('http://example.com/image.png')
.pipe(fs.createWriteStream('image.png'))


Related Topics



Leave a reply



Submit