Pillow/Tests/test_lib_pack.py

864 lines
31 KiB
Python

from __future__ import annotations
from typing import Union
import pytest
from PIL import Image
from .helper import is_big_endian
X = 255
UnPackParamTypes = list[
tuple[str, str, Union[bytes, int], list[Union[float, tuple[int, ...]]]]
]
def get_pack_parameters() -> UnPackParamTypes:
params: UnPackParamTypes = []
# Mode 1
params += [
("1", "1", b"\x01", [0, 0, 0, 0, 0, 0, 0, X]),
("1", "1;I", b"\x01", [X, X, X, X, X, X, X, 0]),
("1", "1;R", b"\x01", [X, 0, 0, 0, 0, 0, 0, 0]),
("1", "1;IR", b"\x01", [0, X, X, X, X, X, X, X]),
("1", "1", b"\xaa", [X, 0, X, 0, X, 0, X, 0]),
("1", "1;I", b"\xaa", [0, X, 0, X, 0, X, 0, X]),
("1", "1;R", b"\xaa", [0, X, 0, X, 0, X, 0, X]),
("1", "1;IR", b"\xaa", [X, 0, X, 0, X, 0, X, 0]),
("1", "L", b"\xff\x00\x00\xff\x00\x00", [X, 0, 0, X, 0, 0]),
]
# Mode L
params += [
("L", "L", 1, [1, 2, 3, 4]),
("L", "L;16", b"\x00\xc6\x00\xaf", [198, 175]),
("L", "L;16B", b"\xc6\x00\xaf\x00", [198, 175]),
]
# Mode LA
params += [
("LA", "LA", 2, [(1, 2), (3, 4), (5, 6)]),
("LA", "LA;L", 2, [(1, 4), (2, 5), (3, 6)]),
]
# Mode La
params += [("La", "La", 2, [(1, 2), (3, 4), (5, 6)])]
# Mode P
params += [
("P", "P;1", b"\xe4", [1, 1, 1, 0, 0, 255, 0, 0]),
("P", "P;2", b"\xe4", [3, 2, 1, 0]),
("P", "P;4", b"\x02\xef", [0, 2, 14, 15]),
("P", "P", 1, [1, 2, 3, 4]),
]
# Mode PA
params += [
("PA", "PA", 2, [(1, 2), (3, 4), (5, 6)]),
("PA", "PA;L", 2, [(1, 4), (2, 5), (3, 6)]),
]
# Mode RGB
params += [
("RGB", "XRGB;1555", b"\x00\x86\x01\x8c", [(8, 131, 0), (24, 0, 8)]),
("RGB", "RGB;565", b"\x00\n\x00\x1c", [(8, 64, 0), (24, 129, 0)]),
("RGB", "RGB", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("RGB", "RGBX", b"\x01\x02\x03\xff\x05\x06\x07\xff", [(1, 2, 3), (5, 6, 7)]),
("RGB", "XRGB", b"\x00\x02\x03\x04\x00\x06\x07\x08", [(2, 3, 4), (6, 7, 8)]),
("RGB", "XBGR;1555", b"\x00\x86\x01\x8c", [(0, 131, 8), (8, 0, 24)]),
("RGB", "BGR;565", b"\x00\n\x00\x1c", [(0, 64, 8), (0, 129, 24)]),
("RGB", "BGR", 3, [(3, 2, 1), (6, 5, 4), (9, 8, 7)]),
("RGB", "BGRX", b"\x01\x02\x03\x00\x05\x06\x07\x00", [(3, 2, 1), (7, 6, 5)]),
("RGB", "XBGR", b"\x00\x02\x03\x04\x00\x06\x07\x08", [(4, 3, 2), (8, 7, 6)]),
("RGB", "RGB;L", 3, [(1, 4, 7), (2, 5, 8), (3, 6, 9)]),
("RGB", "R", 1, [(1, 9, 9), (2, 9, 9), (3, 9, 9)]),
("RGB", "G", 1, [(9, 1, 9), (9, 2, 9), (9, 3, 9)]),
("RGB", "B", 1, [(9, 9, 1), (9, 9, 2), (9, 9, 3)]),
]
# Mode RGBA
params += [
("RGBA", "RGBA", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBA", "RGBA;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("RGBA", "RGB", 3, [(1, 2, 3, 14), (4, 5, 6, 15), (7, 8, 9, 16)]),
("RGBA", "BGR", 3, [(3, 2, 1, 14), (6, 5, 4, 15), (9, 8, 7, 16)]),
("RGBA", "BGRA", 4, [(3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12)]),
("RGBA", "ABGR", 4, [(4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)]),
(
"RGBA",
"BGRa",
4,
[(191, 127, 63, 4), (223, 191, 159, 8), (233, 212, 191, 12)],
),
("RGBA", "R", 1, [(1, 0, 8, 9), (2, 0, 8, 9), (3, 0, 8, 0)]),
("RGBA", "G", 1, [(6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9)]),
("RGBA", "B", 1, [(6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9)]),
("RGBA", "A", 1, [(6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3)]),
]
# Mode RGBa
params += [
("RGBa", "RGBa", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBa", "BGRa", 4, [(3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12)]),
("RGBa", "aBGR", 4, [(4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)]),
]
# Mode RGBX
params += [
("RGBX", "RGBX", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBX", "RGBX;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("RGBX", "RGB", 3, [(1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X)]),
("RGBX", "BGR", 3, [(3, 2, 1, X), (6, 5, 4, X), (9, 8, 7, X)]),
(
"RGBX",
"BGRX",
b"\x01\x02\x03\x00\x05\x06\x07\x00\t\n\x0b\x00",
[(3, 2, 1, X), (7, 6, 5, X), (11, 10, 9, X)],
),
(
"RGBX",
"XBGR",
b"\x00\x02\x03\x04\x00\x06\x07\x08\x00\n\x0b\x0c",
[(4, 3, 2, X), (8, 7, 6, X), (12, 11, 10, X)],
),
("RGBX", "R", 1, [(1, 0, 8, 9), (2, 0, 8, 9), (3, 0, 8, 0)]),
("RGBX", "G", 1, [(6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9)]),
("RGBX", "B", 1, [(6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9)]),
("RGBX", "X", 1, [(6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3)]),
]
# Mode CMYK
params += [
("CMYK", "CMYK", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
(
"CMYK",
"CMYK;I",
4,
[(254, 253, 252, 251), (250, 249, 248, 247), (246, 245, 244, 243)],
),
("CMYK", "CMYK;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("CMYK", "K", 1, [(6, 7, 0, 1), (6, 7, 0, 2), (0, 7, 0, 3)]),
]
# Mode YCbCr
params += [
("YCbCr", "YCbCr", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("YCbCr", "YCbCr;L", 3, [(1, 4, 7), (2, 5, 8), (3, 6, 9)]),
(
"YCbCr",
"YCbCrX",
b"\x01\x02\x03\xff\x05\x06\x07\xff\t\n\x0b\xff",
[(1, 2, 3), (5, 6, 7), (9, 10, 11)],
),
(
"YCbCr",
"YCbCrK",
b"\x01\x02\x03\xff\x05\x06\x07\xff\t\n\x0b\xff",
[(1, 2, 3), (5, 6, 7), (9, 10, 11)],
),
("YCbCr", "Y", 1, [(1, 0, 8, 9), (2, 0, 8, 9), (3, 0, 8, 0)]),
("YCbCr", "Cb", 1, [(6, 1, 8, 9), (6, 2, 8, 9), (6, 3, 8, 9)]),
("YCbCr", "Cr", 1, [(6, 7, 1, 9), (6, 7, 2, 0), (6, 7, 3, 9)]),
]
# Mode LAB
params += [
("LAB", "LAB", 3, [(1, 130, 131), (4, 133, 134), (7, 136, 137)]),
("LAB", "L", 1, [(1, 9, 9), (2, 9, 9), (3, 9, 9)]),
("LAB", "A", 1, [(9, 1, 9), (9, 2, 9), (9, 3, 9)]),
("LAB", "B", 1, [(9, 9, 1), (9, 9, 2), (9, 9, 3)]),
]
# Mode HSV
params += [
("HSV", "HSV", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("HSV", "H", 1, [(1, 9, 9), (2, 9, 9), (3, 9, 9)]),
("HSV", "S", 1, [(9, 1, 9), (9, 2, 9), (9, 3, 9)]),
("HSV", "V", 1, [(9, 9, 1), (9, 9, 2), (9, 9, 3)]),
]
# Mode I
params += [
("I", "I;16B", 2, [0x0102, 0x0304]),
("I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", [0x01000083, -2097151999]),
]
if is_big_endian():
params += [
("I", "I", 4, [0x01020304, 0x05060708]),
(
"I",
"I;32NS",
b"\x83\x00\x00\x01\x01\x00\x00\x83",
[-2097151999, 0x01000083],
),
]
else:
params += [
("I", "I", 4, [0x04030201, 0x08070605]),
(
"I",
"I;32NS",
b"\x83\x00\x00\x01\x01\x00\x00\x83",
[0x01000083, -2097151999],
),
]
# Mode I;16
if is_big_endian():
params += [("I;16N", "I;16N", 2, [0x0102, 0x0304, 0x0506])]
else:
params += [("I;16N", "I;16N", 2, [0x0201, 0x0403, 0x0605])]
# Mode F float
params += [
("F", "F;32F", 4, [1.539989614439558e-36, 4.063216068939723e-34]),
]
if is_big_endian():
params += [
("F", "F", 4, [2.387939260590663e-38, 6.301941157072183e-36]),
("F", "F;32NF", 4, [2.387939260590663e-38, 6.301941157072183e-36]),
]
else:
params += [
("F", "F", 4, [1.539989614439558e-36, 4.063216068939723e-34]),
("F", "F;32NF", 4, [1.539989614439558e-36, 4.063216068939723e-34]),
]
return params
@pytest.mark.parametrize("mode, rawmode, data, pixels", get_pack_parameters())
def test_pack(
mode: str, rawmode: str, data: bytes | int, pixels: list[float | tuple[int, ...]]
) -> None:
"""
Test packing from {mode} to {rawmode}.
data - Either the number of bytes in a pixel of the rawmode, or a byte string.
If a number is given, bytes will be generated starting at 1.
The byte string will be compared against the pack result.
pixels - The pixels to populate the starting image with.
"""
im = Image.new(mode, (len(pixels), 1))
for x, pixel in enumerate(pixels):
im.putpixel((x, 0), pixel)
if isinstance(data, int):
data_len = data * len(pixels)
data = bytes(range(1, data_len + 1))
assert data == im.tobytes("raw", rawmode)
def get_unpack_parameters() -> UnPackParamTypes:
params: UnPackParamTypes = []
# Mode 1
params += [
("1", "1", b"\x01", [0, 0, 0, 0, 0, 0, 0, X]),
("1", "1;I", b"\x01", [X, X, X, X, X, X, X, 0]),
("1", "1;R", b"\x01", [X, 0, 0, 0, 0, 0, 0, 0]),
("1", "1;IR", b"\x01", [0, X, X, X, X, X, X, X]),
("1", "1", b"\xaa", [X, 0, X, 0, X, 0, X, 0]),
("1", "1;I", b"\xaa", [0, X, 0, X, 0, X, 0, X]),
("1", "1;R", b"\xaa", [0, X, 0, X, 0, X, 0, X]),
("1", "1;IR", b"\xaa", [X, 0, X, 0, X, 0, X, 0]),
("1", "1;8", b"\x00\x01\x02\xff", [0, X, X, X]),
]
# Mode L
params += [
("L", "L;2", b"\xe4", [255, 170, 85, 0]),
("L", "L;2I", b"\xe4", [0, 85, 170, 255]),
("L", "L;2R", b"\xe4", [0, 170, 85, 255]),
("L", "L;2IR", b"\xe4", [255, 85, 170, 0]),
("L", "L;4", b"\x02\xef", [0, 34, 238, 255]),
("L", "L;4I", b"\x02\xef", [255, 221, 17, 0]),
("L", "L;4R", b"\x02\xef", [68, 0, 255, 119]),
("L", "L;4IR", b"\x02\xef", [187, 255, 0, 136]),
("L", "L", 1, [1, 2, 3, 4]),
("L", "L;I", 1, [254, 253, 252, 251]),
("L", "L;R", 1, [128, 64, 192, 32]),
("L", "L;16", 2, [2, 4, 6, 8]),
("L", "L;16B", 2, [1, 3, 5, 7]),
("L", "L;16", b"\x00\xc6\x00\xaf", [198, 175]),
("L", "L;16B", b"\xc6\x00\xaf\x00", [198, 175]),
]
# Mode LA
params += [
("LA", "LA", 2, [(1, 2), (3, 4), (5, 6)]),
("LA", "LA;L", 2, [(1, 4), (2, 5), (3, 6)]),
]
# Mode La
params += [
("La", "La", 2, [(1, 2), (3, 4), (5, 6)]),
]
# Mode P
params += [
("P", "P;1", b"\xe4", [1, 1, 1, 0, 0, 1, 0, 0]),
("P", "P;2", b"\xe4", [3, 2, 1, 0]),
# erroneous?
# ("P", "P;2L", b"\xe4", [1, 1, 1, 0]),
("P", "P;4", b"\x02\xef", [0, 2, 14, 15]),
# erroneous?
# ("P", "P;4L", b"\x02\xef", [2, 10, 10, 0]),
("P", "P", 1, [1, 2, 3, 4]),
("P", "P;R", 1, [128, 64, 192, 32]),
]
# Mode PA
params += [
("PA", "PA", 2, [(1, 2), (3, 4), (5, 6)]),
("PA", "PA;L", 2, [(1, 4), (2, 5), (3, 6)]),
]
# Mode RGB
params += [
("RGB", "RGB", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("RGB", "RGB;L", 3, [(1, 4, 7), (2, 5, 8), (3, 6, 9)]),
("RGB", "RGB;R", 3, [(128, 64, 192), (32, 160, 96)]),
("RGB", "RGB;16L", 6, [(2, 4, 6), (8, 10, 12)]),
("RGB", "RGB;16B", 6, [(1, 3, 5), (7, 9, 11)]),
("RGB", "BGR", 3, [(3, 2, 1), (6, 5, 4), (9, 8, 7)]),
("RGB", "XRGB;1555", 2, [(0, 132, 8), (8, 0, 24)]),
("RGB", "ARGB;1555", 2, [(0, 132, 8), (8, 0, 24)]),
("RGB", "ARGB;1555Z", 2, [(0, 132, 8), (8, 0, 24)]),
("RGB", "XBGR;1555", 2, [(8, 132, 0), (24, 0, 8)]),
("RGB", "ABGR;1555", 2, [(8, 132, 0), (24, 0, 8)]),
("RGB", "RGB;565", 2, [(0, 65, 8), (0, 130, 24)]),
("RGB", "BGR;565", 2, [(8, 65, 0), (24, 130, 0)]),
("RGB", "XBGR;4", 2, [(17, 0, 34), (51, 0, 68)]),
("RGB", "ABGR;4", 2, [(17, 0, 34), (51, 0, 68)]),
("RGB", "RGBX", 4, [(1, 2, 3), (5, 6, 7), (9, 10, 11)]),
("RGB", "RGBX;L", 4, [(1, 4, 7), (2, 5, 8), (3, 6, 9)]),
("RGB", "BGRX", 4, [(3, 2, 1), (7, 6, 5), (11, 10, 9)]),
("RGB", "XRGB", 4, [(2, 3, 4), (6, 7, 8), (10, 11, 12)]),
("RGB", "XBGR", 4, [(4, 3, 2), (8, 7, 6), (12, 11, 10)]),
(
"RGB",
"YCC;P",
b"D]\x9c\x82\x1a\x91\xfaOC\xe7J\x12", # random data
[(127, 102, 0), (192, 227, 0), (213, 255, 170), (98, 255, 133)],
),
("RGB", "R", 1, [(1, 0, 0), (2, 0, 0), (3, 0, 0)]),
("RGB", "G", 1, [(0, 1, 0), (0, 2, 0), (0, 3, 0)]),
("RGB", "B", 1, [(0, 0, 1), (0, 0, 2), (0, 0, 3)]),
("RGB", "R;16B", 2, [(1, 0, 0), (3, 0, 0), (5, 0, 0)]),
("RGB", "G;16B", 2, [(0, 1, 0), (0, 3, 0), (0, 5, 0)]),
("RGB", "B;16B", 2, [(0, 0, 1), (0, 0, 3), (0, 0, 5)]),
("RGB", "R;16L", 2, [(2, 0, 0), (4, 0, 0), (6, 0, 0)]),
("RGB", "G;16L", 2, [(0, 2, 0), (0, 4, 0), (0, 6, 0)]),
("RGB", "B;16L", 2, [(0, 0, 2), (0, 0, 4), (0, 0, 6)]),
]
if is_big_endian():
params += [
("RGB", "R;16N", 2, [(1, 0, 0), (3, 0, 0), (5, 0, 0)]),
("RGB", "G;16N", 2, [(0, 1, 0), (0, 3, 0), (0, 5, 0)]),
("RGB", "B;16N", 2, [(0, 0, 1), (0, 0, 3), (0, 0, 5)]),
]
else:
params += [
("RGB", "R;16N", 2, [(2, 0, 0), (4, 0, 0), (6, 0, 0)]),
("RGB", "G;16N", 2, [(0, 2, 0), (0, 4, 0), (0, 6, 0)]),
("RGB", "B;16N", 2, [(0, 0, 2), (0, 0, 4), (0, 0, 6)]),
]
params += [
("RGB", "CMYK", 4, [(250, 249, 248), (242, 241, 240), (234, 233, 233)]),
]
# Mode RGBA
params += [
("RGBA", "LA", 2, [(1, 1, 1, 2), (3, 3, 3, 4), (5, 5, 5, 6)]),
("RGBA", "LA;16B", 4, [(1, 1, 1, 3), (5, 5, 5, 7), (9, 9, 9, 11)]),
("RGBA", "RGBA", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBA", "RGBAX", 5, [(1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14)]),
("RGBA", "RGBAXX", 6, [(1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16)]),
(
"RGBA",
"RGBa",
4,
[
(63, 127, 191, 4),
(159, 191, 223, 8),
(191, 212, 233, 12),
],
),
(
"RGBA",
"RGBa",
b"\x01\x02\x03\x00\x10\x20\x30\x7f\x10\x20\x30\xff",
[
(0, 0, 0, 0),
(32, 64, 96, 127),
(16, 32, 48, 255),
],
),
(
"RGBA",
"RGBaX",
b"\x01\x02\x03\x00-\x10\x20\x30\x7f-\x10\x20\x30\xff-",
[
(0, 0, 0, 0),
(32, 64, 96, 127),
(16, 32, 48, 255),
],
),
(
"RGBA",
"RGBaXX",
b"\x01\x02\x03\x00==\x10\x20\x30\x7f!!\x10\x20\x30\xff??",
[
(0, 0, 0, 0),
(32, 64, 96, 127),
(16, 32, 48, 255),
],
),
(
"RGBA",
"RGBa;16L",
8,
[
(63, 127, 191, 8),
(159, 191, 223, 16),
(191, 212, 233, 24),
],
),
(
"RGBA",
"RGBa;16L",
b"\x88\x01\x88\x02\x88\x03\x88\x00\x88\x10\x88\x20\x88\x30\x88\xff",
[
(0, 0, 0, 0),
(16, 32, 48, 255),
],
),
(
"RGBA",
"RGBa;16B",
8,
[
(36, 109, 182, 7),
(153, 187, 221, 15),
(188, 210, 232, 23),
],
),
(
"RGBA",
"RGBa;16B",
b"\x01\x88\x02\x88\x03\x88\x00\x88\x10\x88\x20\x88\x30\x88\xff\x88",
[
(0, 0, 0, 0),
(16, 32, 48, 255),
],
),
(
"RGBA",
"BGRa",
4,
[
(191, 127, 63, 4),
(223, 191, 159, 8),
(233, 212, 191, 12),
],
),
(
"RGBA",
"BGRa",
b"\x01\x02\x03\x00\x10\x20\x30\xff",
[
(0, 0, 0, 0),
(48, 32, 16, 255),
],
),
(
"RGBA",
"RGBA;I",
4,
[
(254, 253, 252, 4),
(250, 249, 248, 8),
(246, 245, 244, 12),
],
),
("RGBA", "RGBA;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("RGBA", "ARGB;1555", 2, [(0, 132, 8, 0), (8, 0, 24, 0)]),
("RGBA", "ARGB;1555Z", 2, [(0, 132, 8, X), (8, 0, 24, X)]),
("RGBA", "ABGR;1555", 2, [(8, 132, 0, 0), (24, 0, 8, 0)]),
("RGBA", "ABGR;4", 2, [(17, 0, 34, 0), (51, 0, 68, 0)]),
("RGBA", "RGBA;16L", 8, [(2, 4, 6, 8), (10, 12, 14, 16)]),
("RGBA", "RGBA;16B", 8, [(1, 3, 5, 7), (9, 11, 13, 15)]),
("RGBA", "BGRA;16L", 8, [(6, 4, 2, 8), (14, 12, 10, 16)]),
("RGBA", "BGRA;16B", 8, [(5, 3, 1, 7), (13, 11, 9, 15)]),
("RGBA", "BGRA", 4, [(3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12)]),
("RGBA", "ARGB", 4, [(2, 3, 4, 1), (6, 7, 8, 5), (10, 11, 12, 9)]),
("RGBA", "ABGR", 4, [(4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)]),
(
"RGBA",
"YCCA;P",
b"]bE\x04\xdd\xbej\xed57T\xce\xac\xce:\x11", # random data
[
(0, 161, 0, 4),
(255, 255, 255, 237),
(27, 158, 0, 206),
(0, 118, 0, 17),
],
),
("RGBA", "R", 1, [(1, 0, 0, 0), (2, 0, 0, 0), (3, 0, 0, 0)]),
("RGBA", "G", 1, [(0, 1, 0, 0), (0, 2, 0, 0), (0, 3, 0, 0)]),
("RGBA", "B", 1, [(0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0)]),
("RGBA", "A", 1, [(0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)]),
("RGBA", "R;16B", 2, [(1, 0, 0, 0), (3, 0, 0, 0), (5, 0, 0, 0)]),
("RGBA", "G;16B", 2, [(0, 1, 0, 0), (0, 3, 0, 0), (0, 5, 0, 0)]),
("RGBA", "B;16B", 2, [(0, 0, 1, 0), (0, 0, 3, 0), (0, 0, 5, 0)]),
("RGBA", "A;16B", 2, [(0, 0, 0, 1), (0, 0, 0, 3), (0, 0, 0, 5)]),
("RGBA", "R;16L", 2, [(2, 0, 0, 0), (4, 0, 0, 0), (6, 0, 0, 0)]),
("RGBA", "G;16L", 2, [(0, 2, 0, 0), (0, 4, 0, 0), (0, 6, 0, 0)]),
("RGBA", "B;16L", 2, [(0, 0, 2, 0), (0, 0, 4, 0), (0, 0, 6, 0)]),
("RGBA", "A;16L", 2, [(0, 0, 0, 2), (0, 0, 0, 4), (0, 0, 0, 6)]),
]
if is_big_endian():
params += [
("RGBA", "R;16N", 2, [(1, 0, 0, 0), (3, 0, 0, 0), (5, 0, 0, 0)]),
("RGBA", "G;16N", 2, [(0, 1, 0, 0), (0, 3, 0, 0), (0, 5, 0, 0)]),
("RGBA", "B;16N", 2, [(0, 0, 1, 0), (0, 0, 3, 0), (0, 0, 5, 0)]),
("RGBA", "A;16N", 2, [(0, 0, 0, 1), (0, 0, 0, 3), (0, 0, 0, 5)]),
]
else:
params += [
("RGBA", "R;16N", 2, [(2, 0, 0, 0), (4, 0, 0, 0), (6, 0, 0, 0)]),
("RGBA", "G;16N", 2, [(0, 2, 0, 0), (0, 4, 0, 0), (0, 6, 0, 0)]),
("RGBA", "B;16N", 2, [(0, 0, 2, 0), (0, 0, 4, 0), (0, 0, 6, 0)]),
("RGBA", "A;16N", 2, [(0, 0, 0, 2), (0, 0, 0, 4), (0, 0, 0, 6)]),
]
# Mode RGBa
params += [
("RGBa", "RGBa", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBa", "BGRa", 4, [(3, 2, 1, 4), (7, 6, 5, 8), (11, 10, 9, 12)]),
("RGBa", "aRGB", 4, [(2, 3, 4, 1), (6, 7, 8, 5), (10, 11, 12, 9)]),
("RGBa", "aBGR", 4, [(4, 3, 2, 1), (8, 7, 6, 5), (12, 11, 10, 9)]),
]
# Mode RGBX
params += [
("RGBX", "RGB", 3, [(1, 2, 3, X), (4, 5, 6, X), (7, 8, 9, X)]),
("RGBX", "RGB;L", 3, [(1, 4, 7, X), (2, 5, 8, X), (3, 6, 9, X)]),
("RGBX", "RGB;16B", 6, [(1, 3, 5, X), (7, 9, 11, X)]),
("RGBX", "BGR", 3, [(3, 2, 1, X), (6, 5, 4, X), (9, 8, 7, X)]),
("RGBX", "XRGB;1555", 2, [(0, 132, 8, X), (8, 0, 24, X)]),
("RGBX", "RGB;565", 2, [(0, 65, 8, X), (0, 130, 24, X)]),
("RGBX", "XBGR;1555", 2, [(8, 132, 0, X), (24, 0, 8, X)]),
("RGBX", "BGR;565", 2, [(8, 65, 0, X), (24, 130, 0, X)]),
("RGBX", "XBGR;4", 2, [(17, 0, 34, X), (51, 0, 68, X)]),
("RGBX", "RGBX", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("RGBX", "RGBXX", 5, [(1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14)]),
("RGBX", "RGBXXX", 6, [(1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16)]),
("RGBX", "RGBX;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("RGBX", "RGBX;16L", 8, [(2, 4, 6, 8), (10, 12, 14, 16)]),
("RGBX", "RGBX;16B", 8, [(1, 3, 5, 7), (9, 11, 13, 15)]),
("RGBX", "BGRX", 4, [(3, 2, 1, X), (7, 6, 5, X), (11, 10, 9, X)]),
("RGBX", "XRGB", 4, [(2, 3, 4, X), (6, 7, 8, X), (10, 11, 12, X)]),
("RGBX", "XBGR", 4, [(4, 3, 2, X), (8, 7, 6, X), (12, 11, 10, X)]),
(
"RGBX",
"YCC;P",
b"D]\x9c\x82\x1a\x91\xfaOC\xe7J\x12", # random data
[
(127, 102, 0, X),
(192, 227, 0, X),
(213, 255, 170, X),
(98, 255, 133, X),
],
),
("RGBX", "R", 1, [(1, 0, 0, 0), (2, 0, 0, 0), (3, 0, 0, 0)]),
("RGBX", "G", 1, [(0, 1, 0, 0), (0, 2, 0, 0), (0, 3, 0, 0)]),
("RGBX", "B", 1, [(0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0)]),
("RGBX", "X", 1, [(0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)]),
]
# Mode CMYK
params += [
("CMYK", "CMYK", 4, [(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)]),
("CMYK", "CMYKX", 5, [(1, 2, 3, 4), (6, 7, 8, 9), (11, 12, 13, 14)]),
("CMYK", "CMYKXX", 6, [(1, 2, 3, 4), (7, 8, 9, 10), (13, 14, 15, 16)]),
(
"CMYK",
"CMYK;I",
4,
[
(254, 253, 252, 251),
(250, 249, 248, 247),
(246, 245, 244, 243),
],
),
("CMYK", "CMYK;L", 4, [(1, 4, 7, 10), (2, 5, 8, 11), (3, 6, 9, 12)]),
("CMYK", "C", 1, [(1, 0, 0, 0), (2, 0, 0, 0), (3, 0, 0, 0)]),
("CMYK", "M", 1, [(0, 1, 0, 0), (0, 2, 0, 0), (0, 3, 0, 0)]),
("CMYK", "Y", 1, [(0, 0, 1, 0), (0, 0, 2, 0), (0, 0, 3, 0)]),
("CMYK", "K", 1, [(0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)]),
("CMYK", "C;I", 1, [(254, 0, 0, 0), (253, 0, 0, 0), (252, 0, 0, 0)]),
("CMYK", "M;I", 1, [(0, 254, 0, 0), (0, 253, 0, 0), (0, 252, 0, 0)]),
("CMYK", "Y;I", 1, [(0, 0, 254, 0), (0, 0, 253, 0), (0, 0, 252, 0)]),
("CMYK", "K;I", 1, [(0, 0, 0, 254), (0, 0, 0, 253), (0, 0, 0, 252)]),
]
# Mode YCbCr
params += [
("YCbCr", "YCbCr", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("YCbCr", "YCbCr;L", 3, [(1, 4, 7), (2, 5, 8), (3, 6, 9)]),
("YCbCr", "YCbCrK", 4, [(1, 2, 3), (5, 6, 7), (9, 10, 11)]),
("YCbCr", "YCbCrX", 4, [(1, 2, 3), (5, 6, 7), (9, 10, 11)]),
]
# Mode LAB
params += [
("LAB", "LAB", 3, [(1, 130, 131), (4, 133, 134), (7, 136, 137)]),
("LAB", "L", 1, [(1, 0, 0), (2, 0, 0), (3, 0, 0)]),
("LAB", "A", 1, [(0, 1, 0), (0, 2, 0), (0, 3, 0)]),
("LAB", "B", 1, [(0, 0, 1), (0, 0, 2), (0, 0, 3)]),
]
# Mode HSV
params += [
("HSV", "HSV", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
("HSV", "H", 1, [(1, 0, 0), (2, 0, 0), (3, 0, 0)]),
("HSV", "S", 1, [(0, 1, 0), (0, 2, 0), (0, 3, 0)]),
("HSV", "V", 1, [(0, 0, 1), (0, 0, 2), (0, 0, 3)]),
]
# Mode I
params += [
("I", "I;8", 1, [0x01, 0x02, 0x03, 0x04]),
("I", "I;8S", b"\x01\x83", [1, -125]),
("I", "I;16", 2, [0x0201, 0x0403]),
("I", "I;16S", b"\x83\x01\x01\x83", [0x0183, -31999]),
("I", "I;16B", 2, [0x0102, 0x0304]),
("I", "I;16BS", b"\x83\x01\x01\x83", [-31999, 0x0183]),
("I", "I;32", 4, [0x04030201, 0x08070605]),
("I", "I;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", [0x01000083, -2097151999]),
("I", "I;32B", 4, [0x01020304, 0x05060708]),
("I", "I;32BS", b"\x83\x00\x00\x01\x01\x00\x00\x83", [-2097151999, 0x01000083]),
]
if is_big_endian():
params += [
("I", "I", 4, [0x01020304, 0x05060708]),
("I", "I;16N", 2, [0x0102, 0x0304]),
("I", "I;16NS", b"\x83\x01\x01\x83", [-31999, 0x0183]),
("I", "I;32N", 4, [0x01020304, 0x05060708]),
(
"I",
"I;32NS",
b"\x83\x00\x00\x01\x01\x00\x00\x83",
[
-2097151999,
0x01000083,
],
),
]
else:
params += [
("I", "I", 4, [0x04030201, 0x08070605]),
("I", "I;16N", 2, [0x0201, 0x0403]),
("I", "I;16NS", b"\x83\x01\x01\x83", [0x0183, -31999]),
("I", "I;32N", 4, [0x04030201, 0x08070605]),
(
"I",
"I;32NS",
b"\x83\x00\x00\x01\x01\x00\x00\x83",
[
0x01000083,
-2097151999,
],
),
]
# Mode F int
params += [
("F", "F;8", 1, [0x01, 0x02, 0x03, 0x04]),
("F", "F;8S", b"\x01\x83", [1, -125]),
("F", "F;16", 2, [0x0201, 0x0403]),
("F", "F;16S", b"\x83\x01\x01\x83", [0x0183, -31999]),
("F", "F;16B", 2, [0x0102, 0x0304]),
("F", "F;16BS", b"\x83\x01\x01\x83", [-31999, 0x0183]),
("F", "F;32", 4, [67305984, 134678016]),
("F", "F;32S", b"\x83\x00\x00\x01\x01\x00\x00\x83", [16777348, -2097152000]),
("F", "F;32B", 4, [0x01020304, 0x05060708]),
("F", "F;32BS", b"\x83\x00\x00\x01\x01\x00\x00\x83", [-2097152000, 16777348]),
]
if is_big_endian():
params += [
("F", "F;16N", 2, [0x0102, 0x0304]),
("F", "F;16NS", b"\x83\x01\x01\x83", [-31999, 0x0183]),
("F", "F;32N", 4, [0x01020304, 0x05060708]),
(
"F",
"F;32NS",
b"\x83\x00\x00\x01\x01\x00\x00\x83",
[-2097152000, 16777348],
),
]
else:
params += [
("F", "F;16N", 2, [0x0201, 0x0403]),
("F", "F;16NS", b"\x83\x01\x01\x83", [0x0183, -31999]),
("F", "F;32N", 4, [67305984, 134678016]),
(
"F",
"F;32NS",
b"\x83\x00\x00\x01\x01\x00\x00\x83",
[16777348, -2097152000],
),
]
# Mode F float
params += [
("F", "F;32F", 4, [1.539989614439558e-36, 4.063216068939723e-34]),
("F", "F;32BF", 4, [2.387939260590663e-38, 6.301941157072183e-36]),
(
"F",
"F;64F",
b"333333\xc3?\x00\x00\x00\x00\x00J\x93\xc0", # by struct.pack
[0.15000000596046448, -1234.5],
),
(
"F",
"F;64BF",
b"?\xc3333333\xc0\x93J\x00\x00\x00\x00\x00", # by struct.pack
[0.15000000596046448, -1234.5],
),
]
if is_big_endian():
params += [
("F", "F", 4, [2.387939260590663e-38, 6.301941157072183e-36]),
("F", "F;32NF", 4, [2.387939260590663e-38, 6.301941157072183e-36]),
(
"F",
"F;64NF",
b"?\xc3333333\xc0\x93J\x00\x00\x00\x00\x00",
[0.15000000596046448, -1234.5],
),
]
else:
params += [
("F", "F", 4, [1.539989614439558e-36, 4.063216068939723e-34]),
("F", "F;32NF", 4, [1.539989614439558e-36, 4.063216068939723e-34]),
(
"F",
"F;64NF",
b"333333\xc3?\x00\x00\x00\x00\x00J\x93\xc0",
[0.15000000596046448, -1234.5],
),
]
# Mode I;16
params += [
("I;16", "I;16", 2, [0x0201, 0x0403, 0x0605]),
("I;16", "I;16B", 2, [0x0102, 0x0304, 0x0506]),
("I;16B", "I;16B", 2, [0x0102, 0x0304, 0x0506]),
("I;16L", "I;16L", 2, [0x0201, 0x0403, 0x0605]),
("I;16", "I;12", 2, [0x0010, 0x0203, 0x0040]),
]
if is_big_endian():
params += [
("I;16", "I;16N", 2, [0x0102, 0x0304, 0x0506]),
("I;16B", "I;16N", 2, [0x0102, 0x0304, 0x0506]),
("I;16L", "I;16N", 2, [0x0102, 0x0304, 0x0506]),
("I;16N", "I;16N", 2, [0x0102, 0x0304, 0x0506]),
]
else:
params += [
("I;16", "I;16N", 2, [0x0201, 0x0403, 0x0605]),
("I;16B", "I;16N", 2, [0x0201, 0x0403, 0x0605]),
("I;16L", "I;16N", 2, [0x0201, 0x0403, 0x0605]),
("I;16N", "I;16N", 2, [0x0201, 0x0403, 0x0605]),
]
# Mode CMYK
params += [
("CMYK", "CMYK;16L", 8, [(2, 4, 6, 8), (10, 12, 14, 16)]),
("CMYK", "CMYK;16B", 8, [(1, 3, 5, 7), (9, 11, 13, 15)]),
]
if is_big_endian():
params += [
("CMYK", "CMYK;16N", 8, [(1, 3, 5, 7), (9, 11, 13, 15)]),
]
else:
params += [
("CMYK", "CMYK;16N", 8, [(2, 4, 6, 8), (10, 12, 14, 16)]),
]
return params
@pytest.mark.parametrize("mode, rawmode, data, pixels", get_unpack_parameters())
def test_unpack(
mode: str, rawmode: str, data: bytes | int, pixels: list[float | tuple[int, ...]]
) -> None:
"""
Test unpacking from {rawmode} to {mode}.
data - Either the number of bytes in a pixel of the rawmode, or a byte string.
If a number is given, bytes will be generated starting at 1.
The byte string will be used to populate the starting image.
pixels - The pixels to be compared against the image pixels after unpacking.
"""
if isinstance(data, int):
data_len = data * len(pixels)
data = bytes(range(1, data_len + 1))
im = Image.frombytes(mode, (len(pixels), 1), data, "raw", rawmode, 0, 1)
for x, pixel in enumerate(pixels):
assert pixel == im.getpixel((x, 0))
@pytest.mark.parametrize(
"mode, rawmode, data, pixels",
(
# Mode BGR
("BGR;15", "BGR;15", 3, [(8, 131, 0), (24, 0, 8), (41, 131, 8)]),
("BGR;16", "BGR;16", 3, [(8, 64, 0), (24, 129, 0), (41, 194, 0)]),
("BGR;24", "BGR;24", 3, [(1, 2, 3), (4, 5, 6), (7, 8, 9)]),
# Rawmode RGB/BGR/RGBA/BGRA 15/16/4B
("RGB", "RGB;15", 2, [(8, 131, 0), (24, 0, 8)]),
("RGB", "BGR;15", 2, [(0, 131, 8), (8, 0, 24)]),
("RGB", "RGB;16", 2, [(8, 64, 0), (24, 129, 0)]),
("RGB", "BGR;16", 2, [(0, 64, 8), (0, 129, 24)]),
("RGB", "RGB;4B", 2, [(17, 0, 34), (51, 0, 68)]),
("RGBA", "RGBA;15", 2, [(8, 131, 0, 0), (24, 0, 8, 0)]),
("RGBA", "BGRA;15", 2, [(0, 131, 8, 0), (8, 0, 24, 0)]),
("RGBA", "BGRA;15Z", 2, [(0, 131, 8, X), (8, 0, 24, X)]),
("RGBA", "RGBA;4B", 2, [(17, 0, 34, 0), (51, 0, 68, 0)]),
("RGBX", "RGB;15", 2, [(8, 131, 0, X), (24, 0, 8, X)]),
("RGBX", "BGR;15", 2, [(0, 131, 8, X), (8, 0, 24, X)]),
("RGBX", "RGB;4B", 2, [(17, 0, 34, X), (51, 0, 68, X)]),
),
)
def test_unpack_deprecated(
mode: str, rawmode: str, data: int | bytes, pixels: list[float | tuple[int, ...]]
) -> None:
with pytest.warns(DeprecationWarning):
test_unpack(mode, rawmode, data, pixels)
@pytest.mark.parametrize(
"mode, rawmode, data, pixels",
(
("L", "L", 0, [0]),
("RGB", "RGB", 2, [0]),
("CMYK", "CMYK", 2, [0]),
),
)
def test_unpack_valueerror(
mode: str, rawmode: str, data: int | bytes, pixels: list[float | tuple[int, ...]]
) -> None:
with pytest.raises(ValueError):
test_unpack(mode, rawmode, data, pixels)