ironrdp_graphics/rdp6/bitmap_stream/
encoder.rs1use ironrdp_core::{not_enough_bytes_err, EncodeError, WriteCursor};
2use ironrdp_pdu::bitmap::rdp6::{BitmapStreamHeader, ColorPlaneDefinition};
3
4use crate::rdp6::rle::{compress_8bpp_plane, RleEncodeError};
5
6#[derive(Debug)]
7pub enum BitmapEncodeError {
8 Rle(RleEncodeError),
9 Encode(EncodeError),
10}
11
12impl core::fmt::Display for BitmapEncodeError {
13 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
14 match self {
15 BitmapEncodeError::Rle(_error) => write!(f, "failed to rle compress"),
16 BitmapEncodeError::Encode(_error) => write!(f, "failed to encode pdu"),
17 }
18 }
19}
20
21impl core::error::Error for BitmapEncodeError {
22 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
23 match self {
24 BitmapEncodeError::Rle(error) => Some(error),
25 BitmapEncodeError::Encode(error) => Some(error),
26 }
27 }
28}
29
30pub trait ColorChannels {
31 const STRIDE: usize;
32 const R: usize;
33 const G: usize;
34 const B: usize;
35}
36
37pub trait AlphaChannel {
38 const A: usize;
39}
40
41pub trait PixelFormat {
42 const STRIDE: usize;
43
44 fn r(pixel: &[u8]) -> u8;
45 fn g(pixel: &[u8]) -> u8;
46 fn b(pixel: &[u8]) -> u8;
47}
48
49pub trait PixelAlpha: PixelFormat {
50 fn a(pixel: &[u8]) -> u8;
51}
52
53impl<T> PixelFormat for T
54where
55 T: ColorChannels,
56{
57 const STRIDE: usize = T::STRIDE;
58
59 fn r(pixel: &[u8]) -> u8 {
60 pixel[T::R]
61 }
62
63 fn g(pixel: &[u8]) -> u8 {
64 pixel[T::G]
65 }
66
67 fn b(pixel: &[u8]) -> u8 {
68 pixel[T::B]
69 }
70}
71
72impl<T> PixelAlpha for T
73where
74 T: ColorChannels + AlphaChannel,
75{
76 fn a(pixel: &[u8]) -> u8 {
77 pixel[T::A]
78 }
79}
80
81pub struct RgbChannels;
82
83impl ColorChannels for RgbChannels {
84 const STRIDE: usize = 3;
85 const R: usize = 0;
86 const G: usize = 1;
87 const B: usize = 2;
88}
89
90pub struct ARgbChannels;
91
92impl ColorChannels for ARgbChannels {
93 const STRIDE: usize = 4;
94 const R: usize = 1;
95 const G: usize = 2;
96 const B: usize = 3;
97}
98
99impl AlphaChannel for ARgbChannels {
100 const A: usize = 0;
101}
102
103pub struct RgbAChannels;
104
105impl ColorChannels for RgbAChannels {
106 const STRIDE: usize = 4;
107 const R: usize = 0;
108 const G: usize = 1;
109 const B: usize = 2;
110}
111
112impl AlphaChannel for RgbAChannels {
113 const A: usize = 3;
114}
115
116pub struct ABgrChannels;
117
118impl ColorChannels for ABgrChannels {
119 const STRIDE: usize = 4;
120 const R: usize = 3;
121 const G: usize = 2;
122 const B: usize = 1;
123}
124
125impl AlphaChannel for ABgrChannels {
126 const A: usize = 0;
127}
128
129pub struct BgrAChannels;
130
131impl ColorChannels for BgrAChannels {
132 const STRIDE: usize = 4;
133 const R: usize = 2;
134 const G: usize = 1;
135 const B: usize = 0;
136}
137
138impl AlphaChannel for BgrAChannels {
139 const A: usize = 3;
140}
141
142impl BitmapEncodeError {
143 fn rle(e: RleEncodeError) -> Self {
144 Self::Rle(e)
145 }
146}
147
148pub struct BitmapStreamEncoder {
149 width: usize,
150 height: usize,
151}
152
153impl BitmapStreamEncoder {
154 pub fn new(width: usize, height: usize) -> Self {
155 Self { width, height }
156 }
157
158 pub fn encode_channels_stream<R, G, B>(
159 &mut self,
160 (r, g, b): (R, G, B),
161 dst: &mut [u8],
162 rle: bool,
163 ) -> Result<usize, BitmapEncodeError>
164 where
165 R: Iterator<Item = u8>,
166 G: Iterator<Item = u8>,
167 B: Iterator<Item = u8>,
168 {
169 let mut cursor = WriteCursor::new(dst);
170
171 let header = BitmapStreamHeader {
172 enable_rle_compression: rle,
173 use_alpha: false,
174 color_plane_definition: ColorPlaneDefinition::Argb,
175 };
176
177 ironrdp_core::encode_cursor(&header, &mut cursor).map_err(BitmapEncodeError::Encode)?;
178
179 if rle {
180 compress_8bpp_plane(r, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::Rle)?;
181 compress_8bpp_plane(g, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::Rle)?;
182 compress_8bpp_plane(b, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::Rle)?;
183 } else {
184 let remaining = cursor.len();
185 let needed = self.width * self.height * 3 + 1;
186 if needed > remaining {
187 return Err(BitmapEncodeError::Encode(not_enough_bytes_err(
188 "BitmapStreamData",
189 remaining,
190 needed,
191 )));
192 }
193
194 for byte in r.chain(g).chain(b) {
195 cursor.write_u8(byte);
196 }
197 cursor.write_u8(0u8);
198 }
199
200 Ok(cursor.pos())
201 }
202
203 pub fn encode_pixels_stream<'a, I, F>(
204 &mut self,
205 data: I,
206 dst: &mut [u8],
207 rle: bool,
208 ) -> Result<usize, BitmapEncodeError>
209 where
210 F: PixelFormat,
211 I: Iterator<Item = &'a [u8]> + Clone,
212 {
213 let r = data.clone().map(F::r);
214 let g = data.clone().map(F::g);
215 let b = data.map(F::b);
216
217 self.encode_channels_stream((r, g, b), dst, rle)
218 }
219
220 pub fn encode_bitmap<F>(&mut self, src: &[u8], dst: &mut [u8], rle: bool) -> Result<usize, BitmapEncodeError>
221 where
222 F: PixelFormat,
223 {
224 let r = src.chunks_exact(F::STRIDE).map(F::r);
225 let g = src.chunks_exact(F::STRIDE).map(F::g);
226 let b = src.chunks_exact(F::STRIDE).map(F::b);
227
228 self.encode_channels_stream((r, g, b), dst, rle)
229 }
230
231 pub fn encode_channels_stream_alpha<R, G, B, A>(
232 &mut self,
233 (r, g, b, a): (R, G, B, A),
234 dst: &mut [u8],
235 rle: bool,
236 ) -> Result<usize, BitmapEncodeError>
237 where
238 R: Iterator<Item = u8>,
239 G: Iterator<Item = u8>,
240 B: Iterator<Item = u8>,
241 A: Iterator<Item = u8>,
242 {
243 let mut cursor = WriteCursor::new(dst);
244
245 let header = BitmapStreamHeader {
246 enable_rle_compression: rle,
247 use_alpha: false,
248 color_plane_definition: ColorPlaneDefinition::Argb,
249 };
250
251 ironrdp_core::encode_cursor(&header, &mut cursor).map_err(BitmapEncodeError::Encode)?;
252
253 if rle {
254 compress_8bpp_plane(a, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::rle)?;
255 compress_8bpp_plane(r, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::rle)?;
256 compress_8bpp_plane(g, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::rle)?;
257 compress_8bpp_plane(b, &mut cursor, self.width, self.height).map_err(BitmapEncodeError::rle)?;
258 } else {
259 let remaining = cursor.len();
260 let needed = self.width * self.height * 4 + 1;
261 if needed > remaining {
262 return Err(BitmapEncodeError::Encode(not_enough_bytes_err(
263 "BitmapStreamData",
264 remaining,
265 needed,
266 )));
267 }
268
269 for byte in a.chain(r).chain(g).chain(b) {
270 cursor.write_u8(byte);
271 }
272 cursor.write_u8(0u8);
273 }
274
275 Ok(cursor.pos())
276 }
277
278 pub fn encode_bitmap_alpha<F>(&mut self, src: &[u8], dst: &mut [u8], rle: bool) -> Result<usize, BitmapEncodeError>
279 where
280 F: PixelFormat + PixelAlpha,
281 {
282 let r = src.chunks_exact(F::STRIDE).map(F::r);
283 let g = src.chunks_exact(F::STRIDE).map(F::g);
284 let b = src.chunks_exact(F::STRIDE).map(F::b);
285 let a = src.chunks_exact(F::STRIDE).map(F::a);
286
287 self.encode_channels_stream_alpha((r, g, b, a), dst, rle)
288 }
289}