Can I access ImageMagick API with Python?
Asked Answered
S

3

63

I need to use ImageMagick as PIL does not have the amount of image functionality available that I am looking for. However, I am wanting to use Python.

The python bindings (PythonMagick) have not been updated since 2009. The only thing I have been able to find is os.system calls to use the command line interface but this seems clunky.

Is there any way to access the API directly using ctypes and conversions of some sort? As a last resort is there any other library out there that has the extensive amount of image editing tools like ImageMagick that I have looked over?

Sanalda answered 25/10, 2011 at 20:12 Comment(0)
V
79

I would recommend using Wand (explanations follows).

I was looking for proper binding to ImageMagick library, that would:

  • work error/problem free
  • be regularly maintained and up to date
  • allow nice objective Python

But indeed python API (binding) has too many different (mostly discontinued) versions. After reading a nice historical overview by Benjamin Schweizer it has all become clear:

  • GraphicsMagick
  • PythonMagick - first implementation
  • PythonMagickWand/Achim Domma - first Wand - a CDLL implementation
  • PythonMagickWand/Ian Stevens
  • MagickFoo - included in python-magickwand
  • Wand/Hong Minhee - not the latest project
  • [UPD 2023] Eric McConville https://github.com/emcconville/wand

Now Wand is just a (reduced) C API to the ImageMagick ".. API is the recommended interface between the C programming language and the ImageMagick image processing libraries. Unlike the MagickCore C API, MagickWand uses only a few opaque types. Accessors are available to set or get important wand properties." (See project homepage)

So it is already a simplified interface that is easer to maintain.

[UPD 2023] PS as any API software py-wand inherits any transient errors from the parent

Vamoose answered 25/7, 2012 at 20:35 Comment(3)
Main reason why I moved away from want is : github.com/dahlia/wand/issues/312Parisi
Ftr, the "historical overview by Benjamin Schweizer" has moved here: github.com/benschweizer/python-magickwand#alternativesCambridgeshire
Wand's link is dead.Renner
A
11

This has worked for me for the following command to create an image from text for the letter "P":

import subprocess

cmd = '/usr/local/bin/convert -size 30x40 xc:white -fill white -fill black -font Arial -pointsize 40 -gravity South -draw "text 0,0 \'P\'" /Users/fred/desktop/draw_text2.gif'

subprocess.call(cmd, shell=True)
Artie answered 31/10, 2017 at 19:50 Comment(4)
shell=True is a recipe for disaster. Instead of cmd = "a single string with all args" use cmd = ["path/to/program", "arg1", "arg2", ...] and drop the shell=True for good.Practically
Why is that a problem -- injection issues?Artie
Yes, injection is the main problem (Python's manual even prominently warns about this) (however, the injection will probably happen by accident and not by malicious intent). But you also make your script more dependent on its environment / operating system (e.g. Linux shells have different quoting mechanisms than Windows cmd),Practically
alternatively, you can also use R as your shell script runner like this: shell(sprintf('magick mogrify -resize "64x64>" ./folder/*.png'), intern=FALSE) Brownfield
P
7

I found no good Python binding for ImageMagick, so in order to use ImageMagick in Python program I had to use subprocess module to redirect input/output.

For example, let's assume we need to convert PDF file into TIF:

path = "/path/to/some.pdf"
cmd = ["convert", "-monochrome", "-compress", "lzw", path, "tif:-"]
fconvert = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = fconvert.communicate()
assert fconvert.returncode == 0, stderr

# now stdout is TIF image. let's load it with OpenCV
filebytes = numpy.asarray(bytearray(stdout), dtype=numpy.uint8)
image = cv2.imdecode(filebytes, cv2.IMREAD_GRAYSCALE)

Here I used tif:- to tell ImageMagick's command-line utility that I want to get TIF image as stdout stream. In the similar way you may tell it to use stdin stream as input by specifying - as input filename.

Panarabism answered 31/10, 2017 at 19:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.