From 7a2dee7f16b5bf6d48e4afa0729d399ce3887af3 Mon Sep 17 00:00:00 2001 From: Florian Gebhardt Date: Thu, 21 Mar 2024 06:34:08 +0100 Subject: [PATCH] feat: optimize png encoding (#12) --- Cargo.toml | 2 +- src/image_util.rs | 36 ++++++++++++++++++++++++++++++++++-- src/main.rs | 8 +++----- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a1b1ed1..347a031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,6 @@ cast_sign_loss = "allow" [dependencies] clap = { version = "4.5", features = ["derive"] } env_logger = "0.10" -image = "0.25" +image = { version = "0.25", features = ["png"] } log = "0.4" thiserror = "1.0" diff --git a/src/image_util.rs b/src/image_util.rs index 6bafba9..60503d3 100644 --- a/src/image_util.rs +++ b/src/image_util.rs @@ -1,6 +1,8 @@ -use std::{fs, path::Path}; +use std::{fs, ops::Deref, path::Path}; -use image::RgbaImage; +use image::{ + codecs::png, EncodableLayout, ImageBuffer, ImageEncoder, Pixel, PixelWithColorType, RgbaImage, +}; #[derive(Debug, thiserror::Error)] pub enum ImgUtilError { @@ -157,3 +159,33 @@ pub fn crop_images(images: &mut Vec) -> ImgUtilResult<(i32, i32)> { Ok((shift_x, shift_y)) } + +pub trait ImageBufferExt { + fn save_optimized_png(&self, path: impl AsRef) -> ImgUtilResult<()>; +} + +impl ImageBufferExt for ImageBuffer +where + P: Pixel + PixelWithColorType, + [P::Subpixel]: EncodableLayout, + C: Deref, +{ + fn save_optimized_png(&self, path: impl AsRef) -> ImgUtilResult<()> { + let mut file = fs::File::create(path)?; + + let (width, height) = self.dimensions(); + png::PngEncoder::new_with_quality( + &mut file, + png::CompressionType::Best, + png::FilterType::default(), + ) + .write_image( + self.as_bytes(), + width, + height, +

::COLOR_TYPE, + )?; + + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index 634dcbe..768f224 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use std::{ use clap::{Args, Parser, Subcommand}; use image::{ImageBuffer, RgbaImage}; +use image_util::ImageBufferExt; #[macro_use] extern crate log; @@ -277,10 +278,7 @@ fn generate_mipmap_icon(args: &IconArgs) -> Result<(), CommandError> { image::imageops::crop_imm(&res, 0, 0, total_width, res.height()) .to_image() - .save_with_format( - output_name(&args.source, &args.output, None, "png"), - image::ImageFormat::Png, - )?; + .save_optimized_png(output_name(&args.source, &args.output, None, "png"))?; Ok(()) } @@ -401,7 +399,7 @@ fn generate_spritesheet( // save sheets for (sheet, path) in sheets { - sheet.save_with_format(path, image::ImageFormat::Png)?; + sheet.save_optimized_png(path)?; } let name = output_name(source, &args.output, None, "");