# Sketch - A Python-based interactive drawing program # export_raster script # Copyright (C) 1999, 2000, 2002, 2003, 2004 by Bernhard Herzog # 6.12.2000 improved by Bernhard Reiter with Help form Bernhard # (used create_star.py by Tamito KAJIYAMA as an example to # build the dialog) # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Library General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library 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 # Library General Public License for more details. # # You should have received a copy of the GNU Library General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Export Sketch drawings as raster images using ghostscript to render # them # # This script adds the following to the Script menu: # # Export Raster Renders the drawing on a white background # # You can add more with fixed parameters, if you need them frequently # see the comments below, one example is enabled. # # Both commands prompt for a filename. The output file format is # determined by the filename extension and should be something your PIL # installation can handle. For the alpha version this should be PNG or # some other format that can handle an alpha channel. # import sys import os, tempfile import PIL.Image, PIL.ImageChops import Sketch.Scripting from Sketch import _, PostScriptDevice # for parameter dialogs from Sketch.UI.sketchdlg import SKModal from Tkinter import * class CreateRasterParametersDlg(SKModal): "Create Tk Dialog to ask for raster parameters." title = _("Choose Raster Parameters") def build_dlg(self): self.var_ppi = IntVar(self.top) self.var_ppi.set(72) label = Label(self.top, text=_("ppi")) label.grid(column=0, row=0, sticky=E) entry = Entry(self.top, width=15, textvariable=self.var_ppi) entry.grid(column=1, row=0) self.var_alpha = BooleanVar(self.top) self.var_alpha.set(1) label = Label(self.top, text=_("w. Transparency")) label.grid(column=0, row=1, sticky=E) entry = Checkbutton(self.top, variable=self.var_alpha) entry.grid(column=1, row=1) self.var_use_bbox = BooleanVar(self.top) self.var_use_bbox.set(0) label = Label(self.top, text=_("use BB information")) label.grid(column=0, row=2, sticky=E) entry = Checkbutton(self.top, variable=self.var_use_bbox) entry.grid(column=1, row=2) button = Button(self.top, text=_("OK"), command=self.ok) button.grid(column=0, row=3, sticky=W) button = Button(self.top, text=_("Cancel"), command=self.cancel) button.grid(column=1, row=3, sticky=E) def ok(self): self.close_dlg((self.var_ppi.get(), self.var_alpha.get(),self.var_use_bbox.get())) def export_raster_more_interactive(context, alpha = 0, use_bbox = 0, render_ppi=72): "Get Parameter per dialog and run export_raster_interactive()" parms = CreateRasterParametersDlg(context.application.root).RunDialog() if parms is None: return else: render_ppi=parms[0] alpha=parms[1] use_bbox=parms[2] return export_raster_interactive(context,alpha,use_bbox,render_ppi) def make_ps(document): file = tempfile.mktemp('.ps') device = PostScriptDevice(file, as_eps = 0, document = document) document.Draw(device) device.Close() return file def render_ps(filename, resolution, width, height, orig_x = 0, orig_y = 0, prolog = '', antialias = '', gsdevice = 'ppmraw'): if prolog: prolog = '-c ' + '"' + prolog + '"' if antialias: antialias = ("-dTextAlphaBits=%d -dGraphicsAlphaBits=%d" % (antialias, antialias)) else: antialias = "" orig_x = -orig_x orig_y = -orig_y temp = tempfile.mktemp() try: gs_cmd = ('gs -dNOPAUSE -g%(width)dx%(height)d -r%(resolution)d ' '-sOutputFile=%(temp)s %(antialias)s ' '-sDEVICE=%(gsdevice)s -q %(prolog)s ' '-c %(orig_x)f %(orig_y)f translate ' '-f%(filename)s -c quit') gs_cmd = gs_cmd % locals() retval = os.system(gs_cmd) if retval: sys.stderr.write("skencil:export_raster: executing %s failed" " with exit code %x\n" % (repr(gs_cmd), retval)) raise IOError("Error running ghostscript." " Perhaps it's not installed.") image = PIL.Image.open(temp) image.load() return image finally: try: os.unlink(temp) except: pass def export_raster(context, filename, resolution, use_bbox, format = None, antialias = None): # instead of the page size one could also use the bounding box # (returned by the BoundingRect method). if use_bbox: left, bottom, right, top = context.document.BoundingRect() width = right - left height = top - bottom x = left; y = bottom else: width, height = context.document.PageSize() x = y = 0 width = round(width * resolution / 72.0) height = round(height * resolution / 72.0) temp = make_ps(context.document) try: image = render_ps(temp, resolution, width, height, orig_x = x, orig_y = y, antialias = antialias) finally: os.unlink(temp) image.save(filename, format = format) alpha_prolog = "/setrgbcolor {pop pop pop 0 0 0 setrgbcolor} bind def \ /setgray { pop 0 setgray} bind def \ /setcmykcolor { pop pop pop pop 0 0 0 1.0 setcmykcolor} bind def " def export_alpha(context, filename, resolution, use_bbox = 0): if use_bbox: left, bottom, right, top = context.document.BoundingRect() width = right - left height = top - bottom x = left; y = bottom else: width, height = context.document.PageSize() x = y = 0 ps = make_ps(context.document) width = round(width * resolution / 72.0) height = round(height * resolution / 72.0) rgb = render_ps(ps, resolution, width, height, orig_x = x, orig_y = y, antialias = 2) alpha = render_ps(ps, resolution, width, height, orig_x = x, orig_y = y, antialias = 2, prolog = alpha_prolog, gsdevice = 'pgmraw') alpha = PIL.ImageChops.invert(alpha) rgb = rgb.convert('RGBA') rgb.putalpha(alpha) rgb.save(filename) filelist = [(_("Portable Pixmap"), '.ppm'), (_("Portable Graymap"), '.pgm'), (_("Jpeg"), '.jpg'), (_("Portable Network Graphics"), '.png')] def export_raster_interactive(context, alpha = 0, use_bbox = 0, render_ppi=72): # popup a filedialog and export the document doc = context.document # construct the tk filetypes list extensions = {} for text, ext in filelist: extensions[ext] = 1 # determine a default filename basename = os.path.splitext(doc.meta.filename)[0] if alpha: default_ext = '.png' # shift png up in filetypes so it is displayed accordingly filetypes=tuple(filelist[-1:]+filelist[1:-1]) else: default_ext = '.ppm' filetypes=tuple(filelist) filename = context.application.GetSaveFilename( title = _("Export Raster"), filetypes = filetypes, initialdir = doc.meta.directory, initialfile = basename + default_ext) if filename: ext = os.path.splitext(filename)[1] if extensions.has_key(ext): if alpha: export_alpha(context, filename, render_ppi, use_bbox) else: export_raster(context, filename, render_ppi, use_bbox) else: message = _("unknown extension %s") % ext context.application.MessageBox(title = _("Export Raster"), message = message) Sketch.Scripting.AddFunction('export_raster', _("Export Raster"), export_raster_more_interactive, script_type = Sketch.Scripting.AdvancedScript) #Sketch.Scripting.AddFunction('export_raster', 'Export Raster Alpha (Default)', # export_raster_interactive, args = (1,0), # script_type = Sketch.Scripting.AdvancedScript) Sketch.Scripting.AddFunction('export_raster', _("Export Raster Alpha (100ppi)"), export_raster_interactive, args = (1,0,100), script_type = Sketch.Scripting.AdvancedScript) #Sketch.Scripting.AddFunction('export_raster', 'Export Raster Alpha (120ppi)', # export_raster_interactive, args = (1,0,120), # script_type = Sketch.Scripting.AdvancedScript)