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