Skip to content

Commit 2e7e8c3

Browse files
committed
feat: Don't scale down huge non-JPEGs, recode them first (#7977)
If after recoding to JPEG an image isn't huge anymore, don't scale it down, this preserves quality of most screenshots. For JPEGs however we don't try to recode them w/o scaling down: - They are already JPEG-encoded, maybe with higher quality, but anyway. - We don't want extra CPU work for most photos.
1 parent 942172a commit 2e7e8c3

5 files changed

Lines changed: 40 additions & 6 deletions

File tree

src/blob.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,17 @@ impl<'a> BlobObject<'a> {
416416
// also `Viewtype::Gif` (maybe renamed to `Animation`) should be used for animated
417417
// images.
418418
let do_scale = exceeds_max_bytes
419+
// Don't recode huge JPEGs w/o resizing:
420+
// - It may be huge because of high JPEG quality, but we don't know that.
421+
// - We don't want extra CPU work for most photos.
422+
&& (fmt == ImageFormat::Jpeg
423+
|| encoded_img_exceeds_bytes(
424+
context,
425+
&img,
426+
ofmt.clone(),
427+
max_bytes,
428+
&mut encoded,
429+
)?)
419430
|| is_avatar
420431
&& (exceeds_wh
421432
|| exif.is_some() && {
@@ -477,8 +488,7 @@ impl<'a> BlobObject<'a> {
477488
}
478489
}
479490
}
480-
481-
if do_scale || exif.is_some() {
491+
if !encoded.is_empty() || exif.is_some() {
482492
// The file format is JPEG/PNG now, we may have to change the file extension
483493
if !matches!(fmt, ImageFormat::Jpeg)
484494
&& matches!(ofmt, ImageOutputFormat::Jpeg { .. })

src/blob/blob_tests.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,26 @@ async fn test_recode_image_balanced_png() {
462462
.unwrap();
463463
}
464464

465+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
466+
async fn test_recode_image_balanced_png_huge() {
467+
let bytes = include_bytes!("../../test-data/image/screenshot-huge.png");
468+
469+
SendImageCheckMediaquality {
470+
viewtype: Viewtype::Image,
471+
media_quality_config: "0",
472+
bytes,
473+
extension: "jpg",
474+
original_width: 1618,
475+
original_height: 949,
476+
compressed_width: 1618,
477+
compressed_height: 949,
478+
..Default::default()
479+
}
480+
.test()
481+
.await
482+
.unwrap();
483+
}
484+
465485
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
466486
async fn test_sticker_with_exif() {
467487
let bytes = include_bytes!("../../test-data/image/logo-exif.png");

src/tests/pre_messages/additional_text.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ async fn test_additional_text_on_different_viewtypes() -> Result<()> {
3434
let (pre_message, _, _) = send_large_image_message(alice, a_group_id).await?;
3535
let msg = bob.recv_msg(&pre_message).await;
3636
assert_eq!(msg.text, "test".to_owned());
37-
assert_eq!(msg.get_text(), "test [Image – 146.12 KiB]".to_owned());
37+
assert!(msg.get_text().starts_with("test [Image – "));
38+
assert!(msg.get_text().ends_with(" KiB]"));
3839

3940
Ok(())
4041
}

src/tests/pre_messages/receiving.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::EventType;
66
use crate::chat;
77
use crate::chat::send_msg;
88
use crate::config::Config;
9+
use crate::constants;
910
use crate::contact;
1011
use crate::download::{DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD, PostMsgMetadata};
1112
use crate::message::{Message, MessageState, Viewtype, delete_msgs, markseen_msgs};
@@ -402,9 +403,11 @@ async fn test_receive_pre_message_image() -> Result<()> {
402403
// test that metadata is correctly returned by methods
403404
assert_eq!(msg.get_post_message_viewtype(), Some(Viewtype::Image));
404405
// recoded image dimensions
405-
assert_eq!(msg.get_filebytes(bob).await?, Some(149632));
406-
assert_eq!(msg.get_height(), 1280);
407-
assert_eq!(msg.get_width(), 720);
406+
let n_bytes: usize = msg.get_filebytes(bob).await?.unwrap().try_into().unwrap();
407+
assert!(100_000 < n_bytes);
408+
assert!(n_bytes <= constants::BALANCED_IMAGE_BYTES);
409+
assert_eq!(msg.get_height(), 1920);
410+
assert_eq!(msg.get_width(), 1080);
408411

409412
Ok(())
410413
}
792 KB
Loading

0 commit comments

Comments
 (0)