summaryrefslogtreecommitdiff
path: root/src/img2pdf.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/img2pdf.py')
-rwxr-xr-xsrc/img2pdf.py181
1 files changed, 63 insertions, 118 deletions
diff --git a/src/img2pdf.py b/src/img2pdf.py
index 764e745..ef438b5 100755
--- a/src/img2pdf.py
+++ b/src/img2pdf.py
@@ -34,9 +34,15 @@ import logging
import struct
import platform
-PY3 = sys.version_info[0] >= 3
+with_pdfrw = False
+try:
+ import pdfrw
-__version__ = "0.3.4"
+ with_pdfrw = True
+except ImportError:
+ pass
+
+__version__ = "0.3.5"
default_dpi = 96.0
papersizes = {
"letter": "8.5inx11in",
@@ -566,49 +572,26 @@ class MyPdfWriter:
self.addobj(page)
-if PY3:
-
- class MyPdfString:
- @classmethod
- def encode(cls, string, hextype=False):
- if hextype:
- return (
- b"< "
- + b" ".join(("%06x" % c).encode("ascii") for c in string)
- + b" >"
- )
- else:
- try:
- string = string.encode("ascii")
- except UnicodeEncodeError:
- string = b"\xfe\xff" + string.encode("utf-16-be")
- # We should probably encode more here because at least
- # ghostscript interpretes a carriage return byte (0x0D) as a
- # new line byte (0x0A)
- # PDF supports: \n, \r, \t, \b and \f
- string = string.replace(b"\\", b"\\\\")
- string = string.replace(b"(", b"\\(")
- string = string.replace(b")", b"\\)")
- return b"(" + string + b")"
-
-
-else:
-
- class MyPdfString(object):
- @classmethod
- def encode(cls, string, hextype=False):
- if hextype:
- return (
- b"< "
- + b" ".join(("%06x" % c).encode("ascii") for c in string)
- + b" >"
- )
- else:
- # This mimics exactely to what pdfrw does.
- string = string.replace(b"\\", b"\\\\")
- string = string.replace(b"(", b"\\(")
- string = string.replace(b")", b"\\)")
- return b"(" + string + b")"
+class MyPdfString:
+ @classmethod
+ def encode(cls, string, hextype=False):
+ if hextype:
+ return (
+ b"< " + b" ".join(("%06x" % c).encode("ascii") for c in string) + b" >"
+ )
+ else:
+ try:
+ string = string.encode("ascii")
+ except UnicodeEncodeError:
+ string = b"\xfe\xff" + string.encode("utf-16-be")
+ # We should probably encode more here because at least
+ # ghostscript interpretes a carriage return byte (0x0D) as a
+ # new line byte (0x0A)
+ # PDF supports: \n, \r, \t, \b and \f
+ string = string.replace(b"\\", b"\\\\")
+ string = string.replace(b"(", b"\\(")
+ string = string.replace(b")", b"\\)")
+ return b"(" + string + b")"
class pdfdoc(object):
@@ -631,25 +614,14 @@ class pdfdoc(object):
fit_window=False,
center_window=False,
fullscreen=False,
- with_pdfrw=True,
):
if with_pdfrw:
- try:
- from pdfrw import PdfWriter, PdfDict, PdfName, PdfString
-
- self.with_pdfrw = True
- except ImportError:
- PdfWriter = MyPdfWriter
- PdfDict = MyPdfDict
- PdfName = MyPdfName
- PdfString = MyPdfString
- self.with_pdfrw = False
+ from pdfrw import PdfWriter, PdfDict, PdfName, PdfString
else:
PdfWriter = MyPdfWriter
PdfDict = MyPdfDict
PdfName = MyPdfName
PdfString = MyPdfString
- self.with_pdfrw = False
now = datetime.now()
self.info = PdfDict(indirect=True)
@@ -690,7 +662,7 @@ class pdfdoc(object):
self.writer.version = version
# this is done because pdfrw adds info, catalog and pages as the first
# three objects in this order
- if not self.with_pdfrw:
+ if not with_pdfrw:
self.writer.addobj(self.info)
self.writer.addobj(self.writer.catalog)
self.writer.addobj(self.writer.pages)
@@ -726,7 +698,7 @@ class pdfdoc(object):
trimborder=None,
artborder=None,
):
- if self.with_pdfrw:
+ if with_pdfrw:
from pdfrw import PdfDict, PdfName, PdfObject, PdfString
from pdfrw.py23_diffs import convert_load
else:
@@ -743,7 +715,7 @@ class pdfdoc(object):
elif color == Colorspace.CMYK or color == Colorspace["CMYK;I"]:
colorspace = PdfName.DeviceCMYK
elif color == Colorspace.P:
- if self.with_pdfrw:
+ if with_pdfrw:
raise Exception(
"pdfrw does not support hex strings for "
"palette image input, re-run with "
@@ -871,7 +843,7 @@ class pdfdoc(object):
self.writer.addpage(page)
- if not self.with_pdfrw:
+ if not with_pdfrw:
self.writer.addobj(content)
self.writer.addobj(image)
@@ -881,7 +853,7 @@ class pdfdoc(object):
return stream.getvalue()
def tostream(self, outputstream):
- if self.with_pdfrw:
+ if with_pdfrw:
from pdfrw import PdfDict, PdfName, PdfArray, PdfObject
else:
PdfDict = MyPdfDict
@@ -899,7 +871,7 @@ class pdfdoc(object):
# is added, so we can only start using it after all pages have been
# written.
- if self.with_pdfrw:
+ if with_pdfrw:
catalog = self.writer.trailer.Root
else:
catalog = self.writer.catalog
@@ -1005,7 +977,7 @@ class pdfdoc(object):
raise ValueError("unknown page layout: %s" % self.page_layout)
# now write out the PDF
- if self.with_pdfrw:
+ if with_pdfrw:
self.writer.trailer.Info = self.info
self.writer.write(outputstream)
else:
@@ -1809,7 +1781,6 @@ def convert(*images, **kwargs):
viewer_fit_window=False,
viewer_center_window=False,
viewer_fullscreen=False,
- with_pdfrw=True,
outputstream=None,
first_frame_only=False,
allow_oversized=True,
@@ -1821,6 +1792,9 @@ def convert(*images, **kwargs):
for kwname, default in _default_kwargs.items():
if kwname not in kwargs:
kwargs[kwname] = default
+ if "with_pdfrw" in kwargs:
+ global with_pdfrw
+ with_pdfrw = kwargs["with_pdfrw"]
pdf = pdfdoc(
"1.3",
@@ -1840,7 +1814,6 @@ def convert(*images, **kwargs):
kwargs["viewer_fit_window"],
kwargs["viewer_center_window"],
kwargs["viewer_fullscreen"],
- kwargs["with_pdfrw"],
)
# backwards compatibility with older img2pdf versions where the first
@@ -2111,39 +2084,23 @@ def parse_borderarg(string):
def input_images(path):
if path == "-":
# we slurp in all data from stdin because we need to seek in it later
- if PY3:
- result = sys.stdin.buffer.read()
- else:
- result = sys.stdin.read()
+ result = sys.stdin.buffer.read()
if len(result) == 0:
raise argparse.ArgumentTypeError('"%s" is empty' % path)
else:
- if PY3:
- try:
- if os.path.getsize(path) == 0:
- raise argparse.ArgumentTypeError('"%s" is empty' % path)
- # test-read a byte from it so that we can abort early in case
- # we cannot read data from the file
- with open(path, "rb") as im:
- im.read(1)
- except IsADirectoryError:
- raise argparse.ArgumentTypeError('"%s" is a directory' % path)
- except PermissionError:
- raise argparse.ArgumentTypeError('"%s" permission denied' % path)
- except FileNotFoundError:
- raise argparse.ArgumentTypeError('"%s" does not exist' % path)
- else:
- try:
- if os.path.getsize(path) == 0:
- raise argparse.ArgumentTypeError('"%s" is empty' % path)
- # test-read a byte from it so that we can abort early in case
- # we cannot read data from the file
- with open(path, "rb") as im:
- im.read(1)
- except IOError as err:
- raise argparse.ArgumentTypeError(str(err))
- except OSError as err:
- raise argparse.ArgumentTypeError(str(err))
+ try:
+ if os.path.getsize(path) == 0:
+ raise argparse.ArgumentTypeError('"%s" is empty' % path)
+ # test-read a byte from it so that we can abort early in case
+ # we cannot read data from the file
+ with open(path, "rb") as im:
+ im.read(1)
+ except IsADirectoryError:
+ raise argparse.ArgumentTypeError('"%s" is a directory' % path)
+ except PermissionError:
+ raise argparse.ArgumentTypeError('"%s" permission denied' % path)
+ except FileNotFoundError:
+ raise argparse.ArgumentTypeError('"%s" does not exist' % path)
result = path
return result
@@ -2492,6 +2449,9 @@ def gui():
v for v in Colorspace if v.name == args["colorspace"].get()
)
+ global with_pdfrw
+ if with_pdfrw:
+ with_pdfrw = not args["without_pdfrw"].get()
convert(
*infiles,
title=args["title"].get() if args["title"].get() else None,
@@ -2516,7 +2476,6 @@ def gui():
viewer_fit_window=(args["viewer_fit_window"].get() or None),
viewer_center_window=(args["viewer_center_window"].get() or None),
viewer_fullscreen=(args["viewer_fullscreen"].get() or None),
- with_pdfrw=not args["without_pdfrw"].get(),
outputstream=stream,
first_frame_only=args["first_frame_only"].get(),
cropborder=None,
@@ -2631,6 +2590,7 @@ def gui():
variable=args["nodate"],
state=tkinter.DISABLED,
).grid(row=1, column=0, columnspan=2, sticky=tkinter.W)
+ # TODO: only have this checkbox enabled if pdfrw is installed
tkinter.Checkbutton(
output_options,
text="without pdfrw",
@@ -3085,23 +3045,9 @@ Report bugs at https://gitlab.mister-muffin.de/josch/img2pdf/issues
version="%(prog)s " + __version__,
help="Prints version information and exits.",
)
- gui_group = parser.add_mutually_exclusive_group(required=False)
- gui_group.add_argument(
- "--gui",
- dest="gui",
- action="store_true",
- help="run tkinter gui (default on Windows)",
- )
- gui_group.add_argument(
- "--nogui",
- dest="gui",
- action="store_false",
- help="don't run tkinter gui (default elsewhere)",
+ parser.add_argument(
+ "--gui", dest="gui", action="store_true", help="run experimental tkinter gui"
)
- if platform.system() == "Windows":
- parser.set_defaults(gui=True)
- else:
- parser.set_defaults(gui=False)
outargs = parser.add_argument_group(
title="General output arguments",
@@ -3465,10 +3411,7 @@ and left/right, respectively. It is not possible to specify asymmetric borders.
if len(args.images) == 0:
logging.info("reading image from standard input")
try:
- if PY3:
- args.images = [sys.stdin.buffer.read()]
- else:
- args.images = [sys.stdin.read()]
+ args.images = [sys.stdin.buffer.read()]
except KeyboardInterrupt:
exit(0)
@@ -3490,6 +3433,9 @@ and left/right, respectively. It is not possible to specify asymmetric borders.
)
exit(2)
+ global with_pdfrw
+ if with_pdfrw:
+ with_pdfrw = not args.without_pdfrw
try:
convert(
*args.images,
@@ -3511,7 +3457,6 @@ and left/right, respectively. It is not possible to specify asymmetric borders.
viewer_fit_window=args.viewer_fit_window,
viewer_center_window=args.viewer_center_window,
viewer_fullscreen=args.viewer_fullscreen,
- with_pdfrw=not args.without_pdfrw,
outputstream=args.output,
first_frame_only=args.first_frame_only,
cropborder=args.crop_border,