diff --git a/src/palette.rs b/src/palette.rs index 5ff1a7c..428f443 100644 --- a/src/palette.rs +++ b/src/palette.rs @@ -2,6 +2,8 @@ use std::fs::read_to_string; use std::path::PathBuf; use serde_derive::{Serialize, Deserialize}; use crate::colour::Colour; +use image::{GenericImageView, Rgba, DynamicImage, Rgb, GenericImage}; +use image::io::Reader as ImageReader; /// todo enumerate original format #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] @@ -153,6 +155,39 @@ impl Palette { format!("{}\r\n", colours.join("\r\n")) } + + pub fn from_png(path: PathBuf) -> Self { + let name = path.file_stem().unwrap().to_str().unwrap().into(); + let image = ImageReader::open(path).unwrap().decode().unwrap(); + + let mut colours: Vec> = Vec::new(); + + for (_x, _y, pixel) in image.pixels() { + if !colours.contains(&pixel) { + colours.push(pixel); + } + } + + let colours = colours.iter().map(|colour| + Colour { red: colour.0[0], green: colour.0[1], blue: colour.0[2] } + ).collect(); + + // todo preserve original image? + Self { name, colours } + } + + pub fn to_png(&self) -> DynamicImage { + let mut image = DynamicImage::new_rgb8( + self.colours.len() as u32, 1 as u32 + ); + + for (x, colour) in self.colours.iter().enumerate() { + let pixel = Rgba::from([colour.red, colour.green, colour.blue, 255]); + image.put_pixel(x as u32, 0, pixel); + } + + image + } } /// for toml purposes @@ -261,6 +296,24 @@ mod test { assert_eq!(output, expected); } + #[test] + fn palette_from_png() { + let path = PathBuf::from("src/test-resources/basic/palettes/soup11.png"); + let output = Palette::from_png(path); + let expected = crate::mock::palette::soup11(); + assert_eq!(output, expected); + } + + #[test] + fn palette_to_png() { + use image::io::Reader as ImageReader; + + let output = crate::mock::palette::soup11().to_png(); + let path = PathBuf::from("src/test-resources/basic/palettes/soup11.png"); + let expected = ImageReader::open(path).unwrap().decode().unwrap(); + assert_eq!(output, expected); + } + #[test] fn palette_from_toml() { let output = Palette::from( diff --git a/src/test-resources/basic/palettes/soup11.png b/src/test-resources/basic/palettes/soup11.png new file mode 100644 index 0000000..268df16 Binary files /dev/null and b/src/test-resources/basic/palettes/soup11.png differ