From 77861113dd448ec873adac46cd7cf2cee56bb51c Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Fri, 14 Jun 2024 21:18:31 +0200 Subject: [PATCH] Increase PNG compression level (#817) This commit increases the compression level for when we encode PNG images. We do this for Llanfair files (Gered and original) were the images are uncompressed and also for when we encounter BMP images in LiveSplit files or we scale down images. Increasing the compression level doesn't seem to really take much more time, but has a decent impact on the size of the images. --- src/run/parser/llanfair.rs | 4 ++-- src/run/parser/llanfair_gered.rs | 4 ++-- src/settings/image/shrinking.rs | 7 +++++-- src/util/image.rs | 23 +++++++++++++++-------- src/util/mod.rs | 2 +- tests/rendering.rs | 6 +++--- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/run/parser/llanfair.rs b/src/run/parser/llanfair.rs index a6a268cf..255685ab 100644 --- a/src/run/parser/llanfair.rs +++ b/src/run/parser/llanfair.rs @@ -9,7 +9,7 @@ use crate::{ }; use core::{result::Result as StdResult, str}; #[cfg(feature = "std")] -use image::{codecs::png, ExtendedColorType, ImageBuffer, ImageEncoder, Rgba}; +use image::{ExtendedColorType, ImageBuffer, ImageEncoder, Rgba}; use snafu::{OptionExt, ResultExt}; /// The Error type for splits files that couldn't be parsed by the Llanfair @@ -187,7 +187,7 @@ pub fn parse(source: &[u8]) -> Result { #[cfg(feature = "std")] if let Some(image) = ImageBuffer::, _>::from_raw(width, height, _image_data) { buf.clear(); - if png::PngEncoder::new(&mut buf) + if crate::util::image::create_reencoder(&mut buf) .write_image(image.as_ref(), width, height, ExtendedColorType::Rgba8) .is_ok() { diff --git a/src/run/parser/llanfair_gered.rs b/src/run/parser/llanfair_gered.rs index c11f881d..4780ed64 100644 --- a/src/run/parser/llanfair_gered.rs +++ b/src/run/parser/llanfair_gered.rs @@ -18,7 +18,7 @@ use crate::{ RealTime, Run, Segment, Time, TimeSpan, }; #[cfg(feature = "std")] -use image::{codecs::png, ExtendedColorType, ImageEncoder}; +use image::{ExtendedColorType, ImageEncoder}; #[cfg(feature = "std")] use snafu::OptionExt; @@ -123,7 +123,7 @@ where })?; png_buf.clear(); - png::PngEncoder::new(&mut *png_buf) + crate::util::image::create_reencoder(&mut *png_buf) .write_image(image, width, height, ExtendedColorType::Rgba8) .map_err(|_| Error::Image)?; diff --git a/src/settings/image/shrinking.rs b/src/settings/image/shrinking.rs index a64ec678..b255188f 100644 --- a/src/settings/image/shrinking.rs +++ b/src/settings/image/shrinking.rs @@ -1,7 +1,7 @@ use alloc::borrow::Cow; use image::{guess_format, load_from_memory_with_format, ImageEncoder, ImageFormat}; -use crate::util::image::get_dimensions; +use crate::util::image::{create_reencoder, get_dimensions}; fn shrink_inner(data: &[u8], max_dim: u32) -> Option> { let format = guess_format(data).ok()?; @@ -27,8 +27,10 @@ fn shrink_inner(data: &[u8], max_dim: u32) -> Option> { if is_too_large { image = image.thumbnail(max_dim, max_dim); } + let mut data = Vec::new(); - image::codecs::png::PngEncoder::new(&mut data) + + create_reencoder(&mut data) .write_image( image.as_bytes(), image.width(), @@ -36,6 +38,7 @@ fn shrink_inner(data: &[u8], max_dim: u32) -> Option> { image.color().into(), ) .ok()?; + data.into() } else { data.into() diff --git a/src/util/image.rs b/src/util/image.rs index 0656f5cb..ff207288 100644 --- a/src/util/image.rs +++ b/src/util/image.rs @@ -1,14 +1,21 @@ -use std::io::Cursor; +use image::codecs::png::{CompressionType, FilterType, PngEncoder}; -use bytemuck_derive::{Pod, Zeroable}; -use image::{ - codecs::{bmp, farbfeld, hdr, ico, jpeg, pnm, tga, tiff, webp}, - ImageDecoder, ImageFormat, -}; +pub fn create_reencoder(target_buf: &mut Vec) -> PngEncoder<&mut Vec> { + PngEncoder::new_with_quality(target_buf, CompressionType::Best, FilterType::default()) +} + +#[cfg(any(feature = "image-shrinking", feature = "svg-rendering"))] +pub fn get_dimensions(format: image::ImageFormat, data: &[u8]) -> Option<(u32, u32)> { + use std::io::Cursor; + + use bytemuck_derive::{Pod, Zeroable}; + use image::{ + codecs::{bmp, farbfeld, hdr, ico, jpeg, pnm, tga, tiff, webp}, + ImageDecoder, ImageFormat, + }; -use crate::util::byte_parsing::{big_endian::U32, strip_pod}; + use crate::util::byte_parsing::{big_endian::U32, strip_pod}; -pub fn get_dimensions(format: ImageFormat, data: &[u8]) -> Option<(u32, u32)> { Some(match format { ImageFormat::Png => { // We encounter a lot of PNG images in splits files and decoding diff --git a/src/util/mod.rs b/src/util/mod.rs index 93d67fb7..1f7c4301 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -5,7 +5,7 @@ pub(crate) mod ascii_set; pub(crate) mod byte_parsing; pub(crate) mod caseless; mod clear_vec; -#[cfg(any(feature = "image-shrinking", feature = "svg-rendering"))] +#[cfg(feature = "std")] pub(crate) mod image; pub(crate) mod not_nan; pub mod ordered_map; diff --git a/tests/rendering.rs b/tests/rendering.rs index 77cac772..4400d82e 100644 --- a/tests/rendering.rs +++ b/tests/rendering.rs @@ -254,7 +254,7 @@ fn all_components() { &image_cache, [300, 800], "7e7aa83a3b80e1da", - "39b5d1923053c5d9", + "fa3c0357219389d8", "all_components", ); @@ -263,7 +263,7 @@ fn all_components() { &image_cache, [150, 800], "97afa51bfd8a8597", - "82b26ae781d58b78", + "eda169eec3995eeb", "all_components_thin", ); } @@ -308,7 +308,7 @@ fn dark_layout() { &layout.state(&mut image_cache, &timer.snapshot()), &image_cache, "a47c590792c1bab5", - "3f8dfb2da2d43648", + "91a89f563eb4f43d", "dark_layout", ); }