Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-codec / color.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * Color Conversion Routines
4  *
5  * Copyright 2010 Marc-Andre Moreau <marcandre.moreau@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 <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <freerdp/api.h>
24 #include <freerdp/freerdp.h>
25 #include <freerdp/codec/color.h>
26 #include <freerdp/utils/memory.h>
27
28 int freerdp_get_pixel(uint8 * data, int x, int y, int width, int height, int bpp)
29 {
30         int start;
31         int shift;
32         uint16 *src16;
33         uint32 *src32;
34         int red, green, blue;
35
36         switch (bpp)
37         {
38                 case  1:
39                         width = (width + 7) / 8;
40                         start = (y * width) + x / 8;
41                         shift = x % 8;
42                         return (data[start] & (0x80 >> shift)) != 0;
43                 case 8:
44                         return data[y * width + x];
45                 case 15:
46                 case 16:
47                         src16 = (uint16*) data;
48                         return src16[y * width + x];
49                 case 24:
50                         data += y * width * 3;
51                         data += x * 3;
52                         red = data[0];
53                         green = data[1];
54                         blue = data[2];
55                         return RGB24(red, green, blue);
56                 case 32:
57                         src32 = (uint32*) data;
58                         return src32[y * width + x];
59                 default:
60                         break;
61         }
62
63         return 0;
64 }
65
66 void freerdp_set_pixel(uint8* data, int x, int y, int width, int height, int bpp, int pixel)
67 {
68         int start;
69         int shift;
70         int *dst32;
71
72         if (bpp == 1)
73         {
74                 width = (width + 7) / 8;
75                 start = (y * width) + x / 8;
76                 shift = x % 8;
77                 if (pixel)
78                         data[start] = data[start] | (0x80 >> shift);
79                 else
80                         data[start] = data[start] & ~(0x80 >> shift);
81         }
82         else if (bpp == 32)
83         {
84                 dst32 = (int*) data;
85                 dst32[y * width + x] = pixel;
86         }
87 }
88
89 INLINE void freerdp_color_split_rgb(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv)
90 {
91         *red = *green = *blue = 0;
92         *alpha = (clrconv->alpha) ? 0xFF : 0x00;
93
94         switch (bpp)
95         {
96                 case 32:
97                         if (clrconv->alpha)
98                         {
99                                 GetARGB32(*alpha, *red, *green, *blue, *color);
100                         }
101                         else
102                         {
103                                 GetRGB32(*red, *green, *blue, *color);
104                         }
105                         break;
106
107                 case 24:
108                         GetRGB24(*red, *green, *blue, *color);
109                         break;
110
111                 case 16:
112                         GetRGB16(*red, *green, *blue, *color);
113                         break;
114
115                 case 15:
116                         GetRGB15(*red, *green, *blue, *color);
117                         break;
118
119                 case 8:
120                         *color &= 0xFF;
121                         *red = clrconv->palette->entries[*color].red;
122                         *green = clrconv->palette->entries[*color].green;
123                         *blue = clrconv->palette->entries[*color].blue;
124                         break;
125
126                 case 1:
127                         if (*color != 0)
128                         {
129                                 *red = 0xFF;
130                                 *green = 0xFF;
131                                 *blue = 0xFF;
132                         }
133                         break;
134
135                 default:
136                         break;
137         }
138 }
139
140 INLINE void freerdp_color_split_bgr(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv)
141 {
142         *red = *green = *blue = 0;
143         *alpha = (clrconv->alpha) ? 0xFF : 0x00;
144
145         switch (bpp)
146         {
147                 case 32:
148                         if (clrconv->alpha)
149                         {
150                                 GetABGR32(*alpha, *red, *green, *blue, *color);
151                         }
152                         else
153                         {
154                                 GetBGR32(*red, *green, *blue, *color);
155                         }
156                         break;
157
158                 case 24:
159                         GetBGR24(*red, *green, *blue, *color);
160                         break;
161
162                 case 16:
163                         GetBGR16(*red, *green, *blue, *color);
164                         break;
165
166                 case 15:
167                         GetBGR15(*red, *green, *blue, *color);
168                         break;
169
170                 case 8:
171                         *color &= 0xFF;
172                         *red = clrconv->palette->entries[*color].red;
173                         *green = clrconv->palette->entries[*color].green;
174                         *blue = clrconv->palette->entries[*color].blue;
175                         break;
176
177                 case 1:
178                         if (*color != 0)
179                         {
180                                 *red = 0xFF;
181                                 *green = 0xFF;
182                                 *blue = 0xFF;
183                         }
184                         break;
185
186                 default:
187                         break;
188         }
189 }
190
191 INLINE void freerdp_color_make_rgb(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv)
192 {
193         switch (bpp)
194         {
195                 case 32:
196                         *color = ARGB32(*alpha, *red, *green, *blue);
197                         break;
198
199                 case 24:
200                         *color = RGB24(*red, *green, *blue);
201                         break;
202
203                 case 16:
204                         if (clrconv->rgb555)
205                         {
206                                 *color = RGB15(*red, *green, *blue);
207                         }
208                         else
209                         {
210                                 *color = RGB16(*red, *green, *blue);
211                         }
212                         break;
213
214                 case 15:
215                         *color = RGB15(*red, *green, *blue);
216                         break;
217
218                 case 8:
219                         *color = RGB24(*red, *green, *blue);
220                         break;
221
222                 case 1:
223                         if ((*red != 0) || (*green != 0) || (*blue != 0))
224                                 *color = 1;
225                         break;
226
227                 default:
228                         break;
229         }
230 }
231
232 INLINE void freerdp_color_make_bgr(uint32* color, int bpp, uint8* red, uint8* green, uint8* blue, uint8* alpha, HCLRCONV clrconv)
233 {
234         switch (bpp)
235         {
236                 case 32:
237                         *color = ABGR32(*alpha, *red, *green, *blue);
238                         break;
239
240                 case 24:
241                         *color = BGR24(*red, *green, *blue);
242                         break;
243
244                 case 16:
245                         if (clrconv->rgb555)
246                         {
247                                 *color = BGR15(*red, *green, *blue);
248                         }
249                         else
250                         {
251                                 *color = BGR16(*red, *green, *blue);
252                         }
253                         break;
254
255                 case 15:
256                         *color = BGR15(*red, *green, *blue);
257                         break;
258
259                 case 8:
260                         *color = BGR24(*red, *green, *blue);
261                         break;
262
263                 case 1:
264                         if ((*red != 0) || (*green != 0) || (*blue != 0))
265                                 *color = 1;
266                         break;
267
268                 default:
269                         break;
270         }
271 }
272
273 uint32 freerdp_color_convert_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
274 {
275         uint8 red = 0;
276         uint8 green = 0;
277         uint8 blue = 0;
278         uint8 alpha = 0xFF;
279         uint32 dstColor = 0;
280
281         freerdp_color_split_rgb(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv);
282         freerdp_color_make_rgb(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv);
283
284         return dstColor;
285 }
286
287 uint32 freerdp_color_convert_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
288 {
289         uint8 red = 0;
290         uint8 green = 0;
291         uint8 blue = 0;
292         uint8 alpha = 0xFF;
293         uint32 dstColor = 0;
294
295         freerdp_color_split_bgr(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv);
296         freerdp_color_make_bgr(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv);
297
298         return dstColor;
299 }
300
301 uint32 freerdp_color_convert_rgb_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
302 {
303         uint8 red = 0;
304         uint8 green = 0;
305         uint8 blue = 0;
306         uint8 alpha = 0xFF;
307         uint32 dstColor = 0;
308
309         freerdp_color_split_rgb(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv);
310         freerdp_color_make_bgr(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv);
311
312         return dstColor;
313 }
314
315 uint32 freerdp_color_convert_bgr_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
316 {
317         uint8 red = 0;
318         uint8 green = 0;
319         uint8 blue = 0;
320         uint8 alpha = 0xFF;
321         uint32 dstColor = 0;
322
323         freerdp_color_split_bgr(&srcColor, srcBpp, &red, &green, &blue, &alpha, clrconv);
324         freerdp_color_make_rgb(&dstColor, dstBpp, &red, &green, &blue, &alpha, clrconv);
325
326         return dstColor;
327 }
328
329 uint32 freerdp_color_convert_var(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
330 {
331         if (clrconv->invert)
332                 return freerdp_color_convert_var_bgr(srcColor, srcBpp, dstBpp, clrconv);
333         else
334                 return freerdp_color_convert_var_rgb(srcColor, srcBpp, dstBpp, clrconv);
335 }
336
337 uint32 freerdp_color_convert_var_rgb(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
338 {
339         if (srcBpp > 16)
340                 return freerdp_color_convert_bgr_rgb(srcColor, srcBpp, 32, clrconv);
341         else
342                 return freerdp_color_convert_rgb(srcColor, srcBpp, 32, clrconv);
343 }
344
345 uint32 freerdp_color_convert_var_bgr(uint32 srcColor, int srcBpp, int dstBpp, HCLRCONV clrconv)
346 {
347         if (srcBpp > 16)
348                 return freerdp_color_convert_bgr(srcColor, srcBpp, 32, clrconv);
349         else
350                 return freerdp_color_convert_rgb_bgr(srcColor, srcBpp, 32, clrconv);
351 }
352
353 uint8* freerdp_image_convert_8bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv)
354 {
355         int i;
356         uint8 red;
357         uint8 green;
358         uint8 blue;
359         uint32 pixel;
360         uint8 *src8;
361         uint16 *dst16;
362         uint32 *dst32;
363
364         if (dstBpp == 8)
365         {
366                 if (dstData == NULL)
367                         dstData = (uint8*) malloc(width * height);
368
369                 memcpy(dstData, srcData, width * height);
370                 return dstData;
371         }
372         else if (dstBpp == 15 || (dstBpp == 16 && clrconv->rgb555))
373         {
374                 if (dstData == NULL)
375                         dstData = (uint8*) malloc(width * height * 2);
376                 
377                 dst16 = (uint16 *) dstData;
378                 for (i = width * height; i > 0; i--)
379                 {
380                         pixel = *srcData;
381                         srcData++;
382                         red = clrconv->palette->entries[pixel].red;
383                         green = clrconv->palette->entries[pixel].green;
384                         blue = clrconv->palette->entries[pixel].blue;
385                         pixel = (clrconv->invert) ? BGR15(red, green, blue) : RGB15(red, green, blue);
386                         *dst16 = pixel;
387                         dst16++;
388                 }
389                 return dstData;
390         }
391         else if (dstBpp == 16)
392         {
393                 if (dstData == NULL)
394                         dstData = (uint8*) malloc(width * height * 2);
395                 
396                 dst16 = (uint16 *) dstData;
397                 for (i = width * height; i > 0; i--)
398                 {
399                         pixel = *srcData;
400                         srcData++;
401                         red = clrconv->palette->entries[pixel].red;
402                         green = clrconv->palette->entries[pixel].green;
403                         blue = clrconv->palette->entries[pixel].blue;
404                         pixel = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue);
405                         *dst16 = pixel;
406                         dst16++;
407                 }
408                 return dstData;
409         }
410         else if (dstBpp == 32)
411         {
412                 if (dstData == NULL)
413                         dstData = (uint8*) malloc(width * height * 4);
414                 
415                 src8 = (uint8*) srcData;
416                 dst32 = (uint32*) dstData;
417                 for (i = width * height; i > 0; i--)
418                 {
419                         pixel = *src8;
420                         src8++;
421                         red = clrconv->palette->entries[pixel].red;
422                         green = clrconv->palette->entries[pixel].green;
423                         blue = clrconv->palette->entries[pixel].blue;
424                         pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue);
425                         *dst32 = pixel;
426                         dst32++;
427                 }
428                 return dstData;
429         }
430
431         return srcData;
432 }
433
434 uint8* freerdp_image_convert_15bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv)
435 {
436         int i;
437         uint8 red;
438         uint8 green;
439         uint8 blue;
440         uint32 pixel;
441         uint16 *src16;
442         uint16 *dst16;
443         uint32 *dst32;
444
445         if (dstBpp == 15 || (dstBpp == 16 && clrconv->rgb555))
446         {
447                 if (dstData == NULL)
448                         dstData = (uint8*) malloc(width * height * 2);
449
450                 memcpy(dstData, srcData, width * height * 2);
451
452                 return dstData;
453         }
454         else if (dstBpp == 32)
455         {
456                 if (dstData == NULL)
457                         dstData = (uint8*) malloc(width * height * 4);
458                 
459                 src16 = (uint16 *) srcData;
460                 dst32 = (uint32 *) dstData;
461                 for (i = width * height; i > 0; i--)
462                 {
463                         pixel = *src16;
464                         src16++;
465                         GetBGR15(red, green, blue, pixel);
466                         pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue);
467                         *dst32 = pixel;
468                         dst32++;
469                 }
470                 return dstData;
471         }
472         else if (dstBpp == 16)
473         {
474                 if (dstData == NULL)
475                         dstData = (uint8*) malloc(width * height * 2);
476         
477                 src16 = (uint16 *) srcData;
478                 dst16 = (uint16 *) dstData;
479                 for (i = width * height; i > 0; i--)
480                 {
481                         pixel = *src16;
482                         src16++;
483                         GetRGB_555(red, green, blue, pixel);
484                         RGB_555_565(red, green, blue);
485                         pixel = (clrconv->invert) ? BGR565(red, green, blue) : RGB565(red, green, blue);
486                         *dst16 = pixel;
487                         dst16++;
488                 }
489                 return dstData;
490         }
491
492         return srcData;
493 }
494
495 uint8* freerdp_image_convert_16bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv)
496 {
497         if (srcBpp == 15)
498                 return freerdp_image_convert_15bpp(srcData, dstData, width, height, srcBpp, dstBpp, clrconv);
499
500         if (dstBpp == 16)
501         {
502                 if (dstData == NULL)
503                         dstData = (uint8*) malloc(width * height * 2);
504
505                 if (clrconv->rgb555)
506                 {
507                         int i;
508                         uint8 red, green, blue;
509                         uint16* src16 = (uint16 *) srcData;
510                         uint16* dst16 = (uint16 *) dstData;
511
512                         for (i = width * height; i > 0; i--)
513                         {
514                                 GetRGB_565(red, green, blue, (*src16));
515                                 RGB_565_555(red, green, blue);
516                                 (*dst16) = (clrconv->invert) ? BGR555(red, green, blue) : RGB555(red, green, blue);
517                                 src16++;
518                                 dst16++;
519                         }
520                 }
521                 else
522                 {
523                         memcpy(dstData, srcData, width * height * 2);
524                 }
525
526                 return dstData;
527         }
528         else if (dstBpp == 24)
529         {
530                 int i;
531                 uint8 *dst8;
532                 uint16 *src16;
533                 uint8 red, green, blue;
534
535                 if (dstData == NULL)
536                         dstData = (uint8*) malloc(width * height * 3);
537
538                 dst8 = (uint8*) dstData;
539                 src16 = (uint16*) srcData;
540
541                 for (i = width * height; i > 0; i--)
542                 {
543                         GetBGR16(red, green, blue, *src16);
544                         src16++;
545
546                         if (clrconv->invert)
547                         {
548                                 *dst8++ = blue;
549                                 *dst8++ = green;
550                                 *dst8++ = red;
551                         }
552                         else
553                         {
554                                 *dst8++ = red;
555                                 *dst8++ = green;
556                                 *dst8++ = blue;
557                         }
558                 }
559                 return dstData;
560         }
561         else if (dstBpp == 32)
562         {
563                 int i;
564                 uint32 pixel;
565                 uint16* src16;
566                 uint32* dst32;
567                 uint8 red, green, blue;
568
569                 if (dstData == NULL)
570                         dstData = (uint8*) malloc(width * height * 4);
571
572                 src16 = (uint16*) srcData;
573                 dst32 = (uint32*) dstData;
574
575                 for (i = width * height; i > 0; i--)
576                 {
577                         pixel = *src16;
578                         src16++;
579                         GetBGR16(red, green, blue, pixel);
580                         pixel = (clrconv->invert) ? RGB32(red, green, blue) : BGR32(red, green, blue);
581                         *dst32 = pixel;
582                         dst32++;
583                 }
584                 return dstData;
585         }
586
587         return srcData;
588 }
589
590 uint8* freerdp_image_convert_24bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv)
591 {
592         int i;
593
594         if (dstBpp == 32)
595         {
596                 uint8 *dstp;
597                 if (dstData == NULL)
598                         dstData = (uint8*) malloc(width * height * 4);
599                 
600                 dstp = dstData;
601                 for (i = width * height; i > 0; i--)
602                 {
603                         *(dstp++) = *(srcData++);
604                         *(dstp++) = *(srcData++);
605                         *(dstp++) = *(srcData++);
606                         *(dstp++) = 0xFF;
607                 }
608                 return dstData;
609         }
610
611         return srcData;
612 }
613
614 uint8* freerdp_image_convert_32bpp(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv)
615 {
616         if (dstBpp == 16)
617         {
618                 int index;
619                 uint16 *dst16;
620                 uint32 *src32;
621                 uint8 red, green, blue;
622
623                 if (dstData == NULL)
624                         dstData = (uint8*) malloc(width * height * 2);
625
626                 dst16 = (uint16*) dstData;
627                 src32 = (uint32*) srcData;
628
629                 for (index = 0; index < width * height; index++)
630                 {
631                         GetBGR32(blue, green, red, *src32);
632                         *dst16 = (clrconv->invert) ? BGR16(red, green, blue) : RGB16(red, green, blue);
633                         src32++;
634                         dst16++;
635                 }
636                 return dstData;
637         }
638         else if (dstBpp == 24)
639         {
640                 uint8 *dstp;
641                 int index;
642                 uint8 red, green, blue;
643
644                 if (dstData == NULL)
645                         dstData = (uint8*) malloc(width * height * 3);
646
647                 dstp = dstData;
648                 for (index = 0; index < width * height; index++)
649                 {
650                         red = *(srcData++);
651                         green = *(srcData++);
652                         blue = *(srcData++);
653
654                         if (clrconv->invert)
655                         {
656                                 *dstp++ = blue;
657                                 *dstp++ = green;
658                                 *dstp++ = red;
659                         }
660                         else
661                         {
662                                 *dstp++ = red;
663                                 *dstp++ = green;
664                                 *dstp++ = blue;
665                         }
666
667                         srcData++;
668                 }
669                 return dstData;
670         }
671         else if (dstBpp == 32)
672         {
673                 if (clrconv->alpha)
674                 {
675                         int x, y;
676                         uint8 *dstp;
677
678                         if (dstData == NULL)
679                                 dstData = (uint8*) malloc(width * height * 4);
680
681                         memcpy(dstData, srcData, width * height * 4);
682
683                         dstp = dstData;
684                         for (y = 0; y < height; y++)
685                         {
686                                 for (x = 0; x < width * 4; x += 4)
687                                 {
688                                         dstp += 3;
689                                         *dstp = 0xFF;
690                                         dstp++;
691                                 }
692                         }
693                 }
694                 else
695                 {
696                         if (dstData == NULL)
697                                 dstData = (uint8*) malloc(width * height * 4);
698
699                         memcpy(dstData, srcData, width * height * 4);
700                 }
701                 
702                 return dstData;
703         }
704
705         return srcData;
706 }
707
708 p_freerdp_image_convert freerdp_image_convert_[5] =
709 {
710         NULL,
711         freerdp_image_convert_8bpp,
712         freerdp_image_convert_16bpp,
713         freerdp_image_convert_24bpp,
714         freerdp_image_convert_32bpp
715 };
716
717 uint8* freerdp_image_convert(uint8* srcData, uint8* dstData, int width, int height, int srcBpp, int dstBpp, HCLRCONV clrconv)
718 {
719         p_freerdp_image_convert _p_freerdp_image_convert = freerdp_image_convert_[IBPP(srcBpp)];
720
721         if (_p_freerdp_image_convert != NULL)
722                 return _p_freerdp_image_convert(srcData, dstData, width, height, srcBpp, dstBpp, clrconv);
723         else
724                 return 0;
725 }
726
727 void   freerdp_bitmap_flip(uint8 * src, uint8 * dst, int scanLineSz, int height)
728 {
729         int i;
730
731         uint8 * bottomLine = dst + (scanLineSz * (height - 1));
732         uint8 * topLine = src;
733
734         /* Special processing if called for flip-in-place. */
735         if (src == dst)
736         {
737                 /* Allocate a scanline buffer.
738                  * (FIXME: xmalloc / xfree below should be replaced by "get/put
739                  * scanline buffer from a pool/Q of fixed buffers" to reuse
740                  * fixed size buffers (of max scanline size (or adaptative?) )
741                  * -- would be much faster).
742                  */
743                 uint8 * tmpBfr = xmalloc(scanLineSz);
744                 int half = height / 2;
745                 /* Flip buffer in place by line permutations through the temp
746                  * scan line buffer.
747                  * Not that if height has an odd number of line, we don't need
748                  * to move the center scanline anyway.
749                  * Also note that in place flipping takes three memcpy() calls
750                  * to process two scanlines while src to distinct dest would
751                  * only requires two memcpy() calls for two scanlines.
752                  */
753                 height--;
754                 for (i = 0; i < half ; i++)
755                 {
756                         memcpy(tmpBfr, topLine, scanLineSz);
757                         memcpy(topLine, bottomLine, scanLineSz);
758                         memcpy(bottomLine, tmpBfr, scanLineSz);
759                         topLine += scanLineSz;
760                         bottomLine -= scanLineSz;
761                         height--;
762                 }
763                 xfree(tmpBfr);
764         }
765         /* Flip from source buffer to destination buffer. */
766         else
767         {
768
769                 for (i = 0; i < height; i++)
770                 {
771                         memcpy(bottomLine, topLine, scanLineSz);
772                         topLine += scanLineSz;
773                         bottomLine -= scanLineSz;
774                 }
775         }
776
777 }
778
779 uint8* freerdp_image_flip(uint8* srcData, uint8* dstData, int width, int height, int bpp)
780 {
781         int scanline;
782
783         scanline = width * (bpp / 8);
784
785         if (dstData == NULL)
786                 dstData = (uint8*) xmalloc(width * height * (bpp / 8));
787
788         freerdp_bitmap_flip(srcData, dstData, scanline, height);
789         return dstData;
790 }
791
792 uint8* freerdp_icon_convert(uint8* srcData, uint8* dstData, uint8* mask, int width, int height, int bpp, HCLRCONV clrconv)
793 {
794         int x, y;
795         int pixel;
796         uint8* data;
797         uint8 bmask;
798         uint32 pmask;
799         uint32* icon;
800
801         pixel = 0;
802         data = freerdp_image_flip(srcData, dstData, width, height, bpp);
803         dstData = freerdp_image_convert(data, NULL, width, height, bpp, 32, clrconv);
804
805         free(data);
806         bmask = mask[pixel];
807         icon = (uint32*) dstData;
808
809         if (bpp < 32)
810         {
811                 for (y = 0; y < height; y++)
812                 {
813                         for (x = 0; x < width; x++)
814                         {
815                                 if (pixel % 8 == 0)
816                                         bmask = mask[pixel / 8];
817                                 else
818                                         bmask <<= 1;
819
820                                 pmask = (bmask & 0x80) ? 0x00000000 : 0xFF000000;
821
822                                 *icon++ |= pmask;
823
824                                 pixel++;
825                         }
826                 }
827         }
828
829         free(mask);
830
831         return dstData;
832 }
833
834 uint8* freerdp_glyph_convert(int width, int height, uint8* data)
835 {
836         int x, y;
837         uint8 *srcp;
838         uint8 *dstp;
839         uint8 *dstData;
840         int scanline;
841
842         /*
843          * converts a 1-bit-per-pixel glyph to a one-byte-per-pixel glyph:
844          * this approach uses a little more memory, but provides faster
845          * means of accessing individual pixels in blitting operations
846          */
847
848         scanline = (width + 7) / 8;
849         dstData = (uint8*) malloc(width * height);
850         memset(dstData, 0, width * height);
851         dstp = dstData;
852
853         for (y = 0; y < height; y++)
854         {
855                 srcp = data + (y * scanline);
856
857                 for (x = 0; x < width; x++)
858                 {
859                         if ((*srcp & (0x80 >> (x % 8))) != 0)
860                                 *dstp = 0xFF;
861                         dstp++;
862
863                         if (((x + 1) % 8 == 0) && x != 0)
864                                 srcp++;
865                 }
866         }
867
868         return dstData;
869 }
870
871 uint8* freerdp_mono_image_convert(uint8* srcData, int width, int height, int srcBpp, int dstBpp, uint32 bgcolor, uint32 fgcolor, HCLRCONV clrconv)
872 {
873         int index;
874         uint16* dst16;
875         uint32* dst32;
876         uint8* dstData;
877         uint8 bitMask;
878         int bitIndex;
879         uint8 redBg, greenBg, blueBg;
880         uint8 redFg, greenFg, blueFg;
881
882         switch (srcBpp)
883         {
884                 case 8:
885                         bgcolor &= 0xFF;
886                         redBg = clrconv->palette->entries[bgcolor].red;
887                         greenBg = clrconv->palette->entries[bgcolor].green;
888                         blueBg = clrconv->palette->entries[bgcolor].blue;
889
890                         fgcolor &= 0xFF;
891                         redFg = clrconv->palette->entries[fgcolor].red;
892                         greenFg = clrconv->palette->entries[fgcolor].green;
893                         blueFg = clrconv->palette->entries[fgcolor].blue;
894                         break;
895
896                 case 16:
897                         GetRGB16(redBg, greenBg, blueBg, bgcolor);
898                         GetRGB16(redFg, greenFg, blueFg, fgcolor);
899                         break;
900
901                 case 15:
902                         GetRGB15(redBg, greenBg, blueBg, bgcolor);
903                         GetRGB15(redFg, greenFg, blueFg, fgcolor);
904                         break;
905
906                 default:
907                         GetRGB32(redBg, greenBg, blueBg, bgcolor);
908                         GetRGB32(redFg, greenFg, blueFg, fgcolor);
909                         break;
910         }
911
912         if (dstBpp == 16)
913         {
914                 if (clrconv->rgb555)
915                 {
916                         if (srcBpp == 16)
917                         {
918                                 /* convert 15-bit colors to 16-bit colors */
919                                 RGB16_RGB15(redBg, greenBg, blueBg, bgcolor);
920                                 RGB16_RGB15(redFg, greenFg, blueFg, fgcolor);
921                         }
922                 }
923                 else
924                 {
925                         if (srcBpp == 15)
926                         {
927                                 /* convert 15-bit colors to 16-bit colors */
928                                 RGB15_RGB16(redBg, greenBg, blueBg, bgcolor);
929                                 RGB15_RGB16(redFg, greenFg, blueFg, fgcolor);
930                         }
931                 }
932
933                 dstData = (uint8*) malloc(width * height * 2);
934                 dst16 = (uint16*) dstData;
935
936                 for (index = height; index > 0; index--)
937                 {
938                         /* each bit encodes a pixel */
939                         bitMask = *srcData;
940                         for (bitIndex = 7; bitIndex >= 0; bitIndex--)
941                         {
942                                 if ((bitMask >> bitIndex) & 0x01)
943                                 {
944                                         *dst16 = bgcolor;
945                                 }
946                                 else
947                                 {
948                                         *dst16 = fgcolor;
949                                 }
950                                 dst16++;
951                         }
952                         srcData++;
953                 }
954                 return dstData;
955         }
956         else if (dstBpp == 32)
957         {
958                 dstData = (uint8*) malloc(width * height * 4);
959                 dst32 = (uint32*) dstData;
960
961                 for (index = height; index > 0; index--)
962                 {
963                         /* each bit encodes a pixel */
964                         bitMask = *srcData;
965
966                         for (bitIndex = 7; bitIndex >= 0; bitIndex--)
967                         {
968                                 if ((bitMask >> bitIndex) & 0x01)
969                                 {
970                                         *dst32 = (clrconv->invert) ? BGR32(redBg, greenBg, blueBg) : RGB32(redBg, greenBg, blueBg);
971                                 }
972                                 else
973                                 {
974                                         *dst32 = (clrconv->invert) ? BGR32(redFg, greenFg, blueFg) : RGB32(redFg, greenFg, blueFg);
975                                 }
976                                 dst32++;
977                         }
978                         srcData++;
979                 }
980                 return dstData;
981         }
982
983         return srcData;
984 }
985
986 void freerdp_alpha_cursor_convert(uint8* alphaData, uint8* xorMask, uint8* andMask, int width, int height, int bpp, HCLRCONV clrconv)
987 {
988         int xpixel;
989         int apixel;
990         int i, j, jj;
991
992         for (j = 0; j < height; j++)
993         {
994                 jj = (bpp == 1) ? j : (height - 1) - j;
995                 for (i = 0; i < width; i++)
996                 {
997                         xpixel = freerdp_get_pixel(xorMask, i, jj, width, height, bpp);
998                         xpixel = freerdp_color_convert_rgb(xpixel, bpp, 32, clrconv);
999                         apixel = freerdp_get_pixel(andMask, i, jj, width, height, 1);
1000
1001                         if (apixel != 0)
1002                         {
1003                                 if ((xpixel & 0xffffff) == 0xffffff)
1004                                 {
1005                                         /* use pattern (not solid black) for xor area */
1006                                         xpixel = (i & 1) == (j & 1);
1007                                         xpixel = xpixel ? 0xFFFFFF : 0;
1008                                         xpixel |= 0xFF000000;
1009                                 }
1010                                 else if (xpixel == 0xFF000000)
1011                                 {
1012                                         xpixel = 0;
1013                                 }
1014                         }
1015
1016                         freerdp_set_pixel(alphaData, i, j, width, height, 32, xpixel);
1017                 }
1018         }
1019 }
1020
1021 void freerdp_image_swap_color_order(uint8* data, int width, int height)
1022 {
1023         int x, y;
1024         uint32* pixel;
1025         uint8 a, r, g, b;
1026
1027         pixel = (uint32*) data;
1028
1029         for (y = 0; y < height; y++)
1030         {
1031                 for (x = 0; x < width; x++)
1032                 {
1033                         GetARGB32(a, r, g, b, *pixel);
1034                         *pixel = ABGR32(a, r, g, b);
1035                         pixel++;
1036                 }
1037         }
1038 }
1039
1040 HCLRCONV freerdp_clrconv_new(uint32 flags)
1041 {
1042         HCLRCONV clrconv = xnew(CLRCONV);
1043
1044         clrconv->alpha = (flags & CLRCONV_ALPHA) ? true : false;
1045         clrconv->invert = (flags & CLRCONV_INVERT) ? true : false;
1046         clrconv->rgb555 = (flags & CLRCONV_RGB555) ? true : false;
1047         clrconv->palette = xnew(rdpPalette);
1048
1049         return clrconv;
1050 }
1051
1052 void freerdp_clrconv_free(HCLRCONV clrconv)
1053 {
1054         if (clrconv != NULL)
1055         {
1056                 if (clrconv->palette != NULL)
1057                         xfree(clrconv->palette);
1058
1059                 xfree(clrconv);
1060         }
1061 }