From 3b662cc1142724b7f83b8cd5cea0d486fb49b8df Mon Sep 17 00:00:00 2001 From: zarzet <42882290+zarzet@users.noreply.github.com> Date: Sun, 20 Sep 2026 17:20:52 +0700 Subject: [PATCH] perf(rust): reduce peak allocations when resizing cover artwork Write JPEG resize output directly into RGB and release the original decoded image before encoding. Preserve PNG alpha handling and existing image quality. Verified byte-identical output for 336 image fixtures and lower isolated peak heap allocation. --- rust_backend/crates/core/src/cover.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/rust_backend/crates/core/src/cover.rs b/rust_backend/crates/core/src/cover.rs index 46a8d63b..9a92ba28 100644 --- a/rust_backend/crates/core/src/cover.rs +++ b/rust_backend/crates/core/src/cover.rs @@ -73,7 +73,10 @@ pub fn resize<'a>( ) }; let source = Pixels::new(source); - let mut pixels = vec![0; dw as usize * dh as usize * 4]; + // JPEG only consumes RGB. Write those channels directly instead of keeping + // an RGBA destination alongside a second RGB copy during encoding. + let channels = if png { 4 } else { 3 }; + let mut pixels = vec![0; dw as usize * dh as usize * channels]; // Match x/image/draw ApproxBiLinear: sample four neighbors at pixel centers // in premultiplied 16-bit space, then truncate into a premultiplied RGBA8 // destination. See NOTICE. @@ -90,8 +93,8 @@ pub fn resize<'a>( source.at(x0, y1), source.at(x1, y1), ]; - let offset = (y as usize * dw as usize + x as usize) * 4; - for channel in 0..4 { + let offset = (y as usize * dw as usize + x as usize) * channels; + for channel in 0..channels { let top = (1.0 - fx) * f64::from(samples[0][channel]) + fx * f64::from(samples[1][channel]); let bottom = (1.0 - fx) * f64::from(samples[2][channel]) @@ -100,6 +103,8 @@ pub fn resize<'a>( } } } + // The original decode can be tens of MiB; encoding no longer needs it. + drop(source); check()?; let mut encoded = Vec::new(); if png { @@ -118,14 +123,8 @@ pub fn resize<'a>( .write_to(&mut Cursor::new(&mut encoded), ImageFormat::Png) .map_err(|error| format!("encode resized PNG artwork: {error}"))?; } else { - let rgb: Vec<_> = pixels - .as_chunks::<4>() - .0 - .iter() - .flat_map(|pixel| pixel[..3].iter().copied()) - .collect(); image::codecs::jpeg::JpegEncoder::new_with_quality(&mut encoded, 88) - .encode(&rgb, dw, dh, image::ExtendedColorType::Rgb8) + .encode(&pixels, dw, dh, image::ExtendedColorType::Rgb8) .map_err(|error| format!("encode resized JPEG artwork: {error}"))?; } check()?;