diff --git a/board-builder-gui/src/main.rs b/board-builder-gui/src/main.rs index e2c9f3b..3ee0e3a 100644 --- a/board-builder-gui/src/main.rs +++ b/board-builder-gui/src/main.rs @@ -7,7 +7,8 @@ use image::DynamicImage; use rfd::FileDialog; -use board_builder::{ Board, Node, CoordTransformer, read_board_from_file, write_board_to_file }; +use board_builder::{ Board, Node, CoordTransformer }; +use board_builder::io::{ read_board_from_file, write_board_to_file }; use std::path::Path; use std::collections::HashSet; diff --git a/src/io.rs b/src/io.rs new file mode 100644 index 0000000..90a49ff --- /dev/null +++ b/src/io.rs @@ -0,0 +1,56 @@ +use crate::Board; + +use std::io; +use std::io::{ Write, Read, Cursor }; +use std::fs::File; +use std::path::Path; + +use image::io::Reader as ImageReader; +use image::DynamicImage; + +pub fn write_board_to_file(board: &Board, image: Option<&DynamicImage>, path: &Path) -> io::Result<()> { + let file = File::create(path)?; + let mut ar = zip::ZipWriter::new(file); + let options = zip::write::FileOptions::default(); + + ar.start_file("graph.json", options)?; + ar.write_all(&serde_json::to_vec(board)?)?; + if let Some(image) = image { + ar.start_file("image.png", options)?; + let data = encode_png(image); + ar.write_all(&data)?; + ar.flush()?; + } + ar.finish()?; + Ok(()) +} + +pub fn read_board_from_file(path: &Path) -> io::Result<(Board, Option)> { + let file = File::open(path)?; + let mut ar = zip::ZipArchive::new(file)?; + + let json_file = ar.by_name("graph.json")?; + let board = serde_json::from_reader(json_file)?; + let image = ar.by_name("image.png").ok(); + if image.is_none() { + return Ok((board, None)) + } + let mut image_file = image.unwrap(); + let mut buf = Vec::new(); + image_file.read_to_end(&mut buf)?; + let image = decode_png(&buf); + Ok((board, Some(image))) +} + +pub fn encode_png(image: &DynamicImage) -> Vec { + let mut cursor = Cursor::new(Vec::new()); + image.write_to(&mut cursor, image::ImageOutputFormat::Png).unwrap(); + cursor.into_inner() +} + +pub fn decode_png(buf: &[u8]) -> DynamicImage { + let cursor = Cursor::new(buf); + let mut reader = ImageReader::new(cursor); + reader.set_format(image::ImageFormat::Png); + reader.decode().unwrap() +} diff --git a/src/lib.rs b/src/lib.rs index 742e70a..181db74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +pub mod io; + use serde::{ Serialize, Deserialize }; use std::collections::{ HashMap, HashSet }; @@ -13,6 +15,7 @@ impl Default for Config { } } } + #[derive(Serialize, Deserialize, Debug, Default, Clone)] #[serde(default)] pub struct Node { @@ -23,7 +26,6 @@ pub struct Node { pub edges: HashSet, pub labels: HashMap, } - impl Node { pub fn should_wrap_horizontal(&self, other: &Node) -> bool { let mut xs = [self.x, other.x]; @@ -120,61 +122,6 @@ fn dist_sq((x0, y0): (f32, f32), (x1, y1): (f32, f32)) -> f32 { (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) } -use std::io; -use std::io::{ Write, Read, Cursor }; -use std::fs::File; -use std::path::Path; - -use image::io::Reader as ImageReader; -use image::{ DynamicImage }; - -pub fn write_board_to_file(board: &Board, image: Option<&DynamicImage>, path: &Path) -> io::Result<()> { - let file = File::create(path)?; - let mut ar = zip::ZipWriter::new(file); - let options = zip::write::FileOptions::default(); - - ar.start_file("graph.json", options)?; - ar.write_all(&serde_json::to_vec(board)?)?; - if let Some(image) = image { - ar.start_file("image.png", options)?; - let data = encode_png(image); - ar.write_all(&data)?; - ar.flush()?; - } - ar.finish()?; - Ok(()) -} - -pub fn read_board_from_file(path: &Path) -> io::Result<(Board, Option)> { - let file = File::open(path)?; - let mut ar = zip::ZipArchive::new(file)?; - - let json_file = ar.by_name("graph.json")?; - let board = serde_json::from_reader(json_file)?; - let image = ar.by_name("image.png").ok(); - if image.is_none() { - return Ok((board, None)) - } - let mut image_file = image.unwrap(); - let mut buf = Vec::new(); - image_file.read_to_end(&mut buf)?; - let image = decode_png(&buf); - Ok((board, Some(image))) -} - -pub fn encode_png(image: &DynamicImage) -> Vec { - let mut cursor = Cursor::new(Vec::new()); - image.write_to(&mut cursor, image::ImageOutputFormat::Png).unwrap(); - cursor.into_inner() -} - -pub fn decode_png(buf: &[u8]) -> DynamicImage { - let cursor = Cursor::new(buf); - let mut reader = ImageReader::new(cursor); - reader.set_format(image::ImageFormat::Png); - reader.decode().unwrap() -} - fn lerp(v0: f32, v1: f32, t: f32) -> f32 { v0 + t * (v1 - v0) }