The other day, I was haunted by a bug and found that it was caused by PIL after spending a few hours debugging the code.

Initially, the workflow of the my code was like loading the JPEG image with PIL and after some operation, saving the image again. But I didn’t give any other parameters except the file name when using Image.save() method.

After looking up the documentation, I find that PIL will save the image with quality factor 75 by default so that the image quality is reduced. According to the documentation for quality:

The image quality, on a scale from 1 (worst) to 95 (best). The default is 75. Values above 95 should be avoided; 100 disables portions of the JPEG compression algorithm, and results in large files with hardly any gain in image quality.

, using a quality factor of 95 should be enough for preserving the image quality:

img.save('test.jpg', quality=95)

According to this post, even if you use quality=100, the saved image will still be slightly different from the original image. This is because PIL will also use subsampling technique to reduce the image size. You can use subsampling=0 to turn off this feature. Overall, to retain the content of original image, you may use:

img.save('test.jpg', quality=100, subsampling=0)

For JPEG files, there are also a list of preset options you can use for the quality parameter, such web_high, high. The complete list of options can be found here. These preset options will set the subsampling factor and quantization table which is used in image quantization process.

References