Coverage for pyguymer3/media/images2pdf.py: 5%
21 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def images2pdf(
5 imgs,
6 pdf,
7 /,
8 *,
9 author = "My Author",
10 keywords = "My Keywords",
11 mode = "RGB",
12 optimise = True,
13 progressive = False,
14 quality = 95,
15 resolution = 300,
16 screenHeight = -1,
17 screenWidth = -1,
18 subject = "My Subject",
19 title = "My Title",
20):
21 """Convert a sequence of images to a PDF slide pack.
23 This function makes a PDF slide pack from either a list of PIL Images or a
24 list of file paths.
26 Parameters
27 ----------
28 imgs : list of PIL.Image.Image or list of str
29 the list of input PIL Images or list of paths to the input images
30 pdf : str
31 the path to the output PDF
32 author : str, optional
33 The author field in the output PDF metadata
34 keywords : str, optional
35 The keywords field in the output PDF metadata
36 mode : str, optional
37 the mode of the JPGs in the outout PDF
38 optimise : bool, optional
39 optimise the JPGs in the output PDF
40 progressive : bool, optional
41 save progressive JPGs in the output PDF
42 quality : int, optional
43 the quality of the JPGs in the output PDF
44 resolution : int, optional
45 the resolution of the JPGs in the output PDF (has no effect on the JPGs,
46 but the physical size of the PDF is derived from the pixel size of the
47 JPGs)
48 screenHeight : int, optional
49 the height of the screen to downscale the input images to fit within,
50 currently only implemented if "imgs" is a list of str (integers less
51 than 100 imply no downscaling)
52 screenWidth : int, optional
53 the width of the screen to downscale the input images to fit within,
54 currently only implemented if "imgs" is a list of str (integers less
55 than 100 imply no downscaling)
56 subject : str, optional
57 The subject field in the output PDF metadata
58 title : str, optional
59 The title field in the output PDF metadata
61 Notes
62 -----
63 Copyright 2017 Thomas Guymer [1]_
65 References
66 ----------
67 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
68 """
70 # Import special modules ...
71 try:
72 import PIL
73 import PIL.Image
74 PIL.Image.MAX_IMAGE_PIXELS = 1024 * 1024 * 1024 # [px]
75 except:
76 raise Exception("\"PIL\" is not installed; run \"pip install --user Pillow\"") from None
78 # **************************************************************************
80 # Initialize list ...
81 tmpImgs = []
83 # Loop over input ...
84 for img in imgs:
85 # Find out what the user supplied ...
86 match img:
87 case str():
88 # Open image as RGB (even if it is paletted) ...
89 with PIL.Image.open(img) as iObj:
90 tmpImg = iObj.convert("RGB")
92 # Check if the user wants to scale the image down to fit within
93 # a screen size ...
94 if screenWidth >= 100 and screenHeight >= 100:
95 # Resize image in place ...
96 tmpImg.thumbnail(
97 (screenWidth, screenHeight),
98 resample = PIL.Image.Resampling.LANCZOS,
99 )
101 # Convert it to whatever mode the user asked for ...
102 tmpImgs.append(tmpImg.convert(mode))
103 case PIL.Image.Image():
104 # Convert image to whatever mode the user asked for ...
105 tmpImgs.append(img.convert(mode))
106 case _:
107 # Crash ...
108 raise TypeError(f"\"img\" is an unexpected type ({repr(type(img))})") from None
110 # Save it as a PDF ...
111 # NOTE: See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#pdf
112 tmpImgs[0].save(
113 pdf,
114 append_images = tmpImgs[1:],
115 author = author,
116 keywords = keywords,
117 optimise = optimise, # NOTE: Passed to the JPEG encoder.
118 progressive = progressive, # NOTE: Passed to the JPEG encoder.
119 quality = quality, # NOTE: Passed to the JPEG encoder.
120 resolution = resolution,
121 save_all = True,
122 subject = subject,
123 title = title,
124 )