mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 17:06:16 +03:00
Merge pull request #1007 from wiredfool/ico_save
Ico save, additional tests
This commit is contained in:
commit
5ae3c1c881
|
@ -24,6 +24,9 @@
|
|||
|
||||
__version__ = "0.1"
|
||||
|
||||
import struct
|
||||
from io import BytesIO
|
||||
|
||||
from PIL import Image, ImageFile, BmpImagePlugin, PngImagePlugin, _binary
|
||||
from math import log, ceil
|
||||
|
||||
|
@ -37,6 +40,42 @@ i32 = _binary.i32le
|
|||
_MAGIC = b"\0\0\1\0"
|
||||
|
||||
|
||||
def _save(im, fp, filename):
|
||||
fp.write(_MAGIC) # (2+2)
|
||||
sizes = im.encoderinfo.get("sizes",
|
||||
[(16, 16), (24, 24), (32, 32), (48, 48),
|
||||
(64, 64), (128, 128), (255, 255)])
|
||||
width, height = im.size
|
||||
filter(lambda x: False if (x[0] > width or x[1] > height or
|
||||
x[0] > 255 or x[1] > 255) else True, sizes)
|
||||
sizes = sorted(sizes, key=lambda x: x[0])
|
||||
fp.write(struct.pack("H", len(sizes))) # idCount(2)
|
||||
offset = fp.tell() + len(sizes)*16
|
||||
for size in sizes:
|
||||
width, height = size
|
||||
fp.write(struct.pack("B", width)) # bWidth(1)
|
||||
fp.write(struct.pack("B", height)) # bHeight(1)
|
||||
fp.write(b"\0") # bColorCount(1)
|
||||
fp.write(b"\0") # bReserved(1)
|
||||
fp.write(b"\0\0") # wPlanes(2)
|
||||
fp.write(struct.pack("H", 32)) # wBitCount(2)
|
||||
|
||||
image_io = BytesIO()
|
||||
tmp = im.copy()
|
||||
tmp.thumbnail(size, Image.ANTIALIAS)
|
||||
tmp.save(image_io, "png")
|
||||
image_io.seek(0)
|
||||
image_bytes = image_io.read()
|
||||
bytes_len = len(image_bytes)
|
||||
fp.write(struct.pack("I", bytes_len)) # dwBytesInRes(4)
|
||||
fp.write(struct.pack("I", offset)) # dwImageOffset(4)
|
||||
current = fp.tell()
|
||||
fp.seek(offset)
|
||||
fp.write(image_bytes)
|
||||
offset = offset + bytes_len
|
||||
fp.seek(current)
|
||||
|
||||
|
||||
def _accept(prefix):
|
||||
return prefix[:4] == _MAGIC
|
||||
|
||||
|
@ -241,4 +280,5 @@ class IcoImageFile(ImageFile.ImageFile):
|
|||
# --------------------------------------------------------------------
|
||||
|
||||
Image.register_open("ICO", IcoImageFile, _accept)
|
||||
Image.register_save("ICO", _save)
|
||||
Image.register_extension("ICO", ".ico")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from helper import unittest, PillowTestCase
|
||||
from helper import unittest, PillowTestCase, hopper
|
||||
|
||||
import io
|
||||
from PIL import Image
|
||||
|
||||
# sample ppm stream
|
||||
|
@ -16,6 +17,32 @@ class TestFileIco(PillowTestCase):
|
|||
self.assertEqual(im.size, (16, 16))
|
||||
self.assertEqual(im.format, "ICO")
|
||||
|
||||
def test_save_to_bytes(self):
|
||||
output = io.BytesIO()
|
||||
im = hopper()
|
||||
im.save(output, "ico", sizes=[(32, 32), (64, 64)])
|
||||
|
||||
# the default image
|
||||
output.seek(0)
|
||||
reloaded = Image.open(output)
|
||||
self.assertEqual(reloaded.info['sizes'],set([(32, 32), (64, 64)]))
|
||||
|
||||
self.assertEqual(im.mode, reloaded.mode)
|
||||
self.assertEqual((64, 64), reloaded.size)
|
||||
self.assertEqual(reloaded.format, "ICO")
|
||||
self.assert_image_equal(reloaded, hopper().resize((64,64), Image.ANTIALIAS))
|
||||
|
||||
# the other one
|
||||
output.seek(0)
|
||||
reloaded = Image.open(output)
|
||||
reloaded.size = (32,32)
|
||||
|
||||
self.assertEqual(im.mode, reloaded.mode)
|
||||
self.assertEqual((32, 32), reloaded.size)
|
||||
self.assertEqual(reloaded.format, "ICO")
|
||||
self.assert_image_equal(reloaded, hopper().resize((32,32), Image.ANTIALIAS))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -589,6 +589,14 @@ ICO
|
|||
|
||||
ICO is used to store icons on Windows. The largest available icon is read.
|
||||
|
||||
The :py:meth:`~PIL.Image.Image.save` method supports the following options:
|
||||
|
||||
**sizes**
|
||||
A list of sizes including in this ico file; these are a 2-tuple,
|
||||
``(width, height)``; Default to ``[(16, 16), (24, 24), (32, 32), (48, 48),
|
||||
(64, 64), (128, 128), (255, 255)]``. Any size is bigger then the original
|
||||
size or 255 will be ignored.
|
||||
|
||||
ICNS
|
||||
^^^^
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user