use crate::utils::color_gradient::Color;
use alloc::{
slice::{Iter, IterMut},
vec::{IntoIter, Vec},
};
use core::ops::{Index, IndexMut};
#[cfg(feature = "images")]
use std::path::Path;
const RASTER_MAX_WIDTH: u16 = 32_767;
const RASTER_MAX_HEIGHT: u16 = 32_767;
pub struct NoiseImage {
size: (usize, usize),
border_color: Color,
map: Vec<Color>,
}
impl NoiseImage {
pub fn new(width: usize, height: usize) -> Self {
Self::initialize().set_size(width, height)
}
pub fn iter(&self) -> Iter<'_, Color> {
self.map.iter()
}
pub fn iter_mut(&mut self) -> IterMut<'_, Color> {
self.map.iter_mut()
}
pub fn set_size(self, width: usize, height: usize) -> Self {
assert!(width < RASTER_MAX_WIDTH as usize);
assert!(height < RASTER_MAX_HEIGHT as usize);
if width == 0 || height == 0 {
Self::initialize()
} else {
let map_size = width * height;
if self.map.capacity() < map_size {
Self {
map: vec![[0; 4]; map_size],
size: (width, height),
..self
}
} else {
Self {
size: (width, height),
..self
}
}
}
}
pub fn set_border_color(self, color: Color) -> Self {
Self {
border_color: color,
..self
}
}
pub fn set_value(&mut self, x: usize, y: usize, value: Color) {
let (width, height) = self.size;
if x < width && y < height {
self.map[x + y * width] = value;
} else {
}
}
pub fn size(&self) -> (usize, usize) {
self.size
}
pub fn border_color(&self) -> Color {
self.border_color
}
pub fn get_value(&self, x: usize, y: usize) -> Color {
let (width, height) = self.size;
if x < width && y < height {
self.map[x + y * width]
} else {
self.border_color
}
}
fn initialize() -> Self {
Self {
size: (0, 0),
border_color: [0; 4],
map: Vec::new(),
}
}
#[cfg(feature = "images")]
pub fn write_to_file(&self, filename: &Path) {
let (width, height) = self.size;
let mut result = Vec::with_capacity(width * height);
for i in &self.map {
for j in i.iter() {
result.push(*j);
}
}
let _ = image::save_buffer(
filename,
&result,
self.size.0 as u32,
self.size.1 as u32,
image::ColorType::Rgba8,
);
println!("\nFinished generating {}", filename.to_string_lossy());
}
}
impl Default for NoiseImage {
fn default() -> Self {
Self::initialize()
}
}
impl Index<(usize, usize)> for NoiseImage {
type Output = Color;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
let (width, height) = self.size;
if x < width && y < height {
&self.map[x + y * width]
} else {
&self.border_color
}
}
}
impl IndexMut<(usize, usize)> for NoiseImage {
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
let (width, height) = self.size;
if x < width && y < height {
&mut self.map[x + y * width]
} else {
panic!(
"index ({}, {}) out of bounds for NoiseImage of size ({}, {})",
x, y, width, height
)
}
}
}
impl IntoIterator for NoiseImage {
type Item = Color;
type IntoIter = IntoIter<Color>;
fn into_iter(self) -> Self::IntoIter {
self.map.into_iter()
}
}
impl<'a> IntoIterator for &'a NoiseImage {
type Item = &'a Color;
type IntoIter = Iter<'a, Color>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut NoiseImage {
type Item = &'a mut Color;
type IntoIter = IterMut<'a, Color>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}