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