#! /usr/bin/python

''' Convert postscript files to image files using ghostscript.

    Usage: gsconvert.py infile outfile

    Both arguments are required; the extension must match
    the type of file.  In particular, the extension of
    "outfile" must be one of 'jpg', 'png', 'pgm', 'pnm',
    or 'ppm', yielding conversion to one of these types.

    The module may also be imported:

    from gsconvert import gsconvert
    gsconvert(infilename, outfilename, [margin])

    The bounding box of the postscript file is used to
    calculate the size of the image file, and the amount by
    which the image must be shifted on the page to eliminate
    all but a small margin.

'''

import sys, os, re, string


class gsconvert_Error(Exception):
   pass

def gsconvert(infilename, outfilename, margin = 6):

   (infileroot, infileext) = os.path.splitext(infilename)
   (outfileroot, outfileext) = os.path.splitext(outfilename)
   gshelp = os.popen('gs --help').read()

   gsdev_mo = re.search('Available devices:(.*)Search path', gshelp, re.S)
   gsdev_str = gsdev_mo.group(1)
   gsdev_list = string.split(gsdev_str)

   gsdev_dict = {'jpg' : 'jpeg',
                 'png' : 'png16m',
                 'pgm' : 'pgmraw',
                 'pnm' : 'pnmraw',
                 'ppm' : 'ppmraw'}

   gsdev = gsdev_dict[outfileext[1:]]
   print gsdev

   if not gsdev in gsdev_list:
      print 'gs lacks device ', gsdev
      raise gsconvert_Error

   bb_pat = re.compile('%%BoundingBox:\s*(\d+)\s*(\d+)\s*(\d+)\s*(\d+)')
   ps = open(infilename).read()
   bbox_str = bb_pat.search(ps).groups()
   (llx, lly, urx, ury) = map(int, bbox_str)

   width = urx - llx + 2 * margin
   height = ury - lly + 2 * margin
   shiftleft = llx - margin
   shiftdown = lly - margin

   gs_shift = '%d neg %d neg translate\n' % (shiftleft, shiftdown)
   print gs_shift
   gs_geometry = '-g%dx%d' % (width, height)
   gs_out = '-sOutputFile=' + outfilename
   gs_dev = '-sDEVICE=' + gsdev
   # The following seem to have no effect with the png etc files.
   #gs_other = '-dNOINTERPOLATE'
   #gs_other = '-dDOINTERPOLATE'
   gs_other = ''
   gs_cmd = string.join(('gs', '-q', gs_dev, gs_out,
                              gs_other, gs_geometry, '-', infilename))
   print gs_cmd
   os.popen(gs_cmd, 'w').write(gs_shift)


if __name__ == '__main__':
   if len(sys.argv) != 3:
      print __doc__
      sys.exit()
   gsconvert(sys.argv[1], sys.argv[2])


