#include #include #include #include #include #include #include #include #include #include #include "../progressive.h" /** * Microsoft Progressive Codec Sample Data * (available under NDA only) * * ____. * * readme.pdf * * bitmaps/ * 1920by1080-SampleImage1.bmp * 1920by1080-SampleImage2.bmp * 1920by1080-SampleImage3.bmp * * compress/ * enc_0_0_025_sampleimage1.bin * enc_0_0_050_sampleimage1.bin * enc_0_0_075_sampleimage1.bin * enc_0_0_100_sampleimage1.bin * enc_0_1_025_sampleimage1.bin * enc_0_1_050_sampleimage1.bin * enc_0_1_075_sampleimage1.bin * enc_0_1_100_sampleimage1.bin * enc_0_2_025_sampleimage1.bin * enc_0_2_050_sampleimage1.bin * enc_0_2_075_sampleimage1.bin * enc_0_2_100_sampleimage1.bin * enc_0_3_025_sampleimage1.bin * enc_0_3_050_sampleimage1.bin * enc_0_3_075_sampleimage1.bin * enc_0_3_100_sampleimage1.bin * enc_1_0_025_sampleimage2.bin * enc_1_0_050_sampleimage2.bin * enc_1_0_075_sampleimage2.bin * enc_1_0_100_sampleimage2.bin * enc_1_1_025_sampleimage2.bin * enc_1_1_050_sampleimage2.bin * enc_1_1_075_sampleimage2.bin * enc_1_1_100_sampleimage2.bin * enc_1_2_025_sampleimage2.bin * enc_1_2_050_sampleimage2.bin * enc_1_2_075_sampleimage2.bin * enc_1_2_100_sampleimage2.bin * enc_1_3_025_sampleimage2.bin * enc_1_3_050_sampleimage2.bin * enc_1_3_075_sampleimage2.bin * enc_1_3_100_sampleimage2.bin * enc_2_0_025_sampleimage3.bin * enc_2_0_050_sampleimage3.bin * enc_2_0_075_sampleimage3.bin * enc_2_0_100_sampleimage3.bin * enc_2_1_025_sampleimage3.bin * enc_2_1_050_sampleimage3.bin * enc_2_1_075_sampleimage3.bin * enc_2_1_100_sampleimage3.bin * enc_2_2_025_sampleimage3.bin * enc_2_2_050_sampleimage3.bin * enc_2_2_075_sampleimage3.bin * enc_2_2_100_sampleimage3.bin * enc_2_3_025_sampleimage3.bin * enc_2_3_050_sampleimage3.bin * enc_2_3_075_sampleimage3.bin * enc_2_3_100_sampleimage3.bin * * decompress/ * dec_0_0_025_sampleimage1.bmp * dec_0_0_050_sampleimage1.bmp * dec_0_0_075_sampleimage1.bmp * dec_0_0_100_sampleimage1.bmp * dec_0_1_025_sampleimage1.bmp * dec_0_1_050_sampleimage1.bmp * dec_0_1_075_sampleimage1.bmp * dec_0_1_100_sampleimage1.bmp * dec_0_2_025_sampleimage1.bmp * dec_0_2_050_sampleimage1.bmp * dec_0_2_075_sampleimage1.bmp * dec_0_2_100_sampleimage1.bmp * dec_0_3_025_sampleimage1.bmp * dec_0_3_050_sampleimage1.bmp * dec_0_3_075_sampleimage1.bmp * dec_0_3_100_sampleimage1.bmp * dec_1_0_025_sampleimage2.bmp * dec_1_0_050_sampleimage2.bmp * dec_1_0_075_sampleimage2.bmp * dec_1_0_100_sampleimage2.bmp * dec_1_1_025_sampleimage2.bmp * dec_1_1_050_sampleimage2.bmp * dec_1_1_075_sampleimage2.bmp * dec_1_1_100_sampleimage2.bmp * dec_1_2_025_sampleimage2.bmp * dec_1_2_050_sampleimage2.bmp * dec_1_2_075_sampleimage2.bmp * dec_1_2_100_sampleimage2.bmp * dec_1_3_025_sampleimage2.bmp * dec_1_3_050_sampleimage2.bmp * dec_1_3_075_sampleimage2.bmp * dec_1_3_100_sampleimage2.bmp * dec_2_0_025_sampleimage3.bmp * dec_2_0_050_sampleimage3.bmp * dec_2_0_075_sampleimage3.bmp * dec_2_0_100_sampleimage3.bmp * dec_2_1_025_sampleimage3.bmp * dec_2_1_050_sampleimage3.bmp * dec_2_1_075_sampleimage3.bmp * dec_2_1_100_sampleimage3.bmp * dec_2_2_025_sampleimage3.bmp * dec_2_2_050_sampleimage3.bmp * dec_2_2_075_sampleimage3.bmp * dec_2_2_100_sampleimage3.bmp * dec_2_3_025_sampleimage3.bmp * dec_2_3_050_sampleimage3.bmp * dec_2_3_075_sampleimage3.bmp * dec_2_3_100_sampleimage3.bmp */ typedef struct { BYTE* buffer; size_t size; } EGFX_SAMPLE_FILE; static int g_Width = 0; static int g_Height = 0; static int g_DstStep = 0; static BYTE* g_DstData = NULL; static void sample_file_free(EGFX_SAMPLE_FILE* file) { if (!file) return; free(file->buffer); file->buffer = NULL; file->size = 0; } static void test_fill_image_alpha_channel(BYTE* data, int width, int height, BYTE value) { UINT32* pixel = NULL; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { pixel = (UINT32*)&data[((i * width) + j) * 4]; *pixel = ((*pixel & 0x00FFFFFF) | (value << 24)); } } } static void* test_image_memset32(UINT32* ptr, UINT32 fill, size_t length) { while (length--) { *ptr++ = fill; } return (void*)ptr; } static int test_image_fill(BYTE* pDstData, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, UINT32 color) { UINT32* pDstPixel = NULL; if (nDstStep < 0) nDstStep = 4 * nWidth; for (int y = 0; y < nHeight; y++) { pDstPixel = (UINT32*)&pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)]; test_image_memset32(pDstPixel, color, nWidth); } return 1; } static int test_image_fill_quarter(BYTE* pDstData, int nDstStep, int nWidth, int nHeight, UINT32 color, int quarter) { int x = 0; int y = 0; int width = 0; int height = 0; switch (quarter) { case 0: x = 0; y = 0; width = nWidth / 2; height = nHeight / 2; break; case 1: x = nWidth / 2; y = nHeight / 2; width = nWidth / 2; height = nHeight / 2; break; case 2: x = 0; y = nHeight / 2; width = nWidth / 2; height = nHeight / 2; break; case 3: x = nWidth / 2; y = 0; width = nWidth / 2; height = nHeight / 2; break; } test_image_fill(pDstData, nDstStep, x, y, width, height, 0xFF000000); return 1; } static int test_image_fill_unused_quarters(BYTE* pDstData, int nDstStep, int nWidth, int nHeight, UINT32 color, int quarter) { return 1; if (quarter == 0) { test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 2); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 3); } else if (quarter == 1) { test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 0); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 2); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 3); } else if (quarter == 2) { test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 0); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 3); } else if (quarter == 3) { test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 0); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1); test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 2); } return 1; } static BYTE* test_progressive_load_file(const char* path, const char* file, size_t* size) { char* filename = GetCombinedPath(path, file); if (!filename) return NULL; FILE* fp = winpr_fopen(filename, "r"); free(filename); if (!fp) return NULL; _fseeki64(fp, 0, SEEK_END); const INT64 pos = _ftelli64(fp); WINPR_ASSERT(pos >= 0); WINPR_ASSERT(pos <= SIZE_MAX); *size = (size_t)pos; _fseeki64(fp, 0, SEEK_SET); BYTE* buffer = (BYTE*)malloc(*size); if (!buffer) { fclose(fp); return NULL; } if (fread(buffer, *size, 1, fp) != 1) { free(buffer); fclose(fp); return NULL; } fclose(fp); return buffer; } static int test_progressive_load_files(char* ms_sample_path, EGFX_SAMPLE_FILE files[3][4][4]) { int imageNo = 0; int quarterNo = 0; int passNo = 0; /* image 1 */ files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_0_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_0_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_0_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_0_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_1_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_1_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_1_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_1_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_2_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_2_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_2_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_2_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_3_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_3_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_3_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_0_3_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; imageNo++; /* image 2 */ files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_0_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_0_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_0_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_0_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_1_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_1_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_1_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_1_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_2_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_2_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_2_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_2_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_3_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_3_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_3_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_1_3_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; imageNo++; /* image 3 */ files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_0_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_0_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_0_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_0_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_1_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_1_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_1_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_1_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_2_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_2_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_2_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_2_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_3_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_3_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_3_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); passNo = (passNo + 1) % 4; files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, "compress/enc_2_3_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); /* check if all test data has been loaded */ for (imageNo = 0; imageNo < 3; imageNo++) { for (quarterNo = 0; quarterNo < 4; quarterNo++) { for (passNo = 0; passNo < 4; passNo++) { if (!files[imageNo][quarterNo][passNo].buffer) return -1; } } } return 1; } static BYTE* test_progressive_load_bitmap(char* path, char* file, size_t* size, int quarter) { int status = 0; BYTE* buffer = NULL; wImage* image = NULL; char* filename = NULL; filename = GetCombinedPath(path, file); if (!filename) return NULL; image = winpr_image_new(); if (!image) return NULL; status = winpr_image_read(image, filename); if (status < 0) return NULL; buffer = image->data; *size = image->height * image->scanline; test_fill_image_alpha_channel(image->data, image->width, image->height, 0xFF); test_image_fill_unused_quarters(image->data, image->scanline, image->width, image->height, quarter, 0xFF000000); winpr_image_free(image, FALSE); free(filename); return buffer; } static int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps[3][4][4]) { int imageNo = 0; int quarterNo = 0; int passNo = 0; /* image 1 */ bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_0_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_0_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_0_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_0_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_1_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_1_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_1_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_1_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_2_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_2_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_2_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_2_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_3_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_3_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_3_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_0_3_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; imageNo++; /* image 2 */ bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_0_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_0_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_0_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_0_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_1_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_1_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_1_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_1_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_2_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_2_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_2_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_2_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_3_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_3_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_3_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_1_3_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; imageNo++; /* image 3 */ bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_0_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_0_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_0_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_0_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_1_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_1_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_1_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_1_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_2_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_2_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_2_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_2_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_3_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_3_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_3_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, "decompress/dec_2_3_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); /* check if all test data has been loaded */ for (imageNo = 0; imageNo < 3; imageNo++) { for (quarterNo = 0; quarterNo < 4; quarterNo++) { for (passNo = 0; passNo < 4; passNo++) { if (!bitmaps[imageNo][quarterNo][passNo].buffer) return -1; } } } return 1; } static size_t test_memcmp_count(const BYTE* mem1, const BYTE* mem2, size_t size, int margin) { size_t count = 0; for (size_t index = 0; index < size; index++) { if (*mem1 != *mem2) { const int error = (*mem1 > *mem2) ? *mem1 - *mem2 : *mem2 - *mem1; if (error > margin) count++; } mem1++; mem2++; } return count; } static int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], EGFX_SAMPLE_FILE bitmaps[4], int quarter, int count) { int nXSrc = 0; int nYSrc = 0; RECTANGLE_16 clippingRect = { 0 }; clippingRect.right = g_Width; clippingRect.bottom = g_Height; for (int pass = 0; pass < count; pass++) { const int status = progressive_decompress(progressive, files[pass].buffer, files[pass].size, g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, NULL, 0, 0); printf("ProgressiveDecompress: status: %d pass: %d\n", status, pass + 1); PROGRESSIVE_BLOCK_REGION* region = &(progressive->region); switch (quarter) { case 0: clippingRect.left = 0; clippingRect.top = 0; clippingRect.right = g_Width / 2; clippingRect.bottom = g_Height / 2; break; case 1: clippingRect.left = g_Width / 2; clippingRect.top = g_Height / 2; clippingRect.right = g_Width; clippingRect.bottom = g_Height; break; case 2: clippingRect.left = 0; clippingRect.top = g_Height / 2; clippingRect.right = g_Width / 2; clippingRect.bottom = g_Height; break; case 3: clippingRect.left = g_Width / 2; clippingRect.top = 0; clippingRect.right = g_Width; clippingRect.bottom = g_Height / 2; break; } for (UINT16 index = 0; index < region->numTiles; index++) { RFX_PROGRESSIVE_TILE* tile = region->tiles[index]; const RECTANGLE_16 tileRect = { tile->x, tile->y, tile->x + tile->width, tile->y + tile->height }; RECTANGLE_16 updateRect = { 0 }; rectangles_intersection(&tileRect, &clippingRect, &updateRect); const UINT16 nXDst = updateRect.left; const UINT16 nYDst = updateRect.top; const UINT16 nWidth = updateRect.right - updateRect.left; const UINT16 nHeight = updateRect.bottom - updateRect.top; if ((nWidth <= 0) || (nHeight <= 0)) continue; nXSrc = nXDst - tile->x; nYSrc = nYDst - tile->y; freerdp_image_copy(g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, nXDst, nYDst, nWidth, nHeight, tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc, NULL, FREERDP_FLIP_NONE); } const size_t size = bitmaps[pass].size; const size_t cnt = test_memcmp_count(g_DstData, bitmaps[pass].buffer, size, 1); if (cnt) { const float rate = ((float)cnt) / ((float)size) * 100.0f; printf("Progressive RemoteFX decompression failure\n"); printf("Actual, Expected (%" PRIuz "/%" PRIuz " = %.3f%%):\n", cnt, size, rate); } // WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32); } return 1; } static int test_progressive_ms_sample(char* ms_sample_path) { int count = 0; int status = 0; EGFX_SAMPLE_FILE files[3][4][4] = { 0 }; EGFX_SAMPLE_FILE bitmaps[3][4][4] = { 0 }; PROGRESSIVE_CONTEXT* progressive = NULL; g_Width = 1920; g_Height = 1080; g_DstStep = g_Width * 4; status = test_progressive_load_files(ms_sample_path, files); if (status < 0) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) sample_file_free(&files[i][j][k]); } } return -1; } status = test_progressive_load_bitmaps(ms_sample_path, bitmaps); if (status < 0) { for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) sample_file_free(&files[i][j][k]); } } return -1; } count = 4; progressive = progressive_context_new(FALSE); g_DstData = winpr_aligned_malloc(g_DstStep * g_Height, 16); progressive_create_surface_context(progressive, 0, g_Width, g_Height); /* image 1 */ if (1) { printf("\nSample Image 1\n"); test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[0][0], bitmaps[0][0], 0, count); test_progressive_decode(progressive, files[0][1], bitmaps[0][1], 1, count); test_progressive_decode(progressive, files[0][2], bitmaps[0][2], 2, count); test_progressive_decode(progressive, files[0][3], bitmaps[0][3], 3, count); } /* image 2 */ if (0) { printf("\nSample Image 2\n"); /* sample data is in incorrect order */ test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[1][0], bitmaps[1][0], 0, count); test_progressive_decode(progressive, files[1][1], bitmaps[1][1], 1, count); test_progressive_decode(progressive, files[1][2], bitmaps[1][2], 2, count); test_progressive_decode(progressive, files[1][3], bitmaps[1][3], 3, count); } /* image 3 */ if (0) { printf("\nSample Image 3\n"); /* sample data is in incorrect order */ test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[2][0], bitmaps[2][0], 0, count); test_progressive_decode(progressive, files[2][1], bitmaps[2][1], 1, count); test_progressive_decode(progressive, files[2][2], bitmaps[2][2], 2, count); test_progressive_decode(progressive, files[2][3], bitmaps[2][3], 3, count); } progressive_context_free(progressive); for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { sample_file_free(&bitmaps[i][j][k]); sample_file_free(&files[i][j][k]); } } } winpr_aligned_free(g_DstData); return 0; } static BOOL diff(BYTE a, BYTE b) { BYTE big = MAX(a, b); BYTE little = MIN(a, b); if (big - little <= 0x25) return TRUE; return FALSE; } static BOOL colordiff(UINT32 format, UINT32 a, UINT32 b) { BYTE ar = 0; BYTE ag = 0; BYTE ab = 0; BYTE aa = 0; BYTE br = 0; BYTE bg = 0; BYTE bb = 0; BYTE ba = 0; FreeRDPSplitColor(a, format, &ar, &ag, &ab, &aa, NULL); FreeRDPSplitColor(b, format, &br, &bg, &bb, &ba, NULL); if (!diff(aa, ba) || !diff(ar, br) || !diff(ag, bg) || !diff(ab, bb)) return FALSE; return TRUE; } static BOOL test_encode_decode(const char* path) { BOOL res = FALSE; int rc = 0; BYTE* resultData = NULL; BYTE* dstData = NULL; UINT32 dstSize = 0; UINT32 ColorFormat = PIXEL_FORMAT_BGRX32; REGION16 invalidRegion = { 0 }; wImage* image = winpr_image_new(); wImage* dstImage = winpr_image_new(); char* name = GetCombinedPath(path, "progressive.bmp"); PROGRESSIVE_CONTEXT* progressiveEnc = progressive_context_new(TRUE); PROGRESSIVE_CONTEXT* progressiveDec = progressive_context_new(FALSE); region16_init(&invalidRegion); if (!image || !dstImage || !name || !progressiveEnc || !progressiveDec) goto fail; rc = winpr_image_read(image, name); if (rc <= 0) goto fail; resultData = calloc(image->scanline, image->height); if (!resultData) goto fail; // Progressive encode rc = progressive_compress(progressiveEnc, image->data, image->scanline * image->height, ColorFormat, image->width, image->height, image->scanline, NULL, &dstData, &dstSize); // Progressive decode rc = progressive_create_surface_context(progressiveDec, 0, image->width, image->height); if (rc <= 0) goto fail; rc = progressive_decompress(progressiveDec, dstData, dstSize, resultData, ColorFormat, image->scanline, 0, 0, &invalidRegion, 0, 0); if (rc < 0) goto fail; // Compare result if (0) // Dump result image for manual inspection { *dstImage = *image; dstImage->data = resultData; winpr_image_write(dstImage, "/tmp/test.bmp"); } for (UINT32 y = 0; y < image->height; y++) { const BYTE* orig = &image->data[y * image->scanline]; const BYTE* dec = &resultData[y * image->scanline]; for (UINT32 x = 0; x < image->width; x++) { const BYTE* po = &orig[x * 4]; const BYTE* pd = &dec[x * 4]; const DWORD a = FreeRDPReadColor(po, ColorFormat); const DWORD b = FreeRDPReadColor(pd, ColorFormat); if (!colordiff(ColorFormat, a, b)) { printf("xxxxxxx [%u:%u] [%s] %08X != %08X\n", x, y, FreeRDPGetColorFormatName(ColorFormat), a, b); goto fail; } } } res = TRUE; fail: region16_uninit(&invalidRegion); progressive_context_free(progressiveEnc); progressive_context_free(progressiveDec); winpr_image_free(image, TRUE); winpr_image_free(dstImage, FALSE); free(resultData); free(name); return res; } int TestFreeRDPCodecProgressive(int argc, char* argv[]) { int rc = -1; char* ms_sample_path = NULL; char name[8192]; SYSTEMTIME systemTime; WINPR_UNUSED(argc); WINPR_UNUSED(argv); GetSystemTime(&systemTime); sprintf_s(name, sizeof(name), "EGFX_PROGRESSIVE_MS_SAMPLE-%04" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16 "%04" PRIu16, systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds); ms_sample_path = _strdup(CMAKE_CURRENT_SOURCE_DIR); if (!ms_sample_path) { printf("Memory allocation failed\n"); goto fail; } if (winpr_PathFileExists(ms_sample_path)) { /* if (test_progressive_ms_sample(ms_sample_path) < 0) goto fail; */ if (!test_encode_decode(ms_sample_path)) goto fail; rc = 0; } fail: free(ms_sample_path); return rc; }