From a618e2ca1cd1b761ffaa6ea9c95b25b92f597d9d Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 7 Apr 2020 21:13:40 +1000 Subject: [PATCH 1/5] Fixed big-endian saving --- src/PIL/IcnsImagePlugin.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 660de2b9250..963ad199e48 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -336,21 +336,21 @@ def _save(im, fp, filename): ) # Header - fp.write(struct.pack("i", MAGIC)[::-1]) - fp.write(struct.pack("i", file_size)[::-1]) + fp.write(struct.pack(" Date: Tue, 7 Apr 2020 21:11:16 +1000 Subject: [PATCH 2/5] Marked to_int() as private --- src/PIL/IcnsImagePlugin.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 963ad199e48..e3b274295fb 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -300,12 +300,12 @@ def load(self): self.load_end() -def to_int(s): +def _to_int(s): b = s.encode("ascii") return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3] -MAGIC = to_int("icns") +MAGIC = _to_int("icns") HEADER_SIZE = 8 TOC = "TOC " @@ -341,15 +341,15 @@ def _save(im, fp, filename): # TOC toc_size = HEADER_SIZE + (len(entries) * HEADER_SIZE) - fp.write(struct.pack(" Date: Tue, 7 Apr 2020 21:17:09 +1000 Subject: [PATCH 3/5] ICNS can now be saved on non-macOS platforms [ci skip] --- docs/handbook/image-file-formats.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index a12de82e2c0..7bb846b2a3e 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -200,12 +200,16 @@ attributes before loading the file:: ICNS ^^^^ -Pillow reads and (macOS only) writes macOS ``.icns`` files. By default, the +Pillow reads and writes macOS ``.icns`` files. By default, the largest available icon is read, though you can override this by setting the :py:attr:`~PIL.Image.Image.size` property before calling :py:meth:`~PIL.Image.Image.load`. The :py:meth:`~PIL.Image.Image.open` method sets the following :py:attr:`~PIL.Image.Image.info` property: +.. note:: + + Prior to version 7.2.0, Pillow could only write ICNS files on macOS. + **sizes** A list of supported sizes found in this icon file; these are a 3-tuple, ``(width, height, scale)``, where ``scale`` is 2 for a retina From 84b7e268f9646d4aac968f4fb921e84bd01ef432 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Tue, 7 Apr 2020 21:18:37 +1000 Subject: [PATCH 4/5] Merged HEADER_SIZE into HEADERSIZE --- src/PIL/IcnsImagePlugin.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index e3b274295fb..98603e2f967 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -306,7 +306,6 @@ def _to_int(s): MAGIC = _to_int("icns") -HEADER_SIZE = 8 TOC = "TOC " @@ -340,17 +339,17 @@ def _save(im, fp, filename): fp.write(struct.pack(" Date: Tue, 7 Apr 2020 21:42:23 +1000 Subject: [PATCH 5/5] Do not save two temporary files for the same size --- src/PIL/IcnsImagePlugin.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/PIL/IcnsImagePlugin.py b/src/PIL/IcnsImagePlugin.py index 98603e2f967..cf9b5dcf5e8 100644 --- a/src/PIL/IcnsImagePlugin.py +++ b/src/PIL/IcnsImagePlugin.py @@ -325,10 +325,12 @@ def _save(im, fp, filename): file_size = 0 entries = [] provided_images = {im.width: im for im in im.encoderinfo.get("append_images", [])} - for index, s in enumerate(sizes): - temp = io.BytesIO() + temp_sizes = {s: io.BytesIO() for s in set(sizes)} + for s, temp in temp_sizes.items(): nb = provided_images[s] if s in provided_images else im.resize((s, s)) nb.save(temp, "png") + for index, s in enumerate(sizes): + temp = temp_sizes[s] file_size += len(temp.getvalue()) entries.append( {"type": size_str[index], "size": len(temp.getvalue()), "stream": temp} @@ -343,14 +345,14 @@ def _save(im, fp, filename): fp.write(struct.pack("