diff --git a/src/blob.rs b/src/blob.rs index bd426a35c0..9411b2e198 100644 --- a/src/blob.rs +++ b/src/blob.rs @@ -388,14 +388,9 @@ impl<'a> BlobObject<'a> { _ => img, }; - // max_wh is the maximum image width and height, i.e. the resolution-limit. - // target_wh target-resolution for resizing the image. + // max_wh is the maximum image width and height, i.e. the resolution-limit, + // as set by the media-quality-setting. let exceeds_wh = img.width() > max_wh || img.height() > max_wh; - let mut target_wh = if exceeds_wh { - max_wh - } else { - max(img.width(), img.height()) - }; let exceeds_max_bytes = nr_bytes > max_bytes as u64; let jpeg_quality = 75; @@ -434,6 +429,27 @@ impl<'a> BlobObject<'a> { }); if do_scale { + let resolution_of_longest_side_of_image = max(img.width(), img.height()); + let square_root_of_number_of_pixels_in_image = + f64::from(img.width() * img.height()).sqrt(); + + // target_wh will be used as the target-resolution for resizing the image, + // so that the longest sides of the image match the target-resolution, + // without changing the aspect-ratio. + 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. + (f64::from(resolution_of_longest_side_of_image) + * (f64::from(max_wh) / square_root_of_number_of_pixels_in_image)) + as u32 + } else { + max_wh + }; + + if target_wh > resolution_of_longest_side_of_image { + target_wh = resolution_of_longest_side_of_image + }; + loop { if mem::take(&mut add_white_bg) { self::add_white_bg(&mut img); @@ -467,7 +483,8 @@ impl<'a> BlobObject<'a> { )); } - target_wh = target_wh * 2 / 3; + // Note: This is only done for avatar-images. + target_wh = target_wh * 7 / 8; } else { info!( context, diff --git a/src/blob/blob_tests.rs b/src/blob/blob_tests.rs index ed5a2b0017..9ce88fdd1f 100644 --- a/src/blob/blob_tests.rs +++ b/src/blob/blob_tests.rs @@ -384,8 +384,8 @@ async fn test_recode_image_balanced_png() { extension: "png", original_width: 1920, original_height: 1080, - compressed_width: constants::WORSE_IMAGE_SIZE, - compressed_height: constants::WORSE_IMAGE_SIZE * 1080 / 1920, + compressed_width: 853, + compressed_height: 480, ..Default::default() } .test() @@ -475,8 +475,8 @@ async fn test_recode_image_rgba_png_to_jpeg() { extension: "png", original_width: 1920, original_height: 1080, - compressed_width: constants::WORSE_IMAGE_SIZE, - compressed_height: constants::WORSE_IMAGE_SIZE * 1080 / 1920, + compressed_width: 853, + compressed_height: 480, ..Default::default() } .test() @@ -495,8 +495,8 @@ async fn test_recode_image_huge_jpg() { has_exif: true, original_width: 1920, original_height: 1080, - compressed_width: constants::BALANCED_IMAGE_SIZE, - compressed_height: constants::BALANCED_IMAGE_SIZE * 1080 / 1920, + compressed_width: 1706, + compressed_height: 960, ..Default::default() } .test() diff --git a/src/constants.rs b/src/constants.rs index 28eb4c0fed..6850cf243f 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -199,7 +199,7 @@ pub const WORSE_IMAGE_BYTES: usize = 130_000; // max. width/height and bytes of an avatar pub(crate) const BALANCED_AVATAR_SIZE: u32 = 512; pub(crate) const BALANCED_AVATAR_BYTES: usize = 60_000; -pub(crate) const WORSE_AVATAR_SIZE: u32 = 128; +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 diff --git a/src/tests/pre_messages/additional_text.rs b/src/tests/pre_messages/additional_text.rs index 0af33ec8c6..75e97e9c6d 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 – 146.12 KiB]".to_owned()); + assert_eq!(msg.get_text(), "test [Image – 227.50 KiB]".to_owned()); Ok(()) } diff --git a/src/tests/pre_messages/receiving.rs b/src/tests/pre_messages/receiving.rs index 0657f523fd..fbbd1c47bd 100644 --- a/src/tests/pre_messages/receiving.rs +++ b/src/tests/pre_messages/receiving.rs @@ -323,9 +323,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(149632)); - assert_eq!(msg.get_height(), 1280); - assert_eq!(msg.get_width(), 720); + assert_eq!(msg.get_filebytes(bob).await?, Some(232957)); + assert_eq!(msg.get_height(), 1706); + assert_eq!(msg.get_width(), 960); Ok(()) }