2
* FreeRDP: A Remote Desktop Protocol Client
5
* Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
11
* http://www.apache.org/licenses/LICENSE-2.0
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
20
#include <freerdp/utils/stream.h>
21
#include <freerdp/utils/memory.h>
22
#include <freerdp/codec/color.h>
24
#include <freerdp/codec/bitmap.h>
27
RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
28
http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
30
http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
33
#define REGULAR_BG_RUN 0x00
34
#define MEGA_MEGA_BG_RUN 0xF0
35
#define REGULAR_FG_RUN 0x01
36
#define MEGA_MEGA_FG_RUN 0xF1
37
#define LITE_SET_FG_FG_RUN 0x0C
38
#define MEGA_MEGA_SET_FG_RUN 0xF6
39
#define LITE_DITHERED_RUN 0x0E
40
#define MEGA_MEGA_DITHERED_RUN 0xF8
41
#define REGULAR_COLOR_RUN 0x03
42
#define MEGA_MEGA_COLOR_RUN 0xF3
43
#define REGULAR_FGBG_IMAGE 0x02
44
#define MEGA_MEGA_FGBG_IMAGE 0xF2
45
#define LITE_SET_FG_FGBG_IMAGE 0x0D
46
#define MEGA_MEGA_SET_FGBG_IMAGE 0xF7
47
#define REGULAR_COLOR_IMAGE 0x04
48
#define MEGA_MEGA_COLOR_IMAGE 0xF4
49
#define SPECIAL_FGBG_1 0xF9
50
#define SPECIAL_FGBG_2 0xFA
51
#define SPECIAL_WHITE 0xFD
52
#define SPECIAL_BLACK 0xFE
54
#define BLACK_PIXEL 0x000000
55
#define WHITE_PIXEL 0xFFFFFF
59
static const uint8 g_MaskBit0 = 0x01; /* Least significant bit */
60
static const uint8 g_MaskBit1 = 0x02;
61
static const uint8 g_MaskBit2 = 0x04;
62
static const uint8 g_MaskBit3 = 0x08;
63
static const uint8 g_MaskBit4 = 0x10;
64
static const uint8 g_MaskBit5 = 0x20;
65
static const uint8 g_MaskBit6 = 0x40;
66
static const uint8 g_MaskBit7 = 0x80; /* Most significant bit */
68
static const uint8 g_MaskSpecialFgBg1 = 0x03;
69
static const uint8 g_MaskSpecialFgBg2 = 0x05;
71
static const uint8 g_MaskRegularRunLength = 0x1F;
72
static const uint8 g_MaskLiteRunLength = 0x0F;
75
* Reads the supplied order header and extracts the compression
78
static uint32 ExtractCodeId(uint8 bOrderHdr)
84
case MEGA_MEGA_BG_RUN:
85
case MEGA_MEGA_FG_RUN:
86
case MEGA_MEGA_SET_FG_RUN:
87
case MEGA_MEGA_DITHERED_RUN:
88
case MEGA_MEGA_COLOR_RUN:
89
case MEGA_MEGA_FGBG_IMAGE:
90
case MEGA_MEGA_SET_FGBG_IMAGE:
91
case MEGA_MEGA_COLOR_IMAGE:
98
code = bOrderHdr >> 5;
103
case REGULAR_COLOR_RUN:
104
case REGULAR_FGBG_IMAGE:
105
case REGULAR_COLOR_IMAGE:
108
return bOrderHdr >> 4;
112
* Extract the run length of a compression order.
114
static uint32 ExtractRunLength(uint32 code, uint8* pbOrderHdr, uint32* advance)
123
case REGULAR_FGBG_IMAGE:
124
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
127
runLength = (*(pbOrderHdr + 1)) + 1;
132
runLength = runLength * 8;
135
case LITE_SET_FG_FGBG_IMAGE:
136
runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
139
runLength = (*(pbOrderHdr + 1)) + 1;
144
runLength = runLength * 8;
149
case REGULAR_COLOR_RUN:
150
case REGULAR_COLOR_IMAGE:
151
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
154
/* An extended (MEGA) run. */
155
runLength = (*(pbOrderHdr + 1)) + 32;
159
case LITE_SET_FG_FG_RUN:
160
case LITE_DITHERED_RUN:
161
runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
164
/* An extended (MEGA) run. */
165
runLength = (*(pbOrderHdr + 1)) + 16;
169
case MEGA_MEGA_BG_RUN:
170
case MEGA_MEGA_FG_RUN:
171
case MEGA_MEGA_SET_FG_RUN:
172
case MEGA_MEGA_DITHERED_RUN:
173
case MEGA_MEGA_COLOR_RUN:
174
case MEGA_MEGA_FGBG_IMAGE:
175
case MEGA_MEGA_SET_FGBG_IMAGE:
176
case MEGA_MEGA_COLOR_IMAGE:
177
runLength = ((uint16) pbOrderHdr[1]) | ((uint16) (pbOrderHdr[2] << 8));
185
#define UNROLL_COUNT 4
186
#define UNROLL(_exp) do { _exp _exp _exp _exp } while (0)
188
#undef DESTWRITEPIXEL
193
#undef WRITEFGBGIMAGE
194
#undef WRITEFIRSTLINEFGBGIMAGE
197
#define DESTWRITEPIXEL(_buf, _pix) (_buf)[0] = (uint8)(_pix)
198
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
199
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0]
200
#define DESTNEXTPIXEL(_buf) _buf += 1
201
#define SRCNEXTPIXEL(_buf) _buf += 1
202
#define WRITEFGBGIMAGE WriteFgBgImage8to8
203
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
204
#define RLEDECOMPRESS RleDecompress8to8
206
#include "include/bitmap.c"
208
#undef DESTWRITEPIXEL
213
#undef WRITEFGBGIMAGE
214
#undef WRITEFIRSTLINEFGBGIMAGE
217
#define DESTWRITEPIXEL(_buf, _pix) ((uint16*)(_buf))[0] = (uint16)(_pix)
218
#define DESTREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0]
219
#define SRCREADPIXEL(_pix, _buf) _pix = ((uint16*)(_buf))[0]
220
#define DESTNEXTPIXEL(_buf) _buf += 2
221
#define SRCNEXTPIXEL(_buf) _buf += 2
222
#define WRITEFGBGIMAGE WriteFgBgImage16to16
223
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
224
#define RLEDECOMPRESS RleDecompress16to16
226
#include "include/bitmap.c"
228
#undef DESTWRITEPIXEL
233
#undef WRITEFGBGIMAGE
234
#undef WRITEFIRSTLINEFGBGIMAGE
237
#define DESTWRITEPIXEL(_buf, _pix) do { (_buf)[0] = (uint8)(_pix); \
238
(_buf)[1] = (uint8)((_pix) >> 8); (_buf)[2] = (uint8)((_pix) >> 16); } while (0)
239
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
241
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
243
#define DESTNEXTPIXEL(_buf) _buf += 3
244
#define SRCNEXTPIXEL(_buf) _buf += 3
245
#define WRITEFGBGIMAGE WriteFgBgImage24to24
246
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
247
#define RLEDECOMPRESS RleDecompress24to24
249
#include "include/bitmap.c"
251
#define IN_UINT8_MV(_p) (*((_p)++))
254
* decompress an RLE color plane
257
static int process_rle_plane(uint8* in, int width, int height, uint8* out, int size)
276
while (indexh < height)
278
out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
284
while (indexw < width)
286
code = IN_UINT8_MV(in);
288
collen = (code >> 4) & 0xf;
289
revcode = (replen << 4) | collen;
290
if ((revcode <= 47) && (revcode >= 16))
297
color = IN_UINT8_MV(in);
314
while (indexw < width)
316
code = IN_UINT8_MV(in);
318
collen = (code >> 4) & 0xf;
319
revcode = (replen << 4) | collen;
320
if ((revcode <= 47) && (revcode >= 16))
339
x = last_line[indexw * 4] + color;
347
x = last_line[indexw * 4] + color;
356
last_line = this_line;
358
return (int) (in - org_in);
362
* process a raw color plane
364
static int process_raw_plane(uint8* srcData, int width, int height, uint8* dstData, int size)
368
for (y = 0; y < height; y++)
370
for (x = 0; x < width; x++)
372
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
376
return (width * height);
380
* 4 byte bitmap decompress
383
static boolean bitmap_decompress4(uint8* srcData, uint8* dstData, int width, int height, int size)
391
code = IN_UINT8_MV(srcData);
395
NoAlpha = code & 0x20;
399
bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed);
400
total_processed += bytes_processed;
401
srcData += bytes_processed;
406
bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed);
407
total_processed += bytes_processed;
408
srcData += bytes_processed;
410
bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed);
411
total_processed += bytes_processed;
412
srcData += bytes_processed;
414
bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed);
415
total_processed += bytes_processed;
419
bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed);
420
total_processed += bytes_processed;
421
srcData += bytes_processed;
423
bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed);
424
total_processed += bytes_processed;
425
srcData += bytes_processed;
427
bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed);
428
total_processed += bytes_processed + 1;
431
return (size == total_processed) ? true : false;
436
* bitmap decompression routine
438
boolean bitmap_decompress(uint8* srcData, uint8* dstData, int width, int height, int size, int srcBpp, int dstBpp)
440
if (srcBpp == 16 && dstBpp == 16)
442
RleDecompress16to16(srcData, size, dstData, width * 2, width, height);
443
freerdp_bitmap_flip(dstData, dstData, width * 2, height);
445
else if (srcBpp == 32 && dstBpp == 32)
447
if (!bitmap_decompress4(srcData, dstData, width, height, size))
450
else if (srcBpp == 15 && dstBpp == 15)
452
RleDecompress16to16(srcData, size, dstData, width * 2, width, height);
453
freerdp_bitmap_flip(dstData, dstData, width * 2, height);
455
else if (srcBpp == 8 && dstBpp == 8)
457
RleDecompress8to8(srcData, size, dstData, width, width, height);
458
freerdp_bitmap_flip(dstData, dstData, width, height);
460
else if (srcBpp == 24 && dstBpp == 24)
462
RleDecompress24to24(srcData, size, dstData, width * 3, width, height);
463
freerdp_bitmap_flip(dstData, dstData, width * 3, height);