libbitsub_core/pgs/palette.rs
1//! Palette Definition Segment parsing.
2
3use crate::utils::{BigEndianReader, ycbcr_to_rgba};
4
5/// Palette Definition Segment contains color palette entries.
6#[derive(Debug, Clone)]
7pub struct PaletteDefinitionSegment {
8 /// Palette ID (0-7)
9 pub id: u8,
10 /// Version number for this palette
11 pub version: u8,
12 /// RGBA colors indexed by palette entry ID (up to 256 entries)
13 /// Stored as packed u32: [R, G, B, A] in little-endian byte order
14 pub rgba: Vec<u32>,
15}
16
17impl PaletteDefinitionSegment {
18 /// Parse a palette definition segment from binary data.
19 pub fn parse(reader: &mut BigEndianReader, length: usize) -> Option<Self> {
20 let id = reader.read_u8()?;
21 let version = reader.read_u8()?;
22
23 // Each palette entry is 5 bytes: ID, Y, Cr, Cb, A
24 let entry_count = (length - 2) / 5;
25
26 // Pre-allocate with default transparent (256 possible entries)
27 let mut rgba = vec![0u32; 256];
28
29 for _ in 0..entry_count {
30 let entry_id = reader.read_u8()? as usize;
31 let y = reader.read_u8()?;
32 let cr = reader.read_u8()?; // PGS stores Cr before Cb
33 let cb = reader.read_u8()?;
34 let a = reader.read_u8()?;
35
36 // Convert YCbCr to RGBA and store at entry index
37 // PGS palette order is: Y, Cr, Cb, A
38 // ycbcr_to_rgba expects: y, cb, cr, a
39 if entry_id < 256 {
40 rgba[entry_id] = ycbcr_to_rgba(y, cb, cr, a);
41 }
42 }
43
44 Some(Self { id, version, rgba })
45 }
46
47 /// Create an empty palette with default transparent values.
48 pub fn empty() -> Self {
49 Self {
50 id: 0,
51 version: 0,
52 rgba: vec![0u32; 256],
53 }
54 }
55}