From b5a215f363be951a009e15d8e4ccb4bc670777b0 Mon Sep 17 00:00:00 2001 From: Genny Date: Mon, 20 Feb 2023 09:08:58 -0600 Subject: slugs --- Cargo.toml | 3 +- slugs/Cargo.toml | 14 +++++++++ slugs/readme.md | 9 ++++++ slugs/src/main.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 slugs/Cargo.toml create mode 100644 slugs/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index f186b67..f45abd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,5 +2,6 @@ members = [ "gifed", "gifprobe", - "gaudio" + "gaudio", + "slugs" ] \ No newline at end of file diff --git a/slugs/Cargo.toml b/slugs/Cargo.toml new file mode 100644 index 0000000..ba4dac2 --- /dev/null +++ b/slugs/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "slugs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +camino = "1.1.2" +gifed = { path = "../gifed" } +png = "0.17.7" +tepimg = { git = "https://github.com/gennyble/tep" } +thiserror = "1.0.38" +colorsquash = { path = "../../colorsquash" } \ No newline at end of file diff --git a/slugs/readme.md b/slugs/readme.md index f5dbe6b..72a47ca 100644 --- a/slugs/readme.md +++ b/slugs/readme.md @@ -22,4 +22,13 @@ Frame frame1.tep Frame frame2.tep Delay 2 Frame frame3.tep +``` + +```kdl +gif width=16 height=16 delay=4 { + palette "palette" + image "frame1.tep" + image "frame2.tep" delay=2 + image "frame3.tep" +} ``` \ No newline at end of file diff --git a/slugs/src/main.rs b/slugs/src/main.rs new file mode 100644 index 0000000..bdf936e --- /dev/null +++ b/slugs/src/main.rs @@ -0,0 +1,94 @@ +use std::fs::File; + +use camino::{Utf8Path, Utf8PathBuf}; +use colorsquash::{ColorCollector, Squasher}; +use gifed::{ + block::{extension::DisposalMethod, Palette}, + writer::{ImageBuilder, Writer}, + Color, +}; + +fn main() { + let base = Utf8PathBuf::from("/Users/gen/microglass-transfer/transcube"); + let mut collector = ColorCollector::new(); + + let mut imgs = vec![]; + for idx in 1..=120 { + let img = load_and_rgb(base.join(format!("{idx:04}.png"))); + collector.add(&img.b); + imgs.push(img); + } + + let squash: Squasher = collector.as_squasher(255); + let pal = squash.palette(); + let trans_idx = pal + .iter() + .enumerate() + .find(|(_idx, rgb)| rgb[0] == 0 && rgb[1] == 0 && rgb[2] == 0) + .unwrap() + .0; + + let mut palette = Palette::new(); + for c in pal { + palette.push(Color::new(c[0], c[1], c[2])); + } + println!("{}", palette.len()); + + let f = File::create(base.join("transcube.gif")).unwrap(); + let mut write = Writer::new(f, imgs[0].w as u16, imgs[1].h as u16, Some(palette)).unwrap(); + + for img in imgs { + let mut buf = vec![0; img.w as usize * img.h as usize]; + squash.map_unsafe(&img.b, &mut buf); + let img = ImageBuilder::new(img.w as u16, img.h as u16) + .transparent_index(Some(trans_idx as u8)) + .delay(3) + .disposal_method(DisposalMethod::RestoreBackground) + .build(buf) + .unwrap(); + + write.image(img).unwrap(); + } + + write.repeat(gifed::block::LoopCount::Forever).unwrap(); + write.done().unwrap(); +} + +pub fn load_and_rgb>(path: P) -> Img { + let decoder = png::Decoder::new(File::open(path.as_ref()).unwrap()); + let mut reader = decoder.read_info().unwrap(); + let mut b = vec![0; reader.output_buffer_size()]; + let info = reader.next_frame(&mut b).unwrap(); + + let b = (&b[..info.buffer_size()]).to_owned(); + + Img { + b: rgba_replace_a(b, (0, 0, 0), 128), + w: info.width, + h: info.height, + } +} + +pub fn rgba_replace_a(buf: Vec, repl: (u8, u8, u8), tol: u8) -> Vec { + let mut r = vec![0; (buf.len() / 4) * 3]; + + for (idx, px) in buf.chunks(4).enumerate() { + if px[3] >= tol { + r[idx * 3] = px[0]; + r[idx * 3 + 1] = px[1]; + r[idx * 3 + 2] = px[2]; + } else { + r[idx * 3] = repl.0; + r[idx * 3 + 1] = repl.1; + r[idx * 3 + 2] = repl.2; + } + } + + r +} + +pub struct Img { + b: Vec, + w: u32, + h: u32, +} -- cgit 1.4.1-3-g733a5