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}