From ba78f5d0dad12a5fb54930a220f8b0dd2ffe64d7 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 3 Oct 2022 09:39:37 +1100 Subject: [PATCH 1/9] Document the default layout engine --- src/PIL/ImageFont.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 310072dfc..6c747fc3e 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -945,6 +945,8 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): encoding of any text provided in subsequent operations. :param layout_engine: Which layout engine to use, if available: :data:`.ImageFont.Layout.BASIC` or :data:`.ImageFont.Layout.RAQM`. + If it is available, Raqm layout will be used by default. + Otherwise, basic layout will be used. You can check support for Raqm layout using :py:func:`PIL.features.check_feature` with ``feature="raqm"``. From 74f47d8c1a6152a4dd05ccf4a74079fc438673e0 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 3 Oct 2022 10:03:13 +1100 Subject: [PATCH 2/9] Document that basic layout is faster than raqm --- src/PIL/ImageFont.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 6c747fc3e..6a66f8a71 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -948,6 +948,9 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): If it is available, Raqm layout will be used by default. Otherwise, basic layout will be used. + If complex text layout is not required, basic layout will have + better performance. + You can check support for Raqm layout using :py:func:`PIL.features.check_feature` with ``feature="raqm"``. From 7072ccdad1fdacb6073694a43e204b6fb2358efe Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 9 Oct 2022 08:13:35 +1100 Subject: [PATCH 3/9] Updated harfbuzz to 5.3.0 --- winbuild/build_prepare.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index f4515468f..ad7b1ddb6 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -281,9 +281,9 @@ deps = { "libs": [r"imagequant.lib"], }, "harfbuzz": { - "url": "https://github.com/harfbuzz/harfbuzz/archive/5.2.0.zip", - "filename": "harfbuzz-5.2.0.zip", - "dir": "harfbuzz-5.2.0", + "url": "https://github.com/harfbuzz/harfbuzz/archive/5.3.0.zip", + "filename": "harfbuzz-5.3.0.zip", + "dir": "harfbuzz-5.3.0", "build": [ cmd_cmake("-DHB_HAVE_FREETYPE:BOOL=TRUE"), cmd_nmake(target="clean"), From eef4d1ced12119af1a8137adb1d5c1ce4d95da0f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sun, 9 Oct 2022 08:48:07 +1100 Subject: [PATCH 4/9] Moved mode check outside of loops --- src/libImaging/Paste.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libImaging/Paste.c b/src/libImaging/Paste.c index fafd8141e..acf5202e5 100644 --- a/src/libImaging/Paste.c +++ b/src/libImaging/Paste.c @@ -432,18 +432,18 @@ fill_mask_L( } } else { + int alpha_channel = strcmp(imOut->mode, "RGBa") == 0 || + strcmp(imOut->mode, "RGBA") == 0 || + strcmp(imOut->mode, "La") == 0 || + strcmp(imOut->mode, "LA") == 0 || + strcmp(imOut->mode, "PA") == 0; for (y = 0; y < ysize; y++) { UINT8 *out = (UINT8 *)imOut->image[y + dy] + dx * pixelsize; UINT8 *mask = (UINT8 *)imMask->image[y + sy] + sx; for (x = 0; x < xsize; x++) { for (i = 0; i < pixelsize; i++) { UINT8 channel_mask = *mask; - if ((strcmp(imOut->mode, "RGBa") == 0 || - strcmp(imOut->mode, "RGBA") == 0 || - strcmp(imOut->mode, "La") == 0 || - strcmp(imOut->mode, "LA") == 0 || - strcmp(imOut->mode, "PA") == 0) && - i != 3 && channel_mask != 0) { + if (alpha_channel && i != 3 && channel_mask != 0) { channel_mask = 255 - (255 - channel_mask) * (1 - (255 - out[3]) / 255); } From f9a3178bb34e6b28bc46d42ef88f5069ebabde32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20S=2E=20O=2E=20Bueno?= Date: Sun, 9 Oct 2022 11:47:24 -0300 Subject: [PATCH 5/9] Fix #6652: Handle translucent color used in RGB ImagePallete --- Tests/test_imagepalette.py | 9 +++++++++ src/PIL/ImagePalette.py | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index 475d249ed..0583154f7 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -50,6 +50,15 @@ def test_getcolor(): palette.getcolor("unknown") +def test_getcolor_raises_on_incompatible_color(): + palette = ImagePalette.ImagePalette(mode="RGB") + # Opaque RGBA colors should work + palette.getcolor((0, 0, 0, 255)) + assert palette.getcolor((0, 0, 0)) == palette.getcolor((0, 0, 0, 255)) + with pytest.raises(ValueError): + palette.getcolor((0, 0, 0, 128)) + + @pytest.mark.parametrize( "index, palette", [ diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index b73b2cd9d..e407bbcd1 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -114,9 +114,13 @@ class ImagePalette: if self.rawmode: raise ValueError("palette contains raw palette data") if isinstance(color, tuple): - if self.mode == "RGB": - if len(color) == 4 and color[3] == 255: + if self.mode == "RGB" and len(color) == 4: + if color[3] == 255: color = color[:3] + else: + raise ValueError( + "RGB ImagePalette can't handle non-opaque RGBA colors" + ) elif self.mode == "RGBA": if len(color) == 3: color += (255,) From 397167569a3ec91a787ffc3c43ab6cec62193e18 Mon Sep 17 00:00:00 2001 From: Andrew Murray <3112309+radarhere@users.noreply.github.com> Date: Mon, 10 Oct 2022 09:11:41 +1100 Subject: [PATCH 6/9] Recommend raqm for non-English text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondrej Baranovič --- src/PIL/ImageFont.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PIL/ImageFont.py b/src/PIL/ImageFont.py index 6a66f8a71..60d4ca97f 100644 --- a/src/PIL/ImageFont.py +++ b/src/PIL/ImageFont.py @@ -948,8 +948,8 @@ def truetype(font=None, size=10, index=0, encoding="", layout_engine=None): If it is available, Raqm layout will be used by default. Otherwise, basic layout will be used. - If complex text layout is not required, basic layout will have - better performance. + Raqm layout is recommended for all non-English text. If Raqm layout + is not required, basic layout will have better performance. You can check support for Raqm layout using :py:func:`PIL.features.check_feature` with ``feature="raqm"``. From 982d7c49e318339444fb53d29ac04d19f4a68691 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 10 Oct 2022 11:46:33 +1100 Subject: [PATCH 7/9] Corrected test --- Tests/test_image_access.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tests/test_image_access.py b/Tests/test_image_access.py index bb09a7708..a000cb64c 100644 --- a/Tests/test_image_access.py +++ b/Tests/test_image_access.py @@ -345,13 +345,14 @@ class TestCffi(AccessTest): @pytest.mark.parametrize("mode", ("P", "PA")) def test_p_putpixel_rgb_rgba(self, mode): - for color in [(255, 0, 0), (255, 0, 0, 127)]: + for color in ((255, 0, 0), (255, 0, 0, 127 if mode == "PA" else 255)): im = Image.new(mode, (1, 1)) access = PyAccess.new(im, False) access.putpixel((0, 0), color) - alpha = color[3] if len(color) == 4 and mode == "PA" else 255 - assert im.convert("RGBA").getpixel((0, 0)) == (255, 0, 0, alpha) + if len(color) == 3: + color += (255,) + assert im.convert("RGBA").getpixel((0, 0)) == color class TestImagePutPixelError(AccessTest): From 0b2cef5b03fed477f6988ee60ef5d4b7a6084a38 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 10 Oct 2022 12:02:10 +1100 Subject: [PATCH 8/9] Updated error message --- Tests/test_imagepalette.py | 11 ++++++----- src/PIL/ImagePalette.py | 12 ++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Tests/test_imagepalette.py b/Tests/test_imagepalette.py index 0583154f7..5bda28117 100644 --- a/Tests/test_imagepalette.py +++ b/Tests/test_imagepalette.py @@ -50,11 +50,12 @@ def test_getcolor(): palette.getcolor("unknown") -def test_getcolor_raises_on_incompatible_color(): - palette = ImagePalette.ImagePalette(mode="RGB") - # Opaque RGBA colors should work - palette.getcolor((0, 0, 0, 255)) - assert palette.getcolor((0, 0, 0)) == palette.getcolor((0, 0, 0, 255)) +def test_getcolor_rgba_color_rgb_palette(): + palette = ImagePalette.ImagePalette("RGB") + + # Opaque RGBA colors are converted + assert palette.getcolor((0, 0, 0, 255)) == palette.getcolor((0, 0, 0)) + with pytest.raises(ValueError): palette.getcolor((0, 0, 0, 128)) diff --git a/src/PIL/ImagePalette.py b/src/PIL/ImagePalette.py index e407bbcd1..fe76c86f4 100644 --- a/src/PIL/ImagePalette.py +++ b/src/PIL/ImagePalette.py @@ -114,13 +114,13 @@ class ImagePalette: if self.rawmode: raise ValueError("palette contains raw palette data") if isinstance(color, tuple): - if self.mode == "RGB" and len(color) == 4: - if color[3] == 255: + if self.mode == "RGB": + if len(color) == 4: + if color[3] != 255: + raise ValueError( + "cannot add non-opaque RGBA color to RGB palette" + ) color = color[:3] - else: - raise ValueError( - "RGB ImagePalette can't handle non-opaque RGBA colors" - ) elif self.mode == "RGBA": if len(color) == 3: color += (255,) From 995625325d03a3737164e0454e6792b1d70a7d57 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Mon, 10 Oct 2022 19:24:41 +1100 Subject: [PATCH 9/9] Update CHANGES.rst [ci skip] --- CHANGES.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index c3e60acff..55eabefd4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Changelog (Pillow) 9.3.0 (unreleased) ------------------ +- Raise an error when allocating translucent color to RGB palette #6654 + [jsbueno, radarhere] + - Added reading of TIFF child images #6569 [radarhere]