Calling imagemagick from java not working, direct call works - java

I am having the following java code to blur faces in images - the variable convert is set to /usr/bin/mogrify
//String []cmd = {convert, "-region", f.w+"x"+f.h+"+"+x+"+"+y, "-blur 0.0x10.0", path};
String cmd = convert + " -region " + f.w+"x"+f.h+"+"+x+"+"+y + " -blur 0.0x10.0 " + "\"" + path + "\"";
System.out.println(cmd);
// System.out.println(strJoin(cmd, " "));
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(
new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
p.waitFor();
But nothing happens on the images.
The program also outputs the command line it would call, for example:
/usr/bin/mogrify -region 37x44+1759+881 -blur 0.0x10.0 "/home/self/.wine/drive_c/windows/profiles/self/My Pictures/test/pic00164.jpg"
If I call this line manually, everything works fine.
As you can see from the comments, I also tried supplying cmd as an array which should automatically escape the spaces in my path - same effect: none.

Never build command line by hands - there is no single portable solution for this. It works only in rare cases, where no spaces or (double) quotes are present in the command line.
Use process builder instead:
ProcessBuilder pb = new ProcessBuilder(
convert, "-region", f.w+"x"+f.h+"+"+x+"+"+y, "-blur 0.0x10.0", path);
pb.redirectError();
Process process = pb.start();
BufferedReader in = new BufferedReader(
new InputStreamReader(process.getInputStream()));

getErrorStream() - as mentioned in a comment - was the key to success. The escaping did not work the way I tried it. Then I tried it with an array and found our that I have to split up the blur option.
This works:
String []cmd = {convert, "-region", f.w+"x"+f.h+"+"+x+"+"+y, "-blur", "0.0x10.0", path};

Related

Issues while Invoking Python process using java process builder

I am using java process builder to start python process with one flag and with one argument as shown below. But i don't see any exception nor process starts up.
Command i want to run is
python oc_db5.py -c input.json
location of file oc_db5.py is
/opt/jvision/grpc/gui
My code is shown below
processBuilder = new ProcessBuilder(
Arrays.asList(
"python",
"oc_db5.py",
"-c",
"input.json"));
processBuilder.directory(new File("/opt/jvision/grpc/gui"));
processBuilder.start();
logger.info("Process started ..." + new Date());
int count = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(
process.getInputStream()));
while ((lineData = br.readLine()) != null) {
System.out.println("line: " + ++count + " " + lineData);
logger.info("line: " + ++count + " " + lineData);
}
process.waitFor();
process.getErrorStream();
process.waitFor();
process.exitValue();
I can see that log file contains entry "process start..." but i don't really see that process is started. Wondering what i am missing.
Can you check if python is in your PATH? I have similar problem with custom command long long time ago. You can use absolute path to try it :).
You can also check you enviromental variables via
Map env = System.getenv();
If you are using Linux you can start process like "sleep 1000" then check it is present in system process table via "ps aux | grep sleep" or something like it :)

Using `Runtime.getRuntime().exec()` to get the output from `top`

I'd like run the top -n 1 command using Runtime.getRuntime().exec(String) method and get the output of top -n 1 into my Java program.
I've tried the standard way of getting a processes output with a BufferedReader and using the returned Processes InputStream but that returned no data.
I also tried the following...
String path = "/home/user/Desktop/";
String cmd = "#!/bin/sh\ntop -n 1 > " + path + "output";
File shellCmd = new File(path + "topscript.sh");
PrintWriter writer = new PrintWriter(shellCmd);
writer.write(cmd);
writer.flush();
Runtime.getRuntime().exec("chmod +x " + shellCmd.getAbsolutePath());
Runtime.getRuntime().exec(shellCmd.getAbsolutePath());
Which creates the shell script and the output but the output is empty. However, if I then load up my local shell and run the script that the code above made, I get the correct output in the output file.
What's going wrong?
String cmd = "#!/bin/sh\ntop -n1 -b > " + path + "output";
File shellCmd = new File(path + "topscript.sh");
PrintWriter writer = new PrintWriter(shellCmd);
writer.write(cmd);
writer.flush();
Runtime.getRuntime().exec("chmod +x " + shellCmd.getAbsolutePath());
ProcessBuilder pb = new ProcessBuilder(shellCmd.getAbsolutePath());
Map<String, String> enviornments = pb.environment();
enviornments.put("TERM", "xterm-256color");
Process process = pb.start();
BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorStreamReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String str = inputStreamReader.readLine();
System.out.println(str);
System.out.println(errorStreamReader.readLine());
Use ProcessBuilder with setting TERM variables.
and if want to redirect top to file. need to add -b option to avoid error: initializing curses.

how to execute batch command (imagemagick) with java

