Skip to content

Commit f48792b

Browse files
committed
feat: Optimize avatar size multiplier for 2 << n px avatars
Instead of 2/3 which is not optimal for 512 px avatars usually passed to Core, use the sequence 7/8, 6/8, 11/16, 10/16... to do "smaller" downscaling steps and reduce aliasing effects. Before, it was discussed that just 3/4 can be used. However: - If we repeat the downscaling step, we get `3 ** n` as a numerator and this way increase aliasing effects on each step. The same for 7/8. Better limit the numerator value. - As we do downscaling in a loop only for avatars which aren't changed frequently, let's do "smaller" steps and start from 7/8.
1 parent ef718bb commit f48792b

3 files changed

Lines changed: 26 additions & 3 deletions

File tree

src/blob.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,8 @@ impl<'a> BlobObject<'a> {
435435
});
436436

437437
if do_scale {
438+
let (mut m, mut d) = (8, 8);
439+
let wh = target_wh;
438440
loop {
439441
if mem::take(&mut add_white_bg) {
440442
self::add_white_bg(&mut img);
@@ -467,8 +469,11 @@ impl<'a> BlobObject<'a> {
467469
"Failed to scale image to below {max_bytes}B.",
468470
));
469471
}
470-
471-
target_wh = target_wh * 2 / 3;
472+
(m, d) = match m > 6 {
473+
true => (m - 1, d),
474+
false => (11, d * 2),
475+
};
476+
target_wh = wh * m / d;
472477
} else {
473478
info!(
474479
context,

src/blob/blob_tests.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use super::*;
44
use crate::message::{Message, Viewtype};
55
use crate::param::Param;
66
use crate::sql;
7-
use crate::test_utils::{self, AVATAR_64x64_BYTES, AVATAR_64x64_DEDUPLICATED, TestContext};
7+
use crate::test_utils::{
8+
self, AVATAR_64x64_BYTES, AVATAR_64x64_DEDUPLICATED, TestContext, TestContextManager,
9+
};
810
use crate::tools::SystemTime;
911

1012
fn check_image_size(path: impl AsRef<Path>, width: u32, height: u32) -> image::DynamicImage {
@@ -239,6 +241,22 @@ async fn test_selfavatar_in_blobdir() {
239241
);
240242
}
241243

244+
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
245+
async fn test_huge_selfavatar() -> Result<()> {
246+
let mut tcm = TestContextManager::new();
247+
let t = &tcm.unconfigured().await;
248+
let avatar_src = t.get_blobdir().join("avatar.png");
249+
let bytes = include_bytes!("../../test-data/image/noise400x400.png");
250+
251+
fs::write(&avatar_src, bytes).await?;
252+
t.set_config(Config::Selfavatar, Some(avatar_src.to_str().unwrap()))
253+
.await?;
254+
let avatar_cfg = t.get_config(Config::Selfavatar).await?.unwrap();
255+
// At 6/8 the avatar is still huge, so it's downscaled to 11/16.
256+
check_image_size(avatar_cfg, 275, 275);
257+
Ok(())
258+
}
259+
242260
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
243261
async fn test_selfavatar_copy_without_recode() {
244262
let t = TestContext::new().await;

test-data/image/noise400x400.png

470 KB
Loading

0 commit comments

Comments
 (0)