2
* FreeRDP: A Remote Desktop Protocol Implementation
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.
24
#include <winpr/stream.h>
25
#include <freerdp/codec/color.h>
27
#include <freerdp/codec/bitmap.h>
30
RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
31
http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
33
http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
36
#define REGULAR_BG_RUN 0x00
37
#define MEGA_MEGA_BG_RUN 0xF0
38
#define REGULAR_FG_RUN 0x01
39
#define MEGA_MEGA_FG_RUN 0xF1
40
#define LITE_SET_FG_FG_RUN 0x0C
41
#define MEGA_MEGA_SET_FG_RUN 0xF6
42
#define LITE_DITHERED_RUN 0x0E
43
#define MEGA_MEGA_DITHERED_RUN 0xF8
44
#define REGULAR_COLOR_RUN 0x03
45
#define MEGA_MEGA_COLOR_RUN 0xF3
46
#define REGULAR_FGBG_IMAGE 0x02
47
#define MEGA_MEGA_FGBG_IMAGE 0xF2
48
#define LITE_SET_FG_FGBG_IMAGE 0x0D
49
#define MEGA_MEGA_SET_FGBG_IMAGE 0xF7
50
#define REGULAR_COLOR_IMAGE 0x04
51
#define MEGA_MEGA_COLOR_IMAGE 0xF4
52
#define SPECIAL_FGBG_1 0xF9
53
#define SPECIAL_FGBG_2 0xFA
54
#define SPECIAL_WHITE 0xFD
55
#define SPECIAL_BLACK 0xFE
57
#define BLACK_PIXEL 0x000000
58
#define WHITE_PIXEL 0xFFFFFF
62
static const BYTE g_MaskBit0 = 0x01; /* Least significant bit */
63
static const BYTE g_MaskBit1 = 0x02;
64
static const BYTE g_MaskBit2 = 0x04;
65
static const BYTE g_MaskBit3 = 0x08;
66
static const BYTE g_MaskBit4 = 0x10;
67
static const BYTE g_MaskBit5 = 0x20;
68
static const BYTE g_MaskBit6 = 0x40;
69
static const BYTE g_MaskBit7 = 0x80; /* Most significant bit */
71
static const BYTE g_MaskSpecialFgBg1 = 0x03;
72
static const BYTE g_MaskSpecialFgBg2 = 0x05;
74
static const BYTE g_MaskRegularRunLength = 0x1F;
75
static const BYTE g_MaskLiteRunLength = 0x0F;
78
* Reads the supplied order header and extracts the compression
81
static UINT32 ExtractCodeId(BYTE bOrderHdr)
87
case MEGA_MEGA_BG_RUN:
88
case MEGA_MEGA_FG_RUN:
89
case MEGA_MEGA_SET_FG_RUN:
90
case MEGA_MEGA_DITHERED_RUN:
91
case MEGA_MEGA_COLOR_RUN:
92
case MEGA_MEGA_FGBG_IMAGE:
93
case MEGA_MEGA_SET_FGBG_IMAGE:
94
case MEGA_MEGA_COLOR_IMAGE:
101
code = bOrderHdr >> 5;
106
case REGULAR_COLOR_RUN:
107
case REGULAR_FGBG_IMAGE:
108
case REGULAR_COLOR_IMAGE:
111
return bOrderHdr >> 4;
115
* Extract the run length of a compression order.
117
static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance)
126
case REGULAR_FGBG_IMAGE:
127
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
130
runLength = (*(pbOrderHdr + 1)) + 1;
135
runLength = runLength * 8;
138
case LITE_SET_FG_FGBG_IMAGE:
139
runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
142
runLength = (*(pbOrderHdr + 1)) + 1;
147
runLength = runLength * 8;
152
case REGULAR_COLOR_RUN:
153
case REGULAR_COLOR_IMAGE:
154
runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
157
/* An extended (MEGA) run. */
158
runLength = (*(pbOrderHdr + 1)) + 32;
162
case LITE_SET_FG_FG_RUN:
163
case LITE_DITHERED_RUN:
164
runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
167
/* An extended (MEGA) run. */
168
runLength = (*(pbOrderHdr + 1)) + 16;
172
case MEGA_MEGA_BG_RUN:
173
case MEGA_MEGA_FG_RUN:
174
case MEGA_MEGA_SET_FG_RUN:
175
case MEGA_MEGA_DITHERED_RUN:
176
case MEGA_MEGA_COLOR_RUN:
177
case MEGA_MEGA_FGBG_IMAGE:
178
case MEGA_MEGA_SET_FGBG_IMAGE:
179
case MEGA_MEGA_COLOR_IMAGE:
180
runLength = ((UINT16) pbOrderHdr[1]) | ((UINT16) (pbOrderHdr[2] << 8));
188
#define UNROLL_COUNT 4
189
#define UNROLL(_exp) do { _exp _exp _exp _exp } while (0)
191
#undef DESTWRITEPIXEL
196
#undef WRITEFGBGIMAGE
197
#undef WRITEFIRSTLINEFGBGIMAGE
200
#define DESTWRITEPIXEL(_buf, _pix) (_buf)[0] = (BYTE)(_pix)
201
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
202
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0]
203
#define DESTNEXTPIXEL(_buf) _buf += 1
204
#define SRCNEXTPIXEL(_buf) _buf += 1
205
#define WRITEFGBGIMAGE WriteFgBgImage8to8
206
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
207
#define RLEDECOMPRESS RleDecompress8to8
209
#include "include/bitmap.c"
211
#undef DESTWRITEPIXEL
216
#undef WRITEFGBGIMAGE
217
#undef WRITEFIRSTLINEFGBGIMAGE
220
#define DESTWRITEPIXEL(_buf, _pix) ((UINT16*)(_buf))[0] = (UINT16)(_pix)
221
#define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
222
#define SRCREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
223
#define DESTNEXTPIXEL(_buf) _buf += 2
224
#define SRCNEXTPIXEL(_buf) _buf += 2
225
#define WRITEFGBGIMAGE WriteFgBgImage16to16
226
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
227
#define RLEDECOMPRESS RleDecompress16to16
229
#include "include/bitmap.c"
231
#undef DESTWRITEPIXEL
236
#undef WRITEFGBGIMAGE
237
#undef WRITEFIRSTLINEFGBGIMAGE
240
#define DESTWRITEPIXEL(_buf, _pix) do { (_buf)[0] = (BYTE)(_pix); \
241
(_buf)[1] = (BYTE)((_pix) >> 8); (_buf)[2] = (BYTE)((_pix) >> 16); } while (0)
242
#define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
244
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
246
#define DESTNEXTPIXEL(_buf) _buf += 3
247
#define SRCNEXTPIXEL(_buf) _buf += 3
248
#define WRITEFGBGIMAGE WriteFgBgImage24to24
249
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
250
#define RLEDECOMPRESS RleDecompress24to24
252
#include "include/bitmap.c"
254
#define IN_UINT8_MV(_p) (*((_p)++))
257
* decompress an RLE color plane
260
static int process_rle_plane(BYTE* in, int width, int height, BYTE* out, int size)
279
while (indexh < height)
281
out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
287
while (indexw < width)
289
code = IN_UINT8_MV(in);
291
collen = (code >> 4) & 0xf;
292
revcode = (replen << 4) | collen;
293
if ((revcode <= 47) && (revcode >= 16))
300
color = IN_UINT8_MV(in);
317
while (indexw < width)
319
code = IN_UINT8_MV(in);
321
collen = (code >> 4) & 0xf;
322
revcode = (replen << 4) | collen;
323
if ((revcode <= 47) && (revcode >= 16))
342
x = last_line[indexw * 4] + color;
350
x = last_line[indexw * 4] + color;
359
last_line = this_line;
361
return (int) (in - org_in);
365
* process a raw color plane
367
static int process_raw_plane(BYTE* srcData, int width, int height, BYTE* dstData, int size)
371
for (y = 0; y < height; y++)
373
for (x = 0; x < width; x++)
375
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
379
return (width * height);
383
* 4 byte bitmap decompress
386
static BOOL bitmap_decompress4(BYTE* srcData, BYTE* dstData, int width, int height, int size)
394
code = IN_UINT8_MV(srcData);
398
NoAlpha = code & 0x20;
402
bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed);
403
total_processed += bytes_processed;
404
srcData += bytes_processed;
409
bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed);
410
total_processed += bytes_processed;
411
srcData += bytes_processed;
413
bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed);
414
total_processed += bytes_processed;
415
srcData += bytes_processed;
417
bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed);
418
total_processed += bytes_processed;
422
bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed);
423
total_processed += bytes_processed;
424
srcData += bytes_processed;
426
bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed);
427
total_processed += bytes_processed;
428
srcData += bytes_processed;
430
bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed);
431
total_processed += bytes_processed + 1;
434
return (size == total_processed) ? TRUE : FALSE;
439
* bitmap decompression routine
441
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
445
if (srcBpp == 16 && dstBpp == 16)
447
TmpBfr = (BYTE*) malloc(width * height * 2);
448
RleDecompress16to16(srcData, size, TmpBfr, width * 2, width, height);
449
freerdp_bitmap_flip(TmpBfr, dstData, width * 2, height);
452
else if (srcBpp == 32 && dstBpp == 32)
454
if (!bitmap_decompress4(srcData, dstData, width, height, size))
457
else if (srcBpp == 15 && dstBpp == 15)
459
TmpBfr = (BYTE*) malloc(width * height * 2);
460
RleDecompress16to16(srcData, size, TmpBfr, width * 2, width, height);
461
freerdp_bitmap_flip(TmpBfr, dstData, width * 2, height);
464
else if (srcBpp == 8 && dstBpp == 8)
466
TmpBfr = (BYTE*) malloc(width * height);
467
RleDecompress8to8(srcData, size, TmpBfr, width, width, height);
468
freerdp_bitmap_flip(TmpBfr, dstData, width, height);
471
else if (srcBpp == 24 && dstBpp == 24)
473
TmpBfr = (BYTE*) malloc(width * height * 3);
474
RleDecompress24to24(srcData, size, TmpBfr, width * 3, width, height);
475
freerdp_bitmap_flip(TmpBfr, dstData, width * 3, height);