~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to libfreerdp/codec/bitmap_decode.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.2.5)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20141111122050-7z628f4ab38qxad5
Tags: upstream-1.1.0~git20140921.1.440916e+dfsg1
ImportĀ upstreamĀ versionĀ 1.1.0~git20140921.1.440916e+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * FreeRDP: A Remote Desktop Protocol Implementation
 
3
 * Bitmap Decompression
 
4
 *
 
5
 * Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
 
6
 *
 
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
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
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.
 
18
 */
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <winpr/stream.h>
 
25
#include <freerdp/codec/color.h>
 
26
 
 
27
#include <freerdp/codec/bitmap.h>
 
28
 
 
29
/*
 
30
   RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
 
31
   http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
 
32
   pseudo-code
 
33
   http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
 
34
*/
 
35
 
 
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
 
56
 
 
57
#define BLACK_PIXEL 0x000000
 
58
#define WHITE_PIXEL 0xFFFFFF
 
59
 
 
60
typedef UINT32 PIXEL;
 
61
 
 
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 */
 
70
 
 
71
static const BYTE g_MaskSpecialFgBg1 = 0x03;
 
72
static const BYTE g_MaskSpecialFgBg2 = 0x05;
 
73
 
 
74
static const BYTE g_MaskRegularRunLength = 0x1F;
 
75
static const BYTE g_MaskLiteRunLength = 0x0F;
 
76
 
 
77
/**
 
78
 * Reads the supplied order header and extracts the compression
 
79
 * order code ID.
 
80
 */
 
81
static UINT32 ExtractCodeId(BYTE bOrderHdr)
 
82
{
 
83
        int code;
 
84
 
 
85
        switch (bOrderHdr)
 
86
        {
 
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:
 
95
                case SPECIAL_FGBG_1:
 
96
                case SPECIAL_FGBG_2:
 
97
                case SPECIAL_WHITE:
 
98
                case SPECIAL_BLACK:
 
99
                        return bOrderHdr;
 
100
        }
 
101
        code = bOrderHdr >> 5;
 
102
        switch (code)
 
103
        {
 
104
                case REGULAR_BG_RUN:
 
105
                case REGULAR_FG_RUN:
 
106
                case REGULAR_COLOR_RUN:
 
107
                case REGULAR_FGBG_IMAGE:
 
108
                case REGULAR_COLOR_IMAGE:
 
109
                        return code;
 
110
        }
 
111
        return bOrderHdr >> 4;
 
112
}
 
113
 
 
114
/**
 
115
 * Extract the run length of a compression order.
 
116
 */
 
117
static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance)
 
118
{
 
119
        UINT32 runLength;
 
120
        UINT32 ladvance;
 
121
 
 
122
        ladvance = 1;
 
123
        runLength = 0;
 
124
        switch (code)
 
125
        {
 
126
                case REGULAR_FGBG_IMAGE:
 
127
                        runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
 
128
                        if (runLength == 0)
 
129
                        {
 
130
                                runLength = (*(pbOrderHdr + 1)) + 1;
 
131
                                ladvance += 1;
 
132
                        }
 
133
                        else
 
134
                        {
 
135
                                runLength = runLength * 8;
 
136
                        }
 
137
                        break;
 
138
                case LITE_SET_FG_FGBG_IMAGE:
 
139
                        runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
 
140
                        if (runLength == 0)
 
141
                        {
 
142
                                runLength = (*(pbOrderHdr + 1)) + 1;
 
143
                                ladvance += 1;
 
144
                        }
 
145
                        else
 
146
                        {
 
147
                                runLength = runLength * 8;
 
148
                        }
 
149
                        break;
 
150
                case REGULAR_BG_RUN:
 
151
                case REGULAR_FG_RUN:
 
152
                case REGULAR_COLOR_RUN:
 
153
                case REGULAR_COLOR_IMAGE:
 
154
                        runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
 
155
                        if (runLength == 0)
 
156
                        {
 
157
                                /* An extended (MEGA) run. */
 
158
                                runLength = (*(pbOrderHdr + 1)) + 32;
 
159
                                ladvance += 1;
 
160
                        }
 
161
                        break;
 
162
                case LITE_SET_FG_FG_RUN:
 
163
                case LITE_DITHERED_RUN:
 
164
                        runLength = (*pbOrderHdr) & g_MaskLiteRunLength;
 
165
                        if (runLength == 0)
 
166
                        {
 
167
                                /* An extended (MEGA) run. */
 
168
                                runLength = (*(pbOrderHdr + 1)) + 16;
 
169
                                ladvance += 1;
 
170
                        }
 
171
                        break;
 
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));
 
181
                        ladvance += 2;
 
182
                        break;
 
183
        }
 
184
        *advance = ladvance;
 
185
        return runLength;
 
186
}
 
