3

I was hoping to be able to generate montages using PythonMagick. The documentation seems very sparse, but I've been trying to hunt it down using the code completion part of Eclipse at least, as well as a few other questions' suggestions here on Stack Overflow. It seems that the MagickWand API has the function I am looking for, according to this:

http://www.imagemagick.org/api/MagickWand/montage_8c.html

However, I cannot seem to find it in PythonMagick. Is this simply unavailable? If so I might just ditch the rest of my PythonMagick code and rely on subprocess.call on a portable ImageMagick distribution or something like that (this program will have to be portable, and run on Windows with an easy port to Mac OS... so far I have a few other PythonMagick commands working so I'd like to keep this route going if possible).

Thanks!

Mylan Connolly
  • 494
  • 1
  • 5
  • 15

2 Answers2

1

Using the python imagemagick/graphicsmagick bindings helps a lot, but unfortunately not all of the functionality is there yet. I actually had the same problem with @FizxMike. I needed to use montage and then do some further operations, but saving the file on hard disk and then reloading it in a proper pgmagick object in order to do the rest of the operations and saving it again was slow.

Eventually I used the subprocess solution, but instead of saving in a file, I redirect the output in stdout. Then, I use the stdout to load the image from a pgmagick.Blob in a pgmagick.Image object and do the rest of the processing in python code.

The procedure looks like this in code:

import os
import pgmagick
import subprocess

my_files = []
# Dir with the images that you want to operate on
dir_with_images = "."
for file in os.listdir(dir_with_images):
    if file.endswith(".png"):
        my_files.append(os.path.join(dir_with_images, file))

montage_cmd = ['gm', 'montage']
montage_cmd.extend(my_files)
# The trick is in the next line of code. Instead of saving in a file, e.g. myimage.png
# the montaged file will just be "printed" in the stdout with 'png:-'
montage_cmd.extend(['-tile', '2x2', '-background', 'none', '-geometry', '+0+0', 'png:-'])

# Use the command line 'gm montage' since there are not python bindings for it :(
p = subprocess.Popen(montage_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Get the stdout in a variable
stdout, stderr = p.communicate()

# Load the stdout in a python pgmagick Image object using the pgmagick.Blob
# and do the rest of the editing on python code
img = pgmagick.Image(pgmagick.Blob(stdout))
# Display the image
img.display()
geometry = pgmagick.Geometry(300, 200)
geometry.aspect(True)
# Resize the montaged image to 300x200, but keep the aspect ratio
img.scale(geometry)
# Display it again
img.display()
# And finally save it <- Only once disk access at this point.
img.write('myimage.png')
Vangelis Tasoulas
  • 3,109
  • 3
  • 23
  • 36
0

I have the same problem, even pgmagick lacks the montageImage() function needed (Magick++ montage example)

This is what I do (in a Django View):

#ImageMagick CLI is better documented anyway (-background none preserves transparency)
subprocess.call("montage -border 0 -geometry "+str(cols)+"x -tile 1x"+str(len(pages))+" "+target_path[0:len(target_path)-4]+"[0-9]*.png -background none "+target_path,shell=True)`

Not fun because I have to juggle around a bunch of files first... writing to hard disk is not the fastest thing to do, then delete the temp files.

I would much rather do it all in ram.

I am still in search of a better answer myself.

FizxMike
  • 971
  • 1
  • 10
  • 16