#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, tempfile, os, os.path, pprint, subprocess
import FreeImagePy as FIP
EXE_WHICH = "/bin/which"
class ConvertsionError(Exception): pass
class GhostscriptError(IOError): pass
class GhostscriptPathNotFound(GhostscriptError): pass
class Hylaimage(object):
""" Class for make all the transformation needed for
send a receive the fax with hylafax/hylapex.
"""
def __init__(self, freeimagepath=None, imagelist=None,
tmp_path=None, tmp_prefix=None,
path_gs_exe=None, path_gs_home=None,
debug_funct=None, debug=0):
super(Hylaimage, self).__init__()
#Freeimage lib
self._freeimagepath = freeimagepath
self._image = None
#Some debug work
self.debug_funct = debug_funct
self.debug = debug
self._ldebug1 = debug > 0
self._ldebug2 = debug > 1
#Ghostscript paths
self.path_gs_exe = path_gs_exe
self.path_gs_home = path_gs_home
#This will be load at self._ctrlGsPath
self.path_gs_lib = None
self.path_gs_font = None
self._ctrlGsPath()
#Some default parameters
self.image_list = imagelist or []
self.tmp_path = tmp_path or tempfile.gettempdir()
self.tmp_prefix = tmp_prefix or "hylaiamge_"
self._image = None
#
# Interface methods
#
def AddFile(self, path):
""" Add a file path to the image list
"""
if not isinstance(path, (tuple, list)):
path = [path]
for p in path:
try:
#Make sure that the file are avaible and accessible
file(p, 'rb').read(1)
except IOError:
raise IOError("Path not found or not accessible: %s" % p)
self.image_list += path
def GetSingleImage(self):
""" Return the image list converted into one,
multipage, tiff file.
"""
imagelist = []
for ii in self.image_list:
header = open(ii, 'rb').read(4)
if header in (r'%PDF', r'%!PS'):
#We have a ps or a pdf file here
imagelist += self._convertPs(ii)
else:
imagelist.append( ii )
self._loadFIP()
#Create a temp file
fo = self._createTempFile()
ret = self._image.convertToMultiPage(imagelist, fo,
convertToFax=1)
if ret[0]:
raise ConvertsionError, "Error on image conversion: %s" % ret[1]
return fo
def DeleteFiles(self):
""" Delete the file create by me
"""
for path in os.listdir(self.tmp_path):
if not path.startswith(self.tmp_prefix): continue
try: os.remove(os.path.join(self.tmp_path, path) )
except OSError: pass
#
# Internal methods
#
def _convertPs(self, path_in, path_out=None, savetype=None, ext=None):
""" Convert a file from ps or pdf to tiff
"""
savetype = savetype or "pnggray"
ext = ext or "png"
path_out = path_out or self._createTempFile(ext)
if self._ldebug1:
self._debug( "Start convert %s to %s, type: %s" % (path_in, path_out, savetype) )
path_out += ('%d.' + ext)
#Standard args
args = ['-q', '-dNOPAUSE', '-r204x196', '-dBATCH', '-sPAPERSIZE=a4', '-sDEVICE=%s' % savetype]
#if we are on win, we need also the font and library path for make gs work
if sys.platform.startswith('win'):
args += ['-I%s;%s' % (self.path_gs_lib, self.path_gs_font)]
#Create argoments
command = [ self.path_gs_exe ] + args
command += ['-sOutputFile=%s' % path_out, "%s" % path_in ]
if self._ldebug1:
self._debug( 'Execute the conversion: %s' % str(command))
sp = subprocess.Popen(command, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = sp.communicate()
if self._ldebug1:
self._debug( 'Conversion return code: %s' % str(sp.returncode))
if sp.returncode or self._ldebug2:
self._debug( 'Conversion out: %s' % str(out))
self._debug( 'Conversion err: %s' % str(err))
if sp.returncode:
#There is an error on conversion
if not self._ldebug1:
#If not already seen the messagges, print whem
self._debug( 'Conversion out: %s' % str(out))
self._debug( 'Conversion err: %s' % str(err))
raise GhostscriptError("Error while converting file with gs. See the error log.")
f_name = path_out[:path_out.find('%')]
# The conversion with gs is ended, look for how many pages it has create
dir_work = os.path.dirname(f_name)
f_name = os.path.basename(f_name)
f_name_len = len(f_name)
#Number of page
NP = 1
f_name_list = []
for i in os.listdir(dir_work):
if i[:f_name_len] == f_name and len(i) != f_name_len:
f_name_list.append(os.path.join(dir_work, f_name + str(NP) + '.' + ext))
NP += 1
return f_name_list
def _createTempFile(self, ext=None):
""" Common method for create temp file
"""
ext = ext or '.tif'
fd, fo = tempfile.mkstemp(ext, self.tmp_prefix, self.tmp_path)
f = os.fdopen(fd)
f.close()
del f
return fo
def _ctrlGsPath(self):
"""
"""
if self._ldebug2: self._debug("Control gs path")
if sys.platform.startswith('win'):
#we are on win, control if all exists
msg_err = ("Ghostscript path not found (Home:%s - Exe:%s). I need it!" %
(self.path_gs_home, self.path_gs_exe))
if ( not self.path_gs_exe or
(self.path_gs_exe and not os.path.exists(self.path_gs_exe))):
#None exists, raise
raise GhostscriptPathNotFound("path_gs_home not set or not accessible!\n" + msg_err)
elif not self.path_gs_home and self.path_gs_exe and os.path.exists(self.path_gs_exe):
msg = """
Try to search for a suitable gs home path
Here we need the path somethnig like:
gs854w32\gs8.54\bin\gswin32c.exe
So split the exe, control if the lib dir exists and if there is the
gs_init.ps file. If all are ok, go with it!
"""
#Control
gs_bin_base = os.path.split(self.path_gs_exe)[0]
gs_base = os.path.split(gs_bin_base)[0]
if not os.path.isdir(os.path.join(gs_base, "lib")):
raise GhostscriptError(msg_err)
if not os.path.exists(os.path.join(gs_base, "lib", "gs_init.ps")):
raise GhostscriptError(msg_err)
self.path_gs_home = gs_base
self.path_gs_lib = os.path.join(self.path_gs_home, 'lib')
if self._ldebug2: self._debug("We are on windows")
if self._ldebug1: self._debug("Gs path home: %s" % self.path_gs_home)
if self._ldebug1: self._debug("Gs path lib: %s" % self.path_gs_lib)
if not ( os.path.exists(self.path_gs_home) and
os.path.exists(self.path_gs_lib) and
os.path.exists(self.path_gs_exe)):
msg_err = ("Ghostscript path not found (Home:%s - Lib:%s - Exe:%s). I need it!" %
(self.path_gs_home, self.path_gs_lib, self.path_gs_exe))
raise GhostscriptPathNotFound(msg_err)
#Create font path
self.path_gs_font = os.path.join(
os.path.normpath( os.path.join(self.path_gs_home, '..\\') ),
'fonts')
if self._ldebug1: self._debug("Gs path fonts: %s" % self.path_gs_font)
else:
#assuming that all are ok and I can call gs without problems
#test only if ghostscript exists
if self._ldebug2: self._debug("We are on *nix")
po = subprocess.Popen([EXE_WHICH, 'gs'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = po.communicate()
if po.returncode:
raise GhostscriptError, ("Ghostscript not found into the path")
#Remove the \n at the end
self.path_gs_exe = out.strip()
if self._ldebug1: self._debug("Ghostscript found at %s" % self.path_gs_exe)
def _debug(self, *msg, **kw):
""" Debug function
"""
msgP = ''
for m in msg: msgP += str(m)
for v in kw.itervalues(): msgP += str(v)
if callable(self.debug_funct):
call = self.debug_funct
else:
call = pprint.pprint
call(msgP)
def _loadFIP(self):
""" Load FreeImagePy if need
"""
if self._image: return
self._image = FIP.Image()
if __name__ == "__main__":
i = Hylaimage(debug=2)
#i = Hylaimage(debug=2, path_gs_exe=r"V:\hylapex\bin\gs854w32\gs8.54\bin\gswin32c.exe",
# path_gs_home=r"V:\hylapex\bin\gs854w32\gs8.54")
i.DeleteFiles()
#i._convertPs("/tmp/cp 1.pdf")
#i._convertPs(r"V:\hylapex\library\ftp\cp 1.pdf")
i.AddFile( "/tmp/cp.pdf")
print i.GetSingleImage()
|