Fail if chroma subsampling selected when writing RGB JPEG

The user presumably doesn't intend to subsample the green and blue
channels.
This commit is contained in:
Benjamin Gilbert 2023-12-04 07:31:24 -06:00
parent 14146732be
commit a5fab5fc0b
3 changed files with 22 additions and 3 deletions

View File

@ -447,9 +447,15 @@ class TestFileJpeg:
im = self.roundtrip(hopper(), subsampling=subsampling)
assert getsampling(im) == (2, 2, 1, 1, 1, 1)
# RGB colorspace, no subsampling by default
im = self.roundtrip(hopper(), keep_rgb=True)
# RGB colorspace
for subsampling in (-1, 0, "4:4:4"):
# "4:4:4" doesn't really make sense for RGB, but the conversion
# to an integer happens at a higher level
im = self.roundtrip(hopper(), keep_rgb=True, subsampling=subsampling)
assert getsampling(im) == (1, 1, 1, 1, 1, 1)
for subsampling in (1, "4:2:2", 2, "4:2:0", 3):
with pytest.raises(OSError):
self.roundtrip(hopper(), keep_rgb=True, subsampling=subsampling)
with pytest.raises(TypeError):
self.roundtrip(hopper(), subsampling="1:1:1")

View File

@ -491,6 +491,9 @@ The :py:meth:`~PIL.Image.Image.save` method supports the following options:
If this option is present and true, those images will be stored as RGB
instead.
When this option is enabled, attempting to chroma-subsample RGB images
with the ``subsampling`` option will raise an :py:exc:`OSError`.
.. versionadded:: 10.2.0
**subsampling**

View File

@ -144,6 +144,16 @@ ImagingJpegEncode(Imaging im, ImagingCodecState state, UINT8 *buf, int bytes) {
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGBX:
#endif
switch (context->subsampling) {
case -1: /* Default */
case 0: /* No subsampling */
break;
default:
/* Would subsample the green and blue
channels, which doesn't make sense */
state->errcode = IMAGING_CODEC_CONFIG;
return -1;
}
jpeg_set_colorspace(&context->cinfo, JCS_RGB);
break;
default: