2
$ compare --version
Version: ImageMagick 6.9.1-1 Q16 x86_64 2015-04-15 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: DPC Modules
Delegates (built-in): bzlib freetype jng jpeg ltdl lzma png xml zlib


$ node --version
v0.10.33

I'm writing a Node.js script to automatically process some images for me.

When I try to run the script through child-process.exec or child-process.spawn it runs and completes correctly, but exits with code 1 instead of code 0 which throws errors in the script.

When I run the same script on the command line it exits with code 0.

The compare command does return things via stderr, it seems by default, but I don't need that output and if it needs to be, can be suppressed. I've tried adding -quiet with no difference.

Here's the Node script as child-process.spawn (again I tried using child-process.exec as well):

var spawn = require("child-process-promise").spawn,
    filenameA = "img0.png",
    filenameB = "img1.png",
    filenameO = "img.0-1.png";

    var p = spawn('compare', [filenameA, filenameB, '-fuzz', 20, '-highlight-color', "#ffffff", '-lowlight-color', "#000000", filenameO])
        .progress(function (childProcess) {
            console.log('[spawn] childProcess.pid: ', childProcess.pid);
            childProcess.stdout.on('data', function (data) {
                console.log('[spawn] stdout: ', data.toString());
            });
            childProcess.stderr.on('data', function (data) {
                console.log('[spawn] stderr: ', data.toString());
            });
        })
        .then(function(){
            console.log("completed", filenameO);
        })
        .fail(function (err) {
            console.error('[spawn] ERROR: ', err);
        });

Again, I get the generated image, and it looks correct, but the process exits with code 1 (an error occurred).

Output looks like:

[spawn] childProcess.pid:  55002
[spawn] ERROR:  { code: 1,
  message: '`compare img0.png img1.png -fuzz 20 -highlight-color #ffffff -lowlight-color #000000 img.0-1.png` failed with code 1' }

Result from the command line:

$ compare img0.png img1.png -fuzz 20 \
           -highlight-color #ffffff -lowlight-color #000000 img.0-1.png
$ echo $?
> 0

EDIT: The reason that exiting with a code other than 0 was a problem had to do with the child-process-promise node module assuming that any non-zero exit code means error. While that is somewhat standard, it is not formally standard, and Imagemagick can exit normally with non-zero codes.

Patrick Gunderson
  • 3,263
  • 17
  • 28
  • To be ***really*** sure you are not chasing ghosts, try first to compare `img0.png` (not to `img1.png`, but) to **itself** (in terminal as well as in node.js). – Kurt Pfeifle May 13 '15 at 21:34
  • Are you sure that you are running the same version of ImageMagick from the command line and when you use spawn? And what happens when you use absolute paths for the file names instead? – dlemstra May 13 '15 at 22:20
  • @KurtPfeifle I am getting the correct (expected) delta images output, so I'm less worried about that than the fact that `compare` is exiting improperly. My script does work if I ignore that in the console `compare` is exiting with code 1. – Patrick Gunderson May 14 '15 at 00:07
  • @dlemstra it's certainly possible that I'm hitting different versions of IM, I'll check that. Both scripts create the expected delta images, it's just that `compare` is raising an error by exiting with code 1. – Patrick Gunderson May 14 '15 at 00:09
  • 1
    *"...compare is exiting 'improperly'..."* I'm not (yet) convinced of that! – Kurt Pfeifle May 14 '15 at 00:10
  • 1
    @PatrickGunderson: Also, you didn't indicate you version of ImageMagick. Which one is it in your Node.js? Which one is it in your terminal? -- Please add this (essential) bits to your post. After all, this is now about *debugging* your problem... – Kurt Pfeifle May 14 '15 at 00:11
  • I'll go ahead and add those. – Patrick Gunderson May 14 '15 at 00:12
  • 1
    See also the update to my answer. – Kurt Pfeifle May 14 '15 at 00:23
  • @dlemstra both the command line and spawn are using `/usr/local/bin/convert` installed using homebrew today. – Patrick Gunderson May 14 '15 at 00:27
  • @KurtPfeifle You found my problem (an assumption in a different package about exit codes and errors). Thank you very much for your patience and your perseverance. – Patrick Gunderson May 14 '15 at 00:41

1 Answers1

2

I don't know much about running stuff in Node.js, but here is a way that may help you find a workaround:

You can run compare without actually generating a "delta" image, but instead just return one of the supported metric results. A metric is a simple number indicating the differences between two images. To see a list of available metrics, see

compare -list metric

I'd recommend you to look that the AE metric first. This one essentially gives you the count of pixels which are different between the two input images.

To suppress the generation of a "delta" image, just use the special name null: as the output file name.

Example

$ convert wizard: wizard.jpg              # Generate first image
$ convert wizard: wizard.png              # Generate a similar, but different image
$ compare wizard.{jpg,png} delta.pdf      # "Classical" run of `compare`
$ compare wizard.{jpg,png} null:          # No output image, no `metric` either...

Now let's introduce -metric into the picture:

$ compare -metric AE wizard.{j,p}* delta.pdf      # "delta" image AND metric output
$ compare -metric AE wizard.{j,p}* null:          # no image, only metric output

In this case, the last command outputs this:

$ compare -metric AE wizard.{j,p}* null: 
    122473

$ echo $?
    1

$ compare -fuzz 20% -metric AE w.{j,p}* null:
    0

$ echo $?
    0

So even in the terminal you get exit code 1 if your images do exhibit pixel differences. The advantage of looking for the value -metric AE returns is that you get a quantification of the differences.

Your code could still branch for these cases where you want to generate a delta image, if the pixel differences are too large.


Update

The man page for compare has this to say:

The compare program returns 2 on error otherwise 0 if the images are similar or 1 if they are dissimilar.

Kurt Pfeifle
  • 86,724
  • 23
  • 248
  • 345
  • Thanks for the info there, I actually want the delta image for the process I'm doing. – Patrick Gunderson May 14 '15 at 00:04
  • 1
    @PatrickGunderson: Then I don't understand it. If your compare returns exit code `0`, it means no pixel differences, which means your delta image is all black... And you want an all-black image then? – Kurt Pfeifle May 14 '15 at 00:08
  • It's exiting with code 1, BUT it gives me the correct output file. Exit code 1 is not the same as stdout (which is the output stream of a command-line program). Anything other than exit code 0 means the program is exiting with an error. – Patrick Gunderson May 14 '15 at 00:11
  • 1
    @PatrickGunderson: My answer demonstrates to you, that `compare` in the command line will also exit with code 1, and yet it will also create the "expected delta image" if you let it do that. – Kurt Pfeifle May 14 '15 at 00:14
  • 1
    @PatrickGunderson: Oh, and you think I don't know the difference of exit code 1 and the output stream of a command line program? BTW, the `-metric AE` result is not reported on stdout, but on stderr... – Kurt Pfeifle May 14 '15 at 00:16
  • Meant no offense. You never know who's answering your questions. – Patrick Gunderson May 14 '15 at 00:17
  • so it seems that the problem is a disconnect between how node expects processes to terminate and how IM wants to terminate – Patrick Gunderson May 14 '15 at 00:19