convert = function (args, timeout, callback) {
var procopt = {encoding: 'binary'};
if (typeof timeout === 'function') {
callback = timeout;
timeout = 0;
} else if (typeof timeout !== 'number') {
timeout = 0;
}
if (timeout && (timeout = parseInt(timeout)) > 0 && !isNaN(timeout))
procopt.timeout = timeout;
return exec2(exports.convert.path, args, procopt, callback);
}...
### convert(args, callback(err, stdout, stderr))
Raw interface to `convert` passing arguments in the array `args`.
Example:
```javascript
im.convert(['kittens.jpg', '-resize', '25x120', 'kittens
-small.jpg'],
function(err, stdout){
if (err) throw err;
console.log('stdout:', stdout);
});
```
### resize(options, callback(err, stdout, stderr))
...crop = function (options, callback) {
if (typeof options !== 'object')
throw new TypeError('First argument must be an object');
if (!options.srcPath && !options.srcData)
throw new TypeError("No srcPath or data defined");
if (!options.height && !options.width)
throw new TypeError("No width or height defined");
if (options.srcPath){
var args = options.srcPath;
} else {
var args = {
data: options.srcData
};
}
exports.identify(args, function(err, meta) {
if (err) return callback && callback(err);
var t = exports.resizeArgs(options),
ignoreArg = false,
printNext = false,
args = [];
t.args.forEach(function (arg) {
if (printNext === true){
console.log("arg", arg);
printNext = false;
}
// ignoreArg is set when resize flag was found
if (!ignoreArg && (arg != '-resize'))
args.push(arg);
// found resize flag! ignore the next argument
if (arg == '-resize'){
console.log("resize arg");
ignoreArg = true;
printNext = true;
}
if (arg === "-crop"){
console.log("crop arg");
printNext = true;
}
// found the argument after the resize flag; ignore it and set crop options
if ((arg != "-resize") && ignoreArg) {
var dSrc = meta.width / meta.height,
dDst = t.opt.width / t.opt.height,
resizeTo = (dSrc < dDst) ? ''+t.opt.width+'x' : 'x'+t.opt.height,
dGravity = options.gravity ? options.gravity : "Center";
args = args.concat([
'-resize', resizeTo,
'-gravity', dGravity,
'-crop', ''+t.opt.width + 'x' + t.opt.height + '+0+0',
'+repage'
]);
ignoreArg = false;
}
})
t.args = args;
resizeCall(t, callback);
})
}...
### crop(options, callback) ###
Convenience function for resizing and cropping an image. _crop_ uses the resize method, so _options_ and _callback_ are the same
. _crop_ uses _options.srcPath_, so make sure you set it :) Using only _options.width_ or _options.height_ will create a square
dimensioned image. Gravity can also be specified, it defaults to Center. Available gravity options are [NorthWest, North, NorthEast
, West, Center, East, SouthWest, South, SouthEast]
Example:
```javascript
im.crop({
srcPath: path,
dstPath: 'cropped.jpg',
width: 800,
height: 600,
quality: 1,
gravity: "North"
}, function(err, stdout, stderr){
...identify = function (pathOrArgs, callback) {
var isCustom = Array.isArray(pathOrArgs),
isData,
args = isCustom ? ([]).concat(pathOrArgs) : ['-verbose', pathOrArgs];
if (typeof args[args.length-1] === 'object') {
isData = true;
pathOrArgs = args[args.length-1];
args[args.length-1] = '-';
if (!pathOrArgs.data)
throw new Error('first argument is missing the "data" member');
} else if (typeof pathOrArgs === 'function') {
args[args.length-1] = '-';
callback = pathOrArgs;
}
var proc = exec2(exports.identify.path, args, {timeout:120000}, function(err, stdout, stderr) {
var result, geometry;
if (!err) {
if (isCustom) {
result = stdout;
} else {
result = parseIdentify(stdout);
geometry = result['geometry'].split(/x/);
result.format = result.format.match(/\S*/)[0]
result.width = parseInt(geometry[0]);
result.height = parseInt(geometry[1]);
result.depth = parseInt(result.depth);
if (result.quality !== undefined) result.quality = parseInt(result.quality) / 100;
}
}
callback(err, result);
});
if (isData) {
if ('string' === typeof pathOrArgs.data) {
proc.stdin.setEncoding('binary');
proc.stdin.write(pathOrArgs.data, 'binary');
proc.stdin.end();
} else {
proc.stdin.end(pathOrArgs.data);
}
}
return proc;
}...
### identify(path, callback(err, features))
Identify file at `path` and return an object `features`.
Example:
```javascript
im.identify('kittens.jpg', function(err, features){
if (err) throw err;
console.log(features);
// { format: 'JPEG', width: 3904, height: 2622, depth: 8 }
});
```
### identify(args, callback(err, output))
...readMetadata = function (path, callback) {
return exports.identify(['-format', '%[EXIF:*]', path], function(err, stdout) {
var meta = {};
if (!err) {
stdout.split(/\n/).forEach(function(line){
var eq_p = line.indexOf('=');
if (eq_p === -1) return;
var key = line.substr(0, eq_p).replace('/','-'),
value = line.substr(eq_p+1).trim(),
typekey = 'default';
var p = key.indexOf(':');
if (p !== -1) {
typekey = key.substr(0, p);
key = key.substr(p+1);
if (typekey === 'exif') {
key = exifKeyName(key);
var converter = exifFieldConverters[key];
if (converter) value = converter(value);
}
}
if (!(typekey in meta)) meta[typekey] = {key:value};
else meta[typekey][key] = value;
})
}
callback(err, meta);
});
}...
Requires imagemagick CLI tools to be installed. There are numerous ways to install them. For instance, if you're on OS X you
can use [Homebrew](http://mxcl.github.com/homebrew/): `brew install imagemagick`.
## Example
```javascript
var im = require('imagemagick');
im.readMetadata('kittens.jpg', function(err, metadata){
if (err) throw err;
console.log('Shot at '+metadata.exif.dateTimeOriginal);
})
// -> Shot at Tue, 06 Feb 2007 21:13:54 GMT
```
## API
...resize = function (options, callback) {
var t = exports.resizeArgs(options);
return resizeCall(t, callback)
}...
```
srcPath, dstPath and (at least one of) width and height are required. The rest is optional.
Example:
```javascript
im.resize({
srcPath: 'kittens.jpg',
dstPath: 'kittens-small.jpg',
width: 256
}, function(err, stdout, stderr){
if (err) throw err;
console.log('resized kittens.jpg to fit within 256x256px');
});
...resizeArgs = function (options) {
var opt = {
srcPath: null,
srcData: null,
srcFormat: null,
dstPath: null,
quality: 0.8,
format: 'jpg',
progressive: false,
colorspace: null,
width: 0,
height: 0,
strip: true,
filter: 'Lagrange',
sharpening: 0.2,
customArgs: [],
timeout: 0
}
// check options
if (typeof options !== 'object')
throw new Error('first argument must be an object');
for (var k in opt) if (k in options) opt[k] = options[k];
if (!opt.srcPath && !opt.srcData)
throw new Error('both srcPath and srcData are empty');
// normalize options
if (!opt.format) opt.format = 'jpg';
if (!opt.srcPath) {
opt.srcPath = (opt.srcFormat ? opt.srcFormat +':-' : '-'); // stdin
}
if (!opt.dstPath)
opt.dstPath = (opt.format ? opt.format+':-' : '-'); // stdout
if (opt.width === 0 && opt.height === 0)
throw new Error('both width and height can not be 0 (zero)');
// build args
var args = [opt.srcPath];
if (opt.sharpening > 0) {
args = args.concat([
'-set', 'option:filter:blur', String(1.0-opt.sharpening)]);
}
if (opt.filter) {
args.push('-filter');
args.push(opt.filter);
}
if (opt.strip) {
args.push('-strip');
}
if (opt.width || opt.height) {
args.push('-resize');
if (opt.height === 0) args.push(String(opt.width));
else if (opt.width === 0) args.push('x'+String(opt.height));
else args.push(String(opt.width)+'x'+String(opt.height));
}
opt.format = opt.format.toLowerCase();
var isJPEG = (opt.format === 'jpg' || opt.format === 'jpeg');
if (isJPEG && opt.progressive) {
args.push('-interlace');
args.push('plane');
}
if (isJPEG || opt.format === 'png') {
args.push('-quality');
args.push(Math.round(opt.quality * 100.0).toString());
}
else if (opt.format === 'miff' || opt.format === 'mif') {
args.push('-quality');
args.push(Math.round(opt.quality * 9.0).toString());
}
if (opt.colorspace) {
args.push('-colorspace');
args.push(opt.colorspace);
}
if (Array.isArray(opt.customArgs) && opt.customArgs.length)
args = args.concat(opt.customArgs);
args.push(opt.dstPath);
return {opt:opt, args:args};
}...
proc.stdin.end(t.opt.srcData);
}
}
return proc;
}
exports.resize = function(options, callback) {
var t = exports.resizeArgs(options);
return resizeCall(t, callback)
}
exports.crop = function (options, callback) {
if (typeof options !== 'object')
throw new TypeError('First argument must be an object');
if (!options.srcPath && !options.srcData)
...