Add CMYK palettes

This commit is contained in:
Andrew Murray 2026-03-16 20:48:25 +11:00
parent 3a44ba1c75
commit d5d0734169
4 changed files with 39 additions and 4 deletions

View File

@ -91,6 +91,21 @@ def test_rgba_palette(mode: str, palette: tuple[int, ...]) -> None:
assert im.palette.colors == {(1, 2, 3, 4): 0}
@pytest.mark.parametrize(
"mode, palette",
(
("CMYK", (1, 2, 3, 4)),
("CMYKX", (1, 2, 3, 4, 0)),
),
)
def test_cmyk_palette(mode: str, palette: tuple[int, ...]) -> None:
im = Image.new("P", (1, 1))
im.putpalette(palette, mode)
assert im.getpalette() == [250, 249, 248]
assert im.palette is not None
assert im.palette.colors == {(1, 2, 3, 4): 0}
def test_empty_palette() -> None:
im = Image.new("P", (1, 1))
assert im.getpalette() == []

View File

@ -2145,8 +2145,8 @@ class Image:
Alternatively, an 8-bit string may be used instead of an integer sequence.
:param data: A palette sequence (either a list or a string).
:param rawmode: The raw mode of the palette. Either "RGB", "RGBA", or a mode
that can be transformed to "RGB" or "RGBA" (e.g. "R", "BGR;15", "RGBA;L").
:param rawmode: The raw mode of the palette. Either "RGB", "RGBA", "CMYK", or a
mode that can be transformed to one of those modes (e.g. "R", "RGBA;L").
"""
from . import ImagePalette
@ -2165,7 +2165,12 @@ class Image:
palette = ImagePalette.raw(rawmode, data)
self._mode = "PA" if "A" in self.mode else "P"
self.palette = palette
self.palette.mode = "RGBA" if "A" in rawmode else "RGB"
if rawmode.startswith("CMYK"):
self.palette.mode = "CMYK"
elif "A" in rawmode:
self.palette.mode = "RGBA"
else:
self.palette.mode = "RGB"
self.load() # install new palette
def putpixel(

View File

@ -325,6 +325,19 @@ ImagingPackXBGR(UINT8 *out, const UINT8 *in, int pixels) {
}
}
void
ImagingPackCMYK2RGB(UINT8 *out, const UINT8 *in, int xsize) {
int x, nk, tmp;
for (x = 0; x < xsize; x++) {
nk = 255 - in[3];
out[0] = CLIP8(nk - MULDIV255(in[0], nk, tmp));
out[1] = CLIP8(nk - MULDIV255(in[1], nk, tmp));
out[2] = CLIP8(nk - MULDIV255(in[2], nk, tmp));
out += 3;
in += 4;
}
}
void
ImagingPackBGRA(UINT8 *out, const UINT8 *in, int pixels) {
int i;
@ -605,6 +618,7 @@ static struct {
{IMAGING_MODE_CMYK, IMAGING_RAWMODE_M, 8, band1},
{IMAGING_MODE_CMYK, IMAGING_RAWMODE_Y, 8, band2},
{IMAGING_MODE_CMYK, IMAGING_RAWMODE_K, 8, band3},
{IMAGING_MODE_CMYK, IMAGING_RAWMODE_RGB, 24, ImagingPackCMYK2RGB},
/* video (YCbCr) */
{IMAGING_MODE_YCbCr, IMAGING_RAWMODE_YCbCr, 24, ImagingPackRGB},

View File

@ -27,7 +27,8 @@ ImagingPaletteNew(const ModeID mode) {
int i;
ImagingPalette palette;
if (mode != IMAGING_MODE_RGB && mode != IMAGING_MODE_RGBA) {
if (mode != IMAGING_MODE_RGB && mode != IMAGING_MODE_RGBA &&
mode != IMAGING_MODE_CMYK) {
return (ImagingPalette)ImagingError_ModeError();
}