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
How to Specify Multiple Conditions in an If Statement in JavaScript
Why Does Google Chrome Always Add Space After Selected Text
Regex to Find Json Values Without Quotes
Display Images in React Using Jsx Without Import
Stylesheet Not Loading Because Mime Type Is Text/Html
How to Open a Url Link from JavaScript Inside a Google Apps Script HTML Google Site Gadget
React-Native: Convert Image Url to Base64 String
How to Sort a Map by Value in JavaScript
How to Stop the Iframe from Constantly Reloading After Setinterval (Jquery)
Uncaught Typeerror: Cannot Read Property 'Click' of Null Chrome Extension
Check If a Number Has a Decimal Place/Is a Whole Number
Jquery Ajax Post Results in 500 Internal Server Error
How to Change Colour of Text Based on Its Value When a Page Initially Loads
Detect If a Field Is Updated With JavaScript or Jquery
Trigger Event When Element Becomes Visible With Ngif
How to Specify a Single File to Be Seed Only
Get a Value from a Observable<Value> Object
Remove the Default Browser Header and Footer When Printing HTML