Skip to content

Instantly share code, notes, and snippets.

@jonvaldes
Last active February 16, 2021 09:08
Show Gist options
  • Save jonvaldes/607fbc380f816d205afb to your computer and use it in GitHub Desktop.
Save jonvaldes/607fbc380f816d205afb to your computer and use it in GitHub Desktop.
Testing how to generate a tga image with Rust
use std::io;
use std::fs::File;
use std::io::Write;
use std::mem;
use std::slice;
#[derive(Clone)]
struct Color(u8, u8, u8);
struct Image {
width: i32,
height: i32,
data: Vec<Color>,
}
unsafe fn struct_to_u8_slice<T>(s: &T) -> &[u8] {
let data_ptr: *const u8 = mem::transmute(s);
slice::from_raw_parts(data_ptr, mem::size_of::<T>())
}
unsafe fn slice_to_u8_slice<T>(s: &[T]) -> &[u8] {
let data_ptr: *const u8 = mem::transmute(&s[0]);
slice::from_raw_parts(data_ptr, mem::size_of::<T>() * s.len())
}
impl Image {
fn new(width: i32, height: i32) -> Image {
let v = vec![Color(0,0,0);(width*height) as usize];
let result = Image {
width: width,
height: height,
data: v,
};
result
}
fn apply_gamma(self: &mut Image, gamma: f32) {
for c in self.data.iter_mut() {
let Color(r, g, b) = *c;
let fr = ((r as f32) / 255.0).powf(gamma);
let fg = ((g as f32) / 255.0).powf(gamma);
let fb = ((b as f32) / 255.0).powf(gamma);
c.0 = (fr * 255.0) as u8;
c.1 = (fg * 255.0) as u8;
c.2 = (fb * 255.0) as u8;
}
}
fn set_pixel(self: &mut Image, x: i32, y: i32, c: Color) {
self.data[(x + y * self.width) as usize] = c;
}
fn write_to_tga(self: &Image, filename: &str) -> io::Result<()> {
#[repr(C, packed)]
#[derive(Default)]
struct Header {
id_length: u8,
color_map_type: u8,
image_type: u8,
c_map_start: u16,
c_map_length: u16,
c_map_depth: u8,
x_offset: u16,
y_offset: u16,
width: u16,
height: u16,
pixel_depth: u8,
image_descriptor: u8,
}
let h = Header {
image_type: 2,
width: self.width as u16,
height: self.height as u16,
pixel_depth: 24,
..Header::default()
};
let mut f = try!(File::create(filename));
unsafe {
try!(f.write_all(struct_to_u8_slice(&h)));
try!(f.write_all(slice_to_u8_slice(&self.data[..])));
}
Ok(())
}
}
fn main() {
let mut img = Image::new(640, 480);
for y in 0u32..480 {
for x in 0u32..640 {
let r = ((x ^ y) % 256) as u8;
let g = ((x + y) % 256) as u8;
let b = ((y.wrapping_sub(x)) % 256) as u8;
img.set_pixel(x as i32, y as i32, Color(r, g, b));
}
}
img.apply_gamma(2.2);
img.write_to_tga("test.tga").unwrap();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment