gdiplus/tests: Add gif frames composition tests.
[wine.git] / dlls / gdiplus / tests / image.c
blobcc8ae2db0f29882543215e839ba89d4af998fa50
1 /*
2 * Unit test suite for images
4 * Copyright (C) 2007 Google (Evan Stade)
5 * Copyright (C) 2012 Dmitry Timoshkov
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.
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.
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
22 #define COBJMACROS
24 #include <math.h>
25 #include <assert.h>
26 #include <stdio.h>
28 #include "initguid.h"
29 #include "objbase.h"
30 #include "gdiplus.h"
31 #include "wine/test.h"
33 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
34 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
36 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39 c1 >>= 8; c2 >>= 8;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 c1 >>= 8; c2 >>= 8;
42 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
43 c1 >>= 8; c2 >>= 8;
44 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45 return TRUE;
48 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
50 WCHAR bufferW[39];
51 char buffer[39];
52 char buffer2[39];
54 StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
55 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
56 StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
57 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
58 if(todo)
59 todo_wine ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
60 else
61 ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
64 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
66 GUID raw;
67 GpStatus stat;
69 stat = GdipGetImageRawFormat(img, &raw);
70 ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
71 if(stat != Ok) return;
72 expect_guid(expected, &raw, line, todo);
75 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
77 LPSTREAM stream;
78 HGLOBAL hglob;
79 LPBYTE data;
80 HRESULT hres;
81 GpStatus stat;
82 GpImage *img;
84 hglob = GlobalAlloc (0, size);
85 data = GlobalLock (hglob);
86 memcpy(data, buff, size);
87 GlobalUnlock(hglob); data = NULL;
89 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
90 ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
91 if(hres != S_OK) return;
93 stat = GdipLoadImageFromStream(stream, &img);
94 ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
95 if(stat != Ok){
96 IStream_Release(stream);
97 return;
100 expect_rawformat(expected, img, line, todo);
102 GdipDisposeImage(img);
103 IStream_Release(stream);
106 static void test_Scan0(void)
108 GpBitmap *bm;
109 GpStatus stat;
110 BYTE buff[360];
112 bm = NULL;
113 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
114 expect(Ok, stat);
115 ok(NULL != bm, "Expected bitmap to be initialized\n");
116 if (stat == Ok)
117 GdipDisposeImage((GpImage*)bm);
119 bm = (GpBitmap*)0xdeadbeef;
120 stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
121 expect(InvalidParameter, stat);
122 ok( !bm, "expected null bitmap\n" );
124 bm = (GpBitmap*)0xdeadbeef;
125 stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
126 expect(InvalidParameter, stat);
127 ok( !bm, "expected null bitmap\n" );
129 bm = (GpBitmap*)0xdeadbeef;
130 stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
131 expect(InvalidParameter, stat);
132 ok( !bm, "expected null bitmap\n" );
134 bm = NULL;
135 stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
136 expect(Ok, stat);
137 ok(NULL != bm, "Expected bitmap to be initialized\n");
138 if (stat == Ok)
139 GdipDisposeImage((GpImage*)bm);
141 bm = (GpBitmap*) 0xdeadbeef;
142 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
143 expect(InvalidParameter, stat);
144 ok( !bm, "expected null bitmap\n" );
146 bm = (GpBitmap*)0xdeadbeef;
147 stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
148 expect(InvalidParameter, stat);
149 ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
151 bm = NULL;
152 stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
153 expect(Ok, stat);
154 ok(NULL != bm, "Expected bitmap to be initialized\n");
155 if (stat == Ok)
156 GdipDisposeImage((GpImage*)bm);
158 bm = (GpBitmap*)0xdeadbeef;
159 stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
160 expect(InvalidParameter, stat);
161 ok( !bm, "expected null bitmap\n" );
164 static void test_FromGdiDib(void)
166 GpBitmap *bm;
167 GpStatus stat;
168 BYTE buff[400];
169 BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
170 BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
171 PixelFormat format;
173 bm = NULL;
175 memset(rbmi, 0, sizeof(rbmi));
177 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
178 bmi->bmiHeader.biWidth = 10;
179 bmi->bmiHeader.biHeight = 10;
180 bmi->bmiHeader.biPlanes = 1;
181 bmi->bmiHeader.biBitCount = 32;
182 bmi->bmiHeader.biCompression = BI_RGB;
184 stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
185 expect(InvalidParameter, stat);
187 stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
188 expect(InvalidParameter, stat);
190 stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
191 expect(InvalidParameter, stat);
193 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
194 expect(Ok, stat);
195 ok(NULL != bm, "Expected bitmap to be initialized\n");
196 if (stat == Ok)
198 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
199 expect(Ok, stat);
200 expect(PixelFormat32bppRGB, format);
202 GdipDisposeImage((GpImage*)bm);
205 bmi->bmiHeader.biBitCount = 24;
206 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
207 expect(Ok, stat);
208 ok(NULL != bm, "Expected bitmap to be initialized\n");
209 if (stat == Ok)
211 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
212 expect(Ok, stat);
213 expect(PixelFormat24bppRGB, format);
215 GdipDisposeImage((GpImage*)bm);
218 bmi->bmiHeader.biBitCount = 16;
219 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
220 expect(Ok, stat);
221 ok(NULL != bm, "Expected bitmap to be initialized\n");
222 if (stat == Ok)
224 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
225 expect(Ok, stat);
226 expect(PixelFormat16bppRGB555, format);
228 GdipDisposeImage((GpImage*)bm);
231 bmi->bmiHeader.biBitCount = 8;
232 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
233 expect(Ok, stat);
234 ok(NULL != bm, "Expected bitmap to be initialized\n");
235 if (stat == Ok)
237 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
238 expect(Ok, stat);
239 expect(PixelFormat8bppIndexed, format);
241 GdipDisposeImage((GpImage*)bm);
244 bmi->bmiHeader.biBitCount = 4;
245 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
246 expect(Ok, stat);
247 ok(NULL != bm, "Expected bitmap to be initialized\n");
248 if (stat == Ok)
250 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
251 expect(Ok, stat);
252 expect(PixelFormat4bppIndexed, format);
254 GdipDisposeImage((GpImage*)bm);
257 bmi->bmiHeader.biBitCount = 1;
258 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
259 expect(Ok, stat);
260 ok(NULL != bm, "Expected bitmap to be initialized\n");
261 if (stat == Ok)
263 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
264 expect(Ok, stat);
265 expect(PixelFormat1bppIndexed, format);
267 GdipDisposeImage((GpImage*)bm);
270 bmi->bmiHeader.biBitCount = 0;
271 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
272 expect(InvalidParameter, stat);
275 static void test_GetImageDimension(void)
277 GpBitmap *bm;
278 GpStatus stat;
279 const REAL WIDTH = 10.0, HEIGHT = 20.0;
280 REAL w,h;
282 bm = (GpBitmap*)0xdeadbeef;
283 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
284 expect(Ok,stat);
285 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
286 ok(NULL != bm, "Expected bitmap to not be NULL\n");
288 stat = GdipGetImageDimension(NULL,&w,&h);
289 expect(InvalidParameter, stat);
291 stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
292 expect(InvalidParameter, stat);
294 stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
295 expect(InvalidParameter, stat);
297 w = -1;
298 h = -1;
299 stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
300 expect(Ok, stat);
301 expectf(WIDTH, w);
302 expectf(HEIGHT, h);
303 GdipDisposeImage((GpImage*)bm);
306 static void test_GdipImageGetFrameDimensionsCount(void)
308 GpBitmap *bm;
309 GpStatus stat;
310 const REAL WIDTH = 10.0, HEIGHT = 20.0;
311 UINT w;
312 GUID dimension = {0};
313 UINT count;
314 ARGB color;
316 bm = (GpBitmap*)0xdeadbeef;
317 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
318 expect(Ok,stat);
319 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
320 ok(NULL != bm, "Expected bitmap to not be NULL\n");
322 stat = GdipImageGetFrameDimensionsCount(NULL,&w);
323 expect(InvalidParameter, stat);
325 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
326 expect(InvalidParameter, stat);
328 w = -1;
329 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
330 expect(Ok, stat);
331 expect(1, w);
333 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
334 expect(Ok, stat);
335 expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
337 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
338 expect(InvalidParameter, stat);
340 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
341 expect(InvalidParameter, stat);
343 stat = GdipImageGetFrameCount(NULL, &dimension, &count);
344 expect(InvalidParameter, stat);
346 /* WinXP crashes on this test */
347 if(0)
349 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
350 expect(InvalidParameter, stat);
353 stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
354 expect(Ok, stat);
356 count = 12345;
357 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
358 expect(Ok, stat);
359 expect(1, count);
361 GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
363 stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
364 expect(Ok, stat);
366 /* SelectActiveFrame has no effect on image data of memory bitmaps */
367 color = 0xdeadbeef;
368 GdipBitmapGetPixel(bm, 0, 0, &color);
369 expect(0xffffffff, color);
371 GdipDisposeImage((GpImage*)bm);
374 static void test_LoadingImages(void)
376 GpStatus stat;
377 GpBitmap *bm;
378 GpImage *img;
379 static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0};
381 stat = GdipCreateBitmapFromFile(0, 0);
382 expect(InvalidParameter, stat);
384 bm = (GpBitmap *)0xdeadbeef;
385 stat = GdipCreateBitmapFromFile(0, &bm);
386 expect(InvalidParameter, stat);
387 ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm);
389 bm = (GpBitmap *)0xdeadbeef;
390 stat = GdipCreateBitmapFromFile(nonexistentW, &bm);
391 todo_wine expect(InvalidParameter, stat);
392 ok(!bm, "returned %p\n", bm);
394 stat = GdipLoadImageFromFile(0, 0);
395 expect(InvalidParameter, stat);
397 img = (GpImage *)0xdeadbeef;
398 stat = GdipLoadImageFromFile(0, &img);
399 expect(InvalidParameter, stat);
400 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
402 img = (GpImage *)0xdeadbeef;
403 stat = GdipLoadImageFromFile(nonexistentW, &img);
404 todo_wine expect(OutOfMemory, stat);
405 ok(!img, "returned %p\n", img);
407 stat = GdipLoadImageFromFileICM(0, 0);
408 expect(InvalidParameter, stat);
410 img = (GpImage *)0xdeadbeef;
411 stat = GdipLoadImageFromFileICM(0, &img);
412 expect(InvalidParameter, stat);
413 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
415 img = (GpImage *)0xdeadbeef;
416 stat = GdipLoadImageFromFileICM(nonexistentW, &img);
417 todo_wine expect(OutOfMemory, stat);
418 ok(!img, "returned %p\n", img);
421 static void test_SavingImages(void)
423 GpStatus stat;
424 GpBitmap *bm;
425 UINT n;
426 UINT s;
427 const REAL WIDTH = 10.0, HEIGHT = 20.0;
428 REAL w, h;
429 ImageCodecInfo *codecs;
430 static const CHAR filenameA[] = "a.bmp";
431 static const WCHAR filename[] = { 'a','.','b','m','p',0 };
433 codecs = NULL;
435 stat = GdipSaveImageToFile(0, 0, 0, 0);
436 expect(InvalidParameter, stat);
438 bm = NULL;
439 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
440 expect(Ok, stat);
441 if (!bm)
442 return;
444 /* invalid params */
445 stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
446 expect(InvalidParameter, stat);
448 stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
449 expect(InvalidParameter, stat);
451 /* encoder tests should succeed -- already tested */
452 stat = GdipGetImageEncodersSize(&n, &s);
453 if (stat != Ok || n == 0) goto cleanup;
455 codecs = GdipAlloc(s);
456 if (!codecs) goto cleanup;
458 stat = GdipGetImageEncoders(n, s, codecs);
459 if (stat != Ok) goto cleanup;
461 stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
462 expect(Ok, stat);
464 GdipDisposeImage((GpImage*)bm);
465 bm = 0;
467 /* re-load and check image stats */
468 stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
469 expect(Ok, stat);
470 if (stat != Ok) goto cleanup;
472 stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
473 if (stat != Ok) goto cleanup;
475 expectf(WIDTH, w);
476 expectf(HEIGHT, h);
478 cleanup:
479 GdipFree(codecs);
480 if (bm)
481 GdipDisposeImage((GpImage*)bm);
482 ok(DeleteFileA(filenameA), "Delete failed.\n");
485 static void test_encoders(void)
487 GpStatus stat;
488 UINT n;
489 UINT s;
490 ImageCodecInfo *codecs;
491 int i;
492 int bmp_found;
494 static const CHAR bmp_format[] = "BMP";
496 stat = GdipGetImageEncodersSize(&n, &s);
497 expect(stat, Ok);
499 codecs = GdipAlloc(s);
500 if (!codecs)
501 return;
503 stat = GdipGetImageEncoders(n, s, NULL);
504 expect(GenericError, stat);
506 stat = GdipGetImageEncoders(0, s, codecs);
507 expect(GenericError, stat);
509 stat = GdipGetImageEncoders(n, s-1, codecs);
510 expect(GenericError, stat);
512 stat = GdipGetImageEncoders(n, s+1, codecs);
513 expect(GenericError, stat);
515 stat = GdipGetImageEncoders(n, s, codecs);
516 expect(stat, Ok);
518 bmp_found = FALSE;
519 for (i = 0; i < n; i++)
521 CHAR desc[32];
523 WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
524 desc, 32, 0, 0);
526 if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
527 desc, -1,
528 bmp_format, -1) == CSTR_EQUAL) {
529 bmp_found = TRUE;
530 break;
533 if (!bmp_found)
534 ok(FALSE, "No BMP codec found.\n");
536 GdipFree(codecs);
539 static void test_LockBits(void)
541 GpStatus stat;
542 GpBitmap *bm;
543 GpRect rect;
544 BitmapData bd;
545 const INT WIDTH = 10, HEIGHT = 20;
546 ARGB color;
547 int y;
549 bm = NULL;
550 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
551 expect(Ok, stat);
553 rect.X = 2;
554 rect.Y = 3;
555 rect.Width = 4;
556 rect.Height = 5;
558 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
559 expect(Ok, stat);
561 stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
562 expect(Ok, stat);
564 /* read-only */
565 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
566 expect(Ok, stat);
568 if (stat == Ok) {
569 expect(0xc3, ((BYTE*)bd.Scan0)[2]);
570 expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
572 ((char*)bd.Scan0)[2] = 0xff;
574 stat = GdipBitmapUnlockBits(bm, &bd);
575 expect(Ok, stat);
578 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
579 expect(Ok, stat);
580 expect(0xffff0000, color);
582 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
583 expect(Ok, stat);
585 /* read-only, with NULL rect -> whole bitmap lock */
586 stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
587 expect(Ok, stat);
588 expect(bd.Width, WIDTH);
589 expect(bd.Height, HEIGHT);
591 if (stat == Ok) {
592 ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
594 stat = GdipBitmapUnlockBits(bm, &bd);
595 expect(Ok, stat);
598 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
599 expect(Ok, stat);
600 expect(0xffff0000, color);
602 /* read-only, consecutive */
603 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
604 expect(Ok, stat);
606 if (stat == Ok) {
607 stat = GdipBitmapUnlockBits(bm, &bd);
608 expect(Ok, stat);
611 stat = GdipDisposeImage((GpImage*)bm);
612 expect(Ok, stat);
613 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
614 expect(Ok, stat);
616 /* read x2 */
617 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
618 expect(Ok, stat);
619 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
620 expect(WrongState, stat);
622 stat = GdipBitmapUnlockBits(bm, &bd);
623 expect(Ok, stat);
625 stat = GdipDisposeImage((GpImage*)bm);
626 expect(Ok, stat);
627 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
628 expect(Ok, stat);
630 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
631 expect(Ok, stat);
633 stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
634 expect(Ok, stat);
636 /* write, no conversion */
637 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
638 expect(Ok, stat);
640 if (stat == Ok) {
641 /* all bits are readable, inside the rect or not */
642 expect(0xff, ((BYTE*)bd.Scan0)[2]);
643 expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
645 stat = GdipBitmapUnlockBits(bm, &bd);
646 expect(Ok, stat);
649 /* read, conversion */
650 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
651 expect(Ok, stat);
653 if (stat == Ok) {
654 expect(0xff, ((BYTE*)bd.Scan0)[2]);
655 if (0)
656 /* Areas outside the rectangle appear to be uninitialized */
657 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
659 ((BYTE*)bd.Scan0)[2] = 0xc3;
661 stat = GdipBitmapUnlockBits(bm, &bd);
662 expect(Ok, stat);
665 /* writes do not work in read mode if there was a conversion */
666 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
667 expect(Ok, stat);
668 expect(0xffff0000, color);
670 /* read/write, conversion */
671 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
672 expect(Ok, stat);
674 if (stat == Ok) {
675 expect(0xff, ((BYTE*)bd.Scan0)[2]);
676 ((BYTE*)bd.Scan0)[1] = 0x88;
677 if (0)
678 /* Areas outside the rectangle appear to be uninitialized */
679 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
681 stat = GdipBitmapUnlockBits(bm, &bd);
682 expect(Ok, stat);
685 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
686 expect(Ok, stat);
687 expect(0xffff8800, color);
689 /* write, conversion */
690 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
691 expect(Ok, stat);
693 if (stat == Ok) {
694 if (0)
696 /* This is completely uninitialized. */
697 ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
698 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
701 /* Initialize the buffer so the unlock doesn't access undefined memory */
702 for (y=0; y<5; y++)
703 memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
705 ((BYTE*)bd.Scan0)[0] = 0x12;
706 ((BYTE*)bd.Scan0)[1] = 0x34;
707 ((BYTE*)bd.Scan0)[2] = 0x56;
709 stat = GdipBitmapUnlockBits(bm, &bd);
710 expect(Ok, stat);
713 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
714 expect(Ok, stat);
715 expect(0xff563412, color);
717 stat = GdipBitmapGetPixel(bm, 2, 8, &color);
718 expect(Ok, stat);
719 expect(0xffc30000, color);
721 stat = GdipDisposeImage((GpImage*)bm);
722 expect(Ok, stat);
723 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
724 expect(Ok, stat);
726 /* write, no modification */
727 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
728 expect(Ok, stat);
730 if (stat == Ok) {
731 stat = GdipBitmapUnlockBits(bm, &bd);
732 expect(Ok, stat);
735 /* write, consecutive */
736 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
737 expect(Ok, stat);
739 if (stat == Ok) {
740 stat = GdipBitmapUnlockBits(bm, &bd);
741 expect(Ok, stat);
744 stat = GdipDisposeImage((GpImage*)bm);
745 expect(Ok, stat);
746 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
747 expect(Ok, stat);
749 /* write, modify */
750 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
751 expect(Ok, stat);
753 if (stat == Ok) {
754 if (bd.Scan0)
755 ((char*)bd.Scan0)[2] = 0xff;
757 stat = GdipBitmapUnlockBits(bm, &bd);
758 expect(Ok, stat);
761 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
762 expect(Ok, stat);
763 expect(0xffff0000, color);
765 stat = GdipDisposeImage((GpImage*)bm);
766 expect(Ok, stat);
768 /* dispose locked */
769 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
770 expect(Ok, stat);
771 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
772 expect(Ok, stat);
773 stat = GdipDisposeImage((GpImage*)bm);
774 expect(Ok, stat);
777 static void test_LockBits_UserBuf(void)
779 GpStatus stat;
780 GpBitmap *bm;
781 GpRect rect;
782 BitmapData bd;
783 const INT WIDTH = 10, HEIGHT = 20;
784 DWORD bits[200];
785 ARGB color;
787 bm = NULL;
788 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
789 expect(Ok, stat);
791 memset(bits, 0xaa, sizeof(bits));
793 rect.X = 2;
794 rect.Y = 3;
795 rect.Width = 4;
796 rect.Height = 5;
798 bd.Width = 4;
799 bd.Height = 6;
800 bd.Stride = WIDTH * 4;
801 bd.PixelFormat = PixelFormat32bppARGB;
802 bd.Scan0 = &bits[2+3*WIDTH];
803 bd.Reserved = 0xaaaaaaaa;
805 /* read-only */
806 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
807 expect(Ok, stat);
809 expect(0xaaaaaaaa, bits[0]);
810 expect(0, bits[2+3*WIDTH]);
812 bits[2+3*WIDTH] = 0xdeadbeef;
814 if (stat == Ok) {
815 stat = GdipBitmapUnlockBits(bm, &bd);
816 expect(Ok, stat);
819 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
820 expect(Ok, stat);
821 expect(0, color);
823 /* write-only */
824 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
825 expect(Ok, stat);
827 expect(0xdeadbeef, bits[2+3*WIDTH]);
828 bits[2+3*WIDTH] = 0x12345678;
830 if (stat == Ok) {
831 stat = GdipBitmapUnlockBits(bm, &bd);
832 expect(Ok, stat);
835 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
836 expect(Ok, stat);
837 expect(0x12345678, color);
839 bits[2+3*WIDTH] = 0;
841 /* read/write */
842 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
843 expect(Ok, stat);
845 expect(0x12345678, bits[2+3*WIDTH]);
846 bits[2+3*WIDTH] = 0xdeadbeef;
848 if (stat == Ok) {
849 stat = GdipBitmapUnlockBits(bm, &bd);
850 expect(Ok, stat);
853 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
854 expect(Ok, stat);
855 expect(0xdeadbeef, color);
857 stat = GdipDisposeImage((GpImage*)bm);
858 expect(Ok, stat);
861 struct BITMAPINFOWITHBITFIELDS
863 BITMAPINFOHEADER bmiHeader;
864 DWORD masks[3];
867 union BITMAPINFOUNION
869 BITMAPINFO bi;
870 struct BITMAPINFOWITHBITFIELDS bf;
873 static void test_GdipCreateBitmapFromHBITMAP(void)
875 GpBitmap* gpbm = NULL;
876 HBITMAP hbm = NULL;
877 HPALETTE hpal = NULL;
878 GpStatus stat;
879 BYTE buff[1000];
880 LOGPALETTE* LogPal = NULL;
881 REAL width, height;
882 const REAL WIDTH1 = 5;
883 const REAL HEIGHT1 = 15;
884 const REAL WIDTH2 = 10;
885 const REAL HEIGHT2 = 20;
886 HDC hdc;
887 union BITMAPINFOUNION bmi;
888 BYTE *bits;
889 PixelFormat format;
891 stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
892 expect(InvalidParameter, stat);
894 hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
895 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
896 expect(InvalidParameter, stat);
898 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
899 expect(Ok, stat);
900 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
901 expectf(WIDTH1, width);
902 expectf(HEIGHT1, height);
903 if (stat == Ok)
904 GdipDisposeImage((GpImage*)gpbm);
905 DeleteObject(hbm);
907 memset(buff, 0, sizeof(buff));
908 hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
909 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
910 expect(Ok, stat);
911 /* raw format */
912 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
914 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
915 expectf(WIDTH2, width);
916 expectf(HEIGHT2, height);
917 if (stat == Ok)
918 GdipDisposeImage((GpImage*)gpbm);
919 DeleteObject(hbm);
921 hdc = CreateCompatibleDC(0);
922 ok(hdc != NULL, "CreateCompatibleDC failed\n");
923 bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
924 bmi.bi.bmiHeader.biHeight = HEIGHT1;
925 bmi.bi.bmiHeader.biWidth = WIDTH1;
926 bmi.bi.bmiHeader.biBitCount = 24;
927 bmi.bi.bmiHeader.biPlanes = 1;
928 bmi.bi.bmiHeader.biCompression = BI_RGB;
929 bmi.bi.bmiHeader.biClrUsed = 0;
931 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
932 ok(hbm != NULL, "CreateDIBSection failed\n");
934 bits[0] = 0;
936 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
937 expect(Ok, stat);
938 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
939 expectf(WIDTH1, width);
940 expectf(HEIGHT1, height);
941 if (stat == Ok)
943 /* test whether writing to the bitmap affects the original */
944 stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
945 expect(Ok, stat);
947 expect(0, bits[0]);
949 GdipDisposeImage((GpImage*)gpbm);
952 LogPal = GdipAlloc(sizeof(LOGPALETTE));
953 ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
954 LogPal->palVersion = 0x300;
955 LogPal->palNumEntries = 1;
956 hpal = CreatePalette(LogPal);
957 ok(hpal != NULL, "CreatePalette failed\n");
958 GdipFree(LogPal);
960 stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
961 expect(Ok, stat);
963 if (stat == Ok)
964 GdipDisposeImage((GpImage*)gpbm);
966 DeleteObject(hpal);
967 DeleteObject(hbm);
969 /* 16-bit 555 dib, rgb */
970 bmi.bi.bmiHeader.biBitCount = 16;
971 bmi.bi.bmiHeader.biCompression = BI_RGB;
973 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
974 ok(hbm != NULL, "CreateDIBSection failed\n");
976 bits[0] = 0;
978 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
979 expect(Ok, stat);
981 if (stat == Ok)
983 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
984 expect(Ok, stat);
985 expectf(WIDTH1, width);
986 expectf(HEIGHT1, height);
988 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
989 expect(Ok, stat);
990 expect(PixelFormat16bppRGB555, format);
992 GdipDisposeImage((GpImage*)gpbm);
994 DeleteObject(hbm);
996 /* 16-bit 555 dib, with bitfields */
997 bmi.bi.bmiHeader.biSize = sizeof(bmi);
998 bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
999 bmi.bf.masks[0] = 0x7c00;
1000 bmi.bf.masks[1] = 0x3e0;
1001 bmi.bf.masks[2] = 0x1f;
1003 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1004 ok(hbm != NULL, "CreateDIBSection failed\n");
1006 bits[0] = 0;
1008 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1009 expect(Ok, stat);
1011 if (stat == Ok)
1013 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1014 expect(Ok, stat);
1015 expectf(WIDTH1, width);
1016 expectf(HEIGHT1, height);
1018 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1019 expect(Ok, stat);
1020 expect(PixelFormat16bppRGB555, format);
1022 GdipDisposeImage((GpImage*)gpbm);
1024 DeleteObject(hbm);
1026 /* 16-bit 565 dib, with bitfields */
1027 bmi.bf.masks[0] = 0xf800;
1028 bmi.bf.masks[1] = 0x7e0;
1029 bmi.bf.masks[2] = 0x1f;
1031 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1032 ok(hbm != NULL, "CreateDIBSection failed\n");
1034 bits[0] = 0;
1036 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1037 expect(Ok, stat);
1039 if (stat == Ok)
1041 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1042 expect(Ok, stat);
1043 expectf(WIDTH1, width);
1044 expectf(HEIGHT1, height);
1046 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1047 expect(Ok, stat);
1048 expect(PixelFormat16bppRGB565, format);
1050 GdipDisposeImage((GpImage*)gpbm);
1052 DeleteObject(hbm);
1054 DeleteDC(hdc);
1057 static void test_GdipGetImageFlags(void)
1059 GpImage *img;
1060 GpStatus stat;
1061 UINT flags;
1063 img = (GpImage*)0xdeadbeef;
1065 stat = GdipGetImageFlags(NULL, NULL);
1066 expect(InvalidParameter, stat);
1068 stat = GdipGetImageFlags(NULL, &flags);
1069 expect(InvalidParameter, stat);
1071 stat = GdipGetImageFlags(img, NULL);
1072 expect(InvalidParameter, stat);
1074 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1075 expect(Ok, stat);
1076 stat = GdipGetImageFlags(img, &flags);
1077 expect(Ok, stat);
1078 expect(ImageFlagsHasAlpha, flags);
1079 GdipDisposeImage(img);
1081 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1082 expect(Ok, stat);
1083 stat = GdipGetImageFlags(img, &flags);
1084 expect(Ok, stat);
1085 expect(ImageFlagsHasAlpha, flags);
1086 GdipDisposeImage(img);
1088 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1089 expect(Ok, stat);
1090 stat = GdipGetImageFlags(img, &flags);
1091 expect(Ok, stat);
1092 expect(ImageFlagsHasAlpha, flags);
1093 GdipDisposeImage(img);
1095 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1096 expect(Ok, stat);
1097 stat = GdipGetImageFlags(img, &flags);
1098 expect(Ok, stat);
1099 expect(ImageFlagsNone, flags);
1100 GdipDisposeImage(img);
1102 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1103 expect(Ok, stat);
1104 stat = GdipGetImageFlags(img, &flags);
1105 expect(Ok, stat);
1106 expect(ImageFlagsNone, flags);
1107 GdipDisposeImage(img);
1109 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1110 expect(Ok, stat);
1111 stat = GdipGetImageFlags(img, &flags);
1112 expect(Ok, stat);
1113 expect(ImageFlagsNone, flags);
1114 GdipDisposeImage(img);
1116 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1117 expect(Ok, stat);
1118 stat = GdipGetImageFlags(img, &flags);
1119 expect(Ok, stat);
1120 expect(ImageFlagsHasAlpha, flags);
1121 GdipDisposeImage(img);
1123 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1124 expect(Ok, stat);
1125 stat = GdipGetImageFlags(img, &flags);
1126 expect(Ok, stat);
1127 expect(ImageFlagsNone, flags);
1128 GdipDisposeImage(img);
1130 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1131 expect(Ok, stat);
1132 stat = GdipGetImageFlags(img, &flags);
1133 expect(Ok, stat);
1134 expect(ImageFlagsNone, flags);
1135 GdipDisposeImage(img);
1137 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1138 expect(Ok, stat);
1139 stat = GdipGetImageFlags(img, &flags);
1140 expect(Ok, stat);
1141 expect(ImageFlagsHasAlpha, flags);
1142 GdipDisposeImage(img);
1144 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1145 expect(Ok, stat);
1146 stat = GdipGetImageFlags(img, &flags);
1147 expect(Ok, stat);
1148 expect(ImageFlagsHasAlpha, flags);
1149 GdipDisposeImage(img);
1151 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1152 expect(Ok, stat);
1153 if (stat == Ok)
1155 stat = GdipGetImageFlags(img, &flags);
1156 expect(Ok, stat);
1157 expect(ImageFlagsNone, flags);
1158 GdipDisposeImage(img);
1161 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1162 expect(Ok, stat);
1163 if (stat == Ok)
1165 expect(Ok, stat);
1166 stat = GdipGetImageFlags(img, &flags);
1167 expect(Ok, stat);
1168 expect(ImageFlagsHasAlpha, flags);
1169 GdipDisposeImage(img);
1172 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1173 expect(Ok, stat);
1174 if (stat == Ok)
1176 expect(Ok, stat);
1177 stat = GdipGetImageFlags(img, &flags);
1178 expect(Ok, stat);
1179 expect(ImageFlagsHasAlpha, flags);
1180 GdipDisposeImage(img);
1184 static void test_GdipCloneImage(void)
1186 GpStatus stat;
1187 GpRectF rectF;
1188 GpUnit unit;
1189 GpBitmap *bm;
1190 GpImage *image_src, *image_dest = NULL;
1191 const INT WIDTH = 10, HEIGHT = 20;
1193 /* Create an image, clone it, delete the original, make sure the copy works */
1194 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1195 expect(Ok, stat);
1196 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1198 image_src = ((GpImage*)bm);
1199 stat = GdipCloneImage(image_src, &image_dest);
1200 expect(Ok, stat);
1201 expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1203 stat = GdipDisposeImage((GpImage*)bm);
1204 expect(Ok, stat);
1205 stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1206 expect(Ok, stat);
1208 /* Treat FP values carefully */
1209 expectf((REAL)WIDTH, rectF.Width);
1210 expectf((REAL)HEIGHT, rectF.Height);
1212 stat = GdipDisposeImage(image_dest);
1213 expect(Ok, stat);
1216 static void test_testcontrol(void)
1218 GpStatus stat;
1219 DWORD param;
1221 param = 0;
1222 stat = GdipTestControl(TestControlGetBuildNumber, &param);
1223 expect(Ok, stat);
1224 ok(param != 0, "Build number expected, got %u\n", param);
1227 static void test_fromhicon(void)
1229 static const BYTE bmp_bits[1024];
1230 HBITMAP hbmMask, hbmColor;
1231 ICONINFO info;
1232 HICON hIcon;
1233 GpStatus stat;
1234 GpBitmap *bitmap = NULL;
1235 UINT dim;
1236 ImageType type;
1237 PixelFormat format;
1239 /* NULL */
1240 stat = GdipCreateBitmapFromHICON(NULL, NULL);
1241 expect(InvalidParameter, stat);
1242 stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1243 expect(InvalidParameter, stat);
1245 /* color icon 1 bit */
1246 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1247 ok(hbmMask != 0, "CreateBitmap failed\n");
1248 hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1249 ok(hbmColor != 0, "CreateBitmap failed\n");
1250 info.fIcon = TRUE;
1251 info.xHotspot = 8;
1252 info.yHotspot = 8;
1253 info.hbmMask = hbmMask;
1254 info.hbmColor = hbmColor;
1255 hIcon = CreateIconIndirect(&info);
1256 ok(hIcon != 0, "CreateIconIndirect failed\n");
1257 DeleteObject(hbmMask);
1258 DeleteObject(hbmColor);
1260 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1261 ok(stat == Ok ||
1262 broken(stat == InvalidParameter), /* Win98 */
1263 "Expected Ok, got %.8x\n", stat);
1264 if(stat == Ok){
1265 /* check attributes */
1266 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1267 expect(Ok, stat);
1268 expect(16, dim);
1269 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1270 expect(Ok, stat);
1271 expect(16, dim);
1272 stat = GdipGetImageType((GpImage*)bitmap, &type);
1273 expect(Ok, stat);
1274 expect(ImageTypeBitmap, type);
1275 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1276 expect(Ok, stat);
1277 expect(PixelFormat32bppARGB, format);
1278 /* raw format */
1279 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1280 GdipDisposeImage((GpImage*)bitmap);
1282 DestroyIcon(hIcon);
1284 /* color icon 8 bpp */
1285 hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1286 ok(hbmMask != 0, "CreateBitmap failed\n");
1287 hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1288 ok(hbmColor != 0, "CreateBitmap failed\n");
1289 info.fIcon = TRUE;
1290 info.xHotspot = 8;
1291 info.yHotspot = 8;
1292 info.hbmMask = hbmMask;
1293 info.hbmColor = hbmColor;
1294 hIcon = CreateIconIndirect(&info);
1295 ok(hIcon != 0, "CreateIconIndirect failed\n");
1296 DeleteObject(hbmMask);
1297 DeleteObject(hbmColor);
1299 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1300 expect(Ok, stat);
1301 if(stat == Ok){
1302 /* check attributes */
1303 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1304 expect(Ok, stat);
1305 expect(16, dim);
1306 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1307 expect(Ok, stat);
1308 expect(16, dim);
1309 stat = GdipGetImageType((GpImage*)bitmap, &type);
1310 expect(Ok, stat);
1311 expect(ImageTypeBitmap, type);
1312 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1313 expect(Ok, stat);
1314 expect(PixelFormat32bppARGB, format);
1315 /* raw format */
1316 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1317 GdipDisposeImage((GpImage*)bitmap);
1319 DestroyIcon(hIcon);
1322 /* 1x1 pixel png */
1323 static const unsigned char pngimage[285] = {
1324 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1325 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1326 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1327 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1328 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1329 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1330 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1332 /* 1x1 pixel gif */
1333 static const unsigned char gifimage[35] = {
1334 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1335 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1336 0x01,0x00,0x3b
1338 /* 1x1 pixel bmp */
1339 static const unsigned char bmpimage[66] = {
1340 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1341 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1342 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1343 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1344 0x00,0x00
1346 /* 1x1 pixel jpg */
1347 static const unsigned char jpgimage[285] = {
1348 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1349 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1350 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1351 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1352 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1353 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1354 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1355 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1356 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1357 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1358 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1359 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1360 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1361 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1362 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1363 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1364 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1365 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1367 /* 1x1 pixel tiff */
1368 static const unsigned char tiffimage[] = {
1369 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1370 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1371 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1372 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1373 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1374 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1375 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1376 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1377 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1378 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1379 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1380 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1381 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1382 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1383 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1384 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1385 0x00,0x00,0x00,0x01
1387 /* 320x320 twip wmf */
1388 static const unsigned char wmfimage[180] = {
1389 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1390 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1391 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1392 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1393 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1394 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1395 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1396 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1397 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1398 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1399 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1400 0x00,0x00,0x00,0x00
1402 static void test_getrawformat(void)
1404 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE);
1405 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE);
1406 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE);
1407 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1408 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1409 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1412 static void test_loadwmf(void)
1414 LPSTREAM stream;
1415 HGLOBAL hglob;
1416 LPBYTE data;
1417 HRESULT hres;
1418 GpStatus stat;
1419 GpImage *img;
1420 GpRectF bounds;
1421 GpUnit unit;
1422 REAL res = 12345.0;
1423 MetafileHeader header;
1425 hglob = GlobalAlloc (0, sizeof(wmfimage));
1426 data = GlobalLock (hglob);
1427 memcpy(data, wmfimage, sizeof(wmfimage));
1428 GlobalUnlock(hglob); data = NULL;
1430 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1431 ok(hres == S_OK, "Failed to create a stream\n");
1432 if(hres != S_OK) return;
1434 stat = GdipLoadImageFromStream(stream, &img);
1435 ok(stat == Ok, "Failed to create a Bitmap\n");
1436 if(stat != Ok){
1437 IStream_Release(stream);
1438 return;
1441 IStream_Release(stream);
1443 stat = GdipGetImageBounds(img, &bounds, &unit);
1444 expect(Ok, stat);
1445 todo_wine expect(UnitPixel, unit);
1446 expectf(0.0, bounds.X);
1447 expectf(0.0, bounds.Y);
1448 todo_wine expectf(320.0, bounds.Width);
1449 todo_wine expectf(320.0, bounds.Height);
1451 stat = GdipGetImageHorizontalResolution(img, &res);
1452 expect(Ok, stat);
1453 todo_wine expectf(1440.0, res);
1455 stat = GdipGetImageVerticalResolution(img, &res);
1456 expect(Ok, stat);
1457 todo_wine expectf(1440.0, res);
1459 memset(&header, 0, sizeof(header));
1460 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1461 expect(Ok, stat);
1462 if (stat == Ok)
1464 todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1465 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1466 todo_wine expect(0x300, header.Version);
1467 expect(0, header.EmfPlusFlags);
1468 todo_wine expectf(1440.0, header.DpiX);
1469 todo_wine expectf(1440.0, header.DpiY);
1470 expect(0, header.X);
1471 expect(0, header.Y);
1472 todo_wine expect(320, header.Width);
1473 todo_wine expect(320, header.Height);
1474 todo_wine expect(1, U(header).WmfHeader.mtType);
1475 expect(0, header.EmfPlusHeaderSize);
1476 expect(0, header.LogicalDpiX);
1477 expect(0, header.LogicalDpiY);
1480 GdipDisposeImage(img);
1483 static void test_createfromwmf(void)
1485 HMETAFILE hwmf;
1486 GpImage *img;
1487 GpStatus stat;
1488 GpRectF bounds;
1489 GpUnit unit;
1490 REAL res = 12345.0;
1491 MetafileHeader header;
1493 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1494 wmfimage+sizeof(WmfPlaceableFileHeader));
1495 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1497 stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1498 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1499 expect(Ok, stat);
1501 stat = GdipGetImageBounds(img, &bounds, &unit);
1502 expect(Ok, stat);
1503 expect(UnitPixel, unit);
1504 expectf(0.0, bounds.X);
1505 expectf(0.0, bounds.Y);
1506 expectf(320.0, bounds.Width);
1507 expectf(320.0, bounds.Height);
1509 stat = GdipGetImageHorizontalResolution(img, &res);
1510 expect(Ok, stat);
1511 expectf(1440.0, res);
1513 stat = GdipGetImageVerticalResolution(img, &res);
1514 expect(Ok, stat);
1515 expectf(1440.0, res);
1517 memset(&header, 0, sizeof(header));
1518 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1519 expect(Ok, stat);
1520 if (stat == Ok)
1522 todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1523 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1524 todo_wine expect(0x300, header.Version);
1525 expect(0, header.EmfPlusFlags);
1526 todo_wine expectf(1440.0, header.DpiX);
1527 todo_wine expectf(1440.0, header.DpiY);
1528 expect(0, header.X);
1529 expect(0, header.Y);
1530 todo_wine expect(320, header.Width);
1531 todo_wine expect(320, header.Height);
1532 todo_wine expect(1, U(header).WmfHeader.mtType);
1533 expect(0, header.EmfPlusHeaderSize);
1534 expect(0, header.LogicalDpiX);
1535 expect(0, header.LogicalDpiY);
1538 GdipDisposeImage(img);
1541 static void test_resolution(void)
1543 GpStatus stat;
1544 GpBitmap *bitmap;
1545 GpGraphics *graphics;
1546 REAL res=-1.0;
1547 HDC screendc;
1548 int screenxres, screenyres;
1550 /* create Bitmap */
1551 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1552 expect(Ok, stat);
1554 /* test invalid values */
1555 stat = GdipGetImageHorizontalResolution(NULL, &res);
1556 expect(InvalidParameter, stat);
1558 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1559 expect(InvalidParameter, stat);
1561 stat = GdipGetImageVerticalResolution(NULL, &res);
1562 expect(InvalidParameter, stat);
1564 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1565 expect(InvalidParameter, stat);
1567 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1568 expect(InvalidParameter, stat);
1570 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1571 expect(InvalidParameter, stat);
1573 /* defaults to screen resolution */
1574 screendc = GetDC(0);
1576 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1577 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1579 ReleaseDC(0, screendc);
1581 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1582 expect(Ok, stat);
1583 expectf((REAL)screenxres, res);
1585 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1586 expect(Ok, stat);
1587 expectf((REAL)screenyres, res);
1589 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1590 expect(Ok, stat);
1591 stat = GdipGetDpiX(graphics, &res);
1592 expect(Ok, stat);
1593 expectf((REAL)screenxres, res);
1594 stat = GdipGetDpiY(graphics, &res);
1595 expect(Ok, stat);
1596 expectf((REAL)screenyres, res);
1598 /* test changing the resolution */
1599 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1600 expect(Ok, stat);
1602 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1603 expect(Ok, stat);
1604 expectf(screenxres*2.0, res);
1606 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1607 expect(Ok, stat);
1608 expectf(screenyres*3.0, res);
1610 stat = GdipGetDpiX(graphics, &res);
1611 expect(Ok, stat);
1612 expectf((REAL)screenxres, res);
1613 stat = GdipGetDpiY(graphics, &res);
1614 expect(Ok, stat);
1615 expectf((REAL)screenyres, res);
1617 stat = GdipDeleteGraphics(graphics);
1618 expect(Ok, stat);
1620 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1621 expect(Ok, stat);
1622 stat = GdipGetDpiX(graphics, &res);
1623 expect(Ok, stat);
1624 expectf(screenxres*2.0, res);
1625 stat = GdipGetDpiY(graphics, &res);
1626 expect(Ok, stat);
1627 expectf(screenyres*3.0, res);
1628 stat = GdipDeleteGraphics(graphics);
1629 expect(Ok, stat);
1631 stat = GdipDisposeImage((GpImage*)bitmap);
1632 expect(Ok, stat);
1635 static void test_createhbitmap(void)
1637 GpStatus stat;
1638 GpBitmap *bitmap;
1639 HBITMAP hbitmap, oldhbitmap;
1640 BITMAP bm;
1641 int ret;
1642 HDC hdc;
1643 COLORREF pixel;
1644 BYTE bits[640];
1646 memset(bits, 0x68, 640);
1648 /* create Bitmap */
1649 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1650 expect(Ok, stat);
1652 /* test NULL values */
1653 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1654 expect(InvalidParameter, stat);
1656 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1657 expect(InvalidParameter, stat);
1659 /* create HBITMAP */
1660 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1661 expect(Ok, stat);
1663 if (stat == Ok)
1665 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1666 expect(sizeof(BITMAP), ret);
1668 expect(0, bm.bmType);
1669 expect(10, bm.bmWidth);
1670 expect(20, bm.bmHeight);
1671 expect(40, bm.bmWidthBytes);
1672 expect(1, bm.bmPlanes);
1673 expect(32, bm.bmBitsPixel);
1674 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1676 if (bm.bmBits)
1678 DWORD val = *(DWORD*)bm.bmBits;
1679 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1682 hdc = CreateCompatibleDC(NULL);
1684 oldhbitmap = SelectObject(hdc, hbitmap);
1685 pixel = GetPixel(hdc, 5, 5);
1686 SelectObject(hdc, oldhbitmap);
1688 DeleteDC(hdc);
1690 expect(0x686868, pixel);
1692 DeleteObject(hbitmap);
1695 stat = GdipDisposeImage((GpImage*)bitmap);
1696 expect(Ok, stat);
1698 /* make (1,0) have no alpha and (2,0) a different blue value. */
1699 bits[7] = 0x00;
1700 bits[8] = 0x40;
1702 /* create alpha Bitmap */
1703 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1704 expect(Ok, stat);
1706 /* create HBITMAP */
1707 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1708 expect(Ok, stat);
1710 if (stat == Ok)
1712 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1713 expect(sizeof(BITMAP), ret);
1715 expect(0, bm.bmType);
1716 expect(8, bm.bmWidth);
1717 expect(20, bm.bmHeight);
1718 expect(32, bm.bmWidthBytes);
1719 expect(1, bm.bmPlanes);
1720 expect(32, bm.bmBitsPixel);
1721 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1723 if (bm.bmBits)
1725 DWORD val = *(DWORD*)bm.bmBits;
1726 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1727 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1728 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1731 hdc = CreateCompatibleDC(NULL);
1733 oldhbitmap = SelectObject(hdc, hbitmap);
1734 pixel = GetPixel(hdc, 5, 5);
1735 expect(0x2a2a2a, pixel);
1736 pixel = GetPixel(hdc, 1, 0);
1737 expect(0x0, pixel);
1739 SelectObject(hdc, oldhbitmap);
1741 DeleteDC(hdc);
1744 DeleteObject(hbitmap);
1747 /* create HBITMAP with bkgnd colour */
1748 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1749 expect(Ok, stat);
1751 if (stat == Ok)
1753 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1754 expect(sizeof(BITMAP), ret);
1756 expect(0, bm.bmType);
1757 expect(8, bm.bmWidth);
1758 expect(20, bm.bmHeight);
1759 expect(32, bm.bmWidthBytes);
1760 expect(1, bm.bmPlanes);
1761 expect(32, bm.bmBitsPixel);
1762 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1764 if (bm.bmBits)
1766 DWORD val = *(DWORD*)bm.bmBits;
1767 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1768 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1769 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1772 hdc = CreateCompatibleDC(NULL);
1774 oldhbitmap = SelectObject(hdc, hbitmap);
1775 pixel = GetPixel(hdc, 5, 5);
1776 expect(0xc12ac1, pixel);
1777 pixel = GetPixel(hdc, 1, 0);
1778 expect(0xff00ff, pixel);
1779 pixel = GetPixel(hdc, 2, 0);
1780 expect(0xb12ac1, pixel);
1782 SelectObject(hdc, oldhbitmap);
1783 DeleteDC(hdc);
1784 DeleteObject(hbitmap);
1787 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1788 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1789 expect(Ok, stat);
1791 if (stat == Ok)
1793 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1794 expect(sizeof(BITMAP), ret);
1796 expect(0, bm.bmType);
1797 expect(8, bm.bmWidth);
1798 expect(20, bm.bmHeight);
1799 expect(32, bm.bmWidthBytes);
1800 expect(1, bm.bmPlanes);
1801 expect(32, bm.bmBitsPixel);
1802 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1804 if (bm.bmBits)
1806 DWORD val = *(DWORD*)bm.bmBits;
1807 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1808 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1809 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1812 hdc = CreateCompatibleDC(NULL);
1814 oldhbitmap = SelectObject(hdc, hbitmap);
1815 pixel = GetPixel(hdc, 5, 5);
1816 expect(0xc12ac1, pixel);
1817 pixel = GetPixel(hdc, 1, 0);
1818 expect(0xff00ff, pixel);
1819 pixel = GetPixel(hdc, 2, 0);
1820 expect(0xb12ac1, pixel);
1822 SelectObject(hdc, oldhbitmap);
1823 DeleteDC(hdc);
1824 DeleteObject(hbitmap);
1827 stat = GdipDisposeImage((GpImage*)bitmap);
1828 expect(Ok, stat);
1831 static void test_getthumbnail(void)
1833 GpStatus stat;
1834 GpImage *bitmap1, *bitmap2;
1835 UINT width, height;
1837 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1838 expect(InvalidParameter, stat);
1840 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1841 expect(Ok, stat);
1843 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1844 expect(InvalidParameter, stat);
1846 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1847 expect(Ok, stat);
1849 if (stat == Ok)
1851 stat = GdipGetImageWidth(bitmap2, &width);
1852 expect(Ok, stat);
1853 expect(120, width);
1855 stat = GdipGetImageHeight(bitmap2, &height);
1856 expect(Ok, stat);
1857 expect(120, height);
1859 GdipDisposeImage(bitmap2);
1862 GdipDisposeImage(bitmap1);
1865 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1866 expect(Ok, stat);
1868 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1869 expect(Ok, stat);
1871 if (stat == Ok)
1873 stat = GdipGetImageWidth(bitmap2, &width);
1874 expect(Ok, stat);
1875 expect(32, width);
1877 stat = GdipGetImageHeight(bitmap2, &height);
1878 expect(Ok, stat);
1879 expect(32, height);
1881 GdipDisposeImage(bitmap2);
1884 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1885 expect(Ok, stat);
1887 if (stat == Ok)
1889 stat = GdipGetImageWidth(bitmap2, &width);
1890 expect(Ok, stat);
1891 expect(120, width);
1893 stat = GdipGetImageHeight(bitmap2, &height);
1894 expect(Ok, stat);
1895 expect(120, height);
1897 GdipDisposeImage(bitmap2);
1900 GdipDisposeImage(bitmap1);
1903 static void test_getsetpixel(void)
1905 GpStatus stat;
1906 GpBitmap *bitmap;
1907 ARGB color;
1908 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1909 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1911 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1912 expect(Ok, stat);
1914 /* null parameters */
1915 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1916 expect(InvalidParameter, stat);
1918 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1919 expect(InvalidParameter, stat);
1921 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1922 expect(InvalidParameter, stat);
1924 /* out of bounds */
1925 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1926 expect(InvalidParameter, stat);
1928 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1929 expect(InvalidParameter, stat);
1931 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1932 ok(stat == InvalidParameter ||
1933 broken(stat == Ok), /* Older gdiplus */
1934 "Expected InvalidParameter, got %.8x\n", stat);
1936 if (0) /* crashes some gdiplus implementations */
1938 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1939 ok(stat == InvalidParameter ||
1940 broken(stat == Ok), /* Older gdiplus */
1941 "Expected InvalidParameter, got %.8x\n", stat);
1944 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1945 expect(InvalidParameter, stat);
1947 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1948 expect(InvalidParameter, stat);
1950 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1951 expect(InvalidParameter, stat);
1953 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1954 expect(InvalidParameter, stat);
1956 /* valid use */
1957 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1958 expect(Ok, stat);
1959 expect(0xffffffff, color);
1961 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1962 expect(Ok, stat);
1963 expect(0xff0000ff, color);
1965 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1966 expect(Ok, stat);
1968 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1969 expect(Ok, stat);
1971 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1972 expect(Ok, stat);
1973 expect(0xff676869, color);
1975 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1976 expect(Ok, stat);
1977 expect(0xff474849, color);
1979 stat = GdipDisposeImage((GpImage*)bitmap);
1980 expect(Ok, stat);
1983 static void check_halftone_palette(ColorPalette *palette)
1985 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1986 UINT i;
1988 for (i=0; i<palette->Count; i++)
1990 ARGB expected=0xff000000;
1991 if (i<8)
1993 if (i&1) expected |= 0x800000;
1994 if (i&2) expected |= 0x8000;
1995 if (i&4) expected |= 0x80;
1997 else if (i == 8)
1999 expected = 0xffc0c0c0;
2001 else if (i < 16)
2003 if (i&1) expected |= 0xff0000;
2004 if (i&2) expected |= 0xff00;
2005 if (i&4) expected |= 0xff;
2007 else if (i < 40)
2009 expected = 0x00000000;
2011 else
2013 expected |= halftone_values[(i-40)%6];
2014 expected |= halftone_values[((i-40)/6)%6] << 8;
2015 expected |= halftone_values[((i-40)/36)%6] << 16;
2017 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2018 expected, palette->Entries[i], i, palette->Count);
2022 static void test_palette(void)
2024 GpStatus stat;
2025 GpBitmap *bitmap;
2026 INT size;
2027 BYTE buffer[1040];
2028 ColorPalette *palette=(ColorPalette*)buffer;
2029 ARGB *entries = palette->Entries;
2030 ARGB color=0;
2032 /* test initial palette from non-indexed bitmap */
2033 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2034 expect(Ok, stat);
2036 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2037 expect(Ok, stat);
2038 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2040 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2041 expect(Ok, stat);
2042 expect(0, palette->Count);
2044 /* test setting palette on not-indexed bitmap */
2045 palette->Count = 3;
2047 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2048 expect(Ok, stat);
2050 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2051 expect(Ok, stat);
2052 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2054 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2055 expect(Ok, stat);
2056 expect(3, palette->Count);
2058 GdipDisposeImage((GpImage*)bitmap);
2060 /* test initial palette on 1-bit bitmap */
2061 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2062 expect(Ok, stat);
2064 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2065 expect(Ok, stat);
2066 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2068 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2069 expect(Ok, stat);
2070 expect(PaletteFlagsGrayScale, palette->Flags);
2071 expect(2, palette->Count);
2073 expect(0xff000000, entries[0]);
2074 expect(0xffffffff, entries[1]);
2076 /* test getting/setting pixels */
2077 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2078 expect(Ok, stat);
2079 expect(0xff000000, color);
2081 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2082 ok((stat == Ok) ||
2083 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2085 if (stat == Ok)
2087 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2088 expect(Ok, stat);
2089 expect(0xffffffff, color);
2092 GdipDisposeImage((GpImage*)bitmap);
2094 /* test initial palette on 4-bit bitmap */
2095 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2096 expect(Ok, stat);
2098 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2099 expect(Ok, stat);
2100 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2102 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2103 expect(Ok, stat);
2104 expect(0, palette->Flags);
2105 expect(16, palette->Count);
2107 check_halftone_palette(palette);
2109 /* test getting/setting pixels */
2110 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2111 expect(Ok, stat);
2112 expect(0xff000000, color);
2114 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2115 ok((stat == Ok) ||
2116 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2118 if (stat == Ok)
2120 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2121 expect(Ok, stat);
2122 expect(0xffff00ff, color);
2125 GdipDisposeImage((GpImage*)bitmap);
2127 /* test initial palette on 8-bit bitmap */
2128 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2129 expect(Ok, stat);
2131 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2132 expect(Ok, stat);
2133 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2135 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2136 expect(Ok, stat);
2137 expect(PaletteFlagsHalftone, palette->Flags);
2138 expect(256, palette->Count);
2140 check_halftone_palette(palette);
2142 /* test getting/setting pixels */
2143 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2144 expect(Ok, stat);
2145 expect(0xff000000, color);
2147 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2148 ok((stat == Ok) ||
2149 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2151 if (stat == Ok)
2153 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2154 expect(Ok, stat);
2155 expect(0xffcccccc, color);
2158 /* test setting/getting a different palette */
2159 entries[1] = 0xffcccccc;
2161 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2162 expect(Ok, stat);
2164 entries[1] = 0;
2166 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2167 expect(Ok, stat);
2168 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2170 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2171 expect(Ok, stat);
2172 expect(PaletteFlagsHalftone, palette->Flags);
2173 expect(256, palette->Count);
2174 expect(0xffcccccc, entries[1]);
2176 /* test count < 256 */
2177 palette->Flags = 12345;
2178 palette->Count = 3;
2180 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2181 expect(Ok, stat);
2183 entries[1] = 0;
2184 entries[3] = 0xdeadbeef;
2186 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2187 expect(Ok, stat);
2188 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2190 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2191 expect(Ok, stat);
2192 expect(12345, palette->Flags);
2193 expect(3, palette->Count);
2194 expect(0xffcccccc, entries[1]);
2195 expect(0xdeadbeef, entries[3]);
2197 /* test count > 256 */
2198 palette->Count = 257;
2200 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2201 ok(stat == InvalidParameter ||
2202 broken(stat == Ok), /* Old gdiplus behavior */
2203 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2205 GdipDisposeImage((GpImage*)bitmap);
2208 static void test_colormatrix(void)
2210 GpStatus stat;
2211 ColorMatrix colormatrix, graymatrix;
2212 GpImageAttributes *imageattr;
2213 const ColorMatrix identity = {{
2214 {1.0,0.0,0.0,0.0,0.0},
2215 {0.0,1.0,0.0,0.0,0.0},
2216 {0.0,0.0,1.0,0.0,0.0},
2217 {0.0,0.0,0.0,1.0,0.0},
2218 {0.0,0.0,0.0,0.0,1.0}}};
2219 const ColorMatrix double_red = {{
2220 {2.0,0.0,0.0,0.0,0.0},
2221 {0.0,1.0,0.0,0.0,0.0},
2222 {0.0,0.0,1.0,0.0,0.0},
2223 {0.0,0.0,0.0,1.0,0.0},
2224 {0.0,0.0,0.0,0.0,1.0}}};
2225 const ColorMatrix asymmetric = {{
2226 {0.0,1.0,0.0,0.0,0.0},
2227 {0.0,0.0,1.0,0.0,0.0},
2228 {0.0,0.0,0.0,1.0,0.0},
2229 {1.0,0.0,0.0,0.0,0.0},
2230 {0.0,0.0,0.0,0.0,1.0}}};
2231 GpBitmap *bitmap1, *bitmap2;
2232 GpGraphics *graphics;
2233 ARGB color;
2235 colormatrix = identity;
2236 graymatrix = identity;
2238 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2239 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2240 expect(InvalidParameter, stat);
2242 stat = GdipCreateImageAttributes(&imageattr);
2243 expect(Ok, stat);
2245 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2246 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2247 expect(Ok, stat);
2249 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2250 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2251 expect(InvalidParameter, stat);
2253 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2254 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2255 expect(Ok, stat);
2257 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2258 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2259 expect(Ok, stat);
2261 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2262 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2263 expect(InvalidParameter, stat);
2265 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2266 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2267 expect(Ok, stat);
2269 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2270 TRUE, &colormatrix, &graymatrix, 3);
2271 expect(InvalidParameter, stat);
2273 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2274 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2275 expect(InvalidParameter, stat);
2277 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2278 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2279 expect(InvalidParameter, stat);
2281 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2282 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2283 expect(Ok, stat);
2285 /* Drawing a bitmap transforms the colors */
2286 colormatrix = double_red;
2287 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2288 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2289 expect(Ok, stat);
2291 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2292 expect(Ok, stat);
2294 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2295 expect(Ok, stat);
2297 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2298 expect(Ok, stat);
2300 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2301 expect(Ok, stat);
2303 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2304 UnitPixel, imageattr, NULL, NULL);
2305 expect(Ok, stat);
2307 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2308 expect(Ok, stat);
2309 expect(0xff80ccee, color);
2311 colormatrix = asymmetric;
2312 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2313 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2314 expect(Ok, stat);
2316 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2317 expect(Ok, stat);
2319 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2320 UnitPixel, imageattr, NULL, NULL);
2321 expect(Ok, stat);
2323 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2324 expect(Ok, stat);
2325 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2327 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2328 expect(Ok, stat);
2330 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2331 UnitPixel, imageattr, NULL, NULL);
2332 expect(Ok, stat);
2334 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2335 expect(Ok, stat);
2336 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2338 GdipDeleteGraphics(graphics);
2339 GdipDisposeImage((GpImage*)bitmap1);
2340 GdipDisposeImage((GpImage*)bitmap2);
2341 GdipDisposeImageAttributes(imageattr);
2344 static void test_gamma(void)
2346 GpStatus stat;
2347 GpImageAttributes *imageattr;
2348 GpBitmap *bitmap1, *bitmap2;
2349 GpGraphics *graphics;
2350 ARGB color;
2352 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2353 expect(InvalidParameter, stat);
2355 stat = GdipCreateImageAttributes(&imageattr);
2356 expect(Ok, stat);
2358 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2359 expect(Ok, stat);
2361 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2362 expect(InvalidParameter, stat);
2364 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2365 expect(InvalidParameter, stat);
2367 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2368 expect(InvalidParameter, stat);
2370 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2371 expect(Ok, stat);
2373 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2374 expect(Ok, stat);
2376 /* Drawing a bitmap transforms the colors */
2377 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2378 expect(Ok, stat);
2380 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2381 expect(Ok, stat);
2383 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2384 expect(Ok, stat);
2386 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2387 expect(Ok, stat);
2389 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2390 expect(Ok, stat);
2392 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2393 UnitPixel, imageattr, NULL, NULL);
2394 expect(Ok, stat);
2396 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2397 expect(Ok, stat);
2398 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2400 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2401 expect(Ok, stat);
2403 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2404 UnitPixel, imageattr, NULL, NULL);
2405 expect(Ok, stat);
2407 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2408 expect(Ok, stat);
2409 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2411 GdipDeleteGraphics(graphics);
2412 GdipDisposeImage((GpImage*)bitmap1);
2413 GdipDisposeImage((GpImage*)bitmap2);
2414 GdipDisposeImageAttributes(imageattr);
2417 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2418 static const unsigned char gifanimation[72] = {
2419 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2420 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2421 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2422 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2423 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2426 /* Generated with ImageMagick:
2427 * convert -transparent black -delay 100 -size 8x2 xc:black \
2428 * -dispose none -page +0+0 -size 2x2 xc:red \
2429 * -dispose background -page +2+0 -size 2x2 xc:blue \
2430 * -dispose previous -page +4+0 -size 2x2 xc:green \
2431 * -dispose undefined -page +6+0 -size 2x2 xc:gray \
2432 * test.gif
2434 static const unsigned char gifanimation2[] = {
2435 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2436 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2437 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2438 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2439 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2440 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2441 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2442 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2443 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2444 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2445 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2446 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2447 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2448 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2449 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2450 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2451 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2452 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2453 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2454 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2455 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2456 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2457 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2458 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2459 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2460 0x3b
2463 static ARGB gifanimation2_pixels[5][4] = {
2464 {0, 0, 0, 0},
2465 {0xffff0000, 0, 0, 0},
2466 {0xffff0000, 0xff0000ff, 0, 0},
2467 {0xffff0000, 0, 0xff008000, 0},
2468 {0xffff0000, 0, 0, 0xff7e7e7e}
2471 static void test_multiframegif(void)
2473 LPSTREAM stream;
2474 HGLOBAL hglob;
2475 LPBYTE data;
2476 HRESULT hres;
2477 GpStatus stat;
2478 GpBitmap *bmp;
2479 ARGB color;
2480 UINT count;
2481 GUID dimension;
2482 PixelFormat pixel_format;
2483 INT palette_size, i, j;
2485 /* Test frame functions with an animated GIF */
2486 hglob = GlobalAlloc (0, sizeof(gifanimation));
2487 data = GlobalLock (hglob);
2488 memcpy(data, gifanimation, sizeof(gifanimation));
2489 GlobalUnlock(hglob);
2491 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2492 ok(hres == S_OK, "Failed to create a stream\n");
2493 if(hres != S_OK) return;
2495 stat = GdipCreateBitmapFromStream(stream, &bmp);
2496 ok(stat == Ok, "Failed to create a Bitmap\n");
2497 if(stat != Ok){
2498 IStream_Release(stream);
2499 return;
2502 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2503 expect(Ok, stat);
2504 expect(PixelFormat32bppARGB, pixel_format);
2506 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2507 expect(Ok, stat);
2508 ok(palette_size == sizeof(ColorPalette) ||
2509 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2510 "palette_size = %d\n", palette_size);
2512 /* Bitmap starts at frame 0 */
2513 color = 0xdeadbeef;
2514 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2515 expect(Ok, stat);
2516 expect(0xffffffff, color);
2518 /* Check that we get correct metadata */
2519 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2520 expect(Ok, stat);
2521 expect(1, count);
2523 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2524 expect(Ok, stat);
2525 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2527 count = 12345;
2528 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2529 expect(Ok, stat);
2530 expect(2, count);
2532 /* SelectActiveFrame overwrites our current data */
2533 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2534 expect(Ok, stat);
2536 color = 0xdeadbeef;
2537 GdipBitmapGetPixel(bmp, 0, 0, &color);
2538 expect(Ok, stat);
2539 expect(0xff000000, color);
2541 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2542 expect(Ok, stat);
2544 color = 0xdeadbeef;
2545 GdipBitmapGetPixel(bmp, 0, 0, &color);
2546 expect(Ok, stat);
2547 expect(0xffffffff, color);
2549 /* Write over the image data */
2550 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2551 expect(Ok, stat);
2553 /* Switching to the same frame does not overwrite our changes */
2554 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2555 expect(Ok, stat);
2557 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2558 expect(Ok, stat);
2559 expect(0xff000000, color);
2561 /* But switching to another frame and back does */
2562 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2563 expect(Ok, stat);
2565 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2566 expect(Ok, stat);
2568 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2569 expect(Ok, stat);
2570 expect(0xffffffff, color);
2572 /* rotate/flip discards the information about other frames */
2573 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2574 expect(Ok, stat);
2576 count = 12345;
2577 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2578 expect(Ok, stat);
2579 expect(1, count);
2581 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2583 GdipDisposeImage((GpImage*)bmp);
2584 IStream_Release(stream);
2586 /* Test with a non-animated gif */
2587 hglob = GlobalAlloc (0, sizeof(gifimage));
2588 data = GlobalLock (hglob);
2589 memcpy(data, gifimage, sizeof(gifimage));
2590 GlobalUnlock(hglob);
2592 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2593 ok(hres == S_OK, "Failed to create a stream\n");
2594 if(hres != S_OK) return;
2596 stat = GdipCreateBitmapFromStream(stream, &bmp);
2597 ok(stat == Ok, "Failed to create a Bitmap\n");
2598 if(stat != Ok){
2599 IStream_Release(stream);
2600 return;
2603 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2604 expect(Ok, stat);
2605 expect(PixelFormat8bppIndexed, pixel_format);
2607 /* Check metadata */
2608 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2609 expect(Ok, stat);
2610 expect(1, count);
2612 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2613 expect(Ok, stat);
2614 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2616 count = 12345;
2617 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2618 expect(Ok, stat);
2619 expect(1, count);
2621 GdipDisposeImage((GpImage*)bmp);
2622 IStream_Release(stream);
2624 /* Test frame dispose methods */
2625 hglob = GlobalAlloc (0, sizeof(gifanimation2));
2626 data = GlobalLock (hglob);
2627 memcpy(data, gifanimation2, sizeof(gifanimation2));
2628 GlobalUnlock(hglob);
2630 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2631 ok(hres == S_OK, "Failed to create a stream\n");
2633 stat = GdipCreateBitmapFromStream(stream, &bmp);
2634 ok(stat == Ok, "Failed to create a Bitmap\n");
2635 IStream_Release(stream);
2637 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2638 expect(Ok, stat);
2639 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2641 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2642 expect(Ok, stat);
2643 expect(5, count);
2645 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2646 expect(Ok, stat);
2647 expect(0, color);
2649 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2650 stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2651 expect(Ok, stat);
2652 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2653 if(color != 0) {
2654 win_skip("broken animated gif support\n");
2655 GdipDisposeImage((GpImage*)bmp);
2656 return;
2659 for(i=0; i<6; i++) {
2660 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2661 expect(Ok, stat);
2663 for(j=0; j<4; j++) {
2664 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2665 expect(Ok, stat);
2666 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2670 GdipDisposeImage((GpImage*)bmp);
2673 static void test_rotateflip(void)
2675 GpImage *bitmap;
2676 GpStatus stat;
2677 BYTE bits[24];
2678 static const BYTE orig_bits[24] = {
2679 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2680 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2681 UINT width, height;
2682 ARGB color;
2684 memcpy(bits, orig_bits, sizeof(bits));
2685 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2686 expect(Ok, stat);
2688 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2689 expect(Ok, stat);
2691 stat = GdipGetImageWidth(bitmap, &width);
2692 expect(Ok, stat);
2693 stat = GdipGetImageHeight(bitmap, &height);
2694 expect(Ok, stat);
2695 expect(2, width);
2696 expect(3, height);
2698 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2699 expect(Ok, stat);
2700 expect(0xff00ffff, color);
2702 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2703 expect(Ok, stat);
2704 expect(0xffff0000, color);
2706 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2707 expect(Ok, stat);
2708 expect(0xffffff00, color);
2710 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2711 expect(Ok, stat);
2712 expect(0xff0000ff, color);
2714 expect(0, bits[0]);
2715 expect(0, bits[1]);
2716 expect(0xff, bits[2]);
2718 GdipDisposeImage(bitmap);
2720 memcpy(bits, orig_bits, sizeof(bits));
2721 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2722 expect(Ok, stat);
2724 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2725 expect(Ok, stat);
2727 stat = GdipGetImageWidth(bitmap, &width);
2728 expect(Ok, stat);
2729 stat = GdipGetImageHeight(bitmap, &height);
2730 expect(Ok, stat);
2731 expect(3, width);
2732 expect(2, height);
2734 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2735 expect(Ok, stat);
2736 expect(0xff0000ff, color);
2738 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2739 expect(Ok, stat);
2740 expect(0xffff0000, color);
2742 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2743 expect(Ok, stat);
2744 expect(0xffffff00, color);
2746 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2747 expect(Ok, stat);
2748 expect(0xff00ffff, color);
2750 expect(0, bits[0]);
2751 expect(0, bits[1]);
2752 expect(0xff, bits[2]);
2754 GdipDisposeImage(bitmap);
2756 memcpy(bits, orig_bits, sizeof(bits));
2757 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2758 expect(Ok, stat);
2760 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2761 expect(Ok, stat);
2763 stat = GdipGetImageWidth(bitmap, &width);
2764 expect(Ok, stat);
2765 stat = GdipGetImageHeight(bitmap, &height);
2766 expect(Ok, stat);
2767 expect(3, width);
2768 expect(2, height);
2770 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2771 expect(Ok, stat);
2772 expect(0xff00ffff, color);
2774 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2775 expect(Ok, stat);
2776 expect(0xffffff00, color);
2778 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2779 expect(Ok, stat);
2780 expect(0xffff0000, color);
2782 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2783 expect(Ok, stat);
2784 expect(0xff0000ff, color);
2786 expect(0, bits[0]);
2787 expect(0, bits[1]);
2788 expect(0xff, bits[2]);
2790 GdipDisposeImage(bitmap);
2793 static void test_remaptable(void)
2795 GpStatus stat;
2796 GpImageAttributes *imageattr;
2797 GpBitmap *bitmap1, *bitmap2;
2798 GpGraphics *graphics;
2799 ARGB color;
2800 ColorMap *map;
2802 map = GdipAlloc(sizeof(ColorMap));
2804 map->oldColor.Argb = 0xff00ff00;
2805 map->newColor.Argb = 0xffff00ff;
2807 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2808 expect(InvalidParameter, stat);
2810 stat = GdipCreateImageAttributes(&imageattr);
2811 expect(Ok, stat);
2813 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2814 expect(InvalidParameter, stat);
2816 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2817 expect(InvalidParameter, stat);
2819 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2820 expect(InvalidParameter, stat);
2822 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2823 expect(InvalidParameter, stat);
2825 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2826 expect(Ok, stat);
2828 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2829 expect(Ok, stat);
2831 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2832 expect(Ok, stat);
2834 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2835 expect(Ok, stat);
2837 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2838 expect(Ok, stat);
2840 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2841 expect(Ok, stat);
2843 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2844 UnitPixel, imageattr, NULL, NULL);
2845 expect(Ok, stat);
2847 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2848 expect(Ok, stat);
2849 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2851 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2852 expect(Ok, stat);
2854 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2855 UnitPixel, imageattr, NULL, NULL);
2856 expect(Ok, stat);
2858 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2859 expect(Ok, stat);
2860 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
2862 GdipDeleteGraphics(graphics);
2863 GdipDisposeImage((GpImage*)bitmap1);
2864 GdipDisposeImage((GpImage*)bitmap2);
2865 GdipDisposeImageAttributes(imageattr);
2866 GdipFree(map);
2869 static void test_colorkey(void)
2871 GpStatus stat;
2872 GpImageAttributes *imageattr;
2873 GpBitmap *bitmap1, *bitmap2;
2874 GpGraphics *graphics;
2875 ARGB color;
2877 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2878 expect(InvalidParameter, stat);
2880 stat = GdipCreateImageAttributes(&imageattr);
2881 expect(Ok, stat);
2883 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2884 expect(InvalidParameter, stat);
2886 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2887 expect(InvalidParameter, stat);
2889 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2890 expect(Ok, stat);
2892 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2893 expect(Ok, stat);
2895 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2896 expect(Ok, stat);
2898 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2899 expect(Ok, stat);
2901 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2902 expect(Ok, stat);
2904 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
2905 expect(Ok, stat);
2907 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
2908 expect(Ok, stat);
2910 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2911 expect(Ok, stat);
2913 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2914 UnitPixel, imageattr, NULL, NULL);
2915 expect(Ok, stat);
2917 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2918 expect(Ok, stat);
2919 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2921 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2922 expect(Ok, stat);
2923 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2925 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2926 expect(Ok, stat);
2927 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2929 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2930 expect(Ok, stat);
2931 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
2933 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2934 expect(Ok, stat);
2936 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2937 UnitPixel, imageattr, NULL, NULL);
2938 expect(Ok, stat);
2940 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2941 expect(Ok, stat);
2942 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
2944 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2945 expect(Ok, stat);
2946 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
2948 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2949 expect(Ok, stat);
2950 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
2952 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2953 expect(Ok, stat);
2954 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
2957 GdipDeleteGraphics(graphics);
2958 GdipDisposeImage((GpImage*)bitmap1);
2959 GdipDisposeImage((GpImage*)bitmap2);
2960 GdipDisposeImageAttributes(imageattr);
2963 static void test_dispose(void)
2965 GpStatus stat;
2966 GpImage *image;
2967 char invalid_image[256];
2969 stat = GdipDisposeImage(NULL);
2970 expect(InvalidParameter, stat);
2972 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
2973 expect(Ok, stat);
2975 stat = GdipDisposeImage(image);
2976 expect(Ok, stat);
2978 stat = GdipDisposeImage(image);
2979 expect(ObjectBusy, stat);
2981 memset(invalid_image, 0, 256);
2982 stat = GdipDisposeImage((GpImage*)invalid_image);
2983 expect(ObjectBusy, stat);
2986 static LONG obj_refcount(void *obj)
2988 IUnknown_AddRef((IUnknown *)obj);
2989 return IUnknown_Release((IUnknown *)obj);
2992 static GpImage *load_image(const BYTE *image_data, UINT image_size)
2994 IStream *stream;
2995 HGLOBAL hmem;
2996 BYTE *data;
2997 HRESULT hr;
2998 GpStatus status;
2999 GpImage *image = NULL, *clone;
3000 ImageType image_type;
3001 LONG refcount, old_refcount;
3003 hmem = GlobalAlloc(0, image_size);
3004 data = GlobalLock(hmem);
3005 memcpy(data, image_data, image_size);
3006 GlobalUnlock(hmem);
3008 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3009 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3010 if (hr != S_OK) return NULL;
3012 refcount = obj_refcount(stream);
3013 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3015 status = GdipLoadImageFromStream(stream, &image);
3016 ok(status == Ok || broken(status == InvalidParameter), /* XP */
3017 "GdipLoadImageFromStream error %d\n", status);
3018 if (status != Ok)
3020 IStream_Release(stream);
3021 return NULL;
3024 status = GdipGetImageType(image, &image_type);
3025 ok(status == Ok, "GdipGetImageType error %d\n", status);
3027 refcount = obj_refcount(stream);
3028 if (image_type == ImageTypeBitmap)
3029 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3030 else
3031 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3032 old_refcount = refcount;
3034 status = GdipCloneImage(image, &clone);
3035 ok(status == Ok, "GdipCloneImage error %d\n", status);
3036 refcount = obj_refcount(stream);
3037 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3038 status = GdipDisposeImage(clone);
3039 ok(status == Ok, "GdipDisposeImage error %d\n", status);
3040 refcount = obj_refcount(stream);
3041 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3043 refcount = IStream_Release(stream);
3044 if (image_type == ImageTypeBitmap)
3045 ok(refcount >= 1, "expected stream refcount != 0\n");
3046 else
3047 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3049 return image;
3052 static void test_image_properties(void)
3054 static const struct test_data
3056 const BYTE *image_data;
3057 UINT image_size;
3058 ImageType image_type;
3059 UINT prop_count;
3060 UINT prop_count2; /* if win7 behaves differently */
3061 /* 1st property attributes */
3062 UINT prop_size;
3063 UINT prop_size2; /* if win7 behaves differently */
3064 UINT prop_id;
3065 UINT prop_id2; /* if win7 behaves differently */
3067 td[] =
3069 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3070 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3071 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3072 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3073 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3075 GpStatus status;
3076 GpImage *image;
3077 UINT prop_count, prop_size, i;
3078 PROPID prop_id[16] = { 0 };
3079 ImageType image_type;
3080 union
3082 PropertyItem data;
3083 char buf[256];
3084 } item;
3086 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3088 image = load_image(td[i].image_data, td[i].image_size);
3089 if (!image)
3091 trace("%u: failed to load image data\n", i);
3092 continue;
3095 status = GdipGetImageType(image, &image_type);
3096 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3097 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3098 i, td[i].image_type, image_type);
3100 status = GdipGetPropertyCount(image, &prop_count);
3101 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3102 if (td[i].image_data == pngimage || td[i].image_data == jpgimage)
3103 todo_wine
3104 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3105 " %u: expected property count %u or %u, got %u\n",
3106 i, td[i].prop_count, td[i].prop_count2, prop_count);
3107 else
3108 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3109 " %u: expected property count %u or %u, got %u\n",
3110 i, td[i].prop_count, td[i].prop_count2, prop_count);
3112 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3113 expect(InvalidParameter, status);
3114 status = GdipGetPropertyItemSize(image, 0, NULL);
3115 expect(InvalidParameter, status);
3116 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3117 if (image_type == ImageTypeMetafile)
3118 expect(NotImplemented, status);
3119 else
3120 expect(PropertyNotFound, status);
3122 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3123 expect(InvalidParameter, status);
3124 status = GdipGetPropertyItem(image, 0, 0, NULL);
3125 expect(InvalidParameter, status);
3126 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3127 if (image_type == ImageTypeMetafile)
3128 expect(NotImplemented, status);
3129 else
3130 expect(PropertyNotFound, status);
3132 /* FIXME: remove once Wine is fixed */
3133 if (td[i].prop_count != prop_count)
3135 GdipDisposeImage(image);
3136 continue;
3139 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3140 expect(InvalidParameter, status);
3141 status = GdipGetPropertyIdList(image, prop_count, NULL);
3142 expect(InvalidParameter, status);
3143 status = GdipGetPropertyIdList(image, 0, prop_id);
3144 if (image_type == ImageTypeMetafile)
3145 expect(NotImplemented, status);
3146 else if (prop_count == 0)
3147 expect(Ok, status);
3148 else
3149 expect(InvalidParameter, status);
3150 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3151 if (image_type == ImageTypeMetafile)
3152 expect(NotImplemented, status);
3153 else
3154 expect(InvalidParameter, status);
3155 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3156 if (image_type == ImageTypeMetafile)
3157 expect(NotImplemented, status);
3158 else
3159 expect(InvalidParameter, status);
3160 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3161 if (image_type == ImageTypeMetafile)
3162 expect(NotImplemented, status);
3163 else
3165 expect(Ok, status);
3166 if (prop_count != 0)
3167 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3168 " %u: expected property id %#x or %#x, got %#x\n",
3169 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3172 if (status == Ok)
3174 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3175 if (prop_count == 0)
3176 expect(PropertyNotFound, status);
3177 else
3179 expect(Ok, status);
3181 assert(sizeof(item) >= prop_size);
3182 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3183 i, prop_size);
3184 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3185 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3186 " %u: expected property size %u or %u, got %u\n",
3187 i, td[i].prop_size, td[i].prop_size2, prop_size);
3189 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3190 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3191 "%u: expected InvalidParameter, got %d\n", i, status);
3192 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3193 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3194 "%u: expected InvalidParameter, got %d\n", i, status);
3195 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3196 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3197 "%u: expected InvalidParameter, got %d\n", i, status);
3198 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3199 expect(Ok, status);
3200 ok(prop_id[0] == item.data.id,
3201 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3205 GdipDisposeImage(image);
3209 #define IFD_BYTE 1
3210 #define IFD_ASCII 2
3211 #define IFD_SHORT 3
3212 #define IFD_LONG 4
3213 #define IFD_RATIONAL 5
3214 #define IFD_SBYTE 6
3215 #define IFD_UNDEFINED 7
3216 #define IFD_SSHORT 8
3217 #define IFD_SLONG 9
3218 #define IFD_SRATIONAL 10
3219 #define IFD_FLOAT 11
3220 #define IFD_DOUBLE 12
3222 #ifndef PropertyTagTypeSByte
3223 #define PropertyTagTypeSByte 6
3224 #define PropertyTagTypeSShort 8
3225 #define PropertyTagTypeFloat 11
3226 #define PropertyTagTypeDouble 12
3227 #endif
3229 static UINT documented_type(UINT type)
3231 switch (type)
3233 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3234 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3235 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3236 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3237 default: return type;
3241 #include "pshpack2.h"
3242 struct IFD_entry
3244 SHORT id;
3245 SHORT type;
3246 ULONG count;
3247 LONG value;
3250 struct IFD_rational
3252 LONG numerator;
3253 LONG denominator;
3256 static const struct tiff_data
3258 USHORT byte_order;
3259 USHORT version;
3260 ULONG dir_offset;
3261 USHORT number_of_entries;
3262 struct IFD_entry entry[40];
3263 ULONG next_IFD;
3264 struct IFD_rational xres;
3265 DOUBLE double_val;
3266 struct IFD_rational srational_val;
3267 char string[14];
3268 SHORT short_val[4];
3269 LONG long_val[2];
3270 FLOAT float_val[2];
3271 struct IFD_rational rational[3];
3272 BYTE pixel_data[4];
3273 } TIFF_data =
3275 #ifdef WORDS_BIGENDIAN
3276 'M' | 'M' << 8,
3277 #else
3278 'I' | 'I' << 8,
3279 #endif
3281 FIELD_OFFSET(struct tiff_data, number_of_entries),
3284 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3285 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3286 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3287 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3288 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3289 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3290 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3291 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3292 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3293 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3294 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3295 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3296 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3297 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3298 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3299 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3300 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3301 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3302 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3303 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3304 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3305 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3306 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3307 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3308 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3309 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3310 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3311 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3312 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3313 /* Some gdiplus versions ignore these fields.
3314 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3315 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3316 { 0xf014, IFD_LONG, 0, 0x11223344 },
3317 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3318 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3319 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3320 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3323 { 900, 3 },
3324 1234567890.0987654321,
3325 { 0x1a2b3c4d, 0x5a6b7c8d },
3326 "Hello World!",
3327 { 0x0101, 0x0202, 0x0303, 0x0404 },
3328 { 0x11223344, 0x55667788 },
3329 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3330 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3331 { 0x11, 0x22, 0x33, 0 }
3333 #include "poppack.h"
3335 static void test_tiff_properties(void)
3337 static const struct test_data
3339 ULONG type, id, length;
3340 const BYTE value[24];
3341 } td[31] =
3343 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3344 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3345 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3346 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3347 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3348 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3349 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3350 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3351 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3352 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3353 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3354 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3355 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3356 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3357 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3358 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3359 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3360 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3361 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3362 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3363 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3364 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3365 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3366 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3367 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3368 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3369 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3370 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3371 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3372 { PropertyTagTypeSRational, 0xf016, 24,
3373 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3374 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3375 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3376 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3377 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3379 GpStatus status;
3380 GpImage *image;
3381 GUID guid;
3382 UINT dim_count, frame_count, prop_count, prop_size, i;
3383 PROPID *prop_id;
3384 PropertyItem *prop_item;
3386 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3387 if (!image)
3389 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3390 return;
3393 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3394 expect(Ok, status);
3395 expect(1, dim_count);
3397 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3398 expect(Ok, status);
3399 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3401 frame_count = 0xdeadbeef;
3402 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3403 expect(Ok, status);
3404 expect(1, frame_count);
3406 prop_count = 0xdeadbeef;
3407 status = GdipGetPropertyCount(image, &prop_count);
3408 expect(Ok, status);
3409 ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3410 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3411 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3413 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3415 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3416 expect(Ok, status);
3418 for (i = 0; i < prop_count; i++)
3420 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3421 expect(Ok, status);
3422 if (status != Ok) break;
3423 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3425 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3426 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3427 expect(Ok, status);
3428 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3429 ok(td[i].type == prop_item->type ||
3430 /* Win7 stopped using proper but not documented types, and it
3431 looks broken since TypeFloat and TypeDouble now reported as
3432 TypeUndefined, and signed types reported as unsigned. */
3433 broken(prop_item->type == documented_type(td[i].type)),
3434 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3435 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3436 prop_size -= sizeof(*prop_item);
3437 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3438 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3439 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3440 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3441 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3442 if (td[i].length == prop_item->length)
3444 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3445 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3446 if (!match)
3448 UINT j;
3449 BYTE *data = prop_item->value;
3450 trace("id %#x:", prop_item->id);
3451 for (j = 0; j < prop_item->length; j++)
3452 trace(" %02x", data[j]);
3453 trace("\n");
3456 HeapFree(GetProcessHeap(), 0, prop_item);
3459 HeapFree(GetProcessHeap(), 0, prop_id);
3461 GdipDisposeImage(image);
3464 static void test_GdipGetAllPropertyItems(void)
3466 static const struct test_data
3468 ULONG type, id, length;
3469 BYTE value[32];
3470 } td[16] =
3472 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3473 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3474 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3475 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3476 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3477 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3478 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3479 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3480 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3481 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3482 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3483 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3484 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3485 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3486 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3487 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3489 GpStatus status;
3490 GpImage *image;
3491 GUID guid;
3492 UINT dim_count, frame_count, prop_count, prop_size, i;
3493 UINT total_size, total_count;
3494 PROPID *prop_id;
3495 PropertyItem *prop_item;
3496 const char *item_data;
3498 image = load_image(tiffimage, sizeof(tiffimage));
3499 ok(image != 0, "Failed to load TIFF image data\n");
3500 if (!image) return;
3502 dim_count = 0xdeadbeef;
3503 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3504 expect(Ok, status);
3505 expect(1, dim_count);
3507 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3508 expect(Ok, status);
3509 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3511 frame_count = 0xdeadbeef;
3512 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3513 expect(Ok, status);
3514 expect(1, frame_count);
3516 prop_count = 0xdeadbeef;
3517 status = GdipGetPropertyCount(image, &prop_count);
3518 expect(Ok, status);
3519 ok(prop_count == sizeof(td)/sizeof(td[0]),
3520 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3522 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3524 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3525 expect(Ok, status);
3527 prop_size = 0;
3528 for (i = 0; i < prop_count; i++)
3530 UINT size;
3531 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3532 expect(Ok, status);
3533 if (status != Ok) break;
3534 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3536 prop_size += size;
3538 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3539 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3540 expect(Ok, status);
3541 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3542 ok(td[i].type == prop_item->type,
3543 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3544 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3545 size -= sizeof(*prop_item);
3546 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3547 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3548 if (td[i].length == prop_item->length)
3550 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3551 ok(match, "%u: data mismatch\n", i);
3552 if (!match)
3554 UINT j;
3555 BYTE *data = prop_item->value;
3556 trace("id %#x:", prop_item->id);
3557 for (j = 0; j < prop_item->length; j++)
3558 trace(" %02x", data[j]);
3559 trace("\n");
3562 HeapFree(GetProcessHeap(), 0, prop_item);
3565 HeapFree(GetProcessHeap(), 0, prop_id);
3567 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3568 expect(InvalidParameter, status);
3569 status = GdipGetPropertySize(image, &total_size, NULL);
3570 expect(InvalidParameter, status);
3571 status = GdipGetPropertySize(image, NULL, &total_count);
3572 expect(InvalidParameter, status);
3573 status = GdipGetPropertySize(image, NULL, NULL);
3574 expect(InvalidParameter, status);
3575 total_size = 0xdeadbeef;
3576 total_count = 0xdeadbeef;
3577 status = GdipGetPropertySize(image, &total_size, &total_count);
3578 expect(Ok, status);
3579 ok(prop_count == total_count,
3580 "expected total property count %u, got %u\n", prop_count, total_count);
3581 ok(prop_size == total_size,
3582 "expected total property size %u, got %u\n", prop_size, total_size);
3584 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3586 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3587 expect(InvalidParameter, status);
3588 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3589 expect(InvalidParameter, status);
3590 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3591 expect(InvalidParameter, status);
3592 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3593 expect(InvalidParameter, status);
3594 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3595 expect(InvalidParameter, status);
3596 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3597 expect(InvalidParameter, status);
3598 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3599 expect(Ok, status);
3601 item_data = (const char *)(prop_item + prop_count);
3602 for (i = 0; i < prop_count; i++)
3604 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3605 i, item_data, prop_item[i].value);
3606 ok(td[i].type == prop_item[i].type,
3607 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3608 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3609 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3610 if (td[i].length == prop_item[i].length)
3612 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3613 ok(match, "%u: data mismatch\n", i);
3614 if (!match)
3616 UINT j;
3617 BYTE *data = prop_item[i].value;
3618 trace("id %#x:", prop_item[i].id);
3619 for (j = 0; j < prop_item[i].length; j++)
3620 trace(" %02x", data[j]);
3621 trace("\n");
3624 item_data += prop_item[i].length;
3627 HeapFree(GetProcessHeap(), 0, prop_item);
3629 GdipDisposeImage(image);
3632 static void test_tiff_palette(void)
3634 GpStatus status;
3635 GpImage *image;
3636 PixelFormat format;
3637 INT size;
3638 struct
3640 ColorPalette pal;
3641 ARGB entry[256];
3642 } palette;
3643 ARGB *entries = palette.pal.Entries;
3645 /* 1bpp TIFF without palette */
3646 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3647 if (!image)
3649 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3650 return;
3653 status = GdipGetImagePixelFormat(image, &format);
3654 expect(Ok, status);
3655 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3657 status = GdipGetImagePaletteSize(image, &size);
3658 ok(status == Ok || broken(status == GenericError), /* XP */
3659 "GdipGetImagePaletteSize error %d\n", status);
3660 if (status == GenericError)
3662 GdipDisposeImage(image);
3663 return;
3665 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3667 status = GdipGetImagePalette(image, &palette.pal, size);
3668 expect(Ok, status);
3669 expect(0, palette.pal.Flags);
3670 expect(2, palette.pal.Count);
3671 if (palette.pal.Count == 2)
3673 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3674 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3677 GdipDisposeImage(image);
3680 static void test_bitmapbits(void)
3682 /* 8 x 2 bitmap */
3683 static const BYTE pixels_24[48] =
3685 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3686 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3687 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3688 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3690 static const BYTE pixels_00[48] =
3692 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3693 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3694 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3695 0,0,0, 0,0,0, 0,0,0, 0,0,0
3697 static const BYTE pixels_24_77[64] =
3699 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3700 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3701 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3702 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3703 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3704 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3706 static const BYTE pixels_77[64] =
3708 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3709 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3710 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3711 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3712 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3713 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3714 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3715 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3717 static const BYTE pixels_8[16] =
3719 0x01,0,0x01,0,0x01,0,0x01,0,
3720 0x01,0,0x01,0,0x01,0,0x01,0
3722 static const BYTE pixels_8_77[64] =
3724 0x01,0,0x01,0,0x01,0,0x01,0,
3725 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3726 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3727 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3728 0x01,0,0x01,0,0x01,0,0x01,0,
3729 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3730 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3731 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3733 static const BYTE pixels_1_77[64] =
3735 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3736 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3737 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3738 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3739 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3740 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3741 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3742 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3744 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3745 static const struct test_data
3747 PixelFormat format;
3748 UINT bpp;
3749 ImageLockMode mode;
3750 UINT stride, size;
3751 const BYTE *pixels;
3752 const BYTE *pixels_unlocked;
3753 } td[] =
3755 /* 0 */
3756 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3758 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3759 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3760 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3761 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3762 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3763 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3764 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3765 /* 8 */
3766 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3767 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3768 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3769 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3770 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3771 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3772 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3773 /* 15 */
3774 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3775 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3776 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3777 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3778 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3779 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3780 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3782 BYTE buf[64];
3783 GpStatus status;
3784 GpBitmap *bitmap;
3785 UINT i;
3786 BitmapData data;
3787 struct
3789 ColorPalette pal;
3790 ARGB entries[1];
3791 } palette;
3792 ARGB *entries = palette.pal.Entries;
3794 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3796 BYTE pixels[sizeof(pixels_24)];
3797 memcpy(pixels, pixels_24, sizeof(pixels_24));
3798 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3799 expect(Ok, status);
3801 /* associate known palette with pixel data */
3802 palette.pal.Flags = PaletteFlagsGrayScale;
3803 palette.pal.Count = 2;
3804 entries[0] = 0xff000000;
3805 entries[1] = 0xffffffff;
3806 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3807 expect(Ok, status);
3809 memset(&data, 0xfe, sizeof(data));
3810 if (td[i].mode & ImageLockModeUserInputBuf)
3812 memset(buf, 0x77, sizeof(buf));
3813 data.Scan0 = buf;
3814 data.Stride = 32;
3816 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3817 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3818 if (status != Ok)
3820 GdipDisposeImage((GpImage *)bitmap);
3821 continue;
3823 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3824 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3825 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3826 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3827 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3828 if (td[i].mode & ImageLockModeUserInputBuf)
3829 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3830 if (td[i].size == data.Height * data.Stride)
3832 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3834 match = 1;
3835 for (j = 0; j < data.Height; j++)
3837 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3839 match = 0;
3840 break;
3843 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3845 ok(match,
3846 "%u: data should match\n", i);
3847 if (!match)
3849 BYTE *bits = data.Scan0;
3850 trace("%u: data mismatch for format %#x:", i, td[i].format);
3851 for (j = 0; j < td[i].size; j++)
3852 trace(" %02x", bits[j]);
3853 trace("\n");
3856 else
3857 ok(!match, "%u: data shouldn't match\n", i);
3859 memset(data.Scan0, 0, td[i].size);
3862 status = GdipBitmapUnlockBits(bitmap, &data);
3863 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3865 memset(&data, 0xfe, sizeof(data));
3866 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3867 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3868 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3869 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3870 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3871 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3872 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3873 if (data.Height * data.Stride == 48)
3875 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3876 ok(match, "%u: data should match\n", i);
3877 if (!match)
3879 UINT j;
3880 BYTE *bits = data.Scan0;
3881 trace("%u: data mismatch for format %#x:", i, td[i].format);
3882 for (j = 0; j < 48; j++)
3883 trace(" %02x", bits[j]);
3884 trace("\n");
3888 status = GdipBitmapUnlockBits(bitmap, &data);
3889 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3891 status = GdipDisposeImage((GpImage *)bitmap);
3892 expect(Ok, status);
3896 static void test_DrawImage(void)
3898 BYTE black_1x1[4] = { 0,0,0,0 };
3899 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3900 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3901 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3902 0,0,0,0,0,0,0xff,0xff };
3903 GpStatus status;
3904 union
3906 GpBitmap *bitmap;
3907 GpImage *image;
3908 } u1, u2;
3909 GpGraphics *graphics;
3910 int match;
3912 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3913 expect(Ok, status);
3914 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3915 expect(Ok, status);
3917 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3918 expect(Ok, status);
3919 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3920 expect(Ok, status);
3921 status = GdipGetImageGraphicsContext(u2.image, &graphics);
3922 expect(Ok, status);
3923 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3924 expect(Ok, status);
3926 status = GdipDrawImageI(graphics, u1.image, 0, 0);
3927 expect(Ok, status);
3929 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3930 ok(match, "data should match\n");
3931 if (!match)
3933 UINT i, size = sizeof(white_2x2);
3934 BYTE *bits = white_2x2;
3935 for (i = 0; i < size; i++)
3936 trace(" %02x", bits[i]);
3937 trace("\n");
3940 status = GdipDeleteGraphics(graphics);
3941 expect(Ok, status);
3942 status = GdipDisposeImage(u1.image);
3943 expect(Ok, status);
3944 status = GdipDisposeImage(u2.image);
3945 expect(Ok, status);
3948 static void test_GdipDrawImagePointRect(void)
3950 BYTE black_1x1[4] = { 0,0,0,0 };
3951 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3952 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3953 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3954 0,0,0,0,0,0,0xff,0xff };
3955 GpStatus status;
3956 union
3958 GpBitmap *bitmap;
3959 GpImage *image;
3960 } u1, u2;
3961 GpGraphics *graphics;
3962 int match;
3964 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3965 expect(Ok, status);
3966 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3967 expect(Ok, status);
3969 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3970 expect(Ok, status);
3971 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3972 expect(Ok, status);
3973 status = GdipGetImageGraphicsContext(u2.image, &graphics);
3974 expect(Ok, status);
3975 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3976 expect(Ok, status);
3978 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
3979 expect(Ok, status);
3981 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3982 ok(match, "data should match\n");
3983 if (!match)
3985 UINT i, size = sizeof(white_2x2);
3986 BYTE *bits = white_2x2;
3987 for (i = 0; i < size; i++)
3988 trace(" %02x", bits[i]);
3989 trace("\n");
3992 status = GdipDeleteGraphics(graphics);
3993 expect(Ok, status);
3994 status = GdipDisposeImage(u1.image);
3995 expect(Ok, status);
3996 status = GdipDisposeImage(u2.image);
3997 expect(Ok, status);
4000 static void test_image_format(void)
4002 static const PixelFormat fmt[] =
4004 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4005 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4006 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4007 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4008 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4010 GpStatus status;
4011 GpBitmap *bitmap;
4012 GpImage *thumb;
4013 HBITMAP hbitmap;
4014 BITMAP bm;
4015 PixelFormat format;
4016 BitmapData data;
4017 UINT i, ret;
4019 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
4021 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4022 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4023 "GdipCreateBitmapFromScan0 error %d\n", status);
4024 if (status != Ok) continue;
4026 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4027 expect(Ok, status);
4028 expect(fmt[i], format);
4030 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4031 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4032 todo_wine expect(InvalidParameter, status);
4033 else
4035 expect(Ok, status);
4036 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4037 expect(sizeof(bm), ret);
4038 expect(0, bm.bmType);
4039 expect(1, bm.bmWidth);
4040 expect(1, bm.bmHeight);
4041 expect(4, bm.bmWidthBytes);
4042 expect(1, bm.bmPlanes);
4043 expect(32, bm.bmBitsPixel);
4044 DeleteObject(hbitmap);
4047 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4048 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4049 todo_wine
4050 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4051 "expected OutOfMemory, got %d\n", status);
4052 else
4054 expect(Ok, status);
4055 status = GdipGetImagePixelFormat(thumb, &format);
4056 expect(Ok, status);
4057 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4058 "expected PixelFormat32bppPARGB, got %#x\n", format);
4059 status = GdipDisposeImage(thumb);
4060 expect(Ok, status);
4063 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4064 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4065 todo_wine expect(InvalidParameter, status);
4066 else
4068 expect(Ok, status);
4069 status = GdipBitmapUnlockBits(bitmap, &data);
4070 expect(Ok, status);
4073 status = GdipDisposeImage((GpImage *)bitmap);
4074 expect(Ok, status);
4078 static void test_DrawImage_scale(void)
4080 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4081 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4082 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4083 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4084 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4085 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4086 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4087 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4088 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4089 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4090 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4091 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4092 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4093 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4094 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4095 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4096 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4097 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4098 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4099 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4100 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4101 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4102 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4103 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4104 static const struct test_data
4106 REAL scale_x;
4107 PixelOffsetMode pixel_offset_mode;
4108 const BYTE *image;
4109 BOOL todo;
4110 } td[] =
4112 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4113 { 1.0, PixelOffsetModeNone, image_100 },
4114 { 1.2, PixelOffsetModeNone, image_120 },
4115 { 1.5, PixelOffsetModeNone, image_150 },
4116 { 1.8, PixelOffsetModeNone, image_180 },
4117 { 2.0, PixelOffsetModeNone, image_200 },
4118 { 2.5, PixelOffsetModeNone, image_250 },
4120 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4121 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4122 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4123 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4124 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4125 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4126 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4128 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4129 { 1.0, PixelOffsetModeHalf, image_100 },
4130 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4131 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4132 { 1.8, PixelOffsetModeHalf, image_180 },
4133 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4134 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4136 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4137 { 1.0, PixelOffsetModeHighQuality, image_100 },
4138 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4139 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4140 { 1.8, PixelOffsetModeHighQuality, image_180 },
4141 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4142 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4144 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4145 BYTE dst_8x1[24];
4146 GpStatus status;
4147 union
4149 GpBitmap *bitmap;
4150 GpImage *image;
4151 } u1, u2;
4152 GpGraphics *graphics;
4153 GpMatrix *matrix;
4154 int i, match;
4156 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4157 expect(Ok, status);
4158 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4159 expect(Ok, status);
4161 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4162 expect(Ok, status);
4163 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4164 expect(Ok, status);
4165 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4166 expect(Ok, status);
4167 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4168 expect(Ok, status);
4170 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4172 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4173 expect(Ok, status);
4175 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4176 expect(Ok, status);
4177 status = GdipSetWorldTransform(graphics, matrix);
4178 expect(Ok, status);
4179 GdipDeleteMatrix(matrix);
4181 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4182 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4183 expect(Ok, status);
4185 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4186 if (!match && td[i].todo)
4187 todo_wine ok(match, "%d: data should match\n", i);
4188 else
4189 ok(match, "%d: data should match\n", i);
4190 if (!match)
4192 UINT i, size = sizeof(dst_8x1);
4193 const BYTE *bits = dst_8x1;
4194 for (i = 0; i < size; i++)
4195 trace(" %02x", bits[i]);
4196 trace("\n");
4200 status = GdipDeleteGraphics(graphics);
4201 expect(Ok, status);
4202 status = GdipDisposeImage(u1.image);
4203 expect(Ok, status);
4204 status = GdipDisposeImage(u2.image);
4205 expect(Ok, status);
4208 static const BYTE animatedgif[] = {
4209 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4210 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4211 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4212 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4213 0x03,0x01,0x05,0x00,0x00,
4214 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4215 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4216 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4217 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4218 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4219 0x02,0x02,0x4C,0x01,0x00,
4220 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4221 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4222 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4223 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4224 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4225 0x02,0x02,0x44,0x01,0x00,
4226 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4227 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4230 static void test_gif_properties(void)
4232 static const struct test_data
4234 ULONG type, id, length;
4235 const BYTE value[13];
4236 } td[] =
4238 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4239 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4240 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4241 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4242 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4243 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4245 GpStatus status;
4246 GpImage *image;
4247 GUID guid;
4248 UINT dim_count, frame_count, prop_count, prop_size, i;
4249 UINT total_size, total_count;
4250 PROPID *prop_id;
4251 PropertyItem *prop_item;
4252 const char *item_data;
4254 image = load_image(animatedgif, sizeof(animatedgif));
4255 if (!image) /* XP fails to load this GIF image */
4257 trace("Failed to load GIF image data\n");
4258 return;
4261 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4262 expect(Ok, status);
4263 expect(1, dim_count);
4265 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4266 expect(Ok, status);
4267 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4269 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4270 expect(Ok, status);
4271 expect(2, frame_count);
4273 status = GdipImageSelectActiveFrame(image, &guid, 1);
4274 expect(Ok, status);
4276 status = GdipGetPropertyCount(image, &prop_count);
4277 expect(Ok, status);
4278 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
4279 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
4281 if (prop_count != sizeof(td)/sizeof(td[0]))
4283 GdipDisposeImage(image);
4284 return;
4287 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4289 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4290 expect(Ok, status);
4292 prop_size = 0;
4293 for (i = 0; i < prop_count; i++)
4295 UINT size;
4296 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4297 expect(Ok, status);
4298 if (status != Ok) break;
4299 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4301 prop_size += size;
4303 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4304 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4305 expect(Ok, status);
4306 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4307 ok(td[i].type == prop_item->type,
4308 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4309 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4310 size -= sizeof(*prop_item);
4311 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4312 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4313 if (td[i].length == prop_item->length)
4315 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4316 ok(match, "%u: data mismatch\n", i);
4317 if (!match)
4319 UINT j;
4320 BYTE *data = prop_item->value;
4321 trace("id %#x:", prop_item->id);
4322 for (j = 0; j < prop_item->length; j++)
4323 trace(" %02x", data[j]);
4324 trace("\n");
4327 HeapFree(GetProcessHeap(), 0, prop_item);
4330 HeapFree(GetProcessHeap(), 0, prop_id);
4332 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4333 expect(InvalidParameter, status);
4334 status = GdipGetPropertySize(image, &total_size, NULL);
4335 expect(InvalidParameter, status);
4336 status = GdipGetPropertySize(image, NULL, &total_count);
4337 expect(InvalidParameter, status);
4338 status = GdipGetPropertySize(image, NULL, NULL);
4339 expect(InvalidParameter, status);
4340 total_size = 0xdeadbeef;
4341 total_count = 0xdeadbeef;
4342 status = GdipGetPropertySize(image, &total_size, &total_count);
4343 expect(Ok, status);
4344 ok(prop_count == total_count,
4345 "expected total property count %u, got %u\n", prop_count, total_count);
4346 ok(prop_size == total_size,
4347 "expected total property size %u, got %u\n", prop_size, total_size);
4349 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4351 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4352 expect(InvalidParameter, status);
4353 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4354 expect(InvalidParameter, status);
4355 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4356 expect(InvalidParameter, status);
4357 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4358 expect(InvalidParameter, status);
4359 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4360 expect(InvalidParameter, status);
4361 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4362 expect(InvalidParameter, status);
4363 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4364 expect(Ok, status);
4366 item_data = (const char *)(prop_item + prop_count);
4367 for (i = 0; i < prop_count; i++)
4369 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4370 i, item_data, prop_item[i].value);
4371 ok(td[i].type == prop_item[i].type,
4372 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4373 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4374 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4375 if (td[i].length == prop_item[i].length)
4377 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4378 ok(match, "%u: data mismatch\n", i);
4379 if (!match)
4381 UINT j;
4382 BYTE *data = prop_item[i].value;
4383 trace("id %#x:", prop_item[i].id);
4384 for (j = 0; j < prop_item[i].length; j++)
4385 trace(" %02x", data[j]);
4386 trace("\n");
4389 item_data += prop_item[i].length;
4392 HeapFree(GetProcessHeap(), 0, prop_item);
4394 GdipDisposeImage(image);
4397 static void test_ARGB_conversion(void)
4399 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4400 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4401 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4402 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4403 BYTE *bits;
4404 GpBitmap *bitmap;
4405 BitmapData data;
4406 GpStatus status;
4407 int match;
4409 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4410 expect(Ok, status);
4412 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4413 expect(Ok, status);
4414 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4415 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4416 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4417 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4418 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4419 ok(match, "bits don't match\n");
4420 if (!match)
4422 bits = data.Scan0;
4423 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4424 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4426 status = GdipBitmapUnlockBits(bitmap, &data);
4427 expect(Ok, status);
4429 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4430 expect(Ok, status);
4431 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4432 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4433 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4434 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4435 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4436 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4437 ok(match, "bits don't match\n");
4438 if (!match)
4440 bits = data.Scan0;
4441 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4442 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4444 status = GdipBitmapUnlockBits(bitmap, &data);
4445 expect(Ok, status);
4447 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4448 expect(Ok, status);
4449 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4450 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4451 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4452 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4453 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4454 ok(match, "bits don't match\n");
4455 if (!match)
4457 bits = data.Scan0;
4458 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4459 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4461 status = GdipBitmapUnlockBits(bitmap, &data);
4462 expect(Ok, status);
4464 GdipDisposeImage((GpImage *)bitmap);
4468 static void test_CloneBitmapArea(void)
4470 GpStatus status;
4471 GpBitmap *bitmap, *copy;
4472 BitmapData data, data2;
4474 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4475 expect(Ok, status);
4477 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4478 expect(Ok, status);
4480 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4481 expect(WrongState, status);
4483 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4484 expect(Ok, status);
4486 status = GdipBitmapUnlockBits(bitmap, &data);
4487 expect(Ok, status);
4489 GdipDisposeImage((GpImage *)copy);
4490 GdipDisposeImage((GpImage *)bitmap);
4493 START_TEST(image)
4495 struct GdiplusStartupInput gdiplusStartupInput;
4496 ULONG_PTR gdiplusToken;
4498 gdiplusStartupInput.GdiplusVersion = 1;
4499 gdiplusStartupInput.DebugEventCallback = NULL;
4500 gdiplusStartupInput.SuppressBackgroundThread = 0;
4501 gdiplusStartupInput.SuppressExternalCodecs = 0;
4503 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
4505 test_CloneBitmapArea();
4506 test_ARGB_conversion();
4507 test_DrawImage_scale();
4508 test_image_format();
4509 test_DrawImage();
4510 test_GdipDrawImagePointRect();
4511 test_bitmapbits();
4512 test_tiff_palette();
4513 test_GdipGetAllPropertyItems();
4514 test_tiff_properties();
4515 test_gif_properties();
4516 test_image_properties();
4517 test_Scan0();
4518 test_FromGdiDib();
4519 test_GetImageDimension();
4520 test_GdipImageGetFrameDimensionsCount();
4521 test_LoadingImages();
4522 test_SavingImages();
4523 test_encoders();
4524 test_LockBits();
4525 test_LockBits_UserBuf();
4526 test_GdipCreateBitmapFromHBITMAP();
4527 test_GdipGetImageFlags();
4528 test_GdipCloneImage();
4529 test_testcontrol();
4530 test_fromhicon();
4531 test_getrawformat();
4532 test_loadwmf();
4533 test_createfromwmf();
4534 test_resolution();
4535 test_createhbitmap();
4536 test_getthumbnail();
4537 test_getsetpixel();
4538 test_palette();
4539 test_colormatrix();
4540 test_gamma();
4541 test_multiframegif();
4542 test_rotateflip();
4543 test_remaptable();
4544 test_colorkey();
4545 test_dispose();
4547 GdiplusShutdown(gdiplusToken);