Use Array2D for storage in ImageRgbU8
This commit is contained in:
parent
40d9bb0bb1
commit
ef0fb96f9d
|
|
@ -53,8 +53,11 @@ impl ImageSampler {
|
||||||
Vec3::new(
|
Vec3::new(
|
||||||
Self::scale(column, self.image_width_pixels, self.film_width)
|
Self::scale(column, self.image_width_pixels, self.film_width)
|
||||||
- self.film_width * 0.5,
|
- self.film_width * 0.5,
|
||||||
Self::scale(row, self.image_height_pixels, self.film_height)
|
Self::scale(
|
||||||
- self.film_height * 0.5,
|
self.image_height_pixels - (row + 1),
|
||||||
|
self.image_height_pixels,
|
||||||
|
self.film_height,
|
||||||
|
) - self.film_height * 0.5,
|
||||||
self.film_distance,
|
self.film_distance,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -176,7 +179,7 @@ mod tests {
|
||||||
ImageSampler::scale(200, 800, target.film_width) - target.film_width * 0.5;
|
ImageSampler::scale(200, 800, target.film_width) - target.film_width * 0.5;
|
||||||
assert!((point_on_film_plane.x() - expected_x).abs() < 0.0000000001);
|
assert!((point_on_film_plane.x() - expected_x).abs() < 0.0000000001);
|
||||||
let expected_y =
|
let expected_y =
|
||||||
ImageSampler::scale(100, 600, target.film_height) - target.film_height * 0.5;
|
-ImageSampler::scale(100, 600, target.film_height) + target.film_height * 0.5;
|
||||||
assert!((point_on_film_plane.y() - expected_y).abs() < 0.0000000001);
|
assert!((point_on_film_plane.y() - expected_y).abs() < 0.0000000001);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
85
src/image.rs
85
src/image.rs
|
|
@ -5,55 +5,41 @@ use std::path::Path;
|
||||||
|
|
||||||
use crate::colour::{ColourRgbF, ColourRgbU8};
|
use crate::colour::{ColourRgbF, ColourRgbU8};
|
||||||
use crate::math::Vec3;
|
use crate::math::Vec3;
|
||||||
|
use crate::util::Array2D;
|
||||||
|
|
||||||
pub struct ImageRgbU8 {
|
pub struct ImageRgbU8 {
|
||||||
pixel_data: Vec<u8>,
|
data: Array2D<[u8; 3]>,
|
||||||
width: usize,
|
|
||||||
height: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageRgbU8 {
|
impl ImageRgbU8 {
|
||||||
pub fn new(width: usize, height: usize) -> ImageRgbU8 {
|
pub fn new(width: usize, height: usize) -> ImageRgbU8 {
|
||||||
ImageRgbU8 {
|
ImageRgbU8 {
|
||||||
width,
|
data: Array2D::new(height, width),
|
||||||
height,
|
|
||||||
pixel_data: vec![0; (width * height * 3) as usize],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) -> &mut ImageRgbU8 {
|
|
||||||
for byte in self.pixel_data.iter_mut() {
|
|
||||||
*byte = 0u8;
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_colour(&self, row: usize, column: usize) -> ColourRgbU8 {
|
pub fn get_colour(&self, row: usize, column: usize) -> ColourRgbU8 {
|
||||||
assert!(row < self.height && column < self.width);
|
|
||||||
let index = self.calculate_index(row, column);
|
|
||||||
ColourRgbU8 {
|
ColourRgbU8 {
|
||||||
values: self.pixel_data[index..index + 3]
|
values: self.data[row][column].try_into().expect("Wrong length."),
|
||||||
.try_into()
|
|
||||||
.expect("Wrong length."),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_colour(&mut self, row: usize, column: usize, colour: ColourRgbU8) {
|
pub fn set_colour(&mut self, row: usize, column: usize, colour: ColourRgbU8) {
|
||||||
assert!(row < self.height && column < self.width);
|
let slice = &mut self.data[row][column];
|
||||||
let index = self.calculate_index(row, column);
|
slice.copy_from_slice(&colour.values[..]);
|
||||||
self.pixel_data[index..index + 3].copy_from_slice(&colour.values[..]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pixel_data(&self) -> &Vec<u8> {
|
pub fn get_pixel_data(&self) -> &[u8] {
|
||||||
&self.pixel_data
|
let data = self.data.as_slice();
|
||||||
|
unsafe { std::slice::from_raw_parts(data[0].as_ptr(), data.len() * 3) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_width(&self) -> usize {
|
pub fn get_width(&self) -> usize {
|
||||||
self.width
|
self.data.get_width()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_height(&self) -> usize {
|
pub fn get_height(&self) -> usize {
|
||||||
self.height
|
self.data.get_height()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_channels() -> usize {
|
pub fn num_channels() -> usize {
|
||||||
|
|
@ -61,35 +47,24 @@ impl ImageRgbU8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, start_row: usize, start_column: usize, image: &ImageRgbU8) {
|
pub fn update(&mut self, start_row: usize, start_column: usize, image: &ImageRgbU8) {
|
||||||
assert!(start_column + image.width <= self.width);
|
self.data.update_block(start_row, start_column, &image.data);
|
||||||
assert!(start_row + image.height <= self.height);
|
|
||||||
for row in 0..image.height {
|
|
||||||
let source_start = image.calculate_index(row, 0);
|
|
||||||
let source_end = image.calculate_index(row, image.width - 1) + 3;
|
|
||||||
let destination_start = self.calculate_index(start_row + row, start_column);
|
|
||||||
let destination_end =
|
|
||||||
self.calculate_index(start_row + row, start_column + image.width - 1) + 3;
|
|
||||||
self.pixel_data[destination_start..destination_end]
|
|
||||||
.copy_from_slice(&image.pixel_data[source_start..source_end]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_png(&self, filename: &Path) -> Result<(), std::io::Error> {
|
pub fn write_png(&self, filename: &Path) -> Result<(), std::io::Error> {
|
||||||
let file = File::create(filename)?;
|
let file = File::create(filename)?;
|
||||||
let ref mut file_buffer = BufWriter::new(file);
|
let ref mut file_buffer = BufWriter::new(file);
|
||||||
|
|
||||||
let mut encoder = png::Encoder::new(file_buffer, self.width as u32, self.height as u32);
|
let mut encoder = png::Encoder::new(
|
||||||
|
file_buffer,
|
||||||
|
self.get_width() as u32,
|
||||||
|
self.get_height() as u32,
|
||||||
|
);
|
||||||
encoder.set_color(png::ColorType::RGB);
|
encoder.set_color(png::ColorType::RGB);
|
||||||
encoder.set_depth(png::BitDepth::Eight);
|
encoder.set_depth(png::BitDepth::Eight);
|
||||||
let mut writer = encoder.write_header()?;
|
let mut writer = encoder.write_header()?;
|
||||||
writer.write_image_data(self.pixel_data.as_slice())?;
|
writer.write_image_data(self.get_pixel_data())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_index(&self, row: usize, column: usize) -> usize {
|
|
||||||
assert!(row < self.height && column < self.width);
|
|
||||||
(((self.height - (row + 1)) * self.width + column) * Self::num_channels()) as usize
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImageRgbF {
|
pub struct ImageRgbF {
|
||||||
|
|
@ -213,6 +188,30 @@ impl ToneMapper for ClampingToneMapper {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_pixel_data_returns_correct_values() {
|
||||||
|
let mut target = ImageRgbU8::new(4, 3);
|
||||||
|
for i in 0..3 {
|
||||||
|
for j in 0..4 {
|
||||||
|
target.set_colour(
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
ColourRgbU8 {
|
||||||
|
values: [i as u8, j as u8, i as u8],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i in 0..3 {
|
||||||
|
for j in 0..4 {
|
||||||
|
let index = (i * 4 + j) * 3;
|
||||||
|
assert!(target.get_pixel_data()[index] == i as u8);
|
||||||
|
assert!(target.get_pixel_data()[index + 1] == j as u8);
|
||||||
|
assert!(target.get_pixel_data()[index + 2] == i as u8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod normalized_as_byte {
|
mod normalized_as_byte {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ fn update_texture(tile: &Tile, image: &ImageRgbU8, texture: &mut Texture) {
|
||||||
.update(
|
.update(
|
||||||
Rect::new(
|
Rect::new(
|
||||||
tile.start_column as i32,
|
tile.start_column as i32,
|
||||||
texture.query().height as i32 - (tile.start_row as i32 + tile.height() as i32),
|
tile.start_row as i32,
|
||||||
tile.width() as u32,
|
tile.width() as u32,
|
||||||
tile.height() as u32,
|
tile.height() as u32,
|
||||||
),
|
),
|
||||||
image.get_pixel_data().as_slice(),
|
image.get_pixel_data(),
|
||||||
(image.get_width() * ImageRgbU8::num_channels()) as usize,
|
(image.get_width() * ImageRgbU8::num_channels()) as usize,
|
||||||
)
|
)
|
||||||
.expect("Couldn't update texture.");
|
.expect("Couldn't update texture.");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue