ImageMagick is the great set of image processing utilities. But there are some problems to interact with it from your programs (java program in my case). About one of them I would like to talk. In one of our latest projects we used ImageMagick to resize images and put a watermark on them. Everything was fine on developers machines with OS Windows, but when we put project on Unix server… Agrrr. WTF?! We got this error: “convert: Non-conforming drawing primitive definition `image”. Magic… ImageMagick! Here is the best article that I have founded about this problem. It doesn’t help me ’cause it describes a little different problem, but it may be helpful for you) Ok, let us see the code that throws the error (in this example I removed resize parameter ’cause it works fine and the problem only in draw):
public void convertImage() {
// List of commands that we want to execute
List commands = new ArrayList();
// Executable file
commands.add("convert");
// Executable file parameters
commands.add("-gravity");
commands.add("South-East");
commands.add("-draw");
commands.add(""image Over 0,0 0,0 'im-watermark.png'"");
commands.add("im-image.png");
commands.add("im-new.png");
try {
// I also tried to use Runtime.getRuntime().exec(...), but got the same result and it doesn't wonder
// 'cause it use ProcessBuilder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(commands);
Process process = processBuilder.start();
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// Check if we have an error...
if (error.ready()) {
// ...then print them
String line;
while ((line = error.readLine()) != null) {
System.out.println("error: " + line);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
The process builder that we use in our code example must generate such command:
convert -gravity South-East -draw "image Over 0,0 0,0 'im-watermark.png'" im-image.png im-new.jpeg
Looks correct, but doesn’t work. Ok, let’s try to run this command from Unix shell. I can’t belive it! It works! In shell, but not from our program( I think that something happens with convert command parameters when JVM run it or may be it is some kind of Unix feature. I don’t know. So, I did this trick:
-
create shell script “im-convert-proxy.sh” (don’t forget to execute “chmod +x im-convert-proxy.sh” command. It allows you to execute this script) with code:
How you can see it just runs convert command with all parmeters that we passed to script from our java program.
-
replace executable file from “convert” to “im-convert-proxy.sh”:
commands.add("im-convert-proxy.sh"); // was commands.add("convert");
That’s all! Everything works, everyone is happy)
P.S.: if you have found a better solution, please write me.