gdiplus/tests: Add more PNG color format tests.
[wine.git] / dlls / gdiplus / tests / image.c
blobca7874771b010650fa6fefca1eae47e68ae6f01d
1 /*
2 * Unit test suite for images
4 * Copyright (C) 2007 Google (Evan Stade)
5 * Copyright (C) 2012, 2016 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 static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*);
34 static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
35 static GpStatus (WINAPI *pGdipImageSetAbort)(GpImage*,GdiplusAbort*);
37 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
38 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
40 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
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 c1 >>= 8; c2 >>= 8;
46 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
47 c1 >>= 8; c2 >>= 8;
48 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
49 return TRUE;
52 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
54 WCHAR bufferW[39];
55 char buffer[39];
56 char buffer2[39];
58 StringFromGUID2(got, bufferW, ARRAY_SIZE(bufferW));
59 WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer, sizeof(buffer), NULL, NULL);
60 StringFromGUID2(expected, bufferW, ARRAY_SIZE(bufferW));
61 WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer2, sizeof(buffer2), NULL, NULL);
62 todo_wine_if (todo)
63 ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
66 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
68 GUID raw;
69 GpStatus stat;
71 stat = GdipGetImageRawFormat(img, &raw);
72 ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
73 if(stat != Ok) return;
74 expect_guid(expected, &raw, line, todo);
77 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
79 LPSTREAM stream;
80 HGLOBAL hglob;
81 LPBYTE data;
82 HRESULT hres;
83 GpStatus stat;
84 GpImage *img;
86 hglob = GlobalAlloc (0, size);
87 data = GlobalLock (hglob);
88 memcpy(data, buff, size);
89 GlobalUnlock(hglob); data = NULL;
91 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
92 ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
93 if(hres != S_OK) return;
95 stat = GdipLoadImageFromStream(stream, &img);
96 ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
97 if(stat != Ok){
98 IStream_Release(stream);
99 return;
102 expect_rawformat(expected, img, line, todo);
104 GdipDisposeImage(img);
105 IStream_Release(stream);
108 static void test_Scan0(void)
110 GpBitmap *bm;
111 GpStatus stat;
112 BYTE buff[360];
114 bm = NULL;
115 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
116 expect(Ok, stat);
117 ok(NULL != bm, "Expected bitmap to be initialized\n");
118 if (stat == Ok)
119 GdipDisposeImage((GpImage*)bm);
121 bm = (GpBitmap*)0xdeadbeef;
122 stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
123 expect(InvalidParameter, stat);
124 ok( !bm, "expected null bitmap\n" );
126 bm = (GpBitmap*)0xdeadbeef;
127 stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
128 expect(InvalidParameter, stat);
129 ok( !bm, "expected null bitmap\n" );
131 bm = (GpBitmap*)0xdeadbeef;
132 stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
133 expect(InvalidParameter, stat);
134 ok( !bm, "expected null bitmap\n" );
136 bm = NULL;
137 stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
138 expect(Ok, stat);
139 ok(NULL != bm, "Expected bitmap to be initialized\n");
140 if (stat == Ok)
141 GdipDisposeImage((GpImage*)bm);
143 bm = (GpBitmap*) 0xdeadbeef;
144 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
145 expect(InvalidParameter, stat);
146 ok( !bm, "expected null bitmap\n" );
148 bm = (GpBitmap*)0xdeadbeef;
149 stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
150 expect(InvalidParameter, stat);
151 ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
153 bm = NULL;
154 stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
155 expect(Ok, stat);
156 ok(NULL != bm, "Expected bitmap to be initialized\n");
157 if (stat == Ok)
158 GdipDisposeImage((GpImage*)bm);
160 bm = (GpBitmap*)0xdeadbeef;
161 stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
162 expect(InvalidParameter, stat);
163 ok( !bm, "expected null bitmap\n" );
166 static void test_FromGdiDib(void)
168 GpBitmap *bm;
169 GpStatus stat;
170 BYTE buff[400];
171 BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
172 BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
173 PixelFormat format;
175 bm = NULL;
177 memset(rbmi, 0, sizeof(rbmi));
179 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
180 bmi->bmiHeader.biWidth = 10;
181 bmi->bmiHeader.biHeight = 10;
182 bmi->bmiHeader.biPlanes = 1;
183 bmi->bmiHeader.biBitCount = 32;
184 bmi->bmiHeader.biCompression = BI_RGB;
186 stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
187 expect(InvalidParameter, stat);
189 stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
190 expect(InvalidParameter, stat);
192 stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
193 expect(InvalidParameter, stat);
195 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
196 expect(Ok, stat);
197 ok(NULL != bm, "Expected bitmap to be initialized\n");
198 if (stat == Ok)
200 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
201 expect(Ok, stat);
202 expect(PixelFormat32bppRGB, format);
204 GdipDisposeImage((GpImage*)bm);
207 bmi->bmiHeader.biBitCount = 24;
208 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
209 expect(Ok, stat);
210 ok(NULL != bm, "Expected bitmap to be initialized\n");
211 if (stat == Ok)
213 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
214 expect(Ok, stat);
215 expect(PixelFormat24bppRGB, format);
217 GdipDisposeImage((GpImage*)bm);
220 bmi->bmiHeader.biBitCount = 16;
221 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
222 expect(Ok, stat);
223 ok(NULL != bm, "Expected bitmap to be initialized\n");
224 if (stat == Ok)
226 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
227 expect(Ok, stat);
228 expect(PixelFormat16bppRGB555, format);
230 GdipDisposeImage((GpImage*)bm);
233 bmi->bmiHeader.biBitCount = 8;
234 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
235 expect(Ok, stat);
236 ok(NULL != bm, "Expected bitmap to be initialized\n");
237 if (stat == Ok)
239 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
240 expect(Ok, stat);
241 expect(PixelFormat8bppIndexed, format);
243 GdipDisposeImage((GpImage*)bm);
246 bmi->bmiHeader.biBitCount = 4;
247 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
248 expect(Ok, stat);
249 ok(NULL != bm, "Expected bitmap to be initialized\n");
250 if (stat == Ok)
252 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
253 expect(Ok, stat);
254 expect(PixelFormat4bppIndexed, format);
256 GdipDisposeImage((GpImage*)bm);
259 bmi->bmiHeader.biBitCount = 1;
260 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
261 expect(Ok, stat);
262 ok(NULL != bm, "Expected bitmap to be initialized\n");
263 if (stat == Ok)
265 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
266 expect(Ok, stat);
267 expect(PixelFormat1bppIndexed, format);
269 GdipDisposeImage((GpImage*)bm);
272 bmi->bmiHeader.biBitCount = 0;
273 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
274 expect(InvalidParameter, stat);
277 static void test_GetImageDimension(void)
279 GpBitmap *bm;
280 GpStatus stat;
281 const REAL WIDTH = 10.0, HEIGHT = 20.0;
282 REAL w,h;
284 bm = (GpBitmap*)0xdeadbeef;
285 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
286 expect(Ok,stat);
287 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
288 ok(NULL != bm, "Expected bitmap to not be NULL\n");
290 stat = GdipGetImageDimension(NULL,&w,&h);
291 expect(InvalidParameter, stat);
293 stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
294 expect(InvalidParameter, stat);
296 stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
297 expect(InvalidParameter, stat);
299 w = -1;
300 h = -1;
301 stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
302 expect(Ok, stat);
303 expectf(WIDTH, w);
304 expectf(HEIGHT, h);
305 GdipDisposeImage((GpImage*)bm);
308 static void test_GdipImageGetFrameDimensionsCount(void)
310 GpBitmap *bm;
311 GpStatus stat;
312 const REAL WIDTH = 10.0, HEIGHT = 20.0;
313 UINT w;
314 GUID dimension = {0};
315 UINT count;
316 ARGB color;
318 bm = (GpBitmap*)0xdeadbeef;
319 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
320 expect(Ok,stat);
321 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
322 ok(NULL != bm, "Expected bitmap to not be NULL\n");
324 stat = GdipImageGetFrameDimensionsCount(NULL,&w);
325 expect(InvalidParameter, stat);
327 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
328 expect(InvalidParameter, stat);
330 w = -1;
331 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
332 expect(Ok, stat);
333 expect(1, w);
335 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
336 expect(Ok, stat);
337 expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
339 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
340 expect(InvalidParameter, stat);
342 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
343 expect(InvalidParameter, stat);
345 stat = GdipImageGetFrameCount(NULL, &dimension, &count);
346 expect(InvalidParameter, stat);
348 /* WinXP crashes on this test */
349 if(0)
351 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
352 expect(InvalidParameter, stat);
355 stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
356 expect(Ok, stat);
358 count = 12345;
359 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
360 expect(Ok, stat);
361 expect(1, count);
363 GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
365 stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
366 expect(Ok, stat);
368 /* SelectActiveFrame has no effect on image data of memory bitmaps */
369 color = 0xdeadbeef;
370 stat = GdipBitmapGetPixel(bm, 0, 0, &color);
371 expect(Ok, stat);
372 expect(0xffffffff, color);
374 GdipDisposeImage((GpImage*)bm);
377 static void test_LoadingImages(void)
379 GpStatus stat;
380 GpBitmap *bm;
381 GpImage *img;
382 static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0};
384 stat = GdipCreateBitmapFromFile(0, 0);
385 expect(InvalidParameter, stat);
387 bm = (GpBitmap *)0xdeadbeef;
388 stat = GdipCreateBitmapFromFile(0, &bm);
389 expect(InvalidParameter, stat);
390 ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm);
392 bm = (GpBitmap *)0xdeadbeef;
393 stat = GdipCreateBitmapFromFile(nonexistentW, &bm);
394 todo_wine expect(InvalidParameter, stat);
395 ok(!bm, "returned %p\n", bm);
397 stat = GdipLoadImageFromFile(0, 0);
398 expect(InvalidParameter, stat);
400 img = (GpImage *)0xdeadbeef;
401 stat = GdipLoadImageFromFile(0, &img);
402 expect(InvalidParameter, stat);
403 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
405 img = (GpImage *)0xdeadbeef;
406 stat = GdipLoadImageFromFile(nonexistentW, &img);
407 todo_wine expect(OutOfMemory, stat);
408 ok(!img, "returned %p\n", img);
410 stat = GdipLoadImageFromFileICM(0, 0);
411 expect(InvalidParameter, stat);
413 img = (GpImage *)0xdeadbeef;
414 stat = GdipLoadImageFromFileICM(0, &img);
415 expect(InvalidParameter, stat);
416 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
418 img = (GpImage *)0xdeadbeef;
419 stat = GdipLoadImageFromFileICM(nonexistentW, &img);
420 todo_wine expect(OutOfMemory, stat);
421 ok(!img, "returned %p\n", img);
424 static void test_SavingImages(void)
426 GpStatus stat;
427 GpBitmap *bm;
428 UINT n;
429 UINT s;
430 const REAL WIDTH = 10.0, HEIGHT = 20.0;
431 REAL w, h;
432 ImageCodecInfo *codecs;
433 static const CHAR filenameA[] = "a.bmp";
434 static const WCHAR filename[] = { 'a','.','b','m','p',0 };
436 codecs = NULL;
438 stat = GdipSaveImageToFile(0, 0, 0, 0);
439 expect(InvalidParameter, stat);
441 bm = NULL;
442 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
443 expect(Ok, stat);
444 if (!bm)
445 return;
447 /* invalid params */
448 stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
449 expect(InvalidParameter, stat);
451 stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
452 expect(InvalidParameter, stat);
454 /* encoder tests should succeed -- already tested */
455 stat = GdipGetImageEncodersSize(&n, &s);
456 if (stat != Ok || n == 0) goto cleanup;
458 codecs = GdipAlloc(s);
459 if (!codecs) goto cleanup;
461 stat = GdipGetImageEncoders(n, s, codecs);
462 if (stat != Ok) goto cleanup;
464 stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
465 expect(Ok, stat);
467 GdipDisposeImage((GpImage*)bm);
468 bm = 0;
470 /* re-load and check image stats */
471 stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
472 expect(Ok, stat);
473 if (stat != Ok) goto cleanup;
475 stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
476 if (stat != Ok) goto cleanup;
478 expectf(WIDTH, w);
479 expectf(HEIGHT, h);
481 cleanup:
482 GdipFree(codecs);
483 if (bm)
484 GdipDisposeImage((GpImage*)bm);
485 ok(DeleteFileA(filenameA), "Delete failed.\n");
488 static void test_encoders(void)
490 GpStatus stat;
491 UINT n;
492 UINT s;
493 ImageCodecInfo *codecs;
494 int i;
495 int bmp_found;
497 static const CHAR bmp_format[] = "BMP";
499 stat = GdipGetImageEncodersSize(&n, &s);
500 expect(stat, Ok);
502 codecs = GdipAlloc(s);
503 if (!codecs)
504 return;
506 stat = GdipGetImageEncoders(n, s, NULL);
507 expect(GenericError, stat);
509 stat = GdipGetImageEncoders(0, s, codecs);
510 expect(GenericError, stat);
512 stat = GdipGetImageEncoders(n, s-1, codecs);
513 expect(GenericError, stat);
515 stat = GdipGetImageEncoders(n, s+1, codecs);
516 expect(GenericError, stat);
518 stat = GdipGetImageEncoders(n, s, codecs);
519 expect(stat, Ok);
521 bmp_found = FALSE;
522 for (i = 0; i < n; i++)
524 CHAR desc[32];
526 WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
527 desc, 32, 0, 0);
529 if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
530 desc, -1,
531 bmp_format, -1) == CSTR_EQUAL) {
532 bmp_found = TRUE;
533 break;
536 if (!bmp_found)
537 ok(FALSE, "No BMP codec found.\n");
539 GdipFree(codecs);
542 static void test_LockBits(void)
544 GpStatus stat;
545 GpBitmap *bm;
546 GpRect rect;
547 BitmapData bd;
548 const INT WIDTH = 10, HEIGHT = 20;
549 ARGB color;
550 int y;
552 bm = NULL;
553 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
554 expect(Ok, stat);
556 rect.X = 2;
557 rect.Y = 3;
558 rect.Width = 4;
559 rect.Height = 5;
561 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
562 expect(Ok, stat);
564 stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
565 expect(Ok, stat);
567 /* read-only */
568 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
569 expect(Ok, stat);
571 if (stat == Ok) {
572 expect(0xc3, ((BYTE*)bd.Scan0)[2]);
573 expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
575 ((char*)bd.Scan0)[2] = 0xff;
577 stat = GdipBitmapUnlockBits(bm, &bd);
578 expect(Ok, stat);
581 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
582 expect(Ok, stat);
583 expect(0xffff0000, color);
585 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
586 expect(Ok, stat);
588 /* read-only, with NULL rect -> whole bitmap lock */
589 stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
590 expect(Ok, stat);
591 expect(bd.Width, WIDTH);
592 expect(bd.Height, HEIGHT);
594 if (stat == Ok) {
595 ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
597 stat = GdipBitmapUnlockBits(bm, &bd);
598 expect(Ok, stat);
601 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
602 expect(Ok, stat);
603 expect(0xffff0000, color);
605 /* read-only, consecutive */
606 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
607 expect(Ok, stat);
609 if (stat == Ok) {
610 stat = GdipBitmapUnlockBits(bm, &bd);
611 expect(Ok, stat);
614 stat = GdipDisposeImage((GpImage*)bm);
615 expect(Ok, stat);
616 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
617 expect(Ok, stat);
619 /* read x2 */
620 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
621 expect(Ok, stat);
622 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
623 expect(WrongState, stat);
625 stat = GdipBitmapUnlockBits(bm, &bd);
626 expect(Ok, stat);
628 stat = GdipDisposeImage((GpImage*)bm);
629 expect(Ok, stat);
630 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
631 expect(Ok, stat);
633 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
634 expect(Ok, stat);
636 stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
637 expect(Ok, stat);
639 /* write, no conversion */
640 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
641 expect(Ok, stat);
643 if (stat == Ok) {
644 /* all bits are readable, inside the rect or not */
645 expect(0xff, ((BYTE*)bd.Scan0)[2]);
646 expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
648 stat = GdipBitmapUnlockBits(bm, &bd);
649 expect(Ok, stat);
652 /* read, conversion */
653 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
654 expect(Ok, stat);
656 if (stat == Ok) {
657 expect(0xff, ((BYTE*)bd.Scan0)[2]);
658 if (0)
659 /* Areas outside the rectangle appear to be uninitialized */
660 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
662 ((BYTE*)bd.Scan0)[2] = 0xc3;
664 stat = GdipBitmapUnlockBits(bm, &bd);
665 expect(Ok, stat);
668 /* writes do not work in read mode if there was a conversion */
669 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
670 expect(Ok, stat);
671 expect(0xffff0000, color);
673 /* read/write, conversion */
674 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
675 expect(Ok, stat);
677 if (stat == Ok) {
678 expect(0xff, ((BYTE*)bd.Scan0)[2]);
679 ((BYTE*)bd.Scan0)[1] = 0x88;
680 if (0)
681 /* Areas outside the rectangle appear to be uninitialized */
682 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
684 stat = GdipBitmapUnlockBits(bm, &bd);
685 expect(Ok, stat);
688 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
689 expect(Ok, stat);
690 expect(0xffff8800, color);
692 /* write, conversion */
693 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
694 expect(Ok, stat);
696 if (stat == Ok) {
697 if (0)
699 /* This is completely uninitialized. */
700 ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
701 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
704 /* Initialize the buffer so the unlock doesn't access undefined memory */
705 for (y=0; y<5; y++)
706 memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
708 ((BYTE*)bd.Scan0)[0] = 0x12;
709 ((BYTE*)bd.Scan0)[1] = 0x34;
710 ((BYTE*)bd.Scan0)[2] = 0x56;
712 stat = GdipBitmapUnlockBits(bm, &bd);
713 expect(Ok, stat);
716 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
717 expect(Ok, stat);
718 expect(0xff563412, color);
720 stat = GdipBitmapGetPixel(bm, 2, 8, &color);
721 expect(Ok, stat);
722 expect(0xffc30000, color);
724 stat = GdipDisposeImage((GpImage*)bm);
725 expect(Ok, stat);
726 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
727 expect(Ok, stat);
729 /* write, no modification */
730 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
731 expect(Ok, stat);
733 if (stat == Ok) {
734 stat = GdipBitmapUnlockBits(bm, &bd);
735 expect(Ok, stat);
738 /* write, consecutive */
739 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
740 expect(Ok, stat);
742 if (stat == Ok) {
743 stat = GdipBitmapUnlockBits(bm, &bd);
744 expect(Ok, stat);
747 stat = GdipDisposeImage((GpImage*)bm);
748 expect(Ok, stat);
749 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
750 expect(Ok, stat);
752 /* write, modify */
753 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
754 expect(Ok, stat);
756 if (stat == Ok) {
757 if (bd.Scan0)
758 ((char*)bd.Scan0)[2] = 0xff;
760 stat = GdipBitmapUnlockBits(bm, &bd);
761 expect(Ok, stat);
764 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
765 expect(Ok, stat);
766 expect(0xffff0000, color);
768 stat = GdipDisposeImage((GpImage*)bm);
769 expect(Ok, stat);
771 /* dispose locked */
772 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
773 expect(Ok, stat);
774 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
775 expect(Ok, stat);
776 stat = GdipDisposeImage((GpImage*)bm);
777 expect(Ok, stat);
780 static void test_LockBits_UserBuf(void)
782 GpStatus stat;
783 GpBitmap *bm;
784 GpRect rect;
785 BitmapData bd;
786 const INT WIDTH = 10, HEIGHT = 20;
787 DWORD bits[200];
788 ARGB color;
790 bm = NULL;
791 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
792 expect(Ok, stat);
794 memset(bits, 0xaa, sizeof(bits));
796 rect.X = 2;
797 rect.Y = 3;
798 rect.Width = 4;
799 rect.Height = 5;
801 bd.Width = 4;
802 bd.Height = 6;
803 bd.Stride = WIDTH * 4;
804 bd.PixelFormat = PixelFormat32bppARGB;
805 bd.Scan0 = &bits[2+3*WIDTH];
806 bd.Reserved = 0xaaaaaaaa;
808 /* read-only */
809 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
810 expect(Ok, stat);
812 expect(0xaaaaaaaa, bits[0]);
813 expect(0, bits[2+3*WIDTH]);
815 bits[2+3*WIDTH] = 0xdeadbeef;
817 if (stat == Ok) {
818 stat = GdipBitmapUnlockBits(bm, &bd);
819 expect(Ok, stat);
822 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
823 expect(Ok, stat);
824 expect(0, color);
826 /* write-only */
827 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
828 expect(Ok, stat);
830 expect(0xdeadbeef, bits[2+3*WIDTH]);
831 bits[2+3*WIDTH] = 0x12345678;
833 if (stat == Ok) {
834 stat = GdipBitmapUnlockBits(bm, &bd);
835 expect(Ok, stat);
838 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
839 expect(Ok, stat);
840 expect(0x12345678, color);
842 bits[2+3*WIDTH] = 0;
844 /* read/write */
845 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
846 expect(Ok, stat);
848 expect(0x12345678, bits[2+3*WIDTH]);
849 bits[2+3*WIDTH] = 0xdeadbeef;
851 if (stat == Ok) {
852 stat = GdipBitmapUnlockBits(bm, &bd);
853 expect(Ok, stat);
856 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
857 expect(Ok, stat);
858 expect(0xdeadbeef, color);
860 stat = GdipDisposeImage((GpImage*)bm);
861 expect(Ok, stat);
864 struct BITMAPINFOWITHBITFIELDS
866 BITMAPINFOHEADER bmiHeader;
867 DWORD masks[3];
870 union BITMAPINFOUNION
872 BITMAPINFO bi;
873 struct BITMAPINFOWITHBITFIELDS bf;
876 static void test_GdipCreateBitmapFromHBITMAP(void)
878 GpBitmap* gpbm = NULL;
879 HBITMAP hbm = NULL;
880 HPALETTE hpal = NULL;
881 GpStatus stat;
882 BYTE buff[1000];
883 LOGPALETTE* LogPal = NULL;
884 REAL width, height;
885 const REAL WIDTH1 = 5;
886 const REAL HEIGHT1 = 15;
887 const REAL WIDTH2 = 10;
888 const REAL HEIGHT2 = 20;
889 HDC hdc;
890 union BITMAPINFOUNION bmi;
891 BYTE *bits;
892 PixelFormat format;
894 stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
895 expect(InvalidParameter, stat);
897 hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
898 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
899 expect(InvalidParameter, stat);
901 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
902 expect(Ok, stat);
903 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
904 expectf(WIDTH1, width);
905 expectf(HEIGHT1, height);
906 if (stat == Ok)
907 GdipDisposeImage((GpImage*)gpbm);
908 DeleteObject(hbm);
910 memset(buff, 0, sizeof(buff));
911 hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
912 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
913 expect(Ok, stat);
914 /* raw format */
915 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
917 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
918 expectf(WIDTH2, width);
919 expectf(HEIGHT2, height);
920 if (stat == Ok)
921 GdipDisposeImage((GpImage*)gpbm);
922 DeleteObject(hbm);
924 hdc = CreateCompatibleDC(0);
925 ok(hdc != NULL, "CreateCompatibleDC failed\n");
926 bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
927 bmi.bi.bmiHeader.biHeight = HEIGHT1;
928 bmi.bi.bmiHeader.biWidth = WIDTH1;
929 bmi.bi.bmiHeader.biBitCount = 24;
930 bmi.bi.bmiHeader.biPlanes = 1;
931 bmi.bi.bmiHeader.biCompression = BI_RGB;
932 bmi.bi.bmiHeader.biClrUsed = 0;
934 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
935 ok(hbm != NULL, "CreateDIBSection failed\n");
937 bits[0] = 0;
939 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
940 expect(Ok, stat);
941 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
942 expectf(WIDTH1, width);
943 expectf(HEIGHT1, height);
944 if (stat == Ok)
946 /* test whether writing to the bitmap affects the original */
947 stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
948 expect(Ok, stat);
950 expect(0, bits[0]);
952 GdipDisposeImage((GpImage*)gpbm);
955 LogPal = GdipAlloc(sizeof(LOGPALETTE));
956 ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
957 LogPal->palVersion = 0x300;
958 LogPal->palNumEntries = 1;
959 hpal = CreatePalette(LogPal);
960 ok(hpal != NULL, "CreatePalette failed\n");
961 GdipFree(LogPal);
963 stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
964 expect(Ok, stat);
966 if (stat == Ok)
967 GdipDisposeImage((GpImage*)gpbm);
969 DeleteObject(hpal);
970 DeleteObject(hbm);
972 /* 16-bit 555 dib, rgb */
973 bmi.bi.bmiHeader.biBitCount = 16;
974 bmi.bi.bmiHeader.biCompression = BI_RGB;
976 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
977 ok(hbm != NULL, "CreateDIBSection failed\n");
979 bits[0] = 0;
981 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
982 expect(Ok, stat);
984 if (stat == Ok)
986 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
987 expect(Ok, stat);
988 expectf(WIDTH1, width);
989 expectf(HEIGHT1, height);
991 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
992 expect(Ok, stat);
993 expect(PixelFormat16bppRGB555, format);
995 GdipDisposeImage((GpImage*)gpbm);
997 DeleteObject(hbm);
999 /* 16-bit 555 dib, with bitfields */
1000 bmi.bi.bmiHeader.biSize = sizeof(bmi);
1001 bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
1002 bmi.bf.masks[0] = 0x7c00;
1003 bmi.bf.masks[1] = 0x3e0;
1004 bmi.bf.masks[2] = 0x1f;
1006 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1007 ok(hbm != NULL, "CreateDIBSection failed\n");
1009 bits[0] = 0;
1011 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1012 expect(Ok, stat);
1014 if (stat == Ok)
1016 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1017 expect(Ok, stat);
1018 expectf(WIDTH1, width);
1019 expectf(HEIGHT1, height);
1021 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1022 expect(Ok, stat);
1023 expect(PixelFormat16bppRGB555, format);
1025 GdipDisposeImage((GpImage*)gpbm);
1027 DeleteObject(hbm);
1029 /* 16-bit 565 dib, with bitfields */
1030 bmi.bf.masks[0] = 0xf800;
1031 bmi.bf.masks[1] = 0x7e0;
1032 bmi.bf.masks[2] = 0x1f;
1034 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1035 ok(hbm != NULL, "CreateDIBSection failed\n");
1037 bits[0] = 0;
1039 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1040 expect(Ok, stat);
1042 if (stat == Ok)
1044 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1045 expect(Ok, stat);
1046 expectf(WIDTH1, width);
1047 expectf(HEIGHT1, height);
1049 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1050 expect(Ok, stat);
1051 expect(PixelFormat16bppRGB565, format);
1053 GdipDisposeImage((GpImage*)gpbm);
1055 DeleteObject(hbm);
1057 DeleteDC(hdc);
1060 static void test_GdipGetImageFlags(void)
1062 GpImage *img;
1063 GpStatus stat;
1064 UINT flags;
1066 img = (GpImage*)0xdeadbeef;
1068 stat = GdipGetImageFlags(NULL, NULL);
1069 expect(InvalidParameter, stat);
1071 stat = GdipGetImageFlags(NULL, &flags);
1072 expect(InvalidParameter, stat);
1074 stat = GdipGetImageFlags(img, NULL);
1075 expect(InvalidParameter, stat);
1077 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1078 expect(Ok, stat);
1079 stat = GdipGetImageFlags(img, &flags);
1080 expect(Ok, stat);
1081 expect(ImageFlagsHasAlpha, flags);
1082 GdipDisposeImage(img);
1084 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1085 expect(Ok, stat);
1086 stat = GdipGetImageFlags(img, &flags);
1087 expect(Ok, stat);
1088 expect(ImageFlagsHasAlpha, flags);
1089 GdipDisposeImage(img);
1091 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1092 expect(Ok, stat);
1093 stat = GdipGetImageFlags(img, &flags);
1094 expect(Ok, stat);
1095 expect(ImageFlagsHasAlpha, flags);
1096 GdipDisposeImage(img);
1098 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1099 expect(Ok, stat);
1100 stat = GdipGetImageFlags(img, &flags);
1101 expect(Ok, stat);
1102 expect(ImageFlagsNone, flags);
1103 GdipDisposeImage(img);
1105 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1106 expect(Ok, stat);
1107 stat = GdipGetImageFlags(img, &flags);
1108 expect(Ok, stat);
1109 expect(ImageFlagsNone, flags);
1110 GdipDisposeImage(img);
1112 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1113 expect(Ok, stat);
1114 stat = GdipGetImageFlags(img, &flags);
1115 expect(Ok, stat);
1116 expect(ImageFlagsNone, flags);
1117 GdipDisposeImage(img);
1119 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1120 expect(Ok, stat);
1121 stat = GdipGetImageFlags(img, &flags);
1122 expect(Ok, stat);
1123 expect(ImageFlagsHasAlpha, flags);
1124 GdipDisposeImage(img);
1126 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1127 expect(Ok, stat);
1128 stat = GdipGetImageFlags(img, &flags);
1129 expect(Ok, stat);
1130 expect(ImageFlagsNone, flags);
1131 GdipDisposeImage(img);
1133 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1134 expect(Ok, stat);
1135 stat = GdipGetImageFlags(img, &flags);
1136 expect(Ok, stat);
1137 expect(ImageFlagsNone, flags);
1138 GdipDisposeImage(img);
1140 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1141 expect(Ok, stat);
1142 stat = GdipGetImageFlags(img, &flags);
1143 expect(Ok, stat);
1144 expect(ImageFlagsHasAlpha, flags);
1145 GdipDisposeImage(img);
1147 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1148 expect(Ok, stat);
1149 stat = GdipGetImageFlags(img, &flags);
1150 expect(Ok, stat);
1151 expect(ImageFlagsHasAlpha, flags);
1152 GdipDisposeImage(img);
1154 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1155 expect(Ok, stat);
1156 if (stat == Ok)
1158 stat = GdipGetImageFlags(img, &flags);
1159 expect(Ok, stat);
1160 expect(ImageFlagsNone, flags);
1161 GdipDisposeImage(img);
1164 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1165 expect(Ok, stat);
1166 if (stat == Ok)
1168 expect(Ok, stat);
1169 stat = GdipGetImageFlags(img, &flags);
1170 expect(Ok, stat);
1171 expect(ImageFlagsHasAlpha, flags);
1172 GdipDisposeImage(img);
1175 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1176 expect(Ok, stat);
1177 if (stat == Ok)
1179 expect(Ok, stat);
1180 stat = GdipGetImageFlags(img, &flags);
1181 expect(Ok, stat);
1182 expect(ImageFlagsHasAlpha, flags);
1183 GdipDisposeImage(img);
1187 static void test_GdipCloneImage(void)
1189 GpStatus stat;
1190 GpRectF rectF;
1191 GpUnit unit;
1192 GpBitmap *bm;
1193 GpImage *image_src, *image_dest = NULL;
1194 const INT WIDTH = 10, HEIGHT = 20;
1196 /* Create an image, clone it, delete the original, make sure the copy works */
1197 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1198 expect(Ok, stat);
1199 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1201 image_src = ((GpImage*)bm);
1202 stat = GdipCloneImage(image_src, &image_dest);
1203 expect(Ok, stat);
1204 expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1206 stat = GdipDisposeImage((GpImage*)bm);
1207 expect(Ok, stat);
1208 stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1209 expect(Ok, stat);
1211 /* Treat FP values carefully */
1212 expectf((REAL)WIDTH, rectF.Width);
1213 expectf((REAL)HEIGHT, rectF.Height);
1215 stat = GdipDisposeImage(image_dest);
1216 expect(Ok, stat);
1219 static void test_testcontrol(void)
1221 GpStatus stat;
1222 DWORD param;
1224 param = 0;
1225 stat = GdipTestControl(TestControlGetBuildNumber, &param);
1226 expect(Ok, stat);
1227 ok(param != 0, "Build number expected, got %u\n", param);
1230 static void test_fromhicon(void)
1232 static const BYTE bmp_bits[1024];
1233 HBITMAP hbmMask, hbmColor;
1234 ICONINFO info;
1235 HICON hIcon;
1236 GpStatus stat;
1237 GpBitmap *bitmap = NULL;
1238 UINT dim;
1239 ImageType type;
1240 PixelFormat format;
1242 /* NULL */
1243 stat = GdipCreateBitmapFromHICON(NULL, NULL);
1244 expect(InvalidParameter, stat);
1245 stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1246 expect(InvalidParameter, stat);
1248 /* color icon 1 bit */
1249 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1250 ok(hbmMask != 0, "CreateBitmap failed\n");
1251 hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1252 ok(hbmColor != 0, "CreateBitmap failed\n");
1253 info.fIcon = TRUE;
1254 info.xHotspot = 8;
1255 info.yHotspot = 8;
1256 info.hbmMask = hbmMask;
1257 info.hbmColor = hbmColor;
1258 hIcon = CreateIconIndirect(&info);
1259 ok(hIcon != 0, "CreateIconIndirect failed\n");
1260 DeleteObject(hbmMask);
1261 DeleteObject(hbmColor);
1263 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1264 ok(stat == Ok ||
1265 broken(stat == InvalidParameter), /* Win98 */
1266 "Expected Ok, got %.8x\n", stat);
1267 if(stat == Ok){
1268 /* check attributes */
1269 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1270 expect(Ok, stat);
1271 expect(16, dim);
1272 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1273 expect(Ok, stat);
1274 expect(16, dim);
1275 stat = GdipGetImageType((GpImage*)bitmap, &type);
1276 expect(Ok, stat);
1277 expect(ImageTypeBitmap, type);
1278 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1279 expect(Ok, stat);
1280 expect(PixelFormat32bppARGB, format);
1281 /* raw format */
1282 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1283 GdipDisposeImage((GpImage*)bitmap);
1285 DestroyIcon(hIcon);
1287 /* color icon 8 bpp */
1288 hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1289 ok(hbmMask != 0, "CreateBitmap failed\n");
1290 hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1291 ok(hbmColor != 0, "CreateBitmap failed\n");
1292 info.fIcon = TRUE;
1293 info.xHotspot = 8;
1294 info.yHotspot = 8;
1295 info.hbmMask = hbmMask;
1296 info.hbmColor = hbmColor;
1297 hIcon = CreateIconIndirect(&info);
1298 ok(hIcon != 0, "CreateIconIndirect failed\n");
1299 DeleteObject(hbmMask);
1300 DeleteObject(hbmColor);
1302 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1303 expect(Ok, stat);
1304 if(stat == Ok){
1305 /* check attributes */
1306 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1307 expect(Ok, stat);
1308 expect(16, dim);
1309 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1310 expect(Ok, stat);
1311 expect(16, dim);
1312 stat = GdipGetImageType((GpImage*)bitmap, &type);
1313 expect(Ok, stat);
1314 expect(ImageTypeBitmap, type);
1315 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1316 expect(Ok, stat);
1317 expect(PixelFormat32bppARGB, format);
1318 /* raw format */
1319 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1320 GdipDisposeImage((GpImage*)bitmap);
1322 DestroyIcon(hIcon);
1325 /* 1x1 pixel png */
1326 static const unsigned char pngimage[285] = {
1327 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1328 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1329 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1330 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1331 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1332 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1333 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1335 /* 1x1 pixel gif */
1336 static const unsigned char gifimage[35] = {
1337 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1338 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1339 0x01,0x00,0x3b
1341 /* 1x1 pixel transparent gif */
1342 static const unsigned char transparentgif[] = {
1343 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
1344 0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,
1345 0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
1347 /* 1x1 pixel bmp */
1348 static const unsigned char bmpimage[66] = {
1349 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1350 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1351 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1352 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1353 0x00,0x00
1355 /* 1x1 pixel jpg */
1356 static const unsigned char jpgimage[285] = {
1357 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1358 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1359 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1360 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1361 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1362 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1363 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1364 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1365 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1366 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1367 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1368 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1369 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1370 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1371 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1372 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1373 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1374 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1376 /* 1x1 pixel tiff */
1377 static const unsigned char tiffimage[] = {
1378 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1379 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1380 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1381 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1382 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1383 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1384 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1385 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1386 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1387 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1388 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1389 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1390 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1391 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1392 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1393 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1394 0x00,0x00,0x00,0x01
1396 /* 320x320 twip wmf */
1397 static const unsigned char wmfimage[180] = {
1398 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1399 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1400 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1401 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1402 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1403 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1404 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1405 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1406 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1407 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1408 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1409 0x00,0x00,0x00,0x00
1411 static void test_getrawformat(void)
1413 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE);
1414 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE);
1415 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE);
1416 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1417 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1418 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1421 static void test_loadwmf(void)
1423 LPSTREAM stream;
1424 HGLOBAL hglob;
1425 LPBYTE data;
1426 HRESULT hres;
1427 GpStatus stat;
1428 GpImage *img;
1429 GpRectF bounds;
1430 GpUnit unit;
1431 REAL res = 12345.0;
1432 MetafileHeader header;
1434 hglob = GlobalAlloc (0, sizeof(wmfimage));
1435 data = GlobalLock (hglob);
1436 memcpy(data, wmfimage, sizeof(wmfimage));
1437 GlobalUnlock(hglob); data = NULL;
1439 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1440 ok(hres == S_OK, "Failed to create a stream\n");
1441 if(hres != S_OK) return;
1443 stat = GdipLoadImageFromStream(stream, &img);
1444 ok(stat == Ok, "Failed to create a Bitmap\n");
1445 if(stat != Ok){
1446 IStream_Release(stream);
1447 return;
1450 IStream_Release(stream);
1452 stat = GdipGetImageBounds(img, &bounds, &unit);
1453 expect(Ok, stat);
1454 expect(UnitPixel, unit);
1455 expectf(0.0, bounds.X);
1456 expectf(0.0, bounds.Y);
1457 expectf(320.0, bounds.Width);
1458 expectf(320.0, bounds.Height);
1460 stat = GdipGetImageHorizontalResolution(img, &res);
1461 expect(Ok, stat);
1462 expectf(1440.0, res);
1464 stat = GdipGetImageVerticalResolution(img, &res);
1465 expect(Ok, stat);
1466 expectf(1440.0, res);
1468 memset(&header, 0, sizeof(header));
1469 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1470 expect(Ok, stat);
1471 if (stat == Ok)
1473 expect(MetafileTypeWmfPlaceable, header.Type);
1474 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1475 todo_wine expect(0x300, header.Version);
1476 expect(0, header.EmfPlusFlags);
1477 expectf(1440.0, header.DpiX);
1478 expectf(1440.0, header.DpiY);
1479 expect(0, header.X);
1480 expect(0, header.Y);
1481 expect(320, header.Width);
1482 expect(320, header.Height);
1483 expect(1, U(header).WmfHeader.mtType);
1484 expect(0, header.EmfPlusHeaderSize);
1485 expect(0, header.LogicalDpiX);
1486 expect(0, header.LogicalDpiY);
1489 GdipDisposeImage(img);
1492 static void test_createfromwmf(void)
1494 HMETAFILE hwmf;
1495 GpImage *img;
1496 GpStatus stat;
1497 GpRectF bounds;
1498 GpUnit unit;
1499 REAL res = 12345.0;
1500 MetafileHeader header;
1502 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1503 wmfimage+sizeof(WmfPlaceableFileHeader));
1504 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1506 stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1507 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1508 expect(Ok, stat);
1510 stat = GdipGetImageBounds(img, &bounds, &unit);
1511 expect(Ok, stat);
1512 expect(UnitPixel, unit);
1513 expectf(0.0, bounds.X);
1514 expectf(0.0, bounds.Y);
1515 expectf(320.0, bounds.Width);
1516 expectf(320.0, bounds.Height);
1518 stat = GdipGetImageHorizontalResolution(img, &res);
1519 expect(Ok, stat);
1520 expectf(1440.0, res);
1522 stat = GdipGetImageVerticalResolution(img, &res);
1523 expect(Ok, stat);
1524 expectf(1440.0, res);
1526 memset(&header, 0, sizeof(header));
1527 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1528 expect(Ok, stat);
1529 if (stat == Ok)
1531 expect(MetafileTypeWmfPlaceable, header.Type);
1532 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1533 todo_wine expect(0x300, header.Version);
1534 expect(0, header.EmfPlusFlags);
1535 expectf(1440.0, header.DpiX);
1536 expectf(1440.0, header.DpiY);
1537 expect(0, header.X);
1538 expect(0, header.Y);
1539 expect(320, header.Width);
1540 expect(320, header.Height);
1541 expect(1, U(header).WmfHeader.mtType);
1542 expect(0, header.EmfPlusHeaderSize);
1543 expect(0, header.LogicalDpiX);
1544 expect(0, header.LogicalDpiY);
1547 GdipDisposeImage(img);
1550 static void test_createfromwmf_noplaceable(void)
1552 HMETAFILE hwmf;
1553 GpImage *img;
1554 GpStatus stat;
1556 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1557 wmfimage+sizeof(WmfPlaceableFileHeader));
1558 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1560 stat = GdipCreateMetafileFromWmf(hwmf, TRUE, NULL, (GpMetafile**)&img);
1561 expect(Ok, stat);
1563 GdipDisposeImage(img);
1566 static void test_resolution(void)
1568 GpStatus stat;
1569 GpBitmap *bitmap;
1570 GpGraphics *graphics;
1571 REAL res=-1.0;
1572 HDC screendc;
1573 int screenxres, screenyres;
1575 /* create Bitmap */
1576 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1577 expect(Ok, stat);
1579 /* test invalid values */
1580 stat = GdipGetImageHorizontalResolution(NULL, &res);
1581 expect(InvalidParameter, stat);
1583 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1584 expect(InvalidParameter, stat);
1586 stat = GdipGetImageVerticalResolution(NULL, &res);
1587 expect(InvalidParameter, stat);
1589 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1590 expect(InvalidParameter, stat);
1592 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1593 expect(InvalidParameter, stat);
1595 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1596 expect(InvalidParameter, stat);
1598 /* defaults to screen resolution */
1599 screendc = GetDC(0);
1601 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1602 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1604 ReleaseDC(0, screendc);
1606 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1607 expect(Ok, stat);
1608 expectf((REAL)screenxres, res);
1610 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1611 expect(Ok, stat);
1612 expectf((REAL)screenyres, res);
1614 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1615 expect(Ok, stat);
1616 stat = GdipGetDpiX(graphics, &res);
1617 expect(Ok, stat);
1618 expectf((REAL)screenxres, res);
1619 stat = GdipGetDpiY(graphics, &res);
1620 expect(Ok, stat);
1621 expectf((REAL)screenyres, res);
1623 /* test changing the resolution */
1624 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1625 expect(Ok, stat);
1627 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1628 expect(Ok, stat);
1629 expectf(screenxres*2.0, res);
1631 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1632 expect(Ok, stat);
1633 expectf(screenyres*3.0, res);
1635 stat = GdipGetDpiX(graphics, &res);
1636 expect(Ok, stat);
1637 expectf((REAL)screenxres, res);
1638 stat = GdipGetDpiY(graphics, &res);
1639 expect(Ok, stat);
1640 expectf((REAL)screenyres, res);
1642 stat = GdipDeleteGraphics(graphics);
1643 expect(Ok, stat);
1645 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1646 expect(Ok, stat);
1647 stat = GdipGetDpiX(graphics, &res);
1648 expect(Ok, stat);
1649 expectf(screenxres*2.0, res);
1650 stat = GdipGetDpiY(graphics, &res);
1651 expect(Ok, stat);
1652 expectf(screenyres*3.0, res);
1653 stat = GdipDeleteGraphics(graphics);
1654 expect(Ok, stat);
1656 stat = GdipDisposeImage((GpImage*)bitmap);
1657 expect(Ok, stat);
1660 static void test_createhbitmap(void)
1662 GpStatus stat;
1663 GpBitmap *bitmap;
1664 HBITMAP hbitmap, oldhbitmap;
1665 BITMAP bm;
1666 int ret;
1667 HDC hdc;
1668 COLORREF pixel;
1669 BYTE bits[640];
1670 BitmapData lockeddata;
1672 memset(bits, 0x68, 640);
1674 /* create Bitmap */
1675 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1676 expect(Ok, stat);
1678 /* test NULL values */
1679 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1680 expect(InvalidParameter, stat);
1682 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1683 expect(InvalidParameter, stat);
1685 /* create HBITMAP */
1686 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1687 expect(Ok, stat);
1689 if (stat == Ok)
1691 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1692 expect(sizeof(BITMAP), ret);
1694 expect(0, bm.bmType);
1695 expect(10, bm.bmWidth);
1696 expect(20, bm.bmHeight);
1697 expect(40, bm.bmWidthBytes);
1698 expect(1, bm.bmPlanes);
1699 expect(32, bm.bmBitsPixel);
1700 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1702 if (bm.bmBits)
1704 DWORD val = *(DWORD*)bm.bmBits;
1705 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1708 hdc = CreateCompatibleDC(NULL);
1710 oldhbitmap = SelectObject(hdc, hbitmap);
1711 pixel = GetPixel(hdc, 5, 5);
1712 SelectObject(hdc, oldhbitmap);
1714 DeleteDC(hdc);
1716 expect(0x686868, pixel);
1718 DeleteObject(hbitmap);
1721 stat = GdipDisposeImage((GpImage*)bitmap);
1722 expect(Ok, stat);
1724 /* make (1,0) have no alpha and (2,0) a different blue value. */
1725 bits[7] = 0x00;
1726 bits[8] = 0x40;
1728 /* create alpha Bitmap */
1729 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1730 expect(Ok, stat);
1732 /* create HBITMAP */
1733 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1734 expect(Ok, stat);
1736 if (stat == Ok)
1738 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1739 expect(sizeof(BITMAP), ret);
1741 expect(0, bm.bmType);
1742 expect(8, bm.bmWidth);
1743 expect(20, bm.bmHeight);
1744 expect(32, bm.bmWidthBytes);
1745 expect(1, bm.bmPlanes);
1746 expect(32, bm.bmBitsPixel);
1747 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1749 if (bm.bmBits)
1751 DWORD val = *(DWORD*)bm.bmBits;
1752 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1753 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1754 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1757 hdc = CreateCompatibleDC(NULL);
1759 oldhbitmap = SelectObject(hdc, hbitmap);
1760 pixel = GetPixel(hdc, 5, 5);
1761 expect(0x2a2a2a, pixel);
1762 pixel = GetPixel(hdc, 1, 0);
1763 expect(0x0, pixel);
1765 SelectObject(hdc, oldhbitmap);
1767 DeleteDC(hdc);
1770 DeleteObject(hbitmap);
1773 /* create HBITMAP with bkgnd colour */
1774 /* gdiplus.dll 5.1 is broken and only applies the blue value */
1775 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1776 expect(Ok, stat);
1778 if (stat == Ok)
1780 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1781 expect(sizeof(BITMAP), ret);
1783 expect(0, bm.bmType);
1784 expect(8, bm.bmWidth);
1785 expect(20, bm.bmHeight);
1786 expect(32, bm.bmWidthBytes);
1787 expect(1, bm.bmPlanes);
1788 expect(32, bm.bmBitsPixel);
1789 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1791 if (bm.bmBits)
1793 DWORD val = *(DWORD*)bm.bmBits;
1794 ok(val == 0x68c12ac1 || broken(val == 0x682a2ac1), "got %x, expected 0x68c12ac1\n", val);
1795 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1796 ok(val == 0xff00ff || broken(val == 0xff), "got %x, expected 0xff00ff\n", val);
1799 hdc = CreateCompatibleDC(NULL);
1801 oldhbitmap = SelectObject(hdc, hbitmap);
1802 pixel = GetPixel(hdc, 5, 5);
1803 ok(pixel == 0xc12ac1 || broken(pixel == 0xc12a2a), "got %x, expected 0xc12ac1\n", pixel);
1804 pixel = GetPixel(hdc, 1, 0);
1805 ok(pixel == 0xff00ff || broken(pixel == 0xff0000), "got %x, expected 0xff00ff\n", pixel);
1806 pixel = GetPixel(hdc, 2, 0);
1807 ok(pixel == 0xb12ac1 || broken(pixel == 0xb12a2a), "got %x, expected 0xb12ac1\n", pixel);
1809 SelectObject(hdc, oldhbitmap);
1810 DeleteDC(hdc);
1811 DeleteObject(hbitmap);
1814 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1815 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1816 expect(Ok, stat);
1818 if (stat == Ok)
1820 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1821 expect(sizeof(BITMAP), ret);
1823 expect(0, bm.bmType);
1824 expect(8, bm.bmWidth);
1825 expect(20, bm.bmHeight);
1826 expect(32, bm.bmWidthBytes);
1827 expect(1, bm.bmPlanes);
1828 expect(32, bm.bmBitsPixel);
1829 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1831 if (bm.bmBits)
1833 DWORD val = *(DWORD*)bm.bmBits;
1834 ok(val == 0x68c12ac1 || broken(val == 0x682a2ac1), "got %x, expected 0x68c12ac1\n", val);
1835 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1836 ok(val == 0xff00ff || broken(val == 0xff), "got %x, expected 0xff00ff\n", val);
1839 hdc = CreateCompatibleDC(NULL);
1841 oldhbitmap = SelectObject(hdc, hbitmap);
1842 pixel = GetPixel(hdc, 5, 5);
1843 ok(pixel == 0xc12ac1 || broken(pixel == 0xc12a2a), "got %x, expected 0xc12ac1\n", pixel);
1844 pixel = GetPixel(hdc, 1, 0);
1845 ok(pixel == 0xff00ff || broken(pixel == 0xff0000), "got %x, expected 0xff00ff\n", pixel);
1846 pixel = GetPixel(hdc, 2, 0);
1847 ok(pixel == 0xb12ac1 || broken(pixel == 0xb12a2a), "got %x, expected 0xb12ac1\n", pixel);
1849 SelectObject(hdc, oldhbitmap);
1850 DeleteDC(hdc);
1851 DeleteObject(hbitmap);
1854 stat = GdipDisposeImage((GpImage*)bitmap);
1855 expect(Ok, stat);
1857 /* create HBITMAP from locked data */
1858 memset(bits, 0x68, 640);
1859 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1860 expect(Ok, stat);
1862 memset(&lockeddata, 0, sizeof(lockeddata));
1863 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite,
1864 PixelFormat32bppRGB, &lockeddata);
1865 expect(Ok, stat);
1866 ((DWORD*)lockeddata.Scan0)[0] = 0xff242424;
1867 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1868 expect(Ok, stat);
1869 stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
1870 expect(Ok, stat);
1871 stat = GdipDisposeImage((GpImage*)bitmap);
1872 expect(Ok, stat);
1874 hdc = CreateCompatibleDC(NULL);
1875 oldhbitmap = SelectObject(hdc, hbitmap);
1876 pixel = GetPixel(hdc, 0, 0);
1877 expect(0x686868, pixel);
1878 SelectObject(hdc, oldhbitmap);
1879 DeleteDC(hdc);
1882 static void test_getthumbnail(void)
1884 GpStatus stat;
1885 GpImage *bitmap1, *bitmap2;
1886 UINT width, height;
1888 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1889 expect(InvalidParameter, stat);
1891 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1892 expect(Ok, stat);
1894 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1895 expect(InvalidParameter, stat);
1897 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1898 expect(Ok, stat);
1900 if (stat == Ok)
1902 stat = GdipGetImageWidth(bitmap2, &width);
1903 expect(Ok, stat);
1904 expect(120, width);
1906 stat = GdipGetImageHeight(bitmap2, &height);
1907 expect(Ok, stat);
1908 expect(120, height);
1910 GdipDisposeImage(bitmap2);
1913 GdipDisposeImage(bitmap1);
1916 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1917 expect(Ok, stat);
1919 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1920 expect(Ok, stat);
1922 if (stat == Ok)
1924 stat = GdipGetImageWidth(bitmap2, &width);
1925 expect(Ok, stat);
1926 expect(32, width);
1928 stat = GdipGetImageHeight(bitmap2, &height);
1929 expect(Ok, stat);
1930 expect(32, height);
1932 GdipDisposeImage(bitmap2);
1935 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1936 expect(Ok, stat);
1938 if (stat == Ok)
1940 stat = GdipGetImageWidth(bitmap2, &width);
1941 expect(Ok, stat);
1942 expect(120, width);
1944 stat = GdipGetImageHeight(bitmap2, &height);
1945 expect(Ok, stat);
1946 expect(120, height);
1948 GdipDisposeImage(bitmap2);
1951 GdipDisposeImage(bitmap1);
1954 static void test_getsetpixel(void)
1956 GpStatus stat;
1957 GpBitmap *bitmap;
1958 ARGB color;
1959 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1960 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1962 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1963 expect(Ok, stat);
1965 /* null parameters */
1966 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1967 expect(InvalidParameter, stat);
1969 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1970 expect(InvalidParameter, stat);
1972 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1973 expect(InvalidParameter, stat);
1975 /* out of bounds */
1976 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1977 expect(InvalidParameter, stat);
1979 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1980 expect(InvalidParameter, stat);
1982 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1983 ok(stat == InvalidParameter ||
1984 broken(stat == Ok), /* Older gdiplus */
1985 "Expected InvalidParameter, got %.8x\n", stat);
1987 if (0) /* crashes some gdiplus implementations */
1989 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1990 ok(stat == InvalidParameter ||
1991 broken(stat == Ok), /* Older gdiplus */
1992 "Expected InvalidParameter, got %.8x\n", stat);
1995 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1996 expect(InvalidParameter, stat);
1998 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1999 expect(InvalidParameter, stat);
2001 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
2002 expect(InvalidParameter, stat);
2004 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
2005 expect(InvalidParameter, stat);
2007 /* valid use */
2008 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2009 expect(Ok, stat);
2010 expect(0xffffffff, color);
2012 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2013 expect(Ok, stat);
2014 expect(0xff0000ff, color);
2016 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
2017 expect(Ok, stat);
2019 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
2020 expect(Ok, stat);
2022 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2023 expect(Ok, stat);
2024 expect(0xff676869, color);
2026 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2027 expect(Ok, stat);
2028 expect(0xff474849, color);
2030 stat = GdipDisposeImage((GpImage*)bitmap);
2031 expect(Ok, stat);
2034 static void check_halftone_palette(ColorPalette *palette)
2036 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
2037 UINT i;
2039 for (i=0; i<palette->Count; i++)
2041 ARGB expected=0xff000000;
2042 if (i<8)
2044 if (i&1) expected |= 0x800000;
2045 if (i&2) expected |= 0x8000;
2046 if (i&4) expected |= 0x80;
2048 else if (i == 8)
2050 expected = 0xffc0c0c0;
2052 else if (i < 16)
2054 if (i&1) expected |= 0xff0000;
2055 if (i&2) expected |= 0xff00;
2056 if (i&4) expected |= 0xff;
2058 else if (i < 40)
2060 expected = 0x00000000;
2062 else
2064 expected |= halftone_values[(i-40)%6];
2065 expected |= halftone_values[((i-40)/6)%6] << 8;
2066 expected |= halftone_values[((i-40)/36)%6] << 16;
2068 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2069 expected, palette->Entries[i], i, palette->Count);
2073 static void test_palette(void)
2075 GpStatus stat;
2076 GpBitmap *bitmap;
2077 INT size;
2078 BYTE buffer[1040];
2079 ColorPalette *palette=(ColorPalette*)buffer;
2080 ARGB *entries = palette->Entries;
2081 ARGB color=0;
2083 /* test initial palette from non-indexed bitmap */
2084 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2085 expect(Ok, stat);
2087 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2088 expect(Ok, stat);
2089 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2091 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2092 expect(Ok, stat);
2093 expect(0, palette->Count);
2095 /* test setting palette on not-indexed bitmap */
2096 palette->Count = 3;
2098 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2099 expect(Ok, stat);
2101 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2102 expect(Ok, stat);
2103 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2105 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2106 expect(Ok, stat);
2107 expect(3, palette->Count);
2109 GdipDisposeImage((GpImage*)bitmap);
2111 /* test initial palette on 1-bit bitmap */
2112 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2113 expect(Ok, stat);
2115 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2116 expect(Ok, stat);
2117 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2119 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2120 expect(Ok, stat);
2121 expect(PaletteFlagsGrayScale, palette->Flags);
2122 expect(2, palette->Count);
2124 expect(0xff000000, entries[0]);
2125 expect(0xffffffff, entries[1]);
2127 /* test getting/setting pixels */
2128 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2129 expect(Ok, stat);
2130 expect(0xff000000, color);
2132 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2133 ok((stat == Ok) ||
2134 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2136 if (stat == Ok)
2138 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2139 expect(Ok, stat);
2140 expect(0xffffffff, color);
2143 GdipDisposeImage((GpImage*)bitmap);
2145 /* test initial palette on 4-bit bitmap */
2146 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2147 expect(Ok, stat);
2149 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2150 expect(Ok, stat);
2151 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2153 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2154 expect(Ok, stat);
2155 expect(0, palette->Flags);
2156 expect(16, palette->Count);
2158 check_halftone_palette(palette);
2160 /* test getting/setting pixels */
2161 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2162 expect(Ok, stat);
2163 expect(0xff000000, color);
2165 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2166 ok((stat == Ok) ||
2167 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2169 if (stat == Ok)
2171 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2172 expect(Ok, stat);
2173 expect(0xffff00ff, color);
2176 GdipDisposeImage((GpImage*)bitmap);
2178 /* test initial palette on 8-bit bitmap */
2179 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2180 expect(Ok, stat);
2182 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2183 expect(Ok, stat);
2184 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2186 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2187 expect(Ok, stat);
2188 expect(PaletteFlagsHalftone, palette->Flags);
2189 expect(256, palette->Count);
2191 check_halftone_palette(palette);
2193 /* test getting/setting pixels */
2194 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2195 expect(Ok, stat);
2196 expect(0xff000000, color);
2198 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2199 ok((stat == Ok) ||
2200 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2202 if (stat == Ok)
2204 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2205 expect(Ok, stat);
2206 expect(0xffcccccc, color);
2209 /* test setting/getting a different palette */
2210 entries[1] = 0xffcccccc;
2212 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2213 expect(Ok, stat);
2215 entries[1] = 0;
2217 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2218 expect(Ok, stat);
2219 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2221 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2222 expect(Ok, stat);
2223 expect(PaletteFlagsHalftone, palette->Flags);
2224 expect(256, palette->Count);
2225 expect(0xffcccccc, entries[1]);
2227 /* test count < 256 */
2228 palette->Flags = 12345;
2229 palette->Count = 3;
2231 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2232 expect(Ok, stat);
2234 entries[1] = 0;
2235 entries[3] = 0xdeadbeef;
2237 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2238 expect(Ok, stat);
2239 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2241 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2242 expect(Ok, stat);
2243 expect(12345, palette->Flags);
2244 expect(3, palette->Count);
2245 expect(0xffcccccc, entries[1]);
2246 expect(0xdeadbeef, entries[3]);
2248 /* test count > 256 */
2249 palette->Count = 257;
2251 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2252 ok(stat == InvalidParameter ||
2253 broken(stat == Ok), /* Old gdiplus behavior */
2254 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2256 GdipDisposeImage((GpImage*)bitmap);
2259 static void test_colormatrix(void)
2261 GpStatus stat;
2262 ColorMatrix colormatrix, graymatrix;
2263 GpImageAttributes *imageattr;
2264 const ColorMatrix identity = {{
2265 {1.0,0.0,0.0,0.0,0.0},
2266 {0.0,1.0,0.0,0.0,0.0},
2267 {0.0,0.0,1.0,0.0,0.0},
2268 {0.0,0.0,0.0,1.0,0.0},
2269 {0.0,0.0,0.0,0.0,1.0}}};
2270 const ColorMatrix double_red = {{
2271 {2.0,0.0,0.0,0.0,0.0},
2272 {0.0,1.0,0.0,0.0,0.0},
2273 {0.0,0.0,1.0,0.0,0.0},
2274 {0.0,0.0,0.0,1.0,0.0},
2275 {0.0,0.0,0.0,0.0,1.0}}};
2276 const ColorMatrix asymmetric = {{
2277 {0.0,1.0,0.0,0.0,0.0},
2278 {0.0,0.0,1.0,0.0,0.0},
2279 {0.0,0.0,0.0,1.0,0.0},
2280 {1.0,0.0,0.0,0.0,0.0},
2281 {0.0,0.0,0.0,0.0,1.0}}};
2282 GpBitmap *bitmap1, *bitmap2;
2283 GpGraphics *graphics;
2284 ARGB color;
2286 colormatrix = identity;
2287 graymatrix = identity;
2289 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2290 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2291 expect(InvalidParameter, stat);
2293 stat = GdipCreateImageAttributes(&imageattr);
2294 expect(Ok, stat);
2296 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2297 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2298 expect(Ok, stat);
2300 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2301 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2302 expect(InvalidParameter, stat);
2304 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2305 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2306 expect(Ok, stat);
2308 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2309 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2310 expect(Ok, stat);
2312 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2313 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2314 expect(InvalidParameter, stat);
2316 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2317 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2318 expect(Ok, stat);
2320 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2321 TRUE, &colormatrix, &graymatrix, 3);
2322 expect(InvalidParameter, stat);
2324 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2325 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2326 expect(InvalidParameter, stat);
2328 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2329 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2330 expect(InvalidParameter, stat);
2332 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2333 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2334 expect(Ok, stat);
2336 /* Drawing a bitmap transforms the colors */
2337 colormatrix = double_red;
2338 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2339 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2340 expect(Ok, stat);
2342 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2343 expect(Ok, stat);
2345 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2346 expect(Ok, stat);
2348 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2349 expect(Ok, stat);
2351 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2352 expect(Ok, stat);
2354 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2355 UnitPixel, imageattr, NULL, NULL);
2356 expect(Ok, stat);
2358 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2359 expect(Ok, stat);
2360 expect(0xff80ccee, color);
2362 colormatrix = asymmetric;
2363 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2364 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2365 expect(Ok, stat);
2367 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2368 expect(Ok, stat);
2370 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2371 UnitPixel, imageattr, NULL, NULL);
2372 expect(Ok, stat);
2374 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2375 expect(Ok, stat);
2376 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2378 /* Toggle NoOp */
2379 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, FALSE);
2380 expect(Ok, stat);
2382 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2383 UnitPixel, imageattr, NULL, NULL);
2384 expect(Ok, stat);
2386 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2387 expect(Ok, stat);
2388 ok(color_match(0xfefe40cc, color, 3), "expected 0xfefe40cc, got 0x%08x\n", color);
2390 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, TRUE);
2391 expect(Ok, stat);
2393 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2394 UnitPixel, imageattr, NULL, NULL);
2395 expect(Ok, stat);
2397 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2398 expect(Ok, stat);
2399 ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2401 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2402 expect(Ok, stat);
2404 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, FALSE);
2405 expect(Ok, stat);
2407 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2408 UnitPixel, imageattr, NULL, NULL);
2409 expect(Ok, stat);
2411 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2412 expect(Ok, stat);
2413 ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2415 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2416 UnitPixel, imageattr, NULL, NULL);
2417 expect(Ok, stat);
2419 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2420 expect(Ok, stat);
2421 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2423 /* Disable adjustment, toggle NoOp */
2424 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2425 FALSE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2426 expect(Ok, stat);
2428 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, FALSE);
2429 expect(Ok, stat);
2431 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2432 UnitPixel, imageattr, NULL, NULL);
2433 expect(Ok, stat);
2435 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2436 expect(Ok, stat);
2437 ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2439 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, TRUE);
2440 expect(Ok, stat);
2442 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2443 UnitPixel, imageattr, NULL, NULL);
2444 expect(Ok, stat);
2446 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2447 expect(Ok, stat);
2448 ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2450 /* Reset with NoOp on, enable adjustment. */
2451 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2452 expect(Ok, stat);
2454 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2455 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2456 expect(Ok, stat);
2458 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2459 UnitPixel, imageattr, NULL, NULL);
2460 expect(Ok, stat);
2462 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2463 expect(Ok, stat);
2464 ok(color_match(0xfff24ace, color, 3), "expected 0xfff24ace, got 0x%08x\n", color);
2466 /* Now inhibit specific category. */
2467 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2468 expect(Ok, stat);
2470 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeBitmap,
2471 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2472 expect(Ok, stat);
2474 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2475 UnitPixel, imageattr, NULL, NULL);
2476 expect(Ok, stat);
2478 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2479 expect(Ok, stat);
2480 ok(color_match(0xfffe41cc, color, 3), "expected 0xfffe41cc, got 0x%08x\n", color);
2482 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeBitmap, TRUE);
2483 expect(Ok, stat);
2485 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2486 UnitPixel, imageattr, NULL, NULL);
2487 expect(Ok, stat);
2489 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2490 expect(Ok, stat);
2491 ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2493 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeBitmap, FALSE);
2494 expect(Ok, stat);
2496 stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, TRUE);
2497 expect(Ok, stat);
2499 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2500 UnitPixel, imageattr, NULL, NULL);
2501 expect(Ok, stat);
2503 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2504 expect(Ok, stat);
2505 ok(color_match(0xfff24ace, color, 3), "expected 0xfff24ace, got 0x%08x\n", color);
2507 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeBitmap);
2508 expect(Ok, stat);
2510 stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2511 UnitPixel, imageattr, NULL, NULL);
2512 expect(Ok, stat);
2514 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2515 expect(Ok, stat);
2516 ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2518 GdipDeleteGraphics(graphics);
2519 GdipDisposeImage((GpImage*)bitmap1);
2520 GdipDisposeImage((GpImage*)bitmap2);
2521 GdipDisposeImageAttributes(imageattr);
2524 static void test_gamma(void)
2526 GpStatus stat;
2527 GpImageAttributes *imageattr;
2528 GpBitmap *bitmap1, *bitmap2;
2529 GpGraphics *graphics;
2530 ARGB color;
2532 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2533 expect(InvalidParameter, stat);
2535 stat = GdipCreateImageAttributes(&imageattr);
2536 expect(Ok, stat);
2538 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2539 expect(Ok, stat);
2541 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2542 expect(InvalidParameter, stat);
2544 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2545 expect(InvalidParameter, stat);
2547 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2548 expect(InvalidParameter, stat);
2550 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2551 expect(Ok, stat);
2553 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2554 expect(Ok, stat);
2556 /* Drawing a bitmap transforms the colors */
2557 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2558 expect(Ok, stat);
2560 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2561 expect(Ok, stat);
2563 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2564 expect(Ok, stat);
2566 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2567 expect(Ok, stat);
2569 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2570 expect(Ok, stat);
2572 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2573 UnitPixel, imageattr, NULL, NULL);
2574 expect(Ok, stat);
2576 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2577 expect(Ok, stat);
2578 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2580 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2581 expect(Ok, stat);
2583 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2584 UnitPixel, imageattr, NULL, NULL);
2585 expect(Ok, stat);
2587 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2588 expect(Ok, stat);
2589 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2591 GdipDeleteGraphics(graphics);
2592 GdipDisposeImage((GpImage*)bitmap1);
2593 GdipDisposeImage((GpImage*)bitmap2);
2594 GdipDisposeImageAttributes(imageattr);
2597 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2598 static const unsigned char gifanimation[72] = {
2599 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2600 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2601 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2602 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2603 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2606 /* Generated with ImageMagick:
2607 * convert -transparent black -delay 100 -size 8x2 xc:black \
2608 * -dispose none -page +0+0 -size 2x2 xc:red \
2609 * -dispose background -page +2+0 -size 2x2 xc:blue \
2610 * -dispose previous -page +4+0 -size 2x2 xc:green \
2611 * -dispose undefined -page +6+0 -size 2x2 xc:gray \
2612 * test.gif
2614 static const unsigned char gifanimation2[] = {
2615 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2616 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2617 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2618 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2619 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2620 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2621 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2622 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2623 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2624 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2625 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2626 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2627 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2628 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2629 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2630 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2631 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2632 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2633 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2634 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2635 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2636 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2637 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2638 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2639 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2640 0x3b
2643 static ARGB gifanimation2_pixels[5][4] = {
2644 {0, 0, 0, 0},
2645 {0xffff0000, 0, 0, 0},
2646 {0xffff0000, 0xff0000ff, 0, 0},
2647 {0xffff0000, 0, 0xff008000, 0},
2648 {0xffff0000, 0, 0, 0xff7e7e7e}
2651 static void test_multiframegif(void)
2653 LPSTREAM stream;
2654 HGLOBAL hglob;
2655 LPBYTE data;
2656 HRESULT hres;
2657 GpStatus stat;
2658 GpBitmap *bmp;
2659 ARGB color;
2660 UINT count;
2661 GUID dimension;
2662 PixelFormat pixel_format;
2663 INT palette_size, i, j;
2664 char palette_buf[256];
2665 ColorPalette *palette;
2666 ARGB *palette_entries;
2668 /* Test frame functions with an animated GIF */
2669 hglob = GlobalAlloc (0, sizeof(gifanimation));
2670 data = GlobalLock (hglob);
2671 memcpy(data, gifanimation, sizeof(gifanimation));
2672 GlobalUnlock(hglob);
2674 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2675 ok(hres == S_OK, "Failed to create a stream\n");
2676 if(hres != S_OK) return;
2678 stat = GdipCreateBitmapFromStream(stream, &bmp);
2679 ok(stat == Ok, "Failed to create a Bitmap\n");
2680 if(stat != Ok){
2681 IStream_Release(stream);
2682 return;
2685 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2686 expect(Ok, stat);
2687 expect(PixelFormat32bppARGB, pixel_format);
2689 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2690 expect(Ok, stat);
2691 ok(palette_size == sizeof(ColorPalette) ||
2692 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2693 "palette_size = %d\n", palette_size);
2695 /* Bitmap starts at frame 0 */
2696 color = 0xdeadbeef;
2697 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2698 expect(Ok, stat);
2699 expect(0xffffffff, color);
2701 /* Check that we get correct metadata */
2702 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2703 expect(Ok, stat);
2704 expect(1, count);
2706 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2707 expect(Ok, stat);
2708 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2710 count = 12345;
2711 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2712 expect(Ok, stat);
2713 expect(2, count);
2715 /* SelectActiveFrame overwrites our current data */
2716 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2717 expect(Ok, stat);
2719 color = 0xdeadbeef;
2720 GdipBitmapGetPixel(bmp, 0, 0, &color);
2721 expect(Ok, stat);
2722 expect(0xff000000, color);
2724 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2725 expect(Ok, stat);
2727 color = 0xdeadbeef;
2728 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2729 expect(Ok, stat);
2730 expect(0xffffffff, color);
2732 /* Write over the image data */
2733 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2734 expect(Ok, stat);
2736 /* Switching to the same frame does not overwrite our changes */
2737 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2738 expect(Ok, stat);
2740 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2741 expect(Ok, stat);
2742 expect(0xff000000, color);
2744 /* But switching to another frame and back does */
2745 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2746 expect(Ok, stat);
2748 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2749 expect(Ok, stat);
2751 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2752 expect(Ok, stat);
2753 expect(0xffffffff, color);
2755 /* rotate/flip discards the information about other frames */
2756 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2757 expect(Ok, stat);
2759 count = 12345;
2760 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2761 expect(Ok, stat);
2762 expect(1, count);
2764 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2766 GdipDisposeImage((GpImage*)bmp);
2767 IStream_Release(stream);
2769 /* Test with a non-animated gif */
2770 hglob = GlobalAlloc (0, sizeof(gifimage));
2771 data = GlobalLock (hglob);
2772 memcpy(data, gifimage, sizeof(gifimage));
2773 GlobalUnlock(hglob);
2775 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2776 ok(hres == S_OK, "Failed to create a stream\n");
2777 if(hres != S_OK) return;
2779 stat = GdipCreateBitmapFromStream(stream, &bmp);
2780 ok(stat == Ok, "Failed to create a Bitmap\n");
2781 if(stat != Ok){
2782 IStream_Release(stream);
2783 return;
2786 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2787 expect(Ok, stat);
2788 expect(PixelFormat8bppIndexed, pixel_format);
2790 /* Check metadata */
2791 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2792 expect(Ok, stat);
2793 expect(1, count);
2795 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2796 expect(Ok, stat);
2797 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2799 count = 12345;
2800 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2801 expect(Ok, stat);
2802 expect(1, count);
2804 GdipDisposeImage((GpImage*)bmp);
2805 IStream_Release(stream);
2807 /* Test with a non-animated transparent gif */
2808 hglob = GlobalAlloc (0, sizeof(transparentgif));
2809 data = GlobalLock (hglob);
2810 memcpy(data, transparentgif, sizeof(transparentgif));
2811 GlobalUnlock(hglob);
2813 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2814 ok(hres == S_OK, "Failed to create a stream\n");
2816 stat = GdipCreateBitmapFromStream(stream, &bmp);
2817 IStream_Release(stream);
2818 ok(stat == Ok, "Failed to create a Bitmap\n");
2820 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2821 expect(Ok, stat);
2822 expect(PixelFormat8bppIndexed, pixel_format);
2824 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2825 expect(Ok, stat);
2826 expect(0, color);
2828 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2829 expect(Ok, stat);
2830 ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB),
2831 "palette_size = %d\n", palette_size);
2833 memset(palette_buf, 0xfe, sizeof(palette_buf));
2834 palette = (ColorPalette*)palette_buf;
2835 stat = GdipGetImagePalette((GpImage*)bmp, palette,
2836 sizeof(ColorPalette)+sizeof(ARGB));
2837 palette_entries = palette->Entries;
2838 expect(Ok, stat);
2839 expect(PaletteFlagsHasAlpha, palette->Flags);
2840 expect(2, palette->Count);
2841 expect(0, palette_entries[0]);
2842 expect(0xff000000, palette_entries[1]);
2844 count = 12345;
2845 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2846 expect(Ok, stat);
2847 expect(1, count);
2849 GdipDisposeImage((GpImage*)bmp);
2851 /* Test frame dispose methods */
2852 hglob = GlobalAlloc (0, sizeof(gifanimation2));
2853 data = GlobalLock (hglob);
2854 memcpy(data, gifanimation2, sizeof(gifanimation2));
2855 GlobalUnlock(hglob);
2857 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2858 ok(hres == S_OK, "Failed to create a stream\n");
2860 stat = GdipCreateBitmapFromStream(stream, &bmp);
2861 ok(stat == Ok, "Failed to create a Bitmap\n");
2862 IStream_Release(stream);
2864 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2865 expect(Ok, stat);
2866 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2868 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2869 expect(Ok, stat);
2870 expect(5, count);
2872 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2873 expect(Ok, stat);
2874 expect(0, color);
2876 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2877 expect(Ok, stat);
2878 stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2879 expect(Ok, stat);
2880 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2881 if(color != 0) {
2882 win_skip("broken animated gif support\n");
2883 GdipDisposeImage((GpImage*)bmp);
2884 return;
2887 for(i=0; i<6; i++) {
2888 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2889 expect(Ok, stat);
2891 for(j=0; j<4; j++) {
2892 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2893 expect(Ok, stat);
2894 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2898 GdipDisposeImage((GpImage*)bmp);
2901 static void test_rotateflip(void)
2903 GpImage *bitmap;
2904 GpStatus stat;
2905 BYTE bits[24];
2906 static const BYTE orig_bits[24] = {
2907 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2908 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2909 UINT width, height;
2910 ARGB color;
2912 memcpy(bits, orig_bits, sizeof(bits));
2913 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2914 expect(Ok, stat);
2916 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2917 expect(Ok, stat);
2919 stat = GdipGetImageWidth(bitmap, &width);
2920 expect(Ok, stat);
2921 stat = GdipGetImageHeight(bitmap, &height);
2922 expect(Ok, stat);
2923 expect(2, width);
2924 expect(3, height);
2926 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2927 expect(Ok, stat);
2928 expect(0xff00ffff, color);
2930 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2931 expect(Ok, stat);
2932 expect(0xffff0000, color);
2934 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2935 expect(Ok, stat);
2936 expect(0xffffff00, color);
2938 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2939 expect(Ok, stat);
2940 expect(0xff0000ff, color);
2942 expect(0, bits[0]);
2943 expect(0, bits[1]);
2944 expect(0xff, bits[2]);
2946 GdipDisposeImage(bitmap);
2948 memcpy(bits, orig_bits, sizeof(bits));
2949 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2950 expect(Ok, stat);
2952 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2953 expect(Ok, stat);
2955 stat = GdipGetImageWidth(bitmap, &width);
2956 expect(Ok, stat);
2957 stat = GdipGetImageHeight(bitmap, &height);
2958 expect(Ok, stat);
2959 expect(3, width);
2960 expect(2, height);
2962 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2963 expect(Ok, stat);
2964 expect(0xff0000ff, color);
2966 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2967 expect(Ok, stat);
2968 expect(0xffff0000, color);
2970 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2971 expect(Ok, stat);
2972 expect(0xffffff00, color);
2974 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2975 expect(Ok, stat);
2976 expect(0xff00ffff, color);
2978 expect(0, bits[0]);
2979 expect(0, bits[1]);
2980 expect(0xff, bits[2]);
2982 GdipDisposeImage(bitmap);
2984 memcpy(bits, orig_bits, sizeof(bits));
2985 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2986 expect(Ok, stat);
2988 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2989 expect(Ok, stat);
2991 stat = GdipGetImageWidth(bitmap, &width);
2992 expect(Ok, stat);
2993 stat = GdipGetImageHeight(bitmap, &height);
2994 expect(Ok, stat);
2995 expect(3, width);
2996 expect(2, height);
2998 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2999 expect(Ok, stat);
3000 expect(0xff00ffff, color);
3002 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
3003 expect(Ok, stat);
3004 expect(0xffffff00, color);
3006 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
3007 expect(Ok, stat);
3008 expect(0xffff0000, color);
3010 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
3011 expect(Ok, stat);
3012 expect(0xff0000ff, color);
3014 expect(0, bits[0]);
3015 expect(0, bits[1]);
3016 expect(0xff, bits[2]);
3018 GdipDisposeImage(bitmap);
3021 static void test_remaptable(void)
3023 GpStatus stat;
3024 GpImageAttributes *imageattr;
3025 GpBitmap *bitmap1, *bitmap2;
3026 GpGraphics *graphics;
3027 ARGB color;
3028 ColorMap *map;
3030 map = GdipAlloc(sizeof(ColorMap));
3032 map->oldColor.Argb = 0xff00ff00;
3033 map->newColor.Argb = 0xffff00ff;
3035 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
3036 expect(InvalidParameter, stat);
3038 stat = GdipCreateImageAttributes(&imageattr);
3039 expect(Ok, stat);
3041 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
3042 expect(InvalidParameter, stat);
3044 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
3045 expect(InvalidParameter, stat);
3047 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
3048 expect(InvalidParameter, stat);
3050 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
3051 expect(InvalidParameter, stat);
3053 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
3054 expect(Ok, stat);
3056 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
3057 expect(Ok, stat);
3059 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
3060 expect(Ok, stat);
3062 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
3063 expect(Ok, stat);
3065 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
3066 expect(Ok, stat);
3068 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
3069 expect(Ok, stat);
3071 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
3072 UnitPixel, imageattr, NULL, NULL);
3073 expect(Ok, stat);
3075 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3076 expect(Ok, stat);
3077 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
3079 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3080 expect(Ok, stat);
3082 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
3083 UnitPixel, imageattr, NULL, NULL);
3084 expect(Ok, stat);
3086 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3087 expect(Ok, stat);
3088 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
3090 GdipDeleteGraphics(graphics);
3091 GdipDisposeImage((GpImage*)bitmap1);
3092 GdipDisposeImage((GpImage*)bitmap2);
3093 GdipDisposeImageAttributes(imageattr);
3094 GdipFree(map);
3097 static void test_colorkey(void)
3099 GpStatus stat;
3100 GpImageAttributes *imageattr;
3101 GpBitmap *bitmap1, *bitmap2;
3102 GpGraphics *graphics;
3103 ARGB color;
3105 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
3106 expect(InvalidParameter, stat);
3108 stat = GdipCreateImageAttributes(&imageattr);
3109 expect(Ok, stat);
3111 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
3112 expect(InvalidParameter, stat);
3114 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
3115 expect(InvalidParameter, stat);
3117 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
3118 expect(Ok, stat);
3120 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
3121 expect(Ok, stat);
3123 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
3124 expect(Ok, stat);
3126 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
3127 expect(Ok, stat);
3129 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
3130 expect(Ok, stat);
3132 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
3133 expect(Ok, stat);
3135 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
3136 expect(Ok, stat);
3138 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
3139 expect(Ok, stat);
3141 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3142 UnitPixel, imageattr, NULL, NULL);
3143 expect(Ok, stat);
3145 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3146 expect(Ok, stat);
3147 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3149 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3150 expect(Ok, stat);
3151 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3153 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3154 expect(Ok, stat);
3155 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3157 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3158 expect(Ok, stat);
3159 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3161 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3162 expect(Ok, stat);
3164 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3165 UnitPixel, imageattr, NULL, NULL);
3166 expect(Ok, stat);
3168 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3169 expect(Ok, stat);
3170 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
3172 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3173 expect(Ok, stat);
3174 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
3176 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3177 expect(Ok, stat);
3178 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
3180 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3181 expect(Ok, stat);
3182 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3185 GdipDeleteGraphics(graphics);
3186 GdipDisposeImage((GpImage*)bitmap1);
3187 GdipDisposeImage((GpImage*)bitmap2);
3188 GdipDisposeImageAttributes(imageattr);
3191 static void test_dispose(void)
3193 GpStatus stat;
3194 GpImage *image;
3195 char invalid_image[256];
3197 stat = GdipDisposeImage(NULL);
3198 expect(InvalidParameter, stat);
3200 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
3201 expect(Ok, stat);
3203 stat = GdipDisposeImage(image);
3204 expect(Ok, stat);
3206 stat = GdipDisposeImage(image);
3207 expect(ObjectBusy, stat);
3209 memset(invalid_image, 0, 256);
3210 stat = GdipDisposeImage((GpImage*)invalid_image);
3211 expect(ObjectBusy, stat);
3214 static LONG obj_refcount(void *obj)
3216 IUnknown_AddRef((IUnknown *)obj);
3217 return IUnknown_Release((IUnknown *)obj);
3220 static GpImage *load_image(const BYTE *image_data, UINT image_size, BOOL valid_data, BOOL todo_load)
3222 IStream *stream;
3223 HGLOBAL hmem;
3224 BYTE *data;
3225 HRESULT hr;
3226 GpStatus status;
3227 GpImage *image = NULL, *clone;
3228 ImageType image_type;
3229 LONG refcount, old_refcount;
3231 hmem = GlobalAlloc(0, image_size);
3232 data = GlobalLock(hmem);
3233 memcpy(data, image_data, image_size);
3234 GlobalUnlock(hmem);
3236 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3237 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3238 if (hr != S_OK) return NULL;
3240 refcount = obj_refcount(stream);
3241 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3243 status = GdipLoadImageFromStream(stream, &image);
3244 todo_wine_if(todo_load)
3245 if (valid_data)
3246 ok(status == Ok || broken(status == InvalidParameter), /* XP */
3247 "GdipLoadImageFromStream error %d\n", status);
3248 else
3249 ok(status != Ok, "GdipLoadImageFromStream should fail\n");
3250 if (status != Ok)
3252 IStream_Release(stream);
3253 return NULL;
3256 status = GdipGetImageType(image, &image_type);
3257 ok(status == Ok, "GdipGetImageType error %d\n", status);
3259 refcount = obj_refcount(stream);
3260 if (image_type == ImageTypeBitmap)
3261 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3262 else
3263 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3264 old_refcount = refcount;
3266 status = GdipCloneImage(image, &clone);
3267 ok(status == Ok, "GdipCloneImage error %d\n", status);
3268 refcount = obj_refcount(stream);
3269 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3270 status = GdipDisposeImage(clone);
3271 ok(status == Ok, "GdipDisposeImage error %d\n", status);
3272 refcount = obj_refcount(stream);
3273 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3275 refcount = IStream_Release(stream);
3276 if (image_type == ImageTypeBitmap)
3277 ok(refcount >= 1, "expected stream refcount != 0\n");
3278 else
3279 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3281 return image;
3284 static void test_image_properties(void)
3286 static const struct test_data
3288 const BYTE *image_data;
3289 UINT image_size;
3290 ImageType image_type;
3291 UINT prop_count;
3292 UINT prop_count2; /* if win7 behaves differently */
3293 /* 1st property attributes */
3294 UINT prop_size;
3295 UINT prop_size2; /* if win7 behaves differently */
3296 UINT prop_id;
3297 UINT prop_id2; /* if win7 behaves differently */
3299 td[] =
3301 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3302 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3303 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3304 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3305 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3307 GpStatus status;
3308 GpImage *image;
3309 UINT prop_count, prop_size, i;
3310 PROPID prop_id[16] = { 0 };
3311 ImageType image_type;
3312 union
3314 PropertyItem data;
3315 char buf[256];
3316 } item;
3318 for (i = 0; i < ARRAY_SIZE(td); i++)
3320 image = load_image(td[i].image_data, td[i].image_size, TRUE, FALSE);
3321 if (!image)
3323 trace("%u: failed to load image data\n", i);
3324 continue;
3327 status = GdipGetImageType(image, &image_type);
3328 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3329 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3330 i, td[i].image_type, image_type);
3332 status = GdipGetPropertyCount(image, &prop_count);
3333 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3334 todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage)
3335 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3336 " %u: expected property count %u or %u, got %u\n",
3337 i, td[i].prop_count, td[i].prop_count2, prop_count);
3339 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3340 expect(InvalidParameter, status);
3341 status = GdipGetPropertyItemSize(image, 0, NULL);
3342 expect(InvalidParameter, status);
3343 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3344 if (image_type == ImageTypeMetafile)
3345 expect(NotImplemented, status);
3346 else
3347 expect(PropertyNotFound, status);
3349 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3350 expect(InvalidParameter, status);
3351 status = GdipGetPropertyItem(image, 0, 0, NULL);
3352 expect(InvalidParameter, status);
3353 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3354 if (image_type == ImageTypeMetafile)
3355 expect(NotImplemented, status);
3356 else
3357 expect(PropertyNotFound, status);
3359 /* FIXME: remove once Wine is fixed */
3360 if (td[i].prop_count != prop_count)
3362 GdipDisposeImage(image);
3363 continue;
3366 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3367 expect(InvalidParameter, status);
3368 status = GdipGetPropertyIdList(image, prop_count, NULL);
3369 expect(InvalidParameter, status);
3370 status = GdipGetPropertyIdList(image, 0, prop_id);
3371 if (image_type == ImageTypeMetafile)
3372 expect(NotImplemented, status);
3373 else if (prop_count == 0)
3374 expect(Ok, status);
3375 else
3376 expect(InvalidParameter, status);
3377 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3378 if (image_type == ImageTypeMetafile)
3379 expect(NotImplemented, status);
3380 else
3381 expect(InvalidParameter, status);
3382 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3383 if (image_type == ImageTypeMetafile)
3384 expect(NotImplemented, status);
3385 else
3386 expect(InvalidParameter, status);
3387 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3388 if (image_type == ImageTypeMetafile)
3389 expect(NotImplemented, status);
3390 else
3392 expect(Ok, status);
3393 if (prop_count != 0)
3394 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3395 " %u: expected property id %#x or %#x, got %#x\n",
3396 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3399 if (status == Ok)
3401 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3402 if (prop_count == 0)
3403 expect(PropertyNotFound, status);
3404 else
3406 expect(Ok, status);
3408 assert(sizeof(item) >= prop_size);
3409 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3410 i, prop_size);
3411 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3412 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3413 " %u: expected property size %u or %u, got %u\n",
3414 i, td[i].prop_size, td[i].prop_size2, prop_size);
3416 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3417 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3418 "%u: expected InvalidParameter, got %d\n", i, status);
3419 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3420 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3421 "%u: expected InvalidParameter, got %d\n", i, status);
3422 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3423 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3424 "%u: expected InvalidParameter, got %d\n", i, status);
3425 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3426 expect(Ok, status);
3427 ok(prop_id[0] == item.data.id,
3428 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3432 GdipDisposeImage(image);
3436 #define IFD_BYTE 1
3437 #define IFD_ASCII 2
3438 #define IFD_SHORT 3
3439 #define IFD_LONG 4
3440 #define IFD_RATIONAL 5
3441 #define IFD_SBYTE 6
3442 #define IFD_UNDEFINED 7
3443 #define IFD_SSHORT 8
3444 #define IFD_SLONG 9
3445 #define IFD_SRATIONAL 10
3446 #define IFD_FLOAT 11
3447 #define IFD_DOUBLE 12
3449 #ifndef PropertyTagTypeSByte
3450 #define PropertyTagTypeSByte 6
3451 #define PropertyTagTypeSShort 8
3452 #define PropertyTagTypeFloat 11
3453 #define PropertyTagTypeDouble 12
3454 #endif
3456 static UINT documented_type(UINT type)
3458 switch (type)
3460 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3461 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3462 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3463 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3464 default: return type;
3468 #include "pshpack2.h"
3469 struct IFD_entry
3471 SHORT id;
3472 SHORT type;
3473 ULONG count;
3474 LONG value;
3477 struct IFD_rational
3479 LONG numerator;
3480 LONG denominator;
3483 static const struct tiff_data
3485 USHORT byte_order;
3486 USHORT version;
3487 ULONG dir_offset;
3488 USHORT number_of_entries;
3489 struct IFD_entry entry[40];
3490 ULONG next_IFD;
3491 struct IFD_rational xres;
3492 DOUBLE double_val;
3493 struct IFD_rational srational_val;
3494 char string[14];
3495 SHORT short_val[4];
3496 LONG long_val[2];
3497 FLOAT float_val[2];
3498 struct IFD_rational rational[3];
3499 BYTE pixel_data[4];
3500 } TIFF_data =
3502 #ifdef WORDS_BIGENDIAN
3503 'M' | 'M' << 8,
3504 #else
3505 'I' | 'I' << 8,
3506 #endif
3508 FIELD_OFFSET(struct tiff_data, number_of_entries),
3511 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3512 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3513 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3514 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3515 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3516 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3517 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3518 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3519 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3520 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3521 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3522 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3523 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3524 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3525 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3526 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3527 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3528 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3529 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3530 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3531 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3532 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3533 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3534 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3535 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3536 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3537 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3538 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3539 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3540 /* Some gdiplus versions ignore these fields.
3541 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3542 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3543 { 0xf014, IFD_LONG, 0, 0x11223344 },
3544 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3545 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3546 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3547 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3550 { 900, 3 },
3551 1234567890.0987654321,
3552 { 0x1a2b3c4d, 0x5a6b7c8d },
3553 "Hello World!",
3554 { 0x0101, 0x0202, 0x0303, 0x0404 },
3555 { 0x11223344, 0x55667788 },
3556 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3557 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3558 { 0x11, 0x22, 0x33, 0 }
3560 #include "poppack.h"
3562 static void test_tiff_properties(void)
3564 static const struct test_data
3566 ULONG type, id, length;
3567 const BYTE value[24];
3568 } td[31] =
3570 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3571 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3572 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3573 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3574 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3575 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3576 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3577 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3578 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3579 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3580 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3581 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3582 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3583 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3584 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3585 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3586 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3587 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3588 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3589 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3590 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3591 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3592 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3593 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3594 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3595 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3596 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3597 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3598 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3599 { PropertyTagTypeSRational, 0xf016, 24,
3600 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3601 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3602 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3603 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3604 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3606 GpStatus status;
3607 GpImage *image;
3608 GUID guid;
3609 UINT dim_count, frame_count, prop_count, prop_size, i;
3610 PROPID *prop_id;
3611 PropertyItem *prop_item;
3613 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data), TRUE, FALSE);
3614 if (!image)
3616 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3617 return;
3620 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3621 expect(Ok, status);
3622 expect(1, dim_count);
3624 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3625 expect(Ok, status);
3626 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3628 frame_count = 0xdeadbeef;
3629 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3630 expect(Ok, status);
3631 expect(1, frame_count);
3633 prop_count = 0xdeadbeef;
3634 status = GdipGetPropertyCount(image, &prop_count);
3635 expect(Ok, status);
3636 ok(prop_count == ARRAY_SIZE(td) ||
3637 broken(prop_count == ARRAY_SIZE(td) - 1) /* Win7 SP0 */,
3638 "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
3640 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3642 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3643 expect(Ok, status);
3645 for (i = 0; i < prop_count; i++)
3647 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3648 expect(Ok, status);
3649 if (status != Ok) break;
3650 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3652 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3653 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3654 expect(Ok, status);
3655 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3656 ok(td[i].type == prop_item->type ||
3657 /* Win7 stopped using proper but not documented types, and it
3658 looks broken since TypeFloat and TypeDouble now reported as
3659 TypeUndefined, and signed types reported as unsigned. */
3660 broken(prop_item->type == documented_type(td[i].type)),
3661 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3662 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3663 prop_size -= sizeof(*prop_item);
3664 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3665 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3666 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3667 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3668 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3669 if (td[i].length == prop_item->length)
3671 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3672 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3673 if (!match)
3675 UINT j;
3676 BYTE *data = prop_item->value;
3677 trace("id %#x:", prop_item->id);
3678 for (j = 0; j < prop_item->length; j++)
3679 trace(" %02x", data[j]);
3680 trace("\n");
3683 HeapFree(GetProcessHeap(), 0, prop_item);
3686 HeapFree(GetProcessHeap(), 0, prop_id);
3688 GdipDisposeImage(image);
3691 static void test_GdipGetAllPropertyItems(void)
3693 static const struct test_data
3695 ULONG type, id, length;
3696 BYTE value[32];
3697 } td[16] =
3699 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3700 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3701 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3702 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3703 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3704 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3705 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3706 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3707 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3708 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3709 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3710 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3711 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3712 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3713 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3714 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3716 GpStatus status;
3717 GpImage *image;
3718 GUID guid;
3719 UINT dim_count, frame_count, prop_count, prop_size, i;
3720 UINT total_size, total_count;
3721 PROPID *prop_id;
3722 PropertyItem *prop_item;
3723 const char *item_data;
3725 image = load_image(tiffimage, sizeof(tiffimage), TRUE, FALSE);
3726 ok(image != 0, "Failed to load TIFF image data\n");
3727 if (!image) return;
3729 dim_count = 0xdeadbeef;
3730 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3731 expect(Ok, status);
3732 expect(1, dim_count);
3734 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3735 expect(Ok, status);
3736 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3738 frame_count = 0xdeadbeef;
3739 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3740 expect(Ok, status);
3741 expect(1, frame_count);
3743 prop_count = 0xdeadbeef;
3744 status = GdipGetPropertyCount(image, &prop_count);
3745 expect(Ok, status);
3746 ok(prop_count == ARRAY_SIZE(td),
3747 "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
3749 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3751 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3752 expect(Ok, status);
3754 prop_size = 0;
3755 for (i = 0; i < prop_count; i++)
3757 UINT size;
3758 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3759 expect(Ok, status);
3760 if (status != Ok) break;
3761 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3763 prop_size += size;
3765 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3766 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3767 expect(Ok, status);
3768 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3769 ok(td[i].type == prop_item->type,
3770 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3771 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3772 size -= sizeof(*prop_item);
3773 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3774 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3775 if (td[i].length == prop_item->length)
3777 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3778 ok(match, "%u: data mismatch\n", i);
3779 if (!match)
3781 UINT j;
3782 BYTE *data = prop_item->value;
3783 trace("id %#x:", prop_item->id);
3784 for (j = 0; j < prop_item->length; j++)
3785 trace(" %02x", data[j]);
3786 trace("\n");
3789 HeapFree(GetProcessHeap(), 0, prop_item);
3792 HeapFree(GetProcessHeap(), 0, prop_id);
3794 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3795 expect(InvalidParameter, status);
3796 status = GdipGetPropertySize(image, &total_size, NULL);
3797 expect(InvalidParameter, status);
3798 status = GdipGetPropertySize(image, NULL, &total_count);
3799 expect(InvalidParameter, status);
3800 status = GdipGetPropertySize(image, NULL, NULL);
3801 expect(InvalidParameter, status);
3802 total_size = 0xdeadbeef;
3803 total_count = 0xdeadbeef;
3804 status = GdipGetPropertySize(image, &total_size, &total_count);
3805 expect(Ok, status);
3806 ok(prop_count == total_count,
3807 "expected total property count %u, got %u\n", prop_count, total_count);
3808 ok(prop_size == total_size,
3809 "expected total property size %u, got %u\n", prop_size, total_size);
3811 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3813 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3814 expect(InvalidParameter, status);
3815 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3816 expect(InvalidParameter, status);
3817 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3818 expect(InvalidParameter, status);
3819 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3820 expect(InvalidParameter, status);
3821 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3822 expect(InvalidParameter, status);
3823 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3824 expect(InvalidParameter, status);
3825 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3826 expect(Ok, status);
3828 item_data = (const char *)(prop_item + prop_count);
3829 for (i = 0; i < prop_count; i++)
3831 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3832 i, item_data, prop_item[i].value);
3833 ok(td[i].type == prop_item[i].type,
3834 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3835 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3836 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3837 if (td[i].length == prop_item[i].length)
3839 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3840 ok(match, "%u: data mismatch\n", i);
3841 if (!match)
3843 UINT j;
3844 BYTE *data = prop_item[i].value;
3845 trace("id %#x:", prop_item[i].id);
3846 for (j = 0; j < prop_item[i].length; j++)
3847 trace(" %02x", data[j]);
3848 trace("\n");
3851 item_data += prop_item[i].length;
3854 HeapFree(GetProcessHeap(), 0, prop_item);
3856 GdipDisposeImage(image);
3859 static void test_tiff_palette(void)
3861 GpStatus status;
3862 GpImage *image;
3863 PixelFormat format;
3864 INT size;
3865 struct
3867 ColorPalette pal;
3868 ARGB entry[256];
3869 } palette;
3870 ARGB *entries = palette.pal.Entries;
3872 /* 1bpp TIFF without palette */
3873 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data), TRUE, FALSE);
3874 if (!image)
3876 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3877 return;
3880 status = GdipGetImagePixelFormat(image, &format);
3881 expect(Ok, status);
3882 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3884 status = GdipGetImagePaletteSize(image, &size);
3885 ok(status == Ok || broken(status == GenericError), /* XP */
3886 "GdipGetImagePaletteSize error %d\n", status);
3887 if (status == GenericError)
3889 GdipDisposeImage(image);
3890 return;
3892 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3894 status = GdipGetImagePalette(image, &palette.pal, size);
3895 expect(Ok, status);
3896 expect(0, palette.pal.Flags);
3897 expect(2, palette.pal.Count);
3898 if (palette.pal.Count == 2)
3900 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3901 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3904 GdipDisposeImage(image);
3907 static void test_bitmapbits(void)
3909 /* 8 x 2 bitmap */
3910 static const BYTE pixels_24[48] =
3912 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3913 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3914 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3915 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3917 static const BYTE pixels_00[48] =
3919 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3920 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3921 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3922 0,0,0, 0,0,0, 0,0,0, 0,0,0
3924 static const BYTE pixels_24_77[64] =
3926 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3927 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3928 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3929 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3930 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3931 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3933 static const BYTE pixels_77[64] =
3935 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3936 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3937 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3938 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3939 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3940 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3941 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3942 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3944 static const BYTE pixels_8[16] =
3946 0x01,0,0x01,0,0x01,0,0x01,0,
3947 0x01,0,0x01,0,0x01,0,0x01,0
3949 static const BYTE pixels_8_77[64] =
3951 0x01,0,0x01,0,0x01,0,0x01,0,
3952 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3953 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3954 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3955 0x01,0,0x01,0,0x01,0,0x01,0,
3956 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3957 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3958 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3960 static const BYTE pixels_1_77[64] =
3962 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3963 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3964 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3965 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3966 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3967 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3968 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3969 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3971 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3972 static const struct test_data
3974 PixelFormat format;
3975 UINT bpp;
3976 ImageLockMode mode;
3977 UINT stride, size;
3978 const BYTE *pixels;
3979 const BYTE *pixels_unlocked;
3980 } td[] =
3982 /* 0 */
3983 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3985 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3986 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3987 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3988 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3989 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3990 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3991 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3992 /* 8 */
3993 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3994 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3995 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3996 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3997 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3998 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3999 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
4000 /* 15 */
4001 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
4002 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
4003 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
4004 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
4005 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
4006 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
4007 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
4009 BYTE buf[64];
4010 GpStatus status;
4011 GpBitmap *bitmap;
4012 UINT i;
4013 BitmapData data;
4014 struct
4016 ColorPalette pal;
4017 ARGB entries[1];
4018 } palette;
4019 ARGB *entries = palette.pal.Entries;
4021 for (i = 0; i < ARRAY_SIZE(td); i++)
4023 BYTE pixels[sizeof(pixels_24)];
4024 memcpy(pixels, pixels_24, sizeof(pixels_24));
4025 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
4026 expect(Ok, status);
4028 /* associate known palette with pixel data */
4029 palette.pal.Flags = PaletteFlagsGrayScale;
4030 palette.pal.Count = 2;
4031 entries[0] = 0xff000000;
4032 entries[1] = 0xffffffff;
4033 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
4034 expect(Ok, status);
4036 memset(&data, 0xfe, sizeof(data));
4037 if (td[i].mode & ImageLockModeUserInputBuf)
4039 memset(buf, 0x77, sizeof(buf));
4040 data.Scan0 = buf;
4041 data.Stride = 32;
4043 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
4044 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
4045 if (status != Ok)
4047 GdipDisposeImage((GpImage *)bitmap);
4048 continue;
4050 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
4051 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
4052 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
4053 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
4054 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
4055 if (td[i].mode & ImageLockModeUserInputBuf)
4056 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
4057 if (td[i].size == data.Height * data.Stride)
4059 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
4061 match = 1;
4062 for (j = 0; j < data.Height; j++)
4064 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
4066 match = 0;
4067 break;
4070 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
4072 ok(match,
4073 "%u: data should match\n", i);
4074 if (!match)
4076 BYTE *bits = data.Scan0;
4077 trace("%u: data mismatch for format %#x:", i, td[i].format);
4078 for (j = 0; j < td[i].size; j++)
4079 trace(" %02x", bits[j]);
4080 trace("\n");
4083 else
4084 ok(!match, "%u: data shouldn't match\n", i);
4086 memset(data.Scan0, 0, td[i].size);
4089 status = GdipBitmapUnlockBits(bitmap, &data);
4090 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
4092 memset(&data, 0xfe, sizeof(data));
4093 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4094 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
4095 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
4096 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
4097 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
4098 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
4099 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
4100 if (data.Height * data.Stride == 48)
4102 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
4103 ok(match, "%u: data should match\n", i);
4104 if (!match)
4106 UINT j;
4107 BYTE *bits = data.Scan0;
4108 trace("%u: data mismatch for format %#x:", i, td[i].format);
4109 for (j = 0; j < 48; j++)
4110 trace(" %02x", bits[j]);
4111 trace("\n");
4115 status = GdipBitmapUnlockBits(bitmap, &data);
4116 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
4118 status = GdipDisposeImage((GpImage *)bitmap);
4119 expect(Ok, status);
4123 static void test_DrawImage(void)
4125 BYTE black_1x1[4] = { 0,0,0,0 };
4126 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4127 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4128 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4129 0,0,0,0,0,0,0xff,0xff };
4130 GpStatus status;
4131 union
4133 GpBitmap *bitmap;
4134 GpImage *image;
4135 } u1, u2;
4136 GpGraphics *graphics;
4137 int match;
4139 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4140 expect(Ok, status);
4141 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4142 expect(Ok, status);
4144 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4145 expect(Ok, status);
4146 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4147 expect(Ok, status);
4148 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4149 expect(Ok, status);
4150 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4151 expect(Ok, status);
4153 status = GdipDrawImageI(graphics, u1.image, 0, 0);
4154 expect(Ok, status);
4156 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4157 ok(match, "data should match\n");
4158 if (!match)
4160 UINT i, size = sizeof(white_2x2);
4161 BYTE *bits = white_2x2;
4162 for (i = 0; i < size; i++)
4163 trace(" %02x", bits[i]);
4164 trace("\n");
4167 status = GdipDeleteGraphics(graphics);
4168 expect(Ok, status);
4169 status = GdipDisposeImage(u1.image);
4170 expect(Ok, status);
4171 status = GdipDisposeImage(u2.image);
4172 expect(Ok, status);
4175 static void test_DrawImage_SourceCopy(void)
4177 DWORD dst_pixels[4] = { 0xffffffff, 0xffffffff,
4178 0xffffffff, 0xffffffff };
4179 DWORD src_pixels[4] = { 0, 0xffff0000,
4180 0, 0xff00ff };
4182 GpStatus status;
4183 union
4185 GpBitmap *bitmap;
4186 GpImage *image;
4187 } u1, u2;
4188 GpGraphics *graphics;
4190 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)dst_pixels, &u1.bitmap);
4191 expect(Ok, status);
4193 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)src_pixels, &u2.bitmap);
4194 expect(Ok, status);
4195 status = GdipGetImageGraphicsContext(u1.image, &graphics);
4196 expect(Ok, status);
4197 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4198 expect(Ok, status);
4200 status = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
4201 expect(Ok, status);
4203 status = GdipDrawImageI(graphics, u2.image, 0, 0);
4204 expect(Ok, status);
4206 todo_wine expect(0, dst_pixels[0]);
4207 expect(0xffff0000, dst_pixels[1]);
4208 todo_wine expect(0, dst_pixels[2]);
4209 todo_wine expect(0, dst_pixels[3]);
4211 status = GdipDeleteGraphics(graphics);
4212 expect(Ok, status);
4213 status = GdipDisposeImage(u1.image);
4214 expect(Ok, status);
4215 status = GdipDisposeImage(u2.image);
4216 expect(Ok, status);
4219 static void test_GdipDrawImagePointRect(void)
4221 BYTE black_1x1[4] = { 0,0,0,0 };
4222 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4223 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4224 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4225 0,0,0,0,0,0,0xff,0xff };
4226 GpStatus status;
4227 union
4229 GpBitmap *bitmap;
4230 GpImage *image;
4231 } u1, u2;
4232 GpGraphics *graphics;
4233 int match;
4235 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4236 expect(Ok, status);
4237 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4238 expect(Ok, status);
4240 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4241 expect(Ok, status);
4242 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4243 expect(Ok, status);
4244 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4245 expect(Ok, status);
4246 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4247 expect(Ok, status);
4249 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
4250 expect(Ok, status);
4252 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4253 ok(match, "data should match\n");
4254 if (!match)
4256 UINT i, size = sizeof(white_2x2);
4257 BYTE *bits = white_2x2;
4258 for (i = 0; i < size; i++)
4259 trace(" %02x", bits[i]);
4260 trace("\n");
4263 status = GdipDeleteGraphics(graphics);
4264 expect(Ok, status);
4265 status = GdipDisposeImage(u1.image);
4266 expect(Ok, status);
4267 status = GdipDisposeImage(u2.image);
4268 expect(Ok, status);
4271 static void test_image_format(void)
4273 static const PixelFormat fmt[] =
4275 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4276 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4277 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4278 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4279 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4281 GpStatus status;
4282 GpBitmap *bitmap;
4283 GpImage *thumb;
4284 HBITMAP hbitmap;
4285 BITMAP bm;
4286 PixelFormat format;
4287 BitmapData data;
4288 UINT i, ret;
4290 for (i = 0; i < ARRAY_SIZE(fmt); i++)
4292 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4293 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4294 "GdipCreateBitmapFromScan0 error %d\n", status);
4295 if (status != Ok) continue;
4297 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4298 expect(Ok, status);
4299 expect(fmt[i], format);
4301 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4302 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4303 todo_wine expect(InvalidParameter, status);
4304 else
4306 expect(Ok, status);
4307 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4308 expect(sizeof(bm), ret);
4309 expect(0, bm.bmType);
4310 expect(1, bm.bmWidth);
4311 expect(1, bm.bmHeight);
4312 expect(4, bm.bmWidthBytes);
4313 expect(1, bm.bmPlanes);
4314 expect(32, bm.bmBitsPixel);
4315 DeleteObject(hbitmap);
4318 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4319 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4320 todo_wine
4321 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4322 "expected OutOfMemory, got %d\n", status);
4323 else
4324 expect(Ok, status);
4325 if (status == Ok)
4327 status = GdipGetImagePixelFormat(thumb, &format);
4328 expect(Ok, status);
4329 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4330 "expected PixelFormat32bppPARGB, got %#x\n", format);
4331 status = GdipDisposeImage(thumb);
4332 expect(Ok, status);
4335 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4336 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4337 todo_wine expect(InvalidParameter, status);
4338 else
4340 expect(Ok, status);
4341 status = GdipBitmapUnlockBits(bitmap, &data);
4342 expect(Ok, status);
4345 status = GdipDisposeImage((GpImage *)bitmap);
4346 expect(Ok, status);
4350 static void test_DrawImage_scale(void)
4352 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4353 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4354 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4355 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4356 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4357 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4358 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4359 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4360 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4361 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4362 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4363 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4364 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4365 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4366 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4367 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4368 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4369 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4370 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4371 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4372 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4373 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4374 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4375 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4376 static const struct test_data
4378 REAL scale_x;
4379 PixelOffsetMode pixel_offset_mode;
4380 const BYTE *image;
4381 BOOL todo;
4382 } td[] =
4384 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4385 { 1.0, PixelOffsetModeNone, image_100 },
4386 { 1.2, PixelOffsetModeNone, image_120 },
4387 { 1.5, PixelOffsetModeNone, image_150 },
4388 { 1.8, PixelOffsetModeNone, image_180 },
4389 { 2.0, PixelOffsetModeNone, image_200 },
4390 { 2.5, PixelOffsetModeNone, image_250 },
4392 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4393 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4394 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4395 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4396 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4397 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4398 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4400 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4401 { 1.0, PixelOffsetModeHalf, image_100 },
4402 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4403 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4404 { 1.8, PixelOffsetModeHalf, image_180 },
4405 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4406 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4408 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4409 { 1.0, PixelOffsetModeHighQuality, image_100 },
4410 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4411 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4412 { 1.8, PixelOffsetModeHighQuality, image_180 },
4413 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4414 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4416 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4417 BYTE dst_8x1[24];
4418 GpStatus status;
4419 union
4421 GpBitmap *bitmap;
4422 GpImage *image;
4423 } u1, u2;
4424 GpGraphics *graphics;
4425 GpMatrix *matrix;
4426 int i, match;
4428 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4429 expect(Ok, status);
4430 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4431 expect(Ok, status);
4433 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4434 expect(Ok, status);
4435 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4436 expect(Ok, status);
4437 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4438 expect(Ok, status);
4439 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4440 expect(Ok, status);
4442 for (i = 0; i < ARRAY_SIZE(td); i++)
4444 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4445 expect(Ok, status);
4447 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4448 expect(Ok, status);
4449 status = GdipSetWorldTransform(graphics, matrix);
4450 expect(Ok, status);
4451 GdipDeleteMatrix(matrix);
4453 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4454 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4455 expect(Ok, status);
4457 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4458 todo_wine_if (!match && td[i].todo)
4459 ok(match, "%d: data should match\n", i);
4460 if (!match)
4462 UINT i, size = sizeof(dst_8x1);
4463 const BYTE *bits = dst_8x1;
4464 for (i = 0; i < size; i++)
4465 trace(" %02x", bits[i]);
4466 trace("\n");
4470 status = GdipDeleteGraphics(graphics);
4471 expect(Ok, status);
4472 status = GdipDisposeImage(u1.image);
4473 expect(Ok, status);
4474 status = GdipDisposeImage(u2.image);
4475 expect(Ok, status);
4478 static const BYTE animatedgif[] = {
4479 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4480 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4481 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4482 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4483 0x03,0x01,0x05,0x00,0x00,
4484 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4485 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4486 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4487 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4488 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4489 0x02,0x02,0x4C,0x01,0x00,
4490 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4491 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4492 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4493 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4494 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4495 0x02,0x02,0x44,0x01,0x00,
4496 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4497 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4500 static void test_gif_properties(void)
4502 static const struct test_data
4504 ULONG type, id, length;
4505 const BYTE value[13];
4506 } td[] =
4508 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4509 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4510 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4511 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4512 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4513 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4515 GpStatus status;
4516 GpImage *image;
4517 GUID guid;
4518 UINT dim_count, frame_count, prop_count, prop_size, i;
4519 UINT total_size, total_count;
4520 PROPID *prop_id;
4521 PropertyItem *prop_item;
4522 const char *item_data;
4524 image = load_image(animatedgif, sizeof(animatedgif), TRUE, FALSE);
4525 if (!image) /* XP fails to load this GIF image */
4527 trace("Failed to load GIF image data\n");
4528 return;
4531 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4532 expect(Ok, status);
4533 expect(1, dim_count);
4535 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4536 expect(Ok, status);
4537 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4539 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4540 expect(Ok, status);
4541 expect(2, frame_count);
4543 status = GdipImageSelectActiveFrame(image, &guid, 1);
4544 expect(Ok, status);
4546 status = GdipGetPropertyCount(image, &prop_count);
4547 expect(Ok, status);
4548 ok(prop_count == ARRAY_SIZE(td) || broken(prop_count == 1) /* before win7 */,
4549 "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
4551 if (prop_count != ARRAY_SIZE(td))
4553 GdipDisposeImage(image);
4554 return;
4557 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4559 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4560 expect(Ok, status);
4562 prop_size = 0;
4563 for (i = 0; i < prop_count; i++)
4565 UINT size;
4566 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4567 expect(Ok, status);
4568 if (status != Ok) break;
4569 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4571 prop_size += size;
4573 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4574 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4575 expect(Ok, status);
4576 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4577 ok(td[i].type == prop_item->type,
4578 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4579 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4580 size -= sizeof(*prop_item);
4581 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4582 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4583 if (td[i].length == prop_item->length)
4585 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4586 ok(match, "%u: data mismatch\n", i);
4587 if (!match)
4589 UINT j;
4590 BYTE *data = prop_item->value;
4591 trace("id %#x:", prop_item->id);
4592 for (j = 0; j < prop_item->length; j++)
4593 trace(" %02x", data[j]);
4594 trace("\n");
4597 HeapFree(GetProcessHeap(), 0, prop_item);
4600 HeapFree(GetProcessHeap(), 0, prop_id);
4602 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4603 expect(InvalidParameter, status);
4604 status = GdipGetPropertySize(image, &total_size, NULL);
4605 expect(InvalidParameter, status);
4606 status = GdipGetPropertySize(image, NULL, &total_count);
4607 expect(InvalidParameter, status);
4608 status = GdipGetPropertySize(image, NULL, NULL);
4609 expect(InvalidParameter, status);
4610 total_size = 0xdeadbeef;
4611 total_count = 0xdeadbeef;
4612 status = GdipGetPropertySize(image, &total_size, &total_count);
4613 expect(Ok, status);
4614 ok(prop_count == total_count,
4615 "expected total property count %u, got %u\n", prop_count, total_count);
4616 ok(prop_size == total_size,
4617 "expected total property size %u, got %u\n", prop_size, total_size);
4619 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4621 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4622 expect(InvalidParameter, status);
4623 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4624 expect(InvalidParameter, status);
4625 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4626 expect(InvalidParameter, status);
4627 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4628 expect(InvalidParameter, status);
4629 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4630 expect(InvalidParameter, status);
4631 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4632 expect(InvalidParameter, status);
4633 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4634 expect(Ok, status);
4636 item_data = (const char *)(prop_item + prop_count);
4637 for (i = 0; i < prop_count; i++)
4639 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4640 i, item_data, prop_item[i].value);
4641 ok(td[i].type == prop_item[i].type,
4642 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4643 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4644 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4645 if (td[i].length == prop_item[i].length)
4647 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4648 ok(match, "%u: data mismatch\n", i);
4649 if (!match)
4651 UINT j;
4652 BYTE *data = prop_item[i].value;
4653 trace("id %#x:", prop_item[i].id);
4654 for (j = 0; j < prop_item[i].length; j++)
4655 trace(" %02x", data[j]);
4656 trace("\n");
4659 item_data += prop_item[i].length;
4662 HeapFree(GetProcessHeap(), 0, prop_item);
4664 GdipDisposeImage(image);
4667 static void test_ARGB_conversion(void)
4669 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4670 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4671 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4672 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4673 BYTE *bits;
4674 GpBitmap *bitmap;
4675 BitmapData data;
4676 GpStatus status;
4677 int match;
4679 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4680 expect(Ok, status);
4682 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4683 expect(Ok, status);
4684 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4685 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4686 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4687 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4688 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4689 ok(match, "bits don't match\n");
4690 if (!match)
4692 bits = data.Scan0;
4693 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4694 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4696 status = GdipBitmapUnlockBits(bitmap, &data);
4697 expect(Ok, status);
4699 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4700 expect(Ok, status);
4701 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4702 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4703 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4704 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4705 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4706 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4707 ok(match, "bits don't match\n");
4708 if (!match)
4710 bits = data.Scan0;
4711 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4712 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4714 status = GdipBitmapUnlockBits(bitmap, &data);
4715 expect(Ok, status);
4717 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4718 expect(Ok, status);
4719 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4720 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4721 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4722 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4723 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4724 ok(match, "bits don't match\n");
4725 if (!match)
4727 bits = data.Scan0;
4728 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4729 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4731 status = GdipBitmapUnlockBits(bitmap, &data);
4732 expect(Ok, status);
4734 GdipDisposeImage((GpImage *)bitmap);
4738 static void test_CloneBitmapArea(void)
4740 GpStatus status;
4741 GpBitmap *bitmap, *copy;
4742 BitmapData data, data2;
4744 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4745 expect(Ok, status);
4747 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4748 expect(Ok, status);
4750 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4751 expect(WrongState, status);
4753 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4754 expect(Ok, status);
4756 status = GdipBitmapUnlockBits(bitmap, &data);
4757 expect(Ok, status);
4759 GdipDisposeImage((GpImage *)copy);
4760 GdipDisposeImage((GpImage *)bitmap);
4763 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid)
4765 GpStatus status;
4766 UINT n_codecs, info_size, i;
4767 ImageCodecInfo *info;
4768 BOOL ret = FALSE;
4770 status = GdipGetImageEncodersSize(&n_codecs, &info_size);
4771 expect(Ok, status);
4773 info = GdipAlloc(info_size);
4775 status = GdipGetImageEncoders(n_codecs, info_size, info);
4776 expect(Ok, status);
4778 for (i = 0; i < n_codecs; i++)
4780 if (!lstrcmpW(info[i].MimeType, mime))
4782 *format = info[i].FormatID;
4783 *clsid = info[i].Clsid;
4784 ret = TRUE;
4785 break;
4789 GdipFree(info);
4790 return ret;
4793 static void test_supported_encoders(void)
4795 static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 };
4796 static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 };
4797 static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 };
4798 static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 };
4799 static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 };
4800 static const struct test_data
4802 LPCWSTR mime;
4803 const GUID *format;
4804 BOOL todo;
4805 } td[] =
4807 { bmp_mimetype, &ImageFormatBMP, FALSE },
4808 { jpeg_mimetype, &ImageFormatJPEG, FALSE },
4809 { gif_mimetype, &ImageFormatGIF, TRUE },
4810 { tiff_mimetype, &ImageFormatTIFF, FALSE },
4811 { png_mimetype, &ImageFormatPNG, FALSE }
4813 GUID format, clsid;
4814 BOOL ret;
4815 HRESULT hr;
4816 GpStatus status;
4817 GpBitmap *bm;
4818 IStream *stream;
4819 HGLOBAL hmem;
4820 int i;
4822 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
4823 ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
4825 for (i = 0; i < ARRAY_SIZE(td); i++)
4827 ret = get_encoder_clsid(td[i].mime, &format, &clsid);
4828 ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
4829 expect_guid(td[i].format, &format, __LINE__, FALSE);
4831 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
4833 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
4834 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
4836 status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
4837 todo_wine_if (td[i].todo)
4838 ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4840 IStream_Release(stream);
4843 GdipDisposeImage((GpImage *)bm);
4846 static void test_createeffect(void)
4848 static const GUID noneffect = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } };
4849 GpStatus (WINAPI *pGdipCreateEffect)( const GUID guid, CGpEffect **effect);
4850 GpStatus (WINAPI *pGdipDeleteEffect)( CGpEffect *effect);
4851 GpStatus stat;
4852 CGpEffect *effect;
4853 HMODULE mod = GetModuleHandleA("gdiplus.dll");
4854 int i;
4855 const GUID * const effectlist[] =
4856 {&BlurEffectGuid, &SharpenEffectGuid, &ColorMatrixEffectGuid, &ColorLUTEffectGuid,
4857 &BrightnessContrastEffectGuid, &HueSaturationLightnessEffectGuid, &LevelsEffectGuid,
4858 &TintEffectGuid, &ColorBalanceEffectGuid, &RedEyeCorrectionEffectGuid, &ColorCurveEffectGuid};
4860 pGdipCreateEffect = (void*)GetProcAddress( mod, "GdipCreateEffect");
4861 pGdipDeleteEffect = (void*)GetProcAddress( mod, "GdipDeleteEffect");
4862 if(!pGdipCreateEffect || !pGdipDeleteEffect)
4864 /* GdipCreateEffect/GdipDeleteEffect was introduced in Windows Vista. */
4865 win_skip("GDIPlus version 1.1 not available\n");
4866 return;
4869 stat = pGdipCreateEffect(BlurEffectGuid, NULL);
4870 expect(InvalidParameter, stat);
4872 stat = pGdipCreateEffect(noneffect, &effect);
4873 todo_wine expect(Win32Error, stat);
4875 for(i=0; i < ARRAY_SIZE(effectlist); i++)
4877 stat = pGdipCreateEffect(*effectlist[i], &effect);
4878 todo_wine expect(Ok, stat);
4879 if(stat == Ok)
4881 stat = pGdipDeleteEffect(effect);
4882 expect(Ok, stat);
4887 static void test_getadjustedpalette(void)
4889 ColorMap colormap;
4890 GpImageAttributes *imageattributes;
4891 ColorPalette *palette;
4892 GpStatus stat;
4894 stat = GdipCreateImageAttributes(&imageattributes);
4895 expect(Ok, stat);
4897 colormap.oldColor.Argb = 0xffffff00;
4898 colormap.newColor.Argb = 0xffff00ff;
4899 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeBitmap,
4900 TRUE, 1, &colormap);
4901 expect(Ok, stat);
4903 colormap.oldColor.Argb = 0xffffff80;
4904 colormap.newColor.Argb = 0xffff80ff;
4905 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeDefault,
4906 TRUE, 1, &colormap);
4907 expect(Ok, stat);
4909 palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 2);
4910 palette->Count = 0;
4912 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4913 expect(InvalidParameter, stat);
4915 palette->Count = 3;
4916 palette->Entries[0] = 0xffffff00;
4917 palette->Entries[1] = 0xffffff80;
4918 palette->Entries[2] = 0xffffffff;
4920 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4921 expect(Ok, stat);
4922 expect(0xffff00ff, palette->Entries[0]);
4923 expect(0xffffff80, palette->Entries[1]);
4924 expect(0xffffffff, palette->Entries[2]);
4926 palette->Entries[0] = 0xffffff00;
4927 palette->Entries[1] = 0xffffff80;
4928 palette->Entries[2] = 0xffffffff;
4930 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBrush);
4931 expect(Ok, stat);
4932 expect(0xffffff00, palette->Entries[0]);
4933 expect(0xffff80ff, palette->Entries[1]);
4934 expect(0xffffffff, palette->Entries[2]);
4936 stat = GdipGetImageAttributesAdjustedPalette(NULL, palette, ColorAdjustTypeBitmap);
4937 expect(InvalidParameter, stat);
4939 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, NULL, ColorAdjustTypeBitmap);
4940 expect(InvalidParameter, stat);
4942 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, -1);
4943 expect(InvalidParameter, stat);
4945 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeDefault);
4946 expect(InvalidParameter, stat);
4948 GdipFree(palette);
4949 GdipDisposeImageAttributes(imageattributes);
4952 static void test_histogram(void)
4954 UINT ch0[256], ch1[256], ch2[256], ch3[256];
4955 HistogramFormat test_formats[] =
4957 HistogramFormatARGB,
4958 HistogramFormatPARGB,
4959 HistogramFormatRGB,
4960 HistogramFormatGray,
4961 HistogramFormatB,
4962 HistogramFormatG,
4963 HistogramFormatR,
4964 HistogramFormatA,
4966 const UINT WIDTH = 8, HEIGHT = 16;
4967 UINT num, i, x;
4968 GpStatus stat;
4969 GpBitmap *bm;
4971 if (!pGdipBitmapGetHistogramSize)
4973 win_skip("GdipBitmapGetHistogramSize is not supported\n");
4974 return;
4977 stat = pGdipBitmapGetHistogramSize(HistogramFormatARGB, NULL);
4978 expect(InvalidParameter, stat);
4980 stat = pGdipBitmapGetHistogramSize(0xff, NULL);
4981 expect(InvalidParameter, stat);
4983 num = 123;
4984 stat = pGdipBitmapGetHistogramSize(10, &num);
4985 expect(Ok, stat);
4986 expect(256, num);
4988 for (i = 0; i < ARRAY_SIZE(test_formats); i++)
4990 num = 0;
4991 stat = pGdipBitmapGetHistogramSize(test_formats[i], &num);
4992 expect(Ok, stat);
4993 expect(256, num);
4996 bm = NULL;
4997 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
4998 expect(Ok, stat);
5000 /* Three solid rgb rows, next three rows are rgb shades. */
5001 for (x = 0; x < WIDTH; x++)
5003 GdipBitmapSetPixel(bm, x, 0, 0xffff0000);
5004 GdipBitmapSetPixel(bm, x, 1, 0xff00ff00);
5005 GdipBitmapSetPixel(bm, x, 2, 0xff0000ff);
5007 GdipBitmapSetPixel(bm, x, 3, 0xff010000);
5008 GdipBitmapSetPixel(bm, x, 4, 0xff003f00);
5009 GdipBitmapSetPixel(bm, x, 5, 0xff000020);
5012 stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
5013 expect(InvalidParameter, stat);
5015 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3);
5016 expect(InvalidParameter, stat);
5018 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL);
5019 expect(InvalidParameter, stat);
5021 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL);
5022 expect(InvalidParameter, stat);
5024 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL);
5025 expect(InvalidParameter, stat);
5027 /* Requested format matches bitmap format */
5028 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
5029 expect(InvalidParameter, stat);
5031 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL);
5032 expect(InvalidParameter, stat);
5034 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL);
5035 expect(InvalidParameter, stat);
5037 /* Channel 3 is not used, must be NULL */
5038 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL);
5039 expect(Ok, stat);
5041 ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]);
5042 ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]);
5043 ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]);
5044 ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]);
5045 ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]);
5046 ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]);
5048 /* ARGB histogram from RGB data. */
5049 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL);
5050 expect(InvalidParameter, stat);
5052 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3);
5053 expect(Ok, stat);
5055 ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]);
5056 ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]);
5057 ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]);
5058 ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]);
5059 ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]);
5060 ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]);
5062 ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]);
5064 /* Request grayscale histogram from RGB bitmap. */
5065 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3);
5066 expect(InvalidParameter, stat);
5068 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL);
5069 expect(InvalidParameter, stat);
5071 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL);
5072 expect(InvalidParameter, stat);
5074 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL);
5075 expect(Ok, stat);
5077 GdipDisposeImage((GpImage*)bm);
5080 static void test_imageabort(void)
5082 GpStatus stat;
5083 GpBitmap *bm;
5085 if (!pGdipImageSetAbort)
5087 win_skip("GdipImageSetAbort() is not supported.\n");
5088 return;
5091 bm = NULL;
5092 stat = GdipCreateBitmapFromScan0(8, 8, 0, PixelFormat24bppRGB, NULL, &bm);
5093 expect(Ok, stat);
5095 stat = pGdipImageSetAbort(NULL, NULL);
5096 expect(InvalidParameter, stat);
5098 stat = pGdipImageSetAbort((GpImage*)bm, NULL);
5099 expect(Ok, stat);
5101 GdipDisposeImage((GpImage*)bm);
5104 /* RGB 24 bpp 1x1 pixel PNG image */
5105 static const char png_1x1_data[] = {
5106 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a,
5107 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,0xde,
5108 0x00,0x00,0x03,0x00,'P','L','T','E',
5109 0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
5110 0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,0x10,0x10,
5111 0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,
5112 0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,
5113 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28,
5114 0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,
5115 0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
5116 0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
5117 0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x48,
5118 0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,
5119 0x51,0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,0x58,
5120 0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,
5121 0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,
5122 0x69,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x70,
5123 0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,
5124 0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,
5125 0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
5126 0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,0x10,0x10,
5127 0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,
5128 0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,
5129 0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28,
5130 0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,
5131 0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
5132 0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
5133 0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x48,
5134 0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,
5135 0x51,0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,0x58,
5136 0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,
5137 0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,
5138 0x69,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x70,
5139 0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,
5140 0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,
5141 0x76,0xb6,0x24,0x31,
5142 0x00,0x00,0x00,0x02,'t','R','N','S',0xff,0x00,0xe5,0xb7,0x30,0x4a,
5143 0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7,
5144 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
5147 #define PNG_COLOR_TYPE_GRAY 0
5148 #define PNG_COLOR_TYPE_RGB 2
5149 #define PNG_COLOR_TYPE_PALETTE 3
5150 #define PNG_COLOR_TYPE_GRAY_ALPHA 4
5151 #define PNG_COLOR_TYPE_RGB_ALPHA 6
5153 static void test_png_color_formats(void)
5155 static const struct
5157 char bit_depth, color_type;
5158 struct {
5159 PixelFormat format;
5160 ImageFlags flags;
5161 BOOL todo;
5162 BOOL todo_load;
5163 } t[3];
5164 } td[] =
5166 /* 0 */
5167 { 1, PNG_COLOR_TYPE_RGB },
5168 { 2, PNG_COLOR_TYPE_RGB },
5169 { 4, PNG_COLOR_TYPE_RGB },
5170 { 8, PNG_COLOR_TYPE_RGB,
5171 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE },
5172 { PixelFormat24bppRGB, ImageFlagsColorSpaceRGB },
5173 { PixelFormat24bppRGB, ImageFlagsColorSpaceRGB }}},
5174 /* libpng refuses to load our test image complaining about extra compressed data,
5175 * but libpng is still able to load the image with other combination of type/depth
5176 * making RGB 16 bpp case special for some reason. Therefore todo = TRUE.
5178 { 16, PNG_COLOR_TYPE_RGB,
5179 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE },
5180 { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE },
5181 { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE }}},
5183 /* 5 */
5184 { 1, PNG_COLOR_TYPE_GRAY,
5185 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE },
5186 { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB },
5187 { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }}},
5188 { 2, PNG_COLOR_TYPE_GRAY,
5189 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5190 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5191 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5192 { 4, PNG_COLOR_TYPE_GRAY,
5193 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5194 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5195 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5196 { 8, PNG_COLOR_TYPE_GRAY,
5197 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE },
5198 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5199 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5200 { 16, PNG_COLOR_TYPE_GRAY,
5201 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5202 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5203 { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5205 /* 10 */
5206 { 1, PNG_COLOR_TYPE_PALETTE,
5207 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE },
5208 { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB },
5209 { 0, 0 }}},
5210 { 2, PNG_COLOR_TYPE_PALETTE,
5211 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5212 { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5213 { 0, 0 }}},
5214 { 4, PNG_COLOR_TYPE_PALETTE,
5215 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5216 { PixelFormat4bppIndexed, ImageFlagsColorSpaceRGB, TRUE },
5217 { 0, 0 }}},
5218 { 8, PNG_COLOR_TYPE_PALETTE,
5219 {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE },
5220 { PixelFormat8bppIndexed, ImageFlagsColorSpaceRGB },
5221 { 0, 0 }}},
5222 { 16, PNG_COLOR_TYPE_PALETTE },
5224 BYTE buf[sizeof(png_1x1_data)];
5225 GpStatus status;
5226 GpImage *image;
5227 ImageType type;
5228 PixelFormat format;
5229 ImageFlags flags;
5230 BOOL valid;
5231 int i, j, PLTE_off = 0, tRNS_off = 0;
5232 const ImageFlags color_space_mask = ImageFlagsColorSpaceRGB | ImageFlagsColorSpaceCMYK | ImageFlagsColorSpaceGRAY | ImageFlagsColorSpaceYCBCR | ImageFlagsColorSpaceYCCK;
5234 memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
5235 buf[24] = 2;
5236 buf[25] = PNG_COLOR_TYPE_PALETTE;
5237 image = load_image(buf, sizeof(buf), TRUE, FALSE);
5238 status = GdipGetImageFlags(image, &flags);
5239 expect(status, Ok);
5240 ok((flags & color_space_mask) == ImageFlagsColorSpaceRGB || broken(flags == 0x12006) /* before win7 */,
5241 "flags = %#x\n", flags);
5242 if ((flags & color_space_mask) != ImageFlagsColorSpaceRGB) {
5243 GdipDisposeImage(image);
5244 win_skip("broken PNG color space support\n");
5245 return;
5247 GdipDisposeImage(image);
5249 for (i = 0; i < sizeof(png_1x1_data) - 4; i++)
5251 if (!memcmp(buf + i, "tRNS", 4))
5252 tRNS_off = i;
5253 else if (!memcmp(buf + i, "PLTE", 4))
5254 PLTE_off = i;
5257 ok(PLTE_off && tRNS_off, "PLTE offset %d, tRNS offset %d\n", PLTE_off, tRNS_off);
5258 if (!PLTE_off || !tRNS_off) return;
5260 /* In order to test the image data with and without PLTE and tRNS
5261 * chunks, we mask the chunk name with private one (tEST).
5264 for (i = 0; i < ARRAY_SIZE(td); i++)
5266 for (j = 0; j < 3; j++)
5268 memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
5269 buf[24] = td[i].bit_depth;
5270 buf[25] = td[i].color_type;
5271 if (j >=1) memcpy(buf + tRNS_off, "tEST", 4);
5272 if (j >=2) memcpy(buf + PLTE_off, "tEST", 4);
5274 valid = (td[i].t[j].format != 0) || (td[i].t[j].flags != 0);
5275 image = load_image(buf, sizeof(buf), valid, td[i].t[j].todo_load);
5276 todo_wine_if(td[i].t[j].todo_load)
5277 if (valid)
5278 ok(image != NULL, "%d %d: failed to load image data\n", i, j);
5279 else
5281 ok(image == NULL, "%d %d: succeed to load image data\n", i, j);
5282 if (image) GdipDisposeImage(image);
5283 image = NULL;
5285 if (!image) continue;
5287 status = GdipGetImageType(image, &type);
5288 ok(status == Ok, "%d %d: GdipGetImageType error %d\n", i, j, status);
5289 ok(type == ImageTypeBitmap, "%d %d: wrong image type %d\n", i, j, type);
5291 status = GdipGetImagePixelFormat(image, &format);
5292 expect(Ok, status);
5293 todo_wine_if(td[i].t[j].todo)
5294 ok(format == td[i].t[j].format,
5295 "%d %d: expected %#x, got %#x\n", i, j, td[i].t[j].format, format);
5297 status = GdipGetImageFlags(image, &flags);
5298 expect(Ok, status);
5299 ok((flags & color_space_mask) == td[i].t[j].flags,
5300 "%d %d: expected %#x, got %#x\n", i, j, td[i].t[j].flags, flags);
5301 GdipDisposeImage(image);
5305 #undef PNG_COLOR_TYPE_GRAY
5306 #undef PNG_COLOR_TYPE_RGB
5307 #undef PNG_COLOR_TYPE_PALETTE
5308 #undef PNG_COLOR_TYPE_GRAY_ALPHA
5309 #undef PNG_COLOR_TYPE_RGB_ALPHA
5311 static void test_GdipLoadImageFromStream(void)
5313 IStream *stream;
5314 GpStatus status;
5315 GpImage *image;
5316 HGLOBAL hglob;
5317 BYTE *data;
5318 HRESULT hr;
5320 status = GdipLoadImageFromStream(NULL, NULL);
5321 ok(status == InvalidParameter, "Unexpected return value %d.\n", status);
5323 image = (void *)0xdeadbeef;
5324 status = GdipLoadImageFromStream(NULL, &image);
5325 ok(status == InvalidParameter, "Unexpected return value %d.\n", status);
5326 ok(image == (void *)0xdeadbeef, "Unexpected image pointer.\n");
5328 hglob = GlobalAlloc(0, sizeof(pngimage));
5329 data = GlobalLock (hglob);
5330 memcpy(data, pngimage, sizeof(pngimage));
5331 GlobalUnlock(hglob);
5333 hr = CreateStreamOnHGlobal(hglob, TRUE, &stream);
5334 ok(hr == S_OK, "Failed to create a stream.\n");
5336 status = GdipLoadImageFromStream(stream, NULL);
5337 ok(status == InvalidParameter, "Unexpected return value %d.\n", status);
5339 IStream_Release(stream);
5342 START_TEST(image)
5344 HMODULE mod = GetModuleHandleA("gdiplus.dll");
5345 struct GdiplusStartupInput gdiplusStartupInput;
5346 ULONG_PTR gdiplusToken;
5347 HMODULE hmsvcrt;
5348 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
5350 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
5351 hmsvcrt = LoadLibraryA("msvcrt");
5352 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
5353 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
5355 gdiplusStartupInput.GdiplusVersion = 1;
5356 gdiplusStartupInput.DebugEventCallback = NULL;
5357 gdiplusStartupInput.SuppressBackgroundThread = 0;
5358 gdiplusStartupInput.SuppressExternalCodecs = 0;
5360 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
5362 pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize");
5363 pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram");
5364 pGdipImageSetAbort = (void*)GetProcAddress(mod, "GdipImageSetAbort");
5366 test_png_color_formats();
5367 test_supported_encoders();
5368 test_CloneBitmapArea();
5369 test_ARGB_conversion();
5370 test_DrawImage_scale();
5371 test_image_format();
5372 test_DrawImage();
5373 test_DrawImage_SourceCopy();
5374 test_GdipDrawImagePointRect();
5375 test_bitmapbits();
5376 test_tiff_palette();
5377 test_GdipGetAllPropertyItems();
5378 test_tiff_properties();
5379 test_gif_properties();
5380 test_image_properties();
5381 test_Scan0();
5382 test_FromGdiDib();
5383 test_GetImageDimension();
5384 test_GdipImageGetFrameDimensionsCount();
5385 test_LoadingImages();
5386 test_SavingImages();
5387 test_encoders();
5388 test_LockBits();
5389 test_LockBits_UserBuf();
5390 test_GdipCreateBitmapFromHBITMAP();
5391 test_GdipGetImageFlags();
5392 test_GdipCloneImage();
5393 test_testcontrol();
5394 test_fromhicon();
5395 test_getrawformat();
5396 test_loadwmf();
5397 test_createfromwmf();
5398 test_createfromwmf_noplaceable();
5399 test_resolution();
5400 test_createhbitmap();
5401 test_getthumbnail();
5402 test_getsetpixel();
5403 test_palette();
5404 test_colormatrix();
5405 test_gamma();
5406 test_multiframegif();
5407 test_rotateflip();
5408 test_remaptable();
5409 test_colorkey();
5410 test_dispose();
5411 test_createeffect();
5412 test_getadjustedpalette();
5413 test_histogram();
5414 test_imageabort();
5415 test_GdipLoadImageFromStream();
5417 GdiplusShutdown(gdiplusToken);