# HG changeset patch # User unC0Rr # Date 1675323691 -3600 # Node ID 8f093b1b18bca0e7dea0e58b0a8ffccd7a7a1b6d # Parent c571d4b8879c5bdae51e7965231bde21edd4a89f Add loading of tiles from png diff -r c571d4b8879c -r 8f093b1b18bc rust/landgen/Cargo.toml --- a/rust/landgen/Cargo.toml Wed Feb 01 11:19:45 2023 +0100 +++ b/rust/landgen/Cargo.toml Thu Feb 02 08:41:31 2023 +0100 @@ -9,3 +9,4 @@ land2d = { path = "../land2d" } vec2d = { path = "../vec2d" } itertools = "0.7.8" +png = "0.17" diff -r c571d4b8879c -r 8f093b1b18bc rust/landgen/src/wavefront_collapse/generator.rs --- a/rust/landgen/src/wavefront_collapse/generator.rs Wed Feb 01 11:19:45 2023 +0100 +++ b/rust/landgen/src/wavefront_collapse/generator.rs Thu Feb 02 08:41:31 2023 +0100 @@ -1,22 +1,53 @@ +use super::tile_image::TileImage; use super::wavefront_collapse::WavefrontCollapse; -use super::tile_image::TileImage; use crate::{LandGenerationParameters, LandGenerator}; +use integral_geometry::Size; +use png::Decoder; +use std::fs::File; +use std::io::BufReader; pub struct WavefrontCollapseLandGenerator { wfc: WavefrontCollapse, - tiles: Vec, } impl WavefrontCollapseLandGenerator { pub fn new() -> Self { Self { wfc: WavefrontCollapse::default(), - tiles: Vec::new() } } - pub fn load_template() { + pub fn load_template(&self, parameters: &LandGenerationParameters) -> Vec> { + let file = File::open("sample.png").expect("file exists"); + let decoder = Decoder::new(BufReader::new(file)); + let mut reader = decoder.read_info().unwrap(); + + let info = reader.info(); + let mut tiles_image = vec2d::Vec2D::new( + &Size::new(info.width as usize, info.height as usize), + parameters.zero, + ); + + let mut buf = vec![0; reader.output_buffer_size()]; + let info = reader.next_frame(&mut buf).unwrap(); + let bytes = &buf[..info.buffer_size()]; + let mut tiles_image_pixels = tiles_image.as_mut_slice().into_iter(); + + for line in bytes.chunks_exact(info.line_size) { + for value in line.chunks_exact(info.color_type.samples()) { + *tiles_image_pixels + .next() + .expect("vec2d size matching image dimensions") = + if value.into_iter().all(|p| *p == 0) { + parameters.zero + } else { + parameters.basic + }; + } + } + + TileImage::::new(tiles_image).split(3, 3) } } @@ -26,6 +57,23 @@ parameters: &LandGenerationParameters, random_numbers: &mut I, ) -> land2d::Land2D { + let tiles = self.load_template(parameters); + todo!() } } + +#[cfg(test)] +mod tests { + use super::WavefrontCollapseLandGenerator; + use crate::{LandGenerator, LandGenerationParameters}; + use integral_geometry::Size; + use vec2d::Vec2D; + + #[test] + fn test_generation() { + let wfc_gen =WavefrontCollapseLandGenerator::new(); + let landgen_params = LandGenerationParameters::new(0u8, 255u8, 0, true, true); + wfc_gen.generate_land(&landgen_params, &mut std::iter::repeat(1u32)); + } +} diff -r c571d4b8879c -r 8f093b1b18bc rust/landgen/src/wavefront_collapse/tile_image.rs --- a/rust/landgen/src/wavefront_collapse/tile_image.rs Wed Feb 01 11:19:45 2023 +0100 +++ b/rust/landgen/src/wavefront_collapse/tile_image.rs Thu Feb 02 08:41:31 2023 +0100 @@ -1,18 +1,19 @@ -use land2d::Land2D; +use vec2d::Vec2D; use std::rc::Rc; +use integral_geometry::Size; -pub struct TileImage { - image: Rc>, +pub struct TileImage { + image: Rc>, flip: bool, mirror: bool, } -impl TileImage { - pub fn new(flip: bool, mirror: bool) -> Self { +impl TileImage { + pub fn new(image: Vec2D) -> Self { Self { - image: todo!(), - flip, - mirror, + image: Rc::new(image), + flip: false, + mirror: false, } } @@ -20,7 +21,7 @@ Self { image: self.image.clone(), flip: self.flip, - mirror: !self.mirror + mirror: !self.mirror, } } @@ -28,7 +29,50 @@ Self { image: self.image.clone(), flip: !self.flip, - mirror: self.mirror + mirror: self.mirror, } } + + pub fn split(&self, rows: usize, columns: usize) -> Vec> { + let mut result = Vec::new(); + let self_image = self.image.as_ref(); + let (result_width, result_height) = (self_image.width() / columns, self.image.height() / rows); + + for row in 0..rows { + for column in 0..columns { + let mut tile_pixels = Vec::new(); + + for out_row in 0..result_height { + tile_pixels.push(self_image[row * result_height + out_row][column*result_width..(column+1)*result_width].iter()); + } + + let tile_image = Vec2D::from_iter(tile_pixels.into_iter().flatten().map(|p| *p), &Size::new(result_width, result_height)); + + result.push(TileImage::new(tile_image.expect("correct calculation of tile dimensions"))); + } + } + + result + } } + +#[cfg(test)] +mod tests { + use super::TileImage; + use integral_geometry::Size; + use vec2d::Vec2D; + + #[test] + fn test_split() { + let size = Size::new(6, 4); + let sample_data = Vec2D::from_iter((0..24).into_iter(), &size); + + assert!(sample_data.is_some()); + + let sample_data = sample_data.unwrap(); + let big_tile = TileImage::new(sample_data); + let subtiles = big_tile.split(2, 2); + + assert_eq!(subtiles.len(), 4); + } +} diff -r c571d4b8879c -r 8f093b1b18bc rust/landgen/src/wavefront_collapse/wavefront_collapse.rs --- a/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Wed Feb 01 11:19:45 2023 +0100 +++ b/rust/landgen/src/wavefront_collapse/wavefront_collapse.rs Thu Feb 02 08:41:31 2023 +0100 @@ -1,6 +1,6 @@ use integral_geometry::Size; +use std::collections::HashMap; use vec2d::Vec2D; -use std::collections::HashMap; #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub enum Tile { @@ -60,7 +60,7 @@ map_size: &Size, seed_fn: F, random_numbers: &mut I, - ) -> Vec2D { + ) -> Vec2D { let mut land = Vec2D::new(&map_size, Tile::Empty); seed_fn(&mut land); @@ -116,8 +116,12 @@ [ land.get(y, x + 1).map(|p| *p).unwrap_or_default(), land.get(y + 1, x).map(|p| *p).unwrap_or_default(), - land.get(y, x.wrapping_sub(1)).map(|p| *p).unwrap_or_default(), - land.get(y.wrapping_sub(1), x).map(|p| *p).unwrap_or_default(), + land.get(y, x.wrapping_sub(1)) + .map(|p| *p) + .unwrap_or_default(), + land.get(y.wrapping_sub(1), x) + .map(|p| *p) + .unwrap_or_default(), ] } } diff -r c571d4b8879c -r 8f093b1b18bc rust/vec2d/src/lib.rs --- a/rust/vec2d/src/lib.rs Wed Feb 01 11:19:45 2023 +0100 +++ b/rust/vec2d/src/lib.rs Thu Feb 02 08:41:31 2023 +0100 @@ -143,6 +143,17 @@ } } +impl Vec2D { + pub fn from_iter>(iter: I, size: &Size) -> Option> { + let data: Vec = iter.into_iter().collect(); + if size.width * size.height == data.len() { + Some(Vec2D { data, size: *size }) + } else { + None + } + } +} + #[cfg(test)] mod tests { use super::*;