Coverage for pyguymer3/image/image2png.py: 4%
25 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 image2png(
5 img,
6 png,
7 /,
8 *,
9 chunksize = 1048576,
10 debug = __debug__,
11 exif = None,
12 exiftoolPath = None,
13 gifsiclePath = None,
14 jpegtranPath = None,
15 mode = "RGB",
16 optimise = True,
17 optipngPath = None,
18 screenHeight = -1,
19 screenWidth = -1,
20 strip = False,
21 timeout = 60.0,
22):
23 """Save an image as a PNG
25 This function accepts either a PIL Image or a file path and saves the image
26 as a PNG.
28 Parameters
29 ----------
30 img : PIL.Image.Image or str
31 the input PIL Image or path to the input image
32 png : str
33 the path to the output PNG
34 chunksize : int, optional
35 the size of the chunks of any files which are read in (in bytes)
36 debug : bool, optional
37 print debug messages (default False)
38 exif : dict, optional
39 a dictionary of EXIF data to save in the output PNG (default None)
40 exiftoolPath : str, optional
41 the path to the "exiftool" binary (if not provided then Python will attempt to
42 find the binary itself)
43 gifsiclePath : str, optional
44 the path to the "gifsicle" binary (if not provided then Python will attempt to
45 find the binary itself)
46 jpegtranPath : str, optional
47 the path to the "jpegtran" binary (if not provided then Python will attempt to
48 find the binary itself)
49 mode : str, optional
50 the mode of the outout PNG (default "RGB")
51 optimise : bool, optional
52 optimise the output PNG (default True)
53 optipngPath : str, optional
54 the path to the "optipng" binary (if not provided then Python will attempt to
55 find the binary itself)
56 screenHeight : int, optional
57 the height of the screen to downscale the input image to fit within,
58 currently only implemented if "img" is a str (default -1; integers less
59 than 100 imply no downscaling)
60 screenWidth : int, optional
61 the width of the screen to downscale the input image to fit within,
62 currently only implemented if "img" is a str (default -1; integers less
63 than 100 imply no downscaling)
64 strip : bool, optional
65 strip metadata from the output PNG (default False)
66 timeout : float, optional
67 the timeout for any requests/subprocess calls
69 Notes
70 -----
71 Copyright 2017 Thomas Guymer [1]_
73 References
74 ----------
75 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
76 """
78 # Import special modules ...
79 try:
80 import PIL
81 import PIL.Image
82 PIL.Image.MAX_IMAGE_PIXELS = 1024 * 1024 * 1024 # [px]
83 except:
84 raise Exception("\"PIL\" is not installed; run \"pip install --user Pillow\"") from None
86 # Import sub-functions ...
87 from .dict2exif import dict2exif
88 from .optimise_image import optimise_image
90 # Check input ...
91 if exif is not None and strip:
92 print("WARNING: You have provided EXIF data but then asked to strip metadata.")
94 # Find out what the user supplied ...
95 match img:
96 case str():
97 # Open image as RGB (even if it is paletted) ...
98 with PIL.Image.open(img) as iObj:
99 tmpImg = iObj.convert("RGB")
101 # Check if the user wants to scale the image down to fit within a
102 # screen size ...
103 if screenWidth >= 100 and screenHeight >= 100:
104 # Resize image in place ...
105 tmpImg.thumbnail(
106 (screenWidth, screenHeight),
107 resample = PIL.Image.Resampling.LANCZOS,
108 )
110 # Convert it to whatever mode the user asked for ...
111 tmpImg = tmpImg.convert(mode)
112 case PIL.Image.Image():
113 # Convert image to whatever mode the user asked for ...
114 tmpImg = img.convert(mode)
115 case _:
116 # Crash ...
117 raise TypeError(f"\"img\" is an unexpected type ({repr(type(img))})") from None
119 # Save it as a PNG ...
120 # NOTE: See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#png
121 tmpImg.save(
122 png,
123 exif = dict2exif(exif, mode = mode),
124 optimise = optimise,
125 )
127 # Optimise PNG ...
128 if optimise or strip:
129 optimise_image(
130 png,
131 chunksize = chunksize,
132 debug = debug,
133 exiftoolPath = exiftoolPath,
134 gifsiclePath = gifsiclePath,
135 jpegtranPath = jpegtranPath,
136 optipngPath = optipngPath,
137 pool = None,
138 strip = strip,
139 timeout = timeout,
140 )