-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Fix qtables and quality scaling #8879
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix qtables and quality scaling #8879
Conversation
When both `qtables` and `quality` are provided, Pillow previously passed the raw `quality` value directly to `jpeg_add_quant_table()` as the scale factor, which caused incorrect quantization. This commit corrects the behavior by using `jpeg_quality_scaling(quality)` to compute the proper JPEG quantization scaling factor, consistent with `jpeg_set_quality()`. This ensures expected compression behavior when custom qtables are used alongside a specified quality level.
When both a custom quantization table and a quality value are provided, the quantization table should be scaled using the JPEG quality scaling factor. If quality is not explicitly set, the default base quality of 50 is used to preserve the original table. This ensures consistent behavior when saving JPEGs with custom qtables. Fixes part of the issue with applying 'quality' to 'qtables'.
Just to note - this code was originally added in #77 Would you be able to add a test that passes with your change, but fails without it?
Could you link to documentation or similar describing this? |
…equivalent to specifying only a quality
for more information, see https://pre-commit.ci
This behavior is defined directly in the libjpeg-turbo source code. In jcparam.c, it is explicitly stated: /* The basic table is used as-is (scaling 100) for a quality of 50.
* Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
* note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
* to make all the table entries 1 (hence, minimum quantization loss).
* Qualities 1..50 are converted to scaling percentage 5000/Q.
*/ This means that a quality value of 50 corresponds to using the default quantization table as-is, without any scaling. Hence, when reusing or preserving a quantization table, it's consistent to assume that it's equivalent to a quality of 50. |
The test you added was to
You tested it with a value of 75. Testing this further, I find that the results don't match for 0-23, do match for 24-100, but don't match if I don't specify quality at all. Any thoughts? Also, in case you haven't seen it, and think it needs updating, here is our current documentation of the 'quality' parameter. |
…en giving a quality and a qantization table
I found the problem, it came from the fact that force_baseline was set to true when the qtable was not given and to false when the qtable was given so I set it to true when the qtable and the quality were given and to false when only the qtable was given |
for more information, see https://pre-commit.ci
And for the documentation, the quality parameters seem good to me, it's more qtables that need to be modified, adding the fact that they are modified by the quality parameters if they are present. Or add it to the 2? |
@radarhere is it ok with you or are there still things you want me to correct? |
Sorry, still wondering about this. If I save with qtables and no quality, and compare that against no qtables and no quality, it doesn’t match. From the user’s perspective, why should that be a special case? https://pillow--8879.org.readthedocs.build/en/8879/handbook/image-file-formats.html#jpeg-saving
Isn't the default value different when saving with qtables? |
Hello yes save with qtables and no quality use the qtable without changing it and giving no qtable and no quality will take the standard qtables from jpeg standard at 50 and apply a factor calculated from the default quality in pillow so 75 For the default quality value when saving only with qtables, there is none because the qtable is not modified if there is no quality and so can be considered to have already been applied to the qtable sent. This makes it possible to recompress an image with a precise quantization table. |
When both a custom quantization table and a quality value are provided,
the quantization table should be scaled using the JPEG quality scaling factor.
If quality is not explicitly set, the default base quality of 50 is used to preserve the original table.
This ensures consistent behavior when saving JPEGs with custom qtables.
Before this correction, a quality set with a quantization table worked in reverse: the closer the quality was to 0, the less aggressive the quantization table was (made up of 1) and the closer it was to 100, the more it resembled the original table, whereas a standard jpeg table corresponds to a quality of 50. now the inserted table is modified by the quality parameter like a standard jpeg quantization table.