Node JS canvas image data - node.js

I am trying to read a image and the result i want to get is the same when you use a HTML canvas "Uint8ClampedArray"? var imageData = ctx.getImageData(0, 0, width, height); I found a NPM lib canvas but i cant get it to install.
So is there a another way to go without using Canvas?

To strictly answer the question:
So is there a another way to go without using Canvas?
The issue is that, even if we can load an image binary data, we need to be able to parse its binary format to represent it as raw pixel data (ImageData/Uint8Array objects).
This is why the canvas module needs to be compiled when installed: it rely on and links to libpng, libjpeg and other native libraries.
To load a Uint8Array representing pixel raw data from a file, without canvas (or native library wrapper), will requires decoders running only in Javascript.
For e.g. there exist decoders for png and jpeg as third-party libraries.
Decoding PNG
Using png.js:
const PNG = require('png-js');
PNG.decode('./image.png', function(pixels) {
// Pixels is a 1d array (in rgba order) of decoded pixel data
});
Decoding JPEG
Using inkjet:
const inkjet = require('inkjet');
inkjet.decode(fs.readFileSync('./image.jpg'), function(err, decoded) {
// decoded: { width: number, height: number, data: Uint8Array }
});
https://github.com/gchudnov/inkjet

Do not realy know what i did to get canvas to work. I used pixel-util to set image data.
var pixelUtil = require('pixel-util'),
Canvas = require('canvas');
var image = new Canvas.Image,
pixelUtil.createBuffer('http://127.0.0.1:8080/image/test.jpg').then(function(buffer){
image.src = buffer;
canvas = new Canvas(image.width, image.height);
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
runImage(ctx.getImageData(0, 0, canvas.width, canvas.height));
});

Related

How to convert a hex string to base64 for image saving in NodeJS

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!

Add transparent color layer to b&w image using ImageMagick

I'm trying to take a black and white image and add a red transparent layer on top. Something similar to the image. Does anyone know how I can do this using ImageMagick in Node using gm?
I took #Bonzo suggestion and used blend. With Node gm you can call ImageMagick methods directly.
const gm = require('gm');
const im = gm.subClass({ imageMagick: true });
im()
.command('composite')
.in('-blend', '100x100')
.in('-gravity', 'center')
.in('/tmp/top.png')
.in('/tmp/bottom.png').toBuffer('PNG',function (err, buffer) { }

Get file size of GIFs with node-canvas?

After much struggling, I've managed to get node-canvas installed on Windows.
When I try to read in the image size of a GIF, however, it just gives me back 0 for the width and height.
var FileSystem = require('fs');
var Canvas = require('canvas');
FileSystem.readdir(baseDir, function(err, files) {
files.forEach(function(filename) {
var path = Path.join(baseDir, filename);
FileSystem.readFile(path, function(err, buf) {
var img = new Canvas.Image;
img.src = buf;
console.log(path, img.width, img.height);
});
});
Is it not supposed to be able to read GIFs?
You must install giflib and reinstall node-canvas like is said in here https://github.com/LearnBoost/node-canvas/wiki/Installation---OSX and then you will be able to manipulate your gif file (retrieve width/height). But beware, the image processed with canvas will stop being animated.

canvas security error for svg images

What I'm trying to do is draw svg image on canvas and then create a PNG image of this canvas.
Here is an example of what I do:
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.onload = function () {
ctx.drawImage(this, 0, 0, this.width, this.height);
var url = canvas.toDataURL("image/png");
}
img.crossorigin = "Anonymous"; //not sure this affects anything...
img.src="some image url"
When I set a source of png/jpeg image it works fine but then the src is of a svg image I get "Uncaught Error: SECURITY_ERR: DOM Exception 18" when calling "canvas.toDataURL("image/png")".
I don't understand what's the difference?
The same happens when I take an inline svg and render it inside the canvas and then try to create the png image. I don't have the code right now with me - I'll add it later if necessary.
I found a solution. Apparently canvas has another function to draw svgs "drawSvg" so I used it and it works.

Image not saving on a Palm device

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.

Resources