Skip to content

Make image-quality more consistent#7822

Open
72374 wants to merge 4 commits intochatmail:mainfrom
72374:make-image-quality-more-consistent
Open

Make image-quality more consistent#7822
72374 wants to merge 4 commits intochatmail:mainfrom
72374:make-image-quality-more-consistent

Conversation

@72374
Copy link
Contributor

@72374 72374 commented Feb 4, 2026

See commit-descriptions for more information.

@72374 72374 force-pushed the make-image-quality-more-consistent branch 3 times, most recently from 40721b8 to a32210d Compare February 4, 2026 15:47
@72374 72374 marked this pull request as ready for review February 4, 2026 16:08
@72374
Copy link
Contributor Author

72374 commented Feb 27, 2026

Here a comparison for the quality of images sent in chats.

Tap here to view the original images
Whole image Cropped to relevant content Further cropped to 1280 pixels Whole image cropped to square
Original image

1 - whole image - original (3840x2128 = 8,171,520 pixels)
3840x2128 =
8,171,520 pixels

2 - cropped to relevant content - original (3521×990 = 3,485,790 pixels)
3521×990 =
3,485,790 pixels

3 - further cropped to 1280 on the long side - original (1280x990 = 1,267,200 pixels)
1280x990 =
1,267,200 pixels

4 - cropped to square - original (2128x2128 = 4,528,384 pixels)
2128x2128 =
4,528,384 pixels

After sending Whole image Cropped to relevant content Further cropped to 1280 pixels* Whole image cropped to square*
Main branch

1 - whole image - main branch (907,520 pixels)
1280x709 =
907,520 pixels

2 - cropped to relevant content - main branch (460,800 pixels)
1280x360 =
460,800 pixels

3 - further cropped to 1280 pixels on the long side - main branch (1,267,200 pixels)
1280x990 =
1,267,200 pixels

4 - cropped to square - main branch (1,638,400 pixels)
1280x1280 =
1,638,400 pixels

This PR

1 - whole image - this pr (1,638,207 pixels)
1719x953 =
1,638,207 pixels

2 - cropped to relevant content - this pr (1,636,014 pixels)
2413x678 =
1,636,014 pixels

3 - further cropped to 1280 on the long side - this pr (1,267,200 pixels)
1280x990 =
1,267,200 pixels

4 - cropped to square - this pr (1,638,400 pixels)
1280x1280 =
1,638,400 pixels

*: The 2 columns on the right are supposed to be identical; i mostly included them, to make it visible that square-ish images already get encoded with up to ~1.6 megapixels, on the "main"-branch.

@72374 72374 force-pushed the make-image-quality-more-consistent branch 2 times, most recently from 75d524b to d23ef46 Compare March 2, 2026 14:09
@72374 72374 force-pushed the make-image-quality-more-consistent branch from d23ef46 to 2693448 Compare March 13, 2026 21:38
Copy link
Collaborator

@iequidoo iequidoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message "chore: Move the definition of the target_wh-variable" should be "refactor:".

Commit message "feat: Use the available file-size for avatar-images better" -- better tell what it actually does briefly, i.e. "feat: Change multiplier to 7/8 when scaling down huge avatars". Long explanation message can be left as is.

src/blob.rs Outdated
let mut target_wh = if !is_avatar && exceeds_wh {
// Limit resolution to the number of pixels that fit within max_wh * max_wh,
// so that the image-quality does not depend on the aspect-ratio.
let mut resolution_limit =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When saying that the number of JPEG blocks matters, i meant that i'd rewrite this in the way like

let mut resolution_limit =
    (f64::from(n_px_longest_side) * (f64::from(max_wh) / (n_jpeg_blocks_sqrt * 8))) as u32;

When calculating n_jpeg_blocks_sqrt, we should ceil both dimensions of course.

And i think, the while loop below can be removed, it's not a problem even if both dimensions aren't aligned to 8 px, the main thing is that the whole image doesn't contain more JPEG blocks than max_whxmax_wh one contains.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the while-loop, and also tried using the JPEG-block-count (converted back into pixel-count by multiplying it with 64, where it was necessary), but there was no noticeable benefit, when i tested it with various images; and when testing that with a series of 10 images with 1 pixel of resolution-difference each, the changes in file-size and resolution of the encoded images were less consistent, than the current code.

So, i suggest using the current, simpler code.
If there is a concrete benefit when the target-resolution is set based on 8x8-blocks of pixels, the code can still be changed later.

Copy link
Collaborator

@iequidoo iequidoo Mar 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then let's bring back the while loop again, it does almost the same job :) Why i suggested to remove it is that while you're trying to align the longest side to 8 px, you may lose the 8-px alignment for another side (which wasn't checked). But this is a corner case, most of the time this won't happen. A coment on that will be helpful also

Copy link
Collaborator

@iequidoo iequidoo Mar 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But basically the probelm is this: imagine you have a 234057 x 7 image. Overall the number of pixels fits into limit for a 1280 px square (but not the number of JPEG blocks!). Then the while loop will reduce it to 234056 x 7. Still, the number of JPEG blocks will exceed the one for the 1280 px square, this is unfortunate because we now have lower byte quota per JPEG block.
...
Such an image should be reduced to 204800 x 6 ideally.

72374 added 4 commits March 14, 2026 17:50
to the only part of the function where it is used.
Currently, the resolution of a resized image that was sent in a chat,
depends on the aspect-ratio.

Assuming the `balanced`-quality-setting is used,
a square image, that is larger than the limits for resolution and file-size,
will be resized to 1280x1280 (1,638,400 pixels),
an image with an aspect-ratio of 16:9,
will be resized to 1280x720 (921,600 pixels),
and if the aspect-ratio is 32:9, to 1280x360 (460,800 pixels).

This change makes it so, that the number of pixels,
in images with different aspect-ratios, will be similar.
The file-size of many images will already be smaller than 20 kB,
when encoded at 256x256, and it can be a large improvement in quality.
The resolution-limits for avatar-images are currently 512x512 or 256x256.
Reducing the resolution further, to 2/3 each step, can reduce the quality
much more than is necessary to fit within the file-size-limits,
which are currently 60 kB or 20 kB.

An image made entirely of noise (which results in unusually
large file-sizes), encoded with jpeg-quality 75,
and 4:2:2-colour-subsampling (the format currently used
for encoding images), can be below 60 kB at 227x227.
For the lower file-size-limit of 20 kB,
such images can be too large at 170x170, but fit at 149x149.
More normal images will have a lower file-size at the same resolution.

Before this change, the target-resolutions for resampling were:
512x512 ->                       341x341 ->                       227x227.

And for the lower file-size-limit:
256x256 ->                       170x170 ->                       113x113.

After this change, the target-resolutions for resampling will be:
512x512 -> 448x448 -> 392x392 -> 343x343 -> 300x300 -> 262x262 -> 229x229.

And for the lower file-size-limit, those will be:
256x256 -> 224x224 -> 196x196 -> 171x171 -> 149x149 -> 130x130 -> 113x113.

This does add 2 steps between the previous target-resolutions,
while still reaching target-resolutions close to the previous ones,
to reduce situations in which the quality will be lower than before.
@72374 72374 force-pushed the make-image-quality-more-consistent branch from 2693448 to 79286ef Compare March 14, 2026 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants