1 /* 2 * Unit test suite for images 3 * 4 * Copyright (C) 2007 Google (Evan Stade) 5 * Copyright (C) 2012,2016 Dmitry Timoshkov 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "precomp.h" 23 24 #include <assert.h> 25 #include <ole2.h> 26 27 /* FIXME: They belong to gdipluseffects.h */ 28 DEFINE_GUID(BlurEffectGuid, 0x633c80a4, 0x1843, 0x482b, 0x9e, 0xf2, 0xbe, 0x28, 0x34, 0xc5, 0xfd, 0xd4); 29 DEFINE_GUID(SharpenEffectGuid, 0x63cbf3ee, 0xc526, 0x402c, 0x8f, 0x71, 0x62, 0xc5, 0x40, 0xbf, 0x51, 0x42); 30 DEFINE_GUID(ColorMatrixEffectGuid, 0x718f2615, 0x7933, 0x40e3, 0xa5, 0x11, 0x5f, 0x68, 0xfe, 0x14, 0xdd, 0x74); 31 DEFINE_GUID(ColorLUTEffectGuid, 0xa7ce72a9, 0x0f7f, 0x40d7, 0xb3, 0xcc, 0xd0, 0xc0, 0x2d, 0x5c, 0x32, 0x12); 32 DEFINE_GUID(BrightnessContrastEffectGuid, 0xd3a1dbe1, 0x8ec4, 0x4c17, 0x9f, 0x4c, 0xea, 0x97, 0xad, 0x1c, 0x34, 0x3d); 33 DEFINE_GUID(HueSaturationLightnessEffectGuid, 0x8b2dd6c3, 0xeb07, 0x4d87, 0xa5, 0xf0, 0x71, 0x08, 0xe2, 0x6a, 0x9c, 0x5f); 34 DEFINE_GUID(LevelsEffectGuid, 0x99c354ec, 0x2a31, 0x4f3a, 0x8c, 0x34, 0x17, 0xa8, 0x03, 0xb3, 0x3a, 0x25); 35 DEFINE_GUID(TintEffectGuid, 0x1077af00, 0x2848, 0x4441, 0x94, 0x89, 0x44, 0xad, 0x4c, 0x2d, 0x7a, 0x2c); 36 DEFINE_GUID(ColorBalanceEffectGuid, 0x537e597d, 0x251e, 0x48da, 0x96, 0x64, 0x29, 0xca, 0x49, 0x6b, 0x70, 0xf8); 37 DEFINE_GUID(RedEyeCorrectionEffectGuid, 0x74d29d05, 0x69a4, 0x4266, 0x95, 0x49, 0x3c, 0xc5, 0x28, 0x36, 0xb6, 0x32); 38 DEFINE_GUID(ColorCurveEffectGuid, 0xdd6a0022, 0x58e4, 0x4a67, 0x9d, 0x9b, 0xd4, 0x8e, 0xb8, 0x81, 0xa5, 0x3d); 39 40 static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*); 41 static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*); 42 static GpStatus (WINAPI *pGdipImageSetAbort)(GpImage*,GdiplusAbort*); 43 44 static GpStatus (WINGDIPAPI *pGdipInitializePalette)(ColorPalette*,PaletteType,INT,BOOL,GpBitmap*); 45 46 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got)) 47 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got)) 48 49 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff) 50 { 51 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; 52 c1 >>= 8; c2 >>= 8; 53 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; 54 c1 >>= 8; c2 >>= 8; 55 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; 56 c1 >>= 8; c2 >>= 8; 57 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE; 58 return TRUE; 59 } 60 61 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo) 62 { 63 WCHAR bufferW[39]; 64 char buffer[39]; 65 char buffer2[39]; 66 67 StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); 68 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL); 69 StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0])); 70 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL); 71 todo_wine_if (todo) 72 ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer); 73 } 74 75 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo) 76 { 77 GUID raw; 78 GpStatus stat; 79 80 stat = GdipGetImageRawFormat(img, &raw); 81 ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat); 82 if(stat != Ok) return; 83 expect_guid(expected, &raw, line, todo); 84 } 85 86 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo) 87 { 88 LPSTREAM stream; 89 HGLOBAL hglob; 90 LPBYTE data; 91 HRESULT hres; 92 GpStatus stat; 93 GpImage *img; 94 95 hglob = GlobalAlloc (0, size); 96 data = GlobalLock (hglob); 97 memcpy(data, buff, size); 98 GlobalUnlock(hglob); data = NULL; 99 100 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream); 101 ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n"); 102 if(hres != S_OK) return; 103 104 stat = GdipLoadImageFromStream(stream, &img); 105 ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n"); 106 if(stat != Ok){ 107 IStream_Release(stream); 108 return; 109 } 110 111 expect_rawformat(expected, img, line, todo); 112 113 GdipDisposeImage(img); 114 IStream_Release(stream); 115 } 116 117 static void test_Scan0(void) 118 { 119 GpBitmap *bm; 120 GpStatus stat; 121 BYTE buff[360]; 122 123 bm = NULL; 124 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm); 125 expect(Ok, stat); 126 ok(NULL != bm, "Expected bitmap to be initialized\n"); 127 if (stat == Ok) 128 GdipDisposeImage((GpImage*)bm); 129 130 bm = (GpBitmap*)0xdeadbeef; 131 stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm); 132 expect(InvalidParameter, stat); 133 ok( !bm, "expected null bitmap\n" ); 134 135 bm = (GpBitmap*)0xdeadbeef; 136 stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm); 137 expect(InvalidParameter, stat); 138 ok( !bm, "expected null bitmap\n" ); 139 140 bm = (GpBitmap*)0xdeadbeef; 141 stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm); 142 expect(InvalidParameter, stat); 143 ok( !bm, "expected null bitmap\n" ); 144 145 bm = NULL; 146 stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm); 147 expect(Ok, stat); 148 ok(NULL != bm, "Expected bitmap to be initialized\n"); 149 if (stat == Ok) 150 GdipDisposeImage((GpImage*)bm); 151 152 bm = (GpBitmap*) 0xdeadbeef; 153 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm); 154 expect(InvalidParameter, stat); 155 ok( !bm, "expected null bitmap\n" ); 156 157 bm = (GpBitmap*)0xdeadbeef; 158 stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm); 159 expect(InvalidParameter, stat); 160 ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" ); 161 162 bm = NULL; 163 stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm); 164 expect(Ok, stat); 165 ok(NULL != bm, "Expected bitmap to be initialized\n"); 166 if (stat == Ok) 167 GdipDisposeImage((GpImage*)bm); 168 169 bm = (GpBitmap*)0xdeadbeef; 170 stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm); 171 expect(InvalidParameter, stat); 172 ok( !bm, "expected null bitmap\n" ); 173 } 174 175 static void test_FromGdiDib(void) 176 { 177 GpBitmap *bm; 178 GpStatus stat; 179 BYTE buff[400]; 180 BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)]; 181 BITMAPINFO *bmi = (BITMAPINFO*)rbmi; 182 PixelFormat format; 183 184 bm = NULL; 185 186 memset(rbmi, 0, sizeof(rbmi)); 187 188 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 189 bmi->bmiHeader.biWidth = 10; 190 bmi->bmiHeader.biHeight = 10; 191 bmi->bmiHeader.biPlanes = 1; 192 bmi->bmiHeader.biBitCount = 32; 193 bmi->bmiHeader.biCompression = BI_RGB; 194 195 stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm); 196 expect(InvalidParameter, stat); 197 198 stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm); 199 expect(InvalidParameter, stat); 200 201 stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL); 202 expect(InvalidParameter, stat); 203 204 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 205 expect(Ok, stat); 206 ok(NULL != bm, "Expected bitmap to be initialized\n"); 207 if (stat == Ok) 208 { 209 stat = GdipGetImagePixelFormat((GpImage*)bm, &format); 210 expect(Ok, stat); 211 expect(PixelFormat32bppRGB, format); 212 213 GdipDisposeImage((GpImage*)bm); 214 } 215 216 bmi->bmiHeader.biBitCount = 24; 217 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 218 expect(Ok, stat); 219 ok(NULL != bm, "Expected bitmap to be initialized\n"); 220 if (stat == Ok) 221 { 222 stat = GdipGetImagePixelFormat((GpImage*)bm, &format); 223 expect(Ok, stat); 224 expect(PixelFormat24bppRGB, format); 225 226 GdipDisposeImage((GpImage*)bm); 227 } 228 229 bmi->bmiHeader.biBitCount = 16; 230 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 231 expect(Ok, stat); 232 ok(NULL != bm, "Expected bitmap to be initialized\n"); 233 if (stat == Ok) 234 { 235 stat = GdipGetImagePixelFormat((GpImage*)bm, &format); 236 expect(Ok, stat); 237 expect(PixelFormat16bppRGB555, format); 238 239 GdipDisposeImage((GpImage*)bm); 240 } 241 242 bmi->bmiHeader.biBitCount = 8; 243 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 244 expect(Ok, stat); 245 ok(NULL != bm, "Expected bitmap to be initialized\n"); 246 if (stat == Ok) 247 { 248 stat = GdipGetImagePixelFormat((GpImage*)bm, &format); 249 expect(Ok, stat); 250 expect(PixelFormat8bppIndexed, format); 251 252 GdipDisposeImage((GpImage*)bm); 253 } 254 255 bmi->bmiHeader.biBitCount = 4; 256 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 257 expect(Ok, stat); 258 ok(NULL != bm, "Expected bitmap to be initialized\n"); 259 if (stat == Ok) 260 { 261 stat = GdipGetImagePixelFormat((GpImage*)bm, &format); 262 expect(Ok, stat); 263 expect(PixelFormat4bppIndexed, format); 264 265 GdipDisposeImage((GpImage*)bm); 266 } 267 268 bmi->bmiHeader.biBitCount = 1; 269 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 270 expect(Ok, stat); 271 ok(NULL != bm, "Expected bitmap to be initialized\n"); 272 if (stat == Ok) 273 { 274 stat = GdipGetImagePixelFormat((GpImage*)bm, &format); 275 expect(Ok, stat); 276 expect(PixelFormat1bppIndexed, format); 277 278 GdipDisposeImage((GpImage*)bm); 279 } 280 281 bmi->bmiHeader.biBitCount = 0; 282 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm); 283 expect(InvalidParameter, stat); 284 } 285 286 static void test_GetImageDimension(void) 287 { 288 GpBitmap *bm; 289 GpStatus stat; 290 const REAL WIDTH = 10.0, HEIGHT = 20.0; 291 REAL w,h; 292 293 bm = (GpBitmap*)0xdeadbeef; 294 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm); 295 expect(Ok,stat); 296 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n"); 297 ok(NULL != bm, "Expected bitmap to not be NULL\n"); 298 299 stat = GdipGetImageDimension(NULL,&w,&h); 300 expect(InvalidParameter, stat); 301 302 stat = GdipGetImageDimension((GpImage*)bm,NULL,&h); 303 expect(InvalidParameter, stat); 304 305 stat = GdipGetImageDimension((GpImage*)bm,&w,NULL); 306 expect(InvalidParameter, stat); 307 308 w = -1; 309 h = -1; 310 stat = GdipGetImageDimension((GpImage*)bm,&w,&h); 311 expect(Ok, stat); 312 expectf(WIDTH, w); 313 expectf(HEIGHT, h); 314 GdipDisposeImage((GpImage*)bm); 315 } 316 317 static void test_GdipImageGetFrameDimensionsCount(void) 318 { 319 GpBitmap *bm; 320 GpStatus stat; 321 const REAL WIDTH = 10.0, HEIGHT = 20.0; 322 UINT w; 323 GUID dimension = {0}; 324 UINT count; 325 ARGB color; 326 327 bm = (GpBitmap*)0xdeadbeef; 328 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm); 329 expect(Ok,stat); 330 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n"); 331 ok(NULL != bm, "Expected bitmap to not be NULL\n"); 332 333 stat = GdipImageGetFrameDimensionsCount(NULL,&w); 334 expect(InvalidParameter, stat); 335 336 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL); 337 expect(InvalidParameter, stat); 338 339 w = -1; 340 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w); 341 expect(Ok, stat); 342 expect(1, w); 343 344 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1); 345 expect(Ok, stat); 346 expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE); 347 348 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2); 349 expect(InvalidParameter, stat); 350 351 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0); 352 expect(InvalidParameter, stat); 353 354 stat = GdipImageGetFrameCount(NULL, &dimension, &count); 355 expect(InvalidParameter, stat); 356 357 /* WinXP crashes on this test */ 358 if(0) 359 { 360 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL); 361 expect(InvalidParameter, stat); 362 } 363 364 stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count); 365 expect(Ok, stat); 366 367 count = 12345; 368 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count); 369 expect(Ok, stat); 370 expect(1, count); 371 372 GdipBitmapSetPixel(bm, 0, 0, 0xffffffff); 373 374 stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0); 375 expect(Ok, stat); 376 377 /* SelectActiveFrame has no effect on image data of memory bitmaps */ 378 color = 0xdeadbeef; 379 GdipBitmapGetPixel(bm, 0, 0, &color); 380 expect(0xffffffff, color); 381 382 GdipDisposeImage((GpImage*)bm); 383 } 384 385 static void test_LoadingImages(void) 386 { 387 GpStatus stat; 388 GpBitmap *bm; 389 GpImage *img; 390 static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0}; 391 392 stat = GdipCreateBitmapFromFile(0, 0); 393 expect(InvalidParameter, stat); 394 395 bm = (GpBitmap *)0xdeadbeef; 396 stat = GdipCreateBitmapFromFile(0, &bm); 397 expect(InvalidParameter, stat); 398 ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm); 399 400 bm = (GpBitmap *)0xdeadbeef; 401 stat = GdipCreateBitmapFromFile(nonexistentW, &bm); 402 todo_wine expect(InvalidParameter, stat); 403 ok(!bm, "returned %p\n", bm); 404 405 stat = GdipLoadImageFromFile(0, 0); 406 expect(InvalidParameter, stat); 407 408 img = (GpImage *)0xdeadbeef; 409 stat = GdipLoadImageFromFile(0, &img); 410 expect(InvalidParameter, stat); 411 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img); 412 413 img = (GpImage *)0xdeadbeef; 414 stat = GdipLoadImageFromFile(nonexistentW, &img); 415 todo_wine expect(OutOfMemory, stat); 416 ok(!img, "returned %p\n", img); 417 418 stat = GdipLoadImageFromFileICM(0, 0); 419 expect(InvalidParameter, stat); 420 421 img = (GpImage *)0xdeadbeef; 422 stat = GdipLoadImageFromFileICM(0, &img); 423 expect(InvalidParameter, stat); 424 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img); 425 426 img = (GpImage *)0xdeadbeef; 427 stat = GdipLoadImageFromFileICM(nonexistentW, &img); 428 todo_wine expect(OutOfMemory, stat); 429 ok(!img, "returned %p\n", img); 430 } 431 432 static void test_SavingImages(void) 433 { 434 GpStatus stat; 435 GpBitmap *bm; 436 UINT n; 437 UINT s; 438 const REAL WIDTH = 10.0, HEIGHT = 20.0; 439 REAL w, h; 440 ImageCodecInfo *codecs; 441 static const CHAR filenameA[] = "a.bmp"; 442 static const WCHAR filename[] = { 'a','.','b','m','p',0 }; 443 444 codecs = NULL; 445 446 stat = GdipSaveImageToFile(0, 0, 0, 0); 447 expect(InvalidParameter, stat); 448 449 bm = NULL; 450 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 451 expect(Ok, stat); 452 if (!bm) 453 return; 454 455 /* invalid params */ 456 stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0); 457 expect(InvalidParameter, stat); 458 459 stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0); 460 expect(InvalidParameter, stat); 461 462 /* encoder tests should succeed -- already tested */ 463 stat = GdipGetImageEncodersSize(&n, &s); 464 if (stat != Ok || n == 0) goto cleanup; 465 466 codecs = GdipAlloc(s); 467 if (!codecs) goto cleanup; 468 469 stat = GdipGetImageEncoders(n, s, codecs); 470 if (stat != Ok) goto cleanup; 471 472 stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0); 473 expect(Ok, stat); 474 475 GdipDisposeImage((GpImage*)bm); 476 bm = 0; 477 478 /* re-load and check image stats */ 479 stat = GdipLoadImageFromFile(filename, (GpImage**)&bm); 480 expect(Ok, stat); 481 if (stat != Ok) goto cleanup; 482 483 stat = GdipGetImageDimension((GpImage*)bm, &w, &h); 484 if (stat != Ok) goto cleanup; 485 486 expectf(WIDTH, w); 487 expectf(HEIGHT, h); 488 489 cleanup: 490 GdipFree(codecs); 491 if (bm) 492 GdipDisposeImage((GpImage*)bm); 493 ok(DeleteFileA(filenameA), "Delete failed.\n"); 494 } 495 496 static void test_encoders(void) 497 { 498 GpStatus stat; 499 UINT n; 500 UINT s; 501 ImageCodecInfo *codecs; 502 int i; 503 int bmp_found; 504 505 static const CHAR bmp_format[] = "BMP"; 506 507 stat = GdipGetImageEncodersSize(&n, &s); 508 expect(stat, Ok); 509 510 codecs = GdipAlloc(s); 511 if (!codecs) 512 return; 513 514 stat = GdipGetImageEncoders(n, s, NULL); 515 expect(GenericError, stat); 516 517 stat = GdipGetImageEncoders(0, s, codecs); 518 expect(GenericError, stat); 519 520 stat = GdipGetImageEncoders(n, s-1, codecs); 521 expect(GenericError, stat); 522 523 stat = GdipGetImageEncoders(n, s+1, codecs); 524 expect(GenericError, stat); 525 526 stat = GdipGetImageEncoders(n, s, codecs); 527 expect(stat, Ok); 528 529 bmp_found = FALSE; 530 for (i = 0; i < n; i++) 531 { 532 CHAR desc[32]; 533 534 WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1, 535 desc, 32, 0, 0); 536 537 if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, 538 desc, -1, 539 bmp_format, -1) == CSTR_EQUAL) { 540 bmp_found = TRUE; 541 break; 542 } 543 } 544 if (!bmp_found) 545 ok(FALSE, "No BMP codec found.\n"); 546 547 GdipFree(codecs); 548 } 549 550 static void test_LockBits(void) 551 { 552 GpStatus stat; 553 GpBitmap *bm; 554 GpRect rect; 555 BitmapData bd; 556 const INT WIDTH = 10, HEIGHT = 20; 557 ARGB color; 558 int y; 559 560 bm = NULL; 561 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 562 expect(Ok, stat); 563 564 rect.X = 2; 565 rect.Y = 3; 566 rect.Width = 4; 567 rect.Height = 5; 568 569 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000); 570 expect(Ok, stat); 571 572 stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000); 573 expect(Ok, stat); 574 575 /* read-only */ 576 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); 577 expect(Ok, stat); 578 579 if (stat == Ok) { 580 expect(0xc3, ((BYTE*)bd.Scan0)[2]); 581 expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]); 582 583 ((char*)bd.Scan0)[2] = 0xff; 584 585 stat = GdipBitmapUnlockBits(bm, &bd); 586 expect(Ok, stat); 587 } 588 589 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 590 expect(Ok, stat); 591 expect(0xffff0000, color); 592 593 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000); 594 expect(Ok, stat); 595 596 /* read-only, with NULL rect -> whole bitmap lock */ 597 stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd); 598 expect(Ok, stat); 599 expect(bd.Width, WIDTH); 600 expect(bd.Height, HEIGHT); 601 602 if (stat == Ok) { 603 ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff; 604 605 stat = GdipBitmapUnlockBits(bm, &bd); 606 expect(Ok, stat); 607 } 608 609 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 610 expect(Ok, stat); 611 expect(0xffff0000, color); 612 613 /* read-only, consecutive */ 614 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); 615 expect(Ok, stat); 616 617 if (stat == Ok) { 618 stat = GdipBitmapUnlockBits(bm, &bd); 619 expect(Ok, stat); 620 } 621 622 stat = GdipDisposeImage((GpImage*)bm); 623 expect(Ok, stat); 624 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 625 expect(Ok, stat); 626 627 /* read x2 */ 628 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); 629 expect(Ok, stat); 630 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); 631 expect(WrongState, stat); 632 633 stat = GdipBitmapUnlockBits(bm, &bd); 634 expect(Ok, stat); 635 636 stat = GdipDisposeImage((GpImage*)bm); 637 expect(Ok, stat); 638 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 639 expect(Ok, stat); 640 641 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000); 642 expect(Ok, stat); 643 644 stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000); 645 expect(Ok, stat); 646 647 /* write, no conversion */ 648 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); 649 expect(Ok, stat); 650 651 if (stat == Ok) { 652 /* all bits are readable, inside the rect or not */ 653 expect(0xff, ((BYTE*)bd.Scan0)[2]); 654 expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]); 655 656 stat = GdipBitmapUnlockBits(bm, &bd); 657 expect(Ok, stat); 658 } 659 660 /* read, conversion */ 661 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd); 662 expect(Ok, stat); 663 664 if (stat == Ok) { 665 expect(0xff, ((BYTE*)bd.Scan0)[2]); 666 if (0) 667 /* Areas outside the rectangle appear to be uninitialized */ 668 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n"); 669 670 ((BYTE*)bd.Scan0)[2] = 0xc3; 671 672 stat = GdipBitmapUnlockBits(bm, &bd); 673 expect(Ok, stat); 674 } 675 676 /* writes do not work in read mode if there was a conversion */ 677 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 678 expect(Ok, stat); 679 expect(0xffff0000, color); 680 681 /* read/write, conversion */ 682 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd); 683 expect(Ok, stat); 684 685 if (stat == Ok) { 686 expect(0xff, ((BYTE*)bd.Scan0)[2]); 687 ((BYTE*)bd.Scan0)[1] = 0x88; 688 if (0) 689 /* Areas outside the rectangle appear to be uninitialized */ 690 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n"); 691 692 stat = GdipBitmapUnlockBits(bm, &bd); 693 expect(Ok, stat); 694 } 695 696 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 697 expect(Ok, stat); 698 expect(0xffff8800, color); 699 700 /* write, conversion */ 701 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd); 702 expect(Ok, stat); 703 704 if (stat == Ok) { 705 if (0) 706 { 707 /* This is completely uninitialized. */ 708 ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n"); 709 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n"); 710 } 711 712 /* Initialize the buffer so the unlock doesn't access undefined memory */ 713 for (y=0; y<5; y++) 714 memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12); 715 716 ((BYTE*)bd.Scan0)[0] = 0x12; 717 ((BYTE*)bd.Scan0)[1] = 0x34; 718 ((BYTE*)bd.Scan0)[2] = 0x56; 719 720 stat = GdipBitmapUnlockBits(bm, &bd); 721 expect(Ok, stat); 722 } 723 724 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 725 expect(Ok, stat); 726 expect(0xff563412, color); 727 728 stat = GdipBitmapGetPixel(bm, 2, 8, &color); 729 expect(Ok, stat); 730 expect(0xffc30000, color); 731 732 stat = GdipDisposeImage((GpImage*)bm); 733 expect(Ok, stat); 734 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 735 expect(Ok, stat); 736 737 /* write, no modification */ 738 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); 739 expect(Ok, stat); 740 741 if (stat == Ok) { 742 stat = GdipBitmapUnlockBits(bm, &bd); 743 expect(Ok, stat); 744 } 745 746 /* write, consecutive */ 747 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); 748 expect(Ok, stat); 749 750 if (stat == Ok) { 751 stat = GdipBitmapUnlockBits(bm, &bd); 752 expect(Ok, stat); 753 } 754 755 stat = GdipDisposeImage((GpImage*)bm); 756 expect(Ok, stat); 757 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 758 expect(Ok, stat); 759 760 /* write, modify */ 761 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd); 762 expect(Ok, stat); 763 764 if (stat == Ok) { 765 if (bd.Scan0) 766 ((char*)bd.Scan0)[2] = 0xff; 767 768 stat = GdipBitmapUnlockBits(bm, &bd); 769 expect(Ok, stat); 770 } 771 772 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 773 expect(Ok, stat); 774 expect(0xffff0000, color); 775 776 stat = GdipDisposeImage((GpImage*)bm); 777 expect(Ok, stat); 778 779 /* dispose locked */ 780 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 781 expect(Ok, stat); 782 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd); 783 expect(Ok, stat); 784 stat = GdipDisposeImage((GpImage*)bm); 785 expect(Ok, stat); 786 } 787 788 static void test_LockBits_UserBuf(void) 789 { 790 GpStatus stat; 791 GpBitmap *bm; 792 GpRect rect; 793 BitmapData bd; 794 const INT WIDTH = 10, HEIGHT = 20; 795 DWORD bits[200]; 796 ARGB color; 797 798 bm = NULL; 799 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm); 800 expect(Ok, stat); 801 802 memset(bits, 0xaa, sizeof(bits)); 803 804 rect.X = 2; 805 rect.Y = 3; 806 rect.Width = 4; 807 rect.Height = 5; 808 809 bd.Width = 4; 810 bd.Height = 6; 811 bd.Stride = WIDTH * 4; 812 bd.PixelFormat = PixelFormat32bppARGB; 813 bd.Scan0 = &bits[2+3*WIDTH]; 814 bd.Reserved = 0xaaaaaaaa; 815 816 /* read-only */ 817 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd); 818 expect(Ok, stat); 819 820 expect(0xaaaaaaaa, bits[0]); 821 expect(0, bits[2+3*WIDTH]); 822 823 bits[2+3*WIDTH] = 0xdeadbeef; 824 825 if (stat == Ok) { 826 stat = GdipBitmapUnlockBits(bm, &bd); 827 expect(Ok, stat); 828 } 829 830 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 831 expect(Ok, stat); 832 expect(0, color); 833 834 /* write-only */ 835 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd); 836 expect(Ok, stat); 837 838 expect(0xdeadbeef, bits[2+3*WIDTH]); 839 bits[2+3*WIDTH] = 0x12345678; 840 841 if (stat == Ok) { 842 stat = GdipBitmapUnlockBits(bm, &bd); 843 expect(Ok, stat); 844 } 845 846 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 847 expect(Ok, stat); 848 expect(0x12345678, color); 849 850 bits[2+3*WIDTH] = 0; 851 852 /* read/write */ 853 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd); 854 expect(Ok, stat); 855 856 expect(0x12345678, bits[2+3*WIDTH]); 857 bits[2+3*WIDTH] = 0xdeadbeef; 858 859 if (stat == Ok) { 860 stat = GdipBitmapUnlockBits(bm, &bd); 861 expect(Ok, stat); 862 } 863 864 stat = GdipBitmapGetPixel(bm, 2, 3, &color); 865 expect(Ok, stat); 866 expect(0xdeadbeef, color); 867 868 stat = GdipDisposeImage((GpImage*)bm); 869 expect(Ok, stat); 870 } 871 872 struct BITMAPINFOWITHBITFIELDS 873 { 874 BITMAPINFOHEADER bmiHeader; 875 DWORD masks[3]; 876 }; 877 878 union BITMAPINFOUNION 879 { 880 BITMAPINFO bi; 881 struct BITMAPINFOWITHBITFIELDS bf; 882 }; 883 884 static void test_GdipCreateBitmapFromHBITMAP(void) 885 { 886 GpBitmap* gpbm = NULL; 887 HBITMAP hbm = NULL; 888 HPALETTE hpal = NULL; 889 GpStatus stat; 890 BYTE buff[1000]; 891 LOGPALETTE* LogPal = NULL; 892 REAL width, height; 893 const REAL WIDTH1 = 5; 894 const REAL HEIGHT1 = 15; 895 const REAL WIDTH2 = 10; 896 const REAL HEIGHT2 = 20; 897 HDC hdc; 898 union BITMAPINFOUNION bmi; 899 BYTE *bits; 900 PixelFormat format; 901 902 stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL); 903 expect(InvalidParameter, stat); 904 905 hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL); 906 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL); 907 expect(InvalidParameter, stat); 908 909 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); 910 expect(Ok, stat); 911 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height)); 912 expectf(WIDTH1, width); 913 expectf(HEIGHT1, height); 914 if (stat == Ok) 915 GdipDisposeImage((GpImage*)gpbm); 916 DeleteObject(hbm); 917 918 memset(buff, 0, sizeof(buff)); 919 hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff); 920 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); 921 expect(Ok, stat); 922 /* raw format */ 923 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE); 924 925 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height)); 926 expectf(WIDTH2, width); 927 expectf(HEIGHT2, height); 928 if (stat == Ok) 929 GdipDisposeImage((GpImage*)gpbm); 930 DeleteObject(hbm); 931 932 hdc = CreateCompatibleDC(0); 933 ok(hdc != NULL, "CreateCompatibleDC failed\n"); 934 bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader); 935 bmi.bi.bmiHeader.biHeight = HEIGHT1; 936 bmi.bi.bmiHeader.biWidth = WIDTH1; 937 bmi.bi.bmiHeader.biBitCount = 24; 938 bmi.bi.bmiHeader.biPlanes = 1; 939 bmi.bi.bmiHeader.biCompression = BI_RGB; 940 bmi.bi.bmiHeader.biClrUsed = 0; 941 942 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); 943 ok(hbm != NULL, "CreateDIBSection failed\n"); 944 945 bits[0] = 0; 946 947 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); 948 expect(Ok, stat); 949 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height)); 950 expectf(WIDTH1, width); 951 expectf(HEIGHT1, height); 952 if (stat == Ok) 953 { 954 /* test whether writing to the bitmap affects the original */ 955 stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff); 956 expect(Ok, stat); 957 958 expect(0, bits[0]); 959 960 GdipDisposeImage((GpImage*)gpbm); 961 } 962 963 LogPal = GdipAlloc(sizeof(LOGPALETTE)); 964 ok(LogPal != NULL, "unable to allocate LOGPALETTE\n"); 965 LogPal->palVersion = 0x300; 966 LogPal->palNumEntries = 1; 967 hpal = CreatePalette(LogPal); 968 ok(hpal != NULL, "CreatePalette failed\n"); 969 GdipFree(LogPal); 970 971 stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm); 972 expect(Ok, stat); 973 974 if (stat == Ok) 975 GdipDisposeImage((GpImage*)gpbm); 976 977 DeleteObject(hpal); 978 DeleteObject(hbm); 979 980 /* 16-bit 555 dib, rgb */ 981 bmi.bi.bmiHeader.biBitCount = 16; 982 bmi.bi.bmiHeader.biCompression = BI_RGB; 983 984 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); 985 ok(hbm != NULL, "CreateDIBSection failed\n"); 986 987 bits[0] = 0; 988 989 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); 990 expect(Ok, stat); 991 992 if (stat == Ok) 993 { 994 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height); 995 expect(Ok, stat); 996 expectf(WIDTH1, width); 997 expectf(HEIGHT1, height); 998 999 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format); 1000 expect(Ok, stat); 1001 expect(PixelFormat16bppRGB555, format); 1002 1003 GdipDisposeImage((GpImage*)gpbm); 1004 } 1005 DeleteObject(hbm); 1006 1007 /* 16-bit 555 dib, with bitfields */ 1008 bmi.bi.bmiHeader.biSize = sizeof(bmi); 1009 bmi.bi.bmiHeader.biCompression = BI_BITFIELDS; 1010 bmi.bf.masks[0] = 0x7c00; 1011 bmi.bf.masks[1] = 0x3e0; 1012 bmi.bf.masks[2] = 0x1f; 1013 1014 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); 1015 ok(hbm != NULL, "CreateDIBSection failed\n"); 1016 1017 bits[0] = 0; 1018 1019 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); 1020 expect(Ok, stat); 1021 1022 if (stat == Ok) 1023 { 1024 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height); 1025 expect(Ok, stat); 1026 expectf(WIDTH1, width); 1027 expectf(HEIGHT1, height); 1028 1029 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format); 1030 expect(Ok, stat); 1031 expect(PixelFormat16bppRGB555, format); 1032 1033 GdipDisposeImage((GpImage*)gpbm); 1034 } 1035 DeleteObject(hbm); 1036 1037 /* 16-bit 565 dib, with bitfields */ 1038 bmi.bf.masks[0] = 0xf800; 1039 bmi.bf.masks[1] = 0x7e0; 1040 bmi.bf.masks[2] = 0x1f; 1041 1042 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); 1043 ok(hbm != NULL, "CreateDIBSection failed\n"); 1044 1045 bits[0] = 0; 1046 1047 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm); 1048 expect(Ok, stat); 1049 1050 if (stat == Ok) 1051 { 1052 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height); 1053 expect(Ok, stat); 1054 expectf(WIDTH1, width); 1055 expectf(HEIGHT1, height); 1056 1057 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format); 1058 expect(Ok, stat); 1059 expect(PixelFormat16bppRGB565, format); 1060 1061 GdipDisposeImage((GpImage*)gpbm); 1062 } 1063 DeleteObject(hbm); 1064 1065 DeleteDC(hdc); 1066 } 1067 1068 static void test_GdipGetImageFlags(void) 1069 { 1070 GpImage *img; 1071 GpStatus stat; 1072 UINT flags; 1073 1074 img = (GpImage*)0xdeadbeef; 1075 1076 stat = GdipGetImageFlags(NULL, NULL); 1077 expect(InvalidParameter, stat); 1078 1079 stat = GdipGetImageFlags(NULL, &flags); 1080 expect(InvalidParameter, stat); 1081 1082 stat = GdipGetImageFlags(img, NULL); 1083 expect(InvalidParameter, stat); 1084 1085 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img); 1086 expect(Ok, stat); 1087 stat = GdipGetImageFlags(img, &flags); 1088 expect(Ok, stat); 1089 expect(ImageFlagsHasAlpha, flags); 1090 GdipDisposeImage(img); 1091 1092 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img); 1093 expect(Ok, stat); 1094 stat = GdipGetImageFlags(img, &flags); 1095 expect(Ok, stat); 1096 expect(ImageFlagsHasAlpha, flags); 1097 GdipDisposeImage(img); 1098 1099 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img); 1100 expect(Ok, stat); 1101 stat = GdipGetImageFlags(img, &flags); 1102 expect(Ok, stat); 1103 expect(ImageFlagsHasAlpha, flags); 1104 GdipDisposeImage(img); 1105 1106 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img); 1107 expect(Ok, stat); 1108 stat = GdipGetImageFlags(img, &flags); 1109 expect(Ok, stat); 1110 expect(ImageFlagsNone, flags); 1111 GdipDisposeImage(img); 1112 1113 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img); 1114 expect(Ok, stat); 1115 stat = GdipGetImageFlags(img, &flags); 1116 expect(Ok, stat); 1117 expect(ImageFlagsNone, flags); 1118 GdipDisposeImage(img); 1119 1120 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img); 1121 expect(Ok, stat); 1122 stat = GdipGetImageFlags(img, &flags); 1123 expect(Ok, stat); 1124 expect(ImageFlagsNone, flags); 1125 GdipDisposeImage(img); 1126 1127 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img); 1128 expect(Ok, stat); 1129 stat = GdipGetImageFlags(img, &flags); 1130 expect(Ok, stat); 1131 expect(ImageFlagsHasAlpha, flags); 1132 GdipDisposeImage(img); 1133 1134 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img); 1135 expect(Ok, stat); 1136 stat = GdipGetImageFlags(img, &flags); 1137 expect(Ok, stat); 1138 expect(ImageFlagsNone, flags); 1139 GdipDisposeImage(img); 1140 1141 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img); 1142 expect(Ok, stat); 1143 stat = GdipGetImageFlags(img, &flags); 1144 expect(Ok, stat); 1145 expect(ImageFlagsNone, flags); 1146 GdipDisposeImage(img); 1147 1148 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img); 1149 expect(Ok, stat); 1150 stat = GdipGetImageFlags(img, &flags); 1151 expect(Ok, stat); 1152 expect(ImageFlagsHasAlpha, flags); 1153 GdipDisposeImage(img); 1154 1155 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img); 1156 expect(Ok, stat); 1157 stat = GdipGetImageFlags(img, &flags); 1158 expect(Ok, stat); 1159 expect(ImageFlagsHasAlpha, flags); 1160 GdipDisposeImage(img); 1161 1162 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img); 1163 expect(Ok, stat); 1164 if (stat == Ok) 1165 { 1166 stat = GdipGetImageFlags(img, &flags); 1167 expect(Ok, stat); 1168 expect(ImageFlagsNone, flags); 1169 GdipDisposeImage(img); 1170 } 1171 1172 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img); 1173 expect(Ok, stat); 1174 if (stat == Ok) 1175 { 1176 expect(Ok, stat); 1177 stat = GdipGetImageFlags(img, &flags); 1178 expect(Ok, stat); 1179 expect(ImageFlagsHasAlpha, flags); 1180 GdipDisposeImage(img); 1181 } 1182 1183 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img); 1184 expect(Ok, stat); 1185 if (stat == Ok) 1186 { 1187 expect(Ok, stat); 1188 stat = GdipGetImageFlags(img, &flags); 1189 expect(Ok, stat); 1190 expect(ImageFlagsHasAlpha, flags); 1191 GdipDisposeImage(img); 1192 } 1193 } 1194 1195 static void test_GdipCloneImage(void) 1196 { 1197 GpStatus stat; 1198 GpRectF rectF; 1199 GpUnit unit; 1200 GpBitmap *bm; 1201 GpImage *image_src, *image_dest = NULL; 1202 const INT WIDTH = 10, HEIGHT = 20; 1203 1204 /* Create an image, clone it, delete the original, make sure the copy works */ 1205 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 1206 expect(Ok, stat); 1207 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE); 1208 1209 image_src = ((GpImage*)bm); 1210 stat = GdipCloneImage(image_src, &image_dest); 1211 expect(Ok, stat); 1212 expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE); 1213 1214 stat = GdipDisposeImage((GpImage*)bm); 1215 expect(Ok, stat); 1216 stat = GdipGetImageBounds(image_dest, &rectF, &unit); 1217 expect(Ok, stat); 1218 1219 /* Treat FP values carefully */ 1220 expectf((REAL)WIDTH, rectF.Width); 1221 expectf((REAL)HEIGHT, rectF.Height); 1222 1223 stat = GdipDisposeImage(image_dest); 1224 expect(Ok, stat); 1225 } 1226 1227 static void test_testcontrol(void) 1228 { 1229 GpStatus stat; 1230 DWORD param; 1231 1232 param = 0; 1233 stat = GdipTestControl(TestControlGetBuildNumber, ¶m); 1234 expect(Ok, stat); 1235 ok(param != 0, "Build number expected, got %u\n", param); 1236 } 1237 1238 static void test_fromhicon(void) 1239 { 1240 static const BYTE bmp_bits[1024]; 1241 HBITMAP hbmMask, hbmColor; 1242 ICONINFO info; 1243 HICON hIcon; 1244 GpStatus stat; 1245 GpBitmap *bitmap = NULL; 1246 UINT dim; 1247 ImageType type; 1248 PixelFormat format; 1249 1250 /* NULL */ 1251 stat = GdipCreateBitmapFromHICON(NULL, NULL); 1252 expect(InvalidParameter, stat); 1253 stat = GdipCreateBitmapFromHICON(NULL, &bitmap); 1254 expect(InvalidParameter, stat); 1255 1256 /* color icon 1 bit */ 1257 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits); 1258 ok(hbmMask != 0, "CreateBitmap failed\n"); 1259 hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits); 1260 ok(hbmColor != 0, "CreateBitmap failed\n"); 1261 info.fIcon = TRUE; 1262 info.xHotspot = 8; 1263 info.yHotspot = 8; 1264 info.hbmMask = hbmMask; 1265 info.hbmColor = hbmColor; 1266 hIcon = CreateIconIndirect(&info); 1267 ok(hIcon != 0, "CreateIconIndirect failed\n"); 1268 DeleteObject(hbmMask); 1269 DeleteObject(hbmColor); 1270 1271 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap); 1272 ok(stat == Ok || 1273 broken(stat == InvalidParameter), /* Win98 */ 1274 "Expected Ok, got %.8x\n", stat); 1275 if(stat == Ok){ 1276 /* check attributes */ 1277 stat = GdipGetImageHeight((GpImage*)bitmap, &dim); 1278 expect(Ok, stat); 1279 expect(16, dim); 1280 stat = GdipGetImageWidth((GpImage*)bitmap, &dim); 1281 expect(Ok, stat); 1282 expect(16, dim); 1283 stat = GdipGetImageType((GpImage*)bitmap, &type); 1284 expect(Ok, stat); 1285 expect(ImageTypeBitmap, type); 1286 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format); 1287 expect(Ok, stat); 1288 expect(PixelFormat32bppARGB, format); 1289 /* raw format */ 1290 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE); 1291 GdipDisposeImage((GpImage*)bitmap); 1292 } 1293 DestroyIcon(hIcon); 1294 1295 /* color icon 8 bpp */ 1296 hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits); 1297 ok(hbmMask != 0, "CreateBitmap failed\n"); 1298 hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits); 1299 ok(hbmColor != 0, "CreateBitmap failed\n"); 1300 info.fIcon = TRUE; 1301 info.xHotspot = 8; 1302 info.yHotspot = 8; 1303 info.hbmMask = hbmMask; 1304 info.hbmColor = hbmColor; 1305 hIcon = CreateIconIndirect(&info); 1306 ok(hIcon != 0, "CreateIconIndirect failed\n"); 1307 DeleteObject(hbmMask); 1308 DeleteObject(hbmColor); 1309 1310 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap); 1311 expect(Ok, stat); 1312 if(stat == Ok){ 1313 /* check attributes */ 1314 stat = GdipGetImageHeight((GpImage*)bitmap, &dim); 1315 expect(Ok, stat); 1316 expect(16, dim); 1317 stat = GdipGetImageWidth((GpImage*)bitmap, &dim); 1318 expect(Ok, stat); 1319 expect(16, dim); 1320 stat = GdipGetImageType((GpImage*)bitmap, &type); 1321 expect(Ok, stat); 1322 expect(ImageTypeBitmap, type); 1323 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format); 1324 expect(Ok, stat); 1325 expect(PixelFormat32bppARGB, format); 1326 /* raw format */ 1327 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE); 1328 GdipDisposeImage((GpImage*)bitmap); 1329 } 1330 DestroyIcon(hIcon); 1331 } 1332 1333 /* 1x1 pixel png */ 1334 static const unsigned char pngimage[285] = { 1335 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, 1336 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53, 1337 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b, 1338 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5, 1339 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41, 1340 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59, 1341 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 1342 }; 1343 /* 1x1 pixel gif */ 1344 static const unsigned char gifimage[35] = { 1345 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff, 1346 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44, 1347 0x01,0x00,0x3b 1348 }; 1349 /* 1x1 pixel transparent gif */ 1350 static const unsigned char transparentgif[] = { 1351 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x00,0x00, 1352 0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00, 1353 0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b 1354 }; 1355 /* 1x1 pixel bmp */ 1356 static const unsigned char bmpimage[66] = { 1357 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00, 1358 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00, 1359 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00, 1360 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00, 1361 0x00,0x00 1362 }; 1363 /* 1x1 pixel jpg */ 1364 static const unsigned char jpgimage[285] = { 1365 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c, 1366 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05, 1367 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b, 1368 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13, 1369 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17, 1370 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05, 1371 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e, 1372 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, 1373 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, 1374 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0, 1375 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11, 1376 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1377 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00, 1378 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4, 1379 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 1380 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00, 1381 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01, 1382 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9 1383 }; 1384 /* 1x1 pixel tiff */ 1385 static const unsigned char tiffimage[] = { 1386 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00, 1387 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00, 1388 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00, 1389 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01, 1390 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00, 1391 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00, 1392 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01, 1393 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00, 1394 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00, 1395 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01, 1396 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00, 1397 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00, 1398 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00, 1399 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65, 1400 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74, 1401 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48, 1402 0x00,0x00,0x00,0x01 1403 }; 1404 /* 320x320 twip wmf */ 1405 static const unsigned char wmfimage[180] = { 1406 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05, 1407 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00, 1408 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00, 1409 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00, 1410 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00, 1411 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, 1412 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00, 1413 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02, 1414 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00, 1415 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00, 1416 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00, 1417 0x00,0x00,0x00,0x00 1418 }; 1419 static void test_getrawformat(void) 1420 { 1421 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE); 1422 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE); 1423 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE); 1424 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE); 1425 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE); 1426 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE); 1427 } 1428 1429 static void test_loadwmf(void) 1430 { 1431 LPSTREAM stream; 1432 HGLOBAL hglob; 1433 LPBYTE data; 1434 HRESULT hres; 1435 GpStatus stat; 1436 GpImage *img; 1437 GpRectF bounds; 1438 GpUnit unit; 1439 REAL res = 12345.0; 1440 MetafileHeader header; 1441 1442 hglob = GlobalAlloc (0, sizeof(wmfimage)); 1443 data = GlobalLock (hglob); 1444 memcpy(data, wmfimage, sizeof(wmfimage)); 1445 GlobalUnlock(hglob); data = NULL; 1446 1447 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream); 1448 ok(hres == S_OK, "Failed to create a stream\n"); 1449 if(hres != S_OK) return; 1450 1451 stat = GdipLoadImageFromStream(stream, &img); 1452 ok(stat == Ok, "Failed to create a Bitmap\n"); 1453 if(stat != Ok){ 1454 IStream_Release(stream); 1455 return; 1456 } 1457 1458 IStream_Release(stream); 1459 1460 stat = GdipGetImageBounds(img, &bounds, &unit); 1461 expect(Ok, stat); 1462 expect(UnitPixel, unit); 1463 expectf(0.0, bounds.X); 1464 expectf(0.0, bounds.Y); 1465 expectf(320.0, bounds.Width); 1466 expectf(320.0, bounds.Height); 1467 1468 stat = GdipGetImageHorizontalResolution(img, &res); 1469 expect(Ok, stat); 1470 expectf(1440.0, res); 1471 1472 stat = GdipGetImageVerticalResolution(img, &res); 1473 expect(Ok, stat); 1474 expectf(1440.0, res); 1475 1476 memset(&header, 0, sizeof(header)); 1477 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header); 1478 expect(Ok, stat); 1479 if (stat == Ok) 1480 { 1481 expect(MetafileTypeWmfPlaceable, header.Type); 1482 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size); 1483 todo_wine expect(0x300, header.Version); 1484 expect(0, header.EmfPlusFlags); 1485 expectf(1440.0, header.DpiX); 1486 expectf(1440.0, header.DpiY); 1487 expect(0, header.X); 1488 expect(0, header.Y); 1489 expect(320, header.Width); 1490 expect(320, header.Height); 1491 expect(1, U(header).WmfHeader.mtType); 1492 expect(0, header.EmfPlusHeaderSize); 1493 expect(0, header.LogicalDpiX); 1494 expect(0, header.LogicalDpiY); 1495 } 1496 1497 GdipDisposeImage(img); 1498 } 1499 1500 static void test_createfromwmf(void) 1501 { 1502 HMETAFILE hwmf; 1503 GpImage *img; 1504 GpStatus stat; 1505 GpRectF bounds; 1506 GpUnit unit; 1507 REAL res = 12345.0; 1508 MetafileHeader header; 1509 1510 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), 1511 wmfimage+sizeof(WmfPlaceableFileHeader)); 1512 ok(hwmf != 0, "SetMetaFileBitsEx failed\n"); 1513 1514 stat = GdipCreateMetafileFromWmf(hwmf, TRUE, 1515 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img); 1516 expect(Ok, stat); 1517 1518 stat = GdipGetImageBounds(img, &bounds, &unit); 1519 expect(Ok, stat); 1520 expect(UnitPixel, unit); 1521 expectf(0.0, bounds.X); 1522 expectf(0.0, bounds.Y); 1523 expectf(320.0, bounds.Width); 1524 expectf(320.0, bounds.Height); 1525 1526 stat = GdipGetImageHorizontalResolution(img, &res); 1527 expect(Ok, stat); 1528 expectf(1440.0, res); 1529 1530 stat = GdipGetImageVerticalResolution(img, &res); 1531 expect(Ok, stat); 1532 expectf(1440.0, res); 1533 1534 memset(&header, 0, sizeof(header)); 1535 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header); 1536 expect(Ok, stat); 1537 if (stat == Ok) 1538 { 1539 expect(MetafileTypeWmfPlaceable, header.Type); 1540 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size); 1541 todo_wine expect(0x300, header.Version); 1542 expect(0, header.EmfPlusFlags); 1543 expectf(1440.0, header.DpiX); 1544 expectf(1440.0, header.DpiY); 1545 expect(0, header.X); 1546 expect(0, header.Y); 1547 expect(320, header.Width); 1548 expect(320, header.Height); 1549 expect(1, U(header).WmfHeader.mtType); 1550 expect(0, header.EmfPlusHeaderSize); 1551 expect(0, header.LogicalDpiX); 1552 expect(0, header.LogicalDpiY); 1553 } 1554 1555 GdipDisposeImage(img); 1556 } 1557 1558 static void test_createfromwmf_noplaceable(void) 1559 { 1560 HMETAFILE hwmf; 1561 GpImage *img; 1562 GpStatus stat; 1563 1564 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), 1565 wmfimage+sizeof(WmfPlaceableFileHeader)); 1566 ok(hwmf != 0, "SetMetaFileBitsEx failed\n"); 1567 1568 stat = GdipCreateMetafileFromWmf(hwmf, TRUE, NULL, (GpMetafile**)&img); 1569 expect(Ok, stat); 1570 1571 GdipDisposeImage(img); 1572 } 1573 1574 static void test_resolution(void) 1575 { 1576 GpStatus stat; 1577 GpBitmap *bitmap; 1578 GpGraphics *graphics; 1579 REAL res=-1.0; 1580 HDC screendc; 1581 int screenxres, screenyres; 1582 1583 /* create Bitmap */ 1584 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap); 1585 expect(Ok, stat); 1586 1587 /* test invalid values */ 1588 stat = GdipGetImageHorizontalResolution(NULL, &res); 1589 expect(InvalidParameter, stat); 1590 1591 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL); 1592 expect(InvalidParameter, stat); 1593 1594 stat = GdipGetImageVerticalResolution(NULL, &res); 1595 expect(InvalidParameter, stat); 1596 1597 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL); 1598 expect(InvalidParameter, stat); 1599 1600 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0); 1601 expect(InvalidParameter, stat); 1602 1603 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0); 1604 expect(InvalidParameter, stat); 1605 1606 /* defaults to screen resolution */ 1607 screendc = GetDC(0); 1608 1609 screenxres = GetDeviceCaps(screendc, LOGPIXELSX); 1610 screenyres = GetDeviceCaps(screendc, LOGPIXELSY); 1611 1612 ReleaseDC(0, screendc); 1613 1614 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res); 1615 expect(Ok, stat); 1616 expectf((REAL)screenxres, res); 1617 1618 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res); 1619 expect(Ok, stat); 1620 expectf((REAL)screenyres, res); 1621 1622 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); 1623 expect(Ok, stat); 1624 stat = GdipGetDpiX(graphics, &res); 1625 expect(Ok, stat); 1626 expectf((REAL)screenxres, res); 1627 stat = GdipGetDpiY(graphics, &res); 1628 expect(Ok, stat); 1629 expectf((REAL)screenyres, res); 1630 1631 /* test changing the resolution */ 1632 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0); 1633 expect(Ok, stat); 1634 1635 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res); 1636 expect(Ok, stat); 1637 expectf(screenxres*2.0, res); 1638 1639 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res); 1640 expect(Ok, stat); 1641 expectf(screenyres*3.0, res); 1642 1643 stat = GdipGetDpiX(graphics, &res); 1644 expect(Ok, stat); 1645 expectf((REAL)screenxres, res); 1646 stat = GdipGetDpiY(graphics, &res); 1647 expect(Ok, stat); 1648 expectf((REAL)screenyres, res); 1649 1650 stat = GdipDeleteGraphics(graphics); 1651 expect(Ok, stat); 1652 1653 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics); 1654 expect(Ok, stat); 1655 stat = GdipGetDpiX(graphics, &res); 1656 expect(Ok, stat); 1657 expectf(screenxres*2.0, res); 1658 stat = GdipGetDpiY(graphics, &res); 1659 expect(Ok, stat); 1660 expectf(screenyres*3.0, res); 1661 stat = GdipDeleteGraphics(graphics); 1662 expect(Ok, stat); 1663 1664 stat = GdipDisposeImage((GpImage*)bitmap); 1665 expect(Ok, stat); 1666 } 1667 1668 static void test_createhbitmap(void) 1669 { 1670 GpStatus stat; 1671 GpBitmap *bitmap; 1672 HBITMAP hbitmap, oldhbitmap; 1673 BITMAP bm; 1674 int ret; 1675 HDC hdc; 1676 COLORREF pixel; 1677 BYTE bits[640]; 1678 BitmapData lockeddata; 1679 1680 memset(bits, 0x68, 640); 1681 1682 /* create Bitmap */ 1683 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap); 1684 expect(Ok, stat); 1685 1686 /* test NULL values */ 1687 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0); 1688 expect(InvalidParameter, stat); 1689 1690 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0); 1691 expect(InvalidParameter, stat); 1692 1693 /* create HBITMAP */ 1694 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0); 1695 expect(Ok, stat); 1696 1697 if (stat == Ok) 1698 { 1699 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm); 1700 expect(sizeof(BITMAP), ret); 1701 1702 expect(0, bm.bmType); 1703 expect(10, bm.bmWidth); 1704 expect(20, bm.bmHeight); 1705 expect(40, bm.bmWidthBytes); 1706 expect(1, bm.bmPlanes); 1707 expect(32, bm.bmBitsPixel); 1708 ok(bm.bmBits != NULL, "got DDB, expected DIB\n"); 1709 1710 if (bm.bmBits) 1711 { 1712 DWORD val = *(DWORD*)bm.bmBits; 1713 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val); 1714 } 1715 1716 hdc = CreateCompatibleDC(NULL); 1717 1718 oldhbitmap = SelectObject(hdc, hbitmap); 1719 pixel = GetPixel(hdc, 5, 5); 1720 SelectObject(hdc, oldhbitmap); 1721 1722 DeleteDC(hdc); 1723 1724 expect(0x686868, pixel); 1725 1726 DeleteObject(hbitmap); 1727 } 1728 1729 stat = GdipDisposeImage((GpImage*)bitmap); 1730 expect(Ok, stat); 1731 1732 /* make (1,0) have no alpha and (2,0) a different blue value. */ 1733 bits[7] = 0x00; 1734 bits[8] = 0x40; 1735 1736 /* create alpha Bitmap */ 1737 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap); 1738 expect(Ok, stat); 1739 1740 /* create HBITMAP */ 1741 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0); 1742 expect(Ok, stat); 1743 1744 if (stat == Ok) 1745 { 1746 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm); 1747 expect(sizeof(BITMAP), ret); 1748 1749 expect(0, bm.bmType); 1750 expect(8, bm.bmWidth); 1751 expect(20, bm.bmHeight); 1752 expect(32, bm.bmWidthBytes); 1753 expect(1, bm.bmPlanes); 1754 expect(32, bm.bmBitsPixel); 1755 ok(bm.bmBits != NULL, "got DDB, expected DIB\n"); 1756 1757 if (bm.bmBits) 1758 { 1759 DWORD val = *(DWORD*)bm.bmBits; 1760 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val); 1761 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1); 1762 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val); 1763 } 1764 1765 hdc = CreateCompatibleDC(NULL); 1766 1767 oldhbitmap = SelectObject(hdc, hbitmap); 1768 pixel = GetPixel(hdc, 5, 5); 1769 expect(0x2a2a2a, pixel); 1770 pixel = GetPixel(hdc, 1, 0); 1771 expect(0x0, pixel); 1772 1773 SelectObject(hdc, oldhbitmap); 1774 1775 DeleteDC(hdc); 1776 1777 1778 DeleteObject(hbitmap); 1779 } 1780 1781 /* create HBITMAP with bkgnd colour */ 1782 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff); 1783 expect(Ok, stat); 1784 1785 if (stat == Ok) 1786 { 1787 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm); 1788 expect(sizeof(BITMAP), ret); 1789 1790 expect(0, bm.bmType); 1791 expect(8, bm.bmWidth); 1792 expect(20, bm.bmHeight); 1793 expect(32, bm.bmWidthBytes); 1794 expect(1, bm.bmPlanes); 1795 expect(32, bm.bmBitsPixel); 1796 ok(bm.bmBits != NULL, "got DDB, expected DIB\n"); 1797 1798 if (bm.bmBits) 1799 { 1800 DWORD val = *(DWORD*)bm.bmBits; 1801 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val); 1802 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1); 1803 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val); 1804 } 1805 1806 hdc = CreateCompatibleDC(NULL); 1807 1808 oldhbitmap = SelectObject(hdc, hbitmap); 1809 pixel = GetPixel(hdc, 5, 5); 1810 expect(0xc12ac1, pixel); 1811 pixel = GetPixel(hdc, 1, 0); 1812 expect(0xff00ff, pixel); 1813 pixel = GetPixel(hdc, 2, 0); 1814 expect(0xb12ac1, pixel); 1815 1816 SelectObject(hdc, oldhbitmap); 1817 DeleteDC(hdc); 1818 DeleteObject(hbitmap); 1819 } 1820 1821 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */ 1822 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff); 1823 expect(Ok, stat); 1824 1825 if (stat == Ok) 1826 { 1827 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm); 1828 expect(sizeof(BITMAP), ret); 1829 1830 expect(0, bm.bmType); 1831 expect(8, bm.bmWidth); 1832 expect(20, bm.bmHeight); 1833 expect(32, bm.bmWidthBytes); 1834 expect(1, bm.bmPlanes); 1835 expect(32, bm.bmBitsPixel); 1836 ok(bm.bmBits != NULL, "got DDB, expected DIB\n"); 1837 1838 if (bm.bmBits) 1839 { 1840 DWORD val = *(DWORD*)bm.bmBits; 1841 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val); 1842 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1); 1843 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val); 1844 } 1845 1846 hdc = CreateCompatibleDC(NULL); 1847 1848 oldhbitmap = SelectObject(hdc, hbitmap); 1849 pixel = GetPixel(hdc, 5, 5); 1850 expect(0xc12ac1, pixel); 1851 pixel = GetPixel(hdc, 1, 0); 1852 expect(0xff00ff, pixel); 1853 pixel = GetPixel(hdc, 2, 0); 1854 expect(0xb12ac1, pixel); 1855 1856 SelectObject(hdc, oldhbitmap); 1857 DeleteDC(hdc); 1858 DeleteObject(hbitmap); 1859 } 1860 1861 stat = GdipDisposeImage((GpImage*)bitmap); 1862 expect(Ok, stat); 1863 1864 /* create HBITMAP from locked data */ 1865 memset(bits, 0x68, 640); 1866 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap); 1867 expect(Ok, stat); 1868 1869 memset(&lockeddata, 0, sizeof(lockeddata)); 1870 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, 1871 PixelFormat32bppRGB, &lockeddata); 1872 expect(Ok, stat); 1873 ((DWORD*)lockeddata.Scan0)[0] = 0xff242424; 1874 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0); 1875 expect(Ok, stat); 1876 stat = GdipBitmapUnlockBits(bitmap, &lockeddata); 1877 expect(Ok, stat); 1878 stat = GdipDisposeImage((GpImage*)bitmap); 1879 expect(Ok, stat); 1880 1881 hdc = CreateCompatibleDC(NULL); 1882 oldhbitmap = SelectObject(hdc, hbitmap); 1883 pixel = GetPixel(hdc, 0, 0); 1884 expect(0x686868, pixel); 1885 SelectObject(hdc, oldhbitmap); 1886 DeleteDC(hdc); 1887 } 1888 1889 static void test_getthumbnail(void) 1890 { 1891 GpStatus stat; 1892 GpImage *bitmap1, *bitmap2; 1893 UINT width, height; 1894 1895 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL); 1896 expect(InvalidParameter, stat); 1897 1898 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1); 1899 expect(Ok, stat); 1900 1901 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL); 1902 expect(InvalidParameter, stat); 1903 1904 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL); 1905 expect(Ok, stat); 1906 1907 if (stat == Ok) 1908 { 1909 stat = GdipGetImageWidth(bitmap2, &width); 1910 expect(Ok, stat); 1911 expect(120, width); 1912 1913 stat = GdipGetImageHeight(bitmap2, &height); 1914 expect(Ok, stat); 1915 expect(120, height); 1916 1917 GdipDisposeImage(bitmap2); 1918 } 1919 1920 GdipDisposeImage(bitmap1); 1921 1922 1923 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1); 1924 expect(Ok, stat); 1925 1926 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL); 1927 expect(Ok, stat); 1928 1929 if (stat == Ok) 1930 { 1931 stat = GdipGetImageWidth(bitmap2, &width); 1932 expect(Ok, stat); 1933 expect(32, width); 1934 1935 stat = GdipGetImageHeight(bitmap2, &height); 1936 expect(Ok, stat); 1937 expect(32, height); 1938 1939 GdipDisposeImage(bitmap2); 1940 } 1941 1942 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL); 1943 expect(Ok, stat); 1944 1945 if (stat == Ok) 1946 { 1947 stat = GdipGetImageWidth(bitmap2, &width); 1948 expect(Ok, stat); 1949 expect(120, width); 1950 1951 stat = GdipGetImageHeight(bitmap2, &height); 1952 expect(Ok, stat); 1953 expect(120, height); 1954 1955 GdipDisposeImage(bitmap2); 1956 } 1957 1958 GdipDisposeImage(bitmap1); 1959 } 1960 1961 static void test_getsetpixel(void) 1962 { 1963 GpStatus stat; 1964 GpBitmap *bitmap; 1965 ARGB color; 1966 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00, 1967 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00}; 1968 1969 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap); 1970 expect(Ok, stat); 1971 1972 /* null parameters */ 1973 stat = GdipBitmapGetPixel(NULL, 1, 1, &color); 1974 expect(InvalidParameter, stat); 1975 1976 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL); 1977 expect(InvalidParameter, stat); 1978 1979 stat = GdipBitmapSetPixel(NULL, 1, 1, 0); 1980 expect(InvalidParameter, stat); 1981 1982 /* out of bounds */ 1983 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color); 1984 expect(InvalidParameter, stat); 1985 1986 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0); 1987 expect(InvalidParameter, stat); 1988 1989 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color); 1990 ok(stat == InvalidParameter || 1991 broken(stat == Ok), /* Older gdiplus */ 1992 "Expected InvalidParameter, got %.8x\n", stat); 1993 1994 if (0) /* crashes some gdiplus implementations */ 1995 { 1996 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0); 1997 ok(stat == InvalidParameter || 1998 broken(stat == Ok), /* Older gdiplus */ 1999 "Expected InvalidParameter, got %.8x\n", stat); 2000 } 2001 2002 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color); 2003 expect(InvalidParameter, stat); 2004 2005 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0); 2006 expect(InvalidParameter, stat); 2007 2008 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color); 2009 expect(InvalidParameter, stat); 2010 2011 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0); 2012 expect(InvalidParameter, stat); 2013 2014 /* valid use */ 2015 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color); 2016 expect(Ok, stat); 2017 expect(0xffffffff, color); 2018 2019 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color); 2020 expect(Ok, stat); 2021 expect(0xff0000ff, color); 2022 2023 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869); 2024 expect(Ok, stat); 2025 2026 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849); 2027 expect(Ok, stat); 2028 2029 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color); 2030 expect(Ok, stat); 2031 expect(0xff676869, color); 2032 2033 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color); 2034 expect(Ok, stat); 2035 expect(0xff474849, color); 2036 2037 stat = GdipDisposeImage((GpImage*)bitmap); 2038 expect(Ok, stat); 2039 } 2040 2041 static void check_halftone_palette(ColorPalette *palette) 2042 { 2043 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff}; 2044 UINT i; 2045 2046 for (i=0; i<palette->Count; i++) 2047 { 2048 ARGB expected=0xff000000; 2049 if (i<8) 2050 { 2051 if (i&1) expected |= 0x800000; 2052 if (i&2) expected |= 0x8000; 2053 if (i&4) expected |= 0x80; 2054 } 2055 else if (i == 8) 2056 { 2057 expected = 0xffc0c0c0; 2058 } 2059 else if (i < 16) 2060 { 2061 if (i&1) expected |= 0xff0000; 2062 if (i&2) expected |= 0xff00; 2063 if (i&4) expected |= 0xff; 2064 } 2065 else if (i < 40) 2066 { 2067 expected = 0x00000000; 2068 } 2069 else 2070 { 2071 expected |= halftone_values[(i-40)%6]; 2072 expected |= halftone_values[((i-40)/6)%6] << 8; 2073 expected |= halftone_values[((i-40)/36)%6] << 16; 2074 } 2075 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n", 2076 expected, palette->Entries[i], i, palette->Count); 2077 } 2078 } 2079 2080 static void test_palette(void) 2081 { 2082 GpStatus stat; 2083 GpBitmap *bitmap; 2084 INT size; 2085 BYTE buffer[1040]; 2086 ColorPalette *palette=(ColorPalette*)buffer; 2087 ARGB *entries = palette->Entries; 2088 ARGB color=0; 2089 2090 /* test initial palette from non-indexed bitmap */ 2091 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap); 2092 expect(Ok, stat); 2093 2094 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2095 expect(Ok, stat); 2096 expect(sizeof(UINT)*2+sizeof(ARGB), size); 2097 2098 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2099 expect(Ok, stat); 2100 expect(0, palette->Count); 2101 2102 /* test setting palette on not-indexed bitmap */ 2103 palette->Count = 3; 2104 2105 stat = GdipSetImagePalette((GpImage*)bitmap, palette); 2106 expect(Ok, stat); 2107 2108 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2109 expect(Ok, stat); 2110 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size); 2111 2112 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2113 expect(Ok, stat); 2114 expect(3, palette->Count); 2115 2116 GdipDisposeImage((GpImage*)bitmap); 2117 2118 /* test initial palette on 1-bit bitmap */ 2119 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap); 2120 expect(Ok, stat); 2121 2122 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2123 expect(Ok, stat); 2124 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size); 2125 2126 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2127 expect(Ok, stat); 2128 expect(PaletteFlagsGrayScale, palette->Flags); 2129 expect(2, palette->Count); 2130 2131 expect(0xff000000, entries[0]); 2132 expect(0xffffffff, entries[1]); 2133 2134 /* test getting/setting pixels */ 2135 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color); 2136 expect(Ok, stat); 2137 expect(0xff000000, color); 2138 2139 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff); 2140 ok((stat == Ok) || 2141 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat); 2142 2143 if (stat == Ok) 2144 { 2145 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color); 2146 expect(Ok, stat); 2147 expect(0xffffffff, color); 2148 } 2149 2150 GdipDisposeImage((GpImage*)bitmap); 2151 2152 /* test initial palette on 4-bit bitmap */ 2153 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap); 2154 expect(Ok, stat); 2155 2156 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2157 expect(Ok, stat); 2158 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size); 2159 2160 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2161 expect(Ok, stat); 2162 expect(0, palette->Flags); 2163 expect(16, palette->Count); 2164 2165 check_halftone_palette(palette); 2166 2167 /* test getting/setting pixels */ 2168 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color); 2169 expect(Ok, stat); 2170 expect(0xff000000, color); 2171 2172 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff); 2173 ok((stat == Ok) || 2174 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat); 2175 2176 if (stat == Ok) 2177 { 2178 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color); 2179 expect(Ok, stat); 2180 expect(0xffff00ff, color); 2181 } 2182 2183 GdipDisposeImage((GpImage*)bitmap); 2184 2185 /* test initial palette on 8-bit bitmap */ 2186 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap); 2187 expect(Ok, stat); 2188 2189 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2190 expect(Ok, stat); 2191 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size); 2192 2193 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2194 expect(Ok, stat); 2195 expect(PaletteFlagsHalftone, palette->Flags); 2196 expect(256, palette->Count); 2197 2198 check_halftone_palette(palette); 2199 2200 /* test getting/setting pixels */ 2201 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color); 2202 expect(Ok, stat); 2203 expect(0xff000000, color); 2204 2205 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc); 2206 ok((stat == Ok) || 2207 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat); 2208 2209 if (stat == Ok) 2210 { 2211 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color); 2212 expect(Ok, stat); 2213 expect(0xffcccccc, color); 2214 } 2215 2216 /* test setting/getting a different palette */ 2217 entries[1] = 0xffcccccc; 2218 2219 stat = GdipSetImagePalette((GpImage*)bitmap, palette); 2220 expect(Ok, stat); 2221 2222 entries[1] = 0; 2223 2224 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2225 expect(Ok, stat); 2226 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size); 2227 2228 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2229 expect(Ok, stat); 2230 expect(PaletteFlagsHalftone, palette->Flags); 2231 expect(256, palette->Count); 2232 expect(0xffcccccc, entries[1]); 2233 2234 /* test count < 256 */ 2235 palette->Flags = 12345; 2236 palette->Count = 3; 2237 2238 stat = GdipSetImagePalette((GpImage*)bitmap, palette); 2239 expect(Ok, stat); 2240 2241 entries[1] = 0; 2242 entries[3] = 0xdeadbeef; 2243 2244 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size); 2245 expect(Ok, stat); 2246 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size); 2247 2248 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size); 2249 expect(Ok, stat); 2250 expect(12345, palette->Flags); 2251 expect(3, palette->Count); 2252 expect(0xffcccccc, entries[1]); 2253 expect(0xdeadbeef, entries[3]); 2254 2255 /* test count > 256 */ 2256 palette->Count = 257; 2257 2258 stat = GdipSetImagePalette((GpImage*)bitmap, palette); 2259 ok(stat == InvalidParameter || 2260 broken(stat == Ok), /* Old gdiplus behavior */ 2261 "Expected %.8x, got %.8x\n", InvalidParameter, stat); 2262 2263 GdipDisposeImage((GpImage*)bitmap); 2264 } 2265 2266 static void test_colormatrix(void) 2267 { 2268 GpStatus stat; 2269 ColorMatrix colormatrix, graymatrix; 2270 GpImageAttributes *imageattr; 2271 const ColorMatrix identity = {{ 2272 {1.0,0.0,0.0,0.0,0.0}, 2273 {0.0,1.0,0.0,0.0,0.0}, 2274 {0.0,0.0,1.0,0.0,0.0}, 2275 {0.0,0.0,0.0,1.0,0.0}, 2276 {0.0,0.0,0.0,0.0,1.0}}}; 2277 const ColorMatrix double_red = {{ 2278 {2.0,0.0,0.0,0.0,0.0}, 2279 {0.0,1.0,0.0,0.0,0.0}, 2280 {0.0,0.0,1.0,0.0,0.0}, 2281 {0.0,0.0,0.0,1.0,0.0}, 2282 {0.0,0.0,0.0,0.0,1.0}}}; 2283 const ColorMatrix asymmetric = {{ 2284 {0.0,1.0,0.0,0.0,0.0}, 2285 {0.0,0.0,1.0,0.0,0.0}, 2286 {0.0,0.0,0.0,1.0,0.0}, 2287 {1.0,0.0,0.0,0.0,0.0}, 2288 {0.0,0.0,0.0,0.0,1.0}}}; 2289 GpBitmap *bitmap1, *bitmap2; 2290 GpGraphics *graphics; 2291 ARGB color; 2292 2293 colormatrix = identity; 2294 graymatrix = identity; 2295 2296 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault, 2297 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault); 2298 expect(InvalidParameter, stat); 2299 2300 stat = GdipCreateImageAttributes(&imageattr); 2301 expect(Ok, stat); 2302 2303 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2304 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault); 2305 expect(Ok, stat); 2306 2307 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2308 TRUE, NULL, NULL, ColorMatrixFlagsDefault); 2309 expect(InvalidParameter, stat); 2310 2311 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2312 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault); 2313 expect(Ok, stat); 2314 2315 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2316 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays); 2317 expect(Ok, stat); 2318 2319 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2320 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray); 2321 expect(InvalidParameter, stat); 2322 2323 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2324 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray); 2325 expect(Ok, stat); 2326 2327 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2328 TRUE, &colormatrix, &graymatrix, 3); 2329 expect(InvalidParameter, stat); 2330 2331 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount, 2332 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault); 2333 expect(InvalidParameter, stat); 2334 2335 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny, 2336 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault); 2337 expect(InvalidParameter, stat); 2338 2339 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2340 FALSE, NULL, NULL, ColorMatrixFlagsDefault); 2341 expect(Ok, stat); 2342 2343 /* Drawing a bitmap transforms the colors */ 2344 colormatrix = double_red; 2345 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2346 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault); 2347 expect(Ok, stat); 2348 2349 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1); 2350 expect(Ok, stat); 2351 2352 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2); 2353 expect(Ok, stat); 2354 2355 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee); 2356 expect(Ok, stat); 2357 2358 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics); 2359 expect(Ok, stat); 2360 2361 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2362 UnitPixel, imageattr, NULL, NULL); 2363 expect(Ok, stat); 2364 2365 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2366 expect(Ok, stat); 2367 expect(0xff80ccee, color); 2368 2369 colormatrix = asymmetric; 2370 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault, 2371 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault); 2372 expect(Ok, stat); 2373 2374 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0); 2375 expect(Ok, stat); 2376 2377 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2378 UnitPixel, imageattr, NULL, NULL); 2379 expect(Ok, stat); 2380 2381 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2382 expect(Ok, stat); 2383 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color); 2384 2385 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault); 2386 expect(Ok, stat); 2387 2388 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2389 UnitPixel, imageattr, NULL, NULL); 2390 expect(Ok, stat); 2391 2392 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2393 expect(Ok, stat); 2394 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color); 2395 2396 GdipDeleteGraphics(graphics); 2397 GdipDisposeImage((GpImage*)bitmap1); 2398 GdipDisposeImage((GpImage*)bitmap2); 2399 GdipDisposeImageAttributes(imageattr); 2400 } 2401 2402 static void test_gamma(void) 2403 { 2404 GpStatus stat; 2405 GpImageAttributes *imageattr; 2406 GpBitmap *bitmap1, *bitmap2; 2407 GpGraphics *graphics; 2408 ARGB color; 2409 2410 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0); 2411 expect(InvalidParameter, stat); 2412 2413 stat = GdipCreateImageAttributes(&imageattr); 2414 expect(Ok, stat); 2415 2416 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0); 2417 expect(Ok, stat); 2418 2419 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0); 2420 expect(InvalidParameter, stat); 2421 2422 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0); 2423 expect(InvalidParameter, stat); 2424 2425 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0); 2426 expect(InvalidParameter, stat); 2427 2428 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5); 2429 expect(Ok, stat); 2430 2431 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0); 2432 expect(Ok, stat); 2433 2434 /* Drawing a bitmap transforms the colors */ 2435 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0); 2436 expect(Ok, stat); 2437 2438 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1); 2439 expect(Ok, stat); 2440 2441 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2); 2442 expect(Ok, stat); 2443 2444 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff); 2445 expect(Ok, stat); 2446 2447 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics); 2448 expect(Ok, stat); 2449 2450 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2451 UnitPixel, imageattr, NULL, NULL); 2452 expect(Ok, stat); 2453 2454 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2455 expect(Ok, stat); 2456 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color); 2457 2458 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault); 2459 expect(Ok, stat); 2460 2461 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2462 UnitPixel, imageattr, NULL, NULL); 2463 expect(Ok, stat); 2464 2465 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2466 expect(Ok, stat); 2467 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color); 2468 2469 GdipDeleteGraphics(graphics); 2470 GdipDisposeImage((GpImage*)bitmap1); 2471 GdipDisposeImage((GpImage*)bitmap2); 2472 GdipDisposeImageAttributes(imageattr); 2473 } 2474 2475 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */ 2476 static const unsigned char gifanimation[72] = { 2477 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00, 2478 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff, 2479 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00, 2480 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01, 2481 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b 2482 }; 2483 2484 /* Generated with ImageMagick: 2485 * convert -transparent black -delay 100 -size 8x2 xc:black \ 2486 * -dispose none -page +0+0 -size 2x2 xc:red \ 2487 * -dispose background -page +2+0 -size 2x2 xc:blue \ 2488 * -dispose previous -page +4+0 -size 2x2 xc:green \ 2489 * -dispose undefined -page +6+0 -size 2x2 xc:gray \ 2490 * test.gif 2491 */ 2492 static const unsigned char gifanimation2[] = { 2493 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00, 2494 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 2495 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64, 2496 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45, 2497 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e, 2498 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00, 2499 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 2500 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21, 2501 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c, 2502 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 2503 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 2504 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44, 2505 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64, 2506 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00, 2507 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff, 2508 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 2509 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21, 2510 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c, 2511 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, 2512 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 2513 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44, 2514 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64, 2515 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00, 2516 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e, 2517 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00, 2518 0x3b 2519 }; 2520 2521 static ARGB gifanimation2_pixels[5][4] = { 2522 {0, 0, 0, 0}, 2523 {0xffff0000, 0, 0, 0}, 2524 {0xffff0000, 0xff0000ff, 0, 0}, 2525 {0xffff0000, 0, 0xff008000, 0}, 2526 {0xffff0000, 0, 0, 0xff7e7e7e} 2527 }; 2528 2529 static void test_multiframegif(void) 2530 { 2531 LPSTREAM stream; 2532 HGLOBAL hglob; 2533 LPBYTE data; 2534 HRESULT hres; 2535 GpStatus stat; 2536 GpBitmap *bmp; 2537 ARGB color; 2538 UINT count; 2539 GUID dimension; 2540 PixelFormat pixel_format; 2541 INT palette_size, i, j; 2542 char palette_buf[256]; 2543 ColorPalette *palette; 2544 ARGB *palette_entries; 2545 2546 /* Test frame functions with an animated GIF */ 2547 hglob = GlobalAlloc (0, sizeof(gifanimation)); 2548 data = GlobalLock (hglob); 2549 memcpy(data, gifanimation, sizeof(gifanimation)); 2550 GlobalUnlock(hglob); 2551 2552 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream); 2553 ok(hres == S_OK, "Failed to create a stream\n"); 2554 if(hres != S_OK) return; 2555 2556 stat = GdipCreateBitmapFromStream(stream, &bmp); 2557 ok(stat == Ok, "Failed to create a Bitmap\n"); 2558 if(stat != Ok){ 2559 IStream_Release(stream); 2560 return; 2561 } 2562 2563 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format); 2564 expect(Ok, stat); 2565 expect(PixelFormat32bppARGB, pixel_format); 2566 2567 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size); 2568 expect(Ok, stat); 2569 ok(palette_size == sizeof(ColorPalette) || 2570 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])), 2571 "palette_size = %d\n", palette_size); 2572 2573 /* Bitmap starts at frame 0 */ 2574 color = 0xdeadbeef; 2575 stat = GdipBitmapGetPixel(bmp, 0, 0, &color); 2576 expect(Ok, stat); 2577 expect(0xffffffff, color); 2578 2579 /* Check that we get correct metadata */ 2580 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count); 2581 expect(Ok, stat); 2582 expect(1, count); 2583 2584 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1); 2585 expect(Ok, stat); 2586 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE); 2587 2588 count = 12345; 2589 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count); 2590 expect(Ok, stat); 2591 expect(2, count); 2592 2593 /* SelectActiveFrame overwrites our current data */ 2594 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1); 2595 expect(Ok, stat); 2596 2597 color = 0xdeadbeef; 2598 GdipBitmapGetPixel(bmp, 0, 0, &color); 2599 expect(Ok, stat); 2600 expect(0xff000000, color); 2601 2602 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0); 2603 expect(Ok, stat); 2604 2605 color = 0xdeadbeef; 2606 GdipBitmapGetPixel(bmp, 0, 0, &color); 2607 expect(Ok, stat); 2608 expect(0xffffffff, color); 2609 2610 /* Write over the image data */ 2611 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000); 2612 expect(Ok, stat); 2613 2614 /* Switching to the same frame does not overwrite our changes */ 2615 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0); 2616 expect(Ok, stat); 2617 2618 stat = GdipBitmapGetPixel(bmp, 0, 0, &color); 2619 expect(Ok, stat); 2620 expect(0xff000000, color); 2621 2622 /* But switching to another frame and back does */ 2623 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1); 2624 expect(Ok, stat); 2625 2626 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0); 2627 expect(Ok, stat); 2628 2629 stat = GdipBitmapGetPixel(bmp, 0, 0, &color); 2630 expect(Ok, stat); 2631 expect(0xffffffff, color); 2632 2633 /* rotate/flip discards the information about other frames */ 2634 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone); 2635 expect(Ok, stat); 2636 2637 count = 12345; 2638 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count); 2639 expect(Ok, stat); 2640 expect(1, count); 2641 2642 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE); 2643 2644 GdipDisposeImage((GpImage*)bmp); 2645 IStream_Release(stream); 2646 2647 /* Test with a non-animated gif */ 2648 hglob = GlobalAlloc (0, sizeof(gifimage)); 2649 data = GlobalLock (hglob); 2650 memcpy(data, gifimage, sizeof(gifimage)); 2651 GlobalUnlock(hglob); 2652 2653 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream); 2654 ok(hres == S_OK, "Failed to create a stream\n"); 2655 if(hres != S_OK) return; 2656 2657 stat = GdipCreateBitmapFromStream(stream, &bmp); 2658 ok(stat == Ok, "Failed to create a Bitmap\n"); 2659 if(stat != Ok){ 2660 IStream_Release(stream); 2661 return; 2662 } 2663 2664 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format); 2665 expect(Ok, stat); 2666 expect(PixelFormat8bppIndexed, pixel_format); 2667 2668 /* Check metadata */ 2669 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count); 2670 expect(Ok, stat); 2671 expect(1, count); 2672 2673 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1); 2674 expect(Ok, stat); 2675 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE); 2676 2677 count = 12345; 2678 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count); 2679 expect(Ok, stat); 2680 expect(1, count); 2681 2682 GdipDisposeImage((GpImage*)bmp); 2683 IStream_Release(stream); 2684 2685 /* Test with a non-animated transparent gif */ 2686 hglob = GlobalAlloc (0, sizeof(transparentgif)); 2687 data = GlobalLock (hglob); 2688 memcpy(data, transparentgif, sizeof(transparentgif)); 2689 GlobalUnlock(hglob); 2690 2691 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream); 2692 ok(hres == S_OK, "Failed to create a stream\n"); 2693 2694 stat = GdipCreateBitmapFromStream(stream, &bmp); 2695 IStream_Release(stream); 2696 ok(stat == Ok, "Failed to create a Bitmap\n"); 2697 2698 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format); 2699 expect(Ok, stat); 2700 expect(PixelFormat8bppIndexed, pixel_format); 2701 2702 stat = GdipBitmapGetPixel(bmp, 0, 0, &color); 2703 expect(Ok, stat); 2704 expect(0, color); 2705 2706 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size); 2707 expect(Ok, stat); 2708 ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB), 2709 "palette_size = %d\n", palette_size); 2710 2711 memset(palette_buf, 0xfe, sizeof(palette_buf)); 2712 palette = (ColorPalette*)palette_buf; 2713 stat = GdipGetImagePalette((GpImage*)bmp, palette, 2714 sizeof(ColorPalette)+sizeof(ARGB)); 2715 palette_entries = palette->Entries; 2716 expect(Ok, stat); 2717 expect(PaletteFlagsHasAlpha, palette->Flags); 2718 expect(2, palette->Count); 2719 expect(0, palette_entries[0]); 2720 expect(0xff000000, palette_entries[1]); 2721 2722 count = 12345; 2723 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count); 2724 expect(Ok, stat); 2725 expect(1, count); 2726 2727 GdipDisposeImage((GpImage*)bmp); 2728 2729 /* Test frame dispose methods */ 2730 hglob = GlobalAlloc (0, sizeof(gifanimation2)); 2731 data = GlobalLock (hglob); 2732 memcpy(data, gifanimation2, sizeof(gifanimation2)); 2733 GlobalUnlock(hglob); 2734 2735 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream); 2736 ok(hres == S_OK, "Failed to create a stream\n"); 2737 2738 stat = GdipCreateBitmapFromStream(stream, &bmp); 2739 ok(stat == Ok, "Failed to create a Bitmap\n"); 2740 IStream_Release(stream); 2741 2742 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1); 2743 expect(Ok, stat); 2744 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE); 2745 2746 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count); 2747 expect(Ok, stat); 2748 expect(5, count); 2749 2750 stat = GdipBitmapGetPixel(bmp, 0, 0, &color); 2751 expect(Ok, stat); 2752 expect(0, color); 2753 2754 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3); 2755 expect(Ok, stat); 2756 stat = GdipBitmapGetPixel(bmp, 2, 0, &color); 2757 expect(Ok, stat); 2758 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color); 2759 if(color != 0) { 2760 win_skip("broken animated gif support\n"); 2761 GdipDisposeImage((GpImage*)bmp); 2762 return; 2763 } 2764 2765 for(i=0; i<6; i++) { 2766 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5); 2767 expect(Ok, stat); 2768 2769 for(j=0; j<4; j++) { 2770 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color); 2771 expect(Ok, stat); 2772 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]); 2773 } 2774 } 2775 2776 GdipDisposeImage((GpImage*)bmp); 2777 } 2778 2779 static void test_rotateflip(void) 2780 { 2781 GpImage *bitmap; 2782 GpStatus stat; 2783 BYTE bits[24]; 2784 static const BYTE orig_bits[24] = { 2785 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23, 2786 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23}; 2787 UINT width, height; 2788 ARGB color; 2789 2790 memcpy(bits, orig_bits, sizeof(bits)); 2791 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap); 2792 expect(Ok, stat); 2793 2794 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone); 2795 expect(Ok, stat); 2796 2797 stat = GdipGetImageWidth(bitmap, &width); 2798 expect(Ok, stat); 2799 stat = GdipGetImageHeight(bitmap, &height); 2800 expect(Ok, stat); 2801 expect(2, width); 2802 expect(3, height); 2803 2804 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color); 2805 expect(Ok, stat); 2806 expect(0xff00ffff, color); 2807 2808 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color); 2809 expect(Ok, stat); 2810 expect(0xffff0000, color); 2811 2812 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color); 2813 expect(Ok, stat); 2814 expect(0xffffff00, color); 2815 2816 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color); 2817 expect(Ok, stat); 2818 expect(0xff0000ff, color); 2819 2820 expect(0, bits[0]); 2821 expect(0, bits[1]); 2822 expect(0xff, bits[2]); 2823 2824 GdipDisposeImage(bitmap); 2825 2826 memcpy(bits, orig_bits, sizeof(bits)); 2827 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap); 2828 expect(Ok, stat); 2829 2830 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX); 2831 expect(Ok, stat); 2832 2833 stat = GdipGetImageWidth(bitmap, &width); 2834 expect(Ok, stat); 2835 stat = GdipGetImageHeight(bitmap, &height); 2836 expect(Ok, stat); 2837 expect(3, width); 2838 expect(2, height); 2839 2840 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color); 2841 expect(Ok, stat); 2842 expect(0xff0000ff, color); 2843 2844 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color); 2845 expect(Ok, stat); 2846 expect(0xffff0000, color); 2847 2848 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color); 2849 expect(Ok, stat); 2850 expect(0xffffff00, color); 2851 2852 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color); 2853 expect(Ok, stat); 2854 expect(0xff00ffff, color); 2855 2856 expect(0, bits[0]); 2857 expect(0, bits[1]); 2858 expect(0xff, bits[2]); 2859 2860 GdipDisposeImage(bitmap); 2861 2862 memcpy(bits, orig_bits, sizeof(bits)); 2863 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap); 2864 expect(Ok, stat); 2865 2866 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY); 2867 expect(Ok, stat); 2868 2869 stat = GdipGetImageWidth(bitmap, &width); 2870 expect(Ok, stat); 2871 stat = GdipGetImageHeight(bitmap, &height); 2872 expect(Ok, stat); 2873 expect(3, width); 2874 expect(2, height); 2875 2876 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color); 2877 expect(Ok, stat); 2878 expect(0xff00ffff, color); 2879 2880 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color); 2881 expect(Ok, stat); 2882 expect(0xffffff00, color); 2883 2884 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color); 2885 expect(Ok, stat); 2886 expect(0xffff0000, color); 2887 2888 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color); 2889 expect(Ok, stat); 2890 expect(0xff0000ff, color); 2891 2892 expect(0, bits[0]); 2893 expect(0, bits[1]); 2894 expect(0xff, bits[2]); 2895 2896 GdipDisposeImage(bitmap); 2897 } 2898 2899 static void test_remaptable(void) 2900 { 2901 GpStatus stat; 2902 GpImageAttributes *imageattr; 2903 GpBitmap *bitmap1, *bitmap2; 2904 GpGraphics *graphics; 2905 ARGB color; 2906 ColorMap *map; 2907 2908 map = GdipAlloc(sizeof(ColorMap)); 2909 2910 map->oldColor.Argb = 0xff00ff00; 2911 map->newColor.Argb = 0xffff00ff; 2912 2913 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map); 2914 expect(InvalidParameter, stat); 2915 2916 stat = GdipCreateImageAttributes(&imageattr); 2917 expect(Ok, stat); 2918 2919 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL); 2920 expect(InvalidParameter, stat); 2921 2922 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map); 2923 expect(InvalidParameter, stat); 2924 2925 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map); 2926 expect(InvalidParameter, stat); 2927 2928 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map); 2929 expect(InvalidParameter, stat); 2930 2931 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL); 2932 expect(Ok, stat); 2933 2934 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map); 2935 expect(Ok, stat); 2936 2937 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1); 2938 expect(Ok, stat); 2939 2940 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2); 2941 expect(Ok, stat); 2942 2943 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00); 2944 expect(Ok, stat); 2945 2946 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics); 2947 expect(Ok, stat); 2948 2949 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2950 UnitPixel, imageattr, NULL, NULL); 2951 expect(Ok, stat); 2952 2953 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2954 expect(Ok, stat); 2955 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color); 2956 2957 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault); 2958 expect(Ok, stat); 2959 2960 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1, 2961 UnitPixel, imageattr, NULL, NULL); 2962 expect(Ok, stat); 2963 2964 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 2965 expect(Ok, stat); 2966 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color); 2967 2968 GdipDeleteGraphics(graphics); 2969 GdipDisposeImage((GpImage*)bitmap1); 2970 GdipDisposeImage((GpImage*)bitmap2); 2971 GdipDisposeImageAttributes(imageattr); 2972 GdipFree(map); 2973 } 2974 2975 static void test_colorkey(void) 2976 { 2977 GpStatus stat; 2978 GpImageAttributes *imageattr; 2979 GpBitmap *bitmap1, *bitmap2; 2980 GpGraphics *graphics; 2981 ARGB color; 2982 2983 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090); 2984 expect(InvalidParameter, stat); 2985 2986 stat = GdipCreateImageAttributes(&imageattr); 2987 expect(Ok, stat); 2988 2989 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090); 2990 expect(InvalidParameter, stat); 2991 2992 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090); 2993 expect(InvalidParameter, stat); 2994 2995 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090); 2996 expect(Ok, stat); 2997 2998 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1); 2999 expect(Ok, stat); 3000 3001 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2); 3002 expect(Ok, stat); 3003 3004 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060); 3005 expect(Ok, stat); 3006 3007 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070); 3008 expect(Ok, stat); 3009 3010 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090); 3011 expect(Ok, stat); 3012 3013 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff); 3014 expect(Ok, stat); 3015 3016 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics); 3017 expect(Ok, stat); 3018 3019 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2, 3020 UnitPixel, imageattr, NULL, NULL); 3021 expect(Ok, stat); 3022 3023 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 3024 expect(Ok, stat); 3025 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color); 3026 3027 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color); 3028 expect(Ok, stat); 3029 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color); 3030 3031 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color); 3032 expect(Ok, stat); 3033 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color); 3034 3035 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color); 3036 expect(Ok, stat); 3037 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color); 3038 3039 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault); 3040 expect(Ok, stat); 3041 3042 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2, 3043 UnitPixel, imageattr, NULL, NULL); 3044 expect(Ok, stat); 3045 3046 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color); 3047 expect(Ok, stat); 3048 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color); 3049 3050 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color); 3051 expect(Ok, stat); 3052 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color); 3053 3054 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color); 3055 expect(Ok, stat); 3056 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color); 3057 3058 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color); 3059 expect(Ok, stat); 3060 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color); 3061 3062 3063 GdipDeleteGraphics(graphics); 3064 GdipDisposeImage((GpImage*)bitmap1); 3065 GdipDisposeImage((GpImage*)bitmap2); 3066 GdipDisposeImageAttributes(imageattr); 3067 } 3068 3069 static void test_dispose(void) 3070 { 3071 GpStatus stat; 3072 GpImage *image; 3073 char invalid_image[256]; 3074 3075 stat = GdipDisposeImage(NULL); 3076 expect(InvalidParameter, stat); 3077 3078 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image); 3079 expect(Ok, stat); 3080 3081 stat = GdipDisposeImage(image); 3082 expect(Ok, stat); 3083 3084 stat = GdipDisposeImage(image); 3085 expect(ObjectBusy, stat); 3086 3087 memset(invalid_image, 0, 256); 3088 stat = GdipDisposeImage((GpImage*)invalid_image); 3089 expect(ObjectBusy, stat); 3090 } 3091 3092 static LONG obj_refcount(void *obj) 3093 { 3094 IUnknown_AddRef((IUnknown *)obj); 3095 return IUnknown_Release((IUnknown *)obj); 3096 } 3097 3098 static GpImage *load_image(const BYTE *image_data, UINT image_size) 3099 { 3100 IStream *stream; 3101 HGLOBAL hmem; 3102 BYTE *data; 3103 HRESULT hr; 3104 GpStatus status; 3105 GpImage *image = NULL, *clone; 3106 ImageType image_type; 3107 LONG refcount, old_refcount; 3108 3109 hmem = GlobalAlloc(0, image_size); 3110 data = GlobalLock(hmem); 3111 memcpy(data, image_data, image_size); 3112 GlobalUnlock(hmem); 3113 3114 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream); 3115 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr); 3116 if (hr != S_OK) return NULL; 3117 3118 refcount = obj_refcount(stream); 3119 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount); 3120 3121 status = GdipLoadImageFromStream(stream, &image); 3122 if (status != Ok) 3123 { 3124 IStream_Release(stream); 3125 return NULL; 3126 } 3127 3128 status = GdipGetImageType(image, &image_type); 3129 ok(status == Ok, "GdipGetImageType error %d\n", status); 3130 3131 refcount = obj_refcount(stream); 3132 if (image_type == ImageTypeBitmap) 3133 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount); 3134 else 3135 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount); 3136 old_refcount = refcount; 3137 3138 status = GdipCloneImage(image, &clone); 3139 ok(status == Ok, "GdipCloneImage error %d\n", status); 3140 refcount = obj_refcount(stream); 3141 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount); 3142 status = GdipDisposeImage(clone); 3143 ok(status == Ok, "GdipDisposeImage error %d\n", status); 3144 refcount = obj_refcount(stream); 3145 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount); 3146 3147 refcount = IStream_Release(stream); 3148 if (image_type == ImageTypeBitmap) 3149 ok(refcount >= 1, "expected stream refcount != 0\n"); 3150 else 3151 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount); 3152 3153 return image; 3154 } 3155 3156 static void test_image_properties(void) 3157 { 3158 static const struct test_data 3159 { 3160 const BYTE *image_data; 3161 UINT image_size; 3162 ImageType image_type; 3163 UINT prop_count; 3164 UINT prop_count2; /* if win7 behaves differently */ 3165 /* 1st property attributes */ 3166 UINT prop_size; 3167 UINT prop_size2; /* if win7 behaves differently */ 3168 UINT prop_id; 3169 UINT prop_id2; /* if win7 behaves differently */ 3170 } 3171 td[] = 3172 { 3173 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 }, 3174 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 }, 3175 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 }, 3176 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 }, 3177 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 } 3178 }; 3179 GpStatus status; 3180 GpImage *image; 3181 UINT prop_count, prop_size, i; 3182 PROPID prop_id[16] = { 0 }; 3183 ImageType image_type; 3184 union 3185 { 3186 PropertyItem data; 3187 char buf[256]; 3188 } item; 3189 3190 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 3191 { 3192 image = load_image(td[i].image_data, td[i].image_size); 3193 if (!image) 3194 { 3195 trace("%u: failed to load image data\n", i); 3196 continue; 3197 } 3198 3199 status = GdipGetImageType(image, &image_type); 3200 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status); 3201 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n", 3202 i, td[i].image_type, image_type); 3203 3204 status = GdipGetPropertyCount(image, &prop_count); 3205 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status); 3206 todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage) 3207 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count, 3208 " %u: expected property count %u or %u, got %u\n", 3209 i, td[i].prop_count, td[i].prop_count2, prop_count); 3210 3211 status = GdipGetPropertyItemSize(NULL, 0, &prop_size); 3212 expect(InvalidParameter, status); 3213 status = GdipGetPropertyItemSize(image, 0, NULL); 3214 expect(InvalidParameter, status); 3215 status = GdipGetPropertyItemSize(image, 0, &prop_size); 3216 if (image_type == ImageTypeMetafile) 3217 expect(NotImplemented, status); 3218 else 3219 expect(PropertyNotFound, status); 3220 3221 status = GdipGetPropertyItem(NULL, 0, 0, &item.data); 3222 expect(InvalidParameter, status); 3223 status = GdipGetPropertyItem(image, 0, 0, NULL); 3224 expect(InvalidParameter, status); 3225 status = GdipGetPropertyItem(image, 0, 0, &item.data); 3226 if (image_type == ImageTypeMetafile) 3227 expect(NotImplemented, status); 3228 else 3229 expect(PropertyNotFound, status); 3230 3231 /* FIXME: remove once Wine is fixed */ 3232 if (td[i].prop_count != prop_count) 3233 { 3234 GdipDisposeImage(image); 3235 continue; 3236 } 3237 3238 status = GdipGetPropertyIdList(NULL, prop_count, prop_id); 3239 expect(InvalidParameter, status); 3240 status = GdipGetPropertyIdList(image, prop_count, NULL); 3241 expect(InvalidParameter, status); 3242 status = GdipGetPropertyIdList(image, 0, prop_id); 3243 if (image_type == ImageTypeMetafile) 3244 expect(NotImplemented, status); 3245 else if (prop_count == 0) 3246 expect(Ok, status); 3247 else 3248 expect(InvalidParameter, status); 3249 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id); 3250 if (image_type == ImageTypeMetafile) 3251 expect(NotImplemented, status); 3252 else 3253 expect(InvalidParameter, status); 3254 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id); 3255 if (image_type == ImageTypeMetafile) 3256 expect(NotImplemented, status); 3257 else 3258 expect(InvalidParameter, status); 3259 status = GdipGetPropertyIdList(image, prop_count, prop_id); 3260 if (image_type == ImageTypeMetafile) 3261 expect(NotImplemented, status); 3262 else 3263 { 3264 expect(Ok, status); 3265 if (prop_count != 0) 3266 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0], 3267 " %u: expected property id %#x or %#x, got %#x\n", 3268 i, td[i].prop_id, td[i].prop_id2, prop_id[0]); 3269 } 3270 3271 if (status == Ok) 3272 { 3273 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size); 3274 if (prop_count == 0) 3275 expect(PropertyNotFound, status); 3276 else 3277 { 3278 expect(Ok, status); 3279 3280 assert(sizeof(item) >= prop_size); 3281 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n", 3282 i, prop_size); 3283 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size || 3284 td[i].prop_size2 + sizeof(PropertyItem) == prop_size, 3285 " %u: expected property size %u or %u, got %u\n", 3286 i, td[i].prop_size, td[i].prop_size2, prop_size); 3287 3288 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data); 3289 ok(status == InvalidParameter || status == GenericError /* Win7 */, 3290 "%u: expected InvalidParameter, got %d\n", i, status); 3291 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data); 3292 ok(status == InvalidParameter || status == GenericError /* Win7 */, 3293 "%u: expected InvalidParameter, got %d\n", i, status); 3294 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data); 3295 ok(status == InvalidParameter || status == GenericError /* Win7 */, 3296 "%u: expected InvalidParameter, got %d\n", i, status); 3297 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data); 3298 expect(Ok, status); 3299 ok(prop_id[0] == item.data.id, 3300 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id); 3301 } 3302 } 3303 3304 GdipDisposeImage(image); 3305 } 3306 } 3307 3308 #define IFD_BYTE 1 3309 #define IFD_ASCII 2 3310 #define IFD_SHORT 3 3311 #define IFD_LONG 4 3312 #define IFD_RATIONAL 5 3313 #define IFD_SBYTE 6 3314 #define IFD_UNDEFINED 7 3315 #define IFD_SSHORT 8 3316 #define IFD_SLONG 9 3317 #define IFD_SRATIONAL 10 3318 #define IFD_FLOAT 11 3319 #define IFD_DOUBLE 12 3320 3321 #ifndef PropertyTagTypeSByte 3322 #define PropertyTagTypeSByte 6 3323 #define PropertyTagTypeSShort 8 3324 #define PropertyTagTypeFloat 11 3325 #define PropertyTagTypeDouble 12 3326 #endif 3327 3328 static UINT documented_type(UINT type) 3329 { 3330 switch (type) 3331 { 3332 case PropertyTagTypeSByte: return PropertyTagTypeByte; 3333 case PropertyTagTypeSShort: return PropertyTagTypeShort; 3334 case PropertyTagTypeFloat: return PropertyTagTypeUndefined; 3335 case PropertyTagTypeDouble: return PropertyTagTypeUndefined; 3336 default: return type; 3337 } 3338 } 3339 3340 #include "pshpack2.h" 3341 struct IFD_entry 3342 { 3343 SHORT id; 3344 SHORT type; 3345 ULONG count; 3346 LONG value; 3347 }; 3348 3349 struct IFD_rational 3350 { 3351 LONG numerator; 3352 LONG denominator; 3353 }; 3354 3355 static const struct tiff_data 3356 { 3357 USHORT byte_order; 3358 USHORT version; 3359 ULONG dir_offset; 3360 USHORT number_of_entries; 3361 struct IFD_entry entry[40]; 3362 ULONG next_IFD; 3363 struct IFD_rational xres; 3364 DOUBLE double_val; 3365 struct IFD_rational srational_val; 3366 char string[14]; 3367 SHORT short_val[4]; 3368 LONG long_val[2]; 3369 FLOAT float_val[2]; 3370 struct IFD_rational rational[3]; 3371 BYTE pixel_data[4]; 3372 } TIFF_data = 3373 { 3374 #ifdef WORDS_BIGENDIAN 3375 'M' | 'M' << 8, 3376 #else 3377 'I' | 'I' << 8, 3378 #endif 3379 42, 3380 FIELD_OFFSET(struct tiff_data, number_of_entries), 3381 31, 3382 { 3383 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */ 3384 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */ 3385 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */ 3386 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */ 3387 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */ 3388 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */ 3389 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */ 3390 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */ 3391 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */ 3392 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */ 3393 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) }, 3394 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) }, 3395 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */ 3396 { 0xf001, IFD_BYTE, 1, 0x11223344 }, 3397 { 0xf002, IFD_BYTE, 4, 0x11223344 }, 3398 { 0xf003, IFD_SBYTE, 1, 0x11223344 }, 3399 { 0xf004, IFD_SSHORT, 1, 0x11223344 }, 3400 { 0xf005, IFD_SSHORT, 2, 0x11223344 }, 3401 { 0xf006, IFD_SLONG, 1, 0x11223344 }, 3402 { 0xf007, IFD_FLOAT, 1, 0x11223344 }, 3403 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) }, 3404 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) }, 3405 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) }, 3406 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) }, 3407 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) }, 3408 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) }, 3409 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 }, 3410 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) }, 3411 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 }, 3412 /* Some gdiplus versions ignore these fields. 3413 { 0xf012, IFD_BYTE, 0, 0x11223344 }, 3414 { 0xf013, IFD_SHORT, 0, 0x11223344 }, 3415 { 0xf014, IFD_LONG, 0, 0x11223344 }, 3416 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/ 3417 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) }, 3418 /* Win7 before SP1 doesn't recognize this field, everybody else does. */ 3419 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) }, 3420 }, 3421 0, 3422 { 900, 3 }, 3423 1234567890.0987654321, 3424 { 0x1a2b3c4d, 0x5a6b7c8d }, 3425 "Hello World!", 3426 { 0x0101, 0x0202, 0x0303, 0x0404 }, 3427 { 0x11223344, 0x55667788 }, 3428 { (FLOAT)1234.5678, (FLOAT)8765.4321 }, 3429 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } }, 3430 { 0x11, 0x22, 0x33, 0 } 3431 }; 3432 #include "poppack.h" 3433 3434 static void test_tiff_properties(void) 3435 { 3436 static const struct test_data 3437 { 3438 ULONG type, id, length; 3439 const BYTE value[24]; 3440 } td[31] = 3441 { 3442 { PropertyTagTypeShort, 0xff, 2, { 0 } }, 3443 { PropertyTagTypeLong, 0x100, 4, { 1 } }, 3444 { PropertyTagTypeLong, 0x101, 4, { 1 } }, 3445 { PropertyTagTypeShort, 0x102, 2, { 1 } }, 3446 { PropertyTagTypeShort, 0x103, 2, { 1 } }, 3447 { PropertyTagTypeShort, 0x106, 2, { 1 } }, 3448 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } }, 3449 { PropertyTagTypeShort, 0x115, 2, { 1 } }, 3450 { PropertyTagTypeLong, 0x116, 4, { 1 } }, 3451 { PropertyTagTypeLong, 0x117, 4, { 1 } }, 3452 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } }, 3453 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } }, 3454 { PropertyTagTypeShort, 0x128, 2, { 2 } }, 3455 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } }, 3456 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } }, 3457 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } }, 3458 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } }, 3459 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } }, 3460 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } }, 3461 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } }, 3462 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } }, 3463 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } }, 3464 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } }, 3465 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } }, 3466 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } }, 3467 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } }, 3468 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } }, 3469 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } }, 3470 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } }, 3471 { PropertyTagTypeSRational, 0xf016, 24, 3472 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05, 3473 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50, 3474 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } }, 3475 /* Win7 before SP1 doesn't recognize this field, everybody else does. */ 3476 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } }, 3477 }; 3478 GpStatus status; 3479 GpImage *image; 3480 GUID guid; 3481 UINT dim_count, frame_count, prop_count, prop_size, i; 3482 PROPID *prop_id; 3483 PropertyItem *prop_item; 3484 3485 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data)); 3486 if (!image) 3487 { 3488 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n"); 3489 return; 3490 } 3491 3492 status = GdipImageGetFrameDimensionsCount(image, &dim_count); 3493 expect(Ok, status); 3494 expect(1, dim_count); 3495 3496 status = GdipImageGetFrameDimensionsList(image, &guid, 1); 3497 expect(Ok, status); 3498 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE); 3499 3500 frame_count = 0xdeadbeef; 3501 status = GdipImageGetFrameCount(image, &guid, &frame_count); 3502 expect(Ok, status); 3503 expect(1, frame_count); 3504 3505 prop_count = 0xdeadbeef; 3506 status = GdipGetPropertyCount(image, &prop_count); 3507 expect(Ok, status); 3508 ok(prop_count == sizeof(td)/sizeof(td[0]) || 3509 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */, 3510 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count); 3511 3512 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id)); 3513 3514 status = GdipGetPropertyIdList(image, prop_count, prop_id); 3515 expect(Ok, status); 3516 3517 for (i = 0; i < prop_count; i++) 3518 { 3519 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size); 3520 expect(Ok, status); 3521 if (status != Ok) break; 3522 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size); 3523 3524 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size); 3525 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item); 3526 expect(Ok, status); 3527 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value); 3528 ok(td[i].type == prop_item->type || 3529 /* Win7 stopped using proper but not documented types, and it 3530 looks broken since TypeFloat and TypeDouble now reported as 3531 TypeUndefined, and signed types reported as unsigned. */ 3532 broken(prop_item->type == documented_type(td[i].type)), 3533 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type); 3534 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id); 3535 prop_size -= sizeof(*prop_item); 3536 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length); 3537 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */, 3538 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length); 3539 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */, 3540 "%u: expected length %u, got %u\n", i, td[i].length, prop_size); 3541 if (td[i].length == prop_item->length) 3542 { 3543 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0; 3544 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i); 3545 if (!match) 3546 { 3547 UINT j; 3548 BYTE *data = prop_item->value; 3549 trace("id %#x:", prop_item->id); 3550 for (j = 0; j < prop_item->length; j++) 3551 trace(" %02x", data[j]); 3552 trace("\n"); 3553 } 3554 } 3555 HeapFree(GetProcessHeap(), 0, prop_item); 3556 } 3557 3558 HeapFree(GetProcessHeap(), 0, prop_id); 3559 3560 GdipDisposeImage(image); 3561 } 3562 3563 static void test_GdipGetAllPropertyItems(void) 3564 { 3565 static const struct test_data 3566 { 3567 ULONG type, id, length; 3568 BYTE value[32]; 3569 } td[16] = 3570 { 3571 { PropertyTagTypeLong, 0xfe, 4, { 0 } }, 3572 { PropertyTagTypeShort, 0x100, 2, { 1 } }, 3573 { PropertyTagTypeShort, 0x101, 2, { 1 } }, 3574 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } }, 3575 { PropertyTagTypeShort, 0x103, 2, { 1 } }, 3576 { PropertyTagTypeShort, 0x106, 2, { 2,0 } }, 3577 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" }, 3578 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } }, 3579 { PropertyTagTypeShort, 0x112, 2, { 1 } }, 3580 { PropertyTagTypeShort, 0x115, 2, { 3,0 } }, 3581 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } }, 3582 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } }, 3583 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } }, 3584 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } }, 3585 { PropertyTagTypeShort, 0x11c, 2, { 1 } }, 3586 { PropertyTagTypeShort, 0x128, 2, { 2 } } 3587 }; 3588 GpStatus status; 3589 GpImage *image; 3590 GUID guid; 3591 UINT dim_count, frame_count, prop_count, prop_size, i; 3592 UINT total_size, total_count; 3593 PROPID *prop_id; 3594 PropertyItem *prop_item; 3595 const char *item_data; 3596 3597 image = load_image(tiffimage, sizeof(tiffimage)); 3598 ok(image != 0, "Failed to load TIFF image data\n"); 3599 if (!image) return; 3600 3601 dim_count = 0xdeadbeef; 3602 status = GdipImageGetFrameDimensionsCount(image, &dim_count); 3603 expect(Ok, status); 3604 expect(1, dim_count); 3605 3606 status = GdipImageGetFrameDimensionsList(image, &guid, 1); 3607 expect(Ok, status); 3608 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE); 3609 3610 frame_count = 0xdeadbeef; 3611 status = GdipImageGetFrameCount(image, &guid, &frame_count); 3612 expect(Ok, status); 3613 expect(1, frame_count); 3614 3615 prop_count = 0xdeadbeef; 3616 status = GdipGetPropertyCount(image, &prop_count); 3617 expect(Ok, status); 3618 ok(prop_count == sizeof(td)/sizeof(td[0]), 3619 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count); 3620 3621 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id)); 3622 3623 status = GdipGetPropertyIdList(image, prop_count, prop_id); 3624 expect(Ok, status); 3625 3626 prop_size = 0; 3627 for (i = 0; i < prop_count; i++) 3628 { 3629 UINT size; 3630 status = GdipGetPropertyItemSize(image, prop_id[i], &size); 3631 expect(Ok, status); 3632 if (status != Ok) break; 3633 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size); 3634 3635 prop_size += size; 3636 3637 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 3638 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item); 3639 expect(Ok, status); 3640 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value); 3641 ok(td[i].type == prop_item->type, 3642 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type); 3643 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id); 3644 size -= sizeof(*prop_item); 3645 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length); 3646 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length); 3647 if (td[i].length == prop_item->length) 3648 { 3649 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0; 3650 ok(match, "%u: data mismatch\n", i); 3651 if (!match) 3652 { 3653 UINT j; 3654 BYTE *data = prop_item->value; 3655 trace("id %#x:", prop_item->id); 3656 for (j = 0; j < prop_item->length; j++) 3657 trace(" %02x", data[j]); 3658 trace("\n"); 3659 } 3660 } 3661 HeapFree(GetProcessHeap(), 0, prop_item); 3662 } 3663 3664 HeapFree(GetProcessHeap(), 0, prop_id); 3665 3666 status = GdipGetPropertySize(NULL, &total_size, &total_count); 3667 expect(InvalidParameter, status); 3668 status = GdipGetPropertySize(image, &total_size, NULL); 3669 expect(InvalidParameter, status); 3670 status = GdipGetPropertySize(image, NULL, &total_count); 3671 expect(InvalidParameter, status); 3672 status = GdipGetPropertySize(image, NULL, NULL); 3673 expect(InvalidParameter, status); 3674 total_size = 0xdeadbeef; 3675 total_count = 0xdeadbeef; 3676 status = GdipGetPropertySize(image, &total_size, &total_count); 3677 expect(Ok, status); 3678 ok(prop_count == total_count, 3679 "expected total property count %u, got %u\n", prop_count, total_count); 3680 ok(prop_size == total_size, 3681 "expected total property size %u, got %u\n", prop_size, total_size); 3682 3683 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size); 3684 3685 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item); 3686 expect(InvalidParameter, status); 3687 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item); 3688 expect(InvalidParameter, status); 3689 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL); 3690 expect(InvalidParameter, status); 3691 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL); 3692 expect(InvalidParameter, status); 3693 status = GdipGetAllPropertyItems(image, 0, 0, NULL); 3694 expect(InvalidParameter, status); 3695 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item); 3696 expect(InvalidParameter, status); 3697 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item); 3698 expect(Ok, status); 3699 3700 item_data = (const char *)(prop_item + prop_count); 3701 for (i = 0; i < prop_count; i++) 3702 { 3703 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n", 3704 i, item_data, prop_item[i].value); 3705 ok(td[i].type == prop_item[i].type, 3706 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type); 3707 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id); 3708 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length); 3709 if (td[i].length == prop_item[i].length) 3710 { 3711 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0; 3712 ok(match, "%u: data mismatch\n", i); 3713 if (!match) 3714 { 3715 UINT j; 3716 BYTE *data = prop_item[i].value; 3717 trace("id %#x:", prop_item[i].id); 3718 for (j = 0; j < prop_item[i].length; j++) 3719 trace(" %02x", data[j]); 3720 trace("\n"); 3721 } 3722 } 3723 item_data += prop_item[i].length; 3724 } 3725 3726 HeapFree(GetProcessHeap(), 0, prop_item); 3727 3728 GdipDisposeImage(image); 3729 } 3730 3731 static void test_tiff_palette(void) 3732 { 3733 GpStatus status; 3734 GpImage *image; 3735 PixelFormat format; 3736 INT size; 3737 struct 3738 { 3739 ColorPalette pal; 3740 ARGB entry[256]; 3741 } palette; 3742 ARGB *entries = palette.pal.Entries; 3743 3744 /* 1bpp TIFF without palette */ 3745 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data)); 3746 if (!image) 3747 { 3748 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n"); 3749 return; 3750 } 3751 3752 status = GdipGetImagePixelFormat(image, &format); 3753 expect(Ok, status); 3754 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format); 3755 3756 status = GdipGetImagePaletteSize(image, &size); 3757 ok(status == Ok || broken(status == GenericError), /* XP */ 3758 "GdipGetImagePaletteSize error %d\n", status); 3759 if (status == GenericError) 3760 { 3761 GdipDisposeImage(image); 3762 return; 3763 } 3764 expect(sizeof(ColorPalette) + sizeof(ARGB), size); 3765 3766 status = GdipGetImagePalette(image, &palette.pal, size); 3767 expect(Ok, status); 3768 expect(0, palette.pal.Flags); 3769 expect(2, palette.pal.Count); 3770 if (palette.pal.Count == 2) 3771 { 3772 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]); 3773 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]); 3774 } 3775 3776 GdipDisposeImage(image); 3777 } 3778 3779 static void test_bitmapbits(void) 3780 { 3781 /* 8 x 2 bitmap */ 3782 static const BYTE pixels_24[48] = 3783 { 3784 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3785 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3786 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3787 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0 3788 }; 3789 static const BYTE pixels_00[48] = 3790 { 3791 0,0,0, 0,0,0, 0,0,0, 0,0,0, 3792 0,0,0, 0,0,0, 0,0,0, 0,0,0, 3793 0,0,0, 0,0,0, 0,0,0, 0,0,0, 3794 0,0,0, 0,0,0, 0,0,0, 0,0,0 3795 }; 3796 static const BYTE pixels_24_77[64] = 3797 { 3798 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3799 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3800 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3801 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3802 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0, 3803 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77 3804 }; 3805 static const BYTE pixels_77[64] = 3806 { 3807 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3808 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3809 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3810 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3811 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3812 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3813 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3814 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77 3815 }; 3816 static const BYTE pixels_8[16] = 3817 { 3818 0x01,0,0x01,0,0x01,0,0x01,0, 3819 0x01,0,0x01,0,0x01,0,0x01,0 3820 }; 3821 static const BYTE pixels_8_77[64] = 3822 { 3823 0x01,0,0x01,0,0x01,0,0x01,0, 3824 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3825 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3826 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3827 0x01,0,0x01,0,0x01,0,0x01,0, 3828 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3829 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3830 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77 3831 }; 3832 static const BYTE pixels_1_77[64] = 3833 { 3834 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3835 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3836 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3837 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3838 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3839 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3840 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77, 3841 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77 3842 }; 3843 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0}; 3844 static const struct test_data 3845 { 3846 PixelFormat format; 3847 UINT bpp; 3848 ImageLockMode mode; 3849 UINT stride, size; 3850 const BYTE *pixels; 3851 const BYTE *pixels_unlocked; 3852 } td[] = 3853 { 3854 /* 0 */ 3855 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 }, 3856 3857 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 }, 3858 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 }, 3859 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 }, 3860 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 }, 3861 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 }, 3862 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 }, 3863 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 }, 3864 /* 8 */ 3865 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 }, 3866 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 }, 3867 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 }, 3868 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 }, 3869 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 }, 3870 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 }, 3871 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 }, 3872 /* 15 */ 3873 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 }, 3874 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 }, 3875 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 }, 3876 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 }, 3877 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 }, 3878 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 }, 3879 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 }, 3880 }; 3881 BYTE buf[64]; 3882 GpStatus status; 3883 GpBitmap *bitmap; 3884 UINT i; 3885 BitmapData data; 3886 struct 3887 { 3888 ColorPalette pal; 3889 ARGB entries[1]; 3890 } palette; 3891 ARGB *entries = palette.pal.Entries; 3892 3893 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 3894 { 3895 BYTE pixels[sizeof(pixels_24)]; 3896 memcpy(pixels, pixels_24, sizeof(pixels_24)); 3897 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap); 3898 expect(Ok, status); 3899 3900 /* associate known palette with pixel data */ 3901 palette.pal.Flags = PaletteFlagsGrayScale; 3902 palette.pal.Count = 2; 3903 entries[0] = 0xff000000; 3904 entries[1] = 0xffffffff; 3905 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal); 3906 expect(Ok, status); 3907 3908 memset(&data, 0xfe, sizeof(data)); 3909 if (td[i].mode & ImageLockModeUserInputBuf) 3910 { 3911 memset(buf, 0x77, sizeof(buf)); 3912 data.Scan0 = buf; 3913 data.Stride = 32; 3914 } 3915 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data); 3916 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status); 3917 if (status != Ok) 3918 { 3919 GdipDisposeImage((GpImage *)bitmap); 3920 continue; 3921 } 3922 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width); 3923 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height); 3924 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride); 3925 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat); 3926 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride); 3927 if (td[i].mode & ImageLockModeUserInputBuf) 3928 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i); 3929 if (td[i].size == data.Height * data.Stride) 3930 { 3931 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8; 3932 3933 match = 1; 3934 for (j = 0; j < data.Height; j++) 3935 { 3936 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0) 3937 { 3938 match = 0; 3939 break; 3940 } 3941 } 3942 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB) 3943 { 3944 ok(match, 3945 "%u: data should match\n", i); 3946 if (!match) 3947 { 3948 BYTE *bits = data.Scan0; 3949 trace("%u: data mismatch for format %#x:", i, td[i].format); 3950 for (j = 0; j < td[i].size; j++) 3951 trace(" %02x", bits[j]); 3952 trace("\n"); 3953 } 3954 } 3955 else 3956 ok(!match, "%u: data shouldn't match\n", i); 3957 3958 memset(data.Scan0, 0, td[i].size); 3959 } 3960 3961 status = GdipBitmapUnlockBits(bitmap, &data); 3962 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status); 3963 3964 memset(&data, 0xfe, sizeof(data)); 3965 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data); 3966 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status); 3967 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width); 3968 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height); 3969 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride); 3970 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat); 3971 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride); 3972 if (data.Height * data.Stride == 48) 3973 { 3974 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0; 3975 ok(match, "%u: data should match\n", i); 3976 if (!match) 3977 { 3978 UINT j; 3979 BYTE *bits = data.Scan0; 3980 trace("%u: data mismatch for format %#x:", i, td[i].format); 3981 for (j = 0; j < 48; j++) 3982 trace(" %02x", bits[j]); 3983 trace("\n"); 3984 } 3985 } 3986 3987 status = GdipBitmapUnlockBits(bitmap, &data); 3988 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status); 3989 3990 status = GdipDisposeImage((GpImage *)bitmap); 3991 expect(Ok, status); 3992 } 3993 } 3994 3995 static void test_DrawImage(void) 3996 { 3997 BYTE black_1x1[4] = { 0,0,0,0 }; 3998 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 3999 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; 4000 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff, 4001 0,0,0,0,0,0,0xff,0xff }; 4002 GpStatus status; 4003 union 4004 { 4005 GpBitmap *bitmap; 4006 GpImage *image; 4007 } u1, u2; 4008 GpGraphics *graphics; 4009 int match; 4010 4011 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap); 4012 expect(Ok, status); 4013 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0); 4014 expect(Ok, status); 4015 4016 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap); 4017 expect(Ok, status); 4018 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0); 4019 expect(Ok, status); 4020 status = GdipGetImageGraphicsContext(u2.image, &graphics); 4021 expect(Ok, status); 4022 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor); 4023 expect(Ok, status); 4024 4025 status = GdipDrawImageI(graphics, u1.image, 0, 0); 4026 expect(Ok, status); 4027 4028 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0; 4029 ok(match, "data should match\n"); 4030 if (!match) 4031 { 4032 UINT i, size = sizeof(white_2x2); 4033 BYTE *bits = white_2x2; 4034 for (i = 0; i < size; i++) 4035 trace(" %02x", bits[i]); 4036 trace("\n"); 4037 } 4038 4039 status = GdipDeleteGraphics(graphics); 4040 expect(Ok, status); 4041 status = GdipDisposeImage(u1.image); 4042 expect(Ok, status); 4043 status = GdipDisposeImage(u2.image); 4044 expect(Ok, status); 4045 } 4046 4047 static void test_DrawImage_SourceCopy(void) 4048 { 4049 DWORD dst_pixels[4] = { 0xffffffff, 0xffffffff, 4050 0xffffffff, 0xffffffff }; 4051 DWORD src_pixels[4] = { 0, 0xffff0000, 4052 0, 0xff00ff }; 4053 4054 GpStatus status; 4055 union 4056 { 4057 GpBitmap *bitmap; 4058 GpImage *image; 4059 } u1, u2; 4060 GpGraphics *graphics; 4061 4062 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)dst_pixels, &u1.bitmap); 4063 expect(Ok, status); 4064 4065 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)src_pixels, &u2.bitmap); 4066 expect(Ok, status); 4067 status = GdipGetImageGraphicsContext(u1.image, &graphics); 4068 expect(Ok, status); 4069 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor); 4070 expect(Ok, status); 4071 4072 status = GdipSetCompositingMode(graphics, CompositingModeSourceCopy); 4073 expect(Ok, status); 4074 4075 status = GdipDrawImageI(graphics, u2.image, 0, 0); 4076 expect(Ok, status); 4077 4078 todo_wine expect(0, dst_pixels[0]); 4079 expect(0xffff0000, dst_pixels[1]); 4080 todo_wine expect(0, dst_pixels[2]); 4081 todo_wine expect(0, dst_pixels[3]); 4082 4083 status = GdipDeleteGraphics(graphics); 4084 expect(Ok, status); 4085 status = GdipDisposeImage(u1.image); 4086 expect(Ok, status); 4087 status = GdipDisposeImage(u2.image); 4088 expect(Ok, status); 4089 } 4090 4091 static void test_GdipDrawImagePointRect(void) 4092 { 4093 BYTE black_1x1[4] = { 0,0,0,0 }; 4094 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, 4095 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; 4096 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff, 4097 0,0,0,0,0,0,0xff,0xff }; 4098 GpStatus status; 4099 union 4100 { 4101 GpBitmap *bitmap; 4102 GpImage *image; 4103 } u1, u2; 4104 GpGraphics *graphics; 4105 int match; 4106 4107 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap); 4108 expect(Ok, status); 4109 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0); 4110 expect(Ok, status); 4111 4112 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap); 4113 expect(Ok, status); 4114 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0); 4115 expect(Ok, status); 4116 status = GdipGetImageGraphicsContext(u2.image, &graphics); 4117 expect(Ok, status); 4118 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor); 4119 expect(Ok, status); 4120 4121 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel); 4122 expect(Ok, status); 4123 4124 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0; 4125 ok(match, "data should match\n"); 4126 if (!match) 4127 { 4128 UINT i, size = sizeof(white_2x2); 4129 BYTE *bits = white_2x2; 4130 for (i = 0; i < size; i++) 4131 trace(" %02x", bits[i]); 4132 trace("\n"); 4133 } 4134 4135 status = GdipDeleteGraphics(graphics); 4136 expect(Ok, status); 4137 status = GdipDisposeImage(u1.image); 4138 expect(Ok, status); 4139 status = GdipDisposeImage(u2.image); 4140 expect(Ok, status); 4141 } 4142 4143 static void test_image_format(void) 4144 { 4145 static const PixelFormat fmt[] = 4146 { 4147 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed, 4148 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565, 4149 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB, 4150 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB, 4151 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK 4152 }; 4153 GpStatus status; 4154 GpBitmap *bitmap; 4155 GpImage *thumb; 4156 HBITMAP hbitmap; 4157 BITMAP bm; 4158 PixelFormat format; 4159 BitmapData data; 4160 UINT i, ret; 4161 4162 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++) 4163 { 4164 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap); 4165 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */, 4166 "GdipCreateBitmapFromScan0 error %d\n", status); 4167 if (status != Ok) continue; 4168 4169 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format); 4170 expect(Ok, status); 4171 expect(fmt[i], format); 4172 4173 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0); 4174 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK) 4175 todo_wine expect(InvalidParameter, status); 4176 else 4177 { 4178 expect(Ok, status); 4179 ret = GetObjectW(hbitmap, sizeof(bm), &bm); 4180 expect(sizeof(bm), ret); 4181 expect(0, bm.bmType); 4182 expect(1, bm.bmWidth); 4183 expect(1, bm.bmHeight); 4184 expect(4, bm.bmWidthBytes); 4185 expect(1, bm.bmPlanes); 4186 expect(32, bm.bmBitsPixel); 4187 DeleteObject(hbitmap); 4188 } 4189 4190 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL); 4191 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK) 4192 todo_wine 4193 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */, 4194 "expected OutOfMemory, got %d\n", status); 4195 else 4196 expect(Ok, status); 4197 if (status == Ok) 4198 { 4199 status = GdipGetImagePixelFormat(thumb, &format); 4200 expect(Ok, status); 4201 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */, 4202 "expected PixelFormat32bppPARGB, got %#x\n", format); 4203 status = GdipDisposeImage(thumb); 4204 expect(Ok, status); 4205 } 4206 4207 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data); 4208 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK) 4209 todo_wine expect(InvalidParameter, status); 4210 else 4211 { 4212 expect(Ok, status); 4213 status = GdipBitmapUnlockBits(bitmap, &data); 4214 expect(Ok, status); 4215 } 4216 4217 status = GdipDisposeImage((GpImage *)bitmap); 4218 expect(Ok, status); 4219 } 4220 } 4221 4222 static void test_DrawImage_scale(void) 4223 { 4224 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, 4225 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4226 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40, 4227 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4228 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40, 4229 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4230 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40, 4231 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4232 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80, 4233 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4234 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80, 4235 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4236 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80, 4237 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4238 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80, 4239 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 }; 4240 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 4241 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4242 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, 4243 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 }; 4244 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80, 4245 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 }; 4246 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80, 4247 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 }; 4248 static const struct test_data 4249 { 4250 REAL scale_x; 4251 PixelOffsetMode pixel_offset_mode; 4252 const BYTE *image; 4253 BOOL todo; 4254 } td[] = 4255 { 4256 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */ 4257 { 1.0, PixelOffsetModeNone, image_100 }, 4258 { 1.2, PixelOffsetModeNone, image_120 }, 4259 { 1.5, PixelOffsetModeNone, image_150 }, 4260 { 1.8, PixelOffsetModeNone, image_180 }, 4261 { 2.0, PixelOffsetModeNone, image_200 }, 4262 { 2.5, PixelOffsetModeNone, image_250 }, 4263 4264 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */ 4265 { 1.0, PixelOffsetModeHighSpeed, image_100 }, 4266 { 1.2, PixelOffsetModeHighSpeed, image_120 }, 4267 { 1.5, PixelOffsetModeHighSpeed, image_150 }, 4268 { 1.8, PixelOffsetModeHighSpeed, image_180 }, 4269 { 2.0, PixelOffsetModeHighSpeed, image_200 }, 4270 { 2.5, PixelOffsetModeHighSpeed, image_250 }, 4271 4272 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */ 4273 { 1.0, PixelOffsetModeHalf, image_100 }, 4274 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE }, 4275 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE }, 4276 { 1.8, PixelOffsetModeHalf, image_180 }, 4277 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE }, 4278 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE }, 4279 4280 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */ 4281 { 1.0, PixelOffsetModeHighQuality, image_100 }, 4282 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE }, 4283 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE }, 4284 { 1.8, PixelOffsetModeHighQuality, image_180 }, 4285 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE }, 4286 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE }, 4287 }; 4288 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 }; 4289 BYTE dst_8x1[24]; 4290 GpStatus status; 4291 union 4292 { 4293 GpBitmap *bitmap; 4294 GpImage *image; 4295 } u1, u2; 4296 GpGraphics *graphics; 4297 GpMatrix *matrix; 4298 int i, match; 4299 4300 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap); 4301 expect(Ok, status); 4302 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0); 4303 expect(Ok, status); 4304 4305 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap); 4306 expect(Ok, status); 4307 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0); 4308 expect(Ok, status); 4309 status = GdipGetImageGraphicsContext(u2.image, &graphics); 4310 expect(Ok, status); 4311 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor); 4312 expect(Ok, status); 4313 4314 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 4315 { 4316 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode); 4317 expect(Ok, status); 4318 4319 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix); 4320 expect(Ok, status); 4321 status = GdipSetWorldTransform(graphics, matrix); 4322 expect(Ok, status); 4323 GdipDeleteMatrix(matrix); 4324 4325 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1)); 4326 status = GdipDrawImageI(graphics, u1.image, 1, 0); 4327 expect(Ok, status); 4328 4329 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0; 4330 todo_wine_if (!match && td[i].todo) 4331 ok(match, "%d: data should match\n", i); 4332 if (!match) 4333 { 4334 UINT i, size = sizeof(dst_8x1); 4335 const BYTE *bits = dst_8x1; 4336 for (i = 0; i < size; i++) 4337 trace(" %02x", bits[i]); 4338 trace("\n"); 4339 } 4340 } 4341 4342 status = GdipDeleteGraphics(graphics); 4343 expect(Ok, status); 4344 status = GdipDisposeImage(u1.image); 4345 expect(Ok, status); 4346 status = GdipDisposeImage(u2.image); 4347 expect(Ok, status); 4348 } 4349 4350 static const BYTE animatedgif[] = { 4351 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00, 4352 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c, 4353 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/ 4354 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0', 4355 0x03,0x01,0x05,0x00,0x00, 4356 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00, 4357 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00, 4358 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00, 4359 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81, 4360 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac, 4361 0x02,0x02,0x4C,0x01,0x00, 4362 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00, 4363 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00, 4364 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00, 4365 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81, 4366 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc, 4367 0x02,0x02,0x44,0x01,0x00, 4368 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00, 4369 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B 4370 }; 4371 4372 static void test_gif_properties(void) 4373 { 4374 static const struct test_data 4375 { 4376 ULONG type, id, length; 4377 const BYTE value[13]; 4378 } td[] = 4379 { 4380 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } }, 4381 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } }, 4382 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } }, 4383 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } }, 4384 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } }, 4385 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } } 4386 }; 4387 GpStatus status; 4388 GpImage *image; 4389 GUID guid; 4390 UINT dim_count, frame_count, prop_count, prop_size, i; 4391 UINT total_size, total_count; 4392 PROPID *prop_id; 4393 PropertyItem *prop_item; 4394 const char *item_data; 4395 4396 image = load_image(animatedgif, sizeof(animatedgif)); 4397 if (!image) /* XP fails to load this GIF image */ 4398 { 4399 trace("Failed to load GIF image data\n"); 4400 return; 4401 } 4402 4403 status = GdipImageGetFrameDimensionsCount(image, &dim_count); 4404 expect(Ok, status); 4405 expect(1, dim_count); 4406 4407 status = GdipImageGetFrameDimensionsList(image, &guid, 1); 4408 expect(Ok, status); 4409 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE); 4410 4411 status = GdipImageGetFrameCount(image, &guid, &frame_count); 4412 expect(Ok, status); 4413 expect(2, frame_count); 4414 4415 status = GdipImageSelectActiveFrame(image, &guid, 1); 4416 expect(Ok, status); 4417 4418 status = GdipGetPropertyCount(image, &prop_count); 4419 expect(Ok, status); 4420 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */, 4421 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count); 4422 4423 if (prop_count != sizeof(td)/sizeof(td[0])) 4424 { 4425 GdipDisposeImage(image); 4426 return; 4427 } 4428 4429 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id)); 4430 4431 status = GdipGetPropertyIdList(image, prop_count, prop_id); 4432 expect(Ok, status); 4433 4434 prop_size = 0; 4435 for (i = 0; i < prop_count; i++) 4436 { 4437 UINT size; 4438 status = GdipGetPropertyItemSize(image, prop_id[i], &size); 4439 expect(Ok, status); 4440 if (status != Ok) break; 4441 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size); 4442 4443 prop_size += size; 4444 4445 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 4446 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item); 4447 expect(Ok, status); 4448 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value); 4449 ok(td[i].type == prop_item->type, 4450 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type); 4451 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id); 4452 size -= sizeof(*prop_item); 4453 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length); 4454 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length); 4455 if (td[i].length == prop_item->length) 4456 { 4457 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0; 4458 ok(match, "%u: data mismatch\n", i); 4459 if (!match) 4460 { 4461 UINT j; 4462 BYTE *data = prop_item->value; 4463 trace("id %#x:", prop_item->id); 4464 for (j = 0; j < prop_item->length; j++) 4465 trace(" %02x", data[j]); 4466 trace("\n"); 4467 } 4468 } 4469 HeapFree(GetProcessHeap(), 0, prop_item); 4470 } 4471 4472 HeapFree(GetProcessHeap(), 0, prop_id); 4473 4474 status = GdipGetPropertySize(NULL, &total_size, &total_count); 4475 expect(InvalidParameter, status); 4476 status = GdipGetPropertySize(image, &total_size, NULL); 4477 expect(InvalidParameter, status); 4478 status = GdipGetPropertySize(image, NULL, &total_count); 4479 expect(InvalidParameter, status); 4480 status = GdipGetPropertySize(image, NULL, NULL); 4481 expect(InvalidParameter, status); 4482 total_size = 0xdeadbeef; 4483 total_count = 0xdeadbeef; 4484 status = GdipGetPropertySize(image, &total_size, &total_count); 4485 expect(Ok, status); 4486 ok(prop_count == total_count, 4487 "expected total property count %u, got %u\n", prop_count, total_count); 4488 ok(prop_size == total_size, 4489 "expected total property size %u, got %u\n", prop_size, total_size); 4490 4491 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size); 4492 4493 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item); 4494 expect(InvalidParameter, status); 4495 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item); 4496 expect(InvalidParameter, status); 4497 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL); 4498 expect(InvalidParameter, status); 4499 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL); 4500 expect(InvalidParameter, status); 4501 status = GdipGetAllPropertyItems(image, 0, 0, NULL); 4502 expect(InvalidParameter, status); 4503 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item); 4504 expect(InvalidParameter, status); 4505 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item); 4506 expect(Ok, status); 4507 4508 item_data = (const char *)(prop_item + prop_count); 4509 for (i = 0; i < prop_count; i++) 4510 { 4511 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n", 4512 i, item_data, prop_item[i].value); 4513 ok(td[i].type == prop_item[i].type, 4514 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type); 4515 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id); 4516 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length); 4517 if (td[i].length == prop_item[i].length) 4518 { 4519 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0; 4520 ok(match, "%u: data mismatch\n", i); 4521 if (!match) 4522 { 4523 UINT j; 4524 BYTE *data = prop_item[i].value; 4525 trace("id %#x:", prop_item[i].id); 4526 for (j = 0; j < prop_item[i].length; j++) 4527 trace(" %02x", data[j]); 4528 trace("\n"); 4529 } 4530 } 4531 item_data += prop_item[i].length; 4532 } 4533 4534 HeapFree(GetProcessHeap(), 0, prop_item); 4535 4536 GdipDisposeImage(image); 4537 } 4538 4539 static void test_ARGB_conversion(void) 4540 { 4541 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 }; 4542 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 }; 4543 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff }; 4544 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff }; 4545 BYTE *bits; 4546 GpBitmap *bitmap; 4547 BitmapData data; 4548 GpStatus status; 4549 int match; 4550 4551 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap); 4552 expect(Ok, status); 4553 4554 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data); 4555 expect(Ok, status); 4556 ok(data.Width == 2, "expected 2, got %d\n", data.Width); 4557 ok(data.Height == 1, "expected 1, got %d\n", data.Height); 4558 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride); 4559 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat); 4560 match = !memcmp(data.Scan0, pargb, sizeof(pargb)); 4561 ok(match, "bits don't match\n"); 4562 if (!match) 4563 { 4564 bits = data.Scan0; 4565 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB, 4566 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]); 4567 } 4568 status = GdipBitmapUnlockBits(bitmap, &data); 4569 expect(Ok, status); 4570 4571 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data); 4572 expect(Ok, status); 4573 ok(data.Width == 2, "expected 2, got %d\n", data.Width); 4574 ok(data.Height == 1, "expected 1, got %d\n", data.Height); 4575 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride); 4576 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat); 4577 match = !memcmp(data.Scan0, argb, sizeof(argb)) || 4578 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp)); 4579 ok(match, "bits don't match\n"); 4580 if (!match) 4581 { 4582 bits = data.Scan0; 4583 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB, 4584 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]); 4585 } 4586 status = GdipBitmapUnlockBits(bitmap, &data); 4587 expect(Ok, status); 4588 4589 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data); 4590 expect(Ok, status); 4591 ok(data.Width == 2, "expected 2, got %d\n", data.Width); 4592 ok(data.Height == 1, "expected 1, got %d\n", data.Height); 4593 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride); 4594 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat); 4595 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24)); 4596 ok(match, "bits don't match\n"); 4597 if (!match) 4598 { 4599 bits = data.Scan0; 4600 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB, 4601 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]); 4602 } 4603 status = GdipBitmapUnlockBits(bitmap, &data); 4604 expect(Ok, status); 4605 4606 GdipDisposeImage((GpImage *)bitmap); 4607 } 4608 4609 4610 static void test_CloneBitmapArea(void) 4611 { 4612 GpStatus status; 4613 GpBitmap *bitmap, *copy; 4614 BitmapData data, data2; 4615 4616 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap); 4617 expect(Ok, status); 4618 4619 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data); 4620 expect(Ok, status); 4621 4622 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2); 4623 expect(WrongState, status); 4624 4625 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, ©); 4626 expect(Ok, status); 4627 4628 status = GdipBitmapUnlockBits(bitmap, &data); 4629 expect(Ok, status); 4630 4631 GdipDisposeImage((GpImage *)copy); 4632 GdipDisposeImage((GpImage *)bitmap); 4633 } 4634 4635 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid) 4636 { 4637 GpStatus status; 4638 UINT n_codecs, info_size, i; 4639 ImageCodecInfo *info; 4640 BOOL ret = FALSE; 4641 4642 status = GdipGetImageEncodersSize(&n_codecs, &info_size); 4643 expect(Ok, status); 4644 4645 info = GdipAlloc(info_size); 4646 4647 status = GdipGetImageEncoders(n_codecs, info_size, info); 4648 expect(Ok, status); 4649 4650 for (i = 0; i < n_codecs; i++) 4651 { 4652 if (!lstrcmpW(info[i].MimeType, mime)) 4653 { 4654 *format = info[i].FormatID; 4655 *clsid = info[i].Clsid; 4656 ret = TRUE; 4657 break; 4658 } 4659 } 4660 4661 GdipFree(info); 4662 return ret; 4663 } 4664 4665 static void test_supported_encoders(void) 4666 { 4667 static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 }; 4668 static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 }; 4669 static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 }; 4670 static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 }; 4671 static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 }; 4672 static const struct test_data 4673 { 4674 LPCWSTR mime; 4675 const GUID *format; 4676 } td[] = 4677 { 4678 { bmp_mimetype, &ImageFormatBMP }, 4679 { jpeg_mimetype, &ImageFormatJPEG }, 4680 { gif_mimetype, &ImageFormatGIF }, 4681 { tiff_mimetype, &ImageFormatTIFF }, 4682 { png_mimetype, &ImageFormatPNG } 4683 }; 4684 GUID format, clsid; 4685 BOOL ret; 4686 HRESULT hr; 4687 GpStatus status; 4688 GpBitmap *bm; 4689 IStream *stream; 4690 HGLOBAL hmem; 4691 int i; 4692 4693 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm); 4694 ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status); 4695 4696 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 4697 { 4698 ret = get_encoder_clsid(td[i].mime, &format, &clsid); 4699 ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime)); 4700 expect_guid(td[i].format, &format, __LINE__, FALSE); 4701 4702 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16); 4703 4704 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream); 4705 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr); 4706 4707 status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL); 4708 ok(status == Ok, "GdipSaveImageToStream error %d\n", status); 4709 4710 IStream_Release(stream); 4711 } 4712 4713 GdipDisposeImage((GpImage *)bm); 4714 } 4715 4716 static void test_createeffect(void) 4717 { 4718 static const GUID noneffect = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } }; 4719 GpStatus (WINAPI *pGdipCreateEffect)( const GUID guid, CGpEffect **effect); 4720 GpStatus (WINAPI *pGdipDeleteEffect)( CGpEffect *effect); 4721 GpStatus stat; 4722 CGpEffect *effect; 4723 HMODULE mod = GetModuleHandleA("gdiplus.dll"); 4724 int i; 4725 const GUID * const effectlist[] = 4726 {&BlurEffectGuid, &SharpenEffectGuid, &ColorMatrixEffectGuid, &ColorLUTEffectGuid, 4727 &BrightnessContrastEffectGuid, &HueSaturationLightnessEffectGuid, &LevelsEffectGuid, 4728 &TintEffectGuid, &ColorBalanceEffectGuid, &RedEyeCorrectionEffectGuid, &ColorCurveEffectGuid}; 4729 4730 pGdipCreateEffect = (void*)GetProcAddress( mod, "GdipCreateEffect"); 4731 pGdipDeleteEffect = (void*)GetProcAddress( mod, "GdipDeleteEffect"); 4732 if(!pGdipCreateEffect || !pGdipDeleteEffect) 4733 { 4734 /* GdipCreateEffect/GdipDeleteEffect was introduced in Windows Vista. */ 4735 win_skip("GDIPlus version 1.1 not available\n"); 4736 return; 4737 } 4738 4739 stat = pGdipCreateEffect(BlurEffectGuid, NULL); 4740 expect(InvalidParameter, stat); 4741 4742 stat = pGdipCreateEffect(noneffect, &effect); 4743 todo_wine expect(Win32Error, stat); 4744 4745 for(i=0; i < sizeof(effectlist) / sizeof(effectlist[0]); i++) 4746 { 4747 stat = pGdipCreateEffect(*effectlist[i], &effect); 4748 todo_wine expect(Ok, stat); 4749 if(stat == Ok) 4750 { 4751 stat = pGdipDeleteEffect(effect); 4752 expect(Ok, stat); 4753 } 4754 } 4755 } 4756 4757 static void test_getadjustedpalette(void) 4758 { 4759 ColorMap colormap; 4760 GpImageAttributes *imageattributes; 4761 ColorPalette *palette; 4762 GpStatus stat; 4763 4764 stat = GdipCreateImageAttributes(&imageattributes); 4765 expect(Ok, stat); 4766 4767 colormap.oldColor.Argb = 0xffffff00; 4768 colormap.newColor.Argb = 0xffff00ff; 4769 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeBitmap, 4770 TRUE, 1, &colormap); 4771 expect(Ok, stat); 4772 4773 colormap.oldColor.Argb = 0xffffff80; 4774 colormap.newColor.Argb = 0xffff80ff; 4775 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeDefault, 4776 TRUE, 1, &colormap); 4777 expect(Ok, stat); 4778 4779 palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 2); 4780 palette->Count = 0; 4781 4782 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap); 4783 expect(InvalidParameter, stat); 4784 4785 palette->Count = 3; 4786 palette->Entries[0] = 0xffffff00; 4787 palette->Entries[1] = 0xffffff80; 4788 palette->Entries[2] = 0xffffffff; 4789 4790 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap); 4791 expect(Ok, stat); 4792 expect(0xffff00ff, palette->Entries[0]); 4793 expect(0xffffff80, palette->Entries[1]); 4794 expect(0xffffffff, palette->Entries[2]); 4795 4796 palette->Entries[0] = 0xffffff00; 4797 palette->Entries[1] = 0xffffff80; 4798 palette->Entries[2] = 0xffffffff; 4799 4800 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBrush); 4801 expect(Ok, stat); 4802 expect(0xffffff00, palette->Entries[0]); 4803 expect(0xffff80ff, palette->Entries[1]); 4804 expect(0xffffffff, palette->Entries[2]); 4805 4806 stat = GdipGetImageAttributesAdjustedPalette(NULL, palette, ColorAdjustTypeBitmap); 4807 expect(InvalidParameter, stat); 4808 4809 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, NULL, ColorAdjustTypeBitmap); 4810 expect(InvalidParameter, stat); 4811 4812 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, -1); 4813 expect(InvalidParameter, stat); 4814 4815 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeDefault); 4816 expect(InvalidParameter, stat); 4817 4818 GdipFree(palette); 4819 GdipDisposeImageAttributes(imageattributes); 4820 } 4821 4822 static void test_histogram(void) 4823 { 4824 UINT ch0[256], ch1[256], ch2[256], ch3[256]; 4825 HistogramFormat test_formats[] = 4826 { 4827 HistogramFormatARGB, 4828 HistogramFormatPARGB, 4829 HistogramFormatRGB, 4830 HistogramFormatGray, 4831 HistogramFormatB, 4832 HistogramFormatG, 4833 HistogramFormatR, 4834 HistogramFormatA, 4835 }; 4836 const UINT WIDTH = 8, HEIGHT = 16; 4837 UINT num, i, x; 4838 GpStatus stat; 4839 GpBitmap *bm; 4840 4841 if (!pGdipBitmapGetHistogramSize) 4842 { 4843 win_skip("GdipBitmapGetHistogramSize is not supported\n"); 4844 return; 4845 } 4846 4847 stat = pGdipBitmapGetHistogramSize(HistogramFormatARGB, NULL); 4848 expect(InvalidParameter, stat); 4849 4850 stat = pGdipBitmapGetHistogramSize(0xff, NULL); 4851 expect(InvalidParameter, stat); 4852 4853 num = 123; 4854 stat = pGdipBitmapGetHistogramSize(10, &num); 4855 expect(Ok, stat); 4856 expect(256, num); 4857 4858 for (i = 0; i < sizeof(test_formats)/sizeof(test_formats[0]); i++) 4859 { 4860 num = 0; 4861 stat = pGdipBitmapGetHistogramSize(test_formats[i], &num); 4862 expect(Ok, stat); 4863 expect(256, num); 4864 } 4865 4866 bm = NULL; 4867 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm); 4868 expect(Ok, stat); 4869 4870 /* Three solid rgb rows, next three rows are rgb shades. */ 4871 for (x = 0; x < WIDTH; x++) 4872 { 4873 GdipBitmapSetPixel(bm, x, 0, 0xffff0000); 4874 GdipBitmapSetPixel(bm, x, 1, 0xff00ff00); 4875 GdipBitmapSetPixel(bm, x, 2, 0xff0000ff); 4876 4877 GdipBitmapSetPixel(bm, x, 3, 0xff010000); 4878 GdipBitmapSetPixel(bm, x, 4, 0xff003f00); 4879 GdipBitmapSetPixel(bm, x, 5, 0xff000020); 4880 } 4881 4882 stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3); 4883 expect(InvalidParameter, stat); 4884 4885 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3); 4886 expect(InvalidParameter, stat); 4887 4888 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL); 4889 expect(InvalidParameter, stat); 4890 4891 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL); 4892 expect(InvalidParameter, stat); 4893 4894 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL); 4895 expect(InvalidParameter, stat); 4896 4897 /* Requested format matches bitmap format */ 4898 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3); 4899 expect(InvalidParameter, stat); 4900 4901 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL); 4902 expect(InvalidParameter, stat); 4903 4904 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL); 4905 expect(InvalidParameter, stat); 4906 4907 /* Channel 3 is not used, must be NULL */ 4908 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL); 4909 expect(Ok, stat); 4910 4911 ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]); 4912 ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]); 4913 ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]); 4914 ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]); 4915 ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]); 4916 ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]); 4917 4918 /* ARGB histogram from RGB data. */ 4919 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL); 4920 expect(InvalidParameter, stat); 4921 4922 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3); 4923 expect(Ok, stat); 4924 4925 ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]); 4926 ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]); 4927 ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]); 4928 ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]); 4929 ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]); 4930 ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]); 4931 4932 ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]); 4933 4934 /* Request grayscale histogram from RGB bitmap. */ 4935 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3); 4936 expect(InvalidParameter, stat); 4937 4938 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL); 4939 expect(InvalidParameter, stat); 4940 4941 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL); 4942 expect(InvalidParameter, stat); 4943 4944 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL); 4945 expect(Ok, stat); 4946 4947 GdipDisposeImage((GpImage*)bm); 4948 } 4949 4950 static void test_imageabort(void) 4951 { 4952 GpStatus stat; 4953 GpBitmap *bm; 4954 4955 if (!pGdipImageSetAbort) 4956 { 4957 win_skip("GdipImageSetAbort() is not supported.\n"); 4958 return; 4959 } 4960 4961 bm = NULL; 4962 stat = GdipCreateBitmapFromScan0(8, 8, 0, PixelFormat24bppRGB, NULL, &bm); 4963 expect(Ok, stat); 4964 4965 stat = pGdipImageSetAbort(NULL, NULL); 4966 expect(InvalidParameter, stat); 4967 4968 stat = pGdipImageSetAbort((GpImage*)bm, NULL); 4969 expect(Ok, stat); 4970 4971 GdipDisposeImage((GpImage*)bm); 4972 } 4973 4974 /* RGB 24 bpp 1x1 pixel PNG image */ 4975 static const char png_1x1_data[] = { 4976 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a, 4977 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,0xde, 4978 0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7, 4979 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82 4980 }; 4981 4982 static void test_png_color_formats(void) 4983 { 4984 static const struct 4985 { 4986 char bit_depth, color_type; 4987 PixelFormat format; 4988 UINT flags; 4989 } td[] = 4990 { 4991 /* 2 - PNG_COLOR_TYPE_RGB */ 4992 { 8, 2, PixelFormat24bppRGB, ImageFlagsColorSpaceRGB }, 4993 /* 0 - PNG_COLOR_TYPE_GRAY */ 4994 { 1, 0, PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }, 4995 { 2, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, 4996 { 4, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, 4997 { 8, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, 4998 { 16, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }, 4999 }; 5000 BYTE buf[sizeof(png_1x1_data)]; 5001 GpStatus status; 5002 GpImage *image; 5003 ImageType type; 5004 PixelFormat format; 5005 UINT flags; 5006 int i; 5007 5008 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 5009 { 5010 memcpy(buf, png_1x1_data, sizeof(png_1x1_data)); 5011 buf[24] = td[i].bit_depth; 5012 buf[25] = td[i].color_type; 5013 5014 image = load_image(buf, sizeof(buf)); 5015 ok(image != NULL, "%d: failed to load image data\n", i); 5016 if (!image) continue; 5017 5018 status = GdipGetImageType(image, &type); 5019 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status); 5020 ok(type == ImageTypeBitmap, "%d: wrong image type %d\n", i, type); 5021 5022 status = GdipGetImagePixelFormat(image, &format); 5023 expect(Ok, status); 5024 ok(format == td[i].format || 5025 broken(td[i].bit_depth == 1 && td[i].color_type == 0 && format == PixelFormat32bppARGB), /* XP */ 5026 "%d: expected %#x, got %#x\n", i, td[i].format, format); 5027 5028 status = GdipGetImageFlags(image, &flags); 5029 expect(Ok, status); 5030 ok((flags & td[i].flags) == td[i].flags || 5031 broken(td[i].bit_depth == 1 && td[i].color_type == 0 && (flags & ImageFlagsColorSpaceGRAY)), /* XP */ 5032 "%d: expected %#x, got %#x\n", i, td[i].flags, flags); 5033 5034 GdipDisposeImage(image); 5035 } 5036 } 5037 5038 static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride) 5039 { 5040 BYTE *src; 5041 UINT i, j, scale; 5042 5043 *width = 256; 5044 *height = 256; 5045 *stride = (*width * 3 + 3) & ~3; 5046 trace("width %d, height %d, stride %d\n", *width, *height, *stride); 5047 5048 src = HeapAlloc(GetProcessHeap(), 0, *stride * *height); 5049 5050 scale = 256 / *width; 5051 if (!scale) scale = 1; 5052 5053 for (i = 0; i < *height; i++) 5054 { 5055 for (j = 0; j < *width; j++) 5056 { 5057 src[i * *stride + j*3 + 0] = scale * i; 5058 src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2); 5059 src[i * *stride + j*3 + 2] = scale * j; 5060 } 5061 } 5062 5063 return src; 5064 } 5065 5066 static void test_GdipInitializePalette(void) 5067 { 5068 GpStatus status; 5069 BYTE *data; 5070 GpBitmap *bitmap; 5071 ColorPalette *palette; 5072 UINT width, height, stride; 5073 5074 pGdipInitializePalette = (void *)GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipInitializePalette"); 5075 if (!pGdipInitializePalette) 5076 { 5077 win_skip("GdipInitializePalette is not supported on this platform\n"); 5078 return; 5079 } 5080 5081 data = init_bitmap(&width, &height, &stride); 5082 5083 status = GdipCreateBitmapFromScan0(width, height, stride, PixelFormat24bppRGB, data, &bitmap); 5084 expect(Ok, status); 5085 5086 palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 255); 5087 5088 palette->Flags = 0; 5089 palette->Count = 15; 5090 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap); 5091 expect(GenericError, status); 5092 5093 palette->Flags = 0; 5094 palette->Count = 256; 5095 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, NULL); 5096 expect(InvalidParameter, status); 5097 5098 memset(palette->Entries, 0x11, sizeof(ARGB) * 256); 5099 palette->Flags = 0; 5100 palette->Count = 256; 5101 status = pGdipInitializePalette(palette, PaletteTypeCustom, 16, FALSE, NULL); 5102 expect(Ok, status); 5103 expect(0, palette->Flags); 5104 expect(256, palette->Count); 5105 expect(0x11111111, palette->Entries[0]); 5106 expect(0x11111111, palette->Entries[128]); 5107 expect(0x11111111, palette->Entries[255]); 5108 5109 memset(palette->Entries, 0x11, sizeof(ARGB) * 256); 5110 palette->Flags = 0; 5111 palette->Count = 256; 5112 status = pGdipInitializePalette(palette, PaletteTypeFixedBW, 0, FALSE, bitmap); 5113 expect(Ok, status); 5114 todo_wine 5115 expect(0x200, palette->Flags); 5116 expect(2, palette->Count); 5117 expect(0xff000000, palette->Entries[0]); 5118 expect(0xffffffff, palette->Entries[1]); 5119 5120 memset(palette->Entries, 0x11, sizeof(ARGB) * 256); 5121 palette->Flags = 0; 5122 palette->Count = 256; 5123 status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, NULL); 5124 expect(Ok, status); 5125 todo_wine 5126 expect(0x300, palette->Flags); 5127 expect(16, palette->Count); 5128 expect(0xff000000, palette->Entries[0]); 5129 expect(0xffc0c0c0, palette->Entries[8]); 5130 expect(0xff008080, palette->Entries[15]); 5131 5132 memset(palette->Entries, 0x11, sizeof(ARGB) * 256); 5133 palette->Flags = 0; 5134 palette->Count = 256; 5135 status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, bitmap); 5136 expect(Ok, status); 5137 todo_wine 5138 expect(0x300, palette->Flags); 5139 expect(16, palette->Count); 5140 expect(0xff000000, palette->Entries[0]); 5141 expect(0xffc0c0c0, palette->Entries[8]); 5142 expect(0xff008080, palette->Entries[15]); 5143 5144 memset(palette->Entries, 0x11, sizeof(ARGB) * 256); 5145 palette->Flags = 0; 5146 palette->Count = 256; 5147 status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone252, 1, FALSE, bitmap); 5148 expect(Ok, status); 5149 todo_wine 5150 expect(0x800, palette->Flags); 5151 expect(252, palette->Count); 5152 expect(0xff000000, palette->Entries[0]); 5153 expect(0xff990066, palette->Entries[128]); 5154 expect(0xffffffff, palette->Entries[251]); 5155 5156 palette->Flags = 0; 5157 palette->Count = 256; 5158 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 1, FALSE, bitmap); 5159 expect(InvalidParameter, status); 5160 5161 palette->Flags = 0; 5162 palette->Count = 256; 5163 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 2, FALSE, bitmap); 5164 expect(Ok, status); 5165 expect(0, palette->Flags); 5166 expect(2, palette->Count); 5167 5168 palette->Flags = 0; 5169 palette->Count = 256; 5170 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap); 5171 expect(Ok, status); 5172 expect(0, palette->Flags); 5173 expect(16, palette->Count); 5174 5175 /* passing invalid enumeration palette type crashes under most Windows versions */ 5176 5177 GdipFree(palette); 5178 GdipDisposeImage((GpImage *)bitmap); 5179 } 5180 5181 #include "pshpack2.h" 5182 static const struct tiff_1x1_data 5183 { 5184 USHORT byte_order; 5185 USHORT version; 5186 ULONG dir_offset; 5187 USHORT number_of_entries; 5188 struct IFD_entry entry[12]; 5189 ULONG next_IFD; 5190 struct IFD_rational res; 5191 short palette_data[3][256]; 5192 short bps_data[4]; 5193 BYTE pixel_data[32]; 5194 } tiff_1x1_data = 5195 { 5196 #ifdef WORDS_BIGENDIAN 5197 'M' | 'M' << 8, 5198 #else 5199 'I' | 'I' << 8, 5200 #endif 5201 42, 5202 FIELD_OFFSET(struct tiff_1x1_data, number_of_entries), 5203 12, 5204 { 5205 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */ 5206 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */ 5207 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */ 5208 { 0x102, IFD_SHORT, 3, FIELD_OFFSET(struct tiff_1x1_data, bps_data) }, /* BITSPERSAMPLE */ 5209 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */ 5210 { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */ 5211 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1x1_data, pixel_data) }, /* STRIPOFFSETS */ 5212 { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */ 5213 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) }, 5214 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) }, 5215 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */ 5216 { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_1x1_data, palette_data) } /* COLORMAP */ 5217 }, 5218 0, 5219 { 96, 1 }, 5220 { { 0 } }, 5221 { 8,8,8,0 }, 5222 { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 } 5223 }; 5224 #include "poppack.h" 5225 5226 static void test_tiff_color_formats(void) 5227 { 5228 static const struct 5229 { 5230 int photometric; /* PhotometricInterpretation */ 5231 int samples; /* SamplesPerPixel */ 5232 int bps; /* BitsPerSample */ 5233 PixelFormat format; 5234 } td[] = 5235 { 5236 /* 2 - RGB */ 5237 { 2, 3, 1, PixelFormat24bppRGB }, 5238 { 2, 3, 4, PixelFormat24bppRGB }, 5239 { 2, 3, 8, PixelFormat24bppRGB }, 5240 { 2, 3, 16, PixelFormat48bppRGB }, 5241 { 2, 3, 24, 0 }, 5242 #if 0 /* FIXME */ 5243 { 2, 3, 32, 0 }, 5244 #endif 5245 { 2, 4, 1, PixelFormat32bppARGB }, 5246 { 2, 4, 4, PixelFormat32bppARGB }, 5247 { 2, 4, 8, PixelFormat32bppARGB }, 5248 { 2, 4, 16, PixelFormat48bppRGB }, 5249 { 2, 4, 24, 0 }, 5250 { 2, 4, 32, 0 }, 5251 /* 1 - BlackIsZero (Bilevel) */ 5252 { 1, 1, 1, PixelFormat1bppIndexed }, 5253 #if 0 /* FIXME: PNG vs TIFF mismatch */ 5254 { 1, 1, 4, PixelFormat8bppIndexed }, 5255 #endif 5256 { 1, 1, 8, PixelFormat8bppIndexed }, 5257 { 1, 1, 16, PixelFormat32bppARGB }, 5258 { 1, 1, 24, 0 }, 5259 { 1, 1, 32, PixelFormat32bppARGB }, 5260 /* 3 - Palette Color */ 5261 { 3, 1, 1, PixelFormat1bppIndexed }, 5262 { 3, 1, 4, PixelFormat4bppIndexed }, 5263 { 3, 1, 8, PixelFormat8bppIndexed }, 5264 #if 0 /* FIXME: for some reason libtiff replaces photometric 3 by 1 for bps > 8 */ 5265 { 3, 1, 16, 0 }, 5266 { 3, 1, 24, 0 }, 5267 { 3, 1, 32, 0 }, 5268 #endif 5269 /* 5 - Separated */ 5270 { 5, 4, 1, 0 }, 5271 { 5, 4, 4, 0 }, 5272 { 5, 4, 8, PixelFormat32bppCMYK }, 5273 { 5, 4, 16, PixelFormat48bppRGB }, 5274 { 5, 4, 24, 0 }, 5275 { 5, 4, 32, 0 }, 5276 }; 5277 BYTE buf[sizeof(tiff_1x1_data)]; 5278 GpStatus status; 5279 GpImage *image; 5280 UINT count, i; 5281 struct IFD_entry *tag, *tag_photo = NULL, *tag_bps = NULL, *tag_samples = NULL, *tag_colormap = NULL; 5282 short *bps; 5283 ImageType type; 5284 PixelFormat format; 5285 5286 memcpy(buf, &tiff_1x1_data, sizeof(tiff_1x1_data)); 5287 5288 count = *(short *)(buf + tiff_1x1_data.dir_offset); 5289 tag = (struct IFD_entry *)(buf + tiff_1x1_data.dir_offset + sizeof(short)); 5290 5291 /* verify the TIFF structure */ 5292 for (i = 0; i < count; i++) 5293 { 5294 if (tag[i].id == 0x102) /* BitsPerSample */ 5295 tag_bps = &tag[i]; 5296 else if (tag[i].id == 0x106) /* PhotometricInterpretation */ 5297 tag_photo = &tag[i]; 5298 else if (tag[i].id == 0x115) /* SamplesPerPixel */ 5299 tag_samples = &tag[i]; 5300 else if (tag[i].id == 0x140) /* ColorMap */ 5301 tag_colormap = &tag[i]; 5302 } 5303 5304 ok(tag_bps && tag_photo && tag_samples && tag_colormap, "tag 0x102,0x106,0x115 or 0x140 is missing\n"); 5305 if (!tag_bps || !tag_photo || !tag_samples || !tag_colormap) return; 5306 5307 ok(tag_bps->type == IFD_SHORT, "tag 0x102 should have type IFD_SHORT\n"); 5308 bps = (short *)(buf + tag_bps->value); 5309 ok(bps[0] == 8 && bps[1] == 8 && bps[2] == 8 && bps[3] == 0, 5310 "expected bps 8,8,8,0 got %d,%d,%d,%d\n", bps[0], bps[1], bps[2], bps[3]); 5311 5312 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) 5313 { 5314 tag_colormap->count = (1 << td[i].bps) * 3; 5315 tag_photo->value = td[i].photometric; 5316 tag_bps->count = td[i].samples; 5317 tag_samples->value = td[i].samples; 5318 5319 if (td[i].samples == 1) 5320 tag_bps->value = td[i].bps; 5321 else if (td[i].samples == 2) 5322 tag_bps->value = MAKELONG(td[i].bps, td[i].bps); 5323 else if (td[i].samples == 3) 5324 { 5325 tag_bps->value = (BYTE *)bps - buf; 5326 bps[0] = bps[1] = bps[2] = td[i].bps; 5327 } 5328 else if (td[i].samples == 4) 5329 { 5330 tag_bps->value = (BYTE *)bps - buf; 5331 bps[0] = bps[1] = bps[2] = bps[3] = td[i].bps; 5332 } 5333 else 5334 { 5335 ok(0, "%u: unsupported samples count %d\n", i, td[i].samples); 5336 continue; 5337 } 5338 5339 image = load_image(buf, sizeof(buf)); 5340 if (!td[i].format) 5341 ok(!image, 5342 "%u: (%d,%d,%d) TIFF image loading should have failed\n", i, td[i].photometric, td[i].samples, td[i].bps); 5343 else 5344 ok(image != NULL || broken(!image) /* XP */, "%u: failed to load TIFF image data (%d,%d,%d)\n", 5345 i, td[i].photometric, td[i].samples, td[i].bps); 5346 if (!image) continue; 5347 5348 status = GdipGetImageType(image, &type); 5349 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status); 5350 ok(type == ImageTypeBitmap, "%u: wrong image type %d\n", i, type); 5351 5352 status = GdipGetImagePixelFormat(image, &format); 5353 expect(Ok, status); 5354 ok(format == td[i].format, 5355 "%u: expected %#x, got %#x\n", i, td[i].format, format); 5356 5357 GdipDisposeImage(image); 5358 } 5359 } 5360 5361 START_TEST(image) 5362 { 5363 HMODULE mod = GetModuleHandleA("gdiplus.dll"); 5364 struct GdiplusStartupInput gdiplusStartupInput; 5365 ULONG_PTR gdiplusToken; 5366 HMODULE hmsvcrt; 5367 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask); 5368 5369 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */ 5370 hmsvcrt = LoadLibraryA("msvcrt"); 5371 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s"); 5372 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e); 5373 5374 gdiplusStartupInput.GdiplusVersion = 1; 5375 gdiplusStartupInput.DebugEventCallback = NULL; 5376 gdiplusStartupInput.SuppressBackgroundThread = 0; 5377 gdiplusStartupInput.SuppressExternalCodecs = 0; 5378 5379 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 5380 5381 pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize"); 5382 pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram"); 5383 pGdipImageSetAbort = (void*)GetProcAddress(mod, "GdipImageSetAbort"); 5384 5385 test_tiff_color_formats(); 5386 test_GdipInitializePalette(); 5387 test_png_color_formats(); 5388 test_supported_encoders(); 5389 test_CloneBitmapArea(); 5390 test_ARGB_conversion(); 5391 test_DrawImage_scale(); 5392 test_image_format(); 5393 test_DrawImage(); 5394 test_DrawImage_SourceCopy(); 5395 test_GdipDrawImagePointRect(); 5396 test_bitmapbits(); 5397 test_tiff_palette(); 5398 test_GdipGetAllPropertyItems(); 5399 test_tiff_properties(); 5400 test_gif_properties(); 5401 test_image_properties(); 5402 test_Scan0(); 5403 test_FromGdiDib(); 5404 test_GetImageDimension(); 5405 test_GdipImageGetFrameDimensionsCount(); 5406 test_LoadingImages(); 5407 test_SavingImages(); 5408 test_encoders(); 5409 test_LockBits(); 5410 test_LockBits_UserBuf(); 5411 test_GdipCreateBitmapFromHBITMAP(); 5412 test_GdipGetImageFlags(); 5413 test_GdipCloneImage(); 5414 test_testcontrol(); 5415 test_fromhicon(); 5416 test_getrawformat(); 5417 test_loadwmf(); 5418 test_createfromwmf(); 5419 test_createfromwmf_noplaceable(); 5420 test_resolution(); 5421 test_createhbitmap(); 5422 test_getthumbnail(); 5423 test_getsetpixel(); 5424 test_palette(); 5425 test_colormatrix(); 5426 test_gamma(); 5427 test_multiframegif(); 5428 test_rotateflip(); 5429 test_remaptable(); 5430 test_colorkey(); 5431 test_dispose(); 5432 test_createeffect(); 5433 test_getadjustedpalette(); 5434 test_histogram(); 5435 test_imageabort(); 5436 5437 GdiplusShutdown(gdiplusToken); 5438 } 5439