FreeRDP
libfreerdp/codec/include/bitmap.h
1 
22 /* do not compile the file directly */
23 
27 static INLINE BYTE* WRITEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
28  const BYTE* WINPR_RESTRICT pbDestEnd, UINT32 rowDelta,
29  BYTE bitmask, PIXEL fgPel, INT32 cBits)
30 {
31  PIXEL xorPixel;
32  BYTE mask = 0x01;
33 
34  if (cBits > 8)
35  {
36  WLog_ERR(TAG, "cBits %d > 8", cBits);
37  return NULL;
38  }
39 
40  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
41  return NULL;
42 
43  UNROLL(cBits, {
44  UINT32 data;
45  DESTREADPIXEL(xorPixel, pbDest - rowDelta);
46 
47  if (bitmask & mask)
48  data = xorPixel ^ fgPel;
49  else
50  data = xorPixel;
51 
52  DESTWRITEPIXEL(pbDest, data);
53  mask = mask << 1;
54  });
55  return pbDest;
56 }
57 
62 static INLINE BYTE* WRITEFIRSTLINEFGBGIMAGE(BYTE* WINPR_RESTRICT pbDest,
63  const BYTE* WINPR_RESTRICT pbDestEnd, BYTE bitmask,
64  PIXEL fgPel, UINT32 cBits)
65 {
66  BYTE mask = 0x01;
67 
68  if (cBits > 8)
69  {
70  WLog_ERR(TAG, "cBits %d > 8", cBits);
71  return NULL;
72  }
73 
74  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, cBits))
75  return NULL;
76 
77  UNROLL(cBits, {
78  UINT32 data;
79 
80  if (bitmask & mask)
81  data = fgPel;
82  else
83  data = BLACK_PIXEL;
84 
85  DESTWRITEPIXEL(pbDest, data);
86  mask = mask << 1;
87  });
88  return pbDest;
89 }
90 
94 static INLINE BOOL RLEDECOMPRESS(const BYTE* WINPR_RESTRICT pbSrcBuffer, UINT32 cbSrcBuffer,
95  BYTE* WINPR_RESTRICT pbDestBuffer, UINT32 rowDelta, UINT32 width,
96  UINT32 height)
97 {
98 #if defined(WITH_DEBUG_CODECS)
99  char sbuffer[128] = { 0 };
100 #endif
101  const BYTE* pbSrc = pbSrcBuffer;
102  const BYTE* pbEnd;
103  const BYTE* pbDestEnd;
104  BYTE* pbDest = pbDestBuffer;
105  PIXEL temp;
106  PIXEL fgPel = WHITE_PIXEL;
107  BOOL fInsertFgPel = FALSE;
108  BOOL fFirstLine = TRUE;
109  BYTE bitmask;
110  PIXEL pixelA, pixelB;
111  UINT32 runLength;
112  UINT32 code;
113  UINT32 advance = 0;
114  RLEEXTRA
115 
116  if ((rowDelta == 0) || (rowDelta < width))
117  {
118  WLog_ERR(TAG, "Invalid arguments: rowDelta=%" PRIu32 " == 0 || < width=%" PRIu32, rowDelta,
119  width);
120  return FALSE;
121  }
122 
123  if (!pbSrcBuffer || !pbDestBuffer)
124  {
125  WLog_ERR(TAG, "Invalid arguments: pbSrcBuffer=%p, pbDestBuffer=%p", pbSrcBuffer,
126  pbDestBuffer);
127  return FALSE;
128  }
129 
130  pbEnd = pbSrcBuffer + cbSrcBuffer;
131  pbDestEnd = pbDestBuffer + rowDelta * height;
132 
133  while (pbSrc < pbEnd)
134  {
135  /* Watch out for the end of the first scanline. */
136  if (fFirstLine)
137  {
138  if ((UINT32)(pbDest - pbDestBuffer) >= rowDelta)
139  {
140  fFirstLine = FALSE;
141  fInsertFgPel = FALSE;
142  }
143  }
144 
145  /*
146  Extract the compression order code ID from the compression
147  order header.
148  */
149  code = ExtractCodeId(*pbSrc);
150 
151 #if defined(WITH_DEBUG_CODECS)
152  WLog_VRB(TAG, "pbSrc=%p code=%s, rem=%" PRIuz, pbSrc,
153  rle_code_str_buffer(code, sbuffer, sizeof(sbuffer)), pbEnd - pbSrc);
154 #endif
155 
156  /* Handle Background Run Orders. */
157  if ((code == REGULAR_BG_RUN) || (code == MEGA_MEGA_BG_RUN))
158  {
159  runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
160  if (advance == 0)
161  return FALSE;
162  pbSrc = pbSrc + advance;
163 
164  if (fFirstLine)
165  {
166  if (fInsertFgPel)
167  {
168  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
169  return FALSE;
170 
171  DESTWRITEPIXEL(pbDest, fgPel);
172  runLength = runLength - 1;
173  }
174 
175  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
176  return FALSE;
177 
178  UNROLL(runLength, { DESTWRITEPIXEL(pbDest, BLACK_PIXEL); });
179  }
180  else
181  {
182  if (fInsertFgPel)
183  {
184  DESTREADPIXEL(temp, pbDest - rowDelta);
185 
186  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
187  return FALSE;
188 
189  DESTWRITEPIXEL(pbDest, temp ^ fgPel);
190  runLength--;
191  }
192 
193  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
194  return FALSE;
195 
196  UNROLL(runLength, {
197  DESTREADPIXEL(temp, pbDest - rowDelta);
198  DESTWRITEPIXEL(pbDest, temp);
199  });
200  }
201 
202  /* A follow-on background run order will need a foreground pel inserted. */
203  fInsertFgPel = TRUE;
204  continue;
205  }
206 
207  /* For any of the other run-types a follow-on background run
208  order does not need a foreground pel inserted. */
209  fInsertFgPel = FALSE;
210 
211  switch (code)
212  {
213  /* Handle Foreground Run Orders. */
214  case REGULAR_FG_RUN:
215  case MEGA_MEGA_FG_RUN:
216  case LITE_SET_FG_FG_RUN:
217  case MEGA_MEGA_SET_FG_RUN:
218  runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
219  if (advance == 0)
220  return FALSE;
221  pbSrc = pbSrc + advance;
222 
223  if (code == LITE_SET_FG_FG_RUN || code == MEGA_MEGA_SET_FG_RUN)
224  {
225  if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
226  return FALSE;
227  SRCREADPIXEL(fgPel, pbSrc);
228  }
229 
230  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
231  return FALSE;
232 
233  if (fFirstLine)
234  {
235  UNROLL(runLength, { DESTWRITEPIXEL(pbDest, fgPel); });
236  }
237  else
238  {
239  UNROLL(runLength, {
240  DESTREADPIXEL(temp, pbDest - rowDelta);
241  DESTWRITEPIXEL(pbDest, temp ^ fgPel);
242  });
243  }
244 
245  break;
246 
247  /* Handle Dithered Run Orders. */
248  case LITE_DITHERED_RUN:
249  case MEGA_MEGA_DITHERED_RUN:
250  runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
251  if (advance == 0)
252  return FALSE;
253  pbSrc = pbSrc + advance;
254  if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
255  return FALSE;
256  SRCREADPIXEL(pixelA, pbSrc);
257  if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
258  return FALSE;
259  SRCREADPIXEL(pixelB, pbSrc);
260 
261  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength * 2))
262  return FALSE;
263 
264  UNROLL(runLength, {
265  DESTWRITEPIXEL(pbDest, pixelA);
266  DESTWRITEPIXEL(pbDest, pixelB);
267  });
268  break;
269 
270  /* Handle Color Run Orders. */
271  case REGULAR_COLOR_RUN:
272  case MEGA_MEGA_COLOR_RUN:
273  runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
274  if (advance == 0)
275  return FALSE;
276  pbSrc = pbSrc + advance;
277  if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
278  return FALSE;
279  SRCREADPIXEL(pixelA, pbSrc);
280 
281  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
282  return FALSE;
283 
284  UNROLL(runLength, { DESTWRITEPIXEL(pbDest, pixelA); });
285  break;
286 
287  /* Handle Foreground/Background Image Orders. */
288  case REGULAR_FGBG_IMAGE:
289  case MEGA_MEGA_FGBG_IMAGE:
290  case LITE_SET_FG_FGBG_IMAGE:
291  case MEGA_MEGA_SET_FGBG_IMAGE:
292  runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
293  if (advance == 0)
294  return FALSE;
295  pbSrc = pbSrc + advance;
296 
297  if (code == LITE_SET_FG_FGBG_IMAGE || code == MEGA_MEGA_SET_FGBG_IMAGE)
298  {
299  if (!buffer_within_range(pbSrc, PIXEL_SIZE, pbEnd))
300  return FALSE;
301  SRCREADPIXEL(fgPel, pbSrc);
302  }
303 
304  if (!buffer_within_range(pbSrc, runLength / 8, pbEnd))
305  return FALSE;
306  if (fFirstLine)
307  {
308  while (runLength > 8)
309  {
310  bitmask = *pbSrc;
311  pbSrc = pbSrc + 1;
312  pbDest = WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, 8);
313 
314  if (!pbDest)
315  return FALSE;
316 
317  runLength = runLength - 8;
318  }
319  }
320  else
321  {
322  while (runLength > 8)
323  {
324  bitmask = *pbSrc++;
325 
326  pbDest = WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, 8);
327 
328  if (!pbDest)
329  return FALSE;
330 
331  runLength = runLength - 8;
332  }
333  }
334 
335  if (runLength > 0)
336  {
337  if (!buffer_within_range(pbSrc, 1, pbEnd))
338  return FALSE;
339  bitmask = *pbSrc++;
340 
341  if (fFirstLine)
342  {
343  pbDest =
344  WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, bitmask, fgPel, runLength);
345  }
346  else
347  {
348  pbDest =
349  WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, bitmask, fgPel, runLength);
350  }
351 
352  if (!pbDest)
353  return FALSE;
354  }
355 
356  break;
357 
358  /* Handle Color Image Orders. */
359  case REGULAR_COLOR_IMAGE:
360  case MEGA_MEGA_COLOR_IMAGE:
361  runLength = ExtractRunLength(code, pbSrc, pbEnd, &advance);
362  if (advance == 0)
363  return FALSE;
364  pbSrc = pbSrc + advance;
365  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, runLength))
366  return FALSE;
367  if (!ENSURE_CAPACITY(pbSrc, pbEnd, runLength))
368  return FALSE;
369 
370  UNROLL(runLength, {
371  SRCREADPIXEL(temp, pbSrc);
372  DESTWRITEPIXEL(pbDest, temp);
373  });
374  break;
375 
376  /* Handle Special Order 1. */
377  case SPECIAL_FGBG_1:
378  if (!buffer_within_range(pbSrc, 1, pbEnd))
379  return FALSE;
380  pbSrc = pbSrc + 1;
381 
382  if (fFirstLine)
383  {
384  pbDest =
385  WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg1, fgPel, 8);
386  }
387  else
388  {
389  pbDest =
390  WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg1, fgPel, 8);
391  }
392 
393  if (!pbDest)
394  return FALSE;
395 
396  break;
397 
398  /* Handle Special Order 2. */
399  case SPECIAL_FGBG_2:
400  if (!buffer_within_range(pbSrc, 1, pbEnd))
401  return FALSE;
402  pbSrc = pbSrc + 1;
403 
404  if (fFirstLine)
405  {
406  pbDest =
407  WRITEFIRSTLINEFGBGIMAGE(pbDest, pbDestEnd, g_MaskSpecialFgBg2, fgPel, 8);
408  }
409  else
410  {
411  pbDest =
412  WRITEFGBGIMAGE(pbDest, pbDestEnd, rowDelta, g_MaskSpecialFgBg2, fgPel, 8);
413  }
414 
415  if (!pbDest)
416  return FALSE;
417 
418  break;
419 
420  /* Handle White Order. */
421  case SPECIAL_WHITE:
422  if (!buffer_within_range(pbSrc, 1, pbEnd))
423  return FALSE;
424  pbSrc = pbSrc + 1;
425 
426  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
427  return FALSE;
428 
429  DESTWRITEPIXEL(pbDest, WHITE_PIXEL);
430  break;
431 
432  /* Handle Black Order. */
433  case SPECIAL_BLACK:
434  if (!buffer_within_range(pbSrc, 1, pbEnd))
435  return FALSE;
436  pbSrc = pbSrc + 1;
437 
438  if (!ENSURE_CAPACITY(pbDest, pbDestEnd, 1))
439  return FALSE;
440 
441  DESTWRITEPIXEL(pbDest, BLACK_PIXEL);
442  break;
443 
444  default:
445  WLog_ERR(TAG, "invalid code 0x%08" PRIx32 ", pbSrcBuffer=%p, pbSrc=%p, pbEnd=%p",
446  code, pbSrcBuffer, pbSrc, pbEnd);
447  return FALSE;
448  }
449  }
450 
451  return TRUE;
452 }