5#include <winpr/print.h>
6#include <winpr/crypto.h>
9#include <freerdp/freerdp.h>
10#include <freerdp/codec/color.h>
11#include <freerdp/codec/bitmap.h>
12#include <freerdp/codec/planar.h>
14static const UINT32 colorFormatList[] = {
15 PIXEL_FORMAT_RGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_BGR16,
16 PIXEL_FORMAT_RGB24, PIXEL_FORMAT_BGR24, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_ABGR32,
17 PIXEL_FORMAT_XRGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_RGBX32, PIXEL_FORMAT_BGRX32
20static const UINT32 colorFormatCount =
sizeof(colorFormatList) /
sizeof(colorFormatList[0]);
22static BOOL CompareBitmap(
const BYTE* srcA, UINT32 srcAFormat,
const BYTE* srcB, UINT32 srcBFormat,
23 UINT32 width, UINT32 height)
26 const UINT32 srcABits = FreeRDPGetBitsPerPixel(srcAFormat);
27 const UINT32 srcBBits = FreeRDPGetBitsPerPixel(srcBFormat);
28 UINT32 diff = WINPR_ASSERTING_INT_CAST(uint32_t, fabs((
double)srcABits - srcBBits));
31 if ((srcABits < 15) || (srcBBits < 15))
57 if ((srcABits == 32) || (srcBBits == 32))
63 for (
size_t y = 0; y < height; y++)
65 const BYTE* lineA = &srcA[y * width * FreeRDPGetBytesPerPixel(srcAFormat)];
66 const BYTE* lineB = &srcB[y * width * FreeRDPGetBytesPerPixel(srcBFormat)];
68 for (
size_t x = 0; x < width; x++)
78 const BYTE* a = &lineA[x * FreeRDPGetBytesPerPixel(srcAFormat)];
79 const BYTE* b = &lineB[x * FreeRDPGetBytesPerPixel(srcBFormat)];
80 UINT32 colorA = FreeRDPReadColor(a, srcAFormat);
81 UINT32 colorB = FreeRDPReadColor(b, srcBFormat);
82 FreeRDPSplitColor(colorA, srcAFormat, &sR, &sG, &sB, &sA, NULL);
83 FreeRDPSplitColor(colorB, srcBFormat, &dR, &dG, &dB, &dA, NULL);
85 if (fabs((
double)sR - dR) > maxDiff)
88 if (fabs((
double)sG - dG) > maxDiff)
91 if (fabs((
double)sB - dB) > maxDiff)
94 if (fabs((
double)sA - dA) > maxDiff)
102static char* get_path(
const char* type,
const char* name)
104 char path[500] = { 0 };
105 (void)snprintf(path,
sizeof(path),
"planar-%s-%s.bin", type, name);
106 char* s1 = GetCombinedPath(CMAKE_CURRENT_SOURCE_DIR,
"planar");
110 char* s2 = GetCombinedPath(s1, path);
115static void* read_data(
const char* type,
const char* name,
size_t* plength)
119 WINPR_ASSERT(plength);
125 char* path = get_path(type, name);
129 FILE* fp = winpr_fopen(path,
"rb");
134 if (_fseeki64(fp, 0, SEEK_END) != 0)
137 const size_t pos = _ftelli64(fp);
139 if (_fseeki64(fp, 0, SEEK_SET) != 0)
142 cmp = calloc(pos, 1);
146 if (fread(cmp, 1, pos, fp) != pos)
159static void write_data(
const char* type,
const char* name,
const void* data,
size_t length)
164 char* path = get_path(type, name);
168 FILE* fp = winpr_fopen(path,
"wb");
173 if (fwrite(data, 1, length, fp) != length)
180static BOOL compare(
const char* type,
const char* name,
const void* data,
size_t length)
184 void* cmp = read_data(type, name, &cmplen);
187 if (cmplen != length)
189 if (memcmp(data, cmp, length) != 0)
197static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* encplanar, BITMAP_PLANAR_CONTEXT* decplanar,
198 const char* name,
const UINT32 srcFormat,
const UINT32 dstFormat,
199 const UINT32 width,
const UINT32 height)
201 WINPR_ASSERT(encplanar);
202 WINPR_ASSERT(decplanar);
206 BYTE* srcBitmap = read_data(
"bmp", name, &srclen);
210 BYTE* compressedBitmap = freerdp_bitmap_compress_planar(encplanar, srcBitmap, srcFormat, width,
211 height, 0, NULL, &dstSize);
212 BYTE* decompressedBitmap =
213 (BYTE*)calloc(height, 1ULL * width * FreeRDPGetBytesPerPixel(dstFormat));
215 if (!compare(
"bmp", name, srcBitmap,
216 1ull * width * height * FreeRDPGetBytesPerPixel(srcFormat)))
219 if (!compare(
"enc", name, compressedBitmap, dstSize))
222 (void)printf(
"%s [%s] --> [%s]: ", __func__, FreeRDPGetColorFormatName(srcFormat),
223 FreeRDPGetColorFormatName(dstFormat));
225 if (!compressedBitmap || !decompressedBitmap)
228 if (!planar_decompress(decplanar, compressedBitmap, dstSize, width, height, decompressedBitmap,
229 dstFormat, 0, 0, 0, width, height, FALSE))
231 printf(
"failed to decompress experimental bitmap 01: width: %" PRIu32
" height: %" PRIu32
238 if (!compare(
"dec", name, decompressedBitmap,
239 1ull * width * height * FreeRDPGetBytesPerPixel(dstFormat)))
242 if (!CompareBitmap(decompressedBitmap, dstFormat, srcBitmap, srcFormat, width, height))
253 free(compressedBitmap);
254 free(decompressedBitmap);
256 (void)fflush(stdout);
260static BOOL RunTestPlanarSingleColor(BITMAP_PLANAR_CONTEXT* planar,
const UINT32 srcFormat,
261 const UINT32 dstFormat)
264 (void)printf(
"%s: [%s] --> [%s]: ", __func__, FreeRDPGetColorFormatName(srcFormat),
265 FreeRDPGetColorFormatName(dstFormat));
266 (void)fflush(stdout);
268 for (UINT32 j = 0; j < 32; j += 8)
270 for (UINT32 i = 4; i < 32; i += 8)
272 UINT32 compressedSize = 0;
273 const UINT32 fill = j;
274 const UINT32 color = FreeRDPGetColor(srcFormat, (fill >> 8) & 0xF, (fill >> 4) & 0xF,
276 const UINT32 width = i;
277 const UINT32 height = i;
279 const UINT32 srcSize = width * height * FreeRDPGetBytesPerPixel(srcFormat);
280 const UINT32 dstSize = width * height * FreeRDPGetBytesPerPixel(dstFormat);
281 BYTE* compressedBitmap = NULL;
282 BYTE* bmp = malloc(srcSize);
283 BYTE* decompressedBitmap = (BYTE*)malloc(dstSize);
285 if (!bmp || !decompressedBitmap)
288 for (
size_t y = 0; y < height; y++)
290 BYTE* line = &bmp[y * width * FreeRDPGetBytesPerPixel(srcFormat)];
292 for (
size_t x = 0; x < width; x++)
294 FreeRDPWriteColor(line, srcFormat, color);
295 line += FreeRDPGetBytesPerPixel(srcFormat);
299 compressedBitmap = freerdp_bitmap_compress_planar(planar, bmp, srcFormat, width, height,
300 0, NULL, &compressedSize);
302 if (!compressedBitmap)
305 if (!planar_decompress(planar, compressedBitmap, compressedSize, width, height,
306 decompressedBitmap, dstFormat, 0, 0, 0, width, height, FALSE))
309 if (!CompareBitmap(decompressedBitmap, dstFormat, bmp, srcFormat, width, height))
315 free(compressedBitmap);
316 free(decompressedBitmap);
326 (void)printf(
"SUCCESS");
330 (void)fflush(stdout);
334static BOOL TestPlanar(
const UINT32 format)
337 const DWORD planarFlags = PLANAR_FORMAT_HEADER_NA | PLANAR_FORMAT_HEADER_RLE;
338 BITMAP_PLANAR_CONTEXT* encplanar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
339 BITMAP_PLANAR_CONTEXT* decplanar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
341 if (!encplanar || !decplanar)
344 if (!RunTestPlanar(encplanar, decplanar,
"TEST_RLE_BITMAP_EXPERIMENTAL_01", PIXEL_FORMAT_RGBX32,
348 if (!RunTestPlanar(encplanar, decplanar,
"TEST_RLE_BITMAP_EXPERIMENTAL_02", PIXEL_FORMAT_RGBX32,
352 if (!RunTestPlanar(encplanar, decplanar,
"TEST_RLE_BITMAP_EXPERIMENTAL_03", PIXEL_FORMAT_RGBX32,
356 if (!RunTestPlanar(encplanar, decplanar,
"TEST_RLE_UNCOMPRESSED_BITMAP_16BPP",
357 PIXEL_FORMAT_RGB16, format, 32, 32))
360 for (UINT32 x = 0; x < colorFormatCount; x++)
362 if (!RunTestPlanarSingleColor(encplanar, format, colorFormatList[x]))
368 freerdp_bitmap_planar_context_free(encplanar);
369 freerdp_bitmap_planar_context_free(decplanar);
373static UINT32 prand(UINT32 max)
378 winpr_RAND(&tmp,
sizeof(tmp));
379 return tmp % (max - 1) + 1;
382static BOOL FuzzPlanar(
void)
385 const DWORD planarFlags = PLANAR_FORMAT_HEADER_NA | PLANAR_FORMAT_HEADER_RLE;
386 BITMAP_PLANAR_CONTEXT* planar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
391 for (UINT32 x = 0; x < 100; x++)
393 BYTE data[0x10000] = { 0 };
394 size_t dataSize = 0x10000;
395 BYTE dstData[0x10000] = { 0 };
397 UINT32 DstFormat = 0;
401 UINT32 nDstWidth = 0;
402 UINT32 nDstHeight = 0;
406 switch (prand(17) - 1)
409 DstFormat = PIXEL_FORMAT_RGB8;
412 DstFormat = PIXEL_FORMAT_BGR15;
415 DstFormat = PIXEL_FORMAT_RGB15;
418 DstFormat = PIXEL_FORMAT_ABGR15;
421 DstFormat = PIXEL_FORMAT_ABGR15;
424 DstFormat = PIXEL_FORMAT_BGR16;
427 DstFormat = PIXEL_FORMAT_RGB16;
430 DstFormat = PIXEL_FORMAT_BGR24;
433 DstFormat = PIXEL_FORMAT_RGB24;
436 DstFormat = PIXEL_FORMAT_BGRA32;
439 DstFormat = PIXEL_FORMAT_BGRX32;
442 DstFormat = PIXEL_FORMAT_RGBA32;
445 DstFormat = PIXEL_FORMAT_RGBX32;
448 DstFormat = PIXEL_FORMAT_ABGR32;
451 DstFormat = PIXEL_FORMAT_XBGR32;
454 DstFormat = PIXEL_FORMAT_ARGB32;
457 DstFormat = PIXEL_FORMAT_XRGB32;
462 nDstStep = prand(
sizeof(dstData));
463 nXDst = prand(nDstStep);
464 nYDst = prand(
sizeof(dstData) / nDstStep);
465 nDstWidth = prand(nDstStep / FreeRDPGetBytesPerPixel(DstFormat));
466 nDstHeight = prand(
sizeof(dstData) / nDstStep);
467 invalid = nXDst * FreeRDPGetBytesPerPixel(DstFormat) + (nYDst + nDstHeight) * nDstStep >
470 printf(
"DstFormat=%s, nXDst=%" PRIu32
", nYDst=%" PRIu32
", nDstWidth=%" PRIu32
471 ", nDstHeight=%" PRIu32
", nDstStep=%" PRIu32
", total size=%" PRIuz
"\n",
472 FreeRDPGetColorFormatName(DstFormat), nXDst, nYDst, nDstWidth, nDstHeight, nDstStep,
474 freerdp_planar_switch_bgr(planar, ((prand(2) % 2) != 0) ? TRUE : FALSE);
475 planar_decompress(planar, data, dataSize, prand(4096), prand(4096), dstData, DstFormat,
476 nDstStep, nXDst, nYDst, nDstWidth, nDstHeight,
477 ((prand(2) % 2) != 0) ? TRUE : FALSE);
482 freerdp_bitmap_planar_context_free(planar);
486int TestFreeRDPCodecPlanar(
int argc,
char* argv[])
495 for (UINT32 x = 0; x < colorFormatCount; x++)
497 if (!TestPlanar(colorFormatList[x]))
503 printf(
"test returned %d\n", rc);