TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / gdiplus / tests / image.c
blob6be4a5b33402c2c8d5701e6119296aa47dce2c80
1 /*
2 * Unit test suite for images
4 * Copyright (C) 2007 Google (Evan Stade)
5 * Copyright (C) 2012 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
24 #include <math.h>
25 #include <assert.h>
26 #include <stdio.h>
28 #include "initguid.h"
29 #include "objbase.h"
30 #include "gdiplus.h"
31 #include "wine/test.h"
33 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
34 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
36 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
38 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39 c1 >>= 8; c2 >>= 8;
40 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41 c1 >>= 8; c2 >>= 8;
42 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
43 c1 >>= 8; c2 >>= 8;
44 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45 return TRUE;
48 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
50 WCHAR bufferW[39];
51 char buffer[39];
52 char buffer2[39];
54 StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
55 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
56 StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
57 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
58 if(todo)
59 todo_wine ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
60 else
61 ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
64 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
66 GUID raw;
67 GpStatus stat;
69 stat = GdipGetImageRawFormat(img, &raw);
70 ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
71 if(stat != Ok) return;
72 expect_guid(expected, &raw, line, todo);
75 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
77 LPSTREAM stream;
78 HGLOBAL hglob;
79 LPBYTE data;
80 HRESULT hres;
81 GpStatus stat;
82 GpImage *img;
84 hglob = GlobalAlloc (0, size);
85 data = GlobalLock (hglob);
86 memcpy(data, buff, size);
87 GlobalUnlock(hglob); data = NULL;
89 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
90 ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
91 if(hres != S_OK) return;
93 stat = GdipLoadImageFromStream(stream, &img);
94 ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
95 if(stat != Ok){
96 IStream_Release(stream);
97 return;
100 expect_rawformat(expected, img, line, todo);
102 GdipDisposeImage(img);
103 IStream_Release(stream);
106 static void test_Scan0(void)
108 GpBitmap *bm;
109 GpStatus stat;
110 BYTE buff[360];
112 bm = NULL;
113 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
114 expect(Ok, stat);
115 ok(NULL != bm, "Expected bitmap to be initialized\n");
116 if (stat == Ok)
117 GdipDisposeImage((GpImage*)bm);
119 bm = (GpBitmap*)0xdeadbeef;
120 stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
121 expect(InvalidParameter, stat);
122 ok( !bm, "expected null bitmap\n" );
124 bm = (GpBitmap*)0xdeadbeef;
125 stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
126 expect(InvalidParameter, stat);
127 ok( !bm, "expected null bitmap\n" );
129 bm = (GpBitmap*)0xdeadbeef;
130 stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
131 expect(InvalidParameter, stat);
132 ok( !bm, "expected null bitmap\n" );
134 bm = NULL;
135 stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
136 expect(Ok, stat);
137 ok(NULL != bm, "Expected bitmap to be initialized\n");
138 if (stat == Ok)
139 GdipDisposeImage((GpImage*)bm);
141 bm = (GpBitmap*) 0xdeadbeef;
142 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
143 expect(InvalidParameter, stat);
144 ok( !bm, "expected null bitmap\n" );
146 bm = (GpBitmap*)0xdeadbeef;
147 stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
148 expect(InvalidParameter, stat);
149 ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
151 bm = NULL;
152 stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
153 expect(Ok, stat);
154 ok(NULL != bm, "Expected bitmap to be initialized\n");
155 if (stat == Ok)
156 GdipDisposeImage((GpImage*)bm);
158 bm = (GpBitmap*)0xdeadbeef;
159 stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
160 expect(InvalidParameter, stat);
161 ok( !bm, "expected null bitmap\n" );
164 static void test_FromGdiDib(void)
166 GpBitmap *bm;
167 GpStatus stat;
168 BYTE buff[400];
169 BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
170 BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
171 PixelFormat format;
173 bm = NULL;
175 memset(rbmi, 0, sizeof(rbmi));
177 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
178 bmi->bmiHeader.biWidth = 10;
179 bmi->bmiHeader.biHeight = 10;
180 bmi->bmiHeader.biPlanes = 1;
181 bmi->bmiHeader.biBitCount = 32;
182 bmi->bmiHeader.biCompression = BI_RGB;
184 stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
185 expect(InvalidParameter, stat);
187 stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
188 expect(InvalidParameter, stat);
190 stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
191 expect(InvalidParameter, stat);
193 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
194 expect(Ok, stat);
195 ok(NULL != bm, "Expected bitmap to be initialized\n");
196 if (stat == Ok)
198 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
199 expect(Ok, stat);
200 expect(PixelFormat32bppRGB, format);
202 GdipDisposeImage((GpImage*)bm);
205 bmi->bmiHeader.biBitCount = 24;
206 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
207 expect(Ok, stat);
208 ok(NULL != bm, "Expected bitmap to be initialized\n");
209 if (stat == Ok)
211 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
212 expect(Ok, stat);
213 expect(PixelFormat24bppRGB, format);
215 GdipDisposeImage((GpImage*)bm);
218 bmi->bmiHeader.biBitCount = 16;
219 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
220 expect(Ok, stat);
221 ok(NULL != bm, "Expected bitmap to be initialized\n");
222 if (stat == Ok)
224 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
225 expect(Ok, stat);
226 expect(PixelFormat16bppRGB555, format);
228 GdipDisposeImage((GpImage*)bm);
231 bmi->bmiHeader.biBitCount = 8;
232 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
233 expect(Ok, stat);
234 ok(NULL != bm, "Expected bitmap to be initialized\n");
235 if (stat == Ok)
237 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
238 expect(Ok, stat);
239 expect(PixelFormat8bppIndexed, format);
241 GdipDisposeImage((GpImage*)bm);
244 bmi->bmiHeader.biBitCount = 4;
245 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
246 expect(Ok, stat);
247 ok(NULL != bm, "Expected bitmap to be initialized\n");
248 if (stat == Ok)
250 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
251 expect(Ok, stat);
252 expect(PixelFormat4bppIndexed, format);
254 GdipDisposeImage((GpImage*)bm);
257 bmi->bmiHeader.biBitCount = 1;
258 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
259 expect(Ok, stat);
260 ok(NULL != bm, "Expected bitmap to be initialized\n");
261 if (stat == Ok)
263 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
264 expect(Ok, stat);
265 expect(PixelFormat1bppIndexed, format);
267 GdipDisposeImage((GpImage*)bm);
270 bmi->bmiHeader.biBitCount = 0;
271 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
272 expect(InvalidParameter, stat);
275 static void test_GetImageDimension(void)
277 GpBitmap *bm;
278 GpStatus stat;
279 const REAL WIDTH = 10.0, HEIGHT = 20.0;
280 REAL w,h;
282 bm = (GpBitmap*)0xdeadbeef;
283 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
284 expect(Ok,stat);
285 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
286 ok(NULL != bm, "Expected bitmap to not be NULL\n");
288 stat = GdipGetImageDimension(NULL,&w,&h);
289 expect(InvalidParameter, stat);
291 stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
292 expect(InvalidParameter, stat);
294 stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
295 expect(InvalidParameter, stat);
297 w = -1;
298 h = -1;
299 stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
300 expect(Ok, stat);
301 expectf(WIDTH, w);
302 expectf(HEIGHT, h);
303 GdipDisposeImage((GpImage*)bm);
306 static void test_GdipImageGetFrameDimensionsCount(void)
308 GpBitmap *bm;
309 GpStatus stat;
310 const REAL WIDTH = 10.0, HEIGHT = 20.0;
311 UINT w;
312 GUID dimension = {0};
313 UINT count;
314 ARGB color;
316 bm = (GpBitmap*)0xdeadbeef;
317 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
318 expect(Ok,stat);
319 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
320 ok(NULL != bm, "Expected bitmap to not be NULL\n");
322 stat = GdipImageGetFrameDimensionsCount(NULL,&w);
323 expect(InvalidParameter, stat);
325 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
326 expect(InvalidParameter, stat);
328 w = -1;
329 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
330 expect(Ok, stat);
331 expect(1, w);
333 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
334 expect(Ok, stat);
335 expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
337 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
338 expect(InvalidParameter, stat);
340 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
341 expect(InvalidParameter, stat);
343 stat = GdipImageGetFrameCount(NULL, &dimension, &count);
344 expect(InvalidParameter, stat);
346 /* WinXP crashes on this test */
347 if(0)
349 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
350 expect(InvalidParameter, stat);
353 stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
354 expect(Ok, stat);
356 count = 12345;
357 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
358 expect(Ok, stat);
359 expect(1, count);
361 GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
363 stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
364 expect(Ok, stat);
366 /* SelectActiveFrame has no effect on image data of memory bitmaps */
367 color = 0xdeadbeef;
368 GdipBitmapGetPixel(bm, 0, 0, &color);
369 expect(0xffffffff, color);
371 GdipDisposeImage((GpImage*)bm);
374 static void test_LoadingImages(void)
376 GpStatus stat;
377 GpBitmap *bm;
378 GpImage *img;
379 static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0};
381 stat = GdipCreateBitmapFromFile(0, 0);
382 expect(InvalidParameter, stat);
384 bm = (GpBitmap *)0xdeadbeef;
385 stat = GdipCreateBitmapFromFile(0, &bm);
386 expect(InvalidParameter, stat);
387 ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm);
389 bm = (GpBitmap *)0xdeadbeef;
390 stat = GdipCreateBitmapFromFile(nonexistentW, &bm);
391 todo_wine expect(InvalidParameter, stat);
392 ok(!bm, "returned %p\n", bm);
394 stat = GdipLoadImageFromFile(0, 0);
395 expect(InvalidParameter, stat);
397 img = (GpImage *)0xdeadbeef;
398 stat = GdipLoadImageFromFile(0, &img);
399 expect(InvalidParameter, stat);
400 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
402 img = (GpImage *)0xdeadbeef;
403 stat = GdipLoadImageFromFile(nonexistentW, &img);
404 todo_wine expect(OutOfMemory, stat);
405 ok(!img, "returned %p\n", img);
407 stat = GdipLoadImageFromFileICM(0, 0);
408 expect(InvalidParameter, stat);
410 img = (GpImage *)0xdeadbeef;
411 stat = GdipLoadImageFromFileICM(0, &img);
412 expect(InvalidParameter, stat);
413 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
415 img = (GpImage *)0xdeadbeef;
416 stat = GdipLoadImageFromFileICM(nonexistentW, &img);
417 todo_wine expect(OutOfMemory, stat);
418 ok(!img, "returned %p\n", img);
421 static void test_SavingImages(void)
423 GpStatus stat;
424 GpBitmap *bm;
425 UINT n;
426 UINT s;
427 const REAL WIDTH = 10.0, HEIGHT = 20.0;
428 REAL w, h;
429 ImageCodecInfo *codecs;
430 static const CHAR filenameA[] = "a.bmp";
431 static const WCHAR filename[] = { 'a','.','b','m','p',0 };
433 codecs = NULL;
435 stat = GdipSaveImageToFile(0, 0, 0, 0);
436 expect(InvalidParameter, stat);
438 bm = NULL;
439 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
440 expect(Ok, stat);
441 if (!bm)
442 return;
444 /* invalid params */
445 stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
446 expect(InvalidParameter, stat);
448 stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
449 expect(InvalidParameter, stat);
451 /* encoder tests should succeed -- already tested */
452 stat = GdipGetImageEncodersSize(&n, &s);
453 if (stat != Ok || n == 0) goto cleanup;
455 codecs = GdipAlloc(s);
456 if (!codecs) goto cleanup;
458 stat = GdipGetImageEncoders(n, s, codecs);
459 if (stat != Ok) goto cleanup;
461 stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
462 expect(Ok, stat);
464 GdipDisposeImage((GpImage*)bm);
465 bm = 0;
467 /* re-load and check image stats */
468 stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
469 expect(Ok, stat);
470 if (stat != Ok) goto cleanup;
472 stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
473 if (stat != Ok) goto cleanup;
475 expectf(WIDTH, w);
476 expectf(HEIGHT, h);
478 cleanup:
479 GdipFree(codecs);
480 if (bm)
481 GdipDisposeImage((GpImage*)bm);
482 ok(DeleteFileA(filenameA), "Delete failed.\n");
485 static void test_encoders(void)
487 GpStatus stat;
488 UINT n;
489 UINT s;
490 ImageCodecInfo *codecs;
491 int i;
492 int bmp_found;
494 static const CHAR bmp_format[] = "BMP";
496 stat = GdipGetImageEncodersSize(&n, &s);
497 expect(stat, Ok);
499 codecs = GdipAlloc(s);
500 if (!codecs)
501 return;
503 stat = GdipGetImageEncoders(n, s, NULL);
504 expect(GenericError, stat);
506 stat = GdipGetImageEncoders(0, s, codecs);
507 expect(GenericError, stat);
509 stat = GdipGetImageEncoders(n, s-1, codecs);
510 expect(GenericError, stat);
512 stat = GdipGetImageEncoders(n, s+1, codecs);
513 expect(GenericError, stat);
515 stat = GdipGetImageEncoders(n, s, codecs);
516 expect(stat, Ok);
518 bmp_found = FALSE;
519 for (i = 0; i < n; i++)
521 CHAR desc[32];
523 WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
524 desc, 32, 0, 0);
526 if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
527 desc, -1,
528 bmp_format, -1) == CSTR_EQUAL) {
529 bmp_found = TRUE;
530 break;
533 if (!bmp_found)
534 ok(FALSE, "No BMP codec found.\n");
536 GdipFree(codecs);
539 static void test_LockBits(void)
541 GpStatus stat;
542 GpBitmap *bm;
543 GpRect rect;
544 BitmapData bd;
545 const INT WIDTH = 10, HEIGHT = 20;
546 ARGB color;
547 int y;
549 bm = NULL;
550 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
551 expect(Ok, stat);
553 rect.X = 2;
554 rect.Y = 3;
555 rect.Width = 4;
556 rect.Height = 5;
558 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
559 expect(Ok, stat);
561 stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
562 expect(Ok, stat);
564 /* read-only */
565 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
566 expect(Ok, stat);
568 if (stat == Ok) {
569 expect(0xc3, ((BYTE*)bd.Scan0)[2]);
570 expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
572 ((char*)bd.Scan0)[2] = 0xff;
574 stat = GdipBitmapUnlockBits(bm, &bd);
575 expect(Ok, stat);
578 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
579 expect(Ok, stat);
580 expect(0xffff0000, color);
582 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
583 expect(Ok, stat);
585 /* read-only, with NULL rect -> whole bitmap lock */
586 stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
587 expect(Ok, stat);
588 expect(bd.Width, WIDTH);
589 expect(bd.Height, HEIGHT);
591 if (stat == Ok) {
592 ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
594 stat = GdipBitmapUnlockBits(bm, &bd);
595 expect(Ok, stat);
598 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
599 expect(Ok, stat);
600 expect(0xffff0000, color);
602 /* read-only, consecutive */
603 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
604 expect(Ok, stat);
606 if (stat == Ok) {
607 stat = GdipBitmapUnlockBits(bm, &bd);
608 expect(Ok, stat);
611 stat = GdipDisposeImage((GpImage*)bm);
612 expect(Ok, stat);
613 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
614 expect(Ok, stat);
616 /* read x2 */
617 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
618 expect(Ok, stat);
619 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
620 expect(WrongState, stat);
622 stat = GdipBitmapUnlockBits(bm, &bd);
623 expect(Ok, stat);
625 stat = GdipDisposeImage((GpImage*)bm);
626 expect(Ok, stat);
627 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
628 expect(Ok, stat);
630 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
631 expect(Ok, stat);
633 stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
634 expect(Ok, stat);
636 /* write, no conversion */
637 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
638 expect(Ok, stat);
640 if (stat == Ok) {
641 /* all bits are readable, inside the rect or not */
642 expect(0xff, ((BYTE*)bd.Scan0)[2]);
643 expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
645 stat = GdipBitmapUnlockBits(bm, &bd);
646 expect(Ok, stat);
649 /* read, conversion */
650 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
651 expect(Ok, stat);
653 if (stat == Ok) {
654 expect(0xff, ((BYTE*)bd.Scan0)[2]);
655 if (0)
656 /* Areas outside the rectangle appear to be uninitialized */
657 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
659 ((BYTE*)bd.Scan0)[2] = 0xc3;
661 stat = GdipBitmapUnlockBits(bm, &bd);
662 expect(Ok, stat);
665 /* writes do not work in read mode if there was a conversion */
666 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
667 expect(Ok, stat);
668 expect(0xffff0000, color);
670 /* read/write, conversion */
671 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
672 expect(Ok, stat);
674 if (stat == Ok) {
675 expect(0xff, ((BYTE*)bd.Scan0)[2]);
676 ((BYTE*)bd.Scan0)[1] = 0x88;
677 if (0)
678 /* Areas outside the rectangle appear to be uninitialized */
679 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
681 stat = GdipBitmapUnlockBits(bm, &bd);
682 expect(Ok, stat);
685 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
686 expect(Ok, stat);
687 expect(0xffff8800, color);
689 /* write, conversion */
690 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
691 expect(Ok, stat);
693 if (stat == Ok) {
694 if (0)
696 /* This is completely uninitialized. */
697 ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
698 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
701 /* Initialize the buffer so the unlock doesn't access undefined memory */
702 for (y=0; y<5; y++)
703 memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
705 ((BYTE*)bd.Scan0)[0] = 0x12;
706 ((BYTE*)bd.Scan0)[1] = 0x34;
707 ((BYTE*)bd.Scan0)[2] = 0x56;
709 stat = GdipBitmapUnlockBits(bm, &bd);
710 expect(Ok, stat);
713 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
714 expect(Ok, stat);
715 expect(0xff563412, color);
717 stat = GdipBitmapGetPixel(bm, 2, 8, &color);
718 expect(Ok, stat);
719 expect(0xffc30000, color);
721 stat = GdipDisposeImage((GpImage*)bm);
722 expect(Ok, stat);
723 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
724 expect(Ok, stat);
726 /* write, no modification */
727 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
728 expect(Ok, stat);
730 if (stat == Ok) {
731 stat = GdipBitmapUnlockBits(bm, &bd);
732 expect(Ok, stat);
735 /* write, consecutive */
736 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
737 expect(Ok, stat);
739 if (stat == Ok) {
740 stat = GdipBitmapUnlockBits(bm, &bd);
741 expect(Ok, stat);
744 stat = GdipDisposeImage((GpImage*)bm);
745 expect(Ok, stat);
746 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
747 expect(Ok, stat);
749 /* write, modify */
750 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
751 expect(Ok, stat);
753 if (stat == Ok) {
754 if (bd.Scan0)
755 ((char*)bd.Scan0)[2] = 0xff;
757 stat = GdipBitmapUnlockBits(bm, &bd);
758 expect(Ok, stat);
761 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
762 expect(Ok, stat);
763 expect(0xffff0000, color);
765 stat = GdipDisposeImage((GpImage*)bm);
766 expect(Ok, stat);
768 /* dispose locked */
769 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
770 expect(Ok, stat);
771 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
772 expect(Ok, stat);
773 stat = GdipDisposeImage((GpImage*)bm);
774 expect(Ok, stat);
777 static void test_LockBits_UserBuf(void)
779 GpStatus stat;
780 GpBitmap *bm;
781 GpRect rect;
782 BitmapData bd;
783 const INT WIDTH = 10, HEIGHT = 20;
784 DWORD bits[200];
785 ARGB color;
787 bm = NULL;
788 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
789 expect(Ok, stat);
791 memset(bits, 0xaa, sizeof(bits));
793 rect.X = 2;
794 rect.Y = 3;
795 rect.Width = 4;
796 rect.Height = 5;
798 bd.Width = 4;
799 bd.Height = 6;
800 bd.Stride = WIDTH * 4;
801 bd.PixelFormat = PixelFormat32bppARGB;
802 bd.Scan0 = &bits[2+3*WIDTH];
803 bd.Reserved = 0xaaaaaaaa;
805 /* read-only */
806 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
807 expect(Ok, stat);
809 expect(0xaaaaaaaa, bits[0]);
810 expect(0, bits[2+3*WIDTH]);
812 bits[2+3*WIDTH] = 0xdeadbeef;
814 if (stat == Ok) {
815 stat = GdipBitmapUnlockBits(bm, &bd);
816 expect(Ok, stat);
819 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
820 expect(Ok, stat);
821 expect(0, color);
823 /* write-only */
824 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
825 expect(Ok, stat);
827 expect(0xdeadbeef, bits[2+3*WIDTH]);
828 bits[2+3*WIDTH] = 0x12345678;
830 if (stat == Ok) {
831 stat = GdipBitmapUnlockBits(bm, &bd);
832 expect(Ok, stat);
835 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
836 expect(Ok, stat);
837 expect(0x12345678, color);
839 bits[2+3*WIDTH] = 0;
841 /* read/write */
842 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
843 expect(Ok, stat);
845 expect(0x12345678, bits[2+3*WIDTH]);
846 bits[2+3*WIDTH] = 0xdeadbeef;
848 if (stat == Ok) {
849 stat = GdipBitmapUnlockBits(bm, &bd);
850 expect(Ok, stat);
853 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
854 expect(Ok, stat);
855 expect(0xdeadbeef, color);
857 stat = GdipDisposeImage((GpImage*)bm);
858 expect(Ok, stat);
861 struct BITMAPINFOWITHBITFIELDS
863 BITMAPINFOHEADER bmiHeader;
864 DWORD masks[3];
867 union BITMAPINFOUNION
869 BITMAPINFO bi;
870 struct BITMAPINFOWITHBITFIELDS bf;
873 static void test_GdipCreateBitmapFromHBITMAP(void)
875 GpBitmap* gpbm = NULL;
876 HBITMAP hbm = NULL;
877 HPALETTE hpal = NULL;
878 GpStatus stat;
879 BYTE buff[1000];
880 LOGPALETTE* LogPal = NULL;
881 REAL width, height;
882 const REAL WIDTH1 = 5;
883 const REAL HEIGHT1 = 15;
884 const REAL WIDTH2 = 10;
885 const REAL HEIGHT2 = 20;
886 HDC hdc;
887 union BITMAPINFOUNION bmi;
888 BYTE *bits;
889 PixelFormat format;
891 stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
892 expect(InvalidParameter, stat);
894 hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
895 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
896 expect(InvalidParameter, stat);
898 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
899 expect(Ok, stat);
900 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
901 expectf(WIDTH1, width);
902 expectf(HEIGHT1, height);
903 if (stat == Ok)
904 GdipDisposeImage((GpImage*)gpbm);
905 DeleteObject(hbm);
907 memset(buff, 0, sizeof(buff));
908 hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
909 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
910 expect(Ok, stat);
911 /* raw format */
912 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
914 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
915 expectf(WIDTH2, width);
916 expectf(HEIGHT2, height);
917 if (stat == Ok)
918 GdipDisposeImage((GpImage*)gpbm);
919 DeleteObject(hbm);
921 hdc = CreateCompatibleDC(0);
922 ok(hdc != NULL, "CreateCompatibleDC failed\n");
923 bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
924 bmi.bi.bmiHeader.biHeight = HEIGHT1;
925 bmi.bi.bmiHeader.biWidth = WIDTH1;
926 bmi.bi.bmiHeader.biBitCount = 24;
927 bmi.bi.bmiHeader.biPlanes = 1;
928 bmi.bi.bmiHeader.biCompression = BI_RGB;
929 bmi.bi.bmiHeader.biClrUsed = 0;
931 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
932 ok(hbm != NULL, "CreateDIBSection failed\n");
934 bits[0] = 0;
936 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
937 expect(Ok, stat);
938 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
939 expectf(WIDTH1, width);
940 expectf(HEIGHT1, height);
941 if (stat == Ok)
943 /* test whether writing to the bitmap affects the original */
944 stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
945 expect(Ok, stat);
947 expect(0, bits[0]);
949 GdipDisposeImage((GpImage*)gpbm);
952 LogPal = GdipAlloc(sizeof(LOGPALETTE));
953 ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
954 LogPal->palVersion = 0x300;
955 LogPal->palNumEntries = 1;
956 hpal = CreatePalette(LogPal);
957 ok(hpal != NULL, "CreatePalette failed\n");
958 GdipFree(LogPal);
960 stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
961 expect(Ok, stat);
963 if (stat == Ok)
964 GdipDisposeImage((GpImage*)gpbm);
966 DeleteObject(hpal);
967 DeleteObject(hbm);
969 /* 16-bit 555 dib, rgb */
970 bmi.bi.bmiHeader.biBitCount = 16;
971 bmi.bi.bmiHeader.biCompression = BI_RGB;
973 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
974 ok(hbm != NULL, "CreateDIBSection failed\n");
976 bits[0] = 0;
978 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
979 expect(Ok, stat);
981 if (stat == Ok)
983 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
984 expect(Ok, stat);
985 expectf(WIDTH1, width);
986 expectf(HEIGHT1, height);
988 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
989 expect(Ok, stat);
990 expect(PixelFormat16bppRGB555, format);
992 GdipDisposeImage((GpImage*)gpbm);
994 DeleteObject(hbm);
996 /* 16-bit 555 dib, with bitfields */
997 bmi.bi.bmiHeader.biSize = sizeof(bmi);
998 bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
999 bmi.bf.masks[0] = 0x7c00;
1000 bmi.bf.masks[1] = 0x3e0;
1001 bmi.bf.masks[2] = 0x1f;
1003 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1004 ok(hbm != NULL, "CreateDIBSection failed\n");
1006 bits[0] = 0;
1008 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1009 expect(Ok, stat);
1011 if (stat == Ok)
1013 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1014 expect(Ok, stat);
1015 expectf(WIDTH1, width);
1016 expectf(HEIGHT1, height);
1018 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1019 expect(Ok, stat);
1020 expect(PixelFormat16bppRGB555, format);
1022 GdipDisposeImage((GpImage*)gpbm);
1024 DeleteObject(hbm);
1026 /* 16-bit 565 dib, with bitfields */
1027 bmi.bf.masks[0] = 0xf800;
1028 bmi.bf.masks[1] = 0x7e0;
1029 bmi.bf.masks[2] = 0x1f;
1031 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1032 ok(hbm != NULL, "CreateDIBSection failed\n");
1034 bits[0] = 0;
1036 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1037 expect(Ok, stat);
1039 if (stat == Ok)
1041 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1042 expect(Ok, stat);
1043 expectf(WIDTH1, width);
1044 expectf(HEIGHT1, height);
1046 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1047 expect(Ok, stat);
1048 expect(PixelFormat16bppRGB565, format);
1050 GdipDisposeImage((GpImage*)gpbm);
1052 DeleteObject(hbm);
1054 DeleteDC(hdc);
1057 static void test_GdipGetImageFlags(void)
1059 GpImage *img;
1060 GpStatus stat;
1061 UINT flags;
1063 img = (GpImage*)0xdeadbeef;
1065 stat = GdipGetImageFlags(NULL, NULL);
1066 expect(InvalidParameter, stat);
1068 stat = GdipGetImageFlags(NULL, &flags);
1069 expect(InvalidParameter, stat);
1071 stat = GdipGetImageFlags(img, NULL);
1072 expect(InvalidParameter, stat);
1074 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1075 expect(Ok, stat);
1076 stat = GdipGetImageFlags(img, &flags);
1077 expect(Ok, stat);
1078 expect(ImageFlagsHasAlpha, flags);
1079 GdipDisposeImage(img);
1081 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1082 expect(Ok, stat);
1083 stat = GdipGetImageFlags(img, &flags);
1084 expect(Ok, stat);
1085 expect(ImageFlagsHasAlpha, flags);
1086 GdipDisposeImage(img);
1088 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1089 expect(Ok, stat);
1090 stat = GdipGetImageFlags(img, &flags);
1091 expect(Ok, stat);
1092 expect(ImageFlagsHasAlpha, flags);
1093 GdipDisposeImage(img);
1095 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1096 expect(Ok, stat);
1097 stat = GdipGetImageFlags(img, &flags);
1098 expect(Ok, stat);
1099 expect(ImageFlagsNone, flags);
1100 GdipDisposeImage(img);
1102 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1103 expect(Ok, stat);
1104 stat = GdipGetImageFlags(img, &flags);
1105 expect(Ok, stat);
1106 expect(ImageFlagsNone, flags);
1107 GdipDisposeImage(img);
1109 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1110 expect(Ok, stat);
1111 stat = GdipGetImageFlags(img, &flags);
1112 expect(Ok, stat);
1113 expect(ImageFlagsNone, flags);
1114 GdipDisposeImage(img);
1116 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1117 expect(Ok, stat);
1118 stat = GdipGetImageFlags(img, &flags);
1119 expect(Ok, stat);
1120 expect(ImageFlagsHasAlpha, flags);
1121 GdipDisposeImage(img);
1123 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1124 expect(Ok, stat);
1125 stat = GdipGetImageFlags(img, &flags);
1126 expect(Ok, stat);
1127 expect(ImageFlagsNone, flags);
1128 GdipDisposeImage(img);
1130 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1131 expect(Ok, stat);
1132 stat = GdipGetImageFlags(img, &flags);
1133 expect(Ok, stat);
1134 expect(ImageFlagsNone, flags);
1135 GdipDisposeImage(img);
1137 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1138 expect(Ok, stat);
1139 stat = GdipGetImageFlags(img, &flags);
1140 expect(Ok, stat);
1141 expect(ImageFlagsHasAlpha, flags);
1142 GdipDisposeImage(img);
1144 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1145 expect(Ok, stat);
1146 stat = GdipGetImageFlags(img, &flags);
1147 expect(Ok, stat);
1148 expect(ImageFlagsHasAlpha, flags);
1149 GdipDisposeImage(img);
1151 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1152 expect(Ok, stat);
1153 if (stat == Ok)
1155 stat = GdipGetImageFlags(img, &flags);
1156 expect(Ok, stat);
1157 expect(ImageFlagsNone, flags);
1158 GdipDisposeImage(img);
1161 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1162 expect(Ok, stat);
1163 if (stat == Ok)
1165 expect(Ok, stat);
1166 stat = GdipGetImageFlags(img, &flags);
1167 expect(Ok, stat);
1168 expect(ImageFlagsHasAlpha, flags);
1169 GdipDisposeImage(img);
1172 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1173 expect(Ok, stat);
1174 if (stat == Ok)
1176 expect(Ok, stat);
1177 stat = GdipGetImageFlags(img, &flags);
1178 expect(Ok, stat);
1179 expect(ImageFlagsHasAlpha, flags);
1180 GdipDisposeImage(img);
1184 static void test_GdipCloneImage(void)
1186 GpStatus stat;
1187 GpRectF rectF;
1188 GpUnit unit;
1189 GpBitmap *bm;
1190 GpImage *image_src, *image_dest = NULL;
1191 const INT WIDTH = 10, HEIGHT = 20;
1193 /* Create an image, clone it, delete the original, make sure the copy works */
1194 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1195 expect(Ok, stat);
1196 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1198 image_src = ((GpImage*)bm);
1199 stat = GdipCloneImage(image_src, &image_dest);
1200 expect(Ok, stat);
1201 expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1203 stat = GdipDisposeImage((GpImage*)bm);
1204 expect(Ok, stat);
1205 stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1206 expect(Ok, stat);
1208 /* Treat FP values carefully */
1209 expectf((REAL)WIDTH, rectF.Width);
1210 expectf((REAL)HEIGHT, rectF.Height);
1212 stat = GdipDisposeImage(image_dest);
1213 expect(Ok, stat);
1216 static void test_testcontrol(void)
1218 GpStatus stat;
1219 DWORD param;
1221 param = 0;
1222 stat = GdipTestControl(TestControlGetBuildNumber, &param);
1223 expect(Ok, stat);
1224 ok(param != 0, "Build number expected, got %u\n", param);
1227 static void test_fromhicon(void)
1229 static const BYTE bmp_bits[1024];
1230 HBITMAP hbmMask, hbmColor;
1231 ICONINFO info;
1232 HICON hIcon;
1233 GpStatus stat;
1234 GpBitmap *bitmap = NULL;
1235 UINT dim;
1236 ImageType type;
1237 PixelFormat format;
1239 /* NULL */
1240 stat = GdipCreateBitmapFromHICON(NULL, NULL);
1241 expect(InvalidParameter, stat);
1242 stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1243 expect(InvalidParameter, stat);
1245 /* color icon 1 bit */
1246 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1247 ok(hbmMask != 0, "CreateBitmap failed\n");
1248 hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1249 ok(hbmColor != 0, "CreateBitmap failed\n");
1250 info.fIcon = TRUE;
1251 info.xHotspot = 8;
1252 info.yHotspot = 8;
1253 info.hbmMask = hbmMask;
1254 info.hbmColor = hbmColor;
1255 hIcon = CreateIconIndirect(&info);
1256 ok(hIcon != 0, "CreateIconIndirect failed\n");
1257 DeleteObject(hbmMask);
1258 DeleteObject(hbmColor);
1260 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1261 ok(stat == Ok ||
1262 broken(stat == InvalidParameter), /* Win98 */
1263 "Expected Ok, got %.8x\n", stat);
1264 if(stat == Ok){
1265 /* check attributes */
1266 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1267 expect(Ok, stat);
1268 expect(16, dim);
1269 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1270 expect(Ok, stat);
1271 expect(16, dim);
1272 stat = GdipGetImageType((GpImage*)bitmap, &type);
1273 expect(Ok, stat);
1274 expect(ImageTypeBitmap, type);
1275 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1276 expect(Ok, stat);
1277 expect(PixelFormat32bppARGB, format);
1278 /* raw format */
1279 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1280 GdipDisposeImage((GpImage*)bitmap);
1282 DestroyIcon(hIcon);
1284 /* color icon 8 bpp */
1285 hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1286 ok(hbmMask != 0, "CreateBitmap failed\n");
1287 hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1288 ok(hbmColor != 0, "CreateBitmap failed\n");
1289 info.fIcon = TRUE;
1290 info.xHotspot = 8;
1291 info.yHotspot = 8;
1292 info.hbmMask = hbmMask;
1293 info.hbmColor = hbmColor;
1294 hIcon = CreateIconIndirect(&info);
1295 ok(hIcon != 0, "CreateIconIndirect failed\n");
1296 DeleteObject(hbmMask);
1297 DeleteObject(hbmColor);
1299 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1300 expect(Ok, stat);
1301 if(stat == Ok){
1302 /* check attributes */
1303 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1304 expect(Ok, stat);
1305 expect(16, dim);
1306 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1307 expect(Ok, stat);
1308 expect(16, dim);
1309 stat = GdipGetImageType((GpImage*)bitmap, &type);
1310 expect(Ok, stat);
1311 expect(ImageTypeBitmap, type);
1312 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1313 expect(Ok, stat);
1314 expect(PixelFormat32bppARGB, format);
1315 /* raw format */
1316 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1317 GdipDisposeImage((GpImage*)bitmap);
1319 DestroyIcon(hIcon);
1322 /* 1x1 pixel png */
1323 static const unsigned char pngimage[285] = {
1324 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1325 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1326 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1327 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1328 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1329 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1330 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1332 /* 1x1 pixel gif */
1333 static const unsigned char gifimage[35] = {
1334 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1335 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1336 0x01,0x00,0x3b
1338 /* 1x1 pixel transparent gif */
1339 static const unsigned char transparentgif[] = {
1340 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
1341 0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,
1342 0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
1344 /* 1x1 pixel bmp */
1345 static const unsigned char bmpimage[66] = {
1346 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1347 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1348 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1349 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1350 0x00,0x00
1352 /* 1x1 pixel jpg */
1353 static const unsigned char jpgimage[285] = {
1354 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1355 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1356 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1357 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1358 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1359 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1360 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1361 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1362 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1363 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1364 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1365 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1366 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1368 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1369 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1370 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1371 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1373 /* 1x1 pixel tiff */
1374 static const unsigned char tiffimage[] = {
1375 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1376 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1377 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1378 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1379 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1380 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1381 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1382 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1383 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1384 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1385 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1386 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1387 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1388 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1389 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1390 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1391 0x00,0x00,0x00,0x01
1393 /* 320x320 twip wmf */
1394 static const unsigned char wmfimage[180] = {
1395 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1396 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1397 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1398 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1399 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1400 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1401 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1402 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1403 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1404 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1405 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1406 0x00,0x00,0x00,0x00
1408 static void test_getrawformat(void)
1410 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE);
1411 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE);
1412 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE);
1413 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1414 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1415 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1418 static void test_loadwmf(void)
1420 LPSTREAM stream;
1421 HGLOBAL hglob;
1422 LPBYTE data;
1423 HRESULT hres;
1424 GpStatus stat;
1425 GpImage *img;
1426 GpRectF bounds;
1427 GpUnit unit;
1428 REAL res = 12345.0;
1429 MetafileHeader header;
1431 hglob = GlobalAlloc (0, sizeof(wmfimage));
1432 data = GlobalLock (hglob);
1433 memcpy(data, wmfimage, sizeof(wmfimage));
1434 GlobalUnlock(hglob); data = NULL;
1436 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1437 ok(hres == S_OK, "Failed to create a stream\n");
1438 if(hres != S_OK) return;
1440 stat = GdipLoadImageFromStream(stream, &img);
1441 ok(stat == Ok, "Failed to create a Bitmap\n");
1442 if(stat != Ok){
1443 IStream_Release(stream);
1444 return;
1447 IStream_Release(stream);
1449 stat = GdipGetImageBounds(img, &bounds, &unit);
1450 expect(Ok, stat);
1451 todo_wine expect(UnitPixel, unit);
1452 expectf(0.0, bounds.X);
1453 expectf(0.0, bounds.Y);
1454 todo_wine expectf(320.0, bounds.Width);
1455 todo_wine expectf(320.0, bounds.Height);
1457 stat = GdipGetImageHorizontalResolution(img, &res);
1458 expect(Ok, stat);
1459 todo_wine expectf(1440.0, res);
1461 stat = GdipGetImageVerticalResolution(img, &res);
1462 expect(Ok, stat);
1463 todo_wine expectf(1440.0, res);
1465 memset(&header, 0, sizeof(header));
1466 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1467 expect(Ok, stat);
1468 if (stat == Ok)
1470 todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1471 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1472 todo_wine expect(0x300, header.Version);
1473 expect(0, header.EmfPlusFlags);
1474 todo_wine expectf(1440.0, header.DpiX);
1475 todo_wine expectf(1440.0, header.DpiY);
1476 expect(0, header.X);
1477 expect(0, header.Y);
1478 todo_wine expect(320, header.Width);
1479 todo_wine expect(320, header.Height);
1480 todo_wine expect(1, U(header).WmfHeader.mtType);
1481 expect(0, header.EmfPlusHeaderSize);
1482 expect(0, header.LogicalDpiX);
1483 expect(0, header.LogicalDpiY);
1486 GdipDisposeImage(img);
1489 static void test_createfromwmf(void)
1491 HMETAFILE hwmf;
1492 GpImage *img;
1493 GpStatus stat;
1494 GpRectF bounds;
1495 GpUnit unit;
1496 REAL res = 12345.0;
1497 MetafileHeader header;
1499 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1500 wmfimage+sizeof(WmfPlaceableFileHeader));
1501 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1503 stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1504 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1505 expect(Ok, stat);
1507 stat = GdipGetImageBounds(img, &bounds, &unit);
1508 expect(Ok, stat);
1509 expect(UnitPixel, unit);
1510 expectf(0.0, bounds.X);
1511 expectf(0.0, bounds.Y);
1512 expectf(320.0, bounds.Width);
1513 expectf(320.0, bounds.Height);
1515 stat = GdipGetImageHorizontalResolution(img, &res);
1516 expect(Ok, stat);
1517 expectf(1440.0, res);
1519 stat = GdipGetImageVerticalResolution(img, &res);
1520 expect(Ok, stat);
1521 expectf(1440.0, res);
1523 memset(&header, 0, sizeof(header));
1524 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1525 expect(Ok, stat);
1526 if (stat == Ok)
1528 todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1529 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1530 todo_wine expect(0x300, header.Version);
1531 expect(0, header.EmfPlusFlags);
1532 todo_wine expectf(1440.0, header.DpiX);
1533 todo_wine expectf(1440.0, header.DpiY);
1534 expect(0, header.X);
1535 expect(0, header.Y);
1536 todo_wine expect(320, header.Width);
1537 todo_wine expect(320, header.Height);
1538 todo_wine expect(1, U(header).WmfHeader.mtType);
1539 expect(0, header.EmfPlusHeaderSize);
1540 expect(0, header.LogicalDpiX);
1541 expect(0, header.LogicalDpiY);
1544 GdipDisposeImage(img);
1547 static void test_createfromwmf_noplaceable(void)
1549 HMETAFILE hwmf;
1550 GpImage *img;
1551 GpStatus stat;
1553 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1554 wmfimage+sizeof(WmfPlaceableFileHeader));
1555 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1557 stat = GdipCreateMetafileFromWmf(hwmf, TRUE, NULL, (GpMetafile**)&img);
1558 expect(Ok, stat);
1560 GdipDisposeImage(img);
1563 static void test_resolution(void)
1565 GpStatus stat;
1566 GpBitmap *bitmap;
1567 GpGraphics *graphics;
1568 REAL res=-1.0;
1569 HDC screendc;
1570 int screenxres, screenyres;
1572 /* create Bitmap */
1573 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1574 expect(Ok, stat);
1576 /* test invalid values */
1577 stat = GdipGetImageHorizontalResolution(NULL, &res);
1578 expect(InvalidParameter, stat);
1580 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1581 expect(InvalidParameter, stat);
1583 stat = GdipGetImageVerticalResolution(NULL, &res);
1584 expect(InvalidParameter, stat);
1586 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1587 expect(InvalidParameter, stat);
1589 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1590 expect(InvalidParameter, stat);
1592 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1593 expect(InvalidParameter, stat);
1595 /* defaults to screen resolution */
1596 screendc = GetDC(0);
1598 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1599 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1601 ReleaseDC(0, screendc);
1603 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1604 expect(Ok, stat);
1605 expectf((REAL)screenxres, res);
1607 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1608 expect(Ok, stat);
1609 expectf((REAL)screenyres, res);
1611 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1612 expect(Ok, stat);
1613 stat = GdipGetDpiX(graphics, &res);
1614 expect(Ok, stat);
1615 expectf((REAL)screenxres, res);
1616 stat = GdipGetDpiY(graphics, &res);
1617 expect(Ok, stat);
1618 expectf((REAL)screenyres, res);
1620 /* test changing the resolution */
1621 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1622 expect(Ok, stat);
1624 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1625 expect(Ok, stat);
1626 expectf(screenxres*2.0, res);
1628 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1629 expect(Ok, stat);
1630 expectf(screenyres*3.0, res);
1632 stat = GdipGetDpiX(graphics, &res);
1633 expect(Ok, stat);
1634 expectf((REAL)screenxres, res);
1635 stat = GdipGetDpiY(graphics, &res);
1636 expect(Ok, stat);
1637 expectf((REAL)screenyres, res);
1639 stat = GdipDeleteGraphics(graphics);
1640 expect(Ok, stat);
1642 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1643 expect(Ok, stat);
1644 stat = GdipGetDpiX(graphics, &res);
1645 expect(Ok, stat);
1646 expectf(screenxres*2.0, res);
1647 stat = GdipGetDpiY(graphics, &res);
1648 expect(Ok, stat);
1649 expectf(screenyres*3.0, res);
1650 stat = GdipDeleteGraphics(graphics);
1651 expect(Ok, stat);
1653 stat = GdipDisposeImage((GpImage*)bitmap);
1654 expect(Ok, stat);
1657 static void test_createhbitmap(void)
1659 GpStatus stat;
1660 GpBitmap *bitmap;
1661 HBITMAP hbitmap, oldhbitmap;
1662 BITMAP bm;
1663 int ret;
1664 HDC hdc;
1665 COLORREF pixel;
1666 BYTE bits[640];
1668 memset(bits, 0x68, 640);
1670 /* create Bitmap */
1671 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1672 expect(Ok, stat);
1674 /* test NULL values */
1675 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1676 expect(InvalidParameter, stat);
1678 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1679 expect(InvalidParameter, stat);
1681 /* create HBITMAP */
1682 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1683 expect(Ok, stat);
1685 if (stat == Ok)
1687 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1688 expect(sizeof(BITMAP), ret);
1690 expect(0, bm.bmType);
1691 expect(10, bm.bmWidth);
1692 expect(20, bm.bmHeight);
1693 expect(40, bm.bmWidthBytes);
1694 expect(1, bm.bmPlanes);
1695 expect(32, bm.bmBitsPixel);
1696 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1698 if (bm.bmBits)
1700 DWORD val = *(DWORD*)bm.bmBits;
1701 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1704 hdc = CreateCompatibleDC(NULL);
1706 oldhbitmap = SelectObject(hdc, hbitmap);
1707 pixel = GetPixel(hdc, 5, 5);
1708 SelectObject(hdc, oldhbitmap);
1710 DeleteDC(hdc);
1712 expect(0x686868, pixel);
1714 DeleteObject(hbitmap);
1717 stat = GdipDisposeImage((GpImage*)bitmap);
1718 expect(Ok, stat);
1720 /* make (1,0) have no alpha and (2,0) a different blue value. */
1721 bits[7] = 0x00;
1722 bits[8] = 0x40;
1724 /* create alpha Bitmap */
1725 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1726 expect(Ok, stat);
1728 /* create HBITMAP */
1729 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1730 expect(Ok, stat);
1732 if (stat == Ok)
1734 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1735 expect(sizeof(BITMAP), ret);
1737 expect(0, bm.bmType);
1738 expect(8, bm.bmWidth);
1739 expect(20, bm.bmHeight);
1740 expect(32, bm.bmWidthBytes);
1741 expect(1, bm.bmPlanes);
1742 expect(32, bm.bmBitsPixel);
1743 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1745 if (bm.bmBits)
1747 DWORD val = *(DWORD*)bm.bmBits;
1748 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1749 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1750 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1753 hdc = CreateCompatibleDC(NULL);
1755 oldhbitmap = SelectObject(hdc, hbitmap);
1756 pixel = GetPixel(hdc, 5, 5);
1757 expect(0x2a2a2a, pixel);
1758 pixel = GetPixel(hdc, 1, 0);
1759 expect(0x0, pixel);
1761 SelectObject(hdc, oldhbitmap);
1763 DeleteDC(hdc);
1766 DeleteObject(hbitmap);
1769 /* create HBITMAP with bkgnd colour */
1770 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1771 expect(Ok, stat);
1773 if (stat == Ok)
1775 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1776 expect(sizeof(BITMAP), ret);
1778 expect(0, bm.bmType);
1779 expect(8, bm.bmWidth);
1780 expect(20, bm.bmHeight);
1781 expect(32, bm.bmWidthBytes);
1782 expect(1, bm.bmPlanes);
1783 expect(32, bm.bmBitsPixel);
1784 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1786 if (bm.bmBits)
1788 DWORD val = *(DWORD*)bm.bmBits;
1789 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1790 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1791 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1794 hdc = CreateCompatibleDC(NULL);
1796 oldhbitmap = SelectObject(hdc, hbitmap);
1797 pixel = GetPixel(hdc, 5, 5);
1798 expect(0xc12ac1, pixel);
1799 pixel = GetPixel(hdc, 1, 0);
1800 expect(0xff00ff, pixel);
1801 pixel = GetPixel(hdc, 2, 0);
1802 expect(0xb12ac1, pixel);
1804 SelectObject(hdc, oldhbitmap);
1805 DeleteDC(hdc);
1806 DeleteObject(hbitmap);
1809 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1810 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1811 expect(Ok, stat);
1813 if (stat == Ok)
1815 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1816 expect(sizeof(BITMAP), ret);
1818 expect(0, bm.bmType);
1819 expect(8, bm.bmWidth);
1820 expect(20, bm.bmHeight);
1821 expect(32, bm.bmWidthBytes);
1822 expect(1, bm.bmPlanes);
1823 expect(32, bm.bmBitsPixel);
1824 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1826 if (bm.bmBits)
1828 DWORD val = *(DWORD*)bm.bmBits;
1829 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1830 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1831 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1834 hdc = CreateCompatibleDC(NULL);
1836 oldhbitmap = SelectObject(hdc, hbitmap);
1837 pixel = GetPixel(hdc, 5, 5);
1838 expect(0xc12ac1, pixel);
1839 pixel = GetPixel(hdc, 1, 0);
1840 expect(0xff00ff, pixel);
1841 pixel = GetPixel(hdc, 2, 0);
1842 expect(0xb12ac1, pixel);
1844 SelectObject(hdc, oldhbitmap);
1845 DeleteDC(hdc);
1846 DeleteObject(hbitmap);
1849 stat = GdipDisposeImage((GpImage*)bitmap);
1850 expect(Ok, stat);
1853 static void test_getthumbnail(void)
1855 GpStatus stat;
1856 GpImage *bitmap1, *bitmap2;
1857 UINT width, height;
1859 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1860 expect(InvalidParameter, stat);
1862 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1863 expect(Ok, stat);
1865 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1866 expect(InvalidParameter, stat);
1868 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1869 expect(Ok, stat);
1871 if (stat == Ok)
1873 stat = GdipGetImageWidth(bitmap2, &width);
1874 expect(Ok, stat);
1875 expect(120, width);
1877 stat = GdipGetImageHeight(bitmap2, &height);
1878 expect(Ok, stat);
1879 expect(120, height);
1881 GdipDisposeImage(bitmap2);
1884 GdipDisposeImage(bitmap1);
1887 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1888 expect(Ok, stat);
1890 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1891 expect(Ok, stat);
1893 if (stat == Ok)
1895 stat = GdipGetImageWidth(bitmap2, &width);
1896 expect(Ok, stat);
1897 expect(32, width);
1899 stat = GdipGetImageHeight(bitmap2, &height);
1900 expect(Ok, stat);
1901 expect(32, height);
1903 GdipDisposeImage(bitmap2);
1906 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1907 expect(Ok, stat);
1909 if (stat == Ok)
1911 stat = GdipGetImageWidth(bitmap2, &width);
1912 expect(Ok, stat);
1913 expect(120, width);
1915 stat = GdipGetImageHeight(bitmap2, &height);
1916 expect(Ok, stat);
1917 expect(120, height);
1919 GdipDisposeImage(bitmap2);
1922 GdipDisposeImage(bitmap1);
1925 static void test_getsetpixel(void)
1927 GpStatus stat;
1928 GpBitmap *bitmap;
1929 ARGB color;
1930 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1931 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1933 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1934 expect(Ok, stat);
1936 /* null parameters */
1937 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1938 expect(InvalidParameter, stat);
1940 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1941 expect(InvalidParameter, stat);
1943 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1944 expect(InvalidParameter, stat);
1946 /* out of bounds */
1947 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1948 expect(InvalidParameter, stat);
1950 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1951 expect(InvalidParameter, stat);
1953 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1954 ok(stat == InvalidParameter ||
1955 broken(stat == Ok), /* Older gdiplus */
1956 "Expected InvalidParameter, got %.8x\n", stat);
1958 if (0) /* crashes some gdiplus implementations */
1960 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1961 ok(stat == InvalidParameter ||
1962 broken(stat == Ok), /* Older gdiplus */
1963 "Expected InvalidParameter, got %.8x\n", stat);
1966 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1967 expect(InvalidParameter, stat);
1969 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1970 expect(InvalidParameter, stat);
1972 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1973 expect(InvalidParameter, stat);
1975 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1976 expect(InvalidParameter, stat);
1978 /* valid use */
1979 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1980 expect(Ok, stat);
1981 expect(0xffffffff, color);
1983 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1984 expect(Ok, stat);
1985 expect(0xff0000ff, color);
1987 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1988 expect(Ok, stat);
1990 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1991 expect(Ok, stat);
1993 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1994 expect(Ok, stat);
1995 expect(0xff676869, color);
1997 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1998 expect(Ok, stat);
1999 expect(0xff474849, color);
2001 stat = GdipDisposeImage((GpImage*)bitmap);
2002 expect(Ok, stat);
2005 static void check_halftone_palette(ColorPalette *palette)
2007 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
2008 UINT i;
2010 for (i=0; i<palette->Count; i++)
2012 ARGB expected=0xff000000;
2013 if (i<8)
2015 if (i&1) expected |= 0x800000;
2016 if (i&2) expected |= 0x8000;
2017 if (i&4) expected |= 0x80;
2019 else if (i == 8)
2021 expected = 0xffc0c0c0;
2023 else if (i < 16)
2025 if (i&1) expected |= 0xff0000;
2026 if (i&2) expected |= 0xff00;
2027 if (i&4) expected |= 0xff;
2029 else if (i < 40)
2031 expected = 0x00000000;
2033 else
2035 expected |= halftone_values[(i-40)%6];
2036 expected |= halftone_values[((i-40)/6)%6] << 8;
2037 expected |= halftone_values[((i-40)/36)%6] << 16;
2039 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2040 expected, palette->Entries[i], i, palette->Count);
2044 static void test_palette(void)
2046 GpStatus stat;
2047 GpBitmap *bitmap;
2048 INT size;
2049 BYTE buffer[1040];
2050 ColorPalette *palette=(ColorPalette*)buffer;
2051 ARGB *entries = palette->Entries;
2052 ARGB color=0;
2054 /* test initial palette from non-indexed bitmap */
2055 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2056 expect(Ok, stat);
2058 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2059 expect(Ok, stat);
2060 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2062 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2063 expect(Ok, stat);
2064 expect(0, palette->Count);
2066 /* test setting palette on not-indexed bitmap */
2067 palette->Count = 3;
2069 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2070 expect(Ok, stat);
2072 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2073 expect(Ok, stat);
2074 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2076 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2077 expect(Ok, stat);
2078 expect(3, palette->Count);
2080 GdipDisposeImage((GpImage*)bitmap);
2082 /* test initial palette on 1-bit bitmap */
2083 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2084 expect(Ok, stat);
2086 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2087 expect(Ok, stat);
2088 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2090 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2091 expect(Ok, stat);
2092 expect(PaletteFlagsGrayScale, palette->Flags);
2093 expect(2, palette->Count);
2095 expect(0xff000000, entries[0]);
2096 expect(0xffffffff, entries[1]);
2098 /* test getting/setting pixels */
2099 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2100 expect(Ok, stat);
2101 expect(0xff000000, color);
2103 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2104 ok((stat == Ok) ||
2105 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2107 if (stat == Ok)
2109 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2110 expect(Ok, stat);
2111 expect(0xffffffff, color);
2114 GdipDisposeImage((GpImage*)bitmap);
2116 /* test initial palette on 4-bit bitmap */
2117 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2118 expect(Ok, stat);
2120 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2121 expect(Ok, stat);
2122 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2124 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2125 expect(Ok, stat);
2126 expect(0, palette->Flags);
2127 expect(16, palette->Count);
2129 check_halftone_palette(palette);
2131 /* test getting/setting pixels */
2132 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2133 expect(Ok, stat);
2134 expect(0xff000000, color);
2136 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2137 ok((stat == Ok) ||
2138 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2140 if (stat == Ok)
2142 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2143 expect(Ok, stat);
2144 expect(0xffff00ff, color);
2147 GdipDisposeImage((GpImage*)bitmap);
2149 /* test initial palette on 8-bit bitmap */
2150 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2151 expect(Ok, stat);
2153 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2154 expect(Ok, stat);
2155 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2157 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2158 expect(Ok, stat);
2159 expect(PaletteFlagsHalftone, palette->Flags);
2160 expect(256, palette->Count);
2162 check_halftone_palette(palette);
2164 /* test getting/setting pixels */
2165 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2166 expect(Ok, stat);
2167 expect(0xff000000, color);
2169 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2170 ok((stat == Ok) ||
2171 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2173 if (stat == Ok)
2175 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2176 expect(Ok, stat);
2177 expect(0xffcccccc, color);
2180 /* test setting/getting a different palette */
2181 entries[1] = 0xffcccccc;
2183 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2184 expect(Ok, stat);
2186 entries[1] = 0;
2188 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2189 expect(Ok, stat);
2190 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2192 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2193 expect(Ok, stat);
2194 expect(PaletteFlagsHalftone, palette->Flags);
2195 expect(256, palette->Count);
2196 expect(0xffcccccc, entries[1]);
2198 /* test count < 256 */
2199 palette->Flags = 12345;
2200 palette->Count = 3;
2202 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2203 expect(Ok, stat);
2205 entries[1] = 0;
2206 entries[3] = 0xdeadbeef;
2208 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2209 expect(Ok, stat);
2210 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2212 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2213 expect(Ok, stat);
2214 expect(12345, palette->Flags);
2215 expect(3, palette->Count);
2216 expect(0xffcccccc, entries[1]);
2217 expect(0xdeadbeef, entries[3]);
2219 /* test count > 256 */
2220 palette->Count = 257;
2222 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2223 ok(stat == InvalidParameter ||
2224 broken(stat == Ok), /* Old gdiplus behavior */
2225 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2227 GdipDisposeImage((GpImage*)bitmap);
2230 static void test_colormatrix(void)
2232 GpStatus stat;
2233 ColorMatrix colormatrix, graymatrix;
2234 GpImageAttributes *imageattr;
2235 const ColorMatrix identity = {{
2236 {1.0,0.0,0.0,0.0,0.0},
2237 {0.0,1.0,0.0,0.0,0.0},
2238 {0.0,0.0,1.0,0.0,0.0},
2239 {0.0,0.0,0.0,1.0,0.0},
2240 {0.0,0.0,0.0,0.0,1.0}}};
2241 const ColorMatrix double_red = {{
2242 {2.0,0.0,0.0,0.0,0.0},
2243 {0.0,1.0,0.0,0.0,0.0},
2244 {0.0,0.0,1.0,0.0,0.0},
2245 {0.0,0.0,0.0,1.0,0.0},
2246 {0.0,0.0,0.0,0.0,1.0}}};
2247 const ColorMatrix asymmetric = {{
2248 {0.0,1.0,0.0,0.0,0.0},
2249 {0.0,0.0,1.0,0.0,0.0},
2250 {0.0,0.0,0.0,1.0,0.0},
2251 {1.0,0.0,0.0,0.0,0.0},
2252 {0.0,0.0,0.0,0.0,1.0}}};
2253 GpBitmap *bitmap1, *bitmap2;
2254 GpGraphics *graphics;
2255 ARGB color;
2257 colormatrix = identity;
2258 graymatrix = identity;
2260 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2261 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2262 expect(InvalidParameter, stat);
2264 stat = GdipCreateImageAttributes(&imageattr);
2265 expect(Ok, stat);
2267 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2268 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2269 expect(Ok, stat);
2271 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2272 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2273 expect(InvalidParameter, stat);
2275 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2276 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2277 expect(Ok, stat);
2279 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2280 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2281 expect(Ok, stat);
2283 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2284 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2285 expect(InvalidParameter, stat);
2287 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2288 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2289 expect(Ok, stat);
2291 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2292 TRUE, &colormatrix, &graymatrix, 3);
2293 expect(InvalidParameter, stat);
2295 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2296 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2297 expect(InvalidParameter, stat);
2299 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2300 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2301 expect(InvalidParameter, stat);
2303 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2304 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2305 expect(Ok, stat);
2307 /* Drawing a bitmap transforms the colors */
2308 colormatrix = double_red;
2309 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2310 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2311 expect(Ok, stat);
2313 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2314 expect(Ok, stat);
2316 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2317 expect(Ok, stat);
2319 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2320 expect(Ok, stat);
2322 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2323 expect(Ok, stat);
2325 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2326 UnitPixel, imageattr, NULL, NULL);
2327 expect(Ok, stat);
2329 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2330 expect(Ok, stat);
2331 expect(0xff80ccee, color);
2333 colormatrix = asymmetric;
2334 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2335 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2336 expect(Ok, stat);
2338 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2339 expect(Ok, stat);
2341 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2342 UnitPixel, imageattr, NULL, NULL);
2343 expect(Ok, stat);
2345 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2346 expect(Ok, stat);
2347 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2349 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2350 expect(Ok, stat);
2352 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2353 UnitPixel, imageattr, NULL, NULL);
2354 expect(Ok, stat);
2356 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2357 expect(Ok, stat);
2358 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2360 GdipDeleteGraphics(graphics);
2361 GdipDisposeImage((GpImage*)bitmap1);
2362 GdipDisposeImage((GpImage*)bitmap2);
2363 GdipDisposeImageAttributes(imageattr);
2366 static void test_gamma(void)
2368 GpStatus stat;
2369 GpImageAttributes *imageattr;
2370 GpBitmap *bitmap1, *bitmap2;
2371 GpGraphics *graphics;
2372 ARGB color;
2374 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2375 expect(InvalidParameter, stat);
2377 stat = GdipCreateImageAttributes(&imageattr);
2378 expect(Ok, stat);
2380 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2381 expect(Ok, stat);
2383 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2384 expect(InvalidParameter, stat);
2386 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2387 expect(InvalidParameter, stat);
2389 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2390 expect(InvalidParameter, stat);
2392 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2393 expect(Ok, stat);
2395 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2396 expect(Ok, stat);
2398 /* Drawing a bitmap transforms the colors */
2399 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2400 expect(Ok, stat);
2402 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2403 expect(Ok, stat);
2405 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2406 expect(Ok, stat);
2408 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2409 expect(Ok, stat);
2411 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2412 expect(Ok, stat);
2414 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2415 UnitPixel, imageattr, NULL, NULL);
2416 expect(Ok, stat);
2418 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2419 expect(Ok, stat);
2420 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2422 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2423 expect(Ok, stat);
2425 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2426 UnitPixel, imageattr, NULL, NULL);
2427 expect(Ok, stat);
2429 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2430 expect(Ok, stat);
2431 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2433 GdipDeleteGraphics(graphics);
2434 GdipDisposeImage((GpImage*)bitmap1);
2435 GdipDisposeImage((GpImage*)bitmap2);
2436 GdipDisposeImageAttributes(imageattr);
2439 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2440 static const unsigned char gifanimation[72] = {
2441 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2442 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2443 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2444 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2445 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2448 /* Generated with ImageMagick:
2449 * convert -transparent black -delay 100 -size 8x2 xc:black \
2450 * -dispose none -page +0+0 -size 2x2 xc:red \
2451 * -dispose background -page +2+0 -size 2x2 xc:blue \
2452 * -dispose previous -page +4+0 -size 2x2 xc:green \
2453 * -dispose undefined -page +6+0 -size 2x2 xc:gray \
2454 * test.gif
2456 static const unsigned char gifanimation2[] = {
2457 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2458 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2459 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2460 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2461 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2462 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2463 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2464 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2465 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2466 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2467 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2468 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2469 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2470 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2471 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2472 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2473 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2474 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2475 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2476 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2477 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2478 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2479 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2480 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2481 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2482 0x3b
2485 static ARGB gifanimation2_pixels[5][4] = {
2486 {0, 0, 0, 0},
2487 {0xffff0000, 0, 0, 0},
2488 {0xffff0000, 0xff0000ff, 0, 0},
2489 {0xffff0000, 0, 0xff008000, 0},
2490 {0xffff0000, 0, 0, 0xff7e7e7e}
2493 static void test_multiframegif(void)
2495 LPSTREAM stream;
2496 HGLOBAL hglob;
2497 LPBYTE data;
2498 HRESULT hres;
2499 GpStatus stat;
2500 GpBitmap *bmp;
2501 ARGB color;
2502 UINT count;
2503 GUID dimension;
2504 PixelFormat pixel_format;
2505 INT palette_size, i, j;
2506 char palette_buf[256];
2507 ColorPalette *palette;
2508 ARGB *palette_entries;
2510 /* Test frame functions with an animated GIF */
2511 hglob = GlobalAlloc (0, sizeof(gifanimation));
2512 data = GlobalLock (hglob);
2513 memcpy(data, gifanimation, sizeof(gifanimation));
2514 GlobalUnlock(hglob);
2516 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2517 ok(hres == S_OK, "Failed to create a stream\n");
2518 if(hres != S_OK) return;
2520 stat = GdipCreateBitmapFromStream(stream, &bmp);
2521 ok(stat == Ok, "Failed to create a Bitmap\n");
2522 if(stat != Ok){
2523 IStream_Release(stream);
2524 return;
2527 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2528 expect(Ok, stat);
2529 expect(PixelFormat32bppARGB, pixel_format);
2531 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2532 expect(Ok, stat);
2533 ok(palette_size == sizeof(ColorPalette) ||
2534 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2535 "palette_size = %d\n", palette_size);
2537 /* Bitmap starts at frame 0 */
2538 color = 0xdeadbeef;
2539 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2540 expect(Ok, stat);
2541 expect(0xffffffff, color);
2543 /* Check that we get correct metadata */
2544 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2545 expect(Ok, stat);
2546 expect(1, count);
2548 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2549 expect(Ok, stat);
2550 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2552 count = 12345;
2553 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2554 expect(Ok, stat);
2555 expect(2, count);
2557 /* SelectActiveFrame overwrites our current data */
2558 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2559 expect(Ok, stat);
2561 color = 0xdeadbeef;
2562 GdipBitmapGetPixel(bmp, 0, 0, &color);
2563 expect(Ok, stat);
2564 expect(0xff000000, color);
2566 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2567 expect(Ok, stat);
2569 color = 0xdeadbeef;
2570 GdipBitmapGetPixel(bmp, 0, 0, &color);
2571 expect(Ok, stat);
2572 expect(0xffffffff, color);
2574 /* Write over the image data */
2575 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2576 expect(Ok, stat);
2578 /* Switching to the same frame does not overwrite our changes */
2579 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2580 expect(Ok, stat);
2582 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2583 expect(Ok, stat);
2584 expect(0xff000000, color);
2586 /* But switching to another frame and back does */
2587 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2588 expect(Ok, stat);
2590 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2591 expect(Ok, stat);
2593 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2594 expect(Ok, stat);
2595 expect(0xffffffff, color);
2597 /* rotate/flip discards the information about other frames */
2598 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2599 expect(Ok, stat);
2601 count = 12345;
2602 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2603 expect(Ok, stat);
2604 expect(1, count);
2606 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2608 GdipDisposeImage((GpImage*)bmp);
2609 IStream_Release(stream);
2611 /* Test with a non-animated gif */
2612 hglob = GlobalAlloc (0, sizeof(gifimage));
2613 data = GlobalLock (hglob);
2614 memcpy(data, gifimage, sizeof(gifimage));
2615 GlobalUnlock(hglob);
2617 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2618 ok(hres == S_OK, "Failed to create a stream\n");
2619 if(hres != S_OK) return;
2621 stat = GdipCreateBitmapFromStream(stream, &bmp);
2622 ok(stat == Ok, "Failed to create a Bitmap\n");
2623 if(stat != Ok){
2624 IStream_Release(stream);
2625 return;
2628 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2629 expect(Ok, stat);
2630 expect(PixelFormat8bppIndexed, pixel_format);
2632 /* Check metadata */
2633 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2634 expect(Ok, stat);
2635 expect(1, count);
2637 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2638 expect(Ok, stat);
2639 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2641 count = 12345;
2642 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2643 expect(Ok, stat);
2644 expect(1, count);
2646 GdipDisposeImage((GpImage*)bmp);
2647 IStream_Release(stream);
2649 /* Test with a non-animated transparent gif */
2650 hglob = GlobalAlloc (0, sizeof(transparentgif));
2651 data = GlobalLock (hglob);
2652 memcpy(data, transparentgif, sizeof(transparentgif));
2653 GlobalUnlock(hglob);
2655 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2656 ok(hres == S_OK, "Failed to create a stream\n");
2658 stat = GdipCreateBitmapFromStream(stream, &bmp);
2659 IStream_Release(stream);
2660 ok(stat == Ok, "Failed to create a Bitmap\n");
2662 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2663 expect(Ok, stat);
2664 expect(PixelFormat8bppIndexed, pixel_format);
2666 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2667 expect(Ok, stat);
2668 expect(0, color);
2670 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2671 expect(Ok, stat);
2672 ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB),
2673 "palette_size = %d\n", palette_size);
2675 memset(palette_buf, 0xfe, sizeof(palette_buf));
2676 palette = (ColorPalette*)palette_buf;
2677 stat = GdipGetImagePalette((GpImage*)bmp, palette,
2678 sizeof(ColorPalette)+sizeof(ARGB));
2679 palette_entries = palette->Entries;
2680 expect(Ok, stat);
2681 expect(PaletteFlagsHasAlpha, palette->Flags);
2682 expect(2, palette->Count);
2683 expect(0, palette_entries[0]);
2684 expect(0xff000000, palette_entries[1]);
2686 count = 12345;
2687 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2688 expect(Ok, stat);
2689 expect(1, count);
2691 GdipDisposeImage((GpImage*)bmp);
2693 /* Test frame dispose methods */
2694 hglob = GlobalAlloc (0, sizeof(gifanimation2));
2695 data = GlobalLock (hglob);
2696 memcpy(data, gifanimation2, sizeof(gifanimation2));
2697 GlobalUnlock(hglob);
2699 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2700 ok(hres == S_OK, "Failed to create a stream\n");
2702 stat = GdipCreateBitmapFromStream(stream, &bmp);
2703 ok(stat == Ok, "Failed to create a Bitmap\n");
2704 IStream_Release(stream);
2706 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2707 expect(Ok, stat);
2708 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2710 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2711 expect(Ok, stat);
2712 expect(5, count);
2714 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2715 expect(Ok, stat);
2716 expect(0, color);
2718 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2719 expect(Ok, stat);
2720 stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2721 expect(Ok, stat);
2722 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2723 if(color != 0) {
2724 win_skip("broken animated gif support\n");
2725 GdipDisposeImage((GpImage*)bmp);
2726 return;
2729 for(i=0; i<6; i++) {
2730 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2731 expect(Ok, stat);
2733 for(j=0; j<4; j++) {
2734 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2735 expect(Ok, stat);
2736 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2740 GdipDisposeImage((GpImage*)bmp);
2743 static void test_rotateflip(void)
2745 GpImage *bitmap;
2746 GpStatus stat;
2747 BYTE bits[24];
2748 static const BYTE orig_bits[24] = {
2749 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2750 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2751 UINT width, height;
2752 ARGB color;
2754 memcpy(bits, orig_bits, sizeof(bits));
2755 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2756 expect(Ok, stat);
2758 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2759 expect(Ok, stat);
2761 stat = GdipGetImageWidth(bitmap, &width);
2762 expect(Ok, stat);
2763 stat = GdipGetImageHeight(bitmap, &height);
2764 expect(Ok, stat);
2765 expect(2, width);
2766 expect(3, height);
2768 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2769 expect(Ok, stat);
2770 expect(0xff00ffff, color);
2772 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2773 expect(Ok, stat);
2774 expect(0xffff0000, color);
2776 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2777 expect(Ok, stat);
2778 expect(0xffffff00, color);
2780 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2781 expect(Ok, stat);
2782 expect(0xff0000ff, color);
2784 expect(0, bits[0]);
2785 expect(0, bits[1]);
2786 expect(0xff, bits[2]);
2788 GdipDisposeImage(bitmap);
2790 memcpy(bits, orig_bits, sizeof(bits));
2791 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2792 expect(Ok, stat);
2794 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2795 expect(Ok, stat);
2797 stat = GdipGetImageWidth(bitmap, &width);
2798 expect(Ok, stat);
2799 stat = GdipGetImageHeight(bitmap, &height);
2800 expect(Ok, stat);
2801 expect(3, width);
2802 expect(2, height);
2804 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2805 expect(Ok, stat);
2806 expect(0xff0000ff, color);
2808 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2809 expect(Ok, stat);
2810 expect(0xffff0000, color);
2812 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2813 expect(Ok, stat);
2814 expect(0xffffff00, color);
2816 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2817 expect(Ok, stat);
2818 expect(0xff00ffff, color);
2820 expect(0, bits[0]);
2821 expect(0, bits[1]);
2822 expect(0xff, bits[2]);
2824 GdipDisposeImage(bitmap);
2826 memcpy(bits, orig_bits, sizeof(bits));
2827 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2828 expect(Ok, stat);
2830 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2831 expect(Ok, stat);
2833 stat = GdipGetImageWidth(bitmap, &width);
2834 expect(Ok, stat);
2835 stat = GdipGetImageHeight(bitmap, &height);
2836 expect(Ok, stat);
2837 expect(3, width);
2838 expect(2, height);
2840 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2841 expect(Ok, stat);
2842 expect(0xff00ffff, color);
2844 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2845 expect(Ok, stat);
2846 expect(0xffffff00, color);
2848 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2849 expect(Ok, stat);
2850 expect(0xffff0000, color);
2852 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2853 expect(Ok, stat);
2854 expect(0xff0000ff, color);
2856 expect(0, bits[0]);
2857 expect(0, bits[1]);
2858 expect(0xff, bits[2]);
2860 GdipDisposeImage(bitmap);
2863 static void test_remaptable(void)
2865 GpStatus stat;
2866 GpImageAttributes *imageattr;
2867 GpBitmap *bitmap1, *bitmap2;
2868 GpGraphics *graphics;
2869 ARGB color;
2870 ColorMap *map;
2872 map = GdipAlloc(sizeof(ColorMap));
2874 map->oldColor.Argb = 0xff00ff00;
2875 map->newColor.Argb = 0xffff00ff;
2877 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2878 expect(InvalidParameter, stat);
2880 stat = GdipCreateImageAttributes(&imageattr);
2881 expect(Ok, stat);
2883 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2884 expect(InvalidParameter, stat);
2886 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2887 expect(InvalidParameter, stat);
2889 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2890 expect(InvalidParameter, stat);
2892 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2893 expect(InvalidParameter, stat);
2895 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2896 expect(Ok, stat);
2898 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2899 expect(Ok, stat);
2901 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2902 expect(Ok, stat);
2904 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2905 expect(Ok, stat);
2907 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2908 expect(Ok, stat);
2910 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2911 expect(Ok, stat);
2913 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2914 UnitPixel, imageattr, NULL, NULL);
2915 expect(Ok, stat);
2917 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2918 expect(Ok, stat);
2919 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2921 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2922 expect(Ok, stat);
2924 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2925 UnitPixel, imageattr, NULL, NULL);
2926 expect(Ok, stat);
2928 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2929 expect(Ok, stat);
2930 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
2932 GdipDeleteGraphics(graphics);
2933 GdipDisposeImage((GpImage*)bitmap1);
2934 GdipDisposeImage((GpImage*)bitmap2);
2935 GdipDisposeImageAttributes(imageattr);
2936 GdipFree(map);
2939 static void test_colorkey(void)
2941 GpStatus stat;
2942 GpImageAttributes *imageattr;
2943 GpBitmap *bitmap1, *bitmap2;
2944 GpGraphics *graphics;
2945 ARGB color;
2947 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2948 expect(InvalidParameter, stat);
2950 stat = GdipCreateImageAttributes(&imageattr);
2951 expect(Ok, stat);
2953 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2954 expect(InvalidParameter, stat);
2956 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2957 expect(InvalidParameter, stat);
2959 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2960 expect(Ok, stat);
2962 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2963 expect(Ok, stat);
2965 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2966 expect(Ok, stat);
2968 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2969 expect(Ok, stat);
2971 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2972 expect(Ok, stat);
2974 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
2975 expect(Ok, stat);
2977 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
2978 expect(Ok, stat);
2980 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2981 expect(Ok, stat);
2983 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2984 UnitPixel, imageattr, NULL, NULL);
2985 expect(Ok, stat);
2987 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2988 expect(Ok, stat);
2989 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2991 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2992 expect(Ok, stat);
2993 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2995 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2996 expect(Ok, stat);
2997 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2999 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3000 expect(Ok, stat);
3001 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3003 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3004 expect(Ok, stat);
3006 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3007 UnitPixel, imageattr, NULL, NULL);
3008 expect(Ok, stat);
3010 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3011 expect(Ok, stat);
3012 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
3014 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3015 expect(Ok, stat);
3016 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
3018 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3019 expect(Ok, stat);
3020 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
3022 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3023 expect(Ok, stat);
3024 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3027 GdipDeleteGraphics(graphics);
3028 GdipDisposeImage((GpImage*)bitmap1);
3029 GdipDisposeImage((GpImage*)bitmap2);
3030 GdipDisposeImageAttributes(imageattr);
3033 static void test_dispose(void)
3035 GpStatus stat;
3036 GpImage *image;
3037 char invalid_image[256];
3039 stat = GdipDisposeImage(NULL);
3040 expect(InvalidParameter, stat);
3042 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
3043 expect(Ok, stat);
3045 stat = GdipDisposeImage(image);
3046 expect(Ok, stat);
3048 stat = GdipDisposeImage(image);
3049 expect(ObjectBusy, stat);
3051 memset(invalid_image, 0, 256);
3052 stat = GdipDisposeImage((GpImage*)invalid_image);
3053 expect(ObjectBusy, stat);
3056 static LONG obj_refcount(void *obj)
3058 IUnknown_AddRef((IUnknown *)obj);
3059 return IUnknown_Release((IUnknown *)obj);
3062 static GpImage *load_image(const BYTE *image_data, UINT image_size)
3064 IStream *stream;
3065 HGLOBAL hmem;
3066 BYTE *data;
3067 HRESULT hr;
3068 GpStatus status;
3069 GpImage *image = NULL, *clone;
3070 ImageType image_type;
3071 LONG refcount, old_refcount;
3073 hmem = GlobalAlloc(0, image_size);
3074 data = GlobalLock(hmem);
3075 memcpy(data, image_data, image_size);
3076 GlobalUnlock(hmem);
3078 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3079 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3080 if (hr != S_OK) return NULL;
3082 refcount = obj_refcount(stream);
3083 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3085 status = GdipLoadImageFromStream(stream, &image);
3086 ok(status == Ok || broken(status == InvalidParameter), /* XP */
3087 "GdipLoadImageFromStream error %d\n", status);
3088 if (status != Ok)
3090 IStream_Release(stream);
3091 return NULL;
3094 status = GdipGetImageType(image, &image_type);
3095 ok(status == Ok, "GdipGetImageType error %d\n", status);
3097 refcount = obj_refcount(stream);
3098 if (image_type == ImageTypeBitmap)
3099 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3100 else
3101 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3102 old_refcount = refcount;
3104 status = GdipCloneImage(image, &clone);
3105 ok(status == Ok, "GdipCloneImage error %d\n", status);
3106 refcount = obj_refcount(stream);
3107 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3108 status = GdipDisposeImage(clone);
3109 ok(status == Ok, "GdipDisposeImage error %d\n", status);
3110 refcount = obj_refcount(stream);
3111 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3113 refcount = IStream_Release(stream);
3114 if (image_type == ImageTypeBitmap)
3115 ok(refcount >= 1, "expected stream refcount != 0\n");
3116 else
3117 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3119 return image;
3122 static void test_image_properties(void)
3124 static const struct test_data
3126 const BYTE *image_data;
3127 UINT image_size;
3128 ImageType image_type;
3129 UINT prop_count;
3130 UINT prop_count2; /* if win7 behaves differently */
3131 /* 1st property attributes */
3132 UINT prop_size;
3133 UINT prop_size2; /* if win7 behaves differently */
3134 UINT prop_id;
3135 UINT prop_id2; /* if win7 behaves differently */
3137 td[] =
3139 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3140 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3141 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3142 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3143 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3145 GpStatus status;
3146 GpImage *image;
3147 UINT prop_count, prop_size, i;
3148 PROPID prop_id[16] = { 0 };
3149 ImageType image_type;
3150 union
3152 PropertyItem data;
3153 char buf[256];
3154 } item;
3156 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3158 image = load_image(td[i].image_data, td[i].image_size);
3159 if (!image)
3161 trace("%u: failed to load image data\n", i);
3162 continue;
3165 status = GdipGetImageType(image, &image_type);
3166 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3167 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3168 i, td[i].image_type, image_type);
3170 status = GdipGetPropertyCount(image, &prop_count);
3171 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3172 if (td[i].image_data == pngimage || td[i].image_data == jpgimage)
3173 todo_wine
3174 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3175 " %u: expected property count %u or %u, got %u\n",
3176 i, td[i].prop_count, td[i].prop_count2, prop_count);
3177 else
3178 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3179 " %u: expected property count %u or %u, got %u\n",
3180 i, td[i].prop_count, td[i].prop_count2, prop_count);
3182 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3183 expect(InvalidParameter, status);
3184 status = GdipGetPropertyItemSize(image, 0, NULL);
3185 expect(InvalidParameter, status);
3186 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3187 if (image_type == ImageTypeMetafile)
3188 expect(NotImplemented, status);
3189 else
3190 expect(PropertyNotFound, status);
3192 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3193 expect(InvalidParameter, status);
3194 status = GdipGetPropertyItem(image, 0, 0, NULL);
3195 expect(InvalidParameter, status);
3196 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3197 if (image_type == ImageTypeMetafile)
3198 expect(NotImplemented, status);
3199 else
3200 expect(PropertyNotFound, status);
3202 /* FIXME: remove once Wine is fixed */
3203 if (td[i].prop_count != prop_count)
3205 GdipDisposeImage(image);
3206 continue;
3209 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3210 expect(InvalidParameter, status);
3211 status = GdipGetPropertyIdList(image, prop_count, NULL);
3212 expect(InvalidParameter, status);
3213 status = GdipGetPropertyIdList(image, 0, prop_id);
3214 if (image_type == ImageTypeMetafile)
3215 expect(NotImplemented, status);
3216 else if (prop_count == 0)
3217 expect(Ok, status);
3218 else
3219 expect(InvalidParameter, status);
3220 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3221 if (image_type == ImageTypeMetafile)
3222 expect(NotImplemented, status);
3223 else
3224 expect(InvalidParameter, status);
3225 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3226 if (image_type == ImageTypeMetafile)
3227 expect(NotImplemented, status);
3228 else
3229 expect(InvalidParameter, status);
3230 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3231 if (image_type == ImageTypeMetafile)
3232 expect(NotImplemented, status);
3233 else
3235 expect(Ok, status);
3236 if (prop_count != 0)
3237 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3238 " %u: expected property id %#x or %#x, got %#x\n",
3239 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3242 if (status == Ok)
3244 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3245 if (prop_count == 0)
3246 expect(PropertyNotFound, status);
3247 else
3249 expect(Ok, status);
3251 assert(sizeof(item) >= prop_size);
3252 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3253 i, prop_size);
3254 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3255 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3256 " %u: expected property size %u or %u, got %u\n",
3257 i, td[i].prop_size, td[i].prop_size2, prop_size);
3259 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3260 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3261 "%u: expected InvalidParameter, got %d\n", i, status);
3262 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3263 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3264 "%u: expected InvalidParameter, got %d\n", i, status);
3265 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3266 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3267 "%u: expected InvalidParameter, got %d\n", i, status);
3268 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3269 expect(Ok, status);
3270 ok(prop_id[0] == item.data.id,
3271 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3275 GdipDisposeImage(image);
3279 #define IFD_BYTE 1
3280 #define IFD_ASCII 2
3281 #define IFD_SHORT 3
3282 #define IFD_LONG 4
3283 #define IFD_RATIONAL 5
3284 #define IFD_SBYTE 6
3285 #define IFD_UNDEFINED 7
3286 #define IFD_SSHORT 8
3287 #define IFD_SLONG 9
3288 #define IFD_SRATIONAL 10
3289 #define IFD_FLOAT 11
3290 #define IFD_DOUBLE 12
3292 #ifndef PropertyTagTypeSByte
3293 #define PropertyTagTypeSByte 6
3294 #define PropertyTagTypeSShort 8
3295 #define PropertyTagTypeFloat 11
3296 #define PropertyTagTypeDouble 12
3297 #endif
3299 static UINT documented_type(UINT type)
3301 switch (type)
3303 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3304 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3305 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3306 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3307 default: return type;
3311 #include "pshpack2.h"
3312 struct IFD_entry
3314 SHORT id;
3315 SHORT type;
3316 ULONG count;
3317 LONG value;
3320 struct IFD_rational
3322 LONG numerator;
3323 LONG denominator;
3326 static const struct tiff_data
3328 USHORT byte_order;
3329 USHORT version;
3330 ULONG dir_offset;
3331 USHORT number_of_entries;
3332 struct IFD_entry entry[40];
3333 ULONG next_IFD;
3334 struct IFD_rational xres;
3335 DOUBLE double_val;
3336 struct IFD_rational srational_val;
3337 char string[14];
3338 SHORT short_val[4];
3339 LONG long_val[2];
3340 FLOAT float_val[2];
3341 struct IFD_rational rational[3];
3342 BYTE pixel_data[4];
3343 } TIFF_data =
3345 #ifdef WORDS_BIGENDIAN
3346 'M' | 'M' << 8,
3347 #else
3348 'I' | 'I' << 8,
3349 #endif
3351 FIELD_OFFSET(struct tiff_data, number_of_entries),
3354 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3355 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3356 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3357 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3358 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3359 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3360 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3361 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3362 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3363 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3364 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3365 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3366 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3367 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3368 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3369 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3370 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3371 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3372 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3373 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3374 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3375 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3376 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3377 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3378 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3379 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3380 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3381 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3382 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3383 /* Some gdiplus versions ignore these fields.
3384 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3385 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3386 { 0xf014, IFD_LONG, 0, 0x11223344 },
3387 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3388 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3389 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3390 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3393 { 900, 3 },
3394 1234567890.0987654321,
3395 { 0x1a2b3c4d, 0x5a6b7c8d },
3396 "Hello World!",
3397 { 0x0101, 0x0202, 0x0303, 0x0404 },
3398 { 0x11223344, 0x55667788 },
3399 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3400 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3401 { 0x11, 0x22, 0x33, 0 }
3403 #include "poppack.h"
3405 static void test_tiff_properties(void)
3407 static const struct test_data
3409 ULONG type, id, length;
3410 const BYTE value[24];
3411 } td[31] =
3413 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3414 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3415 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3416 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3417 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3418 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3419 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3420 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3421 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3422 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3423 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3424 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3425 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3426 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3427 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3428 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3429 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3430 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3431 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3432 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3433 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3434 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3435 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3436 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3437 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3438 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3439 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3440 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3441 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3442 { PropertyTagTypeSRational, 0xf016, 24,
3443 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3444 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3445 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3446 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3447 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3449 GpStatus status;
3450 GpImage *image;
3451 GUID guid;
3452 UINT dim_count, frame_count, prop_count, prop_size, i;
3453 PROPID *prop_id;
3454 PropertyItem *prop_item;
3456 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3457 if (!image)
3459 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3460 return;
3463 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3464 expect(Ok, status);
3465 expect(1, dim_count);
3467 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3468 expect(Ok, status);
3469 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3471 frame_count = 0xdeadbeef;
3472 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3473 expect(Ok, status);
3474 expect(1, frame_count);
3476 prop_count = 0xdeadbeef;
3477 status = GdipGetPropertyCount(image, &prop_count);
3478 expect(Ok, status);
3479 ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3480 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3481 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3483 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3485 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3486 expect(Ok, status);
3488 for (i = 0; i < prop_count; i++)
3490 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3491 expect(Ok, status);
3492 if (status != Ok) break;
3493 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3495 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3496 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3497 expect(Ok, status);
3498 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3499 ok(td[i].type == prop_item->type ||
3500 /* Win7 stopped using proper but not documented types, and it
3501 looks broken since TypeFloat and TypeDouble now reported as
3502 TypeUndefined, and signed types reported as unsigned. */
3503 broken(prop_item->type == documented_type(td[i].type)),
3504 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3505 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3506 prop_size -= sizeof(*prop_item);
3507 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3508 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3509 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3510 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3511 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3512 if (td[i].length == prop_item->length)
3514 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3515 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3516 if (!match)
3518 UINT j;
3519 BYTE *data = prop_item->value;
3520 trace("id %#x:", prop_item->id);
3521 for (j = 0; j < prop_item->length; j++)
3522 trace(" %02x", data[j]);
3523 trace("\n");
3526 HeapFree(GetProcessHeap(), 0, prop_item);
3529 HeapFree(GetProcessHeap(), 0, prop_id);
3531 GdipDisposeImage(image);
3534 static void test_GdipGetAllPropertyItems(void)
3536 static const struct test_data
3538 ULONG type, id, length;
3539 BYTE value[32];
3540 } td[16] =
3542 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3543 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3544 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3545 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3546 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3547 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3548 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3549 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3550 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3551 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3552 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3553 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3554 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3555 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3556 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3557 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3559 GpStatus status;
3560 GpImage *image;
3561 GUID guid;
3562 UINT dim_count, frame_count, prop_count, prop_size, i;
3563 UINT total_size, total_count;
3564 PROPID *prop_id;
3565 PropertyItem *prop_item;
3566 const char *item_data;
3568 image = load_image(tiffimage, sizeof(tiffimage));
3569 ok(image != 0, "Failed to load TIFF image data\n");
3570 if (!image) return;
3572 dim_count = 0xdeadbeef;
3573 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3574 expect(Ok, status);
3575 expect(1, dim_count);
3577 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3578 expect(Ok, status);
3579 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3581 frame_count = 0xdeadbeef;
3582 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3583 expect(Ok, status);
3584 expect(1, frame_count);
3586 prop_count = 0xdeadbeef;
3587 status = GdipGetPropertyCount(image, &prop_count);
3588 expect(Ok, status);
3589 ok(prop_count == sizeof(td)/sizeof(td[0]),
3590 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3592 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3594 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3595 expect(Ok, status);
3597 prop_size = 0;
3598 for (i = 0; i < prop_count; i++)
3600 UINT size;
3601 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3602 expect(Ok, status);
3603 if (status != Ok) break;
3604 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3606 prop_size += size;
3608 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3609 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3610 expect(Ok, status);
3611 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3612 ok(td[i].type == prop_item->type,
3613 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3614 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3615 size -= sizeof(*prop_item);
3616 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3617 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3618 if (td[i].length == prop_item->length)
3620 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3621 ok(match, "%u: data mismatch\n", i);
3622 if (!match)
3624 UINT j;
3625 BYTE *data = prop_item->value;
3626 trace("id %#x:", prop_item->id);
3627 for (j = 0; j < prop_item->length; j++)
3628 trace(" %02x", data[j]);
3629 trace("\n");
3632 HeapFree(GetProcessHeap(), 0, prop_item);
3635 HeapFree(GetProcessHeap(), 0, prop_id);
3637 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3638 expect(InvalidParameter, status);
3639 status = GdipGetPropertySize(image, &total_size, NULL);
3640 expect(InvalidParameter, status);
3641 status = GdipGetPropertySize(image, NULL, &total_count);
3642 expect(InvalidParameter, status);
3643 status = GdipGetPropertySize(image, NULL, NULL);
3644 expect(InvalidParameter, status);
3645 total_size = 0xdeadbeef;
3646 total_count = 0xdeadbeef;
3647 status = GdipGetPropertySize(image, &total_size, &total_count);
3648 expect(Ok, status);
3649 ok(prop_count == total_count,
3650 "expected total property count %u, got %u\n", prop_count, total_count);
3651 ok(prop_size == total_size,
3652 "expected total property size %u, got %u\n", prop_size, total_size);
3654 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3656 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3657 expect(InvalidParameter, status);
3658 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3659 expect(InvalidParameter, status);
3660 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3661 expect(InvalidParameter, status);
3662 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3663 expect(InvalidParameter, status);
3664 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3665 expect(InvalidParameter, status);
3666 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3667 expect(InvalidParameter, status);
3668 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3669 expect(Ok, status);
3671 item_data = (const char *)(prop_item + prop_count);
3672 for (i = 0; i < prop_count; i++)
3674 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3675 i, item_data, prop_item[i].value);
3676 ok(td[i].type == prop_item[i].type,
3677 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3678 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3679 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3680 if (td[i].length == prop_item[i].length)
3682 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3683 ok(match, "%u: data mismatch\n", i);
3684 if (!match)
3686 UINT j;
3687 BYTE *data = prop_item[i].value;
3688 trace("id %#x:", prop_item[i].id);
3689 for (j = 0; j < prop_item[i].length; j++)
3690 trace(" %02x", data[j]);
3691 trace("\n");
3694 item_data += prop_item[i].length;
3697 HeapFree(GetProcessHeap(), 0, prop_item);
3699 GdipDisposeImage(image);
3702 static void test_tiff_palette(void)
3704 GpStatus status;
3705 GpImage *image;
3706 PixelFormat format;
3707 INT size;
3708 struct
3710 ColorPalette pal;
3711 ARGB entry[256];
3712 } palette;
3713 ARGB *entries = palette.pal.Entries;
3715 /* 1bpp TIFF without palette */
3716 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3717 if (!image)
3719 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3720 return;
3723 status = GdipGetImagePixelFormat(image, &format);
3724 expect(Ok, status);
3725 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3727 status = GdipGetImagePaletteSize(image, &size);
3728 ok(status == Ok || broken(status == GenericError), /* XP */
3729 "GdipGetImagePaletteSize error %d\n", status);
3730 if (status == GenericError)
3732 GdipDisposeImage(image);
3733 return;
3735 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3737 status = GdipGetImagePalette(image, &palette.pal, size);
3738 expect(Ok, status);
3739 expect(0, palette.pal.Flags);
3740 expect(2, palette.pal.Count);
3741 if (palette.pal.Count == 2)
3743 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3744 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3747 GdipDisposeImage(image);
3750 static void test_bitmapbits(void)
3752 /* 8 x 2 bitmap */
3753 static const BYTE pixels_24[48] =
3755 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3756 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3757 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3758 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3760 static const BYTE pixels_00[48] =
3762 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3763 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3764 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3765 0,0,0, 0,0,0, 0,0,0, 0,0,0
3767 static const BYTE pixels_24_77[64] =
3769 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3770 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3771 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3772 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3773 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3774 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3776 static const BYTE pixels_77[64] =
3778 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3779 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3780 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3781 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3782 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3783 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3784 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3785 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3787 static const BYTE pixels_8[16] =
3789 0x01,0,0x01,0,0x01,0,0x01,0,
3790 0x01,0,0x01,0,0x01,0,0x01,0
3792 static const BYTE pixels_8_77[64] =
3794 0x01,0,0x01,0,0x01,0,0x01,0,
3795 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3796 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3797 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3798 0x01,0,0x01,0,0x01,0,0x01,0,
3799 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3800 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3801 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3803 static const BYTE pixels_1_77[64] =
3805 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3806 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3807 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3808 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3809 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3810 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3811 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3812 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3814 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3815 static const struct test_data
3817 PixelFormat format;
3818 UINT bpp;
3819 ImageLockMode mode;
3820 UINT stride, size;
3821 const BYTE *pixels;
3822 const BYTE *pixels_unlocked;
3823 } td[] =
3825 /* 0 */
3826 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3828 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3829 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3830 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3831 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3832 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3833 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3834 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3835 /* 8 */
3836 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3837 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3838 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3839 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3840 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3841 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3842 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3843 /* 15 */
3844 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3845 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3846 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3847 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3848 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3849 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3850 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3852 BYTE buf[64];
3853 GpStatus status;
3854 GpBitmap *bitmap;
3855 UINT i;
3856 BitmapData data;
3857 struct
3859 ColorPalette pal;
3860 ARGB entries[1];
3861 } palette;
3862 ARGB *entries = palette.pal.Entries;
3864 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3866 BYTE pixels[sizeof(pixels_24)];
3867 memcpy(pixels, pixels_24, sizeof(pixels_24));
3868 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3869 expect(Ok, status);
3871 /* associate known palette with pixel data */
3872 palette.pal.Flags = PaletteFlagsGrayScale;
3873 palette.pal.Count = 2;
3874 entries[0] = 0xff000000;
3875 entries[1] = 0xffffffff;
3876 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3877 expect(Ok, status);
3879 memset(&data, 0xfe, sizeof(data));
3880 if (td[i].mode & ImageLockModeUserInputBuf)
3882 memset(buf, 0x77, sizeof(buf));
3883 data.Scan0 = buf;
3884 data.Stride = 32;
3886 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3887 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3888 if (status != Ok)
3890 GdipDisposeImage((GpImage *)bitmap);
3891 continue;
3893 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3894 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3895 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3896 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3897 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3898 if (td[i].mode & ImageLockModeUserInputBuf)
3899 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3900 if (td[i].size == data.Height * data.Stride)
3902 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3904 match = 1;
3905 for (j = 0; j < data.Height; j++)
3907 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3909 match = 0;
3910 break;
3913 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3915 ok(match,
3916 "%u: data should match\n", i);
3917 if (!match)
3919 BYTE *bits = data.Scan0;
3920 trace("%u: data mismatch for format %#x:", i, td[i].format);
3921 for (j = 0; j < td[i].size; j++)
3922 trace(" %02x", bits[j]);
3923 trace("\n");
3926 else
3927 ok(!match, "%u: data shouldn't match\n", i);
3929 memset(data.Scan0, 0, td[i].size);
3932 status = GdipBitmapUnlockBits(bitmap, &data);
3933 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3935 memset(&data, 0xfe, sizeof(data));
3936 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3937 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3938 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3939 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3940 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3941 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3942 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3943 if (data.Height * data.Stride == 48)
3945 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3946 ok(match, "%u: data should match\n", i);
3947 if (!match)
3949 UINT j;
3950 BYTE *bits = data.Scan0;
3951 trace("%u: data mismatch for format %#x:", i, td[i].format);
3952 for (j = 0; j < 48; j++)
3953 trace(" %02x", bits[j]);
3954 trace("\n");
3958 status = GdipBitmapUnlockBits(bitmap, &data);
3959 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3961 status = GdipDisposeImage((GpImage *)bitmap);
3962 expect(Ok, status);
3966 static void test_DrawImage(void)
3968 BYTE black_1x1[4] = { 0,0,0,0 };
3969 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3970 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3971 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3972 0,0,0,0,0,0,0xff,0xff };
3973 GpStatus status;
3974 union
3976 GpBitmap *bitmap;
3977 GpImage *image;
3978 } u1, u2;
3979 GpGraphics *graphics;
3980 int match;
3982 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3983 expect(Ok, status);
3984 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3985 expect(Ok, status);
3987 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3988 expect(Ok, status);
3989 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3990 expect(Ok, status);
3991 status = GdipGetImageGraphicsContext(u2.image, &graphics);
3992 expect(Ok, status);
3993 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3994 expect(Ok, status);
3996 status = GdipDrawImageI(graphics, u1.image, 0, 0);
3997 expect(Ok, status);
3999 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4000 ok(match, "data should match\n");
4001 if (!match)
4003 UINT i, size = sizeof(white_2x2);
4004 BYTE *bits = white_2x2;
4005 for (i = 0; i < size; i++)
4006 trace(" %02x", bits[i]);
4007 trace("\n");
4010 status = GdipDeleteGraphics(graphics);
4011 expect(Ok, status);
4012 status = GdipDisposeImage(u1.image);
4013 expect(Ok, status);
4014 status = GdipDisposeImage(u2.image);
4015 expect(Ok, status);
4018 static void test_DrawImage_SourceCopy(void)
4020 DWORD dst_pixels[4] = { 0xffffffff, 0xffffffff,
4021 0xffffffff, 0xffffffff };
4022 DWORD src_pixels[4] = { 0, 0xffff0000,
4023 0, 0xff00ff };
4025 GpStatus status;
4026 union
4028 GpBitmap *bitmap;
4029 GpImage *image;
4030 } u1, u2;
4031 GpGraphics *graphics;
4033 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)dst_pixels, &u1.bitmap);
4034 expect(Ok, status);
4036 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)src_pixels, &u2.bitmap);
4037 expect(Ok, status);
4038 status = GdipGetImageGraphicsContext(u1.image, &graphics);
4039 expect(Ok, status);
4040 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4041 expect(Ok, status);
4043 status = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
4044 expect(Ok, status);
4046 status = GdipDrawImageI(graphics, u2.image, 0, 0);
4047 expect(Ok, status);
4049 todo_wine expect(0, dst_pixels[0]);
4050 expect(0xffff0000, dst_pixels[1]);
4051 todo_wine expect(0, dst_pixels[2]);
4052 todo_wine expect(0, dst_pixels[3]);
4054 status = GdipDeleteGraphics(graphics);
4055 expect(Ok, status);
4056 status = GdipDisposeImage(u1.image);
4057 expect(Ok, status);
4058 status = GdipDisposeImage(u2.image);
4059 expect(Ok, status);
4062 static void test_GdipDrawImagePointRect(void)
4064 BYTE black_1x1[4] = { 0,0,0,0 };
4065 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4066 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4067 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4068 0,0,0,0,0,0,0xff,0xff };
4069 GpStatus status;
4070 union
4072 GpBitmap *bitmap;
4073 GpImage *image;
4074 } u1, u2;
4075 GpGraphics *graphics;
4076 int match;
4078 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4079 expect(Ok, status);
4080 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4081 expect(Ok, status);
4083 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4084 expect(Ok, status);
4085 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4086 expect(Ok, status);
4087 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4088 expect(Ok, status);
4089 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4090 expect(Ok, status);
4092 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
4093 expect(Ok, status);
4095 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4096 ok(match, "data should match\n");
4097 if (!match)
4099 UINT i, size = sizeof(white_2x2);
4100 BYTE *bits = white_2x2;
4101 for (i = 0; i < size; i++)
4102 trace(" %02x", bits[i]);
4103 trace("\n");
4106 status = GdipDeleteGraphics(graphics);
4107 expect(Ok, status);
4108 status = GdipDisposeImage(u1.image);
4109 expect(Ok, status);
4110 status = GdipDisposeImage(u2.image);
4111 expect(Ok, status);
4114 static void test_image_format(void)
4116 static const PixelFormat fmt[] =
4118 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4119 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4120 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4121 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4122 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4124 GpStatus status;
4125 GpBitmap *bitmap;
4126 GpImage *thumb;
4127 HBITMAP hbitmap;
4128 BITMAP bm;
4129 PixelFormat format;
4130 BitmapData data;
4131 UINT i, ret;
4133 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
4135 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4136 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4137 "GdipCreateBitmapFromScan0 error %d\n", status);
4138 if (status != Ok) continue;
4140 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4141 expect(Ok, status);
4142 expect(fmt[i], format);
4144 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4145 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4146 todo_wine expect(InvalidParameter, status);
4147 else
4149 expect(Ok, status);
4150 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4151 expect(sizeof(bm), ret);
4152 expect(0, bm.bmType);
4153 expect(1, bm.bmWidth);
4154 expect(1, bm.bmHeight);
4155 expect(4, bm.bmWidthBytes);
4156 expect(1, bm.bmPlanes);
4157 expect(32, bm.bmBitsPixel);
4158 DeleteObject(hbitmap);
4161 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4162 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4163 todo_wine
4164 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4165 "expected OutOfMemory, got %d\n", status);
4166 else
4167 expect(Ok, status);
4168 if (status == Ok)
4170 status = GdipGetImagePixelFormat(thumb, &format);
4171 expect(Ok, status);
4172 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4173 "expected PixelFormat32bppPARGB, got %#x\n", format);
4174 status = GdipDisposeImage(thumb);
4175 expect(Ok, status);
4178 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4179 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4180 todo_wine expect(InvalidParameter, status);
4181 else
4183 expect(Ok, status);
4184 status = GdipBitmapUnlockBits(bitmap, &data);
4185 expect(Ok, status);
4188 status = GdipDisposeImage((GpImage *)bitmap);
4189 expect(Ok, status);
4193 static void test_DrawImage_scale(void)
4195 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4196 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4197 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4198 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4199 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4200 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4201 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4202 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4203 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4204 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4205 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4206 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4207 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4208 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4209 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4210 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4211 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4212 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4213 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4214 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4215 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4216 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4217 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4218 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4219 static const struct test_data
4221 REAL scale_x;
4222 PixelOffsetMode pixel_offset_mode;
4223 const BYTE *image;
4224 BOOL todo;
4225 } td[] =
4227 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4228 { 1.0, PixelOffsetModeNone, image_100 },
4229 { 1.2, PixelOffsetModeNone, image_120 },
4230 { 1.5, PixelOffsetModeNone, image_150 },
4231 { 1.8, PixelOffsetModeNone, image_180 },
4232 { 2.0, PixelOffsetModeNone, image_200 },
4233 { 2.5, PixelOffsetModeNone, image_250 },
4235 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4236 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4237 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4238 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4239 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4240 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4241 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4243 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4244 { 1.0, PixelOffsetModeHalf, image_100 },
4245 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4246 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4247 { 1.8, PixelOffsetModeHalf, image_180 },
4248 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4249 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4251 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4252 { 1.0, PixelOffsetModeHighQuality, image_100 },
4253 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4254 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4255 { 1.8, PixelOffsetModeHighQuality, image_180 },
4256 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4257 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4259 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4260 BYTE dst_8x1[24];
4261 GpStatus status;
4262 union
4264 GpBitmap *bitmap;
4265 GpImage *image;
4266 } u1, u2;
4267 GpGraphics *graphics;
4268 GpMatrix *matrix;
4269 int i, match;
4271 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4272 expect(Ok, status);
4273 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4274 expect(Ok, status);
4276 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4277 expect(Ok, status);
4278 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4279 expect(Ok, status);
4280 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4281 expect(Ok, status);
4282 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4283 expect(Ok, status);
4285 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4287 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4288 expect(Ok, status);
4290 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4291 expect(Ok, status);
4292 status = GdipSetWorldTransform(graphics, matrix);
4293 expect(Ok, status);
4294 GdipDeleteMatrix(matrix);
4296 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4297 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4298 expect(Ok, status);
4300 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4301 if (!match && td[i].todo)
4302 todo_wine ok(match, "%d: data should match\n", i);
4303 else
4304 ok(match, "%d: data should match\n", i);
4305 if (!match)
4307 UINT i, size = sizeof(dst_8x1);
4308 const BYTE *bits = dst_8x1;
4309 for (i = 0; i < size; i++)
4310 trace(" %02x", bits[i]);
4311 trace("\n");
4315 status = GdipDeleteGraphics(graphics);
4316 expect(Ok, status);
4317 status = GdipDisposeImage(u1.image);
4318 expect(Ok, status);
4319 status = GdipDisposeImage(u2.image);
4320 expect(Ok, status);
4323 static const BYTE animatedgif[] = {
4324 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4325 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4326 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4327 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4328 0x03,0x01,0x05,0x00,0x00,
4329 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4330 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4331 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4332 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4333 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4334 0x02,0x02,0x4C,0x01,0x00,
4335 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4336 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4337 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4338 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4339 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4340 0x02,0x02,0x44,0x01,0x00,
4341 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4342 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4345 static void test_gif_properties(void)
4347 static const struct test_data
4349 ULONG type, id, length;
4350 const BYTE value[13];
4351 } td[] =
4353 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4354 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4355 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4356 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4357 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4358 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4360 GpStatus status;
4361 GpImage *image;
4362 GUID guid;
4363 UINT dim_count, frame_count, prop_count, prop_size, i;
4364 UINT total_size, total_count;
4365 PROPID *prop_id;
4366 PropertyItem *prop_item;
4367 const char *item_data;
4369 image = load_image(animatedgif, sizeof(animatedgif));
4370 if (!image) /* XP fails to load this GIF image */
4372 trace("Failed to load GIF image data\n");
4373 return;
4376 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4377 expect(Ok, status);
4378 expect(1, dim_count);
4380 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4381 expect(Ok, status);
4382 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4384 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4385 expect(Ok, status);
4386 expect(2, frame_count);
4388 status = GdipImageSelectActiveFrame(image, &guid, 1);
4389 expect(Ok, status);
4391 status = GdipGetPropertyCount(image, &prop_count);
4392 expect(Ok, status);
4393 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
4394 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
4396 if (prop_count != sizeof(td)/sizeof(td[0]))
4398 GdipDisposeImage(image);
4399 return;
4402 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4404 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4405 expect(Ok, status);
4407 prop_size = 0;
4408 for (i = 0; i < prop_count; i++)
4410 UINT size;
4411 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4412 expect(Ok, status);
4413 if (status != Ok) break;
4414 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4416 prop_size += size;
4418 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4419 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4420 expect(Ok, status);
4421 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4422 ok(td[i].type == prop_item->type,
4423 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4424 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4425 size -= sizeof(*prop_item);
4426 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4427 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4428 if (td[i].length == prop_item->length)
4430 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4431 ok(match, "%u: data mismatch\n", i);
4432 if (!match)
4434 UINT j;
4435 BYTE *data = prop_item->value;
4436 trace("id %#x:", prop_item->id);
4437 for (j = 0; j < prop_item->length; j++)
4438 trace(" %02x", data[j]);
4439 trace("\n");
4442 HeapFree(GetProcessHeap(), 0, prop_item);
4445 HeapFree(GetProcessHeap(), 0, prop_id);
4447 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4448 expect(InvalidParameter, status);
4449 status = GdipGetPropertySize(image, &total_size, NULL);
4450 expect(InvalidParameter, status);
4451 status = GdipGetPropertySize(image, NULL, &total_count);
4452 expect(InvalidParameter, status);
4453 status = GdipGetPropertySize(image, NULL, NULL);
4454 expect(InvalidParameter, status);
4455 total_size = 0xdeadbeef;
4456 total_count = 0xdeadbeef;
4457 status = GdipGetPropertySize(image, &total_size, &total_count);
4458 expect(Ok, status);
4459 ok(prop_count == total_count,
4460 "expected total property count %u, got %u\n", prop_count, total_count);
4461 ok(prop_size == total_size,
4462 "expected total property size %u, got %u\n", prop_size, total_size);
4464 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4466 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4467 expect(InvalidParameter, status);
4468 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4469 expect(InvalidParameter, status);
4470 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4471 expect(InvalidParameter, status);
4472 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4473 expect(InvalidParameter, status);
4474 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4475 expect(InvalidParameter, status);
4476 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4477 expect(InvalidParameter, status);
4478 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4479 expect(Ok, status);
4481 item_data = (const char *)(prop_item + prop_count);
4482 for (i = 0; i < prop_count; i++)
4484 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4485 i, item_data, prop_item[i].value);
4486 ok(td[i].type == prop_item[i].type,
4487 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4488 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4489 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4490 if (td[i].length == prop_item[i].length)
4492 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4493 ok(match, "%u: data mismatch\n", i);
4494 if (!match)
4496 UINT j;
4497 BYTE *data = prop_item[i].value;
4498 trace("id %#x:", prop_item[i].id);
4499 for (j = 0; j < prop_item[i].length; j++)
4500 trace(" %02x", data[j]);
4501 trace("\n");
4504 item_data += prop_item[i].length;
4507 HeapFree(GetProcessHeap(), 0, prop_item);
4509 GdipDisposeImage(image);
4512 static void test_ARGB_conversion(void)
4514 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4515 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4516 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4517 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4518 BYTE *bits;
4519 GpBitmap *bitmap;
4520 BitmapData data;
4521 GpStatus status;
4522 int match;
4524 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4525 expect(Ok, status);
4527 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4528 expect(Ok, status);
4529 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4530 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4531 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4532 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4533 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4534 ok(match, "bits don't match\n");
4535 if (!match)
4537 bits = data.Scan0;
4538 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4539 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4541 status = GdipBitmapUnlockBits(bitmap, &data);
4542 expect(Ok, status);
4544 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4545 expect(Ok, status);
4546 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4547 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4548 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4549 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4550 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4551 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4552 ok(match, "bits don't match\n");
4553 if (!match)
4555 bits = data.Scan0;
4556 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4557 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4559 status = GdipBitmapUnlockBits(bitmap, &data);
4560 expect(Ok, status);
4562 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4563 expect(Ok, status);
4564 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4565 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4566 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4567 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4568 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4569 ok(match, "bits don't match\n");
4570 if (!match)
4572 bits = data.Scan0;
4573 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4574 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4576 status = GdipBitmapUnlockBits(bitmap, &data);
4577 expect(Ok, status);
4579 GdipDisposeImage((GpImage *)bitmap);
4583 static void test_CloneBitmapArea(void)
4585 GpStatus status;
4586 GpBitmap *bitmap, *copy;
4587 BitmapData data, data2;
4589 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4590 expect(Ok, status);
4592 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4593 expect(Ok, status);
4595 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4596 expect(WrongState, status);
4598 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4599 expect(Ok, status);
4601 status = GdipBitmapUnlockBits(bitmap, &data);
4602 expect(Ok, status);
4604 GdipDisposeImage((GpImage *)copy);
4605 GdipDisposeImage((GpImage *)bitmap);
4608 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid)
4610 GpStatus status;
4611 UINT n_codecs, info_size, i;
4612 ImageCodecInfo *info;
4613 BOOL ret = FALSE;
4615 status = GdipGetImageEncodersSize(&n_codecs, &info_size);
4616 expect(Ok, status);
4618 info = GdipAlloc(info_size);
4620 status = GdipGetImageEncoders(n_codecs, info_size, info);
4621 expect(Ok, status);
4623 for (i = 0; i < n_codecs; i++)
4625 if (!lstrcmpW(info[i].MimeType, mime))
4627 *format = info[i].FormatID;
4628 *clsid = info[i].Clsid;
4629 ret = TRUE;
4630 break;
4634 GdipFree(info);
4635 return ret;
4638 static void test_supported_encoders(void)
4640 static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 };
4641 static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 };
4642 static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 };
4643 static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 };
4644 static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 };
4645 static const struct test_data
4647 LPCWSTR mime;
4648 const GUID *format;
4649 BOOL todo;
4650 } td[] =
4652 { bmp_mimetype, &ImageFormatBMP, FALSE },
4653 { jpeg_mimetype, &ImageFormatJPEG, FALSE },
4654 { gif_mimetype, &ImageFormatGIF, TRUE },
4655 { tiff_mimetype, &ImageFormatTIFF, FALSE },
4656 { png_mimetype, &ImageFormatPNG, FALSE }
4658 GUID format, clsid;
4659 BOOL ret;
4660 HRESULT hr;
4661 GpStatus status;
4662 GpBitmap *bm;
4663 IStream *stream;
4664 HGLOBAL hmem;
4665 int i;
4667 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
4668 ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
4670 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4672 ret = get_encoder_clsid(td[i].mime, &format, &clsid);
4673 ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
4674 expect_guid(td[i].format, &format, __LINE__, FALSE);
4676 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
4678 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
4679 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
4681 status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
4682 if (td[i].todo)
4683 todo_wine ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4684 else
4685 ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4687 IStream_Release(stream);
4690 GdipDisposeImage((GpImage *)bm);
4693 static void test_createeffect(void)
4695 static const GUID noneffect = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } };
4696 GpStatus (WINAPI *pGdipCreateEffect)( const GUID guid, CGpEffect **effect);
4697 GpStatus (WINAPI *pGdipDeleteEffect)( CGpEffect *effect);
4698 GpStatus stat;
4699 CGpEffect *effect;
4700 HMODULE mod = GetModuleHandleA("gdiplus.dll");
4701 int i;
4702 const GUID * const effectlist[] =
4703 {&BlurEffectGuid, &SharpenEffectGuid, &ColorMatrixEffectGuid, &ColorLUTEffectGuid,
4704 &BrightnessContrastEffectGuid, &HueSaturationLightnessEffectGuid, &LevelsEffectGuid,
4705 &TintEffectGuid, &ColorBalanceEffectGuid, &RedEyeCorrectionEffectGuid, &ColorCurveEffectGuid};
4707 pGdipCreateEffect = (void*)GetProcAddress( mod, "GdipCreateEffect");
4708 pGdipDeleteEffect = (void*)GetProcAddress( mod, "GdipDeleteEffect");
4709 if(!pGdipCreateEffect || !pGdipDeleteEffect)
4711 /* GdipCreateEffect/GdipDeleteEffect was introduced in Windows Vista. */
4712 win_skip("GDIPlus version 1.1 not available\n");
4713 return;
4716 stat = pGdipCreateEffect(BlurEffectGuid, NULL);
4717 expect(InvalidParameter, stat);
4719 stat = pGdipCreateEffect(noneffect, &effect);
4720 todo_wine expect(Win32Error, stat);
4722 for(i=0; i < sizeof(effectlist) / sizeof(effectlist[0]); i++)
4724 stat = pGdipCreateEffect(*effectlist[i], &effect);
4725 todo_wine expect(Ok, stat);
4726 if(stat == Ok)
4728 stat = pGdipDeleteEffect(effect);
4729 expect(Ok, stat);
4734 START_TEST(image)
4736 struct GdiplusStartupInput gdiplusStartupInput;
4737 ULONG_PTR gdiplusToken;
4739 gdiplusStartupInput.GdiplusVersion = 1;
4740 gdiplusStartupInput.DebugEventCallback = NULL;
4741 gdiplusStartupInput.SuppressBackgroundThread = 0;
4742 gdiplusStartupInput.SuppressExternalCodecs = 0;
4744 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
4746 test_supported_encoders();
4747 test_CloneBitmapArea();
4748 test_ARGB_conversion();
4749 test_DrawImage_scale();
4750 test_image_format();
4751 test_DrawImage();
4752 test_DrawImage_SourceCopy();
4753 test_GdipDrawImagePointRect();
4754 test_bitmapbits();
4755 test_tiff_palette();
4756 test_GdipGetAllPropertyItems();
4757 test_tiff_properties();
4758 test_gif_properties();
4759 test_image_properties();
4760 test_Scan0();
4761 test_FromGdiDib();
4762 test_GetImageDimension();
4763 test_GdipImageGetFrameDimensionsCount();
4764 test_LoadingImages();
4765 test_SavingImages();
4766 test_encoders();
4767 test_LockBits();
4768 test_LockBits_UserBuf();
4769 test_GdipCreateBitmapFromHBITMAP();
4770 test_GdipGetImageFlags();
4771 test_GdipCloneImage();
4772 test_testcontrol();
4773 test_fromhicon();
4774 test_getrawformat();
4775 test_loadwmf();
4776 test_createfromwmf();
4777 test_createfromwmf_noplaceable();
4778 test_resolution();
4779 test_createhbitmap();
4780 test_getthumbnail();
4781 test_getsetpixel();
4782 test_palette();
4783 test_colormatrix();
4784 test_gamma();
4785 test_multiframegif();
4786 test_rotateflip();
4787 test_remaptable();
4788 test_colorkey();
4789 test_dispose();
4790 test_createeffect();
4792 GdiplusShutdown(gdiplusToken);