~ubuntu-branches/ubuntu/raring/freerdp/raring-proposed

« back to all changes in this revision

Viewing changes to libfreerdp-codec/bitmap.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

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