diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index e442471d1ca..bd52316d446 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -230,6 +230,14 @@ def test_save_rgba(self, tmp_path: Path) -> None: outfile = tmp_path / "temp.tif" im.save(outfile) + def test_save_ycbcr(self, tmp_path: Path) -> None: + im = hopper("YCbCr") + outfile = tmp_path / "temp.tif" + im.save(outfile) + + with Image.open(outfile) as reloaded: + assert_image_equal(im, reloaded) + def test_save_unsupported_mode(self, tmp_path: Path) -> None: im = hopper("HSV") outfile = tmp_path / "temp.tif" diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 472dfcf5802..69a06ba338e 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -267,10 +267,8 @@ (MM, 5, (1,), 1, (16, 16, 16, 16), ()): ("CMYK", "CMYK;16B"), (II, 6, (1,), 1, (8,), ()): ("L", "L"), (MM, 6, (1,), 1, (8,), ()): ("L", "L"), - # JPEG compressed images handled by LibTiff and auto-converted to RGBX - # Minimal Baseline TIFF requires YCbCr images to have 3 SamplesPerPixel - (II, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGBX"), - (MM, 6, (1,), 1, (8, 8, 8), ()): ("RGB", "RGBX"), + (II, 6, (1,), 1, (8, 8, 8), ()): ("YCbCr", "YCbCr"), + (MM, 6, (1,), 1, (8, 8, 8), ()): ("YCbCr", "YCbCr"), (II, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"), (MM, 8, (1,), 1, (8, 8, 8), ()): ("LAB", "LAB"), } @@ -1588,14 +1586,14 @@ def _setup(self) -> None: # fillorder==2 modes have a corresponding # fillorder=1 mode self._mode, rawmode = OPEN_INFO[key] - # YCbCr images with new jpeg compression with pixels in one plane - # unpacked straight into RGB values - if ( - photo == 6 - and self._compression == "jpeg" - and self._planar_configuration == 1 - ): - rawmode = "RGB" + if photo == 6: + self._mode = "RGB" + if self._compression in "jpeg" and self._planar_configuration == 1: + # YCbCr images with new jpeg compression with pixels in one plane + # unpacked straight into RGB values + rawmode = "RGB" + else: + rawmode = "RGBX" # libtiff always returns the bytes in native order. # we're expecting image byte order. So, if the rawmode # contains I;16, we need to convert from native to image