image_blp/types/direct/
raw1.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use crate::types::{
    header::{BlpHeader, BlpVersion},
    locator::MipmapLocator,
};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BlpRaw1 {
    /// The cmap field array is the colour look up table used for an indexed
    /// colour model. Each element represents 24 bit RGB colour component values
    /// in the order of 0xBBGGRR. The final byte is alignment padding and will
    /// not alter the decoded image in any way. One might be able to improve the
    /// file compressibility by carefully choosing padding values.
    pub cmap: Vec<u32>,
    /// Image itself and all mipmaps levels. If there are no mipmaps,
    /// the length of the vector is 1.
    pub images: Vec<Raw1Image>,
}

impl BlpRaw1 {
    /// Predict internal locator to write down mipmaps
    pub fn mipmap_locator(&self, version: BlpVersion) -> MipmapLocator {
        let mut offsets = [0; 16];
        let mut sizes = [0; 16];
        let mut cur_offset = BlpHeader::size(version) + self.cmap.len() * 4;
        for (i, image) in self.images.iter().take(16).enumerate() {
            offsets[i] = cur_offset as u32;
            sizes[i] = image.len() as u32;
            cur_offset += image.len();
        }

        MipmapLocator::Internal { offsets, sizes }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Raw1Image {
    /// BGR component values can be obtained by using indexedRGB values as an
    /// index in lutBGR. When producing such values using color matching be
    /// aware of the linear nature of the color space. For best results it is
    /// recommended that color matching be performed in sRGB or other perceptual
    /// color spaces.
    pub indexed_rgb: Vec<u8>,

    /// Alpha component can be obtained by breaking indexedAlpha into a bit
    /// field of alphaBits bit length fragments and then using the bit fragment
    /// as the alpha value for the pixel. The alpha pixel components are ordered
    /// from least significant to most significant bit with bytes following the
    /// same pixel order as indexedRGB. Since the alpha is to alphaBits
    /// precision it may need to be resampled to 8 bits be useful depending on
    /// the imaging framework used.
    ///
    /// Example of different alpha packing in a byte:
    ///
    /// ```text
    /// MSB <-> LSB where number indicates the sequential pixel the bits belong to
    /// ALPHA_8B -> 11111111
    /// ALPHA_4B -> 22221111
    /// ALPHA_1B -> 87654321
    /// ```
    pub indexed_alpha: Vec<u8>,
}

impl Raw1Image {
    /// Get size in bytes of serialized image
    pub fn len(&self) -> usize {
        self.indexed_rgb.len() + self.indexed_alpha.len()
    }

    pub fn is_empty(&self) -> bool {
        self.indexed_rgb.is_empty() && self.indexed_alpha.is_empty()
    }
}