mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/utils/image.rs')
| -rw-r--r-- | src/utils/image.rs | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/src/utils/image.rs b/src/utils/image.rs index de6cf6b..959b633 100644 --- a/src/utils/image.rs +++ b/src/utils/image.rs @@ -1,17 +1,39 @@ use fast_image_resize as fr; -use image::{Rgb, Rgba, RgbaImage}; +use image::{GenericImageView, Rgb, Rgba, RgbaImage}; use std::num::NonZeroU32; +use blurslice::gaussian_blur_bytes; + pub trait ImageUtils { + /// Tint this image with the color fn tint(&mut self, color: Rgb<u8>) -> &mut Self; - - fn repeat(&mut self, with: &RgbaImage) -> &mut Self; - - fn overlay(&mut self, with: &RgbaImage, x: u32, y: u32) -> &mut Self; - + /// Repeat with over self + fn repeat(&mut self, with: &Self) -> &mut Self; + /// Overlay with onto self (does not blend) + fn overlay(&mut self, with: &Self, x: u32, y: u32) -> &mut Self; + /// rotate + fn rotate(&mut self, times: u8) -> &mut Self; + /// shadow + fn shadow(&mut self) -> &mut Self; + /// silhouette + fn silhouette(&mut self) -> &mut Self; + /// scale a image + /// + /// SAFETY: to and width and height cannot be 0. unsafe fn scale(self, to: u32) -> Self; } impl ImageUtils for RgbaImage { + fn rotate(&mut self, times: u8) -> &mut Self { + use image::imageops::{rotate180, rotate270, rotate90}; + match times { + 2 => *self = rotate180(self), + 1 => *self = rotate90(self), + 3 => *self = rotate270(self), + _ => {} + } + self + } + fn tint(&mut self, color: Rgb<u8>) -> &mut Self { let [tr, tg, tb] = [ color[0] as f32 / 255.0, @@ -39,7 +61,7 @@ impl ImageUtils for RgbaImage { for j in 0..with.height() { for i in 0..with.width() { let get = with.get_pixel(i, j); - if get[3] > 5 { + if get[3] > 128 { self.put_pixel(i + x, j + y, *get); } } @@ -47,9 +69,6 @@ impl ImageUtils for RgbaImage { self } - /// scales a image - /// - /// SAFETY: to and width and height cannot be 0. unsafe fn scale(self, to: u32) -> Self { debug_assert_ne!(to, 0); debug_assert_ne!(self.width(), 0); @@ -68,4 +87,36 @@ impl ImageUtils for RgbaImage { .unwrap(); RgbaImage::from_raw(to.get(), to.get(), dst.into_vec()).unwrap() } + + fn silhouette(&mut self) -> &mut Self { + for pixel in self.pixels_mut() { + if pixel[3] < 128 { + pixel[2] /= 10; + pixel[1] /= 10; + pixel[0] /= 10; + } + } + self + } + + fn shadow(&mut self) -> &mut Self { + let mut shadow = self.clone(); + shadow.silhouette(); + let samples = shadow.as_flat_samples_mut(); + gaussian_blur_bytes::<4>(samples.samples, self.width() as usize, self.height() as usize, 9.0).unwrap(); + for x in 0..shadow.width() { + for y in 0..shadow.height() { + let Rgba([r, g, b, a]) = self.get_pixel_mut(x, y); + if *a == 0 { + // SAFETY: yes + let p = unsafe { shadow.unsafe_get_pixel(x, y) }; + *r = p[0]; + *g = p[0]; + *b = p[0]; + *a = p[1]; + } + } + } + self + } } |