pillow-avif-plugin 1.4.0__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pillow-avif-plugin might be problematic. Click here for more details.

@@ -0,0 +1,269 @@
1
+ from __future__ import division
2
+
3
+ from io import BytesIO
4
+ import sys
5
+
6
+ from PIL import Image, ImageFile
7
+
8
+ try:
9
+ from pillow_avif import _avif
10
+
11
+ SUPPORTED = True
12
+ except ImportError:
13
+ SUPPORTED = False
14
+
15
+ # Decoder options as module globals, until there is a way to pass parameters
16
+ # to Image.open (see https://github.com/python-pillow/Pillow/issues/569)
17
+ DECODE_CODEC_CHOICE = "auto"
18
+ CHROMA_UPSAMPLING = "auto"
19
+
20
+ _VALID_AVIF_MODES = {"RGB", "RGBA"}
21
+
22
+
23
+ if sys.version_info[0] == 2:
24
+ text_type = unicode # noqa
25
+ else:
26
+ text_type = str
27
+
28
+
29
+ def _accept(prefix):
30
+ if prefix[4:8] != b"ftyp":
31
+ return
32
+ coding_brands = (b"avif", b"avis")
33
+ container_brands = (b"mif1", b"msf1")
34
+ major_brand = prefix[8:12]
35
+ if major_brand in coding_brands:
36
+ if not SUPPORTED:
37
+ return (
38
+ "image file could not be identified because AVIF "
39
+ "support not installed"
40
+ )
41
+ return True
42
+ if major_brand in container_brands:
43
+ # We accept files with AVIF container brands; we can't yet know if
44
+ # the ftyp box has the correct compatible brands, but if it doesn't
45
+ # then the plugin will raise a SyntaxError which Pillow will catch
46
+ # before moving on to the next plugin that accepts the file.
47
+ #
48
+ # Also, because this file might not actually be an AVIF file, we
49
+ # don't raise an error if AVIF support isn't properly compiled.
50
+ return True
51
+
52
+
53
+ class AvifImageFile(ImageFile.ImageFile):
54
+ format = "AVIF"
55
+ format_description = "AVIF image"
56
+ __loaded = -1
57
+ __frame = 0
58
+
59
+ def _open(self):
60
+ self._decoder = _avif.AvifDecoder(
61
+ self.fp.read(), DECODE_CODEC_CHOICE, CHROMA_UPSAMPLING
62
+ )
63
+
64
+ # Get info from decoder
65
+ width, height, n_frames, mode, icc, exif, xmp = self._decoder.get_info()
66
+ self._size = width, height
67
+ self.n_frames = n_frames
68
+ self.is_animated = self.n_frames > 1
69
+ try:
70
+ self.mode = self.rawmode = mode
71
+ except AttributeError:
72
+ self._mode = self.rawmode = mode
73
+ self.tile = []
74
+
75
+ if icc:
76
+ self.info["icc_profile"] = icc
77
+ if exif:
78
+ self.info["exif"] = exif
79
+ if xmp:
80
+ self.info["xmp"] = xmp
81
+
82
+ def seek(self, frame):
83
+ if not self._seek_check(frame):
84
+ return
85
+
86
+ self.__frame = frame
87
+
88
+ def load(self):
89
+ if self.__loaded != self.__frame:
90
+ # We need to load the image data for this frame
91
+ data, timescale, tsp_in_ts, dur_in_ts = self._decoder.get_frame(
92
+ self.__frame
93
+ )
94
+ timestamp = round(1000 * (tsp_in_ts / timescale))
95
+ duration = round(1000 * (dur_in_ts / timescale))
96
+ self.info["timestamp"] = timestamp
97
+ self.info["duration"] = duration
98
+ self.__loaded = self.__frame
99
+
100
+ # Set tile
101
+ if self.fp and self._exclusive_fp:
102
+ self.fp.close()
103
+ self.fp = BytesIO(data)
104
+ self.tile = [("raw", (0, 0) + self.size, 0, self.rawmode)]
105
+
106
+ return super(AvifImageFile, self).load()
107
+
108
+ def tell(self):
109
+ return self.__frame
110
+
111
+
112
+ def _save_all(im, fp, filename):
113
+ _save(im, fp, filename, save_all=True)
114
+
115
+
116
+ def _save(im, fp, filename, save_all=False):
117
+ info = im.encoderinfo.copy()
118
+ if save_all:
119
+ append_images = list(info.get("append_images", []))
120
+ else:
121
+ append_images = []
122
+
123
+ total = 0
124
+ for ims in [im] + append_images:
125
+ total += getattr(ims, "n_frames", 1)
126
+
127
+ is_single_frame = total == 1
128
+
129
+ qmin = info.get("qmin")
130
+ qmax = info.get("qmax")
131
+
132
+ if qmin is None and qmax is None:
133
+ # The min and max quantizer settings in libavif range from 0 (best quality)
134
+ # to 63 (worst quality). If neither are explicitly specified, we use a 0-100
135
+ # quality scale (default 75) and calculate the qmin and qmax from that.
136
+ #
137
+ # - qmin is 0 for quality >= 64. Below that, qmin has an inverse linear
138
+ # relation to quality (i.e., quality 63 = qmin 1, quality 0 => qmin 63)
139
+ # - qmax is 0 for quality=100, then qmax increases linearly relative to
140
+ # quality decreasing, until it flattens out at quality=37.
141
+ quality = info.get("quality", 75)
142
+ if not isinstance(quality, int) or quality < 0 or quality > 100:
143
+ raise ValueError("Invalid quality setting")
144
+ qmin = max(0, min(64 - quality, 63))
145
+ qmax = max(0, min(100 - quality, 63))
146
+
147
+ duration = info.get("duration", 0)
148
+ subsampling = info.get("subsampling", "4:2:0")
149
+ speed = info.get("speed", 6)
150
+ codec = info.get("codec", "auto")
151
+ range_ = info.get("range", "full")
152
+ tile_rows_log2 = info.get("tile_rows", 0)
153
+ tile_cols_log2 = info.get("tile_cols", 0)
154
+ alpha_premultiplied = bool(info.get("alpha_premultiplied", False))
155
+ autotiling = bool(info.get("autotiling", tile_rows_log2 == tile_cols_log2 == 0))
156
+
157
+ icc_profile = info.get("icc_profile", im.info.get("icc_profile"))
158
+ exif = info.get("exif", im.info.get("exif"))
159
+ if isinstance(exif, Image.Exif):
160
+ exif = exif.tobytes()
161
+ xmp = info.get("xmp", im.info.get("xmp") or im.info.get("XML:com.adobe.xmp"))
162
+
163
+ if isinstance(xmp, text_type):
164
+ xmp = xmp.encode("utf-8")
165
+
166
+ advanced = info.get("advanced")
167
+ if isinstance(advanced, dict):
168
+ advanced = tuple([k, v] for (k, v) in advanced.items())
169
+ if advanced is not None:
170
+ try:
171
+ advanced = tuple(advanced)
172
+ except TypeError:
173
+ invalid = True
174
+ else:
175
+ invalid = all(isinstance(v, tuple) and len(v) == 2 for v in advanced)
176
+ if invalid:
177
+ raise ValueError(
178
+ "advanced codec options must be a dict of key-value string "
179
+ "pairs or a series of key-value two-tuples"
180
+ )
181
+ advanced = tuple(
182
+ [(str(k).encode("utf-8"), str(v).encode("utf-8")) for k, v in advanced]
183
+ )
184
+
185
+ # Setup the AVIF encoder
186
+ enc = _avif.AvifEncoder(
187
+ im.size[0],
188
+ im.size[1],
189
+ subsampling,
190
+ qmin,
191
+ qmax,
192
+ quality,
193
+ speed,
194
+ codec,
195
+ range_,
196
+ tile_rows_log2,
197
+ tile_cols_log2,
198
+ alpha_premultiplied,
199
+ autotiling,
200
+ icc_profile or b"",
201
+ exif or b"",
202
+ xmp or b"",
203
+ advanced,
204
+ )
205
+
206
+ # Add each frame
207
+ frame_idx = 0
208
+ frame_dur = 0
209
+ cur_idx = im.tell()
210
+ try:
211
+ for ims in [im] + append_images:
212
+ # Get # of frames in this image
213
+ nfr = getattr(ims, "n_frames", 1)
214
+
215
+ for idx in range(nfr):
216
+ ims.seek(idx)
217
+ ims.load()
218
+
219
+ # Make sure image mode is supported
220
+ frame = ims
221
+ rawmode = ims.mode
222
+ if ims.mode not in _VALID_AVIF_MODES:
223
+ alpha = (
224
+ "A" in ims.mode
225
+ or "a" in ims.mode
226
+ or (ims.mode == "P" and "A" in ims.im.getpalettemode())
227
+ )
228
+ rawmode = "RGBA" if alpha else "RGB"
229
+ frame = ims.convert(rawmode)
230
+
231
+ # Update frame duration
232
+ if isinstance(duration, (list, tuple)):
233
+ frame_dur = duration[frame_idx]
234
+ else:
235
+ frame_dur = duration
236
+
237
+ # Append the frame to the animation encoder
238
+ enc.add(
239
+ frame.tobytes("raw", rawmode),
240
+ frame_dur,
241
+ frame.size[0],
242
+ frame.size[1],
243
+ rawmode,
244
+ is_single_frame,
245
+ )
246
+
247
+ # Update frame index
248
+ frame_idx += 1
249
+
250
+ if not save_all:
251
+ break
252
+
253
+ finally:
254
+ im.seek(cur_idx)
255
+
256
+ # Get the final output from the encoder
257
+ data = enc.finish()
258
+ if data is None:
259
+ raise OSError("cannot write file as AVIF (encoder returned None)")
260
+
261
+ fp.write(data)
262
+
263
+
264
+ Image.register_open(AvifImageFile.format, AvifImageFile, _accept)
265
+ if SUPPORTED:
266
+ Image.register_save(AvifImageFile.format, _save)
267
+ Image.register_save_all(AvifImageFile.format, _save_all)
268
+ Image.register_extensions(AvifImageFile.format, [".avif", ".avifs"])
269
+ Image.register_mime(AvifImageFile.format, "image/avif")
@@ -0,0 +1,5 @@
1
+ from . import AvifImagePlugin
2
+
3
+
4
+ __all__ = ["AvifImagePlugin"]
5
+ __version__ = "1.4.0"
Binary file
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2021, Frankie Dintino. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions are met:
5
+
6
+ * Redistributions of source code must retain the above copyright notice, this
7
+ list of conditions and the following disclaimer.
8
+
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
17
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
21
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.1
2
+ Name: pillow-avif-plugin
3
+ Version: 1.4.0
4
+ Summary: A pillow plugin that adds avif support via libavif
5
+ Home-page: https://github.com/fdintino/pillow-avif-plugin/
6
+ Download-URL: https://github.com/fdintino/pillow-avif-plugin/releases
7
+ Author: Frankie Dintino
8
+ Author-email: fdintino@theatlantic.com
9
+ License: MIT License
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: C
16
+ Classifier: Programming Language :: C++
17
+ Classifier: Programming Language :: Python :: 2.7
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.7
20
+ Classifier: Programming Language :: Python :: 3.8
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: Implementation :: CPython
26
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
27
+ Classifier: Topic :: Multimedia :: Graphics
28
+ Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+
32
+ # pillow-avif-plugin
33
+
34
+ This is a plugin that adds support for AVIF files until official support has been added (see [this pull request](https://github.com/python-pillow/Pillow/pull/5201)).
35
+
36
+ To register this plugin with pillow you will need to add `import pillow_avif` somewhere in your application.
@@ -0,0 +1,9 @@
1
+ pillow_avif/AvifImagePlugin.py,sha256=BYBYS9qD5JUoRQPA7Nrr4asqeyRq_BXKqj1_Sy3O0gk,8703
2
+ pillow_avif/__init__.py,sha256=_ASToIhzqkCoKaYCNv1DUdt_zrIO-tcI1ubuxMaDos4,89
3
+ pillow_avif/_avif.cp312-win_amd64.pyd,sha256=dFmeyYIK0rXvnjI-SfcVzb7VJrRUsBSvoBAdQ8yPAbk,26011648
4
+ pillow_avif_plugin-1.4.0.dist-info/LICENSE,sha256=tubzK3TFrT8GFgUPEKC-WmCziD1dGOFLCjDky3t9Lnc,1321
5
+ pillow_avif_plugin-1.4.0.dist-info/METADATA,sha256=TATphSXrFm1CtSybbOYQ90GxvAtZNBxd7rmgzJfGuvA,1704
6
+ pillow_avif_plugin-1.4.0.dist-info/WHEEL,sha256=aDrgWfEd5Ac7WJzHsr90rcMGiH4MHbAXoCWpyP5CEBc,102
7
+ pillow_avif_plugin-1.4.0.dist-info/top_level.txt,sha256=xrg4zRnqDyl_JEyEQh3oCcAU4BHneocD-DCFDzf4g9E,12
8
+ pillow_avif_plugin-1.4.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
9
+ pillow_avif_plugin-1.4.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.41.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp312-cp312-win_amd64
5
+
@@ -0,0 +1 @@
1
+ pillow_avif