magicklib-native
v0.1.2
Published
NodeJS native bindings for ImageMagick's Magick++ library
Downloads
5
Maintainers
Readme
ImageMagick library
ImageMagick Magick++ library bindings for versatile programatic image manipulation.
This is another approach to bring image manipulation capabilities to nodejs. However conceptually it's more like this. You know, "same same, but different".
WARNING:
This is work in progress...
Magicklib provides an Image
object which can be manipulated in both sync and async mode.
The async mode is triggered either by providing callback to utility method as the last argument or
by calling image.begin() to start batch mode.
##Example
###Synchronous example
var Image = require("magicklib-native").Image
var im = new Image("magick.png")
fs.writeFileSync("magick.jpg",
im.resize(100,100, "aspectfill greater").
extent(100,100, "center").
blur(0.3).
format("JPEG").
quality(80).
write()
);
im.close() // free resources before gc does
###Asynchronous batch example
fs.readFile("magick.png", function(err, blob) {
// bail on err
new Image().
begin().
read(blob).
resize(100,100, "aspectfill").
extent(100,100, "center").
blur(0.3).
format("JPEG").
quality(80).
write(function(err, blob) {
// bail on err
fs.writeFile("magick.jpg", blob, function(err) {
// done
});
});
// in batch mode image is being closed by default
});
To enable batch-only mode:
var im = new Image({batch: true}); // or
// no im.begin() needed anymore
// and no more synchronous calls
im.batch = true; // or
im.prop({batch: true}); // or
im.begin(true);
To disable batch-only mode:
var im = new Image({batch: false}); // or
im.batch = false; // or
im.prop({batch: false}); // or
im.end(false); // this also ends any pending commands
###Copy copy
Images may be copied to perform different transformations without reloading from file or blob.
var im = new Image(blob);
var blobsmall = im.copy().
sharpen(0.2).
resize("100x100").
write();
var blobmedium = im.copy().
blur(0.2).
resize("300x300^").
write();
###Streams
var im = new Image({batch: true}).
format("JPEG").
quality(80).
resize(100, 100, "aspectfill").
extent(100, 100, "center")
// create write stream
fs.createReadStream("image.jpg").
pipe(im.createWriteStream());
// create read stream
im.blur(1).createReadStream().pipe(
fs.createWriteStream("out100x100aspectfill_blurred.jpg")
);
im.end(function(err, image) {
// all transformations done and sent down the stream
});
Asynchronous copy + stream == read once, convert many
var im = new Image({batch: true, autoClose: false}).
copy(true). // must be here otherwise restore() will restore empty image
format("JPEG").
quality(80).
resize(100, 100, "aspectfill").
extent(100, 100, "center")
fs.createReadStream("image.jpg").
pipe( im.createConvertStream() ).
pipe( fs.createWriteStream("out100x100.jpg") );
// create as many read streams as needed
im.restore(). // restore copy
resize(300, 500).
createReadStream().pipe(
fs.createWriteStream("out300x500.jpg")
);
im.restore(). // restore copy
sharpen(2).
// a sugar for createReadStream().pipe()
pipe(
fs.createWriteStream("sharpened.jpg")
);
im.close(true); // auto-close image after transformations
Both write and convert streams insert blob reader at the front of the batch queue.
To turn autoCopy mode on:
var im = new Image({src: buffer, autoCopy: true}); // or
im.autoCopy = true; // or
im.prop({autoCopy: true}); // or
im.copy(true);
###Save memory, auto-close
Image is being closed automatically after finishing batch by default, so rss won't grow like crazy between gc sessions.
var im = new Image({batch: true});
im.autoClose == true;
im.read(blob).
blur(0.5).
write(function(err, blob) {
// play with blob
}).
crop(200, 200, 50, 50).
end(function(err, im) {
setImmediate(function() {
// im is closed by now to free Magick memory as soon as possible
im.empty == true
im.size() // => [0, 0]
});
// im is not yet closed, you can play more with it
im.empty == false
});
To turn off auto close:
new Image({autoClose: false}); // or
im.autoClose = false; // or
im.prop({autoClose: false}); // or
im.close(false);
// to close manually
// batch or sync
im.close();
// async
im.close(function(err, im) { /*...*/ });
Closing image doesn't mean one can't use instantiated JS object anymore. On the contrary - close() simply destroys internal Magick memory associated with Image, bringing back JS object to its pristine state as if new magick.Image() was called.
So yes, one can re-use closed images.
Installation
Unix
Requires ImageMagick at least v6.8.7 C++ library and headers.
$ sudo yum install ImageMagick-c++-devel
or
$ sudo apt-get install libmagick++-dev
brew install imagemagick
Magick++-config should be in PATH.
$ npm install magicklib-native
According to imagemagick-native
- RHEL/CentOS: If the version of ImageMagick required is not available in RPM repository, please try the
-last
version offered by Les RPM de Remi, for example:
$ sudo yum remove -y ImageMagick
$ sudo yum install -y http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
$ sudo yum install -y --enablerepo=remi ImageMagick-last-c++-devel
- Mac OS X: You might need to install
pkgconfig
first:
$ brew install pkgconfig
Windows
Tested on Windows 7 x64, Vista x64 and XP x86.
Install Python >= 2.7.3
Install Visual Studio C++ 2010 Express or (Windows 7/8 only) Microsoft Visual Studio C++ 2012/13
(VS 2010 and 64-bit only) Install Windows 7 64-bit SDK and compiler update for the Windows SDK 7.1
Install ImageMagick Q16/Q8 x64/x86 dll and please remember to check "Install development headers and libraries for C and C++" during install. "-static" library versions won't work.
See node-gyp installation for general troubleshooting.
$ npm install magicklib-native
##API
See API.md for more.
##Performance
node --expose-gc test/bench.js test/test.image.jpg
##TODO
- (much) more Magick++ methods