FreeRDP
interleaved.c
1 
24 #include <winpr/assert.h>
25 #include <freerdp/config.h>
26 
27 #include <freerdp/codec/interleaved.h>
28 #include <freerdp/log.h>
29 
30 #define TAG FREERDP_TAG("codec")
31 
32 #define UNROLL_BODY(_exp, _count) \
33  do \
34  { \
35  for (size_t x = 0; x < (_count); x++) \
36  { \
37  do \
38  { \
39  _exp \
40  } while (FALSE); \
41  } \
42  } while (FALSE)
43 
44 #define UNROLL_MULTIPLE(_condition, _exp, _count) \
45  do \
46  { \
47  while ((_condition) >= (_count)) \
48  { \
49  UNROLL_BODY(_exp, _count); \
50  (_condition) -= (_count); \
51  } \
52  } while (FALSE)
53 
54 #define UNROLL(_condition, _exp) \
55  do \
56  { \
57  UNROLL_MULTIPLE(_condition, _exp, 16); \
58  UNROLL_MULTIPLE(_condition, _exp, 4); \
59  UNROLL_MULTIPLE(_condition, _exp, 1); \
60  } while (FALSE)
61 
62 /*
63  RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
64  http://msdn.microsoft.com/en-us/library/cc240895%28v=prot.10%29.aspx
65  pseudo-code
66  http://msdn.microsoft.com/en-us/library/dd240593%28v=prot.10%29.aspx
67 */
68 
69 #define REGULAR_BG_RUN 0x00
70 #define MEGA_MEGA_BG_RUN 0xF0
71 #define REGULAR_FG_RUN 0x01
72 #define MEGA_MEGA_FG_RUN 0xF1
73 #define LITE_SET_FG_FG_RUN 0x0C
74 #define MEGA_MEGA_SET_FG_RUN 0xF6
75 #define LITE_DITHERED_RUN 0x0E
76 #define MEGA_MEGA_DITHERED_RUN 0xF8
77 #define REGULAR_COLOR_RUN 0x03
78 #define MEGA_MEGA_COLOR_RUN 0xF3
79 #define REGULAR_FGBG_IMAGE 0x02
80 #define MEGA_MEGA_FGBG_IMAGE 0xF2
81 #define LITE_SET_FG_FGBG_IMAGE 0x0D
82 #define MEGA_MEGA_SET_FGBG_IMAGE 0xF7
83 #define REGULAR_COLOR_IMAGE 0x04
84 #define MEGA_MEGA_COLOR_IMAGE 0xF4
85 #define SPECIAL_FGBG_1 0xF9
86 #define SPECIAL_FGBG_2 0xFA
87 #define SPECIAL_WHITE 0xFD
88 #define SPECIAL_BLACK 0xFE
89 
90 #define BLACK_PIXEL 0x000000
91 
92 typedef UINT32 PIXEL;
93 
94 static const BYTE g_MaskSpecialFgBg1 = 0x03;
95 static const BYTE g_MaskSpecialFgBg2 = 0x05;
96 
97 static const BYTE g_MaskRegularRunLength = 0x1F;
98 static const BYTE g_MaskLiteRunLength = 0x0F;
99 
100 static const char* rle_code_str(UINT32 code)
101 {
102  switch (code)
103  {
104  case REGULAR_BG_RUN:
105  return "REGULAR_BG_RUN";
106  case MEGA_MEGA_BG_RUN:
107  return "MEGA_MEGA_BG_RUN";
108  case REGULAR_FG_RUN:
109  return "REGULAR_FG_RUN";
110  case MEGA_MEGA_FG_RUN:
111  return "MEGA_MEGA_FG_RUN";
112  case LITE_SET_FG_FG_RUN:
113  return "LITE_SET_FG_FG_RUN";
114  case MEGA_MEGA_SET_FG_RUN:
115  return "MEGA_MEGA_SET_FG_RUN";
116  case LITE_DITHERED_RUN:
117  return "LITE_DITHERED_RUN";
118  case MEGA_MEGA_DITHERED_RUN:
119  return "MEGA_MEGA_DITHERED_RUN";
120  case REGULAR_COLOR_RUN:
121  return "REGULAR_COLOR_RUN";
122  case MEGA_MEGA_COLOR_RUN:
123  return "MEGA_MEGA_COLOR_RUN";
124  case REGULAR_FGBG_IMAGE:
125  return "REGULAR_FGBG_IMAGE";
126  case MEGA_MEGA_FGBG_IMAGE:
127  return "MEGA_MEGA_FGBG_IMAGE";
128  case LITE_SET_FG_FGBG_IMAGE:
129  return "LITE_SET_FG_FGBG_IMAGE";
130  case MEGA_MEGA_SET_FGBG_IMAGE:
131  return "MEGA_MEGA_SET_FGBG_IMAGE";
132  case REGULAR_COLOR_IMAGE:
133  return "REGULAR_COLOR_IMAGE";
134  case MEGA_MEGA_COLOR_IMAGE:
135  return "MEGA_MEGA_COLOR_IMAGE";
136  case SPECIAL_FGBG_1:
137  return "SPECIAL_FGBG_1";
138  case SPECIAL_FGBG_2:
139  return "SPECIAL_FGBG_2";
140  case SPECIAL_WHITE:
141  return "SPECIAL_WHITE";
142  case SPECIAL_BLACK:
143  return "SPECIAL_BLACK";
144  default:
145  return "UNKNOWN";
146  }
147 }
148 
149 static const char* rle_code_str_buffer(UINT32 code, char* buffer, size_t size)
150 {
151  const char* str = rle_code_str(code);
152  (void)_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, code);
153  return buffer;
154 }
155 
156 #define buffer_within_range(pbSrc, size, pbEnd) \
157  buffer_within_range_((pbSrc), (size), (pbEnd), __func__, __FILE__, __LINE__)
158 static INLINE BOOL buffer_within_range_(const void* pbSrc, size_t size, const void* pbEnd,
159  const char* fkt, const char* file, size_t line)
160 {
161  WINPR_UNUSED(file);
162  WINPR_ASSERT(pbSrc);
163  WINPR_ASSERT(pbEnd);
164 
165  if ((const char*)pbSrc + size > (const char*)pbEnd)
166  {
167  WLog_ERR(TAG, "[%s:%" PRIuz "] pbSrc=%p + %" PRIuz " > pbEnd=%p", fkt, line, pbSrc, size,
168  pbEnd);
169  return FALSE;
170  }
171  return TRUE;
172 }
173 
178 static INLINE UINT32 ExtractCodeId(BYTE bOrderHdr)
179 {
180  if ((bOrderHdr & 0xC0U) != 0xC0U)
181  {
182  /* REGULAR orders
183  * (000x xxxx, 001x xxxx, 010x xxxx, 011x xxxx, 100x xxxx)
184  */
185  return bOrderHdr >> 5;
186  }
187  else if ((bOrderHdr & 0xF0U) == 0xF0U)
188  {
189  /* MEGA and SPECIAL orders (0xF*) */
190  return bOrderHdr;
191  }
192  else
193  {
194  /* LITE orders
195  * 1100 xxxx, 1101 xxxx, 1110 xxxx)
196  */
197  return bOrderHdr >> 4;
198  }
199 }
200 
204 static UINT ExtractRunLengthRegularFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
205 {
206  UINT runLength = 0;
207 
208  WINPR_ASSERT(pbOrderHdr);
209  WINPR_ASSERT(pbEnd);
210  WINPR_ASSERT(advance);
211 
212  runLength = (*pbOrderHdr) & g_MaskRegularRunLength;
213  if (runLength == 0)
214  {
215  if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
216  {
217  *advance = 0;
218  return 0;
219  }
220  runLength = *(pbOrderHdr + 1) + 1;
221  (*advance)++;
222  }
223  else
224  runLength = runLength * 8;
225 
226  return runLength;
227 }
228 
229 static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
230 {
231  UINT runLength = 0;
232 
233  WINPR_ASSERT(pbOrderHdr);
234  WINPR_ASSERT(pbEnd);
235  WINPR_ASSERT(advance);
236 
237  runLength = *pbOrderHdr & g_MaskLiteRunLength;
238  if (runLength == 0)
239  {
240  if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
241  {
242  *advance = 0;
243  return 0;
244  }
245  runLength = *(pbOrderHdr + 1) + 1;
246  (*advance)++;
247  }
248  else
249  runLength = runLength * 8;
250 
251  return runLength;
252 }
253 
254 static UINT ExtractRunLengthRegular(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
255 {
256  UINT runLength = 0;
257 
258  WINPR_ASSERT(pbOrderHdr);
259  WINPR_ASSERT(pbEnd);
260  WINPR_ASSERT(advance);
261 
262  runLength = *pbOrderHdr & g_MaskRegularRunLength;
263  if (runLength == 0)
264  {
265  if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
266  {
267  *advance = 0;
268  return 0;
269  }
270  runLength = *(pbOrderHdr + 1) + 32;
271  (*advance)++;
272  }
273 
274  return runLength;
275 }
276 
277 static UINT ExtractRunLengthMegaMega(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
278 {
279  UINT runLength = 0;
280 
281  WINPR_ASSERT(pbOrderHdr);
282  WINPR_ASSERT(pbEnd);
283  WINPR_ASSERT(advance);
284 
285  if (!buffer_within_range(pbOrderHdr, 3, pbEnd))
286  {
287  *advance = 0;
288  return 0;
289  }
290 
291  runLength = ((UINT16)pbOrderHdr[1]) | (((UINT16)pbOrderHdr[2]) << 8);
292  (*advance) += 2;
293 
294  return runLength;
295 }
296 
297 static UINT ExtractRunLengthLite(const BYTE* pbOrderHdr, const BYTE* pbEnd, UINT32* advance)
298 {
299  UINT runLength = 0;
300 
301  WINPR_ASSERT(pbOrderHdr);
302  WINPR_ASSERT(pbEnd);
303  WINPR_ASSERT(advance);
304 
305  runLength = *pbOrderHdr & g_MaskLiteRunLength;
306  if (runLength == 0)
307  {
308  if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
309  {
310  *advance = 0;
311  return 0;
312  }
313  runLength = *(pbOrderHdr + 1) + 16;
314  (*advance)++;
315  }
316  return runLength;
317 }
318 
319 static INLINE UINT32 ExtractRunLength(UINT32 code, const BYTE* pbOrderHdr, const BYTE* pbEnd,
320  UINT32* advance)
321 {
322  UINT32 runLength = 0;
323  UINT32 ladvance = 1;
324 
325  WINPR_ASSERT(pbOrderHdr);
326  WINPR_ASSERT(pbEnd);
327  WINPR_ASSERT(advance);
328 
329  *advance = 0;
330  if (!buffer_within_range(pbOrderHdr, 0, pbEnd))
331  return 0;
332 
333  switch (code)
334  {
335  case REGULAR_FGBG_IMAGE:
336  runLength = ExtractRunLengthRegularFgBg(pbOrderHdr, pbEnd, &ladvance);
337  break;
338 
339  case LITE_SET_FG_FGBG_IMAGE:
340  runLength = ExtractRunLengthLiteFgBg(pbOrderHdr, pbEnd, &ladvance);
341  break;
342 
343  case REGULAR_BG_RUN:
344  case REGULAR_FG_RUN:
345  case REGULAR_COLOR_RUN:
346  case REGULAR_COLOR_IMAGE:
347  runLength = ExtractRunLengthRegular(pbOrderHdr, pbEnd, &ladvance);
348  break;
349 
350  case LITE_SET_FG_FG_RUN:
351  case LITE_DITHERED_RUN:
352  runLength = ExtractRunLengthLite(pbOrderHdr, pbEnd, &ladvance);
353  break;
354 
355  case MEGA_MEGA_BG_RUN:
356  case MEGA_MEGA_FG_RUN:
357  case MEGA_MEGA_SET_FG_RUN:
358  case MEGA_MEGA_DITHERED_RUN:
359  case MEGA_MEGA_COLOR_RUN:
360  case MEGA_MEGA_FGBG_IMAGE:
361  case MEGA_MEGA_SET_FGBG_IMAGE:
362  case MEGA_MEGA_COLOR_IMAGE:
363  runLength = ExtractRunLengthMegaMega(pbOrderHdr, pbEnd, &ladvance);
364  break;
365 
366  default:
367  runLength = 0;
368  ladvance = 0;
369  break;
370  }
371 
372  *advance = ladvance;
373  return runLength;
374 }
375 
376 #define ensure_capacity(start, end, size, base) \
377  ensure_capacity_((start), (end), (size), (base), __func__, __FILE__, __LINE__)
378 static INLINE BOOL ensure_capacity_(const BYTE* start, const BYTE* end, size_t size, size_t base,
379  const char* fkt, const char* file, size_t line)
380 {
381  const size_t available = (uintptr_t)end - (uintptr_t)start;
382  const BOOL rc = available >= size * base;
383  const BOOL res = rc && (start <= end);
384 
385  if (!res)
386  WLog_ERR(TAG,
387  "[%s:%" PRIuz "] failed: start=%p <= end=%p, available=%" PRIuz " >= size=%" PRIuz
388  " * base=%" PRIuz,
389  fkt, line, start, end, available, size, base);
390  return res;
391 }
392 
393 static INLINE void write_pixel_8(BYTE* _buf, BYTE _pix)
394 {
395  WINPR_ASSERT(_buf);
396  *_buf = _pix;
397 }
398 
399 static INLINE void write_pixel_24(BYTE* _buf, UINT32 _pix)
400 {
401  WINPR_ASSERT(_buf);
402  (_buf)[0] = (BYTE)(_pix);
403  (_buf)[1] = (BYTE)((_pix) >> 8);
404  (_buf)[2] = (BYTE)((_pix) >> 16);
405 }
406 
407 static INLINE void write_pixel_16(BYTE* _buf, UINT16 _pix)
408 {
409  WINPR_ASSERT(_buf);
410  _buf[0] = _pix & 0xFF;
411  _buf[1] = (_pix >> 8) & 0xFF;
412 }
413 
414 #undef DESTWRITEPIXEL
415 #undef DESTREADPIXEL
416 #undef SRCREADPIXEL
417 #undef WRITEFGBGIMAGE
418 #undef WRITEFIRSTLINEFGBGIMAGE
419 #undef RLEDECOMPRESS
420 #undef RLEEXTRA
421 #undef WHITE_PIXEL
422 #undef PIXEL_SIZE
423 #undef PIXEL
424 #define PIXEL_SIZE 1
425 #define PIXEL BYTE
426 #define WHITE_PIXEL 0xFF
427 #define DESTWRITEPIXEL(_buf, _pix) \
428  do \
429  { \
430  write_pixel_8(_buf, _pix); \
431  (_buf) += 1; \
432  } while (0)
433 #define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0]
434 #define SRCREADPIXEL(_pix, _buf) \
435  do \
436  { \
437  (_pix) = (_buf)[0]; \
438  (_buf) += 1; \
439  } while (0)
440 
441 #define WRITEFGBGIMAGE WriteFgBgImage8to8
442 #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage8to8
443 #define RLEDECOMPRESS RleDecompress8to8
444 #define RLEEXTRA
445 #undef ENSURE_CAPACITY
446 #define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 1)
447 #include "include/bitmap.h"
448 
449 #undef DESTWRITEPIXEL
450 #undef DESTREADPIXEL
451 #undef SRCREADPIXEL
452 #undef WRITEFGBGIMAGE
453 #undef WRITEFIRSTLINEFGBGIMAGE
454 #undef RLEDECOMPRESS
455 #undef RLEEXTRA
456 #undef WHITE_PIXEL
457 #undef PIXEL_SIZE
458 #undef PIXEL
459 #define PIXEL_SIZE 2
460 #define PIXEL UINT16
461 #define WHITE_PIXEL 0xFFFF
462 #define DESTWRITEPIXEL(_buf, _pix) \
463  do \
464  { \
465  write_pixel_16(_buf, _pix); \
466  (_buf) += 2; \
467  } while (0)
468 #define DESTREADPIXEL(_pix, _buf) _pix = ((UINT16*)(_buf))[0]
469 #define SRCREADPIXEL(_pix, _buf) \
470  do \
471  { \
472  (_pix) = (_buf)[0] | ((_buf)[1] << 8); \
473  (_buf) += 2; \
474  } while (0)
475 #define WRITEFGBGIMAGE WriteFgBgImage16to16
476 #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage16to16
477 #define RLEDECOMPRESS RleDecompress16to16
478 #define RLEEXTRA
479 #undef ENSURE_CAPACITY
480 #define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 2)
481 #include "include/bitmap.h"
482 
483 #undef DESTWRITEPIXEL
484 #undef DESTREADPIXEL
485 #undef SRCREADPIXEL
486 #undef WRITEFGBGIMAGE
487 #undef WRITEFIRSTLINEFGBGIMAGE
488 #undef RLEDECOMPRESS
489 #undef RLEEXTRA
490 #undef WHITE_PIXEL
491 #undef PIXEL_SIZE
492 #undef PIXEL
493 #define PIXEL_SIZE 3
494 #define PIXEL UINT32
495 #define WHITE_PIXEL 0xffffff
496 #define DESTWRITEPIXEL(_buf, _pix) \
497  do \
498  { \
499  write_pixel_24(_buf, _pix); \
500  (_buf) += 3; \
501  } while (0)
502 #define DESTREADPIXEL(_pix, _buf) _pix = (_buf)[0] | ((_buf)[1] << 8) | ((_buf)[2] << 16)
503 #define SRCREADPIXEL(_pix, _buf) \
504  do \
505  { \
506  (_pix) = (_buf)[0] | ((_buf)[1] << 8) | ((_buf)[2] << 16); \
507  (_buf) += 3; \
508  } while (0)
509 
510 #define WRITEFGBGIMAGE WriteFgBgImage24to24
511 #define WRITEFIRSTLINEFGBGIMAGE WriteFirstLineFgBgImage24to24
512 #define RLEDECOMPRESS RleDecompress24to24
513 #define RLEEXTRA
514 #undef ENSURE_CAPACITY
515 #define ENSURE_CAPACITY(_start, _end, _size) ensure_capacity(_start, _end, _size, 3)
516 #include "include/bitmap.h"
517 
518 struct S_BITMAP_INTERLEAVED_CONTEXT
519 {
520  BOOL Compressor;
521 
522  UINT32 TempSize;
523  BYTE* TempBuffer;
524 
525  wStream* bts;
526 };
527 
528 BOOL interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved,
529  const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, UINT32 nSrcWidth,
530  UINT32 nSrcHeight, UINT32 bpp, BYTE* WINPR_RESTRICT pDstData,
531  UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
532  UINT32 nDstWidth, UINT32 nDstHeight,
533  const gdiPalette* WINPR_RESTRICT palette)
534 {
535  UINT32 scanline = 0;
536  UINT32 SrcFormat = 0;
537  UINT32 BufferSize = 0;
538 
539  if (!interleaved || !pSrcData || !pDstData)
540  {
541  WLog_ERR(TAG, "invalid arguments: interleaved=%p, pSrcData=%p, pDstData=%p", interleaved,
542  pSrcData, pDstData);
543  return FALSE;
544  }
545 
546  switch (bpp)
547  {
548  case 24:
549  scanline = nSrcWidth * 3;
550  SrcFormat = PIXEL_FORMAT_BGR24;
551  break;
552 
553  case 16:
554  scanline = nSrcWidth * 2;
555  SrcFormat = PIXEL_FORMAT_RGB16;
556  break;
557 
558  case 15:
559  scanline = nSrcWidth * 2;
560  SrcFormat = PIXEL_FORMAT_RGB15;
561  break;
562 
563  case 8:
564  scanline = nSrcWidth;
565  SrcFormat = PIXEL_FORMAT_RGB8;
566  break;
567 
568  default:
569  WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", bpp);
570  return FALSE;
571  }
572 
573  BufferSize = scanline * nSrcHeight;
574 
575  if (BufferSize > interleaved->TempSize)
576  {
577  interleaved->TempBuffer =
578  winpr_aligned_recalloc(interleaved->TempBuffer, BufferSize, sizeof(BYTE), 16);
579  interleaved->TempSize = BufferSize;
580  }
581 
582  if (!interleaved->TempBuffer)
583  {
584  WLog_ERR(TAG, "interleaved->TempBuffer=%p", interleaved->TempBuffer);
585  return FALSE;
586  }
587 
588  switch (bpp)
589  {
590  case 24:
591  if (!RleDecompress24to24(pSrcData, SrcSize, interleaved->TempBuffer, scanline,
592  nSrcWidth, nSrcHeight))
593  {
594  WLog_ERR(TAG, "RleDecompress24to24 failed");
595  return FALSE;
596  }
597 
598  break;
599 
600  case 16:
601  case 15:
602  if (!RleDecompress16to16(pSrcData, SrcSize, interleaved->TempBuffer, scanline,
603  nSrcWidth, nSrcHeight))
604  {
605  WLog_ERR(TAG, "RleDecompress16to16 failed");
606  return FALSE;
607  }
608 
609  break;
610 
611  case 8:
612  if (!RleDecompress8to8(pSrcData, SrcSize, interleaved->TempBuffer, scanline, nSrcWidth,
613  nSrcHeight))
614  {
615  WLog_ERR(TAG, "RleDecompress8to8 failed");
616  return FALSE;
617  }
618 
619  break;
620 
621  default:
622  WLog_ERR(TAG, "Invalid color depth %" PRIu32 "", bpp);
623  return FALSE;
624  }
625 
626  if (!freerdp_image_copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth,
627  nDstHeight, interleaved->TempBuffer, SrcFormat, scanline, 0,
628  0, palette, FREERDP_FLIP_VERTICAL | FREERDP_KEEP_DST_ALPHA))
629  {
630  WLog_ERR(TAG, "freerdp_image_copy failed");
631  return FALSE;
632  }
633  return TRUE;
634 }
635 
636 BOOL interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved,
637  BYTE* WINPR_RESTRICT pDstData, UINT32* WINPR_RESTRICT pDstSize,
638  UINT32 nWidth, UINT32 nHeight, const BYTE* WINPR_RESTRICT pSrcData,
639  UINT32 SrcFormat, UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
640  const gdiPalette* WINPR_RESTRICT palette, UINT32 bpp)
641 {
642  BOOL status = 0;
643  wStream* s = NULL;
644  UINT32 DstFormat = 0;
645  const UINT32 maxSize = 64 * 64 * 4;
646 
647  if (!interleaved || !pDstData || !pSrcData)
648  return FALSE;
649 
650  if ((nWidth == 0) || (nHeight == 0))
651  return FALSE;
652 
653  if (nWidth % 4)
654  {
655  WLog_ERR(TAG, "interleaved_compress: width is not a multiple of 4");
656  return FALSE;
657  }
658 
659  if ((nWidth > 64) || (nHeight > 64))
660  {
661  WLog_ERR(TAG,
662  "interleaved_compress: width (%" PRIu32 ") or height (%" PRIu32
663  ") is greater than 64",
664  nWidth, nHeight);
665  return FALSE;
666  }
667 
668  switch (bpp)
669  {
670  case 24:
671  DstFormat = PIXEL_FORMAT_BGRX32;
672  break;
673 
674  case 16:
675  DstFormat = PIXEL_FORMAT_RGB16;
676  break;
677 
678  case 15:
679  DstFormat = PIXEL_FORMAT_RGB15;
680  break;
681 
682  default:
683  return FALSE;
684  }
685 
686  if (!freerdp_image_copy_no_overlap(interleaved->TempBuffer, DstFormat, 0, 0, 0, nWidth, nHeight,
687  pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette,
688  FREERDP_KEEP_DST_ALPHA))
689  return FALSE;
690 
691  s = Stream_New(pDstData, *pDstSize);
692 
693  if (!s)
694  return FALSE;
695 
696  Stream_SetPosition(interleaved->bts, 0);
697 
698  if (freerdp_bitmap_compress(interleaved->TempBuffer, nWidth, nHeight, s, bpp, maxSize,
699  nHeight - 1, interleaved->bts, 0) < 0)
700  status = FALSE;
701  else
702  status = TRUE;
703 
704  Stream_SealLength(s);
705  *pDstSize = (UINT32)Stream_Length(s);
706  Stream_Free(s, FALSE);
707  return status;
708 }
709 
710 BOOL bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved)
711 {
712  if (!interleaved)
713  return FALSE;
714 
715  return TRUE;
716 }
717 
718 BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
719 {
720  BITMAP_INTERLEAVED_CONTEXT* interleaved = NULL;
721  interleaved = (BITMAP_INTERLEAVED_CONTEXT*)winpr_aligned_recalloc(
722  NULL, 1, sizeof(BITMAP_INTERLEAVED_CONTEXT), 32);
723 
724  if (interleaved)
725  {
726  interleaved->TempSize = 64 * 64 * 4;
727  interleaved->TempBuffer = winpr_aligned_calloc(interleaved->TempSize, sizeof(BYTE), 16);
728 
729  if (!interleaved->TempBuffer)
730  goto fail;
731 
732  interleaved->bts = Stream_New(NULL, interleaved->TempSize);
733 
734  if (!interleaved->bts)
735  goto fail;
736  }
737 
738  return interleaved;
739 
740 fail:
741  WINPR_PRAGMA_DIAG_PUSH
742  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
743  bitmap_interleaved_context_free(interleaved);
744  WINPR_PRAGMA_DIAG_POP
745  return NULL;
746 }
747 
748 void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* WINPR_RESTRICT interleaved)
749 {
750  if (!interleaved)
751  return;
752 
753  winpr_aligned_free(interleaved->TempBuffer);
754  Stream_Free(interleaved->bts, TRUE);
755  winpr_aligned_free(interleaved);
756 }