Convert a PDF to a Transparent PNG with GhostScript

ghostscriptpdfpngtransparency

I am attempting, unsuccessfully, to use Ghostscript to rasterize PDF files with a
transparent background to PNG files with a transparent background. I've
searched high and low for questions from others attempting the same thing
and none of the posted solutions, which as far as I can tell come down to
specifying -sDEVICE=pngalpha, have worked with my test files. At this point
I would really appreciate any advice or tips a more experienced hand could
provide.

My test PDF is located here: http://www.kolossus.com/files/test.pdf

It could be that the issue is with this file, but I doubt it. As far as I
can tell, it has no specified background, and when I open the file with a
transparency-aware app like Photoshop or Illustrator, sure enough it
displays with a transparent background. However, when opened with an
application like Adobe Reader the file is rendered with a white background.
I believe that this has more to do with the application rendering the PDF
than with the PDF itself — apps like Adobe Reader assume you want to see
what a printed document will look like and therefore always show a white
canvas behind the artwork — but I can't be sure.

The gs command I'm using is:

gs -dNOPAUSE -dBATCH -sDEVICE=pngalpha -r72 -sOutputFile=test.png test.pdf

This produces a PNG that has transparent pixels outside of the bounding box
of the artwork in the file, but all pixels that are inside the artwork's
bounding box are rasterized against a white background. This is a problem
for me, as my artwork has drop shadows and antialiased edges that need to be
preserved in the final output, and can't just be postprocessed out with
ImageMagick. A sample of my PNG output is at the same location as the pdf above, with .png at the end (stackoverflow won't let me include more than one url in my post).

Interestingly, I see no effects from using the -dBackgroundColor flag, even
if I set it to something non-white like -dBackgroundColor=16#ff0000. Perhaps
my understanding of the syntax of this flag is wrong.

Also interestingly, I see no effects from using the -dTextAlphaBits=4
-dGraphicsAlphaBits=4 flags to try to enable subpixel antialiasing. I would
also appreciate any advice on how to enable subpixel antialiasing,
especially on text.

Finally, I'm using GPL Ghostscript 8.64 on Mac OS 10.5.7, and the rendering
workflow I'm trying to get set up is to generate transparent PNG images from
PDFs output by PrinceXML. I'm calling Ghostscript directly for the rasterization instead of using ImageMagick because ImageMagick delegates to Ghostscript for PDF rasterization and I should be able to control the rasterization better by calling GS directly.

Thanks for your help.

-Jon Wolfe

Best Answer

I share your experience with the -dTextAlphaBits=4 and -dGraphicsAlphaBits=4 flags. They appear not to work on all texts. The "fix" I came up with was to just render the image at 4 times the desired size, and then scale the image down. Luckily ghostscript has no problems rendering gigapixel PNG files.

update

Ghostscript (up to version 9) also seems to enjoy major problems when rendering transparent PNG's with a pixel count above 2.500.000 (i.e. 10 mb of pixel buffer). The transparent background suddenly turns white.

Drilling down the source of ghostscript, I found that when the pixel buffer size exceeds 10 mb, it switches to a different memory allocation scheme. More specifically, the image is rendered using device image32 instead of pngalpha. Given the way the pngalpha driver is implemented, it's whole purpose vanishes when gs decides not to use its pngalpha_fill_rectangle().

Luckily, there is a switch called -dMaxBitmap=N to configure this parameter at runtime. This is mentioned in a workaround for a totally different bug dating back to 1999-01-15, see http://pages.cs.wisc.edu/~ghost/doc/AFPL/5.50/relnotes/index.htm.

Adding -dMaxBitmap=2147483647 solved a lot of problems for me. On 64 bit systems, this number can be higher.

A true fix would of course be to rework the pngalpha driver so that it sets the background color to 0x7f000000 no matter the actual code path, but most systems have enough ram on board for the above trick to work.