mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-25 09:26:16 +03:00
Fixed issue #857.
When saving a JPEG and specifying 'keep' for quality or subsampling, if the source JPEG image is in grayscale mode, don't try to find the subsampling of the source, because grayscale images don't have any subsampling (it's only for color components). For the moment the fix also ignores subsampling of CMYK JPEG because currently Pillow doesn't support encoding JPEG in YCCK mode (and subsampling doesn't make sense in CMYK, but Pillow permits saving CMYK JPEG with subsampling, that's a bug). This fix pass those errors silently, i.e. it doesn't raise an error when 'keep' is used but it's not possible to keep the subsampling (because the image is grayscale or CMYK). I think it's the proper behavior but I'm not sure.
This commit is contained in:
parent
a65351fcdf
commit
416d8e340e
|
@ -545,6 +545,15 @@ def convert_dict_qtables(qtables):
|
||||||
|
|
||||||
|
|
||||||
def get_sampling(im):
|
def get_sampling(im):
|
||||||
|
# There's no subsampling when image have only 1 layer
|
||||||
|
# (grayscale images) or when they are CMYK (4 layers),
|
||||||
|
# so set subsampling to default value.
|
||||||
|
#
|
||||||
|
# NOTE: currently Pillow can't encode JPEG to YCCK format.
|
||||||
|
# If YCCK support is added in the future, subsampling code will have
|
||||||
|
# to be updated (here and in JpegEncode.c) to deal with 4 layers.
|
||||||
|
if not hasattr(im, 'layers') or im.layers in (1, 4):
|
||||||
|
return -1
|
||||||
sampling = im.layer[0][1:3] + im.layer[1][1:3] + im.layer[2][1:3]
|
sampling = im.layer[0][1:3] + im.layer[1][1:3] + im.layer[2][1:3]
|
||||||
return samplings.get(sampling, -1)
|
return samplings.get(sampling, -1)
|
||||||
|
|
||||||
|
|
BIN
Tests/images/lena_gray.jpg
Normal file
BIN
Tests/images/lena_gray.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
|
@ -224,9 +224,18 @@ class TestFileJpeg(PillowTestCase):
|
||||||
self.assertIsNone(im._getmp())
|
self.assertIsNone(im._getmp())
|
||||||
|
|
||||||
def test_quality_keep(self):
|
def test_quality_keep(self):
|
||||||
|
# RGB
|
||||||
im = Image.open("Tests/images/lena.jpg")
|
im = Image.open("Tests/images/lena.jpg")
|
||||||
f = self.tempfile('temp.jpg')
|
f = self.tempfile('temp.jpg')
|
||||||
im.save(f, quality='keep')
|
im.save(f, quality='keep')
|
||||||
|
# Grayscale
|
||||||
|
im = Image.open("Tests/images/lena_gray.jpg")
|
||||||
|
f = self.tempfile('temp.jpg')
|
||||||
|
im.save(f, quality='keep')
|
||||||
|
# CMYK
|
||||||
|
im = Image.open("Tests/images/pil_sample_cmyk.jpg")
|
||||||
|
f = self.tempfile('temp.jpg')
|
||||||
|
im.save(f, quality='keep')
|
||||||
|
|
||||||
def test_junk_jpeg_header(self):
|
def test_junk_jpeg_header(self):
|
||||||
# https://github.com/python-pillow/Pillow/issues/630
|
# https://github.com/python-pillow/Pillow/issues/630
|
||||||
|
|
10
encode.c
10
encode.c
|
@ -540,8 +540,8 @@ static unsigned int** get_qtables_arrays(PyObject* qtables) {
|
||||||
|
|
||||||
tables = PySequence_Fast(qtables, "expected a sequence");
|
tables = PySequence_Fast(qtables, "expected a sequence");
|
||||||
num_tables = PySequence_Size(qtables);
|
num_tables = PySequence_Size(qtables);
|
||||||
if (num_tables < 2 || num_tables > NUM_QUANT_TBLS) {
|
if (num_tables < 1 || num_tables > NUM_QUANT_TBLS) {
|
||||||
PyErr_SetString(PyExc_ValueError, "Not a valid numbers of quantization tables. Should be between 2 and 4.");
|
PyErr_SetString(PyExc_ValueError, "Not a valid numbers of quantization tables. Should be between 1 and 4.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
qarrays = (unsigned int**) PyMem_Malloc(num_tables * sizeof(unsigned int*));
|
qarrays = (unsigned int**) PyMem_Malloc(num_tables * sizeof(unsigned int*));
|
||||||
|
@ -760,7 +760,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
|
||||||
(ttag_t) PyInt_AsLong(key),
|
(ttag_t) PyInt_AsLong(key),
|
||||||
intav);
|
intav);
|
||||||
free(intav);
|
free(intav);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TRACE((" %d elements, setting as floats \n", len));
|
TRACE((" %d elements, setting as floats \n", len));
|
||||||
floatav = malloc(sizeof(float)*len);
|
floatav = malloc(sizeof(float)*len);
|
||||||
|
@ -903,7 +903,7 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args)
|
||||||
j2k_decode_coord_tuple(tile_offset,
|
j2k_decode_coord_tuple(tile_offset,
|
||||||
&context->tile_offset_x,
|
&context->tile_offset_x,
|
||||||
&context->tile_offset_y);
|
&context->tile_offset_y);
|
||||||
j2k_decode_coord_tuple(tile_size,
|
j2k_decode_coord_tuple(tile_size,
|
||||||
&context->tile_size_x,
|
&context->tile_size_x,
|
||||||
&context->tile_size_y);
|
&context->tile_size_y);
|
||||||
|
|
||||||
|
@ -918,7 +918,7 @@ PyImaging_Jpeg2KEncoderNew(PyObject *self, PyObject *args)
|
||||||
|
|
||||||
if (context->tile_offset_x > context->offset_x
|
if (context->tile_offset_x > context->offset_x
|
||||||
|| context->tile_offset_y > context->offset_y) {
|
|| context->tile_offset_y > context->offset_y) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"JPEG 2000 tile offset too large to cover image area");
|
"JPEG 2000 tile offset too large to cover image area");
|
||||||
Py_DECREF(encoder);
|
Py_DECREF(encoder);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user