gdiplus: Move the burden of supporting GIF encoding to the WIC backend.
[wine.git] / dlls / gdiplus / tests / image.c
blob1335d972af434a5a9f24a404c121388f7fafc836
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_resolution(void)
1549 GpStatus stat;
1550 GpBitmap *bitmap;
1551 GpGraphics *graphics;
1552 REAL res=-1.0;
1553 HDC screendc;
1554 int screenxres, screenyres;
1556 /* create Bitmap */
1557 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1558 expect(Ok, stat);
1560 /* test invalid values */
1561 stat = GdipGetImageHorizontalResolution(NULL, &res);
1562 expect(InvalidParameter, stat);
1564 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1565 expect(InvalidParameter, stat);
1567 stat = GdipGetImageVerticalResolution(NULL, &res);
1568 expect(InvalidParameter, stat);
1570 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1571 expect(InvalidParameter, stat);
1573 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1574 expect(InvalidParameter, stat);
1576 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1577 expect(InvalidParameter, stat);
1579 /* defaults to screen resolution */
1580 screendc = GetDC(0);
1582 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1583 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1585 ReleaseDC(0, screendc);
1587 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1588 expect(Ok, stat);
1589 expectf((REAL)screenxres, res);
1591 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1592 expect(Ok, stat);
1593 expectf((REAL)screenyres, res);
1595 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1596 expect(Ok, stat);
1597 stat = GdipGetDpiX(graphics, &res);
1598 expect(Ok, stat);
1599 expectf((REAL)screenxres, res);
1600 stat = GdipGetDpiY(graphics, &res);
1601 expect(Ok, stat);
1602 expectf((REAL)screenyres, res);
1604 /* test changing the resolution */
1605 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1606 expect(Ok, stat);
1608 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1609 expect(Ok, stat);
1610 expectf(screenxres*2.0, res);
1612 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1613 expect(Ok, stat);
1614 expectf(screenyres*3.0, res);
1616 stat = GdipGetDpiX(graphics, &res);
1617 expect(Ok, stat);
1618 expectf((REAL)screenxres, res);
1619 stat = GdipGetDpiY(graphics, &res);
1620 expect(Ok, stat);
1621 expectf((REAL)screenyres, res);
1623 stat = GdipDeleteGraphics(graphics);
1624 expect(Ok, stat);
1626 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1627 expect(Ok, stat);
1628 stat = GdipGetDpiX(graphics, &res);
1629 expect(Ok, stat);
1630 expectf(screenxres*2.0, res);
1631 stat = GdipGetDpiY(graphics, &res);
1632 expect(Ok, stat);
1633 expectf(screenyres*3.0, res);
1634 stat = GdipDeleteGraphics(graphics);
1635 expect(Ok, stat);
1637 stat = GdipDisposeImage((GpImage*)bitmap);
1638 expect(Ok, stat);
1641 static void test_createhbitmap(void)
1643 GpStatus stat;
1644 GpBitmap *bitmap;
1645 HBITMAP hbitmap, oldhbitmap;
1646 BITMAP bm;
1647 int ret;
1648 HDC hdc;
1649 COLORREF pixel;
1650 BYTE bits[640];
1652 memset(bits, 0x68, 640);
1654 /* create Bitmap */
1655 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1656 expect(Ok, stat);
1658 /* test NULL values */
1659 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1660 expect(InvalidParameter, stat);
1662 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1663 expect(InvalidParameter, stat);
1665 /* create HBITMAP */
1666 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1667 expect(Ok, stat);
1669 if (stat == Ok)
1671 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1672 expect(sizeof(BITMAP), ret);
1674 expect(0, bm.bmType);
1675 expect(10, bm.bmWidth);
1676 expect(20, bm.bmHeight);
1677 expect(40, bm.bmWidthBytes);
1678 expect(1, bm.bmPlanes);
1679 expect(32, bm.bmBitsPixel);
1680 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1682 if (bm.bmBits)
1684 DWORD val = *(DWORD*)bm.bmBits;
1685 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1688 hdc = CreateCompatibleDC(NULL);
1690 oldhbitmap = SelectObject(hdc, hbitmap);
1691 pixel = GetPixel(hdc, 5, 5);
1692 SelectObject(hdc, oldhbitmap);
1694 DeleteDC(hdc);
1696 expect(0x686868, pixel);
1698 DeleteObject(hbitmap);
1701 stat = GdipDisposeImage((GpImage*)bitmap);
1702 expect(Ok, stat);
1704 /* make (1,0) have no alpha and (2,0) a different blue value. */
1705 bits[7] = 0x00;
1706 bits[8] = 0x40;
1708 /* create alpha Bitmap */
1709 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1710 expect(Ok, stat);
1712 /* create HBITMAP */
1713 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1714 expect(Ok, stat);
1716 if (stat == Ok)
1718 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1719 expect(sizeof(BITMAP), ret);
1721 expect(0, bm.bmType);
1722 expect(8, bm.bmWidth);
1723 expect(20, bm.bmHeight);
1724 expect(32, bm.bmWidthBytes);
1725 expect(1, bm.bmPlanes);
1726 expect(32, bm.bmBitsPixel);
1727 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1729 if (bm.bmBits)
1731 DWORD val = *(DWORD*)bm.bmBits;
1732 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1733 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1734 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1737 hdc = CreateCompatibleDC(NULL);
1739 oldhbitmap = SelectObject(hdc, hbitmap);
1740 pixel = GetPixel(hdc, 5, 5);
1741 expect(0x2a2a2a, pixel);
1742 pixel = GetPixel(hdc, 1, 0);
1743 expect(0x0, pixel);
1745 SelectObject(hdc, oldhbitmap);
1747 DeleteDC(hdc);
1750 DeleteObject(hbitmap);
1753 /* create HBITMAP with bkgnd colour */
1754 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1755 expect(Ok, stat);
1757 if (stat == Ok)
1759 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1760 expect(sizeof(BITMAP), ret);
1762 expect(0, bm.bmType);
1763 expect(8, bm.bmWidth);
1764 expect(20, bm.bmHeight);
1765 expect(32, bm.bmWidthBytes);
1766 expect(1, bm.bmPlanes);
1767 expect(32, bm.bmBitsPixel);
1768 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1770 if (bm.bmBits)
1772 DWORD val = *(DWORD*)bm.bmBits;
1773 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1774 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1775 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1778 hdc = CreateCompatibleDC(NULL);
1780 oldhbitmap = SelectObject(hdc, hbitmap);
1781 pixel = GetPixel(hdc, 5, 5);
1782 expect(0xc12ac1, pixel);
1783 pixel = GetPixel(hdc, 1, 0);
1784 expect(0xff00ff, pixel);
1785 pixel = GetPixel(hdc, 2, 0);
1786 expect(0xb12ac1, pixel);
1788 SelectObject(hdc, oldhbitmap);
1789 DeleteDC(hdc);
1790 DeleteObject(hbitmap);
1793 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1794 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1795 expect(Ok, stat);
1797 if (stat == Ok)
1799 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1800 expect(sizeof(BITMAP), ret);
1802 expect(0, bm.bmType);
1803 expect(8, bm.bmWidth);
1804 expect(20, bm.bmHeight);
1805 expect(32, bm.bmWidthBytes);
1806 expect(1, bm.bmPlanes);
1807 expect(32, bm.bmBitsPixel);
1808 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1810 if (bm.bmBits)
1812 DWORD val = *(DWORD*)bm.bmBits;
1813 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1814 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1815 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1818 hdc = CreateCompatibleDC(NULL);
1820 oldhbitmap = SelectObject(hdc, hbitmap);
1821 pixel = GetPixel(hdc, 5, 5);
1822 expect(0xc12ac1, pixel);
1823 pixel = GetPixel(hdc, 1, 0);
1824 expect(0xff00ff, pixel);
1825 pixel = GetPixel(hdc, 2, 0);
1826 expect(0xb12ac1, pixel);
1828 SelectObject(hdc, oldhbitmap);
1829 DeleteDC(hdc);
1830 DeleteObject(hbitmap);
1833 stat = GdipDisposeImage((GpImage*)bitmap);
1834 expect(Ok, stat);
1837 static void test_getthumbnail(void)
1839 GpStatus stat;
1840 GpImage *bitmap1, *bitmap2;
1841 UINT width, height;
1843 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1844 expect(InvalidParameter, stat);
1846 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1847 expect(Ok, stat);
1849 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1850 expect(InvalidParameter, stat);
1852 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1853 expect(Ok, stat);
1855 if (stat == Ok)
1857 stat = GdipGetImageWidth(bitmap2, &width);
1858 expect(Ok, stat);
1859 expect(120, width);
1861 stat = GdipGetImageHeight(bitmap2, &height);
1862 expect(Ok, stat);
1863 expect(120, height);
1865 GdipDisposeImage(bitmap2);
1868 GdipDisposeImage(bitmap1);
1871 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1872 expect(Ok, stat);
1874 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1875 expect(Ok, stat);
1877 if (stat == Ok)
1879 stat = GdipGetImageWidth(bitmap2, &width);
1880 expect(Ok, stat);
1881 expect(32, width);
1883 stat = GdipGetImageHeight(bitmap2, &height);
1884 expect(Ok, stat);
1885 expect(32, height);
1887 GdipDisposeImage(bitmap2);
1890 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1891 expect(Ok, stat);
1893 if (stat == Ok)
1895 stat = GdipGetImageWidth(bitmap2, &width);
1896 expect(Ok, stat);
1897 expect(120, width);
1899 stat = GdipGetImageHeight(bitmap2, &height);
1900 expect(Ok, stat);
1901 expect(120, height);
1903 GdipDisposeImage(bitmap2);
1906 GdipDisposeImage(bitmap1);
1909 static void test_getsetpixel(void)
1911 GpStatus stat;
1912 GpBitmap *bitmap;
1913 ARGB color;
1914 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1915 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1917 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1918 expect(Ok, stat);
1920 /* null parameters */
1921 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1922 expect(InvalidParameter, stat);
1924 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1925 expect(InvalidParameter, stat);
1927 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1928 expect(InvalidParameter, stat);
1930 /* out of bounds */
1931 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1932 expect(InvalidParameter, stat);
1934 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1935 expect(InvalidParameter, stat);
1937 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1938 ok(stat == InvalidParameter ||
1939 broken(stat == Ok), /* Older gdiplus */
1940 "Expected InvalidParameter, got %.8x\n", stat);
1942 if (0) /* crashes some gdiplus implementations */
1944 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1945 ok(stat == InvalidParameter ||
1946 broken(stat == Ok), /* Older gdiplus */
1947 "Expected InvalidParameter, got %.8x\n", stat);
1950 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1951 expect(InvalidParameter, stat);
1953 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1954 expect(InvalidParameter, stat);
1956 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1957 expect(InvalidParameter, stat);
1959 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1960 expect(InvalidParameter, stat);
1962 /* valid use */
1963 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1964 expect(Ok, stat);
1965 expect(0xffffffff, color);
1967 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1968 expect(Ok, stat);
1969 expect(0xff0000ff, color);
1971 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1972 expect(Ok, stat);
1974 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1975 expect(Ok, stat);
1977 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1978 expect(Ok, stat);
1979 expect(0xff676869, color);
1981 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1982 expect(Ok, stat);
1983 expect(0xff474849, color);
1985 stat = GdipDisposeImage((GpImage*)bitmap);
1986 expect(Ok, stat);
1989 static void check_halftone_palette(ColorPalette *palette)
1991 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1992 UINT i;
1994 for (i=0; i<palette->Count; i++)
1996 ARGB expected=0xff000000;
1997 if (i<8)
1999 if (i&1) expected |= 0x800000;
2000 if (i&2) expected |= 0x8000;
2001 if (i&4) expected |= 0x80;
2003 else if (i == 8)
2005 expected = 0xffc0c0c0;
2007 else if (i < 16)
2009 if (i&1) expected |= 0xff0000;
2010 if (i&2) expected |= 0xff00;
2011 if (i&4) expected |= 0xff;
2013 else if (i < 40)
2015 expected = 0x00000000;
2017 else
2019 expected |= halftone_values[(i-40)%6];
2020 expected |= halftone_values[((i-40)/6)%6] << 8;
2021 expected |= halftone_values[((i-40)/36)%6] << 16;
2023 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2024 expected, palette->Entries[i], i, palette->Count);
2028 static void test_palette(void)
2030 GpStatus stat;
2031 GpBitmap *bitmap;
2032 INT size;
2033 BYTE buffer[1040];
2034 ColorPalette *palette=(ColorPalette*)buffer;
2035 ARGB *entries = palette->Entries;
2036 ARGB color=0;
2038 /* test initial palette from non-indexed bitmap */
2039 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2040 expect(Ok, stat);
2042 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2043 expect(Ok, stat);
2044 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2046 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2047 expect(Ok, stat);
2048 expect(0, palette->Count);
2050 /* test setting palette on not-indexed bitmap */
2051 palette->Count = 3;
2053 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2054 expect(Ok, stat);
2056 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2057 expect(Ok, stat);
2058 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2060 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2061 expect(Ok, stat);
2062 expect(3, palette->Count);
2064 GdipDisposeImage((GpImage*)bitmap);
2066 /* test initial palette on 1-bit bitmap */
2067 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2068 expect(Ok, stat);
2070 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2071 expect(Ok, stat);
2072 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2074 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2075 expect(Ok, stat);
2076 expect(PaletteFlagsGrayScale, palette->Flags);
2077 expect(2, palette->Count);
2079 expect(0xff000000, entries[0]);
2080 expect(0xffffffff, entries[1]);
2082 /* test getting/setting pixels */
2083 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2084 expect(Ok, stat);
2085 expect(0xff000000, color);
2087 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2088 ok((stat == Ok) ||
2089 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2091 if (stat == Ok)
2093 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2094 expect(Ok, stat);
2095 expect(0xffffffff, color);
2098 GdipDisposeImage((GpImage*)bitmap);
2100 /* test initial palette on 4-bit bitmap */
2101 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2102 expect(Ok, stat);
2104 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2105 expect(Ok, stat);
2106 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2108 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2109 expect(Ok, stat);
2110 expect(0, palette->Flags);
2111 expect(16, palette->Count);
2113 check_halftone_palette(palette);
2115 /* test getting/setting pixels */
2116 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2117 expect(Ok, stat);
2118 expect(0xff000000, color);
2120 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2121 ok((stat == Ok) ||
2122 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2124 if (stat == Ok)
2126 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2127 expect(Ok, stat);
2128 expect(0xffff00ff, color);
2131 GdipDisposeImage((GpImage*)bitmap);
2133 /* test initial palette on 8-bit bitmap */
2134 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2135 expect(Ok, stat);
2137 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2138 expect(Ok, stat);
2139 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2141 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2142 expect(Ok, stat);
2143 expect(PaletteFlagsHalftone, palette->Flags);
2144 expect(256, palette->Count);
2146 check_halftone_palette(palette);
2148 /* test getting/setting pixels */
2149 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2150 expect(Ok, stat);
2151 expect(0xff000000, color);
2153 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2154 ok((stat == Ok) ||
2155 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2157 if (stat == Ok)
2159 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2160 expect(Ok, stat);
2161 expect(0xffcccccc, color);
2164 /* test setting/getting a different palette */
2165 entries[1] = 0xffcccccc;
2167 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2168 expect(Ok, stat);
2170 entries[1] = 0;
2172 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2173 expect(Ok, stat);
2174 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2176 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2177 expect(Ok, stat);
2178 expect(PaletteFlagsHalftone, palette->Flags);
2179 expect(256, palette->Count);
2180 expect(0xffcccccc, entries[1]);
2182 /* test count < 256 */
2183 palette->Flags = 12345;
2184 palette->Count = 3;
2186 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2187 expect(Ok, stat);
2189 entries[1] = 0;
2190 entries[3] = 0xdeadbeef;
2192 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2193 expect(Ok, stat);
2194 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2196 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2197 expect(Ok, stat);
2198 expect(12345, palette->Flags);
2199 expect(3, palette->Count);
2200 expect(0xffcccccc, entries[1]);
2201 expect(0xdeadbeef, entries[3]);
2203 /* test count > 256 */
2204 palette->Count = 257;
2206 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2207 ok(stat == InvalidParameter ||
2208 broken(stat == Ok), /* Old gdiplus behavior */
2209 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2211 GdipDisposeImage((GpImage*)bitmap);
2214 static void test_colormatrix(void)
2216 GpStatus stat;
2217 ColorMatrix colormatrix, graymatrix;
2218 GpImageAttributes *imageattr;
2219 const ColorMatrix identity = {{
2220 {1.0,0.0,0.0,0.0,0.0},
2221 {0.0,1.0,0.0,0.0,0.0},
2222 {0.0,0.0,1.0,0.0,0.0},
2223 {0.0,0.0,0.0,1.0,0.0},
2224 {0.0,0.0,0.0,0.0,1.0}}};
2225 const ColorMatrix double_red = {{
2226 {2.0,0.0,0.0,0.0,0.0},
2227 {0.0,1.0,0.0,0.0,0.0},
2228 {0.0,0.0,1.0,0.0,0.0},
2229 {0.0,0.0,0.0,1.0,0.0},
2230 {0.0,0.0,0.0,0.0,1.0}}};
2231 const ColorMatrix asymmetric = {{
2232 {0.0,1.0,0.0,0.0,0.0},
2233 {0.0,0.0,1.0,0.0,0.0},
2234 {0.0,0.0,0.0,1.0,0.0},
2235 {1.0,0.0,0.0,0.0,0.0},
2236 {0.0,0.0,0.0,0.0,1.0}}};
2237 GpBitmap *bitmap1, *bitmap2;
2238 GpGraphics *graphics;
2239 ARGB color;
2241 colormatrix = identity;
2242 graymatrix = identity;
2244 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2245 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2246 expect(InvalidParameter, stat);
2248 stat = GdipCreateImageAttributes(&imageattr);
2249 expect(Ok, stat);
2251 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2252 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2253 expect(Ok, stat);
2255 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2256 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2257 expect(InvalidParameter, stat);
2259 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2260 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2261 expect(Ok, stat);
2263 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2264 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2265 expect(Ok, stat);
2267 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2268 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2269 expect(InvalidParameter, stat);
2271 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2272 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2273 expect(Ok, stat);
2275 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2276 TRUE, &colormatrix, &graymatrix, 3);
2277 expect(InvalidParameter, stat);
2279 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2280 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2281 expect(InvalidParameter, stat);
2283 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2284 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2285 expect(InvalidParameter, stat);
2287 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2288 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2289 expect(Ok, stat);
2291 /* Drawing a bitmap transforms the colors */
2292 colormatrix = double_red;
2293 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2294 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2295 expect(Ok, stat);
2297 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2298 expect(Ok, stat);
2300 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2301 expect(Ok, stat);
2303 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2304 expect(Ok, stat);
2306 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2307 expect(Ok, stat);
2309 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2310 UnitPixel, imageattr, NULL, NULL);
2311 expect(Ok, stat);
2313 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2314 expect(Ok, stat);
2315 expect(0xff80ccee, color);
2317 colormatrix = asymmetric;
2318 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2319 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2320 expect(Ok, stat);
2322 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
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 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2333 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2334 expect(Ok, stat);
2336 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2337 UnitPixel, imageattr, NULL, NULL);
2338 expect(Ok, stat);
2340 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2341 expect(Ok, stat);
2342 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2344 GdipDeleteGraphics(graphics);
2345 GdipDisposeImage((GpImage*)bitmap1);
2346 GdipDisposeImage((GpImage*)bitmap2);
2347 GdipDisposeImageAttributes(imageattr);
2350 static void test_gamma(void)
2352 GpStatus stat;
2353 GpImageAttributes *imageattr;
2354 GpBitmap *bitmap1, *bitmap2;
2355 GpGraphics *graphics;
2356 ARGB color;
2358 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2359 expect(InvalidParameter, stat);
2361 stat = GdipCreateImageAttributes(&imageattr);
2362 expect(Ok, stat);
2364 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2365 expect(Ok, stat);
2367 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2368 expect(InvalidParameter, stat);
2370 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2371 expect(InvalidParameter, stat);
2373 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2374 expect(InvalidParameter, stat);
2376 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2377 expect(Ok, stat);
2379 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2380 expect(Ok, stat);
2382 /* Drawing a bitmap transforms the colors */
2383 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2384 expect(Ok, stat);
2386 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2387 expect(Ok, stat);
2389 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2390 expect(Ok, stat);
2392 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2393 expect(Ok, stat);
2395 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2396 expect(Ok, stat);
2398 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2399 UnitPixel, imageattr, NULL, NULL);
2400 expect(Ok, stat);
2402 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2403 expect(Ok, stat);
2404 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2406 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2407 expect(Ok, stat);
2409 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2410 UnitPixel, imageattr, NULL, NULL);
2411 expect(Ok, stat);
2413 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2414 expect(Ok, stat);
2415 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2417 GdipDeleteGraphics(graphics);
2418 GdipDisposeImage((GpImage*)bitmap1);
2419 GdipDisposeImage((GpImage*)bitmap2);
2420 GdipDisposeImageAttributes(imageattr);
2423 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2424 static const unsigned char gifanimation[72] = {
2425 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2426 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2427 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2428 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2429 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2432 /* Generated with ImageMagick:
2433 * convert -transparent black -delay 100 -size 8x2 xc:black \
2434 * -dispose none -page +0+0 -size 2x2 xc:red \
2435 * -dispose background -page +2+0 -size 2x2 xc:blue \
2436 * -dispose previous -page +4+0 -size 2x2 xc:green \
2437 * -dispose undefined -page +6+0 -size 2x2 xc:gray \
2438 * test.gif
2440 static const unsigned char gifanimation2[] = {
2441 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2442 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2443 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2444 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2445 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2446 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2447 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2448 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2449 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2450 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2451 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2452 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2453 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2454 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2455 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2456 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2457 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2458 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2459 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2460 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2461 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2462 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2463 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2464 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2465 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2466 0x3b
2469 static ARGB gifanimation2_pixels[5][4] = {
2470 {0, 0, 0, 0},
2471 {0xffff0000, 0, 0, 0},
2472 {0xffff0000, 0xff0000ff, 0, 0},
2473 {0xffff0000, 0, 0xff008000, 0},
2474 {0xffff0000, 0, 0, 0xff7e7e7e}
2477 static void test_multiframegif(void)
2479 LPSTREAM stream;
2480 HGLOBAL hglob;
2481 LPBYTE data;
2482 HRESULT hres;
2483 GpStatus stat;
2484 GpBitmap *bmp;
2485 ARGB color;
2486 UINT count;
2487 GUID dimension;
2488 PixelFormat pixel_format;
2489 INT palette_size, i, j;
2490 char palette_buf[256];
2491 ColorPalette *palette;
2492 ARGB *palette_entries;
2494 /* Test frame functions with an animated GIF */
2495 hglob = GlobalAlloc (0, sizeof(gifanimation));
2496 data = GlobalLock (hglob);
2497 memcpy(data, gifanimation, sizeof(gifanimation));
2498 GlobalUnlock(hglob);
2500 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2501 ok(hres == S_OK, "Failed to create a stream\n");
2502 if(hres != S_OK) return;
2504 stat = GdipCreateBitmapFromStream(stream, &bmp);
2505 ok(stat == Ok, "Failed to create a Bitmap\n");
2506 if(stat != Ok){
2507 IStream_Release(stream);
2508 return;
2511 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2512 expect(Ok, stat);
2513 expect(PixelFormat32bppARGB, pixel_format);
2515 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2516 expect(Ok, stat);
2517 ok(palette_size == sizeof(ColorPalette) ||
2518 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2519 "palette_size = %d\n", palette_size);
2521 /* Bitmap starts at frame 0 */
2522 color = 0xdeadbeef;
2523 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2524 expect(Ok, stat);
2525 expect(0xffffffff, color);
2527 /* Check that we get correct metadata */
2528 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2529 expect(Ok, stat);
2530 expect(1, count);
2532 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2533 expect(Ok, stat);
2534 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2536 count = 12345;
2537 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2538 expect(Ok, stat);
2539 expect(2, count);
2541 /* SelectActiveFrame overwrites our current data */
2542 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2543 expect(Ok, stat);
2545 color = 0xdeadbeef;
2546 GdipBitmapGetPixel(bmp, 0, 0, &color);
2547 expect(Ok, stat);
2548 expect(0xff000000, color);
2550 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2551 expect(Ok, stat);
2553 color = 0xdeadbeef;
2554 GdipBitmapGetPixel(bmp, 0, 0, &color);
2555 expect(Ok, stat);
2556 expect(0xffffffff, color);
2558 /* Write over the image data */
2559 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2560 expect(Ok, stat);
2562 /* Switching to the same frame does not overwrite our changes */
2563 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2564 expect(Ok, stat);
2566 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2567 expect(Ok, stat);
2568 expect(0xff000000, color);
2570 /* But switching to another frame and back does */
2571 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2572 expect(Ok, stat);
2574 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2575 expect(Ok, stat);
2577 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2578 expect(Ok, stat);
2579 expect(0xffffffff, color);
2581 /* rotate/flip discards the information about other frames */
2582 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2583 expect(Ok, stat);
2585 count = 12345;
2586 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2587 expect(Ok, stat);
2588 expect(1, count);
2590 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2592 GdipDisposeImage((GpImage*)bmp);
2593 IStream_Release(stream);
2595 /* Test with a non-animated gif */
2596 hglob = GlobalAlloc (0, sizeof(gifimage));
2597 data = GlobalLock (hglob);
2598 memcpy(data, gifimage, sizeof(gifimage));
2599 GlobalUnlock(hglob);
2601 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2602 ok(hres == S_OK, "Failed to create a stream\n");
2603 if(hres != S_OK) return;
2605 stat = GdipCreateBitmapFromStream(stream, &bmp);
2606 ok(stat == Ok, "Failed to create a Bitmap\n");
2607 if(stat != Ok){
2608 IStream_Release(stream);
2609 return;
2612 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2613 expect(Ok, stat);
2614 expect(PixelFormat8bppIndexed, pixel_format);
2616 /* Check metadata */
2617 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2618 expect(Ok, stat);
2619 expect(1, count);
2621 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2622 expect(Ok, stat);
2623 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2625 count = 12345;
2626 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2627 expect(Ok, stat);
2628 expect(1, count);
2630 GdipDisposeImage((GpImage*)bmp);
2631 IStream_Release(stream);
2633 /* Test with a non-animated transparent gif */
2634 hglob = GlobalAlloc (0, sizeof(transparentgif));
2635 data = GlobalLock (hglob);
2636 memcpy(data, transparentgif, sizeof(transparentgif));
2637 GlobalUnlock(hglob);
2639 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2640 ok(hres == S_OK, "Failed to create a stream\n");
2642 stat = GdipCreateBitmapFromStream(stream, &bmp);
2643 IStream_Release(stream);
2644 ok(stat == Ok, "Failed to create a Bitmap\n");
2646 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2647 expect(Ok, stat);
2648 expect(PixelFormat8bppIndexed, pixel_format);
2650 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2651 expect(Ok, stat);
2652 expect(0, color);
2654 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2655 expect(Ok, stat);
2656 ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB),
2657 "palette_size = %d\n", palette_size);
2659 memset(palette_buf, 0xfe, sizeof(palette_buf));
2660 palette = (ColorPalette*)palette_buf;
2661 stat = GdipGetImagePalette((GpImage*)bmp, palette,
2662 sizeof(ColorPalette)+sizeof(ARGB));
2663 palette_entries = palette->Entries;
2664 expect(Ok, stat);
2665 expect(PaletteFlagsHasAlpha, palette->Flags);
2666 expect(2, palette->Count);
2667 expect(0, palette_entries[0]);
2668 expect(0xff000000, palette_entries[1]);
2670 count = 12345;
2671 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2672 expect(Ok, stat);
2673 expect(1, count);
2675 GdipDisposeImage((GpImage*)bmp);
2677 /* Test frame dispose methods */
2678 hglob = GlobalAlloc (0, sizeof(gifanimation2));
2679 data = GlobalLock (hglob);
2680 memcpy(data, gifanimation2, sizeof(gifanimation2));
2681 GlobalUnlock(hglob);
2683 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2684 ok(hres == S_OK, "Failed to create a stream\n");
2686 stat = GdipCreateBitmapFromStream(stream, &bmp);
2687 ok(stat == Ok, "Failed to create a Bitmap\n");
2688 IStream_Release(stream);
2690 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2691 expect(Ok, stat);
2692 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2694 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2695 expect(Ok, stat);
2696 expect(5, count);
2698 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2699 expect(Ok, stat);
2700 expect(0, color);
2702 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2703 stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2704 expect(Ok, stat);
2705 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2706 if(color != 0) {
2707 win_skip("broken animated gif support\n");
2708 GdipDisposeImage((GpImage*)bmp);
2709 return;
2712 for(i=0; i<6; i++) {
2713 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2714 expect(Ok, stat);
2716 for(j=0; j<4; j++) {
2717 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2718 expect(Ok, stat);
2719 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2723 GdipDisposeImage((GpImage*)bmp);
2726 static void test_rotateflip(void)
2728 GpImage *bitmap;
2729 GpStatus stat;
2730 BYTE bits[24];
2731 static const BYTE orig_bits[24] = {
2732 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2733 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2734 UINT width, height;
2735 ARGB color;
2737 memcpy(bits, orig_bits, sizeof(bits));
2738 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2739 expect(Ok, stat);
2741 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2742 expect(Ok, stat);
2744 stat = GdipGetImageWidth(bitmap, &width);
2745 expect(Ok, stat);
2746 stat = GdipGetImageHeight(bitmap, &height);
2747 expect(Ok, stat);
2748 expect(2, width);
2749 expect(3, height);
2751 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2752 expect(Ok, stat);
2753 expect(0xff00ffff, color);
2755 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2756 expect(Ok, stat);
2757 expect(0xffff0000, color);
2759 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2760 expect(Ok, stat);
2761 expect(0xffffff00, color);
2763 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2764 expect(Ok, stat);
2765 expect(0xff0000ff, color);
2767 expect(0, bits[0]);
2768 expect(0, bits[1]);
2769 expect(0xff, bits[2]);
2771 GdipDisposeImage(bitmap);
2773 memcpy(bits, orig_bits, sizeof(bits));
2774 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2775 expect(Ok, stat);
2777 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2778 expect(Ok, stat);
2780 stat = GdipGetImageWidth(bitmap, &width);
2781 expect(Ok, stat);
2782 stat = GdipGetImageHeight(bitmap, &height);
2783 expect(Ok, stat);
2784 expect(3, width);
2785 expect(2, height);
2787 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2788 expect(Ok, stat);
2789 expect(0xff0000ff, color);
2791 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2792 expect(Ok, stat);
2793 expect(0xffff0000, color);
2795 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2796 expect(Ok, stat);
2797 expect(0xffffff00, color);
2799 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2800 expect(Ok, stat);
2801 expect(0xff00ffff, color);
2803 expect(0, bits[0]);
2804 expect(0, bits[1]);
2805 expect(0xff, bits[2]);
2807 GdipDisposeImage(bitmap);
2809 memcpy(bits, orig_bits, sizeof(bits));
2810 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2811 expect(Ok, stat);
2813 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2814 expect(Ok, stat);
2816 stat = GdipGetImageWidth(bitmap, &width);
2817 expect(Ok, stat);
2818 stat = GdipGetImageHeight(bitmap, &height);
2819 expect(Ok, stat);
2820 expect(3, width);
2821 expect(2, height);
2823 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2824 expect(Ok, stat);
2825 expect(0xff00ffff, color);
2827 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2828 expect(Ok, stat);
2829 expect(0xffffff00, color);
2831 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2832 expect(Ok, stat);
2833 expect(0xffff0000, color);
2835 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2836 expect(Ok, stat);
2837 expect(0xff0000ff, color);
2839 expect(0, bits[0]);
2840 expect(0, bits[1]);
2841 expect(0xff, bits[2]);
2843 GdipDisposeImage(bitmap);
2846 static void test_remaptable(void)
2848 GpStatus stat;
2849 GpImageAttributes *imageattr;
2850 GpBitmap *bitmap1, *bitmap2;
2851 GpGraphics *graphics;
2852 ARGB color;
2853 ColorMap *map;
2855 map = GdipAlloc(sizeof(ColorMap));
2857 map->oldColor.Argb = 0xff00ff00;
2858 map->newColor.Argb = 0xffff00ff;
2860 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2861 expect(InvalidParameter, stat);
2863 stat = GdipCreateImageAttributes(&imageattr);
2864 expect(Ok, stat);
2866 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2867 expect(InvalidParameter, stat);
2869 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2870 expect(InvalidParameter, stat);
2872 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2873 expect(InvalidParameter, stat);
2875 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2876 expect(InvalidParameter, stat);
2878 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2879 expect(Ok, stat);
2881 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2882 expect(Ok, stat);
2884 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2885 expect(Ok, stat);
2887 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2888 expect(Ok, stat);
2890 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2891 expect(Ok, stat);
2893 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2894 expect(Ok, stat);
2896 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2897 UnitPixel, imageattr, NULL, NULL);
2898 expect(Ok, stat);
2900 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2901 expect(Ok, stat);
2902 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2904 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2905 expect(Ok, stat);
2907 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2908 UnitPixel, imageattr, NULL, NULL);
2909 expect(Ok, stat);
2911 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2912 expect(Ok, stat);
2913 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
2915 GdipDeleteGraphics(graphics);
2916 GdipDisposeImage((GpImage*)bitmap1);
2917 GdipDisposeImage((GpImage*)bitmap2);
2918 GdipDisposeImageAttributes(imageattr);
2919 GdipFree(map);
2922 static void test_colorkey(void)
2924 GpStatus stat;
2925 GpImageAttributes *imageattr;
2926 GpBitmap *bitmap1, *bitmap2;
2927 GpGraphics *graphics;
2928 ARGB color;
2930 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2931 expect(InvalidParameter, stat);
2933 stat = GdipCreateImageAttributes(&imageattr);
2934 expect(Ok, stat);
2936 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2937 expect(InvalidParameter, stat);
2939 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2940 expect(InvalidParameter, stat);
2942 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2943 expect(Ok, stat);
2945 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2946 expect(Ok, stat);
2948 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2949 expect(Ok, stat);
2951 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2952 expect(Ok, stat);
2954 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2955 expect(Ok, stat);
2957 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
2958 expect(Ok, stat);
2960 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
2961 expect(Ok, stat);
2963 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2964 expect(Ok, stat);
2966 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2967 UnitPixel, imageattr, NULL, NULL);
2968 expect(Ok, stat);
2970 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2971 expect(Ok, stat);
2972 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2974 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2975 expect(Ok, stat);
2976 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2978 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2979 expect(Ok, stat);
2980 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2982 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2983 expect(Ok, stat);
2984 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
2986 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2987 expect(Ok, stat);
2989 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2990 UnitPixel, imageattr, NULL, NULL);
2991 expect(Ok, stat);
2993 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2994 expect(Ok, stat);
2995 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
2997 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2998 expect(Ok, stat);
2999 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
3001 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3002 expect(Ok, stat);
3003 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
3005 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3006 expect(Ok, stat);
3007 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3010 GdipDeleteGraphics(graphics);
3011 GdipDisposeImage((GpImage*)bitmap1);
3012 GdipDisposeImage((GpImage*)bitmap2);
3013 GdipDisposeImageAttributes(imageattr);
3016 static void test_dispose(void)
3018 GpStatus stat;
3019 GpImage *image;
3020 char invalid_image[256];
3022 stat = GdipDisposeImage(NULL);
3023 expect(InvalidParameter, stat);
3025 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
3026 expect(Ok, stat);
3028 stat = GdipDisposeImage(image);
3029 expect(Ok, stat);
3031 stat = GdipDisposeImage(image);
3032 expect(ObjectBusy, stat);
3034 memset(invalid_image, 0, 256);
3035 stat = GdipDisposeImage((GpImage*)invalid_image);
3036 expect(ObjectBusy, stat);
3039 static LONG obj_refcount(void *obj)
3041 IUnknown_AddRef((IUnknown *)obj);
3042 return IUnknown_Release((IUnknown *)obj);
3045 static GpImage *load_image(const BYTE *image_data, UINT image_size)
3047 IStream *stream;
3048 HGLOBAL hmem;
3049 BYTE *data;
3050 HRESULT hr;
3051 GpStatus status;
3052 GpImage *image = NULL, *clone;
3053 ImageType image_type;
3054 LONG refcount, old_refcount;
3056 hmem = GlobalAlloc(0, image_size);
3057 data = GlobalLock(hmem);
3058 memcpy(data, image_data, image_size);
3059 GlobalUnlock(hmem);
3061 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3062 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3063 if (hr != S_OK) return NULL;
3065 refcount = obj_refcount(stream);
3066 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3068 status = GdipLoadImageFromStream(stream, &image);
3069 ok(status == Ok || broken(status == InvalidParameter), /* XP */
3070 "GdipLoadImageFromStream error %d\n", status);
3071 if (status != Ok)
3073 IStream_Release(stream);
3074 return NULL;
3077 status = GdipGetImageType(image, &image_type);
3078 ok(status == Ok, "GdipGetImageType error %d\n", status);
3080 refcount = obj_refcount(stream);
3081 if (image_type == ImageTypeBitmap)
3082 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3083 else
3084 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3085 old_refcount = refcount;
3087 status = GdipCloneImage(image, &clone);
3088 ok(status == Ok, "GdipCloneImage error %d\n", status);
3089 refcount = obj_refcount(stream);
3090 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3091 status = GdipDisposeImage(clone);
3092 ok(status == Ok, "GdipDisposeImage error %d\n", status);
3093 refcount = obj_refcount(stream);
3094 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3096 refcount = IStream_Release(stream);
3097 if (image_type == ImageTypeBitmap)
3098 ok(refcount >= 1, "expected stream refcount != 0\n");
3099 else
3100 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3102 return image;
3105 static void test_image_properties(void)
3107 static const struct test_data
3109 const BYTE *image_data;
3110 UINT image_size;
3111 ImageType image_type;
3112 UINT prop_count;
3113 UINT prop_count2; /* if win7 behaves differently */
3114 /* 1st property attributes */
3115 UINT prop_size;
3116 UINT prop_size2; /* if win7 behaves differently */
3117 UINT prop_id;
3118 UINT prop_id2; /* if win7 behaves differently */
3120 td[] =
3122 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3123 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3124 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3125 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3126 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3128 GpStatus status;
3129 GpImage *image;
3130 UINT prop_count, prop_size, i;
3131 PROPID prop_id[16] = { 0 };
3132 ImageType image_type;
3133 union
3135 PropertyItem data;
3136 char buf[256];
3137 } item;
3139 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3141 image = load_image(td[i].image_data, td[i].image_size);
3142 if (!image)
3144 trace("%u: failed to load image data\n", i);
3145 continue;
3148 status = GdipGetImageType(image, &image_type);
3149 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3150 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3151 i, td[i].image_type, image_type);
3153 status = GdipGetPropertyCount(image, &prop_count);
3154 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3155 if (td[i].image_data == pngimage || td[i].image_data == jpgimage)
3156 todo_wine
3157 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3158 " %u: expected property count %u or %u, got %u\n",
3159 i, td[i].prop_count, td[i].prop_count2, prop_count);
3160 else
3161 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3162 " %u: expected property count %u or %u, got %u\n",
3163 i, td[i].prop_count, td[i].prop_count2, prop_count);
3165 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3166 expect(InvalidParameter, status);
3167 status = GdipGetPropertyItemSize(image, 0, NULL);
3168 expect(InvalidParameter, status);
3169 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3170 if (image_type == ImageTypeMetafile)
3171 expect(NotImplemented, status);
3172 else
3173 expect(PropertyNotFound, status);
3175 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3176 expect(InvalidParameter, status);
3177 status = GdipGetPropertyItem(image, 0, 0, NULL);
3178 expect(InvalidParameter, status);
3179 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3180 if (image_type == ImageTypeMetafile)
3181 expect(NotImplemented, status);
3182 else
3183 expect(PropertyNotFound, status);
3185 /* FIXME: remove once Wine is fixed */
3186 if (td[i].prop_count != prop_count)
3188 GdipDisposeImage(image);
3189 continue;
3192 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3193 expect(InvalidParameter, status);
3194 status = GdipGetPropertyIdList(image, prop_count, NULL);
3195 expect(InvalidParameter, status);
3196 status = GdipGetPropertyIdList(image, 0, prop_id);
3197 if (image_type == ImageTypeMetafile)
3198 expect(NotImplemented, status);
3199 else if (prop_count == 0)
3200 expect(Ok, status);
3201 else
3202 expect(InvalidParameter, status);
3203 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3204 if (image_type == ImageTypeMetafile)
3205 expect(NotImplemented, status);
3206 else
3207 expect(InvalidParameter, status);
3208 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3209 if (image_type == ImageTypeMetafile)
3210 expect(NotImplemented, status);
3211 else
3212 expect(InvalidParameter, status);
3213 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3214 if (image_type == ImageTypeMetafile)
3215 expect(NotImplemented, status);
3216 else
3218 expect(Ok, status);
3219 if (prop_count != 0)
3220 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3221 " %u: expected property id %#x or %#x, got %#x\n",
3222 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3225 if (status == Ok)
3227 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3228 if (prop_count == 0)
3229 expect(PropertyNotFound, status);
3230 else
3232 expect(Ok, status);
3234 assert(sizeof(item) >= prop_size);
3235 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3236 i, prop_size);
3237 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3238 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3239 " %u: expected property size %u or %u, got %u\n",
3240 i, td[i].prop_size, td[i].prop_size2, prop_size);
3242 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3243 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3244 "%u: expected InvalidParameter, got %d\n", i, status);
3245 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3246 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3247 "%u: expected InvalidParameter, got %d\n", i, status);
3248 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3249 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3250 "%u: expected InvalidParameter, got %d\n", i, status);
3251 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3252 expect(Ok, status);
3253 ok(prop_id[0] == item.data.id,
3254 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3258 GdipDisposeImage(image);
3262 #define IFD_BYTE 1
3263 #define IFD_ASCII 2
3264 #define IFD_SHORT 3
3265 #define IFD_LONG 4
3266 #define IFD_RATIONAL 5
3267 #define IFD_SBYTE 6
3268 #define IFD_UNDEFINED 7
3269 #define IFD_SSHORT 8
3270 #define IFD_SLONG 9
3271 #define IFD_SRATIONAL 10
3272 #define IFD_FLOAT 11
3273 #define IFD_DOUBLE 12
3275 #ifndef PropertyTagTypeSByte
3276 #define PropertyTagTypeSByte 6
3277 #define PropertyTagTypeSShort 8
3278 #define PropertyTagTypeFloat 11
3279 #define PropertyTagTypeDouble 12
3280 #endif
3282 static UINT documented_type(UINT type)
3284 switch (type)
3286 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3287 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3288 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3289 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3290 default: return type;
3294 #include "pshpack2.h"
3295 struct IFD_entry
3297 SHORT id;
3298 SHORT type;
3299 ULONG count;
3300 LONG value;
3303 struct IFD_rational
3305 LONG numerator;
3306 LONG denominator;
3309 static const struct tiff_data
3311 USHORT byte_order;
3312 USHORT version;
3313 ULONG dir_offset;
3314 USHORT number_of_entries;
3315 struct IFD_entry entry[40];
3316 ULONG next_IFD;
3317 struct IFD_rational xres;
3318 DOUBLE double_val;
3319 struct IFD_rational srational_val;
3320 char string[14];
3321 SHORT short_val[4];
3322 LONG long_val[2];
3323 FLOAT float_val[2];
3324 struct IFD_rational rational[3];
3325 BYTE pixel_data[4];
3326 } TIFF_data =
3328 #ifdef WORDS_BIGENDIAN
3329 'M' | 'M' << 8,
3330 #else
3331 'I' | 'I' << 8,
3332 #endif
3334 FIELD_OFFSET(struct tiff_data, number_of_entries),
3337 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3338 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3339 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3340 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3341 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3342 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3343 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3344 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3345 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3346 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3347 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3348 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3349 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3350 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3351 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3352 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3353 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3354 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3355 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3356 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3357 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3358 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3359 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3360 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3361 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3362 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3363 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3364 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3365 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3366 /* Some gdiplus versions ignore these fields.
3367 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3368 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3369 { 0xf014, IFD_LONG, 0, 0x11223344 },
3370 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3371 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3372 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3373 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3376 { 900, 3 },
3377 1234567890.0987654321,
3378 { 0x1a2b3c4d, 0x5a6b7c8d },
3379 "Hello World!",
3380 { 0x0101, 0x0202, 0x0303, 0x0404 },
3381 { 0x11223344, 0x55667788 },
3382 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3383 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3384 { 0x11, 0x22, 0x33, 0 }
3386 #include "poppack.h"
3388 static void test_tiff_properties(void)
3390 static const struct test_data
3392 ULONG type, id, length;
3393 const BYTE value[24];
3394 } td[31] =
3396 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3397 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3398 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3399 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3400 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3401 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3402 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3403 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3404 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3405 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3406 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3407 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3408 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3409 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3410 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3411 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3412 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3413 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3414 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3415 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3416 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3417 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3418 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3419 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3420 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3421 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3422 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3423 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3424 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3425 { PropertyTagTypeSRational, 0xf016, 24,
3426 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3427 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3428 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3429 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3430 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3432 GpStatus status;
3433 GpImage *image;
3434 GUID guid;
3435 UINT dim_count, frame_count, prop_count, prop_size, i;
3436 PROPID *prop_id;
3437 PropertyItem *prop_item;
3439 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3440 if (!image)
3442 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3443 return;
3446 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3447 expect(Ok, status);
3448 expect(1, dim_count);
3450 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3451 expect(Ok, status);
3452 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3454 frame_count = 0xdeadbeef;
3455 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3456 expect(Ok, status);
3457 expect(1, frame_count);
3459 prop_count = 0xdeadbeef;
3460 status = GdipGetPropertyCount(image, &prop_count);
3461 expect(Ok, status);
3462 ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3463 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3464 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3466 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3468 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3469 expect(Ok, status);
3471 for (i = 0; i < prop_count; i++)
3473 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3474 expect(Ok, status);
3475 if (status != Ok) break;
3476 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3478 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3479 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3480 expect(Ok, status);
3481 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3482 ok(td[i].type == prop_item->type ||
3483 /* Win7 stopped using proper but not documented types, and it
3484 looks broken since TypeFloat and TypeDouble now reported as
3485 TypeUndefined, and signed types reported as unsigned. */
3486 broken(prop_item->type == documented_type(td[i].type)),
3487 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3488 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3489 prop_size -= sizeof(*prop_item);
3490 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3491 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3492 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3493 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3494 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3495 if (td[i].length == prop_item->length)
3497 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3498 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3499 if (!match)
3501 UINT j;
3502 BYTE *data = prop_item->value;
3503 trace("id %#x:", prop_item->id);
3504 for (j = 0; j < prop_item->length; j++)
3505 trace(" %02x", data[j]);
3506 trace("\n");
3509 HeapFree(GetProcessHeap(), 0, prop_item);
3512 HeapFree(GetProcessHeap(), 0, prop_id);
3514 GdipDisposeImage(image);
3517 static void test_GdipGetAllPropertyItems(void)
3519 static const struct test_data
3521 ULONG type, id, length;
3522 BYTE value[32];
3523 } td[16] =
3525 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3526 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3527 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3528 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3529 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3530 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3531 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3532 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3533 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3534 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3535 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3536 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3537 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3538 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3539 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3540 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3542 GpStatus status;
3543 GpImage *image;
3544 GUID guid;
3545 UINT dim_count, frame_count, prop_count, prop_size, i;
3546 UINT total_size, total_count;
3547 PROPID *prop_id;
3548 PropertyItem *prop_item;
3549 const char *item_data;
3551 image = load_image(tiffimage, sizeof(tiffimage));
3552 ok(image != 0, "Failed to load TIFF image data\n");
3553 if (!image) return;
3555 dim_count = 0xdeadbeef;
3556 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3557 expect(Ok, status);
3558 expect(1, dim_count);
3560 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3561 expect(Ok, status);
3562 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3564 frame_count = 0xdeadbeef;
3565 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3566 expect(Ok, status);
3567 expect(1, frame_count);
3569 prop_count = 0xdeadbeef;
3570 status = GdipGetPropertyCount(image, &prop_count);
3571 expect(Ok, status);
3572 ok(prop_count == sizeof(td)/sizeof(td[0]),
3573 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3575 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3577 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3578 expect(Ok, status);
3580 prop_size = 0;
3581 for (i = 0; i < prop_count; i++)
3583 UINT size;
3584 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3585 expect(Ok, status);
3586 if (status != Ok) break;
3587 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3589 prop_size += size;
3591 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3592 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3593 expect(Ok, status);
3594 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3595 ok(td[i].type == prop_item->type,
3596 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3597 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3598 size -= sizeof(*prop_item);
3599 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3600 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3601 if (td[i].length == prop_item->length)
3603 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3604 ok(match, "%u: data mismatch\n", i);
3605 if (!match)
3607 UINT j;
3608 BYTE *data = prop_item->value;
3609 trace("id %#x:", prop_item->id);
3610 for (j = 0; j < prop_item->length; j++)
3611 trace(" %02x", data[j]);
3612 trace("\n");
3615 HeapFree(GetProcessHeap(), 0, prop_item);
3618 HeapFree(GetProcessHeap(), 0, prop_id);
3620 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3621 expect(InvalidParameter, status);
3622 status = GdipGetPropertySize(image, &total_size, NULL);
3623 expect(InvalidParameter, status);
3624 status = GdipGetPropertySize(image, NULL, &total_count);
3625 expect(InvalidParameter, status);
3626 status = GdipGetPropertySize(image, NULL, NULL);
3627 expect(InvalidParameter, status);
3628 total_size = 0xdeadbeef;
3629 total_count = 0xdeadbeef;
3630 status = GdipGetPropertySize(image, &total_size, &total_count);
3631 expect(Ok, status);
3632 ok(prop_count == total_count,
3633 "expected total property count %u, got %u\n", prop_count, total_count);
3634 ok(prop_size == total_size,
3635 "expected total property size %u, got %u\n", prop_size, total_size);
3637 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3639 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3640 expect(InvalidParameter, status);
3641 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3642 expect(InvalidParameter, status);
3643 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3644 expect(InvalidParameter, status);
3645 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3646 expect(InvalidParameter, status);
3647 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3648 expect(InvalidParameter, status);
3649 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3650 expect(InvalidParameter, status);
3651 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3652 expect(Ok, status);
3654 item_data = (const char *)(prop_item + prop_count);
3655 for (i = 0; i < prop_count; i++)
3657 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3658 i, item_data, prop_item[i].value);
3659 ok(td[i].type == prop_item[i].type,
3660 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3661 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3662 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3663 if (td[i].length == prop_item[i].length)
3665 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3666 ok(match, "%u: data mismatch\n", i);
3667 if (!match)
3669 UINT j;
3670 BYTE *data = prop_item[i].value;
3671 trace("id %#x:", prop_item[i].id);
3672 for (j = 0; j < prop_item[i].length; j++)
3673 trace(" %02x", data[j]);
3674 trace("\n");
3677 item_data += prop_item[i].length;
3680 HeapFree(GetProcessHeap(), 0, prop_item);
3682 GdipDisposeImage(image);
3685 static void test_tiff_palette(void)
3687 GpStatus status;
3688 GpImage *image;
3689 PixelFormat format;
3690 INT size;
3691 struct
3693 ColorPalette pal;
3694 ARGB entry[256];
3695 } palette;
3696 ARGB *entries = palette.pal.Entries;
3698 /* 1bpp TIFF without palette */
3699 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3700 if (!image)
3702 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3703 return;
3706 status = GdipGetImagePixelFormat(image, &format);
3707 expect(Ok, status);
3708 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3710 status = GdipGetImagePaletteSize(image, &size);
3711 ok(status == Ok || broken(status == GenericError), /* XP */
3712 "GdipGetImagePaletteSize error %d\n", status);
3713 if (status == GenericError)
3715 GdipDisposeImage(image);
3716 return;
3718 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3720 status = GdipGetImagePalette(image, &palette.pal, size);
3721 expect(Ok, status);
3722 expect(0, palette.pal.Flags);
3723 expect(2, palette.pal.Count);
3724 if (palette.pal.Count == 2)
3726 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3727 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3730 GdipDisposeImage(image);
3733 static void test_bitmapbits(void)
3735 /* 8 x 2 bitmap */
3736 static const BYTE pixels_24[48] =
3738 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3739 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3740 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3741 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3743 static const BYTE pixels_00[48] =
3745 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3746 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3747 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3748 0,0,0, 0,0,0, 0,0,0, 0,0,0
3750 static const BYTE pixels_24_77[64] =
3752 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3753 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3754 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
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 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3759 static const BYTE pixels_77[64] =
3761 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3762 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3763 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3764 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3765 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3766 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3767 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3768 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3770 static const BYTE pixels_8[16] =
3772 0x01,0,0x01,0,0x01,0,0x01,0,
3773 0x01,0,0x01,0,0x01,0,0x01,0
3775 static const BYTE pixels_8_77[64] =
3777 0x01,0,0x01,0,0x01,0,0x01,0,
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 0x01,0,0x01,0,0x01,0,0x01,0,
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
3786 static const BYTE pixels_1_77[64] =
3788 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3789 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3790 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3791 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3792 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3793 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3794 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3795 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3797 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3798 static const struct test_data
3800 PixelFormat format;
3801 UINT bpp;
3802 ImageLockMode mode;
3803 UINT stride, size;
3804 const BYTE *pixels;
3805 const BYTE *pixels_unlocked;
3806 } td[] =
3808 /* 0 */
3809 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3811 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3812 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3813 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3814 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3815 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3816 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3817 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3818 /* 8 */
3819 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3820 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3821 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3822 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3823 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3824 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3825 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3826 /* 15 */
3827 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3828 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3829 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3830 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3831 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3832 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3833 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3835 BYTE buf[64];
3836 GpStatus status;
3837 GpBitmap *bitmap;
3838 UINT i;
3839 BitmapData data;
3840 struct
3842 ColorPalette pal;
3843 ARGB entries[1];
3844 } palette;
3845 ARGB *entries = palette.pal.Entries;
3847 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3849 BYTE pixels[sizeof(pixels_24)];
3850 memcpy(pixels, pixels_24, sizeof(pixels_24));
3851 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3852 expect(Ok, status);
3854 /* associate known palette with pixel data */
3855 palette.pal.Flags = PaletteFlagsGrayScale;
3856 palette.pal.Count = 2;
3857 entries[0] = 0xff000000;
3858 entries[1] = 0xffffffff;
3859 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3860 expect(Ok, status);
3862 memset(&data, 0xfe, sizeof(data));
3863 if (td[i].mode & ImageLockModeUserInputBuf)
3865 memset(buf, 0x77, sizeof(buf));
3866 data.Scan0 = buf;
3867 data.Stride = 32;
3869 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3870 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3871 if (status != Ok)
3873 GdipDisposeImage((GpImage *)bitmap);
3874 continue;
3876 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3877 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3878 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3879 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3880 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3881 if (td[i].mode & ImageLockModeUserInputBuf)
3882 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3883 if (td[i].size == data.Height * data.Stride)
3885 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3887 match = 1;
3888 for (j = 0; j < data.Height; j++)
3890 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3892 match = 0;
3893 break;
3896 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3898 ok(match,
3899 "%u: data should match\n", i);
3900 if (!match)
3902 BYTE *bits = data.Scan0;
3903 trace("%u: data mismatch for format %#x:", i, td[i].format);
3904 for (j = 0; j < td[i].size; j++)
3905 trace(" %02x", bits[j]);
3906 trace("\n");
3909 else
3910 ok(!match, "%u: data shouldn't match\n", i);
3912 memset(data.Scan0, 0, td[i].size);
3915 status = GdipBitmapUnlockBits(bitmap, &data);
3916 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3918 memset(&data, 0xfe, sizeof(data));
3919 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3920 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3921 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3922 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3923 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3924 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3925 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3926 if (data.Height * data.Stride == 48)
3928 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3929 ok(match, "%u: data should match\n", i);
3930 if (!match)
3932 UINT j;
3933 BYTE *bits = data.Scan0;
3934 trace("%u: data mismatch for format %#x:", i, td[i].format);
3935 for (j = 0; j < 48; j++)
3936 trace(" %02x", bits[j]);
3937 trace("\n");
3941 status = GdipBitmapUnlockBits(bitmap, &data);
3942 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3944 status = GdipDisposeImage((GpImage *)bitmap);
3945 expect(Ok, status);
3949 static void test_DrawImage(void)
3951 BYTE black_1x1[4] = { 0,0,0,0 };
3952 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3953 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3954 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3955 0,0,0,0,0,0,0xff,0xff };
3956 GpStatus status;
3957 union
3959 GpBitmap *bitmap;
3960 GpImage *image;
3961 } u1, u2;
3962 GpGraphics *graphics;
3963 int match;
3965 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3966 expect(Ok, status);
3967 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3968 expect(Ok, status);
3970 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3971 expect(Ok, status);
3972 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3973 expect(Ok, status);
3974 status = GdipGetImageGraphicsContext(u2.image, &graphics);
3975 expect(Ok, status);
3976 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3977 expect(Ok, status);
3979 status = GdipDrawImageI(graphics, u1.image, 0, 0);
3980 expect(Ok, status);
3982 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3983 ok(match, "data should match\n");
3984 if (!match)
3986 UINT i, size = sizeof(white_2x2);
3987 BYTE *bits = white_2x2;
3988 for (i = 0; i < size; i++)
3989 trace(" %02x", bits[i]);
3990 trace("\n");
3993 status = GdipDeleteGraphics(graphics);
3994 expect(Ok, status);
3995 status = GdipDisposeImage(u1.image);
3996 expect(Ok, status);
3997 status = GdipDisposeImage(u2.image);
3998 expect(Ok, status);
4001 static void test_GdipDrawImagePointRect(void)
4003 BYTE black_1x1[4] = { 0,0,0,0 };
4004 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4005 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4006 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4007 0,0,0,0,0,0,0xff,0xff };
4008 GpStatus status;
4009 union
4011 GpBitmap *bitmap;
4012 GpImage *image;
4013 } u1, u2;
4014 GpGraphics *graphics;
4015 int match;
4017 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4018 expect(Ok, status);
4019 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4020 expect(Ok, status);
4022 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4023 expect(Ok, status);
4024 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4025 expect(Ok, status);
4026 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4027 expect(Ok, status);
4028 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4029 expect(Ok, status);
4031 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
4032 expect(Ok, status);
4034 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4035 ok(match, "data should match\n");
4036 if (!match)
4038 UINT i, size = sizeof(white_2x2);
4039 BYTE *bits = white_2x2;
4040 for (i = 0; i < size; i++)
4041 trace(" %02x", bits[i]);
4042 trace("\n");
4045 status = GdipDeleteGraphics(graphics);
4046 expect(Ok, status);
4047 status = GdipDisposeImage(u1.image);
4048 expect(Ok, status);
4049 status = GdipDisposeImage(u2.image);
4050 expect(Ok, status);
4053 static void test_image_format(void)
4055 static const PixelFormat fmt[] =
4057 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4058 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4059 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4060 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4061 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4063 GpStatus status;
4064 GpBitmap *bitmap;
4065 GpImage *thumb;
4066 HBITMAP hbitmap;
4067 BITMAP bm;
4068 PixelFormat format;
4069 BitmapData data;
4070 UINT i, ret;
4072 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
4074 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4075 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4076 "GdipCreateBitmapFromScan0 error %d\n", status);
4077 if (status != Ok) continue;
4079 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4080 expect(Ok, status);
4081 expect(fmt[i], format);
4083 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4084 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4085 todo_wine expect(InvalidParameter, status);
4086 else
4088 expect(Ok, status);
4089 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4090 expect(sizeof(bm), ret);
4091 expect(0, bm.bmType);
4092 expect(1, bm.bmWidth);
4093 expect(1, bm.bmHeight);
4094 expect(4, bm.bmWidthBytes);
4095 expect(1, bm.bmPlanes);
4096 expect(32, bm.bmBitsPixel);
4097 DeleteObject(hbitmap);
4100 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4101 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4102 todo_wine
4103 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4104 "expected OutOfMemory, got %d\n", status);
4105 else
4106 expect(Ok, status);
4107 if (status == Ok)
4109 status = GdipGetImagePixelFormat(thumb, &format);
4110 expect(Ok, status);
4111 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4112 "expected PixelFormat32bppPARGB, got %#x\n", format);
4113 status = GdipDisposeImage(thumb);
4114 expect(Ok, status);
4117 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4118 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4119 todo_wine expect(InvalidParameter, status);
4120 else
4122 expect(Ok, status);
4123 status = GdipBitmapUnlockBits(bitmap, &data);
4124 expect(Ok, status);
4127 status = GdipDisposeImage((GpImage *)bitmap);
4128 expect(Ok, status);
4132 static void test_DrawImage_scale(void)
4134 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4135 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4136 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4137 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4138 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4139 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4140 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4141 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4142 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4143 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4144 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4145 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4146 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4147 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4148 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4149 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4150 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4151 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4152 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4153 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4154 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4155 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4156 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4157 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4158 static const struct test_data
4160 REAL scale_x;
4161 PixelOffsetMode pixel_offset_mode;
4162 const BYTE *image;
4163 BOOL todo;
4164 } td[] =
4166 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4167 { 1.0, PixelOffsetModeNone, image_100 },
4168 { 1.2, PixelOffsetModeNone, image_120 },
4169 { 1.5, PixelOffsetModeNone, image_150 },
4170 { 1.8, PixelOffsetModeNone, image_180 },
4171 { 2.0, PixelOffsetModeNone, image_200 },
4172 { 2.5, PixelOffsetModeNone, image_250 },
4174 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4175 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4176 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4177 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4178 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4179 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4180 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4182 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4183 { 1.0, PixelOffsetModeHalf, image_100 },
4184 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4185 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4186 { 1.8, PixelOffsetModeHalf, image_180 },
4187 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4188 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4190 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4191 { 1.0, PixelOffsetModeHighQuality, image_100 },
4192 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4193 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4194 { 1.8, PixelOffsetModeHighQuality, image_180 },
4195 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4196 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4198 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4199 BYTE dst_8x1[24];
4200 GpStatus status;
4201 union
4203 GpBitmap *bitmap;
4204 GpImage *image;
4205 } u1, u2;
4206 GpGraphics *graphics;
4207 GpMatrix *matrix;
4208 int i, match;
4210 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4211 expect(Ok, status);
4212 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4213 expect(Ok, status);
4215 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4216 expect(Ok, status);
4217 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4218 expect(Ok, status);
4219 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4220 expect(Ok, status);
4221 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4222 expect(Ok, status);
4224 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4226 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4227 expect(Ok, status);
4229 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4230 expect(Ok, status);
4231 status = GdipSetWorldTransform(graphics, matrix);
4232 expect(Ok, status);
4233 GdipDeleteMatrix(matrix);
4235 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4236 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4237 expect(Ok, status);
4239 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4240 if (!match && td[i].todo)
4241 todo_wine ok(match, "%d: data should match\n", i);
4242 else
4243 ok(match, "%d: data should match\n", i);
4244 if (!match)
4246 UINT i, size = sizeof(dst_8x1);
4247 const BYTE *bits = dst_8x1;
4248 for (i = 0; i < size; i++)
4249 trace(" %02x", bits[i]);
4250 trace("\n");
4254 status = GdipDeleteGraphics(graphics);
4255 expect(Ok, status);
4256 status = GdipDisposeImage(u1.image);
4257 expect(Ok, status);
4258 status = GdipDisposeImage(u2.image);
4259 expect(Ok, status);
4262 static const BYTE animatedgif[] = {
4263 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4264 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4265 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4266 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4267 0x03,0x01,0x05,0x00,0x00,
4268 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4269 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4270 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4271 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4272 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4273 0x02,0x02,0x4C,0x01,0x00,
4274 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4275 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4276 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4277 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4278 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4279 0x02,0x02,0x44,0x01,0x00,
4280 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4281 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4284 static void test_gif_properties(void)
4286 static const struct test_data
4288 ULONG type, id, length;
4289 const BYTE value[13];
4290 } td[] =
4292 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4293 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4294 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4295 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4296 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4297 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4299 GpStatus status;
4300 GpImage *image;
4301 GUID guid;
4302 UINT dim_count, frame_count, prop_count, prop_size, i;
4303 UINT total_size, total_count;
4304 PROPID *prop_id;
4305 PropertyItem *prop_item;
4306 const char *item_data;
4308 image = load_image(animatedgif, sizeof(animatedgif));
4309 if (!image) /* XP fails to load this GIF image */
4311 trace("Failed to load GIF image data\n");
4312 return;
4315 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4316 expect(Ok, status);
4317 expect(1, dim_count);
4319 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4320 expect(Ok, status);
4321 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4323 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4324 expect(Ok, status);
4325 expect(2, frame_count);
4327 status = GdipImageSelectActiveFrame(image, &guid, 1);
4328 expect(Ok, status);
4330 status = GdipGetPropertyCount(image, &prop_count);
4331 expect(Ok, status);
4332 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
4333 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
4335 if (prop_count != sizeof(td)/sizeof(td[0]))
4337 GdipDisposeImage(image);
4338 return;
4341 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4343 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4344 expect(Ok, status);
4346 prop_size = 0;
4347 for (i = 0; i < prop_count; i++)
4349 UINT size;
4350 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4351 expect(Ok, status);
4352 if (status != Ok) break;
4353 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4355 prop_size += size;
4357 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4358 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4359 expect(Ok, status);
4360 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4361 ok(td[i].type == prop_item->type,
4362 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4363 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4364 size -= sizeof(*prop_item);
4365 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4366 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4367 if (td[i].length == prop_item->length)
4369 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4370 ok(match, "%u: data mismatch\n", i);
4371 if (!match)
4373 UINT j;
4374 BYTE *data = prop_item->value;
4375 trace("id %#x:", prop_item->id);
4376 for (j = 0; j < prop_item->length; j++)
4377 trace(" %02x", data[j]);
4378 trace("\n");
4381 HeapFree(GetProcessHeap(), 0, prop_item);
4384 HeapFree(GetProcessHeap(), 0, prop_id);
4386 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4387 expect(InvalidParameter, status);
4388 status = GdipGetPropertySize(image, &total_size, NULL);
4389 expect(InvalidParameter, status);
4390 status = GdipGetPropertySize(image, NULL, &total_count);
4391 expect(InvalidParameter, status);
4392 status = GdipGetPropertySize(image, NULL, NULL);
4393 expect(InvalidParameter, status);
4394 total_size = 0xdeadbeef;
4395 total_count = 0xdeadbeef;
4396 status = GdipGetPropertySize(image, &total_size, &total_count);
4397 expect(Ok, status);
4398 ok(prop_count == total_count,
4399 "expected total property count %u, got %u\n", prop_count, total_count);
4400 ok(prop_size == total_size,
4401 "expected total property size %u, got %u\n", prop_size, total_size);
4403 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4405 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4406 expect(InvalidParameter, status);
4407 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4408 expect(InvalidParameter, status);
4409 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4410 expect(InvalidParameter, status);
4411 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4412 expect(InvalidParameter, status);
4413 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4414 expect(InvalidParameter, status);
4415 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4416 expect(InvalidParameter, status);
4417 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4418 expect(Ok, status);
4420 item_data = (const char *)(prop_item + prop_count);
4421 for (i = 0; i < prop_count; i++)
4423 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4424 i, item_data, prop_item[i].value);
4425 ok(td[i].type == prop_item[i].type,
4426 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4427 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4428 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4429 if (td[i].length == prop_item[i].length)
4431 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4432 ok(match, "%u: data mismatch\n", i);
4433 if (!match)
4435 UINT j;
4436 BYTE *data = prop_item[i].value;
4437 trace("id %#x:", prop_item[i].id);
4438 for (j = 0; j < prop_item[i].length; j++)
4439 trace(" %02x", data[j]);
4440 trace("\n");
4443 item_data += prop_item[i].length;
4446 HeapFree(GetProcessHeap(), 0, prop_item);
4448 GdipDisposeImage(image);
4451 static void test_ARGB_conversion(void)
4453 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4454 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4455 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4456 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4457 BYTE *bits;
4458 GpBitmap *bitmap;
4459 BitmapData data;
4460 GpStatus status;
4461 int match;
4463 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4464 expect(Ok, status);
4466 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4467 expect(Ok, status);
4468 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4469 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4470 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4471 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4472 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4473 ok(match, "bits don't match\n");
4474 if (!match)
4476 bits = data.Scan0;
4477 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4478 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4480 status = GdipBitmapUnlockBits(bitmap, &data);
4481 expect(Ok, status);
4483 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4484 expect(Ok, status);
4485 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4486 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4487 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4488 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4489 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4490 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4491 ok(match, "bits don't match\n");
4492 if (!match)
4494 bits = data.Scan0;
4495 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4496 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4498 status = GdipBitmapUnlockBits(bitmap, &data);
4499 expect(Ok, status);
4501 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4502 expect(Ok, status);
4503 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4504 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4505 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4506 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4507 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4508 ok(match, "bits don't match\n");
4509 if (!match)
4511 bits = data.Scan0;
4512 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4513 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4515 status = GdipBitmapUnlockBits(bitmap, &data);
4516 expect(Ok, status);
4518 GdipDisposeImage((GpImage *)bitmap);
4522 static void test_CloneBitmapArea(void)
4524 GpStatus status;
4525 GpBitmap *bitmap, *copy;
4526 BitmapData data, data2;
4528 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4529 expect(Ok, status);
4531 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4532 expect(Ok, status);
4534 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4535 expect(WrongState, status);
4537 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4538 expect(Ok, status);
4540 status = GdipBitmapUnlockBits(bitmap, &data);
4541 expect(Ok, status);
4543 GdipDisposeImage((GpImage *)copy);
4544 GdipDisposeImage((GpImage *)bitmap);
4547 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid)
4549 GpStatus status;
4550 UINT n_codecs, info_size, i;
4551 ImageCodecInfo *info;
4552 BOOL ret = FALSE;
4554 status = GdipGetImageEncodersSize(&n_codecs, &info_size);
4555 expect(Ok, status);
4557 info = GdipAlloc(info_size);
4559 status = GdipGetImageEncoders(n_codecs, info_size, info);
4560 expect(Ok, status);
4562 for (i = 0; i < n_codecs; i++)
4564 if (!lstrcmpW(info[i].MimeType, mime))
4566 *format = info[i].FormatID;
4567 *clsid = info[i].Clsid;
4568 ret = TRUE;
4569 break;
4573 GdipFree(info);
4574 return ret;
4577 static void test_supported_encoders(void)
4579 static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 };
4580 static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 };
4581 static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 };
4582 static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 };
4583 static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 };
4584 static const struct test_data
4586 LPCWSTR mime;
4587 const GUID *format;
4588 BOOL todo;
4589 } td[] =
4591 { bmp_mimetype, &ImageFormatBMP, FALSE },
4592 { jpeg_mimetype, &ImageFormatJPEG, FALSE },
4593 { gif_mimetype, &ImageFormatGIF, TRUE },
4594 { tiff_mimetype, &ImageFormatTIFF, FALSE },
4595 { png_mimetype, &ImageFormatPNG, FALSE }
4597 GUID format, clsid;
4598 BOOL ret;
4599 HRESULT hr;
4600 GpStatus status;
4601 GpBitmap *bm;
4602 IStream *stream;
4603 HGLOBAL hmem;
4604 int i;
4606 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
4607 ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
4609 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4611 ret = get_encoder_clsid(td[i].mime, &format, &clsid);
4612 ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
4613 expect_guid(td[i].format, &format, __LINE__, FALSE);
4615 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
4617 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
4618 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
4620 status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
4621 if (td[i].todo)
4622 todo_wine ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4623 else
4624 ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4626 IStream_Release(stream);
4629 GdipDisposeImage((GpImage *)bm);
4632 START_TEST(image)
4634 struct GdiplusStartupInput gdiplusStartupInput;
4635 ULONG_PTR gdiplusToken;
4637 gdiplusStartupInput.GdiplusVersion = 1;
4638 gdiplusStartupInput.DebugEventCallback = NULL;
4639 gdiplusStartupInput.SuppressBackgroundThread = 0;
4640 gdiplusStartupInput.SuppressExternalCodecs = 0;
4642 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
4644 test_supported_encoders();
4645 test_CloneBitmapArea();
4646 test_ARGB_conversion();
4647 test_DrawImage_scale();
4648 test_image_format();
4649 test_DrawImage();
4650 test_GdipDrawImagePointRect();
4651 test_bitmapbits();
4652 test_tiff_palette();
4653 test_GdipGetAllPropertyItems();
4654 test_tiff_properties();
4655 test_gif_properties();
4656 test_image_properties();
4657 test_Scan0();
4658 test_FromGdiDib();
4659 test_GetImageDimension();
4660 test_GdipImageGetFrameDimensionsCount();
4661 test_LoadingImages();
4662 test_SavingImages();
4663 test_encoders();
4664 test_LockBits();
4665 test_LockBits_UserBuf();
4666 test_GdipCreateBitmapFromHBITMAP();
4667 test_GdipGetImageFlags();
4668 test_GdipCloneImage();
4669 test_testcontrol();
4670 test_fromhicon();
4671 test_getrawformat();
4672 test_loadwmf();
4673 test_createfromwmf();
4674 test_resolution();
4675 test_createhbitmap();
4676 test_getthumbnail();
4677 test_getsetpixel();
4678 test_palette();
4679 test_colormatrix();
4680 test_gamma();
4681 test_multiframegif();
4682 test_rotateflip();
4683 test_remaptable();
4684 test_colorkey();
4685 test_dispose();
4687 GdiplusShutdown(gdiplusToken);