120 lines
4.8 KiB
Python
120 lines
4.8 KiB
Python
import subprocess
|
|
import re
|
|
|
|
from converter.conf.settings import GM_PATH
|
|
from converter.conf.settings import GM_SETTINGS
|
|
from converter.exceptions import ConvertError, UnknownFileFormat, \
|
|
IdentifyError
|
|
from converter.backends import ConverterBase
|
|
from converter.literals import TRANSFORMATION_RESIZE, \
|
|
TRANSFORMATION_ROTATE, TRANSFORMATION_ZOOM
|
|
from converter.literals import DIMENSION_SEPARATOR, DEFAULT_PAGE_NUMBER, \
|
|
DEFAULT_FILE_FORMAT
|
|
|
|
CONVERTER_ERROR_STRING_NO_DECODER = u'No decode delegate for this image format'
|
|
CONVERTER_ERROR_STARTS_WITH = u'starts with'
|
|
|
|
|
|
class ConverterClass(ConverterBase):
|
|
def identify_file(self, input_filepath, arguments=None):
|
|
command = []
|
|
command.append(unicode(GM_PATH))
|
|
command.append(u'identify')
|
|
if arguments:
|
|
command.extend(arguments)
|
|
command.append(unicode(input_filepath))
|
|
proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
|
return_code = proc.wait()
|
|
if return_code != 0:
|
|
raise IdentifyError(proc.stderr.readline())
|
|
return proc.stdout.read()
|
|
|
|
def convert_file(self, input_filepath, output_filepath, transformations=None, page=DEFAULT_PAGE_NUMBER, file_format=DEFAULT_FILE_FORMAT):
|
|
arguments = []
|
|
|
|
try:
|
|
if transformations:
|
|
for transformation in transformations:
|
|
if transformation['transformation'] == TRANSFORMATION_RESIZE:
|
|
dimensions = []
|
|
dimensions.append(unicode(transformation['arguments']['width']))
|
|
if 'height' in transformation['arguments']:
|
|
dimensions.append(unicode(transformation['arguments']['height']))
|
|
arguments.append(u'-resize')
|
|
arguments.append(u'%s' % DIMENSION_SEPARATOR.join(dimensions))
|
|
|
|
elif transformation['transformation'] == TRANSFORMATION_ZOOM:
|
|
arguments.append(u'-resize')
|
|
arguments.append(u'%d%%' % transformation['arguments']['percent'])
|
|
|
|
elif transformation['transformation'] == TRANSFORMATION_ROTATE:
|
|
arguments.append(u'-rotate')
|
|
arguments.append(u'%s' % transformation['arguments']['degrees'])
|
|
except:
|
|
pass
|
|
|
|
if file_format.lower() == u'jpeg' or file_format.lower() == u'jpg':
|
|
arguments.append(u'-quality')
|
|
arguments.append(u'85')
|
|
|
|
# Graphicsmagick page number is 0 base
|
|
input_arg = u'%s[%d]' % (input_filepath, page - 1)
|
|
|
|
# Specify the file format next to the output filename
|
|
output_filepath = u'%s:%s' % (file_format, output_filepath)
|
|
|
|
command = []
|
|
command.append(unicode(GM_PATH))
|
|
command.append(u'convert')
|
|
command.extend(unicode(GM_SETTINGS).split())
|
|
command.append(unicode(input_arg))
|
|
if arguments:
|
|
command.extend(arguments)
|
|
command.append(unicode(output_filepath))
|
|
proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
|
return_code = proc.wait()
|
|
if return_code != 0:
|
|
#Got an error from convert program
|
|
error_line = proc.stderr.readline()
|
|
if (CONVERTER_ERROR_STRING_NO_DECODER in error_line) or (CONVERTER_ERROR_STARTS_WITH in error_line):
|
|
#Try to determine from error message which class of error is it
|
|
raise UnknownFileFormat
|
|
else:
|
|
raise ConvertError(error_line)
|
|
|
|
def get_format_list(self):
|
|
"""
|
|
Call GraphicsMagick to parse all of it's supported file formats, and
|
|
return a list of the names and descriptions
|
|
"""
|
|
format_regex = re.compile(' *([A-Z0-9]+)[*]? +([A-Z0-9]+) +([rw\-+]+) *(.*).*')
|
|
formats = []
|
|
command = []
|
|
command.append(unicode(GM_PATH))
|
|
command.append(u'convert')
|
|
command.append(u'-list')
|
|
command.append(u'formats')
|
|
proc = subprocess.Popen(command, close_fds=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
|
return_code = proc.wait()
|
|
if return_code != 0:
|
|
raise ConvertError(proc.stderr.readline())
|
|
|
|
for line in proc.stdout.readlines():
|
|
fields = format_regex.findall(line)
|
|
if fields:
|
|
formats.append(fields[0][0])
|
|
|
|
return formats
|
|
|
|
def get_available_transformations(self):
|
|
return [
|
|
TRANSFORMATION_RESIZE, TRANSFORMATION_ROTATE, \
|
|
TRANSFORMATION_ZOOM
|
|
]
|
|
|
|
def get_page_count(self, input_filepath):
|
|
try:
|
|
return len(self.identify_file(unicode(input_filepath)).splitlines())
|
|
except IdentifyError:
|
|
raise UnknownFileFormat
|