almost done with tga stuff
This commit is contained in:
commit
7d190cec88
6 changed files with 172 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
4
.rustfmt.toml
Normal file
4
.rustfmt.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
imports_granularity = "Crate"
|
||||
group_imports = "StdExternalCrate"
|
||||
wrap_comments = true
|
||||
edition = "2024"
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "tinyrender"
|
||||
version = "0.1.0"
|
6
Cargo.toml
Normal file
6
Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "tinyrender"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
3
src/main.rs
Normal file
3
src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
151
src/tga.rs
Normal file
151
src/tga.rs
Normal file
|
@ -0,0 +1,151 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
io::Read,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[repr(C, packed)]
|
||||
pub struct TGAHeader {
|
||||
pub id_length: u8,
|
||||
pub colormap_type: u8,
|
||||
pub datatype_code: u8,
|
||||
pub colormap_origin: u16,
|
||||
pub colormap_length: u16,
|
||||
pub colormap_depth: u8,
|
||||
pub x_origin: u16,
|
||||
pub y_origin: u16,
|
||||
pub width: u16,
|
||||
pub height: u16,
|
||||
pub bits_per_pixel: u8,
|
||||
pub image_descriptor: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum Format {
|
||||
Grayscale = 1,
|
||||
RGB = 3,
|
||||
#[default]
|
||||
RGBA = 4,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for Format {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
1 => Ok(Self::Grayscale),
|
||||
3 => Ok(Self::RGB),
|
||||
4 => Ok(Self::RGBA),
|
||||
_ => Err(format!("could not convert {value} into a Format")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct TGAColor {
|
||||
pub bgra: [u8; 4],
|
||||
}
|
||||
|
||||
impl Deref for TGAColor {
|
||||
type Target = [u8; 4];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.bgra
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for TGAColor {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.bgra
|
||||
}
|
||||
}
|
||||
|
||||
impl TGAColor {
|
||||
pub fn new() -> Self {
|
||||
Self { bgra: [0; 4] }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
struct TGAImage {
|
||||
pub format: Format,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
pub type IoResult = std::io::Result<()>;
|
||||
|
||||
impl TGAImage {
|
||||
pub fn new(width: u32, height: u32, format: Format) -> Self {
|
||||
Self {
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
data: Vec::with_capacity((format as usize) * (width * height) as usize),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes_per_pixel(&self) -> u8 {
|
||||
self.format as u8
|
||||
}
|
||||
|
||||
pub fn read_file(&mut self, file: &str) -> IoResult {
|
||||
let mut file = std::fs::File::open(file)?;
|
||||
let header_size = size_of::<TGAHeader>();
|
||||
assert_eq!(header_size, 18);
|
||||
let mut bytes = [0u8; header_size];
|
||||
file.read_exact(&mut bytes)?;
|
||||
let header: TGAHeader = unsafe { std::mem::transmute(bytes) };
|
||||
|
||||
if header.width < 1 || header.height < 1 {
|
||||
return Err("bad image metadata".into());
|
||||
}
|
||||
self.format = (header.bits_per_pixel >> 3).try_into()?;
|
||||
|
||||
self.width = header.width;
|
||||
self.height = header.height;
|
||||
|
||||
let nbytes = self.format as usize * (self.width * self.height) as usize;
|
||||
let mut image_data = Vec::with_capacity(nbytes);
|
||||
match header.datatype_code {
|
||||
2 | 3 => {
|
||||
file.read_to_end(&mut image_data)?;
|
||||
self.data = image_data;
|
||||
}
|
||||
10 | 11 => {
|
||||
self.read_rle_file(&mut file)?;
|
||||
}
|
||||
_ => {
|
||||
return Err("invalid TGA file".into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_file(&self, file: &str) -> IoResult {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn flip_horizontal(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn flip_vertical(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn set(&mut self, x: u32, y: u32, color: &TGAColor) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn get(&self, x: u32, y: u32) -> Option<TGAColor> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn read_rle_file(&mut self, file: &mut File) -> IoResult {
|
||||
todo!()
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue