#!/usr/local/bin/python # -*- coding: iso-8859-1 -*- # # Convert a PNM file (.ppm, .pgm, .pbm) to PostScript. # See the usage message for details. # # Requires /usr/local/bin/convert from ImageMagick to be installed. # (On FreeBSD it is available from /usr/ports/graphics/ImageMagick.) # # Copyright (c) 2005-2010 by Oliver Fromme, Munich, Germany. # # import sys, getopt, re, os, os.path # The default is to use ISO A4 paper # and no additional border. paper_width = 21.0 paper_height = 29.7 border = 1.0 debug = 0 convert = "/usr/local/bin/convert" me = os.path.basename(sys.argv[0]) def usage(): "Print the usage message and exit." sys.stderr.writelines (( "Usage: %s [] [...]\n" % me, "Options:\n", " -d print debug info, don't execute commands\n", " -w specify paper width (in cm)\n", " -h specify paper height (in cm)\n", " -b specify border (in cm)\n", "All numbers are interpreted as centimeters.\n", "The defaults are -w 21.0 -h 27.9 (ISO A4) and -b 1.0.\n", "Output files are named *.ps.", )) sys.exit (1) def die (msg, what = None): "Print an error message and exit" if what: errmsg = "%s: %s: %s\n" %(me, what, msg) else: errmsg = "%s: %s\n" %(me, msg) sys.stderr.write (errmsg) sys.exit (1) def check_float (string): "Convert string to float and check for error." try: return float(string) except ValueError: die ("Illegal number.", string) def cm2pp (cm): "Convert centimeters to PostScript points." return cm / 2.54 * 72 tokens = [] def read_pnm_token (file): "Read a token from a PNM file (skips comments etc.)." global tokens while not tokens: line = file.readline() if not line: die ("Unexpected EOF.", file.name) com = line.find("#") if com >= 0: line = line[:com] line = line.strip() if not line: continue tokens = line.split() next_token = tokens[0] del tokens[0] return next_token # # The "main" program starts here. # try: opts, args = getopt.getopt(sys.argv[1:], "dw:h:b:") except getopt.GetoptError: usage() if not args: usage() for opt, par in opts: if opt == "-d": debug = 1 elif opt == "-w": paper_width = check_float(par) elif opt == "-h": paper_height = check_float(par) elif opt == "-b": border = check_float(par) else: raise "Internal error: options inconsistency" dest_width = paper_width - 2 * border dest_height = paper_height - 2 * border landscape = dest_width > dest_height if debug: print "Debug mode is ON. No actual commands are executed." print "Paper size: ", paper_width, "x", paper_height, "cm", print ["(portrait)", "(landscape)"][landscape], print "with", border, "cm border." print "Printable area: ", dest_width, "x", dest_height, "cm." for src in args: try: file = open(src) except IOError, bang: die (bang.strerror, src) if not re.match("^P[1-6]", read_pnm_token(file)): die ("Not a PNM file.", src) try: img_width = int(read_pnm_token(file)) img_height = int(read_pnm_token(file)) except ValueError: die ("Can't find width and height in PNM file.", src) file.close() if debug: print "\nFile %s: " % src, print img_width, "x", img_height, "pixels." rotate = landscape == (img_width < img_height) if rotate: img_width, img_height = img_height, img_width if debug: print "(Rotating image to better fit the page.)" # pixels per centimeter ppc = max ( img_width / dest_width, img_height / dest_height ) left_margin = (paper_width - img_width / ppc) / 2 bottom_margin = (paper_height - img_height / ppc) / 2 if debug: print "Using a resolution of", ppc, "pixels per cm." print "Positioning image at x =", left_margin, print "cm and y =", bottom_margin, "cm." if rotate: cmd = convert + " -rotate -90" else: cmd = convert cmd = "%s -density %fx%f -page %dx%d+%d+%d %s %s.ps" % ( cmd, ppc * 2.54, ppc * 2.54, img_width, img_height, cm2pp(left_margin), cm2pp(bottom_margin), src, os.path.splitext(src)[0] ) if debug: print "NOT executing command:\n", cmd else: os.system(cmd) #--