Merge branch 'main' into jpeg2000_l
This commit is contained in:
commit
77df8a36c1
@ -452,6 +452,7 @@ def test_pclr() -> None:
|
||||
) as im:
|
||||
assert im.mode == "P"
|
||||
assert im.palette is not None
|
||||
assert im.palette.mode == "CMYK"
|
||||
assert len(im.palette.colors) == 139
|
||||
assert im.palette.colors[(0, 0, 0, 0)] == 0
|
||||
|
||||
|
||||
@ -707,6 +707,16 @@ class TestFilePng:
|
||||
assert reloaded.png.im_palette is not None
|
||||
assert len(reloaded.png.im_palette[1]) == 3
|
||||
|
||||
def test_plte_cmyk(self, tmp_path: Path) -> None:
|
||||
im = Image.new("P", (1, 1))
|
||||
im.putpalette((0, 100, 150, 200), "CMYK")
|
||||
|
||||
out = tmp_path / "temp.png"
|
||||
im.save(out)
|
||||
|
||||
with Image.open(out) as reloaded:
|
||||
assert reloaded.convert("CMYK").getpixel((0, 0)) == (200, 222, 232, 0)
|
||||
|
||||
def test_getxmp(self) -> None:
|
||||
with Image.open("Tests/images/color_snakes.png") as im:
|
||||
if ElementTree is None:
|
||||
|
||||
@ -13,8 +13,6 @@ _TGA_DIR = os.path.join("Tests", "images", "tga")
|
||||
_TGA_DIR_COMMON = os.path.join(_TGA_DIR, "common")
|
||||
|
||||
|
||||
_ORIGINS = ("tl", "bl")
|
||||
|
||||
_ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1}
|
||||
|
||||
|
||||
@ -29,7 +27,7 @@ _ORIGIN_TO_ORIENTATION = {"tl": 1, "bl": -1}
|
||||
("200x32", "RGBA"),
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize("origin", _ORIGINS)
|
||||
@pytest.mark.parametrize("origin", _ORIGIN_TO_ORIENTATION)
|
||||
@pytest.mark.parametrize("rle", (True, False))
|
||||
def test_sanity(
|
||||
size_mode: tuple[str, str], origin: str, rle: str, tmp_path: Path
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
from .helper import skip_unless_feature
|
||||
from .helper import skip_unless_feature_version
|
||||
|
||||
|
||||
class TestFontCrash:
|
||||
@ -18,8 +16,7 @@ class TestFontCrash:
|
||||
draw.multiline_textbbox((10, 10), "ABC\nAaaa", font, stroke_width=2)
|
||||
draw.text((10, 10), "Test Text", font=font, fill="#000")
|
||||
|
||||
@skip_unless_feature("freetype2")
|
||||
@skip_unless_feature_version("freetype2", "2.12.0")
|
||||
def test_segfault(self) -> None:
|
||||
with pytest.raises(OSError):
|
||||
font = ImageFont.truetype("Tests/fonts/fuzz_font-5203009437302784")
|
||||
self._fuzz_font(font)
|
||||
font = ImageFont.truetype("Tests/fonts/fuzz_font-5203009437302784")
|
||||
self._fuzz_font(font)
|
||||
|
||||
@ -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() == []
|
||||
|
||||
@ -885,7 +885,7 @@ class Image:
|
||||
|
||||
# unpack data
|
||||
e = _getencoder(self.mode, encoder_name, encoder_args)
|
||||
e.setimage(self.im)
|
||||
e.setimage(self.im, (0, 0) + self.size)
|
||||
|
||||
from . import ImageFile
|
||||
|
||||
@ -956,7 +956,7 @@ class Image:
|
||||
|
||||
# unpack data
|
||||
d = _getdecoder(self.mode, decoder_name, decoder_args)
|
||||
d.setimage(self.im)
|
||||
d.setimage(self.im, (0, 0) + self.size)
|
||||
s = d.decode(data)
|
||||
|
||||
if s[0] >= 0:
|
||||
@ -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(
|
||||
|
||||
@ -203,6 +203,7 @@ def _parse_jp2_header(
|
||||
if enumcs in (0, 15):
|
||||
colr = "1"
|
||||
elif enumcs == 12:
|
||||
colr = "CMYK"
|
||||
if nc == 4:
|
||||
mode = "CMYK"
|
||||
elif enumcs == 17:
|
||||
@ -217,7 +218,11 @@ def _parse_jp2_header(
|
||||
if bitdepth > max_bitdepth:
|
||||
max_bitdepth = bitdepth
|
||||
if max_bitdepth <= 8:
|
||||
palette = ImagePalette.ImagePalette("RGBA" if npc == 4 else "RGB")
|
||||
if npc == 4:
|
||||
palette_mode = "CMYK" if colr == "CMYK" else "RGBA"
|
||||
else:
|
||||
palette_mode = "RGB"
|
||||
palette = ImagePalette.ImagePalette(palette_mode)
|
||||
for i in range(ne):
|
||||
color: list[int] = []
|
||||
for value in header.read_fields(">" + ("B" * npc)):
|
||||
|
||||
@ -1353,6 +1353,9 @@ def _save(
|
||||
mode = im.mode
|
||||
|
||||
outmode = mode
|
||||
palette = []
|
||||
if im.palette:
|
||||
palette = im.getpalette() or []
|
||||
if mode == "P":
|
||||
#
|
||||
# attempt to minimize storage requirements for palette images
|
||||
@ -1362,7 +1365,7 @@ def _save(
|
||||
else:
|
||||
# check palette contents
|
||||
if im.palette:
|
||||
colors = max(min(len(im.palette.getdata()[1]) // 3, 256), 1)
|
||||
colors = max(min(len(palette) // 3, 256), 1)
|
||||
else:
|
||||
colors = 256
|
||||
|
||||
@ -1435,7 +1438,7 @@ def _save(
|
||||
|
||||
if im.mode == "P":
|
||||
palette_byte_number = colors * 3
|
||||
palette_bytes = im.im.getpalette("RGB")[:palette_byte_number]
|
||||
palette_bytes = bytes(palette[:palette_byte_number])
|
||||
while len(palette_bytes) < palette_byte_number:
|
||||
palette_bytes += b"\0"
|
||||
chunk(fp, b"PLTE", palette_bytes)
|
||||
|
||||
266
src/_imagingft.c
266
src/_imagingft.c
@ -1042,130 +1042,99 @@ font_render(FontObject *self, PyObject *args) {
|
||||
yy = -(py + glyph_slot->bitmap_top);
|
||||
}
|
||||
|
||||
// Null buffer, is dereferenced in FT_Bitmap_Convert
|
||||
if (!bitmap.buffer && bitmap.rows) {
|
||||
PyErr_SetString(PyExc_OSError, "Bitmap missing for glyph");
|
||||
goto glyph_error;
|
||||
}
|
||||
|
||||
/* convert non-8bpp bitmaps */
|
||||
switch (bitmap.pixel_mode) {
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
convert_scale = 255;
|
||||
break;
|
||||
case FT_PIXEL_MODE_GRAY2:
|
||||
convert_scale = 255 / 3;
|
||||
break;
|
||||
case FT_PIXEL_MODE_GRAY4:
|
||||
convert_scale = 255 / 15;
|
||||
break;
|
||||
default:
|
||||
convert_scale = 1;
|
||||
}
|
||||
switch (bitmap.pixel_mode) {
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
case FT_PIXEL_MODE_GRAY2:
|
||||
case FT_PIXEL_MODE_GRAY4:
|
||||
if (!bitmap_converted_ready) {
|
||||
FT_Bitmap_Init(&bitmap_converted);
|
||||
bitmap_converted_ready = 1;
|
||||
}
|
||||
error = FT_Bitmap_Convert(library, &bitmap, &bitmap_converted, 1);
|
||||
if (error) {
|
||||
geterror(error);
|
||||
goto glyph_error;
|
||||
}
|
||||
bitmap = bitmap_converted;
|
||||
/* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
break;
|
||||
case FT_PIXEL_MODE_BGRA:
|
||||
if (color) {
|
||||
if (bitmap.buffer) {
|
||||
/* convert non-8bpp bitmaps */
|
||||
switch (bitmap.pixel_mode) {
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
convert_scale = 255;
|
||||
break;
|
||||
}
|
||||
/* we didn't ask for color, fall through to default */
|
||||
default:
|
||||
PyErr_SetString(PyExc_OSError, "unsupported bitmap pixel mode");
|
||||
goto glyph_error;
|
||||
}
|
||||
|
||||
/* clip glyph bitmap width to target image bounds */
|
||||
x0 = 0;
|
||||
x1 = bitmap.width;
|
||||
if (xx < 0) {
|
||||
x0 = -xx;
|
||||
}
|
||||
if (xx + x1 > im->xsize) {
|
||||
x1 = im->xsize - xx;
|
||||
}
|
||||
|
||||
source = (unsigned char *)bitmap.buffer;
|
||||
for (bitmap_y = 0; bitmap_y < bitmap.rows; bitmap_y++, yy++) {
|
||||
/* clip glyph bitmap height to target image bounds */
|
||||
if (yy >= 0 && yy < im->ysize) {
|
||||
/* blend this glyph into the buffer */
|
||||
int k;
|
||||
unsigned char *target;
|
||||
unsigned int tmp;
|
||||
if (color) {
|
||||
/* target[RGB] returns the color, target[A] returns the mask */
|
||||
/* target bands get split again in ImageDraw.text */
|
||||
target = (unsigned char *)im->image[yy] + xx * 4;
|
||||
} else {
|
||||
target = im->image8[yy] + xx;
|
||||
}
|
||||
if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
|
||||
/* paste color glyph */
|
||||
for (k = x0; k < x1; k++) {
|
||||
unsigned int src_alpha = source[k * 4 + 3];
|
||||
|
||||
/* paste only if source has data */
|
||||
if (src_alpha > 0) {
|
||||
/* unpremultiply BGRa */
|
||||
int src_red =
|
||||
CLIP8((255 * (int)source[k * 4 + 2]) / src_alpha);
|
||||
int src_green =
|
||||
CLIP8((255 * (int)source[k * 4 + 1]) / src_alpha);
|
||||
int src_blue =
|
||||
CLIP8((255 * (int)source[k * 4 + 0]) / src_alpha);
|
||||
|
||||
/* blend required if target has data */
|
||||
if (target[k * 4 + 3] > 0) {
|
||||
/* blend RGBA colors */
|
||||
target[k * 4 + 0] =
|
||||
BLEND(src_alpha, target[k * 4 + 0], src_red, tmp);
|
||||
target[k * 4 + 1] =
|
||||
BLEND(src_alpha, target[k * 4 + 1], src_green, tmp);
|
||||
target[k * 4 + 2] =
|
||||
BLEND(src_alpha, target[k * 4 + 2], src_blue, tmp);
|
||||
target[k * 4 + 3] = CLIP8(
|
||||
src_alpha +
|
||||
MULDIV255(target[k * 4 + 3], (255 - src_alpha), tmp)
|
||||
);
|
||||
} else {
|
||||
/* paste unpremultiplied RGBA values */
|
||||
target[k * 4 + 0] = src_red;
|
||||
target[k * 4 + 1] = src_green;
|
||||
target[k * 4 + 2] = src_blue;
|
||||
target[k * 4 + 3] = src_alpha;
|
||||
}
|
||||
}
|
||||
case FT_PIXEL_MODE_GRAY2:
|
||||
convert_scale = 255 / 3;
|
||||
break;
|
||||
case FT_PIXEL_MODE_GRAY4:
|
||||
convert_scale = 255 / 15;
|
||||
break;
|
||||
default:
|
||||
convert_scale = 1;
|
||||
}
|
||||
switch (bitmap.pixel_mode) {
|
||||
case FT_PIXEL_MODE_MONO:
|
||||
case FT_PIXEL_MODE_GRAY2:
|
||||
case FT_PIXEL_MODE_GRAY4:
|
||||
if (!bitmap_converted_ready) {
|
||||
FT_Bitmap_Init(&bitmap_converted);
|
||||
bitmap_converted_ready = 1;
|
||||
}
|
||||
} else if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
|
||||
error = FT_Bitmap_Convert(library, &bitmap, &bitmap_converted, 1);
|
||||
if (error) {
|
||||
geterror(error);
|
||||
goto glyph_error;
|
||||
}
|
||||
bitmap = bitmap_converted;
|
||||
/* bitmap is now FT_PIXEL_MODE_GRAY, fall through */
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
break;
|
||||
case FT_PIXEL_MODE_BGRA:
|
||||
if (color) {
|
||||
unsigned char *ink = (unsigned char *)&foreground_ink;
|
||||
break;
|
||||
}
|
||||
/* we didn't ask for color, fall through to default */
|
||||
default:
|
||||
PyErr_SetString(PyExc_OSError, "unsupported bitmap pixel mode");
|
||||
goto glyph_error;
|
||||
}
|
||||
|
||||
/* clip glyph bitmap width to target image bounds */
|
||||
x0 = 0;
|
||||
x1 = bitmap.width;
|
||||
if (xx < 0) {
|
||||
x0 = -xx;
|
||||
}
|
||||
if (xx + x1 > im->xsize) {
|
||||
x1 = im->xsize - xx;
|
||||
}
|
||||
|
||||
source = (unsigned char *)bitmap.buffer;
|
||||
for (bitmap_y = 0; bitmap_y < bitmap.rows; bitmap_y++, yy++) {
|
||||
/* clip glyph bitmap height to target image bounds */
|
||||
if (yy >= 0 && yy < im->ysize) {
|
||||
/* blend this glyph into the buffer */
|
||||
int k;
|
||||
unsigned char *target;
|
||||
unsigned int tmp;
|
||||
if (color) {
|
||||
/* target[RGB] returns the color, target[A] returns the mask */
|
||||
/* target bands get split again in ImageDraw.text */
|
||||
target = (unsigned char *)im->image[yy] + xx * 4;
|
||||
} else {
|
||||
target = im->image8[yy] + xx;
|
||||
}
|
||||
if (color && bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) {
|
||||
/* paste color glyph */
|
||||
for (k = x0; k < x1; k++) {
|
||||
unsigned int src_alpha = source[k] * convert_scale;
|
||||
unsigned int src_alpha = source[k * 4 + 3];
|
||||
|
||||
/* paste only if source has data */
|
||||
if (src_alpha > 0) {
|
||||
/* unpremultiply BGRa */
|
||||
int src_red =
|
||||
CLIP8((255 * (int)source[k * 4 + 2]) / src_alpha);
|
||||
int src_green =
|
||||
CLIP8((255 * (int)source[k * 4 + 1]) / src_alpha);
|
||||
int src_blue =
|
||||
CLIP8((255 * (int)source[k * 4 + 0]) / src_alpha);
|
||||
|
||||
/* blend required if target has data */
|
||||
if (target[k * 4 + 3] > 0) {
|
||||
/* blend RGBA colors */
|
||||
target[k * 4 + 0] = BLEND(
|
||||
src_alpha, target[k * 4 + 0], ink[0], tmp
|
||||
src_alpha, target[k * 4 + 0], src_red, tmp
|
||||
);
|
||||
target[k * 4 + 1] = BLEND(
|
||||
src_alpha, target[k * 4 + 1], ink[1], tmp
|
||||
src_alpha, target[k * 4 + 1], src_green, tmp
|
||||
);
|
||||
target[k * 4 + 2] = BLEND(
|
||||
src_alpha, target[k * 4 + 2], ink[2], tmp
|
||||
src_alpha, target[k * 4 + 2], src_blue, tmp
|
||||
);
|
||||
target[k * 4 + 3] = CLIP8(
|
||||
src_alpha +
|
||||
@ -1174,35 +1143,68 @@ font_render(FontObject *self, PyObject *args) {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
target[k * 4 + 0] = ink[0];
|
||||
target[k * 4 + 1] = ink[1];
|
||||
target[k * 4 + 2] = ink[2];
|
||||
/* paste unpremultiplied RGBA values */
|
||||
target[k * 4 + 0] = src_red;
|
||||
target[k * 4 + 1] = src_green;
|
||||
target[k * 4 + 2] = src_blue;
|
||||
target[k * 4 + 3] = src_alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (k = x0; k < x1; k++) {
|
||||
unsigned int src_alpha = source[k] * convert_scale;
|
||||
if (src_alpha > 0) {
|
||||
target[k] =
|
||||
target[k] > 0
|
||||
? CLIP8(
|
||||
src_alpha +
|
||||
MULDIV255(
|
||||
target[k], (255 - src_alpha), tmp
|
||||
} else if (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
|
||||
if (color) {
|
||||
unsigned char *ink = (unsigned char *)&foreground_ink;
|
||||
for (k = x0; k < x1; k++) {
|
||||
unsigned int src_alpha = source[k] * convert_scale;
|
||||
if (src_alpha > 0) {
|
||||
if (target[k * 4 + 3] > 0) {
|
||||
target[k * 4 + 0] = BLEND(
|
||||
src_alpha, target[k * 4 + 0], ink[0], tmp
|
||||
);
|
||||
target[k * 4 + 1] = BLEND(
|
||||
src_alpha, target[k * 4 + 1], ink[1], tmp
|
||||
);
|
||||
target[k * 4 + 2] = BLEND(
|
||||
src_alpha, target[k * 4 + 2], ink[2], tmp
|
||||
);
|
||||
target[k * 4 + 3] = CLIP8(
|
||||
src_alpha + MULDIV255(
|
||||
target[k * 4 + 3],
|
||||
(255 - src_alpha),
|
||||
tmp
|
||||
)
|
||||
);
|
||||
} else {
|
||||
target[k * 4 + 0] = ink[0];
|
||||
target[k * 4 + 1] = ink[1];
|
||||
target[k * 4 + 2] = ink[2];
|
||||
target[k * 4 + 3] = src_alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (k = x0; k < x1; k++) {
|
||||
unsigned int src_alpha = source[k] * convert_scale;
|
||||
if (src_alpha > 0) {
|
||||
target[k] =
|
||||
target[k] > 0
|
||||
? CLIP8(
|
||||
src_alpha +
|
||||
MULDIV255(
|
||||
target[k], (255 - src_alpha), tmp
|
||||
)
|
||||
)
|
||||
)
|
||||
: src_alpha;
|
||||
: src_alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString(PyExc_OSError, "unsupported bitmap pixel mode");
|
||||
goto glyph_error;
|
||||
}
|
||||
} else {
|
||||
PyErr_SetString(PyExc_OSError, "unsupported bitmap pixel mode");
|
||||
goto glyph_error;
|
||||
}
|
||||
source += bitmap.pitch;
|
||||
}
|
||||
source += bitmap.pitch;
|
||||
}
|
||||
x += glyph_info[i].x_advance;
|
||||
y += glyph_info[i].y_advance;
|
||||
|
||||
15
src/decode.c
15
src/decode.c
@ -163,7 +163,7 @@ _setimage(ImagingDecoderObject *decoder, PyObject *args) {
|
||||
x0 = y0 = x1 = y1 = 0;
|
||||
|
||||
/* FIXME: should publish the ImagingType descriptor */
|
||||
if (!PyArg_ParseTuple(args, "O|(iiii)", &op, &x0, &y0, &x1, &y1)) {
|
||||
if (!PyArg_ParseTuple(args, "O(iiii)", &op, &x0, &y0, &x1, &y1)) {
|
||||
return NULL;
|
||||
}
|
||||
im = PyImaging_AsImaging(op);
|
||||
@ -176,15 +176,10 @@ _setimage(ImagingDecoderObject *decoder, PyObject *args) {
|
||||
state = &decoder->state;
|
||||
|
||||
/* Setup decoding tile extent */
|
||||
if (x0 == 0 && x1 == 0) {
|
||||
state->xsize = im->xsize;
|
||||
state->ysize = im->ysize;
|
||||
} else {
|
||||
state->xoff = x0;
|
||||
state->yoff = y0;
|
||||
state->xsize = x1 - x0;
|
||||
state->ysize = y1 - y0;
|
||||
}
|
||||
state->xoff = x0;
|
||||
state->yoff = y0;
|
||||
state->xsize = x1 - x0;
|
||||
state->ysize = y1 - y0;
|
||||
|
||||
if (state->xoff < 0 || state->xsize <= 0 ||
|
||||
state->xsize + state->xoff > (int)im->xsize || state->yoff < 0 ||
|
||||
|
||||
15
src/encode.c
15
src/encode.c
@ -232,7 +232,7 @@ _setimage(ImagingEncoderObject *encoder, PyObject *args) {
|
||||
x0 = y0 = x1 = y1 = 0;
|
||||
|
||||
/* FIXME: should publish the ImagingType descriptor */
|
||||
if (!PyArg_ParseTuple(args, "O|(nnnn)", &op, &x0, &y0, &x1, &y1)) {
|
||||
if (!PyArg_ParseTuple(args, "O(nnnn)", &op, &x0, &y0, &x1, &y1)) {
|
||||
return NULL;
|
||||
}
|
||||
im = PyImaging_AsImaging(op);
|
||||
@ -248,15 +248,10 @@ _setimage(ImagingEncoderObject *encoder, PyObject *args) {
|
||||
|
||||
state = &encoder->state;
|
||||
|
||||
if (x0 == 0 && x1 == 0) {
|
||||
state->xsize = im->xsize;
|
||||
state->ysize = im->ysize;
|
||||
} else {
|
||||
state->xoff = x0;
|
||||
state->yoff = y0;
|
||||
state->xsize = x1 - x0;
|
||||
state->ysize = y1 - y0;
|
||||
}
|
||||
state->xoff = x0;
|
||||
state->yoff = y0;
|
||||
state->xsize = x1 - x0;
|
||||
state->ysize = y1 - y0;
|
||||
|
||||
if (state->xoff < 0 || state->xsize <= 0 ||
|
||||
state->xsize + state->xoff > im->xsize || state->yoff < 0 ||
|
||||
|
||||
@ -601,6 +601,7 @@ j2ku_sycca_rgba(
|
||||
static const struct j2k_decode_unpacker j2k_unpackers[] = {
|
||||
{IMAGING_MODE_L, OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_l},
|
||||
{IMAGING_MODE_P, OPJ_CLRSPC_SRGB, 1, 0, j2ku_gray_l},
|
||||
{IMAGING_MODE_P, OPJ_CLRSPC_CMYK, 1, 0, j2ku_gray_l},
|
||||
{IMAGING_MODE_PA, OPJ_CLRSPC_SRGB, 2, 0, j2ku_graya_la},
|
||||
{IMAGING_MODE_I_16, OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_i},
|
||||
{IMAGING_MODE_I_16B, OPJ_CLRSPC_GRAY, 1, 0, j2ku_gray_i},
|
||||
|
||||
@ -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},
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user