|
24 | 24 | def _accept(prefix: bytes) -> bool | str: |
25 | 25 | if prefix[4:8] != b"ftyp": |
26 | 26 | return False |
27 | | - coding_brands = (b"avif", b"avis") |
28 | | - container_brands = (b"mif1", b"msf1") |
29 | 27 | major_brand = prefix[8:12] |
30 | | - if major_brand in coding_brands: |
31 | | - if not SUPPORTED: |
32 | | - return ( |
33 | | - "image file could not be identified because AVIF " |
34 | | - "support not installed" |
35 | | - ) |
36 | | - return True |
37 | | - if major_brand in container_brands: |
| 28 | + if major_brand in ( |
| 29 | + # coding brands |
| 30 | + b"avif", |
| 31 | + b"avis", |
38 | 32 | # We accept files with AVIF container brands; we can't yet know if |
39 | 33 | # the ftyp box has the correct compatible brands, but if it doesn't |
40 | 34 | # then the plugin will raise a SyntaxError which Pillow will catch |
41 | 35 | # before moving on to the next plugin that accepts the file. |
42 | 36 | # |
43 | 37 | # Also, because this file might not actually be an AVIF file, we |
44 | 38 | # don't raise an error if AVIF support isn't properly compiled. |
| 39 | + b"mif1", |
| 40 | + b"msf1", |
| 41 | + ): |
| 42 | + if not SUPPORTED: |
| 43 | + return ( |
| 44 | + "image file could not be identified because AVIF " |
| 45 | + "support not installed" |
| 46 | + ) |
45 | 47 | return True |
46 | 48 | return False |
47 | 49 |
|
@@ -72,6 +74,11 @@ def _open(self) -> None: |
72 | 74 | ) |
73 | 75 | raise SyntaxError(msg) |
74 | 76 |
|
| 77 | + if DECODE_CODEC_CHOICE != "auto" and not _avif.decoder_codec_available( |
| 78 | + DECODE_CODEC_CHOICE |
| 79 | + ): |
| 80 | + msg = "Invalid opening codec" |
| 81 | + raise ValueError(msg) |
75 | 82 | self._decoder = _avif.AvifDecoder( |
76 | 83 | self.fp.read(), |
77 | 84 | DECODE_CODEC_CHOICE, |
@@ -104,10 +111,8 @@ def load(self) -> Image.core.PixelAccess | None: |
104 | 111 | data, timescale, tsp_in_ts, dur_in_ts = self._decoder.get_frame( |
105 | 112 | self.__frame |
106 | 113 | ) |
107 | | - timestamp = round(1000 * (tsp_in_ts / timescale)) |
108 | | - duration = round(1000 * (dur_in_ts / timescale)) |
109 | | - self.info["timestamp"] = timestamp |
110 | | - self.info["duration"] = duration |
| 114 | + self.info["timestamp"] = round(1000 * (tsp_in_ts / timescale)) |
| 115 | + self.info["duration"] = round(1000 * (dur_in_ts / timescale)) |
111 | 116 | self.__loaded = self.__frame |
112 | 117 |
|
113 | 118 | # Set tile |
@@ -153,6 +158,9 @@ def _save( |
153 | 158 | speed = info.get("speed", 6) |
154 | 159 | max_threads = info.get("max_threads", _get_default_max_threads()) |
155 | 160 | codec = info.get("codec", "auto") |
| 161 | + if codec != "auto" and not _avif.encoder_codec_available(codec): |
| 162 | + msg = "Invalid saving codec" |
| 163 | + raise ValueError(msg) |
156 | 164 | range_ = info.get("range", "full") |
157 | 165 | tile_rows_log2 = info.get("tile_rows", 0) |
158 | 166 | tile_cols_log2 = info.get("tile_cols", 0) |
@@ -199,7 +207,7 @@ def _save( |
199 | 207 | ) |
200 | 208 | raise ValueError(msg) |
201 | 209 | advanced = tuple( |
202 | | - [(str(k).encode("utf-8"), str(v).encode("utf-8")) for k, v in advanced] |
| 210 | + (str(k).encode("utf-8"), str(v).encode("utf-8")) for k, v in advanced |
203 | 211 | ) |
204 | 212 |
|
205 | 213 | # Setup the AVIF encoder |
|
0 commit comments