2#include <winpr/string.h>
3#include <winpr/assert.h>
6#include <winpr/image.h>
9static const char test_src_filename[] = TEST_SOURCE_PATH
"/rgb";
10static const char test_bin_filename[] = TEST_BINARY_PATH
"/rgb";
12static BOOL test_image_equal(
const wImage* imageA,
const wImage* imageB)
14 return winpr_image_equal(imageA, imageB,
15 WINPR_IMAGE_CMP_IGNORE_DEPTH | WINPR_IMAGE_CMP_IGNORE_ALPHA |
16 WINPR_IMAGE_CMP_FUZZY);
19static BOOL test_equal_to(
const wImage* bmp,
const char* name, UINT32 format)
22 wImage* cmp = winpr_image_new();
26 char path[MAX_PATH] = WINPR_C_ARRAY_INIT;
27 (void)_snprintf(path,
sizeof(path),
"%s.%s", name, winpr_image_format_extension(format));
28 const int cmpSize = winpr_image_read(cmp, path);
31 (void)fprintf(stderr,
"[%s] winpr_image_read failed for %s", __func__, path);
35 rc = test_image_equal(bmp, cmp);
37 (void)fprintf(stderr,
"[%s] winpr_image_eqal failed", __func__);
40 winpr_image_free(cmp, TRUE);
44static BOOL test_equal(
void)
47 wImage* bmp = winpr_image_new();
52 char path[MAX_PATH] = WINPR_C_ARRAY_INIT;
53 if (_snprintf(path,
sizeof(path),
"%s.bmp", test_src_filename) < 0)
55 if (FAILED(PathCchConvertStyleA(path,
sizeof(path), PATH_STYLE_NATIVE)))
58 const int bmpSize = winpr_image_read(bmp, path);
61 (void)fprintf(stderr,
"[%s] winpr_image_read failed for %s", __func__, path);
65 for (UINT32 x = 0; x < UINT8_MAX; x++)
67 if (!winpr_image_format_is_supported(x))
69 if (!test_equal_to(bmp, test_src_filename, x))
75 winpr_image_free(bmp, TRUE);
80static BOOL test_read_write_compare(
const char* tname,
const char* tdst, UINT32 format)
83 wImage* bmp1 = winpr_image_new();
84 wImage* bmp2 = winpr_image_new();
85 wImage* bmp3 = winpr_image_new();
86 if (!bmp1 || !bmp2 || !bmp3)
89 char spath[MAX_PATH] = WINPR_C_ARRAY_INIT;
90 char dpath[MAX_PATH] = WINPR_C_ARRAY_INIT;
91 char bpath1[MAX_PATH] = WINPR_C_ARRAY_INIT;
92 char bpath2[MAX_PATH] = WINPR_C_ARRAY_INIT;
93 if (_snprintf(spath,
sizeof(spath),
"%s.%s", tname, winpr_image_format_extension(format)) < 0)
95 if (_snprintf(dpath,
sizeof(dpath),
"%s.%s", tdst, winpr_image_format_extension(format)) < 0)
97 if (_snprintf(bpath1,
sizeof(bpath1),
"%s.src.%s", dpath,
98 winpr_image_format_extension(WINPR_IMAGE_BITMAP)) < 0)
100 if (_snprintf(bpath2,
sizeof(bpath2),
"%s.bin.%s", dpath,
101 winpr_image_format_extension(WINPR_IMAGE_BITMAP)) < 0)
103 if (FAILED(PathCchConvertStyleA(spath,
sizeof(spath), PATH_STYLE_NATIVE)))
105 if (FAILED(PathCchConvertStyleA(dpath,
sizeof(dpath), PATH_STYLE_NATIVE)))
107 if (FAILED(PathCchConvertStyleA(bpath1,
sizeof(bpath1), PATH_STYLE_NATIVE)))
109 if (FAILED(PathCchConvertStyleA(bpath2,
sizeof(bpath2), PATH_STYLE_NATIVE)))
112 const int bmpRSize = winpr_image_read(bmp1, spath);
115 (void)fprintf(stderr,
"[%s] winpr_image_read failed for %s", __func__, spath);
119 const int bmpWSize = winpr_image_write(bmp1, dpath);
122 (void)fprintf(stderr,
"[%s] winpr_image_write failed for %s", __func__, dpath);
126 const int bmp2RSize = winpr_image_read(bmp2, dpath);
129 (void)fprintf(stderr,
"[%s] winpr_image_read failed for %s", __func__, dpath);
133 const int bmpSrcWSize = winpr_image_write_ex(bmp1, WINPR_IMAGE_BITMAP, bpath1);
134 if (bmpSrcWSize <= 0)
136 (void)fprintf(stderr,
"[%s] winpr_image_write_ex failed for %s", __func__, bpath1);
142 const int bmpBinWSize = winpr_image_write_ex(bmp2, WINPR_IMAGE_BITMAP, bpath2);
143 if (bmpBinWSize <= 0)
145 (void)fprintf(stderr,
"[%s] winpr_image_write_ex failed for %s", __func__, bpath2);
149 const int bmp3RSize = winpr_image_read(bmp3, bpath2);
152 (void)fprintf(stderr,
"[%s] winpr_image_read failed for %s", __func__, bpath2);
156 if (!winpr_image_equal(bmp1, bmp2,
157 WINPR_IMAGE_CMP_IGNORE_DEPTH | WINPR_IMAGE_CMP_IGNORE_ALPHA |
158 WINPR_IMAGE_CMP_FUZZY))
160 (void)fprintf(stderr,
"[%s] winpr_image_eqal failed bmp1 bmp2", __func__);
164 rc = winpr_image_equal(bmp3, bmp2,
165 WINPR_IMAGE_CMP_IGNORE_DEPTH | WINPR_IMAGE_CMP_IGNORE_ALPHA |
166 WINPR_IMAGE_CMP_FUZZY);
168 (void)fprintf(stderr,
"[%s] winpr_image_eqal failed bmp3 bmp2", __func__);
170 winpr_image_free(bmp1, TRUE);
171 winpr_image_free(bmp2, TRUE);
172 winpr_image_free(bmp3, TRUE);
176static BOOL test_read_write(
void)
179 for (UINT32 x = 0; x < UINT8_MAX; x++)
181 if (!winpr_image_format_is_supported(x))
183 if (!test_read_write_compare(test_src_filename, test_bin_filename, x))
189static BOOL test_load_file(
const char* name)
192 wImage* image = winpr_image_new();
196 const int res = winpr_image_read(image, name);
200 winpr_image_free(image, TRUE);
204static void put_u16(BYTE* p, UINT16 v)
206 p[0] = (BYTE)(v & 0xff);
207 p[1] = (BYTE)((v >> 8) & 0xff);
210static void put_u32(BYTE* p, UINT32 v)
212 p[0] = (BYTE)(v & 0xff);
213 p[1] = (BYTE)((v >> 8) & 0xff);
214 p[2] = (BYTE)((v >> 16) & 0xff);
215 p[3] = (BYTE)((v >> 24) & 0xff);
222static BOOL test_unaligned_no_overread(
void)
225 const UINT32 width = 1;
226 const UINT32 height = 10;
227 const UINT32 bpp = 3;
228 const UINT32 uscanline = width * bpp;
229 const UINT32 biSizeImage = uscanline * height;
230 const size_t offBits = 54;
231 const size_t size = offBits + biSizeImage;
233 wImage* image = winpr_image_new();
234 BYTE* bmp = (BYTE*)calloc(1, size);
240 put_u32(&bmp[2], (UINT32)size);
241 put_u32(&bmp[10], (UINT32)offBits);
242 put_u32(&bmp[14], 40);
243 put_u32(&bmp[18], width);
244 put_u32(&bmp[22], (UINT32)(-(INT32)height));
245 put_u16(&bmp[26], 1);
246 put_u16(&bmp[28], 24);
247 put_u32(&bmp[30], 0);
248 put_u32(&bmp[34], biSizeImage);
249 for (UINT32 i = 0; i < biSizeImage; i++)
250 bmp[offBits + i] = (BYTE)i;
252 if (winpr_image_read_buffer(image, bmp, size) <= 0)
255 if ((image->width != width) || (image->height != height))
258 for (UINT32 row = 0; row < height; row++)
260 for (UINT32 b = 0; b < uscanline; b++)
262 if (image->data[1ULL * row * image->scanline + b] != (BYTE)(row * uscanline + b))
270 winpr_image_free(image, TRUE);
274static BOOL test_load(
void)
276 const char* names[] = {
277 "rgb.16a.bmp",
"rgb.16a.nocolor.bmp",
"rgb.16.bmp",
"rgb.16.nocolor.bmp",
278 "rgb.16x.bmp",
"rgb.16x.nocolor.bmp",
"rgb.24.bmp",
"rgb.24.nocolor.bmp",
279 "rgb.32.bmp",
"rgb.32.nocolor.bmp",
"rgb.32x.bmp",
"rgb.32x.nocolor.bmp",
283 for (
size_t x = 0; x < ARRAYSIZE(names); x++)
285 const char* name = names[x];
286 char* fname = GetCombinedPath(TEST_SOURCE_PATH, name);
287 const BOOL res = test_load_file(fname);
297static BOOL test_bmp_offbits(UINT32 compression, UINT32 padding, BOOL topDown)
300 const UINT32 width = 2;
301 const UINT32 height = 2;
302 const UINT32 bpp = 32;
303 const UINT32 stride = width * bpp / 8;
304 const UINT32 biSizeImage = stride * height;
305 const size_t headerSize = 54;
306 const size_t maskSize = (compression == BI_BITFIELDS) ? 3 *
sizeof(DWORD) : 0;
307 const size_t minOffset = headerSize + maskSize;
308 const size_t offBits = minOffset + padding;
309 const size_t size = offBits + biSizeImage;
311 wImage* image = winpr_image_new();
312 BYTE* bmp = (BYTE*)calloc(1, size);
318 put_u32(&bmp[2], (UINT32)size);
319 put_u32(&bmp[10], (UINT32)offBits);
320 put_u32(&bmp[14], 40);
321 put_u32(&bmp[18], width);
322 put_u32(&bmp[22], topDown ? (UINT32)(-(INT32)height) : height);
323 put_u16(&bmp[26], 1);
324 put_u16(&bmp[28], bpp);
325 put_u32(&bmp[30], compression);
326 put_u32(&bmp[34], biSizeImage);
327 if (compression == BI_BITFIELDS)
329 put_u32(&bmp[54], 0x00FF0000);
330 put_u32(&bmp[58], 0x0000FF00);
331 put_u32(&bmp[62], 0x000000FF);
335 const BYTE pixels[16] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
336 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 };
337 memcpy(&bmp[offBits], pixels,
sizeof(pixels));
339 if (winpr_image_read_buffer(image, bmp, size) <= 0)
341 (void)fprintf(stderr,
"[%s] failed to read BMP at offset %" PRIuz
"\n", __func__,
346 if ((image->width != width) || (image->height != height) || (image->bitsPerPixel != bpp) ||
347 (image->bytesPerPixel != bpp / 8) || (image->scanline != stride) || !image->data)
349 (void)fprintf(stderr,
"[%s] unexpected image layout\n", __func__);
353 for (
size_t row = 0; row < height; row++)
355 const size_t srcRow = topDown ? row : height - 1 - row;
356 if (memcmp(&image->data[row * image->scanline], &pixels[srcRow * stride], stride) != 0)
358 (void)fprintf(stderr,
"[%s] unexpected pixels in row %" PRIuz
"\n", __func__, row);
367 const UINT32 offsets[] = { 0,
368 (UINT32)(headerSize - 1),
369 (UINT32)(minOffset - 1),
374 for (
size_t x = 0; x < ARRAYSIZE(offsets); x++)
376 winpr_image_free(image, TRUE);
377 image = winpr_image_new();
380 put_u32(&bmp[10], offsets[x]);
381 if (winpr_image_read_buffer(image, bmp, size) > 0)
383 (void)fprintf(stderr,
"[%s] accepted invalid offset %" PRIu32
"\n", __func__,
393 winpr_image_free(image, TRUE);
397int TestImage(
int argc,
char* argv[])
407 if (!test_read_write())
413 if (!test_unaligned_no_overread())
416 if (!test_bmp_offbits(BI_BITFIELDS, 0, FALSE) || !test_bmp_offbits(BI_BITFIELDS, 4, TRUE) ||
417 !test_bmp_offbits(BI_RGB, 0, FALSE) || !test_bmp_offbits(BI_RGB, 12, TRUE))