4

I am trying to compare two images located under my OS machine. I have ImageMagick running on my os machine. and I am using this method:

public boolean compareImages (String expectedScreenShot, String capturedScreenShot, String pdiffCompare) {
  ProcessStarter.setGlobalSearchPath("/usr/local/bin/");
  CompareCmd compare = new CompareCmd();
  // For metric-output
  IMOperation cmpOp = new IMOperation();
  // Set the compare metric
  cmpOp.metric("AE");
  // Add the expected image
  cmpOp.addImage(expectedScreenShot);
  // Add the current image
  cmpOp.addImage(capturedScreenShot);
  // This stores the difference
  cmpOp.addImage(pdiffCompare);
  try {
     // Do the compare
     compare.run(cmpOp);
     compare.getErrorText();
     return true;
  }
  catch (Exception ex) {
     return false;
  }
   }

I'm using im4java:1.4.0, but when I run compare.run(cmpOp); I am receiving this exception:

org.im4java.core.CommandException: org.im4java.core.CommandException: magick: no images found for operation `-metric' at CLI arg 1 @ error/operation.c/CLIOption/5225.

Any help would be appreciated.

fmw42
  • 46,825
  • 10
  • 62
  • 80
Youssef
  • 41
  • 1
  • 4
  • What are the values of `expectedScreenShot` and `capturedScreenShot`? What is an OS machine? – Mark Setchell Oct 30 '16 at 12:48
  • @Mark Setchell expectedScreenShot and capturedScreenShot are the absolute path of the images that i want to compare between them and Yes it's an OS machine expectedScreenShot = /Users/username/src/automation/test2/test.png capturedScreenShot = /Users/username/src/automation/test3/test.png – Youssef Oct 30 '16 at 13:12
  • If you want the `AE` you need to set up a consumer for `stderr` with `compare.setErrorConsumer(StandardStream.STDERR);` I think. – Mark Setchell Oct 30 '16 at 13:16
  • @Mark Setchell when i used compare.setErrorConsumer(StandardStream.STDERR); i received org.im4java.core.CommandException: java.lang.NullPointerException – Youssef Oct 30 '16 at 13:19
  • Mmmm, not too sure about that one - sorry. Can you try temporarily creating two JPEG files to compare rather than two PNG files and see if that helps. (Your installation may be incomplete and JPEG is more likely to work than PNG as the latter requires 2 additional libraries.) – Mark Setchell Oct 30 '16 at 13:26
  • @MarkSetchell same issue even when i use jpeg org.im4java.core.CommandException: java.lang.NullPointerException still apears – Youssef Oct 30 '16 at 13:41

3 Answers3

3

Actually this is a comment and not an answer, but I'm not allowed to comment here. I'm the author of im4java, but I don't have currently IM 7 installed on my machine. I'll try to upgrade if possible and gain some insights.

In the meantime, could you please try to dump the generated commandline (see the im4java-docs) and try that commandline directly? Please post the result.

Another workaround would be to use the convert-command, something like convert -verbose file1.jpg file2.jpg -metric ae -compare diff.jpg

This creates the diff file, but my installation does not write the metrics to stderr. This might be the problem you have with the ErrorConsumer. In this case, ImageMagick has to fix their tools (magick is just a new name for convert).

Another option would be to switch to GraphicsMagick.

  • 1
    Thanks for the hint. My working solution is to add "convert": op.addRawArgs("convert"); Is this you intended solution? – Matthias M Jun 26 '17 at 06:32
  • Thanks Matthias! I was experiencing a similar issue with `Info` class / `identify` command and my solution was to write a similar class as `Info` but with `op.addRawArgs("identify");`. I guess this makes im4java run `magick identify args...` thus working around the issue. – Dário Oct 09 '20 at 07:29
2

I was also seeing this on linux, but not windows, with IMJava version 1.4 and ImageMagick 7.

After digging and debugging I was able to workaround this by deleting the compare file (a symlink to magick) and then copy magick back over compare (to get rid of the symlink).

Some more details for the curious - when im4java is getting ready to run the imagemagick command it does a File.getCanonicalName on the command (in this case 'compare') and that call comes back with 'magick'. So then im4java runs and calls magick with the command line parameters that compare expects and you get the exception youssef reported. The workaround above tricks getCanonicalName into not resolving to 'magick'.

Edit to answer Bernhard's question because i too can't comment: if you run the command line it generates you get no errors because the command line uses the 'compare' command. What's happening in the API is that it's using 'magick' instead. For example "compare -metric AE foo.png bar.png diff.png" works but "magick -metric AE foo.png bar.png diff.png" will not.

AMichaud
  • 21
  • 2
  • Reply above really helped us a lot. As a side note - you can also create hardlinks to `magick` instead of symlinks that it is by default: `ln magick compare` -- make sure to do so for all of them (`identify`, `convert`, etc) – Aramir Jan 15 '18 at 21:15
0

I met the same question today with ImageMagick7 and im4java. And that is my answer:Use custom command instead of these prepared commands,like ImageCommand imageCommand = new ImageCommand("magick","compare"); instead of CompareCmd compare = new CompareCmd();, because IM7 add a prefix 'magick' before IM6's commands.