Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

using -format for identify to get more robust results #35

Open
wants to merge 2 commits into from

1 participant

@naltatis

I was having issues with filenames that contained spaces.

Here is the documentation of identify's format option. Could be helpful if for future additions.
http://www.imagemagick.org/script/escape.php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 9, 2012
  1. @naltatis
Commits on Sep 11, 2012
  1. @naltatis
This page is out of date. Refresh to see the latest.
Showing with 41 additions and 132 deletions.
  1. +41 −132 imagemagick.js
View
173 imagemagick.js
@@ -1,139 +1,46 @@
-var childproc = require('child_process'),
- EventEmitter = require('events').EventEmitter;
-
-
-function exec2(file, args /*, options, callback */) {
- var options = { encoding: 'utf8'
- , timeout: 0
- , maxBuffer: 500*1024
- , killSignal: 'SIGKILL'
- , output: null
- };
-
- var callback = arguments[arguments.length-1];
- if ('function' != typeof callback) callback = null;
-
- if (typeof arguments[2] == 'object') {
- var keys = Object.keys(options);
- for (var i = 0; i < keys.length; i++) {
- var k = keys[i];
- if (arguments[2][k] !== undefined) options[k] = arguments[2][k];
- }
- }
-
- var child = childproc.spawn(file, args);
- var killed = false;
- var timedOut = false;
-
- var Wrapper = function(proc) {
- this.proc = proc;
- this.stderr = new Accumulator();
- proc.emitter = new EventEmitter();
- proc.on = proc.emitter.on.bind(proc.emitter);
- this.out = proc.emitter.emit.bind(proc.emitter, 'data');
- this.err = this.stderr.out.bind(this.stderr);
- this.errCurrent = this.stderr.current.bind(this.stderr);
- };
- Wrapper.prototype.finish = function(err) {
- this.proc.emitter.emit('end', err, this.errCurrent());
- };
-
- var Accumulator = function(cb) {
- this.stdout = {contents: ""};
- this.stderr = {contents: ""};
- this.callback = cb;
-
- var limitedWrite = function(stream) {
- return function(chunk) {
- stream.contents += chunk;
- if (!killed && stream.contents.length > options.maxBuffer) {
- child.kill(options.killSignal);
- killed = true;
- }
- };
- };
- this.out = limitedWrite(this.stdout);
- this.err = limitedWrite(this.stderr);
- };
- Accumulator.prototype.current = function() { return this.stdout.contents; };
- Accumulator.prototype.errCurrent = function() { return this.stderr.contents; };
- Accumulator.prototype.finish = function(err) { this.callback(err, this.stdout.contents, this.stderr.contents); };
-
- var std = callback ? new Accumulator(callback) : new Wrapper(child);
-
- var timeoutId;
- if (options.timeout > 0) {
- timeoutId = setTimeout(function () {
- if (!killed) {
- child.kill(options.killSignal);
- timedOut = true;
- killed = true;
- timeoutId = null;
- }
- }, options.timeout);
+var spawn = require('child_process').spawn,
+ EventEmitter = require('events').EventEmitter,
+ StringDecoder = require('string_decoder').StringDecoder;
+
+// based on https://github.com/bahamas10/node-exec
+function exec2(program, args, opts, callback) {
+ var out = '',
+ err = '',
+ code,
+ i = 0,
+ decoder = new StringDecoder(),
+ v = process.version.split('.')[1];
+
+ if (typeof opts === 'function') {
+ callback = opts;
+ opts = null;
}
+ var child = spawn(program, args, opts);
- child.stdout.setEncoding(options.encoding);
- child.stderr.setEncoding(options.encoding);
+ child.stdout.on('data', function(data) {
+ out += decoder.write(data);
+ });
+ child.stderr.on('data', function(data) {
+ err += decoder.write(data);
+ });
- child.stdout.addListener("data", function (chunk) { std.out(chunk, options.encoding); });
- child.stderr.addListener("data", function (chunk) { std.err(chunk, options.encoding); });
+ child.on('exit', function(c) {
+ code = c;
+ if (++i >= 2 || v < 8) callback(err, out, code);
+ });
- child.addListener("exit", function (code, signal) {
- if (timeoutId) clearTimeout(timeoutId);
- if (code === 0 && signal === null) {
- std.finish(null);
- } else {
- var e = new Error("Command "+(timedOut ? "timed out" : "failed")+": " + std.errCurrent());
- e.timedOut = timedOut;
- e.killed = killed;
- e.code = code;
- e.signal = signal;
- std.finish(e);
- }
+ child.on('close', function() {
+ if (++i >= 2) callback(err, out, code);
});
return child;
};
-
-function parseIdentify(input) {
- var lines = input.split("\n"),
- prop = {},
- props = [prop],
- prevIndent = 0,
- indents = [indent],
- currentLine, comps, indent;
-
- lines.shift(); //drop first line (Image: name.jpg)
-
- for (i in lines) {
- currentLine = lines[i];
- if (currentLine.length > 0) {
- indent = currentLine.search(/\S/);
- comps = currentLine.split(': ');
- if (indent > prevIndent) indents.push(indent);
- while (indent < prevIndent) {
- indents.pop();
- prop = props.pop();
- prevIndent = indents[indents.length - 1];
- }
- if (comps.length < 2) {
- props.push(prop);
- prop = prop[currentLine.split(':')[0].trim().toLowerCase()] = {};
- } else {
- prop[comps[0].trim().toLowerCase()] = comps[1].trim()
- }
- prevIndent = indent;
- }
- }
- return props[0];
-};
-
+// see http://www.imagemagick.org/script/escape.php for formatting options
exports.identify = function(pathOrArgs, callback) {
var isCustom = Array.isArray(pathOrArgs),
isData,
- args = isCustom ? ([]).concat(pathOrArgs) : ['-verbose', pathOrArgs];
+ args = isCustom ? ([]).concat(pathOrArgs) : ['-format', '%m %w %h %z %Q', pathOrArgs];
if (typeof args[args.length-1] === 'object') {
isData = true;
@@ -151,14 +58,16 @@ exports.identify = function(pathOrArgs, callback) {
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;
+ var v = stdout.trim().split(' ');
+ result = {
+ format: v[0],
+ width: parseInt(v[1]),
+ height: parseInt(v[2]),
+ depth: parseInt(v[3])
+ };
+ if (v[4] !== "0") {
+ result.quality = parseInt(v[4]) / 100;
+ }
}
}
callback(err, result);
Something went wrong with that request. Please try again.