pgs_parse/
pgs_display_set.rs

1//! # PGS Display Set
2//!
3//! This module defines the `PgsDisplaySet` struct, which represents a collection of segments
4//! involved in the rendering of a PGS (Presentation Graphic Stream) subtitle frame. The display set
5//! includes PCS (Presentation Composition Segment), WDS (Window Definition Segment), PDS (Palette
6//! Definition Segment), and ODS (Object Definition Segment). The state of the display set can be
7//! used to determine if a frame is complete and ready for rendering.
8
9use std::rc::Rc;
10
11use crate::{pgs_decode_rle::decode_rle, Error, PgsOdsSegment, PgsPcsSegment, PgsPdsSegment, PgsWdsSegment, Result};
12
13/// Enum representing the state of the `PgsDisplaySet`.
14#[derive(Debug, Clone, Copy, PartialEq)]
15pub enum PgsDisplaySetState {
16    /// The display set is incomplete, not all required segments (PCS, WDS, PDS, ODS) are present.
17    Incomplete,
18    /// The display set is complete and ready to be rendered.
19    Complete,
20    /// The display set contains only empty frames, meaning it has PCS and WDS but no PDS or ODS.
21    EmptyFrame
22}
23
24/// Struct representing a collection of PGS segments required for rendering a single subtitle frame.
25/// The segments include:
26/// - `pcs`: Presentation Composition Segment.
27/// - `wds`: Window Definition Segment.
28/// - `pds`: Palette Definition Segment.
29/// - `ods`: Object Definition Segment.
30#[derive(Debug, Default, Clone)]
31pub struct PgsDisplaySet {
32    pub pcs: Option<Rc<PgsPcsSegment>>,
33    pub wds: Option<Rc<PgsWdsSegment>>,
34    pub pds: Option<Rc<PgsPdsSegment>>,
35    pub ods: Option<Rc<PgsOdsSegment>>
36}
37
38impl PgsDisplaySet {
39    /// Creates a new, empty `PgsDisplaySet` with no segments.
40    ///
41    /// # Returns
42    /// A new `PgsDisplaySet` instance with all segment options set to `None`.
43    pub fn new() -> Self {
44        PgsDisplaySet {
45            pcs: None,
46            wds: None,
47            pds: None,
48            ods: None
49        }
50    }
51
52    /// Clears the display set by setting all segments (PCS, WDS, PDS, ODS) to `None`.
53    ///
54    /// This can be used to reset the display set for reuse.
55    pub(crate) fn clean(&mut self) {
56        self.pcs = None;
57        self.wds = None;
58        self.pds = None;
59        self.ods = None;
60    }
61
62    /// Determines the current state of the display set.
63    ///
64    /// - If PCS and WDS are present, but PDS and ODS are not, the state is `EmptyFrame`.
65    /// - If all segments (PCS, WDS, PDS, ODS) are present, the state is `Complete`.
66    /// - Otherwise, the state is `Incomplete`.
67    ///
68    /// # Returns
69    /// The current state of the `PgsDisplaySet`.
70    pub fn state(&self) -> PgsDisplaySetState {
71        if self.pcs.is_some() && self.wds.is_some() {
72            if self.pds.is_some() && self.ods.is_some() {
73                return PgsDisplaySetState::Complete;
74            }
75            return PgsDisplaySetState::EmptyFrame;
76        }
77        PgsDisplaySetState::Incomplete
78    }
79
80    /// Returns a reference to the RLE (Run-Length Encoded) image data contained in the ODS segment.
81    ///
82    /// # Errors
83    /// Returns `Error::IncompleteDisplaySet` if the display set is not in the `Complete` state.
84    ///
85    /// # Returns
86    /// A reference to the raw RLE image data.    
87    pub fn get_rle_image(&self) -> Result<&Vec<u8>> {
88        if self.state() != PgsDisplaySetState::Complete {
89            return Err(Error::IncompleteDisplaySet);
90        }
91        Ok(&self.ods.as_ref().unwrap().object_data)
92    }
93
94    /// Decodes the RLE image data and returns the image as a 2D array of pixels.
95    ///
96    /// This function decodes the image contained in the ODS segment using the palette from the PDS
97    /// segment. It can return the image in either grayscale or color depending on the `gray` parameter.
98    ///
99    /// # Parameters
100    /// - `gray`: A boolean flag indicating whether to decode the image in grayscale (`true`) or color (`false`).
101    ///
102    /// # Errors
103    /// Returns `Error::IncompleteDisplaySet` if the display set is not in the `Complete` state.
104    ///
105    /// # Returns
106    /// A 2D vector containing the decoded pixels, where each pixel is represented as a 32-bit color value.
107    pub fn get_decoded_image(&self, gray: bool) -> Result<Vec<Vec<u32>>> {
108        if self.state() != PgsDisplaySetState::Complete {
109            return Err(Error::IncompleteDisplaySet);
110        }
111
112        let ods: &Rc<PgsOdsSegment> = self.ods.as_ref().unwrap();
113        let pds = self.pds.as_ref().unwrap();
114        let pixels = decode_rle(pds.clone(), ods.clone(), gray)?;
115        Ok(pixels)
116    }
117}