Skip to main content

uorustlibs/
texmap.rs

1//! Methods for reading texture data out of texmaps.mul
2//!
3//! Texmaps are used when non-flat surfaces need to be drawn
4//!
5//! Texmaps exist as a sequence of colours, and are either 128x128, or 64x64
6#[cfg(feature = "image")]
7use crate::color::Color;
8use crate::color::Color16;
9use crate::error::MulReaderResult;
10use crate::mul::MulReader;
11use byteorder::{LittleEndian, ReadBytesExt};
12#[cfg(feature = "image")]
13use image::{Rgba, RgbaImage};
14use std::fs::File;
15use std::io::{Cursor, Read, Seek};
16use std::path::Path;
17
18pub const LARGE_TILE: usize = 0x8000;
19
20/// A texture. They are always either 128x128 or 64x64
21#[derive(Debug, PartialEq, Eq, Clone)]
22pub struct TexMap {
23    pub data: Vec<Color16>,
24}
25
26#[cfg(feature = "image")]
27impl TexMap {
28    /// Convert this asset into a standarized image format
29    pub fn to_image(&self) -> RgbaImage {
30        let tile_width = if self.data.len() * 2 >= LARGE_TILE {
31            128
32        } else {
33            64
34        };
35
36        let mut buffer = RgbaImage::new(tile_width, tile_width);
37        for (idx, pixel) in self.data.iter().enumerate() {
38            let x = idx as u32 % tile_width;
39            let y = idx as u32 / tile_width;
40            let (r, g, b, a) = pixel.to_rgba();
41            buffer.put_pixel(x, y, Rgba([r, g, b, a]));
42        }
43        buffer
44    }
45}
46
47/// A struct to help read out TexMap data
48#[derive(Debug)]
49pub struct TexMapReader<T: Read + Seek> {
50    mul_reader: MulReader<T>,
51}
52
53impl TexMapReader<File> {
54    /// Create a new TexMapReader from an index and mul path
55    pub fn new(index_path: &Path, mul_path: &Path) -> MulReaderResult<TexMapReader<File>> {
56        let mul_reader = MulReader::new(index_path, mul_path)?;
57        Ok(TexMapReader { mul_reader })
58    }
59}
60
61impl<T: Read + Seek> TexMapReader<T> {
62    /// Create a TexMapReader from an existing mul reader
63    pub fn from_mul(reader: MulReader<T>) -> TexMapReader<T> {
64        TexMapReader { mul_reader: reader }
65    }
66
67    /// Read a single texmap
68    pub fn read(&mut self, id: u32) -> MulReaderResult<TexMap> {
69        let raw = self.mul_reader.read(id)?;
70        let len = raw.data.len();
71        let mut reader = Cursor::new(raw.data);
72        let mut data = vec![];
73        for _idx in 0..len / 2 {
74            data.push(reader.read_u16::<LittleEndian>()?);
75        }
76        Ok(TexMap { data })
77    }
78}