Node get image properties (height, width) - image

I'm looking for a means to get the height and width of images from a given path locally. I know about imagemagick and graphicmagick but I'd prefer a method that doesn't involve installing extra software to the OS. If I can keep it to node modules that would be fantastic.
Does anyone have any ideas that may help me?
Worst case scenario, I'll use IM and GM but like it said would prefer to avoid this path.

You can use JIMP(JavaScript Image Manipulation Program). An image processing library for Node written entirely in JavaScript, with zero external or native dependencies. It has so many other image manipulation options available if you want.
var Jimp = require('jimp');
var image = new Jimp("./path/to/image.jpg", function (err, image) {
var w = image.bitmap.width; // width of the image
var h = image.bitmap.height; // height of the image
});
Hope this will help.

You can use a pure JS node module https://www.npmjs.org/package/image-size .. doesn't require installing anything extra
var sizeOf = require('image-size');
var dimensions = sizeOf('images/funny-cats.png');
console.log(dimensions.width, dimensions.height);

Related

Saving D3.js (circles and lines) as an image

I'm trying to modify this d3js graph example https://bl.ocks.org/nitaku/7512487 to generate and download as an image. I can get it to work with just the nodes, but can't seem to get the lines (edges) between the nodes to save.
Pasting the following into the console on the example above will generate the image of the nodes:
function svg2img(){
var svg = document.querySelector('svg');
var xml = new XMLSerializer().serializeToString(svg);
var svg64 = btoa(xml); //for utf8: btoa(unescape(encodeURIComponent(xml)))
var b64start = 'data:image/svg+xml;base64,';
var image64 = b64start + svg64;
return image64;
};svg2img()
For some wider context, it's used within a Python Flask app - I allow the user to create a graph network, then require it to be downloaded.
Many thanks!
When you export an SVG to an image like that, you lose all styles that are not inline. After all, it doesn't have access to the CSS files any more, when it's encoded as base64. You are not the first to have encountered this problem, but if you want do do it yourself, you'd need to first traverse the SVG nodes, then get their styles using window.getComputedLayout(node), and then export it. Or you can change the D3 code to apply all styles directly onto the nodes using .attr() or .style().
If you're fine using outside tools, there are many just on github alone, like this one, this one, and this one. You can install them or just use their code as inspiration.

Node.js: image resizing without ImageMagick

I'm developing a web app on Node.js (+ express 4) where users can set their profile image by uploading it to the server. We already limit the file mimetype and max filesize, so the user can't upload more than 200KB png or jpeg images.
The problem is we'd like to resize (serverside) the uploaded image resolution to 200x200 to improve page loading and saving space on disk. After some research, all answers pointed to using any module based on ImageMagick or GraphicsMagick.
However, having to install ImageMagick/GraphicsMagick to do a simple image resizing seems too overkill for me, so, is there any other solution other than this for Node.js?
Edit: I've changed the accepted solution to sharp as the previous solution (lwip) is no longer maintained. Thanks for all your feedback!
I would vote for sharp:
sharp('input.jpg')
.resize(200, 200)
.toFile('ouput.jpg', function(err) {
// output.jpg is a 200 pixels wide and 200 pixels high image
// containing a scaled and cropped version of input.jpg
});
It's fast, typically 6x faster than the fastest imagemagick-based node bindings, and runs in very little memory, perhaps 10x less. sharp links to the libvips image library directly, there is no shelling out to an external program, and the library itself is faster and more efficient than *magick at this task. It supports useful things like stream, buffer and filesystem input and output, colour management, transparency, promises, overlays, WebP, SVG, and more.
As of sharp 0.20, npm will automatically download complete pre-compiled binaries on most platforms, so there's no need for node-gyp. Just enter:
npm install sharp
or:
yarn add sharp
And off you go.
I have recently started developing an image processing module for NodeJS without any runtime dependencies (read why). It's still at early stages, but already usable.
What you are asking for would be done as follows:
image.resize(200, 200, function(err, image){
// encode resized image to jpeg and get a Buffer object
image.toBuffer('jpg', function(err, buffer){
// save buffer to disk / send over network / etc.
});
});
More info at the module's Github repo.
Take a look at lwip : https://github.com/EyalAr/lwip
Very simple and easy to use
npm install lwip
and then in your node code,
// obtain an image object:
require('lwip').open('image.jpg', function(err, image){
// check err...
// define a batch of manipulations and save to disk as JPEG:
image.batch()
.scale(0.75) // scale to 75%
.rotate(45, 'white') // rotate 45degs clockwise (white fill)
.crop(200) // crop a 200X200 square from center
.blur(5) // Gaussian blur with SD=5
.writeFile('output.jpg', function(err){
// check err...
// done.
});
});
I have successfully implemented this in my file uploader and it works like a charm.
There is a good image manipulation library written entirely in JavaScript, without dependencies to any other libraries, Jimp. https://github.com/oliver-moran/jimp
Example usage:
var Jimp = require("jimp");
// open a file called "lenna.png"
Jimp.read("lenna.png", function (err, lenna) {
if (err) throw err;
lenna.resize(256, 256) // resize
.quality(60) // set JPEG quality
.write("lena-small.jpg"); // save
});
sharp has enjoyed some popularity recently, but it’s the same idea as *Magick bindings.
However, having to install ImageMagick/GraphicsMagick to do a simple image resizing seems too overkill for me
Image resizing is anything but simple. The JPEG format is particularly complex, and there are several ways to scale graphics with results of varying quality, few of them easily implemented. Image processing libraries exist to do this job, so if there’s no other reason why you can’t install them, go for it.
According to images-manipulation-performance, Canvas is 2.3 times faster than ImageMagick.
Sample results:
Library
Imges per Second
Minimum Free Memory
sharp.js
9.501
929Mb
canvas.js
8.246
578Mb
gm.js
4.433
791Mb
gm-imagemagic.js
3.654
804Mb
lwip.js
1.203
54Mb
jimp.js
0.445
82Mb
If you don't need a large image, you can resize it on the client side before uploading it:
Reading files in JavaScript using the File APIs
Image resizing client-side with javascript before upload to the server
Many users might have a good picture of themselves from a smartphone, and many of them are over 200kB. Note that client-provided data is not to be trusted, so server-side checks still apply.
I was using lwip (as previously suggested by arvind) but switched to png-crop. It seems to work a little faster for me (Win 8.1 x64, Node v0.12.7). The code in the repo looks incredibly lightweight, and operationally it's simple to use.
var pngcrop = require('png-crop');
var config = {left: 10, top: 100, height: 150, width: 150};
pngcrop.crop('cats.png','cats-cropped.png',config);
Of course, it'll only do png files...
Sharp work very well and is easy to use with streams, work like a charm, but you need to compile it with the node version, this is a downside to it.
I was using Sharp for image processing, with an image from an AWS S3 bucket and worked perfectly, but I had to use another module. GM didn't work for me, but Jimp worked very good!
You have to pay attention to the path of the written picture, it might give you some errors if you start the path with a "/".
This is how I used Jimp in nodeJS:
const imageUrl = `SOME_URL`;
let imgExported = 'EXPORTED_PIC.png';
Jimp.read(imageUrl)
.then(image => {
image
.resize(X, Y)
.write(`tmp/`+ imgExported, err => {
if(err)
console.error('Write error: ', err);
else { ... // don't forget to put a callback() } }
});
Also watch out for the order of execution, put a callback so other things don't happen when you don't want to. Tried using "await" for the Jimp.read() but it didn't do the job well.
You can do this using jimp (node_module)
Local Write:
Jimp.read(path) // this can be url or local location
.then(image=> {
image
.resize(size, Jimp.AUTO) // jimp.AUTO automatically sets the width so that the image doesnot looks odd
.write('path-to-save');
})
.catch(err => {
console.log(err);
});
To upload to s3 or where ever you like.
Jimp.read(urls) // this can be url or local location
.then(image=> {
image
.resize(size, Jimp.AUTO) // jimp.AUTO automatically sets the width so that the image doesnot looks odd
.getBase64(Jimp.AUTO, (err, res) => {
const buf = new Buffer(
res.replace(/^data:image\/\w+;base64,/, ""),
"base64"
);
var data = {
Key: key,
Bucket: bucket,
Body: body,
ContentEncoding: "base64",
ContentType: "image/jpeg"
};
s3.putObject(data, function(err, data) {
if (err) {
throw err;
} else {
console.log("succesfully uploaded the image!");
}
});
});
})
.catch(err => {
console.log(err);
});
I like resize-img library for its simplicity.
const fs = require('fs');
const resizeImg = require('resize-img');
(async () => {
const image = fs.readFileSync('unicorn.png');
const newImage = await resizeImg(image, { width: 128, height: 128 });
fs.writeFileSync('unicorn-128x128.png', newImage);
})();
Implemented image resize using Google Drive API v3. This method is recommended for Google Apps Script to insert images into Google Sheets.
Algorithm:
Upload image to the Google Drive folder.
Get image thumbnail public URL.
Replace 'resize' parameter in the URL with necessary width and/or height. (Default thumbnail size is 220px).
Download resized thumbnail from the Google Drive.
See example here:
https://github.com/dobromyslov/google-drive-utils/blob/511c44c2c48862b47c60038423b7f71bf1d28f49/src/index.ts#L150
And beware of GDrive quotas:
queries per day: 1000000000
queries per 100 sec per user: 1000
queries per 100 sec: 10000

Create new .png Image in D

I am trying to create a .png image that is X pixels tall and Y pixels short. I am not finding what I am looking for on dlang.org, and am struggling to find any other resources via google.
Can you please provide an example of how to create a .png image in D?
For example, BufferedImage off_Image = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); from http://docs.oracle.com/javase/tutorial/2d/images/drawonimage.html is what I am looking for (I think), except in the D programming language.
I wrote a little lib that can do this too. Grab png.d and color.d from here:
https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff
import arsd.png;
void main() {
// width * height
TrueColorImage image = new TrueColorImage(100, 50);
// fill it in with a gradient
auto colorData = image.imageData.colors; // get a ref to the color array
foreach(y; 0 .. image.height)
foreach(x; 0 .. image.width)
colorData[y * image.width + x] = Color(x * 2, 0, 0); // fill in (r,g,b,a=255)
writePng("test.png", image); // save it to a file
}
There is nothing in standard library for image work but you should be able to use DevIL or FreeImage to do what you want. Both of them have Derelict bindings.
DevIL (derelict-il)
FreeImage (derelict-fi)
Just use the C API documentation for either of them.
There is no standard 2D or 3D graphics API in Phobos, nor there is something similar to the ImageIO API from Java. However, there are plenty of D libraries written by various individuals, as well as various bindings to C/C++ libraries that could aid you in what you are doing. I am sure you should be able to accomplish what you need by using some parts of the GtkD .
I'd like to offer an alternative to Adam's solution - dlib has quite a few modules that come in handy when writing multi-media applications - image manipulation, linear algebra as well as geometry processing, I/O streams done right, basic XML parsing and others. It's still getting some development on the core interfaces (as of February 2014), but that should get pretty stable within a few weeks.
With dlib, that example code would translate to:
import dlib.image;
// width * height
auto image = new Image!(PixelFormat.RGB8)(100, 50);
// fill it in with a gradient
foreach(y; 0 .. image.height)
foreach(x; 0 .. image.width)
image[x, y] = Color4f(x * 2 / 255.0f, 0, 0);
savePNG(image, "test.png");
Grabbing the bytes directly is of course possible too, but why not do it the easier way? Premature optimization, etc.
If you're building your application with dub (which you probably should), using the latest and best of dlib is as simple as adding "dlib": "~master" to your dependencies.

Resize Images crossplattform with node.js

I wrote a little tool with node-webkit. One reason I chose node-webkit is the fact that it is easy to distribute your app to all major plattforms.
Something I would love to do now, is to resize a bunch of images located on the file storage.
I found plenty of packages which do this via ImageMagick. This would require the user to have ImageMagick installed, which is bad...
Using a webservice is no option. There can easily be around 600 images.
If there is no solution, I will only run that task IF imagemagick is installed.
You could use the canvas tag to resize your image.
Load the image in a canvas with the new size:
...
var tempCanvas = document.createElement('canvas');
tempCanvas.width = newWidth;
tempCanvas.height = newHeight;
var ctx = tempCanvas.getContext('2d');
var img = new Image();
img.src = imageSrc;
img.onload = function () {
ctx.drawImage(this, 0, 0);
};
Get resized image back from canvas:
...
var image = canvas.toDataURL('image/png');
image = image.replace('data:image/png;base64,', '');
var buffer = new Buffer(image, 'base64');
fs.writeFile('filename.png', buffer, function (error) {
if (error) {
// TODO handle error
}
});
...
In this example the resulting image will be a png. You can use as result type whatever node-webkit supports. If you have different image types as input and want to output in the same type you need to add some code that sets the correct mime type to canvas.toDataURL.
I am developing an image processing module without any runtime dependencies; which means your users don't need to have imagemagick installed. It's still at early stages, but already usable.
Part of the module is written in C++, so you'll have to make sure to npm install the module on each platform you package your app (better than telling your users to pre-install imagemagick, imho). node-webkit apps are distributed per-platform anyway, so it shouldn't be a problem. Note, though, that I haven't yet tested it with node-webkit,
With this module, resizing an image is as simple as:
image.batch().resize(200, 200).writeFile('output.jpg',function(err){
// done
});
More info at the module's Github repo.

Best way to preload SVG image tags?

I'm building an SVG-based visualization that (partially) relies on showing many images in quick succession. The images can't be fetched fast enough from the network, so they must be preloaded.
My understanding is that SVG doesn't properly cache image tags, at least in major browsers. So JavaScript preloading librairies and techniques (eg. this SO question) won't work. (I could resort to using layered HTML img tags, but because of the specifics of my application, I would like to stick to pure SVG as much as possible)
I see two options:
Encoding the PNG image data as base64, storing it in memory as strings and using the strings to iteratively populate image tags using data:image/png;base64.
Layering many SVG groups on top of each other with all but one set to display: none or visibility: hidden and iteratively unhiding the appropriate group. However, I believe it won't be possible to programatically detect that all images have finished preloading.
What's the best way to preload the image data? Perhaps I've missed an easier option.
I'm not familiar enough with the underlying mechanics of web browsers to know if this will work with svg image tags, but I had success caching images with new Image():
//download low quality images
var imageArray = []
for (var i = 0; i < 600; i++){
imageArray[i] = new Image();
imageArray[i].src = moviePath + (i + 1) + '.jpg.t';
imageArray[i].onload = function(){
var i = this.src.split(movieName + '/')[1].split(".")[0];
d3.select("#bar" + i).style("stroke", 'rgb(' + colors[i].rgb + ')');
}
}
To show an image, I just set the src of the displayed image to one that was already loaded and the browser loads it from its cache.
There is another small trick used later in the source - show a low quality image first and starting loading a high quality one only after a short timeout passes without another image being selected. Then, after the high quality image has loaded, show it only if the same image is still selected.
No idea if these are best practices or anything, but it worked reasonably well.

Resources