Updated: webOS version 2.1...
This base64 encoded image data generates the correct data image when I append it to the source of an image, like this:
var img = new Image();
img.src= data
var data = "data:image/png;base64,iVBORw0KGgoAAAANSUh
EUgAAAJYAAACmCAIAAAC3GeEYAAEkgklEQVR4AQD9/wIAADt8Fj5/GUSA IESAIEN/GUd/H0V+IEaEIE
WFHUOEHEqJIE2KIk2KI1GQKFSQLFaQKlaOKVaQKlORLlaYLVaVKFWV KVWUKliWKFiXJlKVIliTJW2oP
m6jOW+kPGqkPmehPWWePWagOmmjP2ykQ2ulQmylRWykQmqmP2qr QGqnP26qSGyvRmquQWyyQGquP2yu
RHSzSHWwSXGxSGytRG+vSG6vSW2vRWquRGqtRGmsQnO1R3Gw SG+rSXavUXWwUnKqR3CuRWquP26zQ3C
yRXK0SHG0SWupR2qoR3CuS2qrQ3CsSG6vS22pR26qSGyq RWetO22uQ2yqP22wRGetP2yyP4TEWgElAB
UrBRYmAx05AidHBB9MCydRDylSGChWGCZUFyFLEyNK Ex5IDBtJBhc/Bx9FDBxDDh5HDyRGExs8DRs4D
B04DRw8Exo6DxMuBw8kAhEeABIYAQ4VABAUAA0S AAwVAg8bAw0bAgwaAxAYAAULAQgQAQcQBQsPAAwQ
AggMAwMLAQAIAAgOBAYOAAsWBg4bChMgDxUk DxcmERopEh8vFBwuExspEhcnDxUpDhcqERUnDhUnDRQ
rDxgsERgvEx8xGQA+fxk7gxU9hBc9ghg/ gR1CgBxBhBtChRxIhyFMiyNMiyNNjiZNiypRkCpSjydRkC
VVkSpTkihYmi9YlC9XlCxVlClYlixW lSpZlS1eli16skJnqDxppj1qpDxmpD9mpD1loj1opz9qqENvq
Udpp0FmqD9npkFtpUVvp0ZvrUVs q0NsrEFtrURsrkBrsT9vskFvrj5srz5ssUJsrkJsrkNtr0NusEVm
qjxrrz5ttkNquEFqtEFu"
I am trying to save the image using my custom service, but it does not save the correct image. Here is the Node.js code for saving the image:
var fs = IMPORTS.require('fs');
var path = IMPORTS.require('path');
var buff = new Buffer(img.substr('data:image/png;base64,'.length), 'base64');
path.exists('/media/internal/wallpapers/', function(exists){
if (exists) {
var id = fs.openSync('/media/internal/wallpapers/i.png', 'w', 666);
var written = fs.writeSync(id, buff,0, buff.length, 0);
fs.closeSync(id);
}
});
The saved version of the image has totally different pixel values.
EDIT
I came to find out that the image data above isn't correct. I am using a PNG library to generate base64 image data of a canvas pixel array. The link is http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/.
That is an alternative to canvas.toDataURL();. webOS does not support toDataURL, so I had to use a library.
Here is the code I have used with this library to manipulate my canvas image data as a pixel array:
EditorAssistant.prototype.getDataURL = function(width,height,pixelArray) {
var p = new PNGlib(height, width, 256); // Construcor takes height, weight and color-depth.
var background = p.color(0, 0, 0, 0);
var k = 0;
for (var j = 0; j<height; j++) {
for (var i =0; i<width; i++) {
var x =i;
var y =j;
p.buffer[p.index(x,y)] = p.color(pixelArray[k], pixelArray[k+1], pixelArray[k+2]);
k+=4;
}
}
return 'data:image/png;base64,'+p.getBase64() ;
}
Does this library work and where am I doing it wrong?
libpng.js only supports 256 color images, so that may be the problem. There are other base64 encoding utilities which may work as expected.
Related
I'm making a NodeJS sockets.io multiplayer drawing canvas. The data gets saved as color id's in a 2D matrix, and I have an array of color hex codes to match with the id's.
I need to be able to save the image as a file, and so I got to the point of storing the image data as a continuous string, joining every pixel's hex code:
// 'boardData' contains the index of the color for each pixel
// 'colors' is an array on hex values
var hexString = ""
for (var x = 0; x < boardWidth; x++) {
for (var y = 0; y < boardHeight; y++) {
hexString += colors[boardData[x][y]].replace('#','');
}
}
The result is something like ffffff3fbae52dffba...
I managed to convert this string into base64 by doing the following:
var base64Data = Buffer.from(hexString, 'hex').toString('base64')
Then, I tried saving it by doing this:
fs.writeFile("image.png", base64Data, {encoding: 'base64'}, function(err) {
if (err) return err;
console.log('Saved!');
});
But the resulting images seem to have an incompatible format.
When I try saving a 16x16 completely white image, the base64 code comes out as ///////////////////////////..., but when I try online image converters, a 16x16 white image becomes iVBORw0KGgoAAAANSUhEUgAAAAg..., and hardcoding this into the fs.writeFile data works just fine. Actually, seems like even a 1x1 white image yields a lot of characters, so I'm not entirely sure how this even works.
I believe I'm missing a step here. Can someone point me in the right direction? Is there maybe another way of converting this raw color data into an image file?
I've found a solution. This library called Jimp does exactly what i was looking for.
For anyone that wants to know. just had to install the module by openning up a command terminal, navigating to my nodejs server folder and running this:
npm install --save jimp
Then, on my server code, i have to import this library (Note that it has to be uppercase J):
var Jimp = require('jimp')
And so i just do this to save the image:
let jimg = new Jimp(boardWidth, boardHeight);
for (var x=0; x<boardWidth; x++) {
for (var y=0; y<boardHeight; y++) {
var hex = colors[boardData[x][y]].replace('#','');
var num = parseInt(hex+"ff", 16);
jimg.setPixelColor(num, x, y);
}
}
jimg.write("output.png")
Hope this helps someone!
I tried to capture and save an image from screen with robotjs (http://robotjs.io/) but when I open the file bitmap the image is not in a valid format. This is my code:
var robot = require("robotjs");
var fs = require("fs");
var size = 10;
var img = robot.screen.capture(0, 0, size, size);
fs.writeFileSync('img.bmp',img.image);
Jimp supports converting Raw Pixel Buffer into PNG out-of-the-box and works a lot faster.
let robot = require("robotjs");
let Jimp = require('jimp');
const img = robot.screen.capture(0, 0, width, height).image;
new Jimp({data: img, width, height}, (err, image) => {
image.write(fileName);
});
The image will be saved with the wrong colors. To fix it, you can use the following code:
function screenCaptureToFile2(robotScreenPic, path) {
return new Promise((resolve, reject) => {
try {
const image = new Jimp(robotScreenPic.width, robotScreenPic.height);
let pos = 0;
image.scan(0, 0, image.bitmap.width, image.bitmap.height, (x, y, idx) => {
image.bitmap.data[idx + 2] = robotScreenPic.image.readUInt8(pos++);
image.bitmap.data[idx + 1] = robotScreenPic.image.readUInt8(pos++);
image.bitmap.data[idx + 0] = robotScreenPic.image.readUInt8(pos++);
image.bitmap.data[idx + 3] = robotScreenPic.image.readUInt8(pos++);
});
image.write(path, resolve);
} catch (e) {
console.error(e);
reject(e);
}
});
}
var pic = robot.screen.capture();
screenCaptureToFile2(pic)
Note that your img.image Buffer from Robotjs is a raw buffer with pixels; not a BMP or PNG or any other format.
You should do some data conversion and probably save it using a library that supports writing to file (I do not see that in Robotjs).
Please look at this other question, which also uses robot.screen.capture and saves file to a PNG file using Jimp library. That code answers your question too.
Did someone of you try to make svg.js work with node.js? I tried to use the jsdom module to render svg but jsdom but SVG.supported returns false. Is there a way to make this library work with node.js?
Thanks in advance!
EDIT: Here is my code, I want to make that on Node.js and then probably render the SVG in a pdf or as a png:
var draw = SVG('drawing').size(600, 600)
var image = draw.image('inclusions.png')
image.size(400, 150)
var rect = draw.rect(400, 150).attr({ fill: 'orange' })
for (i = 0; i < 10; i++) {
var point = draw.circle(5)
var xpos = Math.floor((Math.random() * 400) + 1);
var ypos = Math.floor((Math.random() * 150) + 1);
point.x(xpos)
point.y(ypos)
point.fill('black')
}
image.front()
Here is the working example usage of svg.js inside nodejs project,
svgdom is the suggested library from svg.js official website
const window = require('svgdom');
const SVG = require('svg.js')(window);
const document = window.document;
function generateSVGTextLines(width, height, lineList, tAsset) {
var draw = SVG(document.documentElement).size(width, height);
draw.clear();
draw.text(function (add) {
if (lineList) {
for (var i = 0; i < lineList.length; i++) {
add.tspan(lineList[i].text).attr("x", "50%").newLine();
}
}
}).font({
family: tAsset.fontFamily,
size: tAsset.fontHeight,
leading: '1.2em',
anchor: "middle"
}).move(width / 2, 0);
return draw.svg();
}
This link might be helpful: http://techslides.com/save-svg-as-an-image
This documents a client side solution that causes the requisite SVG to be drawn on the end user's browser, rather than on the server, but it provides the end result you want by putting the SVG into an image tag and allowing the user to download it. If keeping the SVG drawing logic secret is a problem, you could use a similar principle by sicing PhantomJS on the generator page and sending the user the image it downloads.
I can't seem to make it work to resize. How can I resize base64 image using gm?
I have the following code:
var regexBase64ContentType = /^data:image\/\w+;base64,/;
var buffer = new Buffer(imgData.replace(regexBase64ContentType, ""),'base64');
gm(buffer, "img.png")
.resize(height, width)
.toBuffer('PNG', function(err, buf){
return buf;
});
Is there an easy way in Node.js to read a PNG file and get the pixels of the image? Something like node-image, but the other way :)
I went through the libraries listed at https://github.com/joyent/node/wiki/modules#wiki-graphics, but they are either simple wrappers around command line tools providing cropping and resizing or complex drawing tools like node-canvas.
This one does both PNG decoding and encoding without native dependancies:
pngjs - PNG encoder/decoder for Node.js with no native dependencies.
An example for inverting the colors of a PNG:
var fs = require('fs'),
PNG = require('pngjs').PNG;
fs.createReadStream('in.png')
.pipe(new PNG())
.on('parsed', function() {
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
var idx = (this.width * y + x) << 2;
// invert color
this.data[idx] = 255 - this.data[idx]; // R
this.data[idx+1] = 255 - this.data[idx+1]; // G
this.data[idx+2] = 255 - this.data[idx+2]; // B
// and reduce opacity
this.data[idx+3] = this.data[idx+3] >> 1;
}
}
this.pack().pipe(fs.createWriteStream('out.png'));
});
I was about to became mad searching, but I found one:
png.js ― A PNG decoder in JS for the canvas element or Node.js.
var PNG = require('png-js');
var myimage = new PNG('myimage.png');
var width = myimage.width;
var height = myimage.height;
myimage.decode(function (pixels) {
//Pixels is a 1D array containing pixel data
});
Please note it's pure JavaScript. Works both in the browser <canvas> and in Node.JS.
There are more properties apart from width and height, see this source.
I think
var myimage = new PNG('myimage.png');
should be
var myimage = new PNG.load('myimage.png');