Coverage for pyguymer3/media/images2webp.py: 5%
22 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 images2webp(
5 imgs,
6 webp,
7 /,
8 *,
9 exif = None,
10 fps = 25.0,
11 lossless = False,
12 method = 6,
13 minimize_size = True,
14 mode = "RGB",
15 quality = 100,
16 screenHeight = -1,
17 screenWidth = -1,
18):
19 """Convert a sequence of images to a WEBP animation.
21 This function makes a WEBP animation from either a list of PIL Images or a
22 list of file paths. The user is able to set the framerate.
24 Parameters
25 ----------
26 imgs : list of PIL.Image.Image or list of str
27 the list of input PIL Images or list of paths to the input images
28 webp : str
29 the path to the output WEBP
30 exif : dict, optional
31 a dictionary of EXIF data to save in the output WEBP (default None)
32 fps : float, optional
33 the framerate, default 25.0
34 lossless : bool, optional
35 save a lossless WEBP (default False)
36 method : int, optional
37 the method to use when saving the WEBP (default 6)
38 minimize_size : bool, optional
39 minimize the output size (default True)
40 mode : str, optional
41 the mode of the outout WEBP (default "RGB")
42 quality : int, optional
43 the quality of the output WEBP (default 100)
44 screenHeight : int, optional
45 the height of the screen to downscale the input images to fit within,
46 currently only implemented if "imgs" is a list of str (default -1;
47 integers less than 100 imply no downscaling)
48 screenWidth : int, optional
49 the width of the screen to downscale the input images to fit within,
50 currently only implemented if "imgs" is a list of str (default -1;
51 integers less than 100 imply no downscaling)
53 Notes
54 -----
55 Copyright 2017 Thomas Guymer [1]_
57 References
58 ----------
59 .. [1] PyGuymer3, https://github.com/Guymer/PyGuymer3
60 """
62 # Import special modules ...
63 try:
64 import PIL
65 import PIL.Image
66 PIL.Image.MAX_IMAGE_PIXELS = 1024 * 1024 * 1024 # [px]
67 except:
68 raise Exception("\"PIL\" is not installed; run \"pip install --user Pillow\"") from None
70 # Import sub-functions ...
71 from ..image import dict2exif
73 # **************************************************************************
75 # Initialize list ...
76 tmpImgs = []
78 # Loop over input ...
79 for img in imgs:
80 # Find out what the user supplied ...
81 match img:
82 case str():
83 # Open image as RGB (even if it is paletted) ...
84 with PIL.Image.open(img) as iObj:
85 tmpImg = iObj.convert("RGB")
87 # Check if the user wants to scale the image down to fit within
88 # a screen size ...
89 if screenWidth >= 100 and screenHeight >= 100:
90 # Resize image in place ...
91 tmpImg.thumbnail(
92 (screenWidth, screenHeight),
93 resample = PIL.Image.Resampling.LANCZOS,
94 )
96 # Convert it to whatever mode the user asked for ...
97 tmpImgs.append(tmpImg.convert(mode))
98 case PIL.Image.Image():
99 # Convert image to whatever mode the user asked for ...
100 tmpImgs.append(img.convert(mode))
101 case _:
102 # Crash ...
103 raise TypeError(f"\"img\" is an unexpected type ({repr(type(img))})") from None
105 # Save it as a WEBP ...
106 # NOTE: See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#webp
107 tmpImgs[0].save(
108 webp,
109 append_images = tmpImgs[1:],
110 duration = round(1000.0 / fps),
111 exif = dict2exif(exif, mode = mode),
112 loop = 0,
113 lossless = lossless,
114 method = method,
115 minimize_size = minimize_size,
116 quality = quality,
117 save_all = True,
118 )