187
 
 
188
#define UNROLL_COUNT 4
 
189
#define UNROLL(_exp) do { _exp _exp _exp _exp } while (0)
 
190
 
 
191
#undef DESTWRITEPIXEL
 
192
#undef DESTREADPIXEL
 
193
#undef SRCREADPIXEL
 
194
#undef DESTNEXTPIXEL
 
195
#undef SRCNEXTPIXEL
 
196
#undef WRITEFGBGIMAGE
 
197
#undef WRITEFIRSTLINEFGBGIMAGE
 
198
#undef RLEDECOMPRESS
 
199
#undef RLEEXTRA
 
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
 
208
#define RLEEXTRA
 
209
#include "include/bitmap.c"
 
210
 
 
211
#undef DESTWRITEPIXEL
 
212
#undef DESTREADPIXEL
 
213
#undef SRCREADPIXEL
 
214
#undef DESTNEXTPIXEL
 
215
#undef SRCNEXTPIXEL
 
216
#undef WRITEFGBGIMAGE
 
217
#undef WRITEFIRSTLINEFGBGIMAGE
 
218
#undef RLEDECOMPRESS
 
219
#undef RLEEXTRA
 
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
 
228
#define RLEEXTRA
 
229
#include "include/bitmap.c"
 
230
 
 
231
#undef DESTWRITEPIXEL
 
232
#undef DESTREADPIXEL
 
233
#undef SRCREADPIXEL
 
234
#undef DESTNEXTPIXEL
 
235
#undef SRCNEXTPIXEL
 
236
#undef WRITEFGBGIMAGE
 
237
#undef WRITEFIRSTLINEFGBGIMAGE
 
238
#undef RLEDECOMPRESS
 
239
#undef RLEEXTRA
 
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) | \
 
243
  ((_buf)[2] << 16)
 
244
#define SRCREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | \
 
245
  ((_buf)[2] << 16)
 
246
#define DESTNEXTPIXEL(_buf) _buf += 3
 
247
#define SRCNEXTPIXEL(_buf) _buf += 3
 
248
#define WRITEFGBGIMAGE WriteFgBgImage24to24
 
249
#define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
 
250
#define RLEDECOMPRESS RleDecompress24to24
 
251
#define RLEEXTRA
 
252
#include "include/bitmap.c"
 
253
 
 
254
#define IN_UINT8_MV(_p) (*((_p)++))
 
255
 
 
256
/**
 
257
 * decompress an RLE color plane
 
258
 * RDP6_BITMAP_STREAM
 
259
 */
 
260
static int process_rle_plane(BYTE* in, int width, int height, BYTE* out, int size)
 
261
{
 
262
        int indexw;
 
263
        int indexh;
 
264
        int code;
 
265
        int collen;
 
266
        int replen;
 
267
        int color;
 
268
        int x;
 
269
        int revcode;
 
270
        BYTE* last_line;
 
271
        BYTE* this_line;
 
272
        BYTE* org_in;
 
273
        BYTE* org_out;
 
274
 
 
275
        org_in = in;
 
276
        org_out = out;
 
277
        last_line = 0;
 
278
        indexh = 0;
 
279
        while (indexh < height)
 
280
        {
 
281
                out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
 
282
                color = 0;
 
283
                this_line = out;
 
284
                indexw = 0;
 
285
                if (last_line == 0)
 
286
                {
 
287
                        while (indexw < width)
 
288
                        {
 
289
                                code = IN_UINT8_MV(in);
 
290
                                replen = code & 0xf;
 
291
                                collen = (code >> 4) & 0xf;
 
292
                                revcode = (replen << 4) | collen;
 
293
                                if ((revcode <= 47) && (revcode >= 16))
 
294
                                {
 
295
                                        replen = revcode;
 
296
                                        collen = 0;
 
297
                                }
 
298
                                while (collen > 0)
 
299
                                {
 
300
                                        color = IN_UINT8_MV(in);
 
301
                                        *out = color;
 
302
                                        out += 4;
 
303
                                        indexw++;
 
304
                                        collen--;
 
305
                                }
 
306
                                while (replen > 0)
 
307
                                {
 
308
                                        *out = color;
 
309
                                        out += 4;
 
310
                                        indexw++;
 
311
                                        replen--;
 
312
                                }
 
313
                        }
 
314
                }
 
315
                else
 
316
                {
 
317
                        while (indexw < width)
 
318
                        {
 
319
                                code = IN_UINT8_MV(in);
 
320
                                replen = code & 0xf;
 
321
                                collen = (code >> 4) & 0xf;
 
322
                                revcode = (replen << 4) | collen;
 
323
                                if ((revcode <= 47) && (revcode >= 16))
 
324
                                {
 
325
                                        replen = revcode;
 
326
                                        collen = 0;
 
327
                                }
 
328
                                while (collen > 0)
 
329
                                {
 
330
                                        x = IN_UINT8_MV(in);
 
331
                                        if (x & 1)
 
332
                                        {
 
333
                                                x = x >> 1;
 
334
                                                x = x + 1;
 
335
                                                color = -x;
 
336
                                        }
 
337
                                        else
 
338
                                        {
 
339
                                                x = x >> 1;
 
340
                                                color = x;
 
341
                                        }
 
342
                                        x = last_line[indexw * 4] + color;
 
343
                                        *out = x;
 
344
                                        out += 4;
 
345
                                        indexw++;
 
346
                                        collen--;
 
347
                                }
 
348
                                while (replen > 0)
 
349
                                {
 
350
                                        x = last_line[indexw * 4] + color;
 
351
                                        *out = x;
 
352
                                        out += 4;
 
353
                                        indexw++;
 
354
                                        replen--;
 
355
                                }
 
356
                        }
 
357
                }
 
358
                indexh++;
 
359
                last_line = this_line;
 
360
        }
 
361
        return (int) (in - org_in);
 
362
}
 
