gardesk/garbg / 4fe782c

Browse files

add scale_image_fast using Triangle filter for animation frames

Authored by espadonne
SHA
4fe782c8ca2c6344ac7843cd87e1e38feda760f1
Parents
8d66b98
Tree
edffbe3

2 changed files

StatusFile+-
M garbg/src/media/mod.rs 1 1
M garbg/src/media/scaler.rs 33 13
garbg/src/media/mod.rsmodified
@@ -13,7 +13,7 @@ mod frame_buffer;
1313
 mod video;
1414
 
1515
 pub use loader::ImageLoader;
16
-pub use scaler::scale_image;
16
+pub use scaler::{scale_image, scale_image_fast};
1717
 pub use gif::{AnimatedGif, AnimationFrame, is_animated_gif};
1818
 pub use webp::{AnimatedWebP, is_animated_webp, is_animated_webp_bytes};
1919
 pub use apng::{AnimatedPng, is_animated_png, is_animated_png_bytes};
garbg/src/media/scaler.rsmodified
@@ -4,24 +4,44 @@ use image::{imageops::FilterType, RgbaImage};
44
 
55
 use crate::config::ScaleMode;
66
 
7
-/// Scale an image according to the specified mode
7
+/// Scale an image according to the specified mode (high quality, Lanczos3)
88
 pub fn scale_image(
99
     image: &RgbaImage,
1010
     target_width: u32,
1111
     target_height: u32,
1212
     mode: ScaleMode,
13
+) -> RgbaImage {
14
+    scale_image_inner(image, target_width, target_height, mode, FilterType::Lanczos3)
15
+}
16
+
17
+/// Scale an image using a fast filter (Triangle) — suited for animation frames
18
+pub fn scale_image_fast(
19
+    image: &RgbaImage,
20
+    target_width: u32,
21
+    target_height: u32,
22
+    mode: ScaleMode,
23
+) -> RgbaImage {
24
+    scale_image_inner(image, target_width, target_height, mode, FilterType::Triangle)
25
+}
26
+
27
+fn scale_image_inner(
28
+    image: &RgbaImage,
29
+    target_width: u32,
30
+    target_height: u32,
31
+    mode: ScaleMode,
32
+    filter: FilterType,
1333
 ) -> RgbaImage {
1434
     match mode {
15
-        ScaleMode::Fill => scale_fill(image, target_width, target_height),
16
-        ScaleMode::Fit => scale_fit(image, target_width, target_height),
17
-        ScaleMode::Stretch => scale_stretch(image, target_width, target_height),
35
+        ScaleMode::Fill => scale_fill(image, target_width, target_height, filter),
36
+        ScaleMode::Fit => scale_fit(image, target_width, target_height, filter),
37
+        ScaleMode::Stretch => scale_stretch(image, target_width, target_height, filter),
1838
         ScaleMode::Center => scale_center(image, target_width, target_height),
1939
         ScaleMode::Tile => scale_tile(image, target_width, target_height),
2040
     }
2141
 }
2242
 
2343
 /// Fill: Scale to cover entire area, crop excess
24
-fn scale_fill(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaImage {
44
+fn scale_fill(image: &RgbaImage, target_width: u32, target_height: u32, filter: FilterType) -> RgbaImage {
2545
     let (src_width, src_height) = image.dimensions();
2646
 
2747
     // Calculate scale factor to cover the entire target
@@ -33,7 +53,7 @@ fn scale_fill(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaI
3353
     let scaled_height = (src_height as f64 * scale).round() as u32;
3454
 
3555
     // Scale image
36
-    let scaled = image::imageops::resize(image, scaled_width, scaled_height, FilterType::Lanczos3);
56
+    let scaled = image::imageops::resize(image, scaled_width, scaled_height, filter);
3757
 
3858
     // Crop to target size (center crop)
3959
     let crop_x = (scaled_width.saturating_sub(target_width)) / 2;
@@ -43,7 +63,7 @@ fn scale_fill(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaI
4363
 }
4464
 
4565
 /// Fit: Scale to fit within area, letterbox if needed
46
-fn scale_fit(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaImage {
66
+fn scale_fit(image: &RgbaImage, target_width: u32, target_height: u32, filter: FilterType) -> RgbaImage {
4767
     let (src_width, src_height) = image.dimensions();
4868
 
4969
     // Calculate scale factor to fit within target
@@ -55,7 +75,7 @@ fn scale_fit(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaIm
5575
     let scaled_height = (src_height as f64 * scale).round() as u32;
5676
 
5777
     // Scale image
58
-    let scaled = image::imageops::resize(image, scaled_width, scaled_height, FilterType::Lanczos3);
78
+    let scaled = image::imageops::resize(image, scaled_width, scaled_height, filter);
5979
 
6080
     // Create output with black background
6181
     let mut output = RgbaImage::from_pixel(target_width, target_height, image::Rgba([0, 0, 0, 255]));
@@ -70,8 +90,8 @@ fn scale_fit(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaIm
7090
 }
7191
 
7292
 /// Stretch: Scale to exact target size, ignoring aspect ratio
73
-fn scale_stretch(image: &RgbaImage, target_width: u32, target_height: u32) -> RgbaImage {
74
-    image::imageops::resize(image, target_width, target_height, FilterType::Lanczos3)
93
+fn scale_stretch(image: &RgbaImage, target_width: u32, target_height: u32, filter: FilterType) -> RgbaImage {
94
+    image::imageops::resize(image, target_width, target_height, filter)
7595
 }
7696
 
7797
 /// Center: Display at original size, centered
@@ -136,21 +156,21 @@ mod tests {
136156
     #[test]
137157
     fn test_scale_stretch() {
138158
         let img = test_image(100, 100);
139
-        let scaled = scale_stretch(&img, 200, 150);
159
+        let scaled = scale_stretch(&img, 200, 150, FilterType::Lanczos3);
140160
         assert_eq!(scaled.dimensions(), (200, 150));
141161
     }
142162
 
143163
     #[test]
144164
     fn test_scale_fill() {
145165
         let img = test_image(100, 100);
146
-        let scaled = scale_fill(&img, 200, 150);
166
+        let scaled = scale_fill(&img, 200, 150, FilterType::Lanczos3);
147167
         assert_eq!(scaled.dimensions(), (200, 150));
148168
     }
149169
 
150170
     #[test]
151171
     fn test_scale_fit() {
152172
         let img = test_image(100, 100);
153
-        let scaled = scale_fit(&img, 200, 150);
173
+        let scaled = scale_fit(&img, 200, 150, FilterType::Lanczos3);
154174
         assert_eq!(scaled.dimensions(), (200, 150));
155175
     }
156176