#!/usr/bin/env python # -*- encoding: utf-8 -*- # # # Copyright (C) 2003 André Wobst <wobsta@users.sourceforge.net> # # epstopng is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # epstopng is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with epstopng; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # TODO: - set dpi in png (don't know how to do this in PIL) # - this is much too slow --- consider a rewrite in C import getopt, sys, os, StringIO, re, math import Image # we use the python image library (PIL) progname = "epstopng v0.1: eps to transparent antialiased png converter" def epstopng(epsname, pngname, resolution, scale, transparent, gsname, quiet): sys.stderr.write("run ghostscript to create a %i times larger non-antialiased image ... " % scale) gsout = os.popen("%s -dEPSCrop -dNOPAUSE -dQUIET -dBATCH -sDEVICE=ppmraw -sOutputFile=- -r%i %s" % (gsname, resolution*scale, epsname)) input = Image.open(StringIO.StringIO(gsout.read())).convert("RGB") # ensure rgb here output = Image.new("RGBA", [(x+scale-1)/scale for x in input.size]) sys.stderr.write("done\n") sys.stderr.write("image size is %ix%i\n" % output.size) inputdata = input.getdata() # getdata instead of getpixel leads to about a factor of 2 in running time # similar effect with putdata possible??? (didn't got that running) inputsizex, inputsizey = input.size # loop over the small image for x in range(output.size[0]): sys.stderr.write("transparent antialias conversion ... %5.2f %%\r" % (x*100.0/output.size[0])) for y in range(output.size[1]): # r, g, b: sum of the rgb-values; u: number of non-transparent pixels r = g = b = u = 0 # loop over the pixels of the large image to be used for pixel (x, y) for xo in range(x*scale, min((x+1)*scale, inputsizex-1)): for yo in range(y*scale, min((y+1)*scale, inputsizey-1)): ro, go, bo = inputdata[xo+inputsizex*yo] if (ro, go, bo) != transparent: r += ro g += go b += bo u += 1 if u: output.putpixel((x, y), (r/u, g/u, b/u, (u*255)/(scale*scale))) else: output.putpixel((x, y), (255, 255, 255, 0)) sys.stderr.write("transparent antialias conversion ... done \n") output.save(pngname) def usage(): print progname print "Copyright (C) 2003 André Wobst <wobsta@users.sourceforge.net>" print "usage: epstopng [options] <eps-file>" print "-h, --help: show this help" print "-q, --quiet: be quiet" print "-o, --output <file>: output file name; must be set" print "-r, --resolution <dpi>: resolution; default: 100" print "-s, --scale <scale>: input scale for antialias; default: 4" print "-t, --transparent (<r>, <g>, <b>): transparent color; default: (255, 255, 255)" print "-g, --gsname <name>: name of the gs interpreter (gs version >= 8.0 needed!); default: \"gs\"" def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hqo:r:s:t:g:", ["help", "quiet", "output", "resolution", "scale", "transparent", "gsname"]) except getopt.GetoptError: # print help information and exit: usage() sys.exit(2) output = None resolution = 100 scale = 4 transparent = (255, 255, 255) gsname = "gs" quiet = 0 for o, a in opts: if o in ("-h", "--help"): usage() sys.exit() if o in ("-o", "--output"): output = a if o in ("-r", "--resolution"): resolution = int(a) if o in ("-s", "--scale"): scale = int(a) if o in ("-t", "--transparent"): m = re.compile(r"\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)\s*$").match(a) if not m: raise RuntimeError("transparent argument does not match") transparent = [int(x) for x in m.groups()] if o in ("-g", "--gsname"): gsname = a if len(args) == 1: input = args[0] elif len(args): raise RuntimeError("can't handle several input files") else: raise RuntimeError("must specify an input file (reading from stdin is not yet supported)") if output is None: raise RuntimeError("you must specify an output file name") if not quiet: sys.stderr.write(progname + "\n") epstopng(input, output, resolution, scale, transparent, gsname, quiet) if __name__ == "__main__": main()