3

How can you use imagemagick from python without opening a new command line window and losing focus?

This loop show the problem; the system becomes unusable while working on images because you lose focus with every system call:

for i in range(0,100,1):
    image = 'convert -background '+'black'+' -fill '+'white'+' -font '+'arial'+' -size '+'50'+'x50'+' -encoding utf8'+' -gravity center caption'+':'+'"just stole your focus"'+' '+'C:/'+'testFile.png'
    os.system(image)

'start /min' or '/b' only minimize the window quickly, so you still lose focus. And for some reason I don't get an output file if I put these before 'image'.

Is there some way to use os.system, os.spawnv, subprocess.Popen or another system command to call imagemagick in the background?

I read about PythonMagickWand but only found install directions for nix: Python bindings for ImageMagick's MagickWand API

Can I install/compile these bindings under windows? If so, how?

Edit: MRAB's solution:

import os
import subprocess

# Start all the processes.
processes = []
# Define directories
convertDir = 'C:/Program Files/ImageMagick-6.7.5-Q16/convert.exe'
outputDir = 'C:/test/'
outputFileName = 'testFile_look_ma_no_windows_'
if not os.path.exists(outputDir):
    os.makedirs(outputDir)

for i in range(100):
    outputDirFile = outputDir+outputFileName+str(i)+'.png'
    image = convertDir+' '+'-background'+' '+'blue'+' '+'-fill'+' '+'white'+' '+'-font'+' '+'arial,'+' '+'-size '+' '+'50x50'+' '+'-encoding'+' '+'utf8'+' '+'-gravity'+' '+'center'+' '+'caption:"did not steal your focus"'+' '+outputDirFile
    #CREATE_NO_WINDOW Flag: 0x08000000
    p = subprocess.Popen(image, creationflags=0x08000000)
    processes.append(p)

# Wait for all the processes to finish.
# Some may finish faster, so the files are out of order before all are done;
# if you need the files immediately, put p.wait after p = subprocess.Popen
# and comment out lines 5,18,24 and 25
for p in processes:
    p.wait()

print 'Done, created ',str(i+1),' images in ',outputDir
James Rather
  • 85
  • 1
  • 7
  • Consider [PythonMagic](http://www.imagemagick.org/download/python/) ([Windows binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/#pythonmagick)). – cgohlke Feb 11 '12 at 21:16
  • @cgohlke Thanks, I've actually used your PIL binaries before. I tried PythonMagic but because of the lack of any real documentation (http://stackoverflow.com/questions/2445985/where-can-i-find-pythonmagick-documentation http://stackoverflow.com/questions/1740158/documents-and-examples-of-pythonmagick/5188661#5188661) I don't think I'll be able to work with it within a reasonable timeframe. – James Rather Feb 12 '12 at 13:08
  • I recommended that for safety you quote any paths or pass Popen a list of various parts of the command-line as in my answer. – MRAB Feb 14 '12 at 01:38

1 Answers1

3

subprocesses.Popen is the recommended way to do it:

# Start all the processes.
processes = []
for i in range(100):
    p = subprocess.Popen(['convert', '-background', 'black', '-fill', 'white', '-font', 'arial', '-size', '50x50', '-encoding', 'utf8', '-gravity', 'center', 'caption:"just stole your focus"', 'C:/testFile.png'])
    processes.append(p)

# Wait for all the processes to finish.
for p in processes:
    p.wait()
MRAB
  • 20,356
  • 6
  • 40
  • 33
  • Thank you; unfortunately this doesn't produce any image output on my system (python 2.6 x64). It just runs empty. The commandline outputs 'invalid parameter: black'. And after I added the spaces between the parameters it outputs 'invalid parameter: -background'. When i pass it my string that worked with os.system() it returns the invalid black again. Then I illogically added a space before convert and it gives me 'WindowsError: [Error 87] The parameter is incorrect'; then I tried imageString="'%s'"%image and got 'WindowsError: [Error 2] The system cannot find the file specified'. – James Rather Feb 12 '12 at 10:58
  • And I still get all the open command line windows, just now all of them in a short burst. It's slightly better, but is there a way to not get any command line windows at all? – James Rather Feb 12 '12 at 11:15
  • The problem might be that you're not giving the full path to `convert`, so it's actually calling another executable which happens to be called `convert`. Try replacing `'convert'` with its full path. – MRAB Feb 12 '12 at 20:42
  • Thanks, that did the trick ('C:/Program Files/ImageMagick-6.7.5-Q16/convert.exe ' on my machine). Now is there any way to maybe have only one command line window open and use it to run all the lined up proccesses in the background so there aren't a few hundred windows for a few hundred operations every few minutes? Sorry to be such a pain. – James Rather Feb 12 '12 at 23:33
  • How about writing a `.bat` file and then running that? – MRAB Feb 13 '12 at 00:27
  • According to the Python docs, on Windows it calls the underlying function `CreateFunction` and you can pass it the creation flags in the argument `creationflags`; and according to the Windows docs, you can suppress the console window using the `CREATE_NO_WINDOW` flag, which has the value 0x08000000. Therefore, `subprocess.Popen(..., creationflags=0x08000000)` should work. – MRAB Feb 13 '12 at 00:41
  • I have too many interlocking parts for a .bat file and just can't think of a way to make that work. – James Rather Feb 13 '12 at 14:08