mindustry logic execution, map- and schematic- parsing and rendering
Diffstat (limited to 'src/utils/image.rs')
-rw-r--r--src/utils/image.rs71
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
+ }
}