crop whitespace

This commit is contained in:
Reid 2023-10-12 00:36:20 -07:00
parent 0acf6bac7b
commit fcf664dc2e
Signed by: reidlab
GPG key ID: 6C9EAA3364F962C8
4 changed files with 34 additions and 6 deletions

2
Cargo.lock generated
View file

@ -192,7 +192,7 @@ dependencies = [
[[package]] [[package]]
name = "gd-icon-renderer" name = "gd-icon-renderer"
version = "1.1.0" version = "1.2.0"
dependencies = [ dependencies = [
"image", "image",
"imageproc", "imageproc",

View file

@ -1,7 +1,7 @@
[package] [package]
name = "gd-icon-renderer" name = "gd-icon-renderer"
description = "A tool to render Geometry Dash icons." description = "A tool to render Geometry Dash icons."
version = "1.1.0" version = "1.2.0"
edition = "2021" edition = "2021"
license-file = "LICENSE" license-file = "LICENSE"
repository = "https://git.reidlab.online/reidlab/gd-icon-renderer" repository = "https://git.reidlab.online/reidlab/gd-icon-renderer"

View file

@ -42,5 +42,4 @@ Provide your `GJ_GameSheet02-uhd`, `GJ_GameSheetGlow-uhd`, `Robot_AnimDesc2`, an
## Todo ## Todo
- Add examples to the repo. - Add examples to the repo.
- Trim extra alpha space on the final result.
- I think theres some weird shifting and offsets going on, please investigate 🥺. Really big on `spider_16` for some reason?? Related issue on the inspired project [here](https://github.com/oatmealine/gd-icon-renderer/issues/2). - I think theres some weird shifting and offsets going on, please investigate 🥺. Really big on `spider_16` for some reason?? Related issue on the inspired project [here](https://github.com/oatmealine/gd-icon-renderer/issues/2).

View file

@ -123,6 +123,31 @@ fn is_black(c: [f32; 3]) -> bool {
c == [0.0, 0.0, 0.0] c == [0.0, 0.0, 0.0]
} }
fn crop_whitespace(img: DynamicImage) -> DynamicImage {
let (width, height) = img.dimensions();
let mut left = width;
let mut right = 0;
let mut top = height;
let mut bottom = 0;
for x in 0..width {
for y in 0..height {
let pixel = img.get_pixel(x, y);
if pixel[3] != 0 {
left = left.min(x);
right = right.max(x);
top = top.min(y);
bottom = bottom.max(y);
}
}
}
let cropped_image = img.clone().crop(left, top, right - left, bottom - top);
return cropped_image
}
/// Renders out a non-robot/spider icon. You may be looking for `render_icon`. /// Renders out a non-robot/spider icon. You may be looking for `render_icon`.
pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool, game_sheet_02: LoadedSpritesheet, game_sheet_glow: LoadedSpritesheet) -> DynamicImage { pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool, game_sheet_02: LoadedSpritesheet, game_sheet_glow: LoadedSpritesheet) -> DynamicImage {
let glow_col = if is_black(col2) { if is_black(col1) { [1.0, 1.0, 1.0] } else { col1 } } else { col2 }; let glow_col = if is_black(col2) { if is_black(col1) { [1.0, 1.0, 1.0] } else { col1 } } else { col2 };
@ -147,7 +172,7 @@ pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: boo
None None
]; ];
return render_layered( let layered_images = render_layered(
layers.iter() layers.iter()
.filter_map(|s| s.as_ref().map(|(img, _spr)| img.to_owned())) .filter_map(|s| s.as_ref().map(|(img, _spr)| img.to_owned()))
.collect(), .collect(),
@ -161,6 +186,8 @@ pub fn render_normal(basename: String, col1: [f32; 3], col2: [f32; 3], glow: boo
vec![None, None, None, None, None], vec![None, None, None, None, None],
vec![None, None, None, None, None] vec![None, None, None, None, None]
); );
return crop_whitespace(layered_images);
} }
fn flip(scale: (f32, f32), flipped: (bool, bool)) -> (f32, f32) { fn flip(scale: (f32, f32), flipped: (bool, bool)) -> (f32, f32) {
@ -221,13 +248,15 @@ pub fn render_zany(basename: String, col1: [f32; 3], col2: [f32; 3], glow: bool,
.filter_map(|(opt_sprite, pos, scale, rot, glow, color)| opt_sprite.clone().map(|sprite| ((sprite.0, sprite.1), *pos, *scale, *rot, *glow, *color))) .filter_map(|(opt_sprite, pos, scale, rot, glow, color)| opt_sprite.clone().map(|sprite| ((sprite.0, sprite.1), *pos, *scale, *rot, *glow, *color)))
.collect::<Vec<((DynamicImage, Sprite), (f32, f32), (f32, f32), f64, bool, Option<[f32; 3]>)>>(); .collect::<Vec<((DynamicImage, Sprite), (f32, f32), (f32, f32), f64, bool, Option<[f32; 3]>)>>();
return render_layered( let layered_images = render_layered(
layers_r.iter().map(|t| t.0.0.clone()).collect(), layers_r.iter().map(|t| t.0.0.clone()).collect(),
layers_r.iter().map(|t| Some((t.0.1.offset.0 + t.1.0 * 4.0, t.0.1.offset.1 * -1.0 + t.1.1 * -4.0))).collect(), layers_r.iter().map(|t| Some((t.0.1.offset.0 + t.1.0 * 4.0, t.0.1.offset.1 * -1.0 + t.1.1 * -4.0))).collect(),
layers_r.iter().map(|t| t.5).collect(), layers_r.iter().map(|t| t.5).collect(),
layers_r.iter().map(|t| Some(t.2)).collect(), layers_r.iter().map(|t| Some(t.2)).collect(),
layers_r.iter().map(|t| Some(t.3 as f32)).collect() layers_r.iter().map(|t| Some(t.3 as f32)).collect()
) );
return crop_whitespace(layered_images);
} }
/// The main entrypoint for icon rendering; this should be all you need to render out an icon. /// The main entrypoint for icon rendering; this should be all you need to render out an icon.