1use model::error::{RdpResult, Error, RdpError, RdpErrorKind};
2use std::io::{Cursor, Read};
3use byteorder::{ReadBytesExt, LittleEndian};
4
5fn process_plane(input: &mut dyn Read, width: u32, height: u32, output: &mut [u8]) -> RdpResult<()> {
11 let mut indexw;
12 let mut indexh= 0;
13 let mut code ;
14 let mut collen;
15 let mut replen;
16 let mut color:i8;
17 let mut x;
18 let mut revcode;
19
20 let mut this_line: u32;
21 let mut last_line: u32 = 0;
22
23 while indexh < height {
24 let mut out = (width * height * 4) - ((indexh + 1) * width * 4);
25 color = 0;
26 this_line = out;
27 indexw = 0;
28 if last_line == 0 {
29 while indexw < width {
30 code = input.read_u8()?;
31 replen = code & 0xf;
32 collen = (code >> 4) & 0xf;
33 revcode = (replen << 4) | collen;
34 if (revcode <= 47) && (revcode >= 16) {
35 replen = revcode;
36 collen = 0;
37 }
38 while collen > 0 {
39 color = input.read_u8()? as i8;
40 output[out as usize] = color as u8;
41 out += 4;
42 indexw += 1;
43 collen -= 1;
44 }
45 while replen > 0 {
46 output[out as usize] = color as u8;
47 out += 4;
48 indexw += 1;
49 replen -= 1;
50 }
51 }
52 }
53 else
54 {
55 while indexw < width {
56 code = input.read_u8()?;
57 replen = code & 0xf;
58 collen = (code >> 4) & 0xf;
59 revcode = (replen << 4) | collen;
60 if (revcode <= 47) && (revcode >= 16) {
61 replen = revcode;
62 collen = 0;
63 }
64 while collen > 0 {
65 x = input.read_u8()?;
66 if x & 1 != 0{
67 x = x >> 1;
68 x = x + 1;
69 color = -(x as i32) as i8;
70 }
71 else
72 {
73 x = x >> 1;
74 color = x as i8;
75 }
76 x = (output[(last_line + (indexw * 4)) as usize] as i32 + color as i32) as u8;
77 output[out as usize] = x;
78 out += 4;
79 indexw += 1;
80 collen -= 1;
81 }
82 while replen > 0 {
83 x = (output[(last_line + (indexw * 4)) as usize] as i32 + color as i32) as u8;
84 output[out as usize] = x;
85 out += 4;
86 indexw += 1;
87 replen -= 1;
88 }
89 }
90 }
91 indexh += 1;
92 last_line = this_line;
93 }
94 Ok(())
95}
96
97pub fn rle_32_decompress(input: &[u8], width: u32, height: u32, output: &mut [u8]) -> RdpResult<()> {
99 let mut input_cursor = Cursor::new(input);
100
101 if input_cursor.read_u8()? != 0x10 {
102 return Err(Error::RdpError(RdpError::new(RdpErrorKind::UnexpectedType, "Bad header")))
103 }
104
105 process_plane(&mut input_cursor, width, height, &mut output[3..])?;
106 process_plane(&mut input_cursor, width, height, &mut output[2..])?;
107 process_plane(&mut input_cursor, width, height, &mut output[1..])?;
108 process_plane(&mut input_cursor, width, height, &mut output[0..])?;
109
110 Ok(())
111}
112
113macro_rules! repeat {
114 ($expr:expr, $count:expr, $x:expr, $width:expr) => {
115 while (($count & !0x7) != 0) && ($x + 8) < $width {
116 $expr; $count -= 1; $x += 1;
117 $expr; $count -= 1; $x += 1;
118 $expr; $count -= 1; $x += 1;
119 $expr; $count -= 1; $x += 1;
120 $expr; $count -= 1; $x += 1;
121 $expr; $count -= 1; $x += 1;
122 $expr; $count -= 1; $x += 1;
123 $expr; $count -= 1; $x += 1;
124 }
125 while $count > 0 && $x < $width {
126 $expr;
127 $count -= 1;
128 $x += 1;
129 }
130 };
131}
132
133pub fn rle_16_decompress(input: &[u8], width: usize, mut height: usize, output: &mut [u16]) -> RdpResult<()> {
134 let mut input_cursor = Cursor::new(input);
135
136 let mut code: u8;
137 let mut opcode: u8;
138 let mut lastopcode: u8 = 0xFF;
139 let mut count: u16;
140 let mut offset: u16;
141 let mut isfillormix;
142 let mut insertmix = false;
143 let mut x: usize = width;
144 let mut prevline : Option<usize> = None;
145 let mut line : Option<usize> = None;
146 let mut colour1= 0;
147 let mut colour2 = 0;
148 let mut mix = 0xffff;
149 let mut mask:u8 = 0;
150 let mut fom_mask : u8;
151 let mut mixmask:u8;
152 let mut bicolour = false;
153
154 while (input_cursor.position() as usize) < input.len() {
155 fom_mask = 0;
156 code = input_cursor.read_u8()?;
157 opcode = code >> 4;
158
159 match opcode {
160 0xC | 0xD | 0xE => {
161 opcode -= 6;
162 count = (code & 0xf) as u16;
163 offset = 16;
164 }
165 0xF => {
166 opcode = code & 0xf;
167 if opcode < 9 {
168 count = input_cursor.read_u16::<LittleEndian>()?
169 } else if opcode < 0xb {
170 count = 8
171 } else {
172 count = 1
173 }
174 offset = 0;
175 }
176 _ => {
177 opcode >>= 1;
178 count = (code & 0x1f) as u16;
179 offset = 32;
180 }
181 }
182
183 if offset != 0 {
184 isfillormix = (opcode == 2) || (opcode == 7);
185 if count == 0 {
186 if isfillormix {
187 count = input_cursor.read_u8()? as u16 + 1;
188 } else {
189 count = input_cursor.read_u8()? as u16 + offset;
190 }
191 } else if isfillormix {
192 count <<= 3;
193 }
194 }
195
196 match opcode {
197 0 => {
198 if lastopcode == opcode && !(x == width && prevline == None) {
199 insertmix = true;
200 }
201 },
202 8 => {
203 colour1 = input_cursor.read_u16::<LittleEndian>()?;
204 colour2 = input_cursor.read_u16::<LittleEndian>()?;
205 },
206 3 => {
207 colour2 = input_cursor.read_u16::<LittleEndian>()?;
208 },
209 6 | 7 => {
210 mix = input_cursor.read_u16::<LittleEndian>()?;
211 opcode -= 5;
212 }
213 9 => {
214 mask = 0x03;
215 opcode = 0x02;
216 fom_mask = 3;
217 },
218 0xa => {
219 mask = 0x05;
220 opcode = 0x02;
221 fom_mask = 5;
222 }
223 _ => ()
224 }
225 lastopcode = opcode;
226 mixmask = 0;
227
228 while count > 0 {
229 if x >= width {
230 if height <= 0 {
231 return Err(Error::RdpError(RdpError::new(RdpErrorKind::InvalidData, "error during decompress")))
232 }
233 x = 0;
234 height -= 1;
235 prevline = line;
236 line = Some(height * width);
237 }
238
239 match opcode {
240 0 => {
241 if insertmix {
242 if let Some(e) = prevline {
243 output[line.unwrap() + x] = output[e + x] ^ mix;
244 }
245 else {
246 output[line.unwrap() + x] = mix;
247 }
248 insertmix = false;
249 count -= 1;
250 x += 1;
251 }
252
253 if let Some(e) = prevline {
254 repeat!(output[line.unwrap() + x] = output[e + x], count, x, width);
255 }
256 else {
257 repeat!(output[line.unwrap() + x] = 0, count, x, width);
258 }
259 },
260 1 => {
261 if let Some(e) = prevline {
262 repeat!(output[line.unwrap() + x] = output[e + x] ^ mix, count, x, width);
263 }
264 else {
265 repeat!(output[line.unwrap() + x] = mix, count, x, width);
266 }
267 },
268 2 => {
269 if let Some(e) = prevline {
270 repeat!({
271 mixmask <<= 1;
272 if mixmask == 0 {
273 mask = if fom_mask != 0 { fom_mask } else { input_cursor.read_u8()? };
274 mixmask = 1;
275 }
276 if (mask & mixmask) != 0 {
277 output[line.unwrap() + x] = output[e + x] ^ mix;
278 }
279 else {
280 output[line.unwrap() + x] = output[e + x];
281 }
282 }, count, x, width);
283 }
284 else {
285 repeat!({
286 mixmask <<= 1;
287 if mixmask == 0 {
288 mask = if fom_mask != 0 { fom_mask } else { input_cursor.read_u8()? };
289 mixmask = 1;
290 }
291 if (mask & mixmask) != 0 {
292 output[line.unwrap() + x] = mix;
293 }
294 else {
295 output[line.unwrap() + x] = 0;
296 }
297 }, count, x, width);
298 }
299 },
300 3 => {
301 repeat!(output[line.unwrap() + x] = colour2, count, x, width);
302 },
303 4 => {
304 repeat!(output[line.unwrap() + x] = input_cursor.read_u16::<LittleEndian>()?, count, x, width);
305 },
306 8 => {
307 repeat!({
308 if bicolour {
309 output[line.unwrap() + x] = colour2;
310 bicolour = false;
311 } else {
312 output[line.unwrap() + x] = colour1;
313 bicolour = true;
314 count += 1;
315 };
316 }, count, x, width);
317 },
318 0xd => {
319 repeat!(output[line.unwrap() + x] = 0xffff, count, x, width);
320 },
321 0xe => {
322 repeat!(output[line.unwrap() + x] = 0, count, x, width);
323 }
324 _ => panic!("opcode")
325 }
326 }
327 }
328
329 Ok(())
330}
331
332
333pub fn rgb565torgb32(input: &[u16], width: usize, height: usize) -> Vec<u8> {
334 let mut result_32_bpp = vec![0 as u8; width as usize * height as usize * 4];
335 for i in 0..height {
336 for j in 0..width {
337 let index = (i * width + j) as usize;
338 let v = input[index];
339 result_32_bpp[index * 4 + 3] = 0xff;
340 result_32_bpp[index * 4 + 2] = (((((v >> 11) & 0x1f) * 527) + 23) >> 6) as u8;
341 result_32_bpp[index * 4 + 1] = (((((v >> 5) & 0x3f) * 259) + 33) >> 6) as u8;
342 result_32_bpp[index * 4] = ((((v & 0x1f) * 527) + 23) >> 6) as u8;
343 }
344 }
345 result_32_bpp
346}