Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gm

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gm - npm Package Compare versions

Comparing version 0.5.0 to 0.6.0

examples/imgs/morpher.jpg

4

History.md
## v0.6.0 - 12/14/2011
* added; stream support [kainosnoema] (#22)
## v0.5.0 - 07/07/2011

@@ -3,0 +7,0 @@

23

index.js

@@ -8,3 +8,3 @@

var escape = require('./lib/utils').escape;
var Stream = require('stream').Stream;

@@ -14,4 +14,4 @@ /**

*
* @param {String|Number} path - path to img source or width of img to create
* @param {Number} [height] - optional height of img to create
* @param {String|Number} path - path to img source or ReadableStream or width of img to create
* @param {Number} [height] - optional filename of ReadableStream or height of img to create
* @param {String} [color] - optional hex background color of created img

@@ -31,3 +31,6 @@ */

if (height) {
if (source instanceof Stream) {
this.sourceStream = source;
source = height || 'unknown.jpg';
} else if (height) {
// new images

@@ -42,5 +45,11 @@ width = source;

}
}
} else {
source = escape(source);
// parse out gif frame brackets from filename
// since stream doesn't use source path
// eg. "filename.gif[0]"
var frames;
if (frames = source.match(/(\[.+\])$/)) {
this.sourceFrames = source.substr(frames.index, frames[0].length);
source = source.substr(0, frames.index);
}

@@ -66,3 +75,3 @@

module.exports = gm;
module.exports.version = "0.5.0";
module.exports.version = "0.6.0";

@@ -15,3 +15,3 @@

// avoid error "geometry does not contain image (unable to crop image)" - gh-17
if (!(this.inputIs('jpg') && ~this._out.indexOf('"-crop"'))) {
if (!(this.inputIs('jpg') && ~this._out.indexOf('-crop'))) {
this.in("-size", w +"x"+ h + options);

@@ -30,4 +30,3 @@ }

proto.noProfile = function noProfile () {
// profile has a lame particularity so we don't escape
this._out.push('+profile "*"');
this.out('+profile', '"*"');
return this;

@@ -60,3 +59,3 @@ }

// avoid error "geometry does not contain image (unable to crop image)" - gh-17
var index = this._in.indexOf('"-size"');
var index = this._in.indexOf('-size');
if (~index) {

@@ -312,6 +311,6 @@ this._in.splice(index, 2);

}
// http://www.graphicsmagick.org/GraphicsMagick.html#details-trim
proto.trim = function trim () {
return this.out("-trim");
return this.out("-trim");
}

@@ -318,0 +317,0 @@ };

@@ -9,3 +9,4 @@

var exec = require('child_process').exec;
var escape = require('./utils').escape;
var spawn = require('child_process').spawn;
var utils = require('./utils');

@@ -25,3 +26,3 @@ /**

for (; i < len; ++i) {
a.push(escape(arguments[i]));
a.push(arguments[i]);
}

@@ -37,2 +38,10 @@

/**
* Execute the command and write the image to the specified file name.
*
* @param {String} name
* @param {Function} callback
* @return {Object} gm
*/
proto.write = function write (name, callback) {

@@ -46,31 +55,128 @@ if (!callback) callback = name, name = null;

if (!name) {
throw new TypeError("gm().write() expects a filename when writing new files")
return callback(TypeError("gm().write() expects a filename when writing new files"));
}
if (name) {
this.outname = escape(name);
this.outname = name;
return this._spawn("gm", this.args(), true, callback);
}
/**
* Execute the command and return stdin and stderr ReadableStreams providing the image data.
*
* @param {Function} callback
* @return {Object} gm
*/
proto.stream = function stream (format, callback) {
if (!callback) callback = format, format = null;
if ("function" !== typeof callback) {
throw new TypeError("gm().stream() expects a callback function")
}
return this._exec(this.cmd(), callback);
if (format) {
format = format.split('.').slice(-1)[0].toUpperCase();
this.outname = format + ":-";
}
return this._spawn("gm", this.args(), false, callback);
}
proto._exec = function _exec (cmd, callback) {
var self = this;
/**
* Execute the command, buffer input and output, return stdout and stderr buffers.
*
* @param {String} bin
* @param {Array} args
* @param {Function} callback
* @return {Object} gm
*/
exec(cmd, function (err, stdout, stderr) {
callback.call(self, err, stdout, stderr, cmd);
});
proto._exec = function _exec (bin, args, callback) {
return this._spawn(bin, args, true, callback);
}
return self;
/**
* Execute the command with stdin, returning stdout and stderr streams or buffers.
*
* @param {String} bin
* @param {Array} args
* @param {ReadableStream} stream
* @param {Boolean} shouldBuffer
* @param {Function} callback
* @return {Object} gm
*/
proto._spawn = function _spawn (bin, args, bufferOutput, callback) {
var proc = spawn(bin, args)
, cmd = bin + " " + args.map(utils.escape).join(' ')
, self = this
, err;
// pipe in the sourceStream if present
if (self.sourceStream) {
if (!self.sourceStream.readable && !self.bufferStream) {
err = new Error("gm().stream() or gm().write() with a non-readable " +
"stream. Pass \"{bufferStream: true}\" to identify() " +
"or getter (size, format, etc...)");
return callback.call(this, err);
}
self.sourceStream.pipe(proc.stdin);
// resume any buffered events from a previous identify operation
if (self.buffer) {
self.buffer.resume();
// if {bufferStream: true} was passed to an identify operation,
// we buffer the input stream events so we can use them again
} else if (self.bufferStream) {
self.buffer = utils.buffer(self.sourceStream);
}
}
// for _exec operations (identify() mostly), we also
// need to buffer the output stream before returning
if (bufferOutput) {
var stdout = ''
, stderr = ''
, onOut
, onErr
, onExit
proc.stdout.addListener('data', onOut = function (data) {
stdout += data;
});
proc.stderr.addListener('data', onErr = function (data) {
stderr += data;
});
proc.addListener('exit', onExit = function (code, signal) {
if (code !== 0 || signal !== null) {
err = new Error('Command failed: ' + stderr);
err.code = code;
err.signal = signal;
};
callback.call(this, err, stdout, stderr, cmd);
stdout = stderr = onOut = onErr = onExit = null;
});
} else {
callback.call(this, null, proc.stdout, proc.stderr, cmd);
}
return this;
}
proto.cmd = function cmd () {
return "gm convert "
+ this._in.join(" ")
+ " "
+ this.source
+ " "
+ this._out.join(" ")
+ " "
+ this.outname || this.source;
proto.args = function args () {
var source = (this.sourceStream ? "-" : this.source);
if (source && this.sourceFrames) source += this.sourceFrames;
return [].concat(
'convert'
, this._in
, source
, this._out
, this.outname || "-"
).filter(Boolean); // remove falsey
}

@@ -83,8 +189,8 @@

var types = {
'jpg': /[\.jpg|\.jpeg]"$/i
, 'png' : /\.png"$/i
, 'gif' : /\.gif"$/i
, 'tiff': /[\.tiff|\.tif]"$/i
, 'bmp' : /[\.bmp|\.dib]"$/i
, 'webp': /\.webp"$/i
'jpg': /[\.jpg|\.jpeg]$/i
, 'png' : /\.png$/i
, 'gif' : /\.gif$/i
, 'tiff': /[\.tiff|\.tif]$/i
, 'bmp' : /[\.bmp|\.dib]$/i
, 'webp': /\.webp$/i
};

@@ -111,3 +217,3 @@

if ('.' !== type[0]) type = '.' + type;
rgx = new RegExp('\\' + type + '"$', 'i');
rgx = new RegExp('\\' + type + '$', 'i');
}

@@ -114,0 +220,0 @@

@@ -5,2 +5,8 @@

/**
* Module dependencies.
*/
var escape = require('./utils').escape;
/**
* Extend proto.

@@ -123,3 +129,3 @@ */

var gravity = String(gravity || "").toLowerCase()
, arg = ["text " + x0 + "," + y0 + ' "' + text + '"'];
, arg = ["text " + x0 + "," + y0 + " " + escape(text)];

@@ -126,0 +132,0 @@ if (~this._gravities.indexOf(gravity)) {

@@ -12,5 +12,6 @@

proto[getter] = function (callback) {
proto[getter] = function (opts, callback) {
if (!callback) callback = opts, opts = {};
var self = this;
if (self.data[getter]) {

@@ -21,3 +22,3 @@ callback.call(self, null, self.data[getter]);

self.identify(function (err, stdout, stderr, cmd) {
self.identify(opts, function (err, stdout, stderr, cmd) {
if (err) {

@@ -34,3 +35,5 @@ return callback.call(self, err, stdout, stderr, cmd);

proto.identify = function identify (callback) {
proto.identify = function identify (opts, callback) {
if (!callback) callback = opts, opts = {};
var self = this;

@@ -40,2 +43,4 @@

self.bufferStream = !! opts.bufferStream;
if (self._identifying) {

@@ -54,5 +59,5 @@ self._iq.push(callback);

var cmd = "gm identify -ping -verbose " + self.source;
var args = ['identify', '-ping', '-verbose', self.sourceStream ? '-' : self.source];
self._exec(cmd, function (err, stdout, stderr) {
self._exec("gm", args, function (err, stdout, stderr) {
if (err) {

@@ -59,0 +64,0 @@ return callback.call(self, err, stdout, stderr, cmd);

@@ -15,1 +15,48 @@

}
/**
* Buffer `data` and `end` events from the given stream `obj`.
*
* @param {Stream} obj
* @api public
*/
// __Attribution:__ Taken from node-http-proxy's stream buffer implementation
// https://github.com/nodejitsu/node-http-proxy/blob/9f05e6c567/lib/node-http-proxy.js#L223-256
// https://github.com/nodejitsu/node-http-proxy/blob/9f05e6c567/LICENSE
exports.buffer = function (obj) {
var events = []
, onData
, onEnd;
obj.on('data', onData = function (data, encoding) {
events.push(['data', data, encoding]);
});
obj.on('end', onEnd = function (data, encoding) {
events.push(['end', data, encoding]);
});
return {
end: function () {
obj.removeListener('data', onData);
obj.removeListener('end', onEnd);
}
, destroy: function () {
this.end();
this.resume = function () {
console.error("Cannot resume buffer after destroying it.");
};
onData = onEnd = events = obj = null;
}
, resume: function () {
this.end();
for (var i = 0, len = events.length; i < len; ++i) {
obj.emit.apply(obj, events[i]);
}
}
};
};
{ "name": "gm"
, "description": "Graphics Magick for node."
, "version": "0.5.0"
, "version": "0.6.0"
, "author": "Aaron Heckmann <aaron.heckmann+github@gmail.com>"
, "keywords": ["nodejs", "graphics magick", "graphics", "magick", "image"]
, "engines": { "node": ">= 0.1.96" }
, "engines": { "node": ">= 0.4.2" }
, "bugs": "http://github.com/aheckmann/gm/issues"

@@ -20,3 +20,4 @@ , "licenses": [{ "type": "MIT", "url": "http://www.opensource.org/licenses/mit-license.php"}]

"should": "0.2.1"
, "gleak": "0.2.2"
}
}
# gm
GraphicsMagick for node
var gm = require('./gm');
// resize and remove EXIF profile data
gm('/path/to/my/img.jpg')
.resize(240, 240)
.noProfile()
.write('/path/to/resize.png', function (err) {
if (!err) console.log('done');
});
## Basic Usage
```` js
var fs = require('fs')
, gm = require('./gm');
// obtain the size of an image
gm('/path/to/my/img.jpg')
.size(function (err, size) {
if (!err)
console.log(size.width > size.height ? 'wider' : 'taller than you');
});
// resize and remove EXIF profile data
gm('/path/to/my/img.jpg')
.resize(240, 240)
.noProfile()
.write('/path/to/resize.png', function (err) {
if (!err) console.log('done');
});
// output all available image properties
gm('/path/to/img.png')
.identify(function (err, data) {
if (!err) console.dir(data)
});
// obtain the size of an image
gm('/path/to/my/img.jpg')
.size(function (err, size) {
if (!err)
console.log(size.width > size.height ? 'wider' : 'taller than you');
});
// pull out the first frame of an animated gif and save as png
gm('/path/to/animated.gif[0]')
.write('/path/to/firstframe.png', function (err) {
if (err) console.log('aaw, shucks');
});
// output all available image properties
gm('/path/to/img.png')
.identify(function (err, data) {
if (!err) console.dir(data)
});
// crazytown
gm('/path/to/my/img.jpg')
.flip()
.magnify()
.rotate('green', 45)
.blur(7, 3)
.crop(300, 300, 150, 130)
.edge(3)
.write('/path/to/crazy.jpg', function (err) {
if (!err) console.log('crazytown has arrived');
})
// pull out the first frame of an animated gif and save as png
gm('/path/to/animated.gif[0]')
.write('/path/to/firstframe.png', function (err) {
if (err) console.log('aaw, shucks');
});
// annotate an image
gm('/path/to/my/img.jpg')
.stroke("#ffffff")
.drawCircle(10, 10, 20, 10)
.font("Helvetica.ttf", 12)
.drawText(30, 20, "GMagick!")
.write("/path/to/drawing.png", function (err) {
if (!err) console.log('done');
});
// crazytown
gm('/path/to/my/img.jpg')
.flip()
.magnify()
.rotate('green', 45)
.blur(7, 3)
.crop(300, 300, 150, 130)
.edge(3)
.write('/path/to/crazy.jpg', function (err) {
if (!err) console.log('crazytown has arrived');
})
// creating an image
gm(200, 400, "#ddff99f3")
.drawText(10, 50, "from scratch")
.write("/path/to/brandNewImg.jpg", function (err) {
// ...
});
// annotate an image
gm('/path/to/my/img.jpg')
.stroke("#ffffff")
.drawCircle(10, 10, 20, 10)
.font("Helvetica.ttf", 12)
.drawText(30, 20, "GMagick!")
.write("/path/to/drawing.png", function (err) {
if (!err) console.log('done');
});
// creating an image
gm(200, 400, "#ddff99f3")
.drawText(10, 50, "from scratch")
.write("/path/to/brandNewImg.jpg", function (err) {
// ...
});
````
## Image paths or Streams
```` js
// can provide either a file path or a ReadableStream
// (from a local file or incoming network request)
var readStream = fs.createReadStream('/path/to/my/img.jpg');
gm(readStream, 'img.jpg')
.write('/path/to/reformat.png', function (err) {
if (!err) console.log('done');
});
// can also stream output to a ReadableStream
// (can be piped to a local file or remote server)
gm('/path/to/my/img.jpg')
.resize('200', '200')
.stream(function (err, stdout, stderr) {
var writeStream = fs.createWriteStream('/path/to/my/resized.jpg');
stdout.pipe(writeStream);
});
// pass a format or filename to stream() and
// gm will provide image data in that format
gm('/path/to/my/img.jpg')
.stream('png', function (err, stdout, stderr) {
var writeStream = fs.createWriteStream('/path/to/my/reformated.png');
stdout.pipe(writeStream);
});
// combine the two for true streaming image processing
var readStream = fs.createReadStream('/path/to/my/img.jpg');
gm(readStream, 'img.jpg')
.resize('200', '200')
.stream(function (err, stdout, stderr) {
var writeStream = fs.createWriteStream('/path/to/my/resized.jpg');
stdout.pipe(writeStream);
});
// when working with input streams and any 'identify'
// operation (size, format, etc), you must pass "{bufferStream: true}" if
// you also need to convert (write() or stream()) the image afterwards
// NOTE: this temporarily buffers the image stream in Node memory
var readStream = fs.createReadStream('/path/to/my/img.jpg');
gm(readStream, 'img.jpg')
.size({bufferStream: true}, function(err, size) {
this.resize(size.width / 2, size.height / 2)
this.write('/path/to/resized.jpg', function (err) {
if (!err) console.log('done');
});
});
````
## Getting started

@@ -83,4 +138,4 @@ First download and install [GraphicsMagick](http://www.graphicsmagick.org/)

- 1) `gm(path)` When you pass a string as the first argument it is interpreted as the path to an image you intend to manipulate.
- 2) `gm(width, height)` When you pass two arguments it tells gm to create a new image on the fly with the provided dimensions. And you can still chain just like you do with pre-existing images too. See [here](http://github.com/aheckmann/gm/blob/master/examples/new.js) for an example.
- 3) `gm(width, height, color)` The same as #2 but you may also specify a background color for the created image.
- 2) `gm(stream, [filename])` You may also pass a ReadableStream as the first argument, with an optional file name for format inference.
- 3) `gm(width, height, [color])` When you pass two integer arguments, gm will create a new image on the fly with the provided dimensions and an optional background color. And you can still chain just like you do with pre-existing images too. See [here](http://github.com/aheckmann/gm/blob/master/examples/new.js) for an example.

@@ -170,5 +225,8 @@ ## Methods

- image output
- **write** - writes the processed image data to the specified filename
- **stream** - provides a ReadableStream with the processed image data
## Node version
Compatible with > v0.1.96
## Contributors
[https://github.com/aheckmann/gm/contributors](https://github.com/aheckmann/gm/contributors)

@@ -175,0 +233,0 @@ ## Inspiration

@@ -5,4 +5,19 @@

var dir = __dirname + '/../examples/imgs';
var gm = require('../')
var gm = require('../');
var assert = require('assert');
var gleak = require('gleak')();
var fs = require('fs');
var files = fs.readdirSync(__dirname).filter(filter);
var pending, total = pending = files.length;
function filter (file) {
if (!/\.js$/.test(file)) return false;
if ('index.js' === file) return false;
var filename = __dirname + '/' + file;
if (!fs.statSync(filename).isFile()) return false;
return true;
}
function test () {

@@ -12,17 +27,28 @@ return gm(dir + '/original.jpg');

var fs = require('fs');
function finish (filename) {
return function (err) {
if (err) throw new Error(err);
fs.readdirSync(__dirname).forEach(function (file) {
if (!/\.js$/.test(file)) return;
if ('index.js' === file) return;
--pending;
process.stderr.write(
'\u001B[30m'
+ (new Array(total - pending)).join('√')
+ '\u001B[0m'
+ '\u001B[30m'
+ (new Array(pending)).join('░')
+ '\u001B[0m'
+ '\r'
);
var filename = __dirname + '/' + file;
if (pending) return;
if (!fs.statSync(filename).isFile()) return;
var leaks = gleak.detect();
assert.equal(0, leaks.length, "global leaks detected: " + leaks);
console.error("\n\u001B[32mAll tests passed\u001B[0m")
}
}
require(filename)(test(), dir, finish, gm);
files.forEach(function (file) {
var filename = __dirname + '/' + file;
require(filename)(test(), dir, finish(filename), gm);
});
function finish (err) {
if (err) throw new Error(err);
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc