1
0
Fork 0
forked from josch/img2pdf

raise exceptions instead of doing an exit()

This commit is contained in:
Johannes 'josch' Schauer 2016-02-13 09:31:33 +01:00
parent 900346d430
commit cc59fbc3e4

View file

@ -73,7 +73,23 @@ Unit = Enum('Unit', 'pt cm mm inch')
ImgUnit = Enum('ImgUnit', 'pt cm mm inch perc dpi') ImgUnit = Enum('ImgUnit', 'pt cm mm inch perc dpi')
class NegativeDimensionException(Exception): class NegativeDimensionError(Exception):
pass
class UnsupportedColorspaceError(Exception):
pass
class ImageOpenError(Exception):
pass
class MonochromeJpegError(Exception):
pass
class PdfTooLargeError(Exception):
pass pass
@ -103,13 +119,13 @@ def parse(cont, indent=1):
return parse(cont.content, indent) return parse(cont.content, indent)
elif type(cont) is str or isinstance(cont, bytes): elif type(cont) is str or isinstance(cont, bytes):
if type(cont) is str and type(cont) is not bytes: if type(cont) is str and type(cont) is not bytes:
raise Exception( raise TypeError(
"parse must be passed a bytes object in py3. Got: %s" % cont) "parse must be passed a bytes object in py3. Got: %s" % cont)
return cont return cont
elif isinstance(cont, list): elif isinstance(cont, list):
return b"[ "+b" ".join([parse(c, indent) for c in cont])+b" ]" return b"[ "+b" ".join([parse(c, indent) for c in cont])+b" ]"
else: else:
raise Exception("cannot handle type %s with content %s" % (type(cont), raise TypeError("cannot handle type %s with content %s" % (type(cont),
cont)) cont))
@ -351,8 +367,8 @@ class pdfdoc(object):
elif color == Colorspace.CMYK or color == Colorspace['CMYK;I']: elif color == Colorspace.CMYK or color == Colorspace['CMYK;I']:
colorspace = PdfName.DeviceCMYK colorspace = PdfName.DeviceCMYK
else: else:
logging.error("unsupported color space: %s", color.name) raise UnsupportedColorspaceError("unsupported color space: %s"
exit(1) % color.name)
# either embed the whole jpeg or deflate the bitmap representation # either embed the whole jpeg or deflate the bitmap representation
if imgformat is ImageFormat.JPEG: if imgformat is ImageFormat.JPEG:
@ -447,7 +463,7 @@ class pdfdoc(object):
elif self.panes in [PageMode.none, None]: elif self.panes in [PageMode.none, None]:
pass pass
else: else:
raise Exception("unknown page mode: %s" % self.panes) raise ValueError("unknown page mode: %s" % self.panes)
if self.fit_window: if self.fit_window:
catalog[PdfName.ViewerPreferences][PdfName.FitWindow] = TrueObject catalog[PdfName.ViewerPreferences][PdfName.FitWindow] = TrueObject
@ -501,7 +517,7 @@ class pdfdoc(object):
elif self.magnification is None: elif self.magnification is None:
pass pass
else: else:
raise Exception("unknown magnification: %s" % self.magnification) raise ValueError("unknown magnification: %s" % self.magnification)
if self.page_layout == PageLayout.single: if self.page_layout == PageLayout.single:
catalog[PdfName.PageLayout] = PdfName.SinglePage catalog[PdfName.PageLayout] = PdfName.SinglePage
@ -514,7 +530,7 @@ class pdfdoc(object):
elif self.page_layout is None: elif self.page_layout is None:
pass pass
else: else:
raise Exception("unknown page layout: %s" % self.page_layout) raise ValueError("unknown page layout: %s" % self.page_layout)
# now write out the PDF # now write out the PDF
if self.with_pdfrw: if self.with_pdfrw:
@ -532,9 +548,8 @@ def read_image(rawdata, colorspace):
except IOError as e: except IOError as e:
# test if it is a jpeg2000 image # test if it is a jpeg2000 image
if rawdata[:12] != "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A": if rawdata[:12] != "\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A":
logging.error("cannot read input image (not jpeg2000)") raise ImageOpenError("cannot read input image (not jpeg2000). "
logging.error("PIL: error reading image: %s", e) "PIL: error reading image: %s" % e)
exit(1)
# image is jpeg2000 # image is jpeg2000
imgwidthpx, imgheightpx, ics = parsejp2(rawdata) imgwidthpx, imgheightpx, ics = parsejp2(rawdata)
imgformat = ImageFormat.JPEG2000 imgformat = ImageFormat.JPEG2000
@ -556,7 +571,7 @@ def read_image(rawdata, colorspace):
if f.name == imgdata.format: if f.name == imgdata.format:
imgformat = f imgformat = f
if imgformat is None: if imgformat is None:
raise Exception("unknown PIL image format: %s" % imgdata.format) raise ValueError("unknown PIL image format: %s" % imgdata.format)
ndpi = imgdata.info.get("dpi", (default_dpi, default_dpi)) ndpi = imgdata.info.get("dpi", (default_dpi, default_dpi))
# In python3, the returned dpi value for some tiff images will # In python3, the returned dpi value for some tiff images will
@ -576,7 +591,7 @@ def read_image(rawdata, colorspace):
if c.name == imgdata.mode: if c.name == imgdata.mode:
color = c color = c
if color is None: if color is None:
raise Exception("unknown PIL colorspace: %s" % imgdata.mode) raise ValueError("unknown PIL colorspace: %s" % imgdata.mode)
if color == Colorspace.CMYK and imgformat == ImageFormat.JPEG: if color == Colorspace.CMYK and imgformat == ImageFormat.JPEG:
# Adobe inverts CMYK JPEGs for some reason, and others # Adobe inverts CMYK JPEGs for some reason, and others
# have followed suit as well. Some software assumes the # have followed suit as well. Some software assumes the
@ -596,8 +611,7 @@ def read_image(rawdata, colorspace):
# image or the zlib compressed color information # image or the zlib compressed color information
if imgformat == ImageFormat.JPEG or imgformat == ImageFormat.JPEG2000: if imgformat == ImageFormat.JPEG or imgformat == ImageFormat.JPEG2000:
if color == Colorspace['1']: if color == Colorspace['1']:
logging.error("jpeg can't be monochrome") raise MonochromeJpegError("jpeg can't be monochrome")
exit(1)
imgdata = rawdata imgdata = rawdata
else: else:
# because we do not support /CCITTFaxDecode # because we do not support /CCITTFaxDecode
@ -613,7 +627,7 @@ def read_image(rawdata, colorspace):
imgdata = imgdata.convert('RGB') imgdata = imgdata.convert('RGB')
color = Colorspace.RGB color = Colorspace.RGB
else: else:
raise Exception("unknown colorspace: %s" % color.name) raise ValueError("unknown colorspace: %s" % color.name)
img = imgdata.tobytes() img = imgdata.tobytes()
# the python-pil version 2.3.0-1ubuntu3 in Ubuntu does not have the # the python-pil version 2.3.0-1ubuntu3 in Ubuntu does not have the
# close() method # close() method
@ -647,13 +661,13 @@ def in_to_pt(length):
def get_layout_fun(pagesize, imgsize, border, fit, auto_orient): def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
def fitfun(fit, imgwidth, imgheight, fitwidth, fitheight): def fitfun(fit, imgwidth, imgheight, fitwidth, fitheight):
if fitwidth is None and fitheight is None: if fitwidth is None and fitheight is None:
raise Exception("fitwidth and fitheight cannot both be None") raise ValueError("fitwidth and fitheight cannot both be None")
# if fit is fill or enlarge then it is okay if one of the dimensions # if fit is fill or enlarge then it is okay if one of the dimensions
# are negative but one of them must still be positive # are negative but one of them must still be positive
# if fit is not fill or enlarge then both dimensions must be positive # if fit is not fill or enlarge then both dimensions must be positive
if fit in [FitMode.fill, FitMode.enlarge] and \ if fit in [FitMode.fill, FitMode.enlarge] and \
(fitwidth < 0 and fitheight < 0): (fitwidth < 0 and fitheight < 0):
raise Exception("cannot fit into a rectangle where both " raise ValueError("cannot fit into a rectangle where both "
"dimensions are negative") "dimensions are negative")
elif fit not in [FitMode.fill, FitMode.enlarge] and \ elif fit not in [FitMode.fill, FitMode.enlarge] and \
(fitwidth < 0 or fitheight < 0): (fitwidth < 0 or fitheight < 0):
@ -674,7 +688,7 @@ def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
newimgwidth = fitwidth newimgwidth = fitwidth
newimgheight = (newimgwidth * imgheight)/imgwidth newimgheight = (newimgwidth * imgheight)/imgwidth
else: else:
raise Exception("fitwidth and fitheight cannot both be None") raise ValueError("fitwidth and fitheight cannot both be None")
return newimgwidth, newimgheight return newimgwidth, newimgheight
if fit is None or fit == FitMode.into: if fit is None or fit == FitMode.into:
return default() return default()
@ -692,7 +706,7 @@ def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
newimgwidth = fitwidth newimgwidth = fitwidth
newimgheight = (newimgwidth * imgheight)/imgwidth newimgheight = (newimgwidth * imgheight)/imgwidth
else: else:
raise Exception("fitwidth and fitheight cannot both be None") raise ValueError("fitwidth and fitheight cannot both be None")
return newimgwidth, newimgheight return newimgwidth, newimgheight
elif fit == FitMode.exact: elif fit == FitMode.exact:
if fitwidth is not None and fitheight is not None: if fitwidth is not None and fitheight is not None:
@ -704,7 +718,7 @@ def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
newimgwidth = fitwidth newimgwidth = fitwidth
newimgheight = (newimgwidth * imgheight)/imgwidth newimgheight = (newimgwidth * imgheight)/imgwidth
else: else:
raise Exception("fitwidth and fitheight cannot both be None") raise ValueError("fitwidth and fitheight cannot both be None")
elif fit == FitMode.shrink: elif fit == FitMode.shrink:
if fitwidth is not None and fitheight is not None: if fitwidth is not None and fitheight is not None:
if imgwidth <= fitwidth and imgheight <= fitheight: if imgwidth <= fitwidth and imgheight <= fitheight:
@ -716,7 +730,7 @@ def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
if imgwidth <= fitwidth: if imgwidth <= fitwidth:
return imgwidth, imgheight return imgwidth, imgheight
else: else:
raise Exception("fitwidth and fitheight cannot both be None") raise ValueError("fitwidth and fitheight cannot both be None")
return default() return default()
elif fit == FitMode.enlarge: elif fit == FitMode.enlarge:
if fitwidth is not None and fitheight is not None: if fitwidth is not None and fitheight is not None:
@ -729,7 +743,7 @@ def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
if imgwidth > fitwidth: if imgwidth > fitwidth:
return imgwidth, imgheight return imgwidth, imgheight
else: else:
raise Exception("fitwidth and fitheight cannot both be None") raise ValueError("fitwidth and fitheight cannot both be None")
return default() return default()
else: else:
raise NotImplementedError raise NotImplementedError
@ -773,13 +787,13 @@ def get_layout_fun(pagesize, imgsize, border, fit, auto_orient):
if fit in [FitMode.fill, FitMode.enlarge] and \ if fit in [FitMode.fill, FitMode.enlarge] and \
fitwidth is not None and fitwidth < 0 and \ fitwidth is not None and fitwidth < 0 and \
fitheight is not None and fitheight < 0: fitheight is not None and fitheight < 0:
raise NegativeDimensionException( raise NegativeDimensionError(
"at least one border dimension musts be smaller than half " "at least one border dimension musts be smaller than half "
"the respective page dimension") "the respective page dimension")
elif fit not in [FitMode.fill, FitMode.enlarge] \ elif fit not in [FitMode.fill, FitMode.enlarge] \
and ((fitwidth is not None and fitwidth < 0) or and ((fitwidth is not None and fitwidth < 0) or
(fitheight is not None and fitheight < 0)): (fitheight is not None and fitheight < 0)):
raise NegativeDimensionException( raise NegativeDimensionError(
"one border dimension is larger than half of the " "one border dimension is larger than half of the "
"respective page dimension") "respective page dimension")
imgwidthpdf, imgheightpdf = \ imgwidthpdf, imgheightpdf = \
@ -879,8 +893,8 @@ def convert(*images, title=None,
logging.warning("pdf width or height is below 3.00 - too small " logging.warning("pdf width or height is below 3.00 - too small "
"for some viewers!") "for some viewers!")
elif pagewidth > 14400.0 or pageheight > 14400.0: elif pagewidth > 14400.0 or pageheight > 14400.0:
logging.error("pdf width or height must not exceed 200 inches.") raise PdfTooLargeError(
exit(1) "pdf width or height must not exceed 200 inches.")
# the image is always centered on the page # the image is always centered on the page
imgxpdf = (pagewidth - imgwidthpdf)/2.0 imgxpdf = (pagewidth - imgwidthpdf)/2.0
imgypdf = (pageheight - imgheightpdf)/2.0 imgypdf = (pageheight - imgheightpdf)/2.0
@ -1523,13 +1537,14 @@ values set via the --border option.
parser.prog) parser.prog)
exit(2) exit(2)
try:
convert( convert(
*args.images, title=args.title, author=args.author, *args.images, title=args.title, author=args.author,
creator=args.creator, producer=args.producer, creator=args.creator, producer=args.producer,
creationdate=args.creationdate, moddate=args.moddate, creationdate=args.creationdate, moddate=args.moddate,
subject=args.subject, keywords=args.keywords, subject=args.subject, keywords=args.keywords,
colorspace=args.colorspace, nodate=args.nodate, layout_fun=layout_fun, colorspace=args.colorspace, nodate=args.nodate,
viewer_panes=args.viewer_panes, layout_fun=layout_fun, viewer_panes=args.viewer_panes,
viewer_initial_page=args.viewer_initial_page, viewer_initial_page=args.viewer_initial_page,
viewer_magnification=args.viewer_magnification, viewer_magnification=args.viewer_magnification,
viewer_page_layout=args.viewer_page_layout, viewer_page_layout=args.viewer_page_layout,
@ -1537,6 +1552,9 @@ values set via the --border option.
viewer_center_window=args.viewer_center_window, viewer_center_window=args.viewer_center_window,
viewer_fullscreen=args.viewer_fullscreen, with_pdfrw=not viewer_fullscreen=args.viewer_fullscreen, with_pdfrw=not
args.without_pdfrw, outputstream=args.output) args.without_pdfrw, outputstream=args.output)
except Exception as e:
logging.error("error: " + str(e))
exit(1)
if __name__ == '__main__': if __name__ == '__main__':
main() main()