mirror of
				https://github.com/python-pillow/Pillow.git
				synced 2025-11-04 01:47:47 +03:00 
			
		
		
		
	Added ICO saving in BMP format
This commit is contained in:
		
							parent
							
								
									22e1fff754
								
							
						
					
					
						commit
						2c9a9b3529
					
				| 
						 | 
				
			
			@ -56,6 +56,35 @@ def test_save_to_bytes():
 | 
			
		|||
        assert_image_equal(reloaded, hopper().resize((32, 32), Image.LANCZOS))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@pytest.mark.parametrize("mode", ("1", "L", "P", "RGB", "RGBA"))
 | 
			
		||||
def test_save_to_bytes_bmp(mode):
 | 
			
		||||
    output = io.BytesIO()
 | 
			
		||||
    im = hopper(mode)
 | 
			
		||||
    im.save(output, "ico", bitmap_format="bmp", sizes=[(32, 32), (64, 64)])
 | 
			
		||||
 | 
			
		||||
    # The default image
 | 
			
		||||
    output.seek(0)
 | 
			
		||||
    with Image.open(output) as reloaded:
 | 
			
		||||
        assert reloaded.info["sizes"] == {(32, 32), (64, 64)}
 | 
			
		||||
 | 
			
		||||
        assert "RGBA" == reloaded.mode
 | 
			
		||||
        assert (64, 64) == reloaded.size
 | 
			
		||||
        assert reloaded.format == "ICO"
 | 
			
		||||
        im = hopper(mode).resize((64, 64), Image.LANCZOS).convert("RGBA")
 | 
			
		||||
        assert_image_equal(reloaded, im)
 | 
			
		||||
 | 
			
		||||
    # The other one
 | 
			
		||||
    output.seek(0)
 | 
			
		||||
    with Image.open(output) as reloaded:
 | 
			
		||||
        reloaded.size = (32, 32)
 | 
			
		||||
 | 
			
		||||
        assert "RGBA" == reloaded.mode
 | 
			
		||||
        assert (32, 32) == reloaded.size
 | 
			
		||||
        assert reloaded.format == "ICO"
 | 
			
		||||
        im = hopper(mode).resize((32, 32), Image.LANCZOS).convert("RGBA")
 | 
			
		||||
        assert_image_equal(reloaded, im)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_incorrect_size():
 | 
			
		||||
    with Image.open(TEST_ICO_FILE) as im:
 | 
			
		||||
        with pytest.raises(ValueError):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -247,6 +247,12 @@ The :py:meth:`~PIL.Image.Image.save` method can take the following keyword argum
 | 
			
		|||
 | 
			
		||||
    .. versionadded:: 8.1.0
 | 
			
		||||
 | 
			
		||||
**bitmap_format**
 | 
			
		||||
    By default, the image data will be saved in PNG format. With a bitmap format of
 | 
			
		||||
    "bmp", image data will be saved in BMP format instead.
 | 
			
		||||
 | 
			
		||||
    .. versionadded:: 8.3.0
 | 
			
		||||
 | 
			
		||||
IM
 | 
			
		||||
^^
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,6 +30,7 @@ from math import ceil, log
 | 
			
		|||
from . import BmpImagePlugin, Image, ImageFile, PngImagePlugin
 | 
			
		||||
from ._binary import i16le as i16
 | 
			
		||||
from ._binary import i32le as i32
 | 
			
		||||
from ._binary import o32le as o32
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# --------------------------------------------------------------------
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +54,7 @@ def _save(im, fp, filename):
 | 
			
		|||
    sizes = list(sizes)
 | 
			
		||||
    fp.write(struct.pack("<H", len(sizes)))  # idCount(2)
 | 
			
		||||
    offset = fp.tell() + len(sizes) * 16
 | 
			
		||||
    bmp = im.encoderinfo.get("bitmap_format") == "bmp"
 | 
			
		||||
    provided_images = {im.size: im for im in im.encoderinfo.get("append_images", [])}
 | 
			
		||||
    for size in sizes:
 | 
			
		||||
        width, height = size
 | 
			
		||||
| 
						 | 
				
			
			@ -62,17 +64,30 @@ def _save(im, fp, filename):
 | 
			
		|||
        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 = provided_images.get(size)
 | 
			
		||||
        if not tmp:
 | 
			
		||||
            # TODO: invent a more convenient method for proportional scalings
 | 
			
		||||
            tmp = im.copy()
 | 
			
		||||
            tmp.thumbnail(size, Image.LANCZOS, reducing_gap=None)
 | 
			
		||||
        tmp.save(image_io, "png")
 | 
			
		||||
        bits = BmpImagePlugin.SAVE[tmp.mode][1] if bmp else 32
 | 
			
		||||
        fp.write(struct.pack("<H", bits))  # wBitCount(2)
 | 
			
		||||
 | 
			
		||||
        image_io = BytesIO()
 | 
			
		||||
        if bmp:
 | 
			
		||||
            tmp.save(image_io, "dib")
 | 
			
		||||
 | 
			
		||||
            if bits != 32:
 | 
			
		||||
                and_mask = Image.new("1", tmp.size)
 | 
			
		||||
                ImageFile._save(
 | 
			
		||||
                    and_mask, image_io, [("raw", (0, 0) + tmp.size, 0, ("1", 0, -1))]
 | 
			
		||||
                )
 | 
			
		||||
        else:
 | 
			
		||||
            tmp.save(image_io, "png")
 | 
			
		||||
        image_io.seek(0)
 | 
			
		||||
        image_bytes = image_io.read()
 | 
			
		||||
        if bmp:
 | 
			
		||||
            image_bytes = image_bytes[:8] + o32(height * 2) + image_bytes[12:]
 | 
			
		||||
        bytes_len = len(image_bytes)
 | 
			
		||||
        fp.write(struct.pack("<I", bytes_len))  # dwBytesInRes(4)
 | 
			
		||||
        fp.write(struct.pack("<I", offset))  # dwImageOffset(4)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user