Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-codec / include / bitmap.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * RLE Compressed Bitmap Stream
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 /* do not compile the file directly */
21
22 /**
23  * Write a foreground/background image to a destination buffer.
24  */
25 static uint8* WRITEFGBGIMAGE(uint8* pbDest, uint32 rowDelta,
26         uint8 bitmask, PIXEL fgPel, uint32 cBits)
27 {
28         PIXEL xorPixel;
29
30         DESTREADPIXEL(xorPixel, pbDest - rowDelta);
31         if (bitmask & g_MaskBit0)
32         {
33                 DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
34         }
35         else
36         {
37                 DESTWRITEPIXEL(pbDest, xorPixel);
38         }
39         DESTNEXTPIXEL(pbDest);
40         cBits = cBits - 1;
41         if (cBits > 0)
42         {
43                 DESTREADPIXEL(xorPixel, pbDest - rowDelta);
44                 if (bitmask & g_MaskBit1)
45                 {
46                         DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
47                 }
48                 else
49                 {
50                         DESTWRITEPIXEL(pbDest, xorPixel);
51                 }
52                 DESTNEXTPIXEL(pbDest);
53                 cBits = cBits - 1;
54                 if (cBits > 0)
55                 {
56                         DESTREADPIXEL(xorPixel, pbDest - rowDelta);
57                         if (bitmask & g_MaskBit2)
58                         {
59                                 DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
60                         }
61                         else
62                         {
63                                 DESTWRITEPIXEL(pbDest, xorPixel);
64                         }
65                         DESTNEXTPIXEL(pbDest);
66                         cBits = cBits - 1;
67                         if (cBits > 0)
68                         {
69                                 DESTREADPIXEL(xorPixel, pbDest - rowDelta);
70                                 if (bitmask & g_MaskBit3)
71                                 {
72                                         DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
73                                 }
74                                 else
75                                 {
76                                         DESTWRITEPIXEL(pbDest, xorPixel);
77                                 }
78                                 DESTNEXTPIXEL(pbDest);
79                                 cBits = cBits - 1;
80                                 if (cBits > 0)
81                                 {
82                                         DESTREADPIXEL(xorPixel, pbDest - rowDelta);
83                                         if (bitmask & g_MaskBit4)
84                                         {
85                                                 DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
86                                         }
87                                         else
88                                         {
89                                                 DESTWRITEPIXEL(pbDest, xorPixel);
90                                         }
91                                         DESTNEXTPIXEL(pbDest);
92                                         cBits = cBits - 1;
93                                         if (cBits > 0)
94                                         {
95                                                 DESTREADPIXEL(xorPixel, pbDest - rowDelta);
96                                                 if (bitmask & g_MaskBit5)
97                                                 {
98                                                         DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
99                                                 }
100                                                 else
101                                                 {
102                                                         DESTWRITEPIXEL(pbDest, xorPixel);
103                                                 }
104                                                 DESTNEXTPIXEL(pbDest);
105                                                 cBits = cBits - 1;
106                                                 if (cBits > 0)
107                                                 {
108                                                         DESTREADPIXEL(xorPixel, pbDest - rowDelta);
109                                                         if (bitmask & g_MaskBit6)
110                                                         {
111                                                                 DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
112                                                         }
113                                                         else
114                                                         {
115                                                                 DESTWRITEPIXEL(pbDest, xorPixel);
116                                                         }
117                                                         DESTNEXTPIXEL(pbDest);
118                                                         cBits = cBits - 1;
119                                                         if (cBits > 0)
120                                                         {
121                                                                 DESTREADPIXEL(xorPixel, pbDest - rowDelta);
122                                                                 if (bitmask & g_MaskBit7)
123                                                                 {
124                                                                         DESTWRITEPIXEL(pbDest, xorPixel ^ fgPel);
125                                                                 }
126                                                                 else
127                                                                 {
128                                                                         DESTWRITEPIXEL(pbDest, xorPixel);
129                                                                 }
130                                                                 DESTNEXTPIXEL(pbDest);
131                                                         }
132                                                 }
133                                         }
134                                 }
135                         }
136                 }
137         }
138         return pbDest;
139 }
140
141 /**
142  * Write a foreground/background image to a destination buffer
143  * for the first line of compressed data.
144  */
145 static uint8* WRITEFIRSTLINEFGBGIMAGE(uint8* pbDest, uint8 bitmask,
146         PIXEL fgPel, uint32 cBits)
147 {
148         if (bitmask & g_MaskBit0)
149         {
150                 DESTWRITEPIXEL(pbDest, fgPel);
151         }
152         else
153         {
154                 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
155         }
156         DESTNEXTPIXEL(pbDest);
157         cBits = cBits - 1;
158         if (cBits > 0)
159         {
160                 if (bitmask & g_MaskBit1)
161                 {
162                         DESTWRITEPIXEL(pbDest, fgPel);
163                 }
164                 else
165                 {
166                         DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
167                 }
168                 DESTNEXTPIXEL(pbDest);
169                 cBits = cBits - 1;
170                 if (cBits > 0)
171                 {
172                         if (bitmask & g_MaskBit2)
173                         {
174                                 DESTWRITEPIXEL(pbDest, fgPel);
175                         }
176                         else
177                         {
178                                 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
179                         }
180                         DESTNEXTPIXEL(pbDest);
181                         cBits = cBits - 1;
182                         if (cBits > 0)
183                         {
184                                 if (bitmask & g_MaskBit3)
185                                 {
186                                         DESTWRITEPIXEL(pbDest, fgPel);
187                                 }
188                                 else
189                                 {
190                                         DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
191                                 }
192                                 DESTNEXTPIXEL(pbDest);
193                                 cBits = cBits - 1;
194                                 if (cBits > 0)
195                                 {
196                                         if (bitmask & g_MaskBit4)
197                                         {
198                                                 DESTWRITEPIXEL(pbDest, fgPel);
199                                         }
200                                         else
201                                         {
202                                                 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
203                                         }
204                                         DESTNEXTPIXEL(pbDest);
205                                         cBits = cBits - 1;
206                                         if (cBits > 0)
207                                         {
208                                                 if (bitmask & g_MaskBit5)
209                                                 {
210                                                         DESTWRITEPIXEL(pbDest, fgPel);
211                                                 }
212                                                 else
213                                                 {
214                                                         DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
215                                                 }
216                                                 DESTNEXTPIXEL(pbDest);
217                                                 cBits = cBits - 1;
218                                                 if (cBits > 0)
219                                                 {
220                                                         if (bitmask & g_MaskBit6)
221                                                         {
222                                                                 DESTWRITEPIXEL(pbDest, fgPel);
223                                                         }
224                                                         else
225                                                         {
226                                                                 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
227                                                         }
228                                                         DESTNEXTPIXEL(pbDest);
229                                                         cBits = cBits - 1;
230                                                         if (cBits > 0)
231                                                         {
232                                                                 if (bitmask & g_MaskBit7)
233                                                                 {
234                                                                         DESTWRITEPIXEL(pbDest, fgPel);
235                                                                 }
236                                                                 else
237                                                                 {
238                                                                         DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
239                                                                 }
240                                                                 DESTNEXTPIXEL(pbDest);
241                                                         }
242                                                 }
243                                         }
244                                 }
245                         }
246                 }
247         }
248         return pbDest;
249 }
250
251 /**
252  * Decompress an RLE compressed bitmap.
253  */
254 void RLEDECOMPRESS(uint8* pbSrcBuffer, uint32 cbSrcBuffer, uint8* pbDestBuffer,
255         uint32 rowDelta, uint32 width, uint32 height)
256 {
257         uint8* pbSrc = pbSrcBuffer;
258         uint8* pbEnd = pbSrcBuffer + cbSrcBuffer;
259         uint8* pbDest = pbDestBuffer;
260
261         PIXEL temp;
262         PIXEL fgPel = WHITE_PIXEL;
263         boolean fInsertFgPel = false;
264         boolean fFirstLine = true;
265
266         uint8 bitmask;
267         PIXEL pixelA, pixelB;
268
269         uint32 runLength;
270         uint32 code;
271
272         uint32 advance;
273
274         RLEEXTRA
275
276         while (pbSrc < pbEnd)
277         {
278                 /* Watch out for the end of the first scanline. */
279                 if (fFirstLine)
280                 {
281                         if ((uint32)(pbDest - pbDestBuffer) >= rowDelta)
282                         {
283                                 fFirstLine = false;
284                                 fInsertFgPel = false;
285                         }
286                 }
287
288                 /*
289                    Extract the compression order code ID from the compression
290                    order header.
291                 */
292                 code = ExtractCodeId(*pbSrc);
293
294                 /* Handle Background Run Orders. */
295                 if (code == REGULAR_BG_RUN || code == MEGA_MEGA_BG_RUN)
296                 {
297                         runLength = ExtractRunLength(code, pbSrc, &advance);
298                         pbSrc = pbSrc + advance;
299                         if (fFirstLine)
300                         {
301                                 if (fInsertFgPel)
302                                 {
303                                         DESTWRITEPIXEL(pbDest, fgPel);
304                                         DESTNEXTPIXEL(pbDest);
305                                         runLength = runLength - 1;
306                                 }
307                                 while (runLength >= UNROLL_COUNT)
308                                 {
309                                         UNROLL(
310                                                 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
311                                                 DESTNEXTPIXEL(pbDest); );
312                                         runLength = runLength - UNROLL_COUNT;
313                                 }
314                                 while (runLength > 0)
315                                 {
316                                         DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
317                                         DESTNEXTPIXEL(pbDest);
318                                         runLength = runLength - 1;
319                                 }
320                         }
321                         else
322                         {
323                                 if (fInsertFgPel)
324                                 {
325                                         DESTREADPIXEL(temp, pbDest - rowDelta);
326                                         DESTWRITEPIXEL(pbDest, temp ^ fgPel);
327                                         DESTNEXTPIXEL(pbDest);
328                                         runLength = runLength - 1;
329                                 }
330                                 while (runLength >= UNROLL_COUNT)
331                                 {
332                                         UNROLL(
333                                                 DESTREADPIXEL(temp, pbDest - rowDelta);
334                                                 DESTWRITEPIXEL(pbDest, temp);
335                                                 DESTNEXTPIXEL(pbDest); );
336                                         runLength = runLength - UNROLL_COUNT;
337                                 }
338                                 while (runLength > 0)
339                                 {
340                                         DESTREADPIXEL(temp, pbDest - rowDelta);
341                                         DESTWRITEPIXEL(pbDest, temp);
342                                         DESTNEXTPIXEL(pbDest);
343                                         runLength = runLength - 1;
344                                 }
345                         }
346                         /* A follow-on background run order will need a foreground pel inserted. */
347                         fInsertFgPel = true;
348                         continue;
349                 }
350
351                 /* For any of the other run-types a follow-on background run
352                         order does not need a foreground pel inserted. */
353                 fInsertFgPel = false;
354
355                 switch (code)
356                 {
357                         /* Handle Foreground Run Orders. */
358                         case REGULAR_FG_RUN:
359                         case MEGA_MEGA_FG_RUN:
360                         case LITE_SET_FG_FG_RUN:
361                         case MEGA_MEGA_SET_FG_RUN:
362                                 runLength = ExtractRunLength(code, pbSrc, &advance);
363                                 pbSrc = pbSrc + advance;
364                                 if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
365                                 {
366                                         SRCREADPIXEL(fgPel, pbSrc);
367                                         SRCNEXTPIXEL(pbSrc);
368                                 }
369                                 if (fFirstLine)
370                                 {
371                                         while (runLength >= UNROLL_COUNT)
372                                         {
373                                                 UNROLL(
374                                                         DESTWRITEPIXEL(pbDest, fgPel);
375                                                         DESTNEXTPIXEL(pbDest); );
376                                                 runLength = runLength - UNROLL_COUNT;
377                                         }
378                                         while (runLength > 0)
379                                         {
380                                                 DESTWRITEPIXEL(pbDest, fgPel);
381                                                 DESTNEXTPIXEL(pbDest);
382                                                 runLength = runLength - 1;
383                                         }
384                                 }
385                                 else
386                                 {
387                                         while (runLength >= UNROLL_COUNT)
388                                         {
389                                                 UNROLL(
390                                                         DESTREADPIXEL(temp, pbDest - rowDelta);
391                                                         DESTWRITEPIXEL(pbDest, temp ^ fgPel);
392                                                         DESTNEXTPIXEL(pbDest); );
393                                                 runLength = runLength - UNROLL_COUNT;
394                                         }
395                                         while (runLength > 0)
396                                         {
397                                                 DESTREADPIXEL(temp, pbDest - rowDelta);
398                                                 DESTWRITEPIXEL(pbDest, temp ^ fgPel);
399                                                 DESTNEXTPIXEL(pbDest);
400                                                 runLength = runLength - 1;
401                                         }
402                                 }
403                                 break;
404
405                         /* Handle Dithered Run Orders. */
406                         case LITE_DITHERED_RUN:
407                         case MEGA_MEGA_DITHERED_RUN:
408                                 runLength = ExtractRunLength(code, pbSrc, &advance);
409                                 pbSrc = pbSrc + advance;
410                                 SRCREADPIXEL(pixelA, pbSrc);
411                                 SRCNEXTPIXEL(pbSrc);
412                                 SRCREADPIXEL(pixelB, pbSrc);
413                                 SRCNEXTPIXEL(pbSrc);
414                                 while (runLength >= UNROLL_COUNT)
415                                 {
416                                         UNROLL(
417                                                 DESTWRITEPIXEL(pbDest, pixelA);
418                                                 DESTNEXTPIXEL(pbDest);
419                                                 DESTWRITEPIXEL(pbDest, pixelB);
420                                                 DESTNEXTPIXEL(pbDest); );
421                                         runLength = runLength - UNROLL_COUNT;
422                                 }
423                                 while (runLength > 0)
424                                 {
425                                         DESTWRITEPIXEL(pbDest, pixelA);
426                                         DESTNEXTPIXEL(pbDest);
427                                         DESTWRITEPIXEL(pbDest, pixelB);
428                                         DESTNEXTPIXEL(pbDest);
429                                         runLength = runLength - 1;
430                                 }
431                                 break;
432
433                         /* Handle Color Run Orders. */
434                         case REGULAR_COLOR_RUN:
435                         case MEGA_MEGA_COLOR_RUN:
436                                 runLength = ExtractRunLength(code, pbSrc, &advance);
437                                 pbSrc = pbSrc + advance;
438                                 SRCREADPIXEL(pixelA, pbSrc);
439                                 SRCNEXTPIXEL(pbSrc);
440                                 while (runLength >= UNROLL_COUNT)
441                                 {
442                                         UNROLL(
443                                                 DESTWRITEPIXEL(pbDest, pixelA);
444                                                 DESTNEXTPIXEL(pbDest); );
445                                         runLength = runLength - UNROLL_COUNT;
446                                 }
447                                 while (runLength > 0)
448                                 {
449                                         DESTWRITEPIXEL(pbDest, pixelA);
450                                         DESTNEXTPIXEL(pbDest);
451                                         runLength = runLength - 1;
452                                 }
453                                 break;
454
455                         /* Handle Foreground/Background Image Orders. */
456                         case REGULAR_FGBG_IMAGE:
457                         case MEGA_MEGA_FGBG_IMAGE:
458                         case LITE_SET_FG_FGBG_IMAGE:
459                         case MEGA_MEGA_SET_FGBG_IMAGE:
460                                 runLength = ExtractRunLength(code, pbSrc, &advance);
461                                 pbSrc = pbSrc + advance;
462                                 if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
463                                 {
464                                         SRCREADPIXEL(fgPel, pbSrc);
465                                         SRCNEXTPIXEL(pbSrc);
466                                 }
467                                 if (fFirstLine)
468                                 {
469                                         while (runLength > 8)
470                                         {
471                                                 bitmask = *pbSrc;
472                                                 pbSrc = pbSrc + 1;
473                                                 pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, bitmask, fgPel, 8);
474                                                 runLength = runLength - 8;
475                                         }
476                                 }
477                                 else
478                                 {
479                                         while (runLength > 8)
480                                         {
481                                                 bitmask = *pbSrc;
482                                                 pbSrc = pbSrc + 1;
483                                                 pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, bitmask, fgPel, 8);
484                                                 runLength = runLength - 8;
485                                         }
486                                 }
487                                 if (runLength > 0)
488                                 {
489                                         bitmask = *pbSrc;
490                                         pbSrc = pbSrc + 1;
491                                         if (fFirstLine)
492                                         {
493                                                 pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, bitmask, fgPel, runLength);
494                                         }
495                                         else
496                                         {
497                                                 pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, bitmask, fgPel, runLength);
498                                         }
499                                 }
500                                 break;
501
502                         /* Handle Color Image Orders. */
503                         case REGULAR_COLOR_IMAGE:
504                         case MEGA_MEGA_COLOR_IMAGE:
505                                 runLength = ExtractRunLength(code, pbSrc, &advance);
506                                 pbSrc = pbSrc + advance;
507                                 while (runLength >= UNROLL_COUNT)
508                                 {
509                                         UNROLL(
510                                                 SRCREADPIXEL(temp, pbSrc);
511                                                 SRCNEXTPIXEL(pbSrc);
512                                                 DESTWRITEPIXEL(pbDest, temp);
513                                                 DESTNEXTPIXEL(pbDest); );
514                                         runLength = runLength - UNROLL_COUNT;
515                                 }
516                                 while (runLength > 0)
517                                 {
518                                         SRCREADPIXEL(temp, pbSrc);
519                                         SRCNEXTPIXEL(pbSrc);
520                                         DESTWRITEPIXEL(pbDest, temp);
521                                         DESTNEXTPIXEL(pbDest);
522                                         runLength = runLength - 1;
523                                 }
524                                 break;
525
526                         /* Handle Special Order 1. */
527                         case SPECIAL_FGBG_1:
528                                 pbSrc = pbSrc + 1;
529                                 if (fFirstLine)
530                                 {
531                                         pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, g_MaskSpecialFgBg1, fgPel, 8);
532                                 }
533                                 else
534                                 {
535                                         pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
536                                 }
537                                 break;
538
539                         /* Handle Special Order 2. */
540                         case SPECIAL_FGBG_2:
541                                 pbSrc = pbSrc + 1;
542                                 if (fFirstLine)
543                                 {
544                                         pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, g_MaskSpecialFgBg2, fgPel, 8);
545                                 }
546                                 else
547                                 {
548                                         pbDest = WRITEFGBGIMAGE(pbDest, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
549                                 }
550                                 break;
551
552                                 /* Handle White Order. */
553                         case SPECIAL_WHITE:
554                                 pbSrc = pbSrc + 1;
555                                 DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
556                                 DESTNEXTPIXEL(pbDest);
557                                 break;
558
559                         /* Handle Black Order. */
560                         case SPECIAL_BLACK:
561                                 pbSrc = pbSrc + 1;
562                                 DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
563                                 DESTNEXTPIXEL(pbDest);
564                                 break;
565                 }
566         }
567 }