I'm trying to convert from PDF to JPG using PythonMagick, but I can't find a way to set the background color, which by default is changed from transparent to black. I can get the desired result using os.system and the -flatten parameter as shown below.
import os
os.system('convert -flatten -background \#ffffff -density 400 -adaptive-resize 1900x infile.pdf outfile.jpg')
However, PythonMagick does not seem to have a flatten
method and the following snippet produces an image with a black background.
import PythonMagick
import os
img = PythonMagick.Image("infile.pdf")
img.backgroundColor('#ffffff')
img.density('400')
img.resize('1900x')
img.magick('JPG')
img.quality(60)
img.write("outfile.jpg")
There is also a transparent() method that takes a color. I'm not quite sure what it's for, but img.transparent('#ffffff')
did not help. Is there another way to achieve the same result? I'd rather not do it using os.system
, since it seems to take quite alot longer.
If you look at the documentation for the -flatten
command-line option, you will see it is an alias for -layers flatten
.
The -layers flatten
command is itself a combination command, which comprises creating a layer of the current background colour the size of the first images canvas, and then composing each layer in turn on top of it.
PythonMagick is essentially just a binding layer to the Magick++ C++ interface. The advanced commands that convert
provides, are not necessarily replicated in the lower level libraries, as they are really a sequence of commands as described above. So whilst there is no single command for it in the PythonMagick library, the functionality can be replicated.
The method you are after is .composite()
, the PythonMagick documentation is so limited ( or indeed non-existent), most people stay clear of the library. But I think the usage is something like this, if there was only one layer in the PDF (totally untested):
import PythonMagick
img = PythonMagick.Image("infile.pdf")
img.density('400')
bgColour = PythonMagick.ColorRGB(1.0, 1.0, 1.0)
size = "%sx%s" % (img.columns(), img.rows())
flattened = PythonMagick.Image(size, bgColour)
flattened.type = img.type
flattened.composite(img, 0, 0, PythonMagick.CompositeOperator.SrcOverCompositeOp)
flattened.resize('1900x')
flattened.magick('JPG')
flattened.quality(60)
flattened.write("outfile.jpg")
NB. The composition operator could be PythonMagick.CompositeOperator.DstOverCompositeOp
, I'm not sure which way round it is handling that.
Though PDFs are a special case with ImageMagick, as they are usually passed off to ghostscript to rasterize. Which means you might need to give ghostscript (gs
) some odd parameters to handle the alpha channel properly. Try adding verbose options to the command that works to see what delegate commands it issues and consider doing the PDF rasterisation yourself via an os.system('gs ...')
command and then doing the resize. Though I doubt that would be faster than just calling convert
.