I used the terminal command to convert all the images in the folder into RGB images using imagemagick tool
"C:\Documents and Settings\admin\My
Documents\NetBeansProjects\Archiveindexer\resources\T0003SathyabamaT\Active\CBE_2014_03_02_FE_04_MN_IMAGES_CONVERTED"
is my image folder
terminal command:
myimagefolder> mogrify -colorspace RGB *.jpg
This works fine. But when run this using java it is not working
File destpathfinalconv = new File("C:/Documents and Settings/admin/My Documents/NetBeansProjects/Archiveindexer/T0003SathyabamaT/Active/CBE_2014_03_02_FE_04_MN_IMAGES_CONVERTED");
ProcessBuilder pb = new ProcessBuilder("mogrify", "-colorspace RGB", destpathfinalconv.toString(),
"*.jpg");
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = br.readLine()) != null) {
System.err.println(line);
}
System.err.println("Error "+p.waitFor());
System is throwing error "mogrify.exe: unrecognized option
`-colorspace RGB' # error/mogrify.c/MogrifyImageCommand/4254. Error 1"
Any idea please suggest.
You are specifying '-colorspace RGB' as a single argument, but it should be two arguments. And you should combine the path and file and search pattern into a single argument. The constructor of ProcesBuilder should be called like this:
ProcessBuilder pb = new ProcessBuilder("mogrify", "-colorspace", "RGB",
destpathfinalconv.toString() + "\\" + "*.jpg");
Try this:
ProcessBuilder pb = new ProcessBuilder(
"mogrify",
"-colorspace",
"RGB",
destpathfinalconv.toString(),
"*.jpg");
Explanation: Each String argument in the ProcessBuilder ends up as a "word" (according to shell parlance) or a separate parameter in the resulting execve call.
Combining "-colorspace RGB" results in a single parameter to mogrify, which is the (unknown) option "-colorspace\ RGB".

How to detect java process exit?

In a java program, I am generating an sh script for use on a centOS machine, which will use sox and lame to decode an MP3 audio file, then apply some gain to the file respectively. Im having some issues getting the Process.waitFor() method to do anything other than hang indefinitely. Here is the code:
try
{
// TODO code application logic here
String reviewPath = "/SomeDirectory/";
String fileName = "FileName";
String extension = ".mp3";
StringBuilder sb = new StringBuilder();
sb.append("#!/bin/bash\n");
sb.append("cd " + reviewPath + "\n");
sb.append("lame --decode " + fileName + extension + "\n");
File script = new File(reviewPath + fileName + ".sh");
script.createNewFile();
script.setExecutable(true);
FileWriter writer = new FileWriter(script);
writer.write(sb.toString());
writer.close();
Process p = Runtime.getRuntime().exec(script.getAbsolutePath());
String line;
BufferedReader bri = new BufferedReader
(new InputStreamReader(p.getInputStream()));
BufferedReader bre = new BufferedReader
(new InputStreamReader(p.getErrorStream()));
while ((line = bri.readLine()) != null) {
System.out.println(line);
}
bri.close();
while ((line = bre.readLine()) != null) {
System.out.println(line);
}
bre.close();
p.waitFor();
System.out.println("Done.");
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
The odd part is that when I run the .sh file it generates by hand, it runs and exits nicely, but when I execute it from a process object in java, it never exits. The exitValue of the process is always "Process has not exited". Ive tried adding set -e to the script, and exit to the end of the script. Short of using the kill command (which I dont really think I can do here) Im at a loss as to what is going on here. Any suggestions?
Add something like while(p.getInputStream().read() != -1); after starting the process. The buffer will get filled and the process will stop waiting for something (in this case, your program) to read from it to free up space.
I figured it out! The problem here was indeed that the output streams needed to be flushed for the application to exit, but simply reading from the streams is not enough. I used Suresh Koya's suggestion and used the processBuilder api, and redirected the error stream on the process before starting it, and read from the streams. This fixed the issues I was having :D

how to write log file while starting services using java

hello everyone i created a java file,in that java i written a code for starting,stoping and restarring a windows service ,in that i want to create a log file and write output of window service as a console please if any one knows give suggestion
i used code for stoping service
public static void stopService(String serviceName) throws IOException,
InterruptedException {
String executeCmd = "cmd /c net stop \"" + serviceName + "\"";
Process runtimeProcess = Runtime.getRuntime().exec(executeCmd);
int processComplete = runtimeProcess.waitFor();
System.out.println("processComplete: " + processComplete);
if (processComplete == 1) {// if values equal 1 process failed
System.out.println("Service failed");
}
else if (processComplete == 0) {
System.out.println("Service Success");
}
}
Probably the best way to achieve this is Log4J. If you haven't used it before it can seem overbearing, but there are a lot of good tutorials out there to cherry pick from, should you need to. Put the LogFactory in your class definition and then pop lines like log.info.println("service starting"). The other keyword to keep an eye our for is FileAppender. (Sorry no better references, writing from my phone!)
The best solution is to use some logging API have a look at http://www.vogella.com/articles/Logging/article.html tutorial.
Or the other trivial option is to redirect the output of executing the command in some text File. Change the command
String executeCmd = "cmd /c net stop \" + serviceName + "\"+" >> "+ fileName".
In order to get the output of a command you can do this:
String lineSeparator = System.getProperty("line.separator");
stderr = runtimeProcess.getErrorStream();
stdout = runtimeProcess.getInputStream();
// clean up if any output in stdout
BufferedReader brCleanUp =
new BufferedReader(new InputStreamReader(stdout));
StringBuilder output = new StringBuilder();
String line;
while ((line = brCleanUp.readLine()) != null) {
output.append(line).append(lineSeparator);
}
brCleanUp.close();
// clean up if any output in stderr
brCleanUp =
new BufferedReader(new InputStreamReader(stderr));
StringBuilder error = new StringBuilder();
while ((line = brCleanUp.readLine()) != null) {
error.append(line).append(lineSeparator);
}
brCleanUp.close();
And now in output and error String you have the "standard output" and "standard error" of the process you executed.

Categories