363
 
 
364
/**
 
365
 * process a raw color plane
 
366
 */
 
367
static int process_raw_plane(BYTE* srcData, int width, int height, BYTE* dstData, int size)
 
368
{
 
369
        int x, y;
 
370
 
 
371
        for (y = 0; y < height; y++)
 
372
        {
 
373
                for (x = 0; x < width; x++)
 
374
                {
 
375
                        dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
 
376
                }
 
377
        }
 
378
 
 
379
        return (width * height);
 
380
}
 
381
 
 
382
/**
 
383
 * 4 byte bitmap decompress
 
384
 * RDP6_BITMAP_STREAM
 
385
 */
 
386
static BOOL bitmap_decompress4(BYTE* srcData, BYTE* dstData, int width, int height, int size)
 
387
{
 
388
        int RLE;
 
389
        int code;
 
390
        int NoAlpha;
 
391
        int bytes_processed;
 
392
        int total_processed;
 
393
 
 
394
        code = IN_UINT8_MV(srcData);
 
395
        RLE = code & 0x10;
 
396
 
 
397
        total_processed = 1;
 
398
        NoAlpha = code & 0x20;
 
399
 
 
400
        if (NoAlpha == 0)
 
401
        {
 
402
                bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed);
 
403
                total_processed += bytes_processed;
 
404
                srcData += bytes_processed;
 
405
        }
 
406
 
 
407
        if (RLE != 0)
 
408
        {
 
409
                bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed);
 
410
                total_processed += bytes_processed;
 
411
                srcData += bytes_processed;
 
412
 
 
413
                bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed);
 
414
                total_processed += bytes_processed;
 
415
                srcData += bytes_processed;
 
416
 
 
417
                bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed);
 
418
                total_processed += bytes_processed;
 
419
        }
 
420
        else
 
421
        {
 
422
                bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed);
 
423
                total_processed += bytes_processed;
 
424
                srcData += bytes_processed;
 
425
 
 
426
                bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed);
 
427
                total_processed += bytes_processed;
 
428
                srcData += bytes_processed;
 
429
 
 
430
                bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed);
 
431
                total_processed += bytes_processed + 1;
 
432
        }
 
433
 
 
434
        return (size == total_processed) ? TRUE : FALSE;
 
435
}
 
436
 
 
437
 
 
438
/**
 
439
 * bitmap decompression routine
 
440
 */
 
441
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
 
442
{
 
443
        BYTE * TmpBfr;
 
444
 
 
445
        if (srcBpp == 16 && dstBpp == 16)
 
446
        {
 
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);
 
450
                free(TmpBfr);
 
451
        }
 
452
        else if (srcBpp == 32 && dstBpp == 32)
 
453
        {
 
454
                if (!bitmap_decompress4(srcData, dstData, width, height, size))
 
455
                        return FALSE;
 
456
        }
 
457
        else if (srcBpp == 15 && dstBpp == 15)
 
458
        {
 
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);
 
462
                free(TmpBfr);
 
463
        }
 
464
        else if (srcBpp == 8 && dstBpp == 8)
 
465
        {
 
466
                TmpBfr = (BYTE*) malloc(width * height);
 
467
                RleDecompress8to8(srcData, size, TmpBfr, width, width, height);
 
468
                freerdp_bitmap_flip(TmpBfr, dstData, width, height);
 
469
                free(TmpBfr);
 
470
        }
 
471
        else if (srcBpp == 24 && dstBpp == 24)
 
472
        {
 
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);
 
476
                free(TmpBfr);
 
477
        }
 
478
        else
 
479
        {
 
480
                return FALSE;
 
481
        }
 
482
 
 
483
        return TRUE;
 
484
}