about summary refs log tree commit diff
path: root/squash/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'squash/src/main.rs')
-rw-r--r--squash/src/main.rs88
1 files changed, 87 insertions, 1 deletions
diff --git a/squash/src/main.rs b/squash/src/main.rs
index f328e4d..b6eb699 100644
--- a/squash/src/main.rs
+++ b/squash/src/main.rs
@@ -1 +1,87 @@
-fn main() {}
+use std::{fs::File, io::BufWriter};
+
+use anyhow::bail;
+use camino::{Utf8Path, Utf8PathBuf};
+use colorsquash::Squasher;
+use png::{ColorType, Decoder, Encoder};
+
+fn main() -> Result<(), anyhow::Error> {
+	// I should use clap or at least getopt, but this is fine. It's 20LOC.
+	let usage = || -> ! {
+		println!("usage: squash <color count> <input> <output>");
+		std::process::exit(0);
+	};
+	let mut argv = std::env::args().skip(1);
+
+	let color_count: u8 = if let Some(Ok(count)) = argv.next().map(|r| r.parse()) {
+		count
+	} else {
+		usage()
+	};
+
+	let input_path: Utf8PathBuf = if let Some(path) = argv.next() {
+		path.into()
+	} else {
+		usage();
+	};
+
+	let output_path: Utf8PathBuf = if let Some(path) = argv.next() {
+		path.into()
+	} else {
+		usage();
+	};
+
+	let mut image = get_png(input_path)?;
+
+	let squasher = Squasher::new(color_count, &image.data);
+	let size = squasher.map_over(&mut image.data);
+	image.data.resize(size, 0);
+
+	// PNG Output
+	let file = File::create(output_path)?;
+	let bufw = BufWriter::new(file);
+
+	let mut enc = Encoder::new(bufw, image.width as u32, image.height as u32);
+	enc.set_color(ColorType::Indexed);
+	enc.set_depth(png::BitDepth::Eight);
+	enc.set_palette(squasher.palette_bytes());
+	enc.write_header()?.write_image_data(&image.data)?;
+
+	Ok(())
+}
+
+fn get_png<P: AsRef<Utf8Path>>(path: P) -> Result<Image, anyhow::Error> {
+	let decoder = Decoder::new(File::open(path.as_ref())?);
+	let mut reader = decoder.read_info()?;
+
+	let mut buf = vec![0; reader.output_buffer_size()];
+	let info = reader.next_frame(&mut buf)?;
+	let data = &buf[..info.buffer_size()];
+
+	println!(
+		"{}x{} * 3 = {} | out={}, bs={}",
+		info.width,
+		info.height,
+		info.width as usize * info.height as usize * 3,
+		buf.len(),
+		info.buffer_size()
+	);
+
+	let colors = info.color_type;
+	match colors {
+		ColorType::Grayscale | ColorType::GrayscaleAlpha | ColorType::Indexed | ColorType::Rgba => {
+			bail!("colortype {colors:?} not supported")
+		}
+		ColorType::Rgb => Ok(Image {
+			width: info.width as usize,
+			height: info.height as usize,
+			data: data.to_vec(),
+		}),
+	}
+}
+
+struct Image {
+	width: usize,
+	height: usize,
+	data: Vec<u8>,
+}