imagemagick-stream
Advanced tools
Comparing version 3.0.0 to 4.0.0
458
index.js
@@ -1,292 +0,264 @@ | ||
var PassThrough = require('stream').PassThrough; | ||
var spawn = require('child_process').spawn; | ||
var Duplexify = require('duplexify'); | ||
var util = require('util'); | ||
var isError = util.isError; | ||
var inherit = util.inherits; | ||
var fs = require('fs'); | ||
"use strict"; | ||
/** | ||
* Expose `ImageMagick` | ||
*/ | ||
const spawn = require('child_process').spawn; | ||
const isError = require('util').isError; | ||
const Duplexify = require('duplexify'); | ||
const fs = require('fs'); | ||
module.exports = ImageMagick; | ||
const operators = Symbol(); | ||
const settings = Symbol(); | ||
/** | ||
* Constructor | ||
* | ||
* @param {String} src | ||
* @api public | ||
*/ | ||
class ImageMagick extends Duplexify { | ||
function ImageMagick (src) { | ||
if (!(this instanceof ImageMagick)) return new ImageMagick(src); | ||
/** | ||
* Constructor | ||
* | ||
* @param {String} src | ||
* @api public | ||
*/ | ||
this.input = '-'; | ||
this.output = '-'; | ||
this._operations = []; | ||
this._settings = []; | ||
constructor (src) { | ||
super(); | ||
this.input = '-'; | ||
this.output = '-'; | ||
this[operators] = []; | ||
this[settings] = []; | ||
if (src) this.from(src); | ||
} | ||
this.spawn = this.spawn.bind(this); | ||
this.onerror = this.onerror.bind(this); | ||
/** | ||
* Resume | ||
*/ | ||
Duplexify.call(this); | ||
resume () { | ||
this.spawn(); | ||
super.resume(); | ||
} | ||
if (src) this.from(src); | ||
setImmediate(this.spawn); | ||
} | ||
/** | ||
* Sets the input file format | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Inherit from `Duplexify` | ||
*/ | ||
inputFormat (args) { | ||
this.input = `${args}:-`; | ||
return this; | ||
} | ||
inherit(ImageMagick, Duplexify); | ||
/** | ||
* Sets the output file format | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the input file format | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
outputFormat (args) { | ||
this.output = `${args}:-`; | ||
return this; | ||
} | ||
ImageMagick.prototype.inputFormat = function (args) { | ||
this.input = args + ':-'; | ||
return this; | ||
}, | ||
/** | ||
* Sets the `quality` option | ||
* | ||
* @param {String|Number} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the output file format | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
quality (args) { | ||
this[operators].push('-quality', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.outputFormat = function (args) { | ||
this.output = args + ':-'; | ||
return this; | ||
}; | ||
/** | ||
* Sets the `resize` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `quality` option | ||
* | ||
* @param {String|Number} args | ||
* @api public | ||
*/ | ||
resize (args) { | ||
this[operators].push('-resize', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.quality = function (args) { | ||
this._operations.push('-quality', args); | ||
return this; | ||
}; | ||
/** | ||
* Sets the `scale` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `resize` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
scale (args) { | ||
this[operators].push('-scale', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.resize = function (args) { | ||
this._operations.push('-resize', args); | ||
return this; | ||
}; | ||
/** | ||
* Sets the `crop` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `scale` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
crop (args) { | ||
this[operators].push('-crop', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.scale = function (args) { | ||
this._operations.push('-scale', args); | ||
return this; | ||
}; | ||
/** | ||
* Sets the `gravity` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `crop` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
gravity (args) { | ||
this[operators].push('-gravity', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.crop = function (args) { | ||
this._operations.push('-crop', args); | ||
return this; | ||
}; | ||
/** | ||
* Sets the `thumbnail` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `gravity` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
thumbnail (args) { | ||
this[operators].push('-thumbnail', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.gravity = function (args) { | ||
this._operations.push('-gravity', args); | ||
return this; | ||
}; | ||
/** | ||
* Sets the `auto-orient` option | ||
* | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `thumbnail` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
autoOrient () { | ||
this[operators].push('-auto-orient'); | ||
return this; | ||
} | ||
ImageMagick.prototype.thumbnail = function (args) { | ||
this._operations.push('-thumbnail', args); | ||
return this; | ||
}; | ||
/** | ||
* Sets the `type` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `auto-orient` option | ||
* | ||
* @api public | ||
*/ | ||
type (args) { | ||
this[operators].push('-type', args); | ||
return this; | ||
} | ||
ImageMagick.prototype.autoOrient = function () { | ||
this._operations.push('-auto-orient'); | ||
return this; | ||
}; | ||
/** | ||
* Passes additional settings | ||
* | ||
* @param {String} key | ||
* @param {Mixed} val | ||
* @api public | ||
*/ | ||
/** | ||
* Sets the `type` option | ||
* | ||
* @param {String} args | ||
* @api public | ||
*/ | ||
set (key, val) { | ||
this[settings].push(`-${key}`); | ||
if (val != null) this[settings].push(val); | ||
return this; | ||
} | ||
ImageMagick.prototype.type = function (args) { | ||
this._operations.push('-type', args); | ||
return this; | ||
}; | ||
/** | ||
* Passes additional operators | ||
* | ||
* @param {String} key | ||
* @param {Mixed} val | ||
* @api public | ||
*/ | ||
/** | ||
* Passes additional settings | ||
* | ||
* @param {String|Object} key | ||
* @param {Mixed} val | ||
* @api public | ||
*/ | ||
op (key, val) { | ||
this[operators].push(`-${key}`); | ||
if (val != null) this[operators].push(val); | ||
return this; | ||
} | ||
ImageMagick.prototype.settings = | ||
ImageMagick.prototype.set = function (key, val) { | ||
this.freehand('_settings', key, val); | ||
return this; | ||
} | ||
/** | ||
* Read image data from path | ||
* | ||
* @param {String} path | ||
* @api public | ||
*/ | ||
/** | ||
* Passes additional operations | ||
* | ||
* @param {String|Object} key | ||
* @param {Mixed} val | ||
* @api public | ||
*/ | ||
from (path) { | ||
const read = fs.createReadStream(path); | ||
read.on('error', this.onerror); | ||
read.pipe(this); | ||
return this; | ||
} | ||
ImageMagick.prototype.operations = | ||
ImageMagick.prototype.op = function (key, val) { | ||
this.freehand('_operations', key, val); | ||
return this; | ||
}; | ||
/** | ||
* Write image data to path | ||
* | ||
* @param {String} path | ||
* @return {Stream} writable stream | ||
* @api public | ||
*/ | ||
/** | ||
* Read image data from path | ||
* | ||
* @param {String} path | ||
* @api public | ||
*/ | ||
to (path) { | ||
const write = fs.createWriteStream(path); | ||
write.on('error', this.onerror); | ||
this.pipe(write); | ||
return write; | ||
} | ||
ImageMagick.prototype.from = function (path) { | ||
var read = fs.createReadStream(path); | ||
read.on('error', this.onerror); | ||
read.pipe(this); | ||
return this; | ||
}; | ||
/** | ||
* Spawn `convert` | ||
* | ||
* @api private | ||
*/ | ||
/** | ||
* Write image data to path | ||
* | ||
* @param {String} path | ||
* @return {Stream} writable stream | ||
* @api public | ||
*/ | ||
spawn () { | ||
const proc = spawn('convert', this.args()); | ||
ImageMagick.prototype.to = function (path) { | ||
var write = fs.createWriteStream(path); | ||
write.on('error', this.onerror); | ||
this.pipe(write); | ||
return write; | ||
}; | ||
const stdout = proc.stdout; | ||
stdout.on('error', (e) => this.onerror(e)); | ||
this.setReadable(stdout); | ||
/** | ||
* Spawn `convert` | ||
* | ||
* @api private | ||
*/ | ||
const stdin = proc.stdin; | ||
stdin.on('error', (e) => this.onerror(e)); | ||
this.setWritable(stdin); | ||
ImageMagick.prototype.spawn = function () { | ||
var proc = spawn('convert', this.args()); | ||
const stderr = proc.stderr; | ||
stderr.on('data', this.onerror); | ||
stderr.on('error', (e) => this.onerror(e)); | ||
} | ||
var stdout = proc.stdout; | ||
stdout.on('error', this.onerror); | ||
this.setReadable(stdout); | ||
/** | ||
* Constructs args for cli call | ||
* | ||
* @api private | ||
*/ | ||
var stdin = proc.stdin; | ||
stdin.on('error', this.onerror); | ||
this.setWritable(stdin); | ||
args () { | ||
return this[settings].concat([this.input], this[operators], [this.output]); | ||
} | ||
var stderr = proc.stderr; | ||
stderr.on('data', this.onerror); | ||
stderr.on('error', this.onerror); | ||
/** | ||
* Re-emit errors | ||
* | ||
* @param {Error|Buffer} err | ||
* @api private | ||
*/ | ||
this.emit('spawn', proc); | ||
}; | ||
/** | ||
* Helper for freehand settings and operations | ||
* | ||
* @param {String} key | ||
* @param {String|Object} obj | ||
* @param {Mixed} [val] | ||
* @api private | ||
*/ | ||
ImageMagick.prototype.freehand = function (key, op, val) { | ||
var self = this; | ||
if (typeof op == 'string') { | ||
return push(key, op, val); | ||
} | ||
Object.keys(op).forEach(function (prop) { | ||
push(key, prop, op[prop]); | ||
}); | ||
function push (key, op, val) { | ||
self[key].push('-' + op); | ||
if (val != null) self[key].push(val); | ||
} | ||
}; | ||
/** | ||
* Constructs args for cli call | ||
* | ||
* @api private | ||
*/ | ||
ImageMagick.prototype.args = function() { | ||
return this._settings.concat([this.input], this._operations, [this.output]); | ||
onerror (err) { | ||
if (!isError(err)) err = new Error(err); | ||
if (!this.listeners('error')) throw err; | ||
this.emit('error', err); | ||
} | ||
} | ||
/** | ||
* Re-emit errors | ||
* | ||
* @param {Error|Buffer} err | ||
* @api private | ||
* Expose factory method. | ||
*/ | ||
ImageMagick.prototype.onerror = function (err) { | ||
if (!isError(err)) err = new Error(err); | ||
if (!this.listeners('error')) throw err; | ||
this.emit('error', err); | ||
}; | ||
module.exports = (src) => new ImageMagick(src); |
{ | ||
"name": "imagemagick-stream", | ||
"version": "3.0.0", | ||
"version": "4.0.0", | ||
"description": "Streaming Imagemagick api", | ||
@@ -12,3 +12,3 @@ "keywords": [ | ||
"scripts": { | ||
"test": "make test" | ||
"test": "./node_modules/.bin/mocha --reporter spec" | ||
}, | ||
@@ -15,0 +15,0 @@ "dependencies": { |
@@ -8,20 +8,18 @@ # imagemagick-stream | ||
## Use | ||
## Install | ||
$ npm install imagemagick-stream | ||
## Usage | ||
```js | ||
var im = require('imagemagick-stream'); | ||
var read = fs.createReadStream('image.png'); | ||
var write = fs.createWriteStream('image-resized.png'); | ||
const im = require('imagemagick-stream'); | ||
const read = fs.createReadStream('image.png'); | ||
const write = fs.createWriteStream('image-resized.png'); | ||
var resize = im().resize('200x200').quality(90); | ||
const resize = im().resize('200x200').quality(90); | ||
read.pipe(resize).pipe(write); | ||
``` | ||
// Alternatively | ||
im('image.png') | ||
.resize('200x200') | ||
.quality(90) | ||
.pipe(write); | ||
For convenience, you can also pass the input filename to the constructor and the output filename to the `.to()` method. | ||
// Or | ||
```js | ||
im('image.png') | ||
@@ -33,3 +31,4 @@ .resize('200x200') | ||
For freehand settings and operations, use `.op()` and `.set()`. | ||
To use settings and operators that are not currently part of the API, please submit a pull request, or use the `.set()` and `.op()` methods. | ||
See the [imagemagick docs](http://www.imagemagick.org/script/convert.php) for a list of available options. | ||
@@ -47,8 +46,10 @@ | ||
**NOTE:** You shold listen to the `finish` event on the writable stream you're piping to, not the stream from ImageMagick: | ||
```js | ||
var read = fs.createReadStream('image.png'); | ||
var write = fs.createWriteStream('image-resized.png'); | ||
var resize = im().resize('200x200').quality(90); | ||
const read = fs.createReadStream('image.png'); | ||
const write = fs.createWriteStream('image-resized.png'); | ||
write.on('finish', function () { | ||
im().resize('200x200').quality(90).pipe(write); | ||
write.on('finish', () => { | ||
// finished writing | ||
@@ -55,0 +56,0 @@ }); |
@@ -31,2 +31,3 @@ var assert = require('assert'); | ||
img.end(); | ||
img.resume(); | ||
img.on('error', function (err) { | ||
@@ -65,8 +66,16 @@ assert(/^convert/.test(err.message)); | ||
describe('.spawn()', function () { | ||
it('should call .spawn() with setImmediate', function (done) { | ||
im().on('spawn', function (proc) { | ||
assert(proc.stdin); | ||
assert(proc.stdout); | ||
it('should call .spawn() when stream is flowing', function (done) { | ||
var img = im(); | ||
var size = 0; | ||
fs.createReadStream(__dirname + '/test.jpg').pipe(img); | ||
img.on('data', function (chunk) { | ||
size += chunk.byteSize; | ||
}); | ||
img.on('end', function () { | ||
assert(size != 0); | ||
done(); | ||
}); | ||
}) | ||
}); | ||
@@ -164,5 +173,5 @@ | ||
it('should set the input format', function () { | ||
var img = im().inputFormat('test'); | ||
var img = im().inputFormat('jpg'); | ||
var args = img.args(); | ||
assert(args[0] == 'test:-'); | ||
assert(args[0] == 'jpg:-'); | ||
}); | ||
@@ -173,5 +182,5 @@ }); | ||
it('should set the output format', function () { | ||
var img = im().outputFormat('test'); | ||
var img = im().outputFormat('jpg'); | ||
var args = img.args(); | ||
assert(args[1] == 'test:-'); | ||
assert(args[1] == 'jpg:-'); | ||
}); | ||
@@ -192,24 +201,4 @@ }); | ||
}); | ||
it('should accept an object', function () { | ||
var img = im().op({ | ||
'gaussian-blur': 0.05, | ||
'interlace': 'Plane' | ||
}); | ||
var args = img.args(); | ||
assert(args[1] == '-gaussian-blur'); | ||
assert(args[2] == '0.05'); | ||
assert(args[3] == '-interlace'); | ||
assert(args[4] == 'Plane'); | ||
}); | ||
}); | ||
describe('.operations()', function () { | ||
it('should alias .op()', function () { | ||
var img = im(); | ||
assert(img.op === img.operations); | ||
}); | ||
}); | ||
describe('.set()', function() { | ||
@@ -230,17 +219,2 @@ it('should accept a key-value pair', function() { | ||
it('should accept an object', function() { | ||
var img = im().set({ | ||
'density': 500, | ||
'channel': 'RGB' | ||
}); | ||
var args = img.args(); | ||
assert(args[0] == '-density'); | ||
assert(args[1] == 500); | ||
assert(args[2] == '-channel'); | ||
assert(args[3] == 'RGB'); | ||
assert(args[4] == '-'); | ||
assert(args[5] == '-'); | ||
}); | ||
it('should be combinable with freehand operations', function() { | ||
@@ -260,9 +234,2 @@ var img = im(); | ||
}); | ||
describe('.settings()', function () { | ||
it('should alias .set()', function () { | ||
var img = im(); | ||
assert(img.set === img.settings); | ||
}) | ||
}) | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
59
43057
7
418