|
| 1 | +""" |
| 2 | +Opener for Pillow library. |
| 3 | +""" |
| 4 | + |
1 | 5 | from PIL import Image, ImageFile |
2 | 6 |
|
3 | | -from .reader import read |
| 7 | +from .constants import heif_filetype_no |
| 8 | +from .reader import open_heif, check_heif |
4 | 9 | from .error import HeifError |
5 | 10 |
|
6 | 11 |
|
7 | 12 | class HeifImageFile(ImageFile.ImageFile): |
8 | | - format = 'HEIF' |
9 | | - format_description = 'HEIF/HEIC image' |
| 13 | + format = "HEIF" |
| 14 | + format_description = "HEIF/HEIC image" |
10 | 15 | color_profile = None |
| 16 | + heif_file = None |
11 | 17 |
|
12 | 18 | def _open(self): |
13 | | - data = self.fp.read(16) |
14 | | - if not check_heif_magic(data): |
15 | | - raise SyntaxError('not a HEIF file') |
16 | | - self.fp.seek(0) |
17 | 19 | try: |
18 | | - heif_file = read(self.fp) |
| 20 | + heif_file = open_heif(self.fp) |
19 | 21 | except HeifError as e: |
20 | 22 | raise SyntaxError(str(e)) from None |
21 | | - |
22 | | - # size in pixels (width, height) |
| 23 | + if getattr(self, "_exclusive_fp", False): |
| 24 | + if hasattr(self, "fp") and self.fp is not None: |
| 25 | + self.fp.close() |
| 26 | + self.fp = None |
23 | 27 | self._size = heif_file.size |
24 | | - |
25 | | - # mode setting |
26 | 28 | self.mode = heif_file.mode |
27 | 29 |
|
28 | | - # Add Exif |
29 | 30 | if heif_file.metadata: |
30 | 31 | for data in heif_file.metadata: |
31 | | - if data['type'] == 'Exif': |
32 | | - self.info['exif'] = data['data'] |
| 32 | + if data["type"] == "Exif": |
| 33 | + self.info["exif"] = data["data"] |
33 | 34 | break |
34 | 35 |
|
35 | | - # Add Color Profile |
36 | 36 | if heif_file.color_profile: |
37 | | - if heif_file.color_profile['type'] != 'unknown': |
| 37 | + if heif_file.color_profile["type"] != "unknown": |
38 | 38 | self.color_profile = heif_file.color_profile |
39 | | - offset = self.fp.tell() |
40 | | - self.tile = [('heif', (0, 0) + self.size, offset, (heif_file,))] |
41 | | - |
42 | | - |
43 | | -class HeifDecoder(ImageFile.PyDecoder): |
44 | | - _pulls_fd = True |
| 39 | + if heif_file.color_profile["type"] in ("rICC", "prof"): |
| 40 | + self.info["icc_profile"] = heif_file.color_profile["data"] |
| 41 | + self.tile = [] |
| 42 | + self.heif_file = heif_file |
45 | 43 |
|
46 | | - def decode(self, buffer): |
47 | | - heif_file = self.args[0] |
48 | | - mode = heif_file.mode |
49 | | - raw_decoder = Image._getdecoder(mode, 'raw', (mode, heif_file.stride)) |
50 | | - raw_decoder.setimage(self.im) |
51 | | - return raw_decoder.decode(heif_file.data) |
| 44 | + def load(self): |
| 45 | + if self.heif_file is not None and self.heif_file: |
| 46 | + heif_file = self.heif_file.load() |
| 47 | + self.load_prepare() |
| 48 | + self.frombytes(heif_file.data, "raw", (self.mode, heif_file.stride)) |
| 49 | + self.heif_file.data = None |
| 50 | + self.heif_file = None |
| 51 | + return super().load() |
52 | 52 |
|
53 | 53 |
|
54 | 54 | def check_heif_magic(data) -> bool: |
55 | | - # according to HEIF standard ISO/IEC 23008-12:2017 |
56 | | - # https://standards.iso.org/ittf/PubliclyAvailableStandards/c066067_ISO_IEC_23008-12_2017.zip |
57 | | - if len(data) < 12: |
58 | | - return False |
59 | | - magic1 = data[4:8] |
60 | | - if magic1 != b"ftyp": |
61 | | - return False |
62 | | - magic2 = data[8:12] |
63 | | - code_list = [ |
64 | | - b"heic", # the usual HEIF images |
65 | | - b"heix", # 10bit images, or anything that uses h265 with range extension |
66 | | - b"hevc", # image sequences |
67 | | - b"hevx", # image sequences |
68 | | - b"heim", # multiview |
69 | | - b"heis", # scalable |
70 | | - b"hevm", # multiview sequence |
71 | | - b"hevs", # scalable sequence |
72 | | - b"mif1", # image, any coding algorithm |
73 | | - b"msf1", # sequence, any coding algorithm |
74 | | - # avif |
75 | | - # avis |
76 | | - ] |
77 | | - return magic2 in code_list |
| 55 | + return check_heif(data) != heif_filetype_no |
78 | 56 |
|
79 | 57 |
|
80 | 58 | def register_heif_opener(): |
81 | 59 | Image.register_open(HeifImageFile.format, HeifImageFile, check_heif_magic) |
82 | | - Image.register_decoder('heif', HeifDecoder) |
83 | | - Image.register_extensions(HeifImageFile.format, ['.heic', '.heif']) |
84 | | - Image.register_mime(HeifImageFile.format, 'image/heif') |
| 60 | + Image.register_mime(HeifImageFile.format, "image/heif") |
0 commit comments