Skip to main content

blp/core/
image.rs

1use crate::core::mipmap::Mipmap;
2use crate::core::types::{SourceKind, TextureType, Version};
3use crate::error::error::BlpError;
4
5pub const MAX_MIPS: usize = 16;
6pub const HEADER_SIZE: u64 = 156;
7
8/// Checks if buffer is a BLP file by signature
9fn is_blp_file(buf: &[u8]) -> bool {
10    // BLP files start with "BLP1" or "BLP2" signature (or just "BLP" prefix)
11    buf.len() >= 3 && &buf[..3] == b"BLP"
12}
13
14#[derive(Debug, Default)]
15pub struct ImageBlp {
16    #[allow(dead_code)]
17    pub version: Version,
18    pub texture_type: TextureType,
19    pub compression: u8,
20    pub alpha_bits: u32,
21    pub alpha_type: u8,
22    pub has_mips: u8,
23    pub width: u32,
24    pub height: u32,
25    pub extra: u32,       // meaningful only if version <= BLP1
26    pub has_mipmaps: u32, // meaningful only if version <= BLP1 or >= BLP2
27    //
28    pub mipmaps: Vec<Mipmap>,
29    pub holes: usize,
30    pub header_offset: usize,
31    pub header_length: usize,
32    //
33    pub source: SourceKind,
34}
35
36impl ImageBlp {
37    pub fn from_buf(buf: &[u8]) -> Result<Self, BlpError> {
38        if is_blp_file(buf) {
39            Self::from_buf_blp(buf)
40        } else {
41            Self::from_buf_image(buf)
42        }
43    }
44
45    /// Create BLP from raw RGBA buffer.
46    /// Buffer must be in RGBA format (4 bytes per pixel).
47    /// Width and height must match the buffer size.
48    pub fn from_rgba(rgba_buf: &[u8], width: u32, height: u32) -> Result<Self, BlpError> {
49        Self::from_rgba_impl(rgba_buf, width, height)
50    }
51
52    /// Top-level decode entry.
53    ///
54    /// `mip_visible[i] == false` → skip decoding for mip `i`.
55    /// Missing indices are treated as `true`.
56    pub fn decode(&mut self, buf: &[u8], mip_visible: &[bool]) -> Result<(), BlpError> {
57        match self.source {
58            SourceKind::Blp => match self.texture_type {
59                TextureType::DIRECT => self.decode_direct(buf, mip_visible),
60                TextureType::JPEG => self.decode_jpeg(buf, mip_visible),
61            },
62            SourceKind::Image => self.decode_image(buf, mip_visible),
63        }
64    }
65}