mirror of
https://github.com/chatmail/core.git
synced 2026-05-03 05:16:28 +03:00
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.
This commit is contained in:
14
src/blob.rs
14
src/blob.rs
@@ -416,6 +416,17 @@ impl<'a> BlobObject<'a> {
|
|||||||
// also `Viewtype::Gif` (maybe renamed to `Animation`) should be used for animated
|
// also `Viewtype::Gif` (maybe renamed to `Animation`) should be used for animated
|
||||||
// images.
|
// images.
|
||||||
let do_scale = exceeds_max_bytes
|
let do_scale = exceeds_max_bytes
|
||||||
|
// Don't recode huge JPEGs w/o resizing:
|
||||||
|
// - It may be huge because of high JPEG quality, but we don't know that.
|
||||||
|
// - We don't want extra CPU work for most photos.
|
||||||
|
&& (fmt == ImageFormat::Jpeg
|
||||||
|
|| encoded_img_exceeds_bytes(
|
||||||
|
context,
|
||||||
|
&img,
|
||||||
|
ofmt.clone(),
|
||||||
|
max_bytes,
|
||||||
|
&mut encoded,
|
||||||
|
)?)
|
||||||
|| is_avatar
|
|| is_avatar
|
||||||
&& (exceeds_wh
|
&& (exceeds_wh
|
||||||
|| exif.is_some() && {
|
|| exif.is_some() && {
|
||||||
@@ -477,8 +488,7 @@ impl<'a> BlobObject<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !encoded.is_empty() || exif.is_some() {
|
||||||
if do_scale || exif.is_some() {
|
|
||||||
// The file format is JPEG/PNG now, we may have to change the file extension
|
// The file format is JPEG/PNG now, we may have to change the file extension
|
||||||
if !matches!(fmt, ImageFormat::Jpeg)
|
if !matches!(fmt, ImageFormat::Jpeg)
|
||||||
&& matches!(ofmt, ImageOutputFormat::Jpeg { .. })
|
&& matches!(ofmt, ImageOutputFormat::Jpeg { .. })
|
||||||
|
|||||||
@@ -462,6 +462,26 @@ async fn test_recode_image_balanced_png() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
async fn test_recode_image_balanced_png_huge() {
|
||||||
|
let bytes = include_bytes!("../../test-data/image/screenshot-huge.png");
|
||||||
|
|
||||||
|
SendImageCheckMediaquality {
|
||||||
|
viewtype: Viewtype::Image,
|
||||||
|
media_quality_config: "0",
|
||||||
|
bytes,
|
||||||
|
extension: "jpg",
|
||||||
|
original_width: 1618,
|
||||||
|
original_height: 949,
|
||||||
|
compressed_width: 1618,
|
||||||
|
compressed_height: 949,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.test()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_sticker_with_exif() {
|
async fn test_sticker_with_exif() {
|
||||||
let bytes = include_bytes!("../../test-data/image/logo-exif.png");
|
let bytes = include_bytes!("../../test-data/image/logo-exif.png");
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ async fn test_additional_text_on_different_viewtypes() -> Result<()> {
|
|||||||
let (pre_message, _, _) = send_large_image_message(alice, a_group_id).await?;
|
let (pre_message, _, _) = send_large_image_message(alice, a_group_id).await?;
|
||||||
let msg = bob.recv_msg(&pre_message).await;
|
let msg = bob.recv_msg(&pre_message).await;
|
||||||
assert_eq!(msg.text, "test".to_owned());
|
assert_eq!(msg.text, "test".to_owned());
|
||||||
assert_eq!(msg.get_text(), "test [Image – 146.12 KiB]".to_owned());
|
assert!(msg.get_text().starts_with("test [Image – "));
|
||||||
|
assert!(msg.get_text().ends_with(" KiB]"));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::EventType;
|
|||||||
use crate::chat;
|
use crate::chat;
|
||||||
use crate::chat::send_msg;
|
use crate::chat::send_msg;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::constants;
|
||||||
use crate::contact;
|
use crate::contact;
|
||||||
use crate::download::{DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD, PostMsgMetadata};
|
use crate::download::{DownloadState, PRE_MSG_ATTACHMENT_SIZE_THRESHOLD, PostMsgMetadata};
|
||||||
use crate::message::{Message, MessageState, Viewtype, delete_msgs, markseen_msgs};
|
use crate::message::{Message, MessageState, Viewtype, delete_msgs, markseen_msgs};
|
||||||
@@ -402,9 +403,11 @@ async fn test_receive_pre_message_image() -> Result<()> {
|
|||||||
// test that metadata is correctly returned by methods
|
// test that metadata is correctly returned by methods
|
||||||
assert_eq!(msg.get_post_message_viewtype(), Some(Viewtype::Image));
|
assert_eq!(msg.get_post_message_viewtype(), Some(Viewtype::Image));
|
||||||
// recoded image dimensions
|
// recoded image dimensions
|
||||||
assert_eq!(msg.get_filebytes(bob).await?, Some(149632));
|
let n_bytes: usize = msg.get_filebytes(bob).await?.unwrap().try_into().unwrap();
|
||||||
assert_eq!(msg.get_height(), 1280);
|
assert!(100_000 < n_bytes);
|
||||||
assert_eq!(msg.get_width(), 720);
|
assert!(n_bytes <= constants::BALANCED_IMAGE_BYTES);
|
||||||
|
assert_eq!(msg.get_height(), 1920);
|
||||||
|
assert_eq!(msg.get_width(), 1080);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
test-data/image/screenshot-huge.png
Normal file
BIN
test-data/image/screenshot-huge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 792 KiB |
Reference in New Issue
Block a user