diff --git a/packages/cli/src/opt/image.rs b/packages/cli/src/opt/image.rs index 1d6044811e..13a6983aeb 100644 --- a/packages/cli/src/opt/image.rs +++ b/packages/cli/src/opt/image.rs @@ -15,8 +15,24 @@ pub(crate) fn process_image( .decode(); if let Ok(image) = &mut image { - if let ImageSize::Manual { width, height } = image_options.size() { - *image = image.resize_exact(width, height, image::imageops::FilterType::Lanczos3); + match image_options.size() { + ImageSize::Manual { width, height } => { + *image = + image.resize_exact(*width, *height, image::imageops::FilterType::Lanczos3); + } + ImageSize::WidthOnly { width } => { + let ratio = image.height() as f64 / image.width() as f64; + let height = (*width as f64 * ratio).round() as u32; + *image = + image.resize_exact(*width, height, image::imageops::FilterType::Lanczos3); + } + ImageSize::HeightOnly { height } => { + let ratio = image.width() as f64 / image.height() as f64; + let width = (*height as f64 * ratio).round() as u32; + *image = + image.resize_exact(width, *height, image::imageops::FilterType::Lanczos3); + } + ImageSize::Automatic => {} } } diff --git a/packages/manganis/manganis-core/src/images.rs b/packages/manganis/manganis-core/src/images.rs index f3a4f00a36..d85c721567 100644 --- a/packages/manganis/manganis-core/src/images.rs +++ b/packages/manganis/manganis-core/src/images.rs @@ -51,6 +51,16 @@ pub enum ImageSize { /// The height of the image in pixels height: u32, }, + /// Only the width is specified; the height will be derived from the image's aspect ratio + WidthOnly { + /// The width of the image in pixels + width: u32, + }, + /// Only the height is specified; the width will be derived from the image's aspect ratio + HeightOnly { + /// The height of the image in pixels + height: u32, + }, /// The size will be automatically determined from the image source Automatic, } @@ -225,6 +235,36 @@ impl AssetOptionsBuilder { self } + /// Sets the width of the image and derives the height from the aspect ratio + /// + /// This is useful when you want to resize an image to a specific width but maintain + /// its original aspect ratio. The height will be computed at build time from the + /// actual image dimensions. + /// + /// ```rust + /// # use manganis::{asset, Asset, AssetOptions}; + /// const _: Asset = asset!("/assets/image.png", AssetOptions::image().with_width(52)); + /// ``` + pub const fn with_width(mut self, width: u32) -> Self { + self.variant.size = ImageSize::WidthOnly { width }; + self + } + + /// Sets the height of the image and derives the width from the aspect ratio + /// + /// This is useful when you want to resize an image to a specific height but maintain + /// its original aspect ratio. The width will be computed at build time from the + /// actual image dimensions. + /// + /// ```rust + /// # use manganis::{asset, Asset, AssetOptions}; + /// const _: Asset = asset!("/assets/image.png", AssetOptions::image().with_height(52)); + /// ``` + pub const fn with_height(mut self, height: u32) -> Self { + self.variant.size = ImageSize::HeightOnly { height }; + self + } + /// Convert the options into options for a generic asset pub const fn into_asset_options(self) -> AssetOptions { AssetOptions {