From d0a7ccc4ed51264990dcc9dbbf0a538dfd4ed3e5 Mon Sep 17 00:00:00 2001 From: 72374 <250991390+72374@users.noreply.github.com> Date: Wed, 15 Apr 2026 00:27:31 +0200 Subject: [PATCH 1/3] feat: Use `resize` when resampling images with up to 4 megapixels --- src/blob.rs | 24 +++++++++++------------ src/tests/pre_messages/additional_text.rs | 2 +- src/tests/pre_messages/receiving.rs | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/blob.rs b/src/blob.rs index a60ebe65c7..0f96056ed1 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -457,19 +457,17 @@ impl<'a> BlobObject<'a> { self::add_white_bg(&mut img); } - // resize() results in often slightly better quality, - // however, comes at high price of being 4+ times slower than thumbnail(). - // for a typical camera image that is sent, this may be a change from "instant" (500ms) to "long time waiting" (3s). - // as we do not have recoding in background while chat has already a preview, - // we vote for speed. - // exception is the avatar image: this is far more often sent than recoded, - // usually has less pixels by cropping, UI that needs to wait anyways, - // and also benefits from slightly better (5%) encoding of Triangle-filtered images. - let new_img = if is_avatar { - img.resize(target_wh, target_wh, image::imageops::FilterType::Triangle) - } else { - img.thumbnail(target_wh, target_wh) - }; + // resize() results in better quality than thumbnail(); however, when using resize(), + // sending images can require about 60% more time. + // As we do not have recoding in the background, while the chat already has a preview, + // and the processing-time is proportional to the original resolution, + // we choose the faster resampling, if the original image has a high resolution. + let new_img = + if is_avatar || img.width().saturating_mul(img.height()) <= 2000 * 2000 { + img.resize(target_wh, target_wh, image::imageops::FilterType::Triangle) + } else { + img.thumbnail(target_wh, target_wh) + }; if encoded_img_exceeds_bytes( context, diff --git a/src/tests/pre_messages/additional_text.rs b/src/tests/pre_messages/additional_text.rs index f37baa4e4e..40204a9c97 100644 --- a/src/tests/pre_messages/additional_text.rs +++ b/src/tests/pre_messages/additional_text.rs @@ -34,7 +34,7 @@ async fn test_additional_text_on_different_viewtypes() -> Result<()> { let (pre_message, _, _) = send_large_image_message(alice, a_group_id).await?; let msg = bob.recv_msg(&pre_message).await; assert_eq!(msg.text, "test".to_owned()); - assert_eq!(msg.get_text(), "test [Image – 228.45 KiB]".to_owned()); + assert_eq!(msg.get_text(), "test [Image – 210.38 KiB]".to_owned()); Ok(()) } diff --git a/src/tests/pre_messages/receiving.rs b/src/tests/pre_messages/receiving.rs index 06f7abec5b..2ecd4a0ad7 100644 --- a/src/tests/pre_messages/receiving.rs +++ b/src/tests/pre_messages/receiving.rs @@ -402,7 +402,7 @@ async fn test_receive_pre_message_image() -> Result<()> { // test that metadata is correctly returned by methods assert_eq!(msg.get_post_message_viewtype(), Some(Viewtype::Image)); // recoded image dimensions - assert_eq!(msg.get_filebytes(bob).await?, Some(233935)); + assert_eq!(msg.get_filebytes(bob).await?, Some(215424)); assert_eq!(msg.get_height(), 1704); assert_eq!(msg.get_width(), 959); From 5e6cc88b06190c2bf87bb7e2ecca553260b4feea Mon Sep 17 00:00:00 2001 From: 72374 <250991390+72374@users.noreply.github.com> Date: Thu, 25 Jun 2026 12:29:58 +0200 Subject: [PATCH 2/3] feat: Increase `BALANCED_IMAGE_SIZE` from 1280 to 1360 --- src/blob/blob_tests.rs | 4 ++-- src/constants.rs | 2 +- src/tests/pre_messages/additional_text.rs | 2 +- src/tests/pre_messages/receiving.rs | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/blob/blob_tests.rs b/src/blob/blob_tests.rs index 0b765d72a9..fa71402c06 100644 --- a/src/blob/blob_tests.rs +++ b/src/blob/blob_tests.rs @@ -517,8 +517,8 @@ async fn test_recode_image_huge_jpg() { has_exif: true, original_width: 1920, original_height: 1080, - compressed_width: 1704, - compressed_height: 959, + compressed_width: 1808, + compressed_height: 1017, ..Default::default() } .test() diff --git a/src/constants.rs b/src/constants.rs index 9b109c0f59..1b2dc07c42 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -192,7 +192,7 @@ pub(crate) const WORSE_AVATAR_SIZE: u32 = 256; pub(crate) const WORSE_AVATAR_BYTES: usize = 20_000; // this also fits to Outlook servers don't allowing headers larger than 32k. // max. width/height of images scaled down because of being too huge -pub const BALANCED_IMAGE_SIZE: u32 = 1280; +pub const BALANCED_IMAGE_SIZE: u32 = 1360; pub const WORSE_IMAGE_SIZE: u32 = 640; /// Limit for received images size. Bigger images become `Viewtype::File` to avoid excessive memory diff --git a/src/tests/pre_messages/additional_text.rs b/src/tests/pre_messages/additional_text.rs index 40204a9c97..dec6452ae0 100644 --- a/src/tests/pre_messages/additional_text.rs +++ b/src/tests/pre_messages/additional_text.rs @@ -34,7 +34,7 @@ async fn test_additional_text_on_different_viewtypes() -> Result<()> { let (pre_message, _, _) = send_large_image_message(alice, a_group_id).await?; let msg = bob.recv_msg(&pre_message).await; assert_eq!(msg.text, "test".to_owned()); - assert_eq!(msg.get_text(), "test [Image – 210.38 KiB]".to_owned()); + assert_eq!(msg.get_text(), "test [Image – 225.81 KiB]".to_owned()); Ok(()) } diff --git a/src/tests/pre_messages/receiving.rs b/src/tests/pre_messages/receiving.rs index 2ecd4a0ad7..29ad29083c 100644 --- a/src/tests/pre_messages/receiving.rs +++ b/src/tests/pre_messages/receiving.rs @@ -402,9 +402,9 @@ async fn test_receive_pre_message_image() -> Result<()> { // test that metadata is correctly returned by methods assert_eq!(msg.get_post_message_viewtype(), Some(Viewtype::Image)); // recoded image dimensions - assert_eq!(msg.get_filebytes(bob).await?, Some(215424)); - assert_eq!(msg.get_height(), 1704); - assert_eq!(msg.get_width(), 959); + assert_eq!(msg.get_filebytes(bob).await?, Some(231228)); + assert_eq!(msg.get_height(), 1808); + assert_eq!(msg.get_width(), 1017); Ok(()) } From 5154abd567167bea56137bbd0b46d0483cc1ab02 Mon Sep 17 00:00:00 2001 From: 72374 <250991390+72374@users.noreply.github.com> Date: Sun, 12 Jul 2026 17:38:11 +0200 Subject: [PATCH 3/3] feat: Increase `WORSE_IMAGE_SIZE` from 640 to 680 --- src/blob/blob_tests.rs | 8 ++++---- src/constants.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/blob/blob_tests.rs b/src/blob/blob_tests.rs index fa71402c06..a600610945 100644 --- a/src/blob/blob_tests.rs +++ b/src/blob/blob_tests.rs @@ -406,8 +406,8 @@ async fn test_recode_image_balanced_png() { extension: "png", original_width: 1920, original_height: 1080, - compressed_width: 848, - compressed_height: 477, + compressed_width: 904, + compressed_height: 509, ..Default::default() } .test() @@ -497,8 +497,8 @@ async fn test_recode_image_rgba_png_to_jpeg() { extension: "png", original_width: 1920, original_height: 1080, - compressed_width: 848, - compressed_height: 477, + compressed_width: 904, + compressed_height: 509, ..Default::default() } .test() diff --git a/src/constants.rs b/src/constants.rs index 1b2dc07c42..d6b8251952 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -193,7 +193,7 @@ pub(crate) const WORSE_AVATAR_BYTES: usize = 20_000; // this also fits to Outloo // max. width/height of images scaled down because of being too huge pub const BALANCED_IMAGE_SIZE: u32 = 1360; -pub const WORSE_IMAGE_SIZE: u32 = 640; +pub const WORSE_IMAGE_SIZE: u32 = 680; /// Limit for received images size. Bigger images become `Viewtype::File` to avoid excessive memory /// usage by UIs.