diff options
-rw-r--r-- | src/bin/tile-editor.rs | 84 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/tile.rs | 76 |
3 files changed, 83 insertions, 78 deletions
diff --git a/src/bin/tile-editor.rs b/src/bin/tile-editor.rs index 1e361fb..07b9640 100644 --- a/src/bin/tile-editor.rs +++ b/src/bin/tile-editor.rs @@ -1,79 +1,4 @@ -use std::io::{BufRead as _, Read as _, Seek as _, Write as _}; - -use image::Pixel as _; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -struct Tile([u8; 32]); - -impl Tile { - fn load_from_file<F: AsRef<std::path::Path>>( - filename: F, - idx: usize, - ) -> Self { - let mut fh = std::fs::File::open(filename).unwrap(); - let mut buf = [0; 32]; - fh.seek(std::io::SeekFrom::Start(u64::try_from(idx * 32).unwrap())) - .unwrap(); - fh.read_exact(&mut buf).unwrap(); - Self(buf) - } - - fn write_to_file<F: AsRef<std::path::Path>>( - self, - filename: F, - idx: usize, - ) { - let mut fh = std::fs::OpenOptions::new() - .write(true) - .open(filename) - .unwrap(); - fh.seek(std::io::SeekFrom::Start(u64::try_from(idx * 32).unwrap())) - .unwrap(); - fh.write_all(&self.0).unwrap(); - } - - fn from_image_at(im: &image::GrayImage, idx: usize) -> Self { - let (width, _) = im.dimensions(); - assert_eq!(width, 128); - - let tile_row = idx / 16; - let tile_col = idx % 16; - - let mut bytes = [0; 32]; - for row_offset in 0..8 { - for col_offset in 0..8 { - let row = tile_row * 8 + row_offset; - let col = tile_col * 8 + col_offset; - let pixel = im.get_pixel( - col.try_into().unwrap(), - row.try_into().unwrap(), - ); - let val = pixel.channels()[0] / 16; - let b1 = val & 0x01; - let b2 = (val >> 1) & 0x01; - let b3 = (val >> 2) & 0x01; - let b4 = (val >> 3) & 0x01; - bytes[row_offset * 2] |= b1 << (7 - col_offset); - bytes[row_offset * 2 + 1] |= b2 << (7 - col_offset); - bytes[row_offset * 2 + 16] |= b3 << (7 - col_offset); - bytes[row_offset * 2 + 17] |= b4 << (7 - col_offset); - } - } - - Self(bytes) - } - - fn to_image(self) -> image::GrayImage { - image::GrayImage::from_fn(8, 8, |x, y| { - let row = usize::try_from(y).unwrap(); - let col = usize::try_from(x).unwrap(); - image::Luma::from([((self.0[row * 2] >> (7 - col)) & 0x01) - | (((self.0[row * 2 + 1] >> (7 - col)) & 0x01) << 1) - | (((self.0[row * 2 + 16] >> (7 - col)) & 0x01) << 2) - | (((self.0[row * 2 + 17] >> (7 - col)) & 0x01) << 3)]) - }) - } -} +use std::io::BufRead as _; // Graphics/GFX05.bin: // 0C Graphics/GFX02.bin:0E:2 @@ -97,7 +22,7 @@ impl TilemapEdit { for offset in offsets { let tile = match self.from_file.extension().and_then(|s| s.to_str()) { - Some("bin") => Tile::load_from_file( + Some("bin") => smw_tools::tile::Tile::load_from_file( &self.from_file, self.from_idx + offset, ), @@ -106,7 +31,10 @@ impl TilemapEdit { image::io::Reader::open(&self.from_file).unwrap(); let im = im.decode().unwrap(); let im = image::GrayImage::from(im); - Tile::from_image_at(&im, self.from_idx + offset) + smw_tools::tile::Tile::from_image_at( + &im, + self.from_idx + offset, + ) } _ => unimplemented!(), }; diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d825d0c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod tile; diff --git a/src/tile.rs b/src/tile.rs new file mode 100644 index 0000000..ee8bc5f --- /dev/null +++ b/src/tile.rs @@ -0,0 +1,76 @@ +use std::io::{Read as _, Seek as _, Write as _}; + +use image::Pixel as _; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Tile([u8; 32]); + +impl Tile { + pub fn load_from_file<F: AsRef<std::path::Path>>( + filename: F, + idx: usize, + ) -> Self { + let mut fh = std::fs::File::open(filename).unwrap(); + let mut buf = [0; 32]; + fh.seek(std::io::SeekFrom::Start(u64::try_from(idx * 32).unwrap())) + .unwrap(); + fh.read_exact(&mut buf).unwrap(); + Self(buf) + } + + pub fn write_to_file<F: AsRef<std::path::Path>>( + self, + filename: F, + idx: usize, + ) { + let mut fh = std::fs::OpenOptions::new() + .write(true) + .open(filename) + .unwrap(); + fh.seek(std::io::SeekFrom::Start(u64::try_from(idx * 32).unwrap())) + .unwrap(); + fh.write_all(&self.0).unwrap(); + } + + pub fn from_image_at(im: &image::GrayImage, idx: usize) -> Self { + let (width, _) = im.dimensions(); + assert_eq!(width, 128); + + let tile_row = idx / 16; + let tile_col = idx % 16; + + let mut bytes = [0; 32]; + for row_offset in 0..8 { + for col_offset in 0..8 { + let row = tile_row * 8 + row_offset; + let col = tile_col * 8 + col_offset; + let pixel = im.get_pixel( + col.try_into().unwrap(), + row.try_into().unwrap(), + ); + let val = pixel.channels()[0] / 16; + let b1 = val & 0x01; + let b2 = (val >> 1) & 0x01; + let b3 = (val >> 2) & 0x01; + let b4 = (val >> 3) & 0x01; + bytes[row_offset * 2] |= b1 << (7 - col_offset); + bytes[row_offset * 2 + 1] |= b2 << (7 - col_offset); + bytes[row_offset * 2 + 16] |= b3 << (7 - col_offset); + bytes[row_offset * 2 + 17] |= b4 << (7 - col_offset); + } + } + + Self(bytes) + } + + pub fn to_image(self) -> image::GrayImage { + image::GrayImage::from_fn(8, 8, |x, y| { + let row = usize::try_from(y).unwrap(); + let col = usize::try_from(x).unwrap(); + image::Luma::from([((self.0[row * 2] >> (7 - col)) & 0x01) + | (((self.0[row * 2 + 1] >> (7 - col)) & 0x01) << 1) + | (((self.0[row * 2 + 16] >> (7 - col)) & 0x01) << 2) + | (((self.0[row * 2 + 17] >> (7 - col)) & 0x01) << 3)]) + }) + } +} |