gdiplus/tests: Add a test for loading PNG grayscale images.
[wine.git] / dlls / gdiplus / tests / image.c
blob989c2179bbdc129f39a3a0af24e7deda143b0060
1 /*
2 * Unit test suite for images
4 * Copyright (C) 2007 Google (Evan Stade)
5 * Copyright (C) 2012, 2016 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define COBJMACROS
24 #include <math.h>
25 #include <assert.h>
26 #include <stdio.h>
28 #include "initguid.h"
29 #include "objbase.h"
30 #include "gdiplus.h"
31 #include "wine/test.h"
33 static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*);
34 static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
35 static GpStatus (WINAPI *pGdipImageSetAbort)(GpImage*,GdiplusAbort*);
37 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
38 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
40 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
42 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
43 c1 >>= 8; c2 >>= 8;
44 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45 c1 >>= 8; c2 >>= 8;
46 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
47 c1 >>= 8; c2 >>= 8;
48 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
49 return TRUE;
52 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
54 WCHAR bufferW[39];
55 char buffer[39];
56 char buffer2[39];
58 StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
59 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
60 StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
61 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
62 todo_wine_if (todo)
63 ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
66 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
68 GUID raw;
69 GpStatus stat;
71 stat = GdipGetImageRawFormat(img, &raw);
72 ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
73 if(stat != Ok) return;
74 expect_guid(expected, &raw, line, todo);
77 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
79 LPSTREAM stream;
80 HGLOBAL hglob;
81 LPBYTE data;
82 HRESULT hres;
83 GpStatus stat;
84 GpImage *img;
86 hglob = GlobalAlloc (0, size);
87 data = GlobalLock (hglob);
88 memcpy(data, buff, size);
89 GlobalUnlock(hglob); data = NULL;
91 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
92 ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
93 if(hres != S_OK) return;
95 stat = GdipLoadImageFromStream(stream, &img);
96 ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
97 if(stat != Ok){
98 IStream_Release(stream);
99 return;
102 expect_rawformat(expected, img, line, todo);
104 GdipDisposeImage(img);
105 IStream_Release(stream);
108 static void test_Scan0(void)
110 GpBitmap *bm;
111 GpStatus stat;
112 BYTE buff[360];
114 bm = NULL;
115 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
116 expect(Ok, stat);
117 ok(NULL != bm, "Expected bitmap to be initialized\n");
118 if (stat == Ok)
119 GdipDisposeImage((GpImage*)bm);
121 bm = (GpBitmap*)0xdeadbeef;
122 stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
123 expect(InvalidParameter, stat);
124 ok( !bm, "expected null bitmap\n" );
126 bm = (GpBitmap*)0xdeadbeef;
127 stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
128 expect(InvalidParameter, stat);
129 ok( !bm, "expected null bitmap\n" );
131 bm = (GpBitmap*)0xdeadbeef;
132 stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
133 expect(InvalidParameter, stat);
134 ok( !bm, "expected null bitmap\n" );
136 bm = NULL;
137 stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
138 expect(Ok, stat);
139 ok(NULL != bm, "Expected bitmap to be initialized\n");
140 if (stat == Ok)
141 GdipDisposeImage((GpImage*)bm);
143 bm = (GpBitmap*) 0xdeadbeef;
144 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
145 expect(InvalidParameter, stat);
146 ok( !bm, "expected null bitmap\n" );
148 bm = (GpBitmap*)0xdeadbeef;
149 stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
150 expect(InvalidParameter, stat);
151 ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
153 bm = NULL;
154 stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
155 expect(Ok, stat);
156 ok(NULL != bm, "Expected bitmap to be initialized\n");
157 if (stat == Ok)
158 GdipDisposeImage((GpImage*)bm);
160 bm = (GpBitmap*)0xdeadbeef;
161 stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
162 expect(InvalidParameter, stat);
163 ok( !bm, "expected null bitmap\n" );
166 static void test_FromGdiDib(void)
168 GpBitmap *bm;
169 GpStatus stat;
170 BYTE buff[400];
171 BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
172 BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
173 PixelFormat format;
175 bm = NULL;
177 memset(rbmi, 0, sizeof(rbmi));
179 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
180 bmi->bmiHeader.biWidth = 10;
181 bmi->bmiHeader.biHeight = 10;
182 bmi->bmiHeader.biPlanes = 1;
183 bmi->bmiHeader.biBitCount = 32;
184 bmi->bmiHeader.biCompression = BI_RGB;
186 stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
187 expect(InvalidParameter, stat);
189 stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
190 expect(InvalidParameter, stat);
192 stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
193 expect(InvalidParameter, stat);
195 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
196 expect(Ok, stat);
197 ok(NULL != bm, "Expected bitmap to be initialized\n");
198 if (stat == Ok)
200 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
201 expect(Ok, stat);
202 expect(PixelFormat32bppRGB, format);
204 GdipDisposeImage((GpImage*)bm);
207 bmi->bmiHeader.biBitCount = 24;
208 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
209 expect(Ok, stat);
210 ok(NULL != bm, "Expected bitmap to be initialized\n");
211 if (stat == Ok)
213 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
214 expect(Ok, stat);
215 expect(PixelFormat24bppRGB, format);
217 GdipDisposeImage((GpImage*)bm);
220 bmi->bmiHeader.biBitCount = 16;
221 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
222 expect(Ok, stat);
223 ok(NULL != bm, "Expected bitmap to be initialized\n");
224 if (stat == Ok)
226 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
227 expect(Ok, stat);
228 expect(PixelFormat16bppRGB555, format);
230 GdipDisposeImage((GpImage*)bm);
233 bmi->bmiHeader.biBitCount = 8;
234 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
235 expect(Ok, stat);
236 ok(NULL != bm, "Expected bitmap to be initialized\n");
237 if (stat == Ok)
239 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
240 expect(Ok, stat);
241 expect(PixelFormat8bppIndexed, format);
243 GdipDisposeImage((GpImage*)bm);
246 bmi->bmiHeader.biBitCount = 4;
247 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
248 expect(Ok, stat);
249 ok(NULL != bm, "Expected bitmap to be initialized\n");
250 if (stat == Ok)
252 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
253 expect(Ok, stat);
254 expect(PixelFormat4bppIndexed, format);
256 GdipDisposeImage((GpImage*)bm);
259 bmi->bmiHeader.biBitCount = 1;
260 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
261 expect(Ok, stat);
262 ok(NULL != bm, "Expected bitmap to be initialized\n");
263 if (stat == Ok)
265 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
266 expect(Ok, stat);
267 expect(PixelFormat1bppIndexed, format);
269 GdipDisposeImage((GpImage*)bm);
272 bmi->bmiHeader.biBitCount = 0;
273 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
274 expect(InvalidParameter, stat);
277 static void test_GetImageDimension(void)
279 GpBitmap *bm;
280 GpStatus stat;
281 const REAL WIDTH = 10.0, HEIGHT = 20.0;
282 REAL w,h;
284 bm = (GpBitmap*)0xdeadbeef;
285 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
286 expect(Ok,stat);
287 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
288 ok(NULL != bm, "Expected bitmap to not be NULL\n");
290 stat = GdipGetImageDimension(NULL,&w,&h);
291 expect(InvalidParameter, stat);
293 stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
294 expect(InvalidParameter, stat);
296 stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
297 expect(InvalidParameter, stat);
299 w = -1;
300 h = -1;
301 stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
302 expect(Ok, stat);
303 expectf(WIDTH, w);
304 expectf(HEIGHT, h);
305 GdipDisposeImage((GpImage*)bm);
308 static void test_GdipImageGetFrameDimensionsCount(void)
310 GpBitmap *bm;
311 GpStatus stat;
312 const REAL WIDTH = 10.0, HEIGHT = 20.0;
313 UINT w;
314 GUID dimension = {0};
315 UINT count;
316 ARGB color;
318 bm = (GpBitmap*)0xdeadbeef;
319 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
320 expect(Ok,stat);
321 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
322 ok(NULL != bm, "Expected bitmap to not be NULL\n");
324 stat = GdipImageGetFrameDimensionsCount(NULL,&w);
325 expect(InvalidParameter, stat);
327 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
328 expect(InvalidParameter, stat);
330 w = -1;
331 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
332 expect(Ok, stat);
333 expect(1, w);
335 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
336 expect(Ok, stat);
337 expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
339 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
340 expect(InvalidParameter, stat);
342 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
343 expect(InvalidParameter, stat);
345 stat = GdipImageGetFrameCount(NULL, &dimension, &count);
346 expect(InvalidParameter, stat);
348 /* WinXP crashes on this test */
349 if(0)
351 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
352 expect(InvalidParameter, stat);
355 stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
356 expect(Ok, stat);
358 count = 12345;
359 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
360 expect(Ok, stat);
361 expect(1, count);
363 GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
365 stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
366 expect(Ok, stat);
368 /* SelectActiveFrame has no effect on image data of memory bitmaps */
369 color = 0xdeadbeef;
370 GdipBitmapGetPixel(bm, 0, 0, &color);
371 expect(0xffffffff, color);
373 GdipDisposeImage((GpImage*)bm);
376 static void test_LoadingImages(void)
378 GpStatus stat;
379 GpBitmap *bm;
380 GpImage *img;
381 static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0};
383 stat = GdipCreateBitmapFromFile(0, 0);
384 expect(InvalidParameter, stat);
386 bm = (GpBitmap *)0xdeadbeef;
387 stat = GdipCreateBitmapFromFile(0, &bm);
388 expect(InvalidParameter, stat);
389 ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm);
391 bm = (GpBitmap *)0xdeadbeef;
392 stat = GdipCreateBitmapFromFile(nonexistentW, &bm);
393 todo_wine expect(InvalidParameter, stat);
394 ok(!bm, "returned %p\n", bm);
396 stat = GdipLoadImageFromFile(0, 0);
397 expect(InvalidParameter, stat);
399 img = (GpImage *)0xdeadbeef;
400 stat = GdipLoadImageFromFile(0, &img);
401 expect(InvalidParameter, stat);
402 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
404 img = (GpImage *)0xdeadbeef;
405 stat = GdipLoadImageFromFile(nonexistentW, &img);
406 todo_wine expect(OutOfMemory, stat);
407 ok(!img, "returned %p\n", img);
409 stat = GdipLoadImageFromFileICM(0, 0);
410 expect(InvalidParameter, stat);
412 img = (GpImage *)0xdeadbeef;
413 stat = GdipLoadImageFromFileICM(0, &img);
414 expect(InvalidParameter, stat);
415 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
417 img = (GpImage *)0xdeadbeef;
418 stat = GdipLoadImageFromFileICM(nonexistentW, &img);
419 todo_wine expect(OutOfMemory, stat);
420 ok(!img, "returned %p\n", img);
423 static void test_SavingImages(void)
425 GpStatus stat;
426 GpBitmap *bm;
427 UINT n;
428 UINT s;
429 const REAL WIDTH = 10.0, HEIGHT = 20.0;
430 REAL w, h;
431 ImageCodecInfo *codecs;
432 static const CHAR filenameA[] = "a.bmp";
433 static const WCHAR filename[] = { 'a','.','b','m','p',0 };
435 codecs = NULL;
437 stat = GdipSaveImageToFile(0, 0, 0, 0);
438 expect(InvalidParameter, stat);
440 bm = NULL;
441 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
442 expect(Ok, stat);
443 if (!bm)
444 return;
446 /* invalid params */
447 stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
448 expect(InvalidParameter, stat);
450 stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
451 expect(InvalidParameter, stat);
453 /* encoder tests should succeed -- already tested */
454 stat = GdipGetImageEncodersSize(&n, &s);
455 if (stat != Ok || n == 0) goto cleanup;
457 codecs = GdipAlloc(s);
458 if (!codecs) goto cleanup;
460 stat = GdipGetImageEncoders(n, s, codecs);
461 if (stat != Ok) goto cleanup;
463 stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
464 expect(Ok, stat);
466 GdipDisposeImage((GpImage*)bm);
467 bm = 0;
469 /* re-load and check image stats */
470 stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
471 expect(Ok, stat);
472 if (stat != Ok) goto cleanup;
474 stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
475 if (stat != Ok) goto cleanup;
477 expectf(WIDTH, w);
478 expectf(HEIGHT, h);
480 cleanup:
481 GdipFree(codecs);
482 if (bm)
483 GdipDisposeImage((GpImage*)bm);
484 ok(DeleteFileA(filenameA), "Delete failed.\n");
487 static void test_encoders(void)
489 GpStatus stat;
490 UINT n;
491 UINT s;
492 ImageCodecInfo *codecs;
493 int i;
494 int bmp_found;
496 static const CHAR bmp_format[] = "BMP";
498 stat = GdipGetImageEncodersSize(&n, &s);
499 expect(stat, Ok);
501 codecs = GdipAlloc(s);
502 if (!codecs)
503 return;
505 stat = GdipGetImageEncoders(n, s, NULL);
506 expect(GenericError, stat);
508 stat = GdipGetImageEncoders(0, s, codecs);
509 expect(GenericError, stat);
511 stat = GdipGetImageEncoders(n, s-1, codecs);
512 expect(GenericError, stat);
514 stat = GdipGetImageEncoders(n, s+1, codecs);
515 expect(GenericError, stat);
517 stat = GdipGetImageEncoders(n, s, codecs);
518 expect(stat, Ok);
520 bmp_found = FALSE;
521 for (i = 0; i < n; i++)
523 CHAR desc[32];
525 WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
526 desc, 32, 0, 0);
528 if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
529 desc, -1,
530 bmp_format, -1) == CSTR_EQUAL) {
531 bmp_found = TRUE;
532 break;
535 if (!bmp_found)
536 ok(FALSE, "No BMP codec found.\n");
538 GdipFree(codecs);
541 static void test_LockBits(void)
543 GpStatus stat;
544 GpBitmap *bm;
545 GpRect rect;
546 BitmapData bd;
547 const INT WIDTH = 10, HEIGHT = 20;
548 ARGB color;
549 int y;
551 bm = NULL;
552 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
553 expect(Ok, stat);
555 rect.X = 2;
556 rect.Y = 3;
557 rect.Width = 4;
558 rect.Height = 5;
560 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
561 expect(Ok, stat);
563 stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
564 expect(Ok, stat);
566 /* read-only */
567 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
568 expect(Ok, stat);
570 if (stat == Ok) {
571 expect(0xc3, ((BYTE*)bd.Scan0)[2]);
572 expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
574 ((char*)bd.Scan0)[2] = 0xff;
576 stat = GdipBitmapUnlockBits(bm, &bd);
577 expect(Ok, stat);
580 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
581 expect(Ok, stat);
582 expect(0xffff0000, color);
584 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
585 expect(Ok, stat);
587 /* read-only, with NULL rect -> whole bitmap lock */
588 stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
589 expect(Ok, stat);
590 expect(bd.Width, WIDTH);
591 expect(bd.Height, HEIGHT);
593 if (stat == Ok) {
594 ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
596 stat = GdipBitmapUnlockBits(bm, &bd);
597 expect(Ok, stat);
600 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
601 expect(Ok, stat);
602 expect(0xffff0000, color);
604 /* read-only, consecutive */
605 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
606 expect(Ok, stat);
608 if (stat == Ok) {
609 stat = GdipBitmapUnlockBits(bm, &bd);
610 expect(Ok, stat);
613 stat = GdipDisposeImage((GpImage*)bm);
614 expect(Ok, stat);
615 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
616 expect(Ok, stat);
618 /* read x2 */
619 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
620 expect(Ok, stat);
621 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
622 expect(WrongState, stat);
624 stat = GdipBitmapUnlockBits(bm, &bd);
625 expect(Ok, stat);
627 stat = GdipDisposeImage((GpImage*)bm);
628 expect(Ok, stat);
629 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
630 expect(Ok, stat);
632 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
633 expect(Ok, stat);
635 stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
636 expect(Ok, stat);
638 /* write, no conversion */
639 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
640 expect(Ok, stat);
642 if (stat == Ok) {
643 /* all bits are readable, inside the rect or not */
644 expect(0xff, ((BYTE*)bd.Scan0)[2]);
645 expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
647 stat = GdipBitmapUnlockBits(bm, &bd);
648 expect(Ok, stat);
651 /* read, conversion */
652 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
653 expect(Ok, stat);
655 if (stat == Ok) {
656 expect(0xff, ((BYTE*)bd.Scan0)[2]);
657 if (0)
658 /* Areas outside the rectangle appear to be uninitialized */
659 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
661 ((BYTE*)bd.Scan0)[2] = 0xc3;
663 stat = GdipBitmapUnlockBits(bm, &bd);
664 expect(Ok, stat);
667 /* writes do not work in read mode if there was a conversion */
668 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
669 expect(Ok, stat);
670 expect(0xffff0000, color);
672 /* read/write, conversion */
673 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
674 expect(Ok, stat);
676 if (stat == Ok) {
677 expect(0xff, ((BYTE*)bd.Scan0)[2]);
678 ((BYTE*)bd.Scan0)[1] = 0x88;
679 if (0)
680 /* Areas outside the rectangle appear to be uninitialized */
681 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
683 stat = GdipBitmapUnlockBits(bm, &bd);
684 expect(Ok, stat);
687 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
688 expect(Ok, stat);
689 expect(0xffff8800, color);
691 /* write, conversion */
692 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
693 expect(Ok, stat);
695 if (stat == Ok) {
696 if (0)
698 /* This is completely uninitialized. */
699 ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
700 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
703 /* Initialize the buffer so the unlock doesn't access undefined memory */
704 for (y=0; y<5; y++)
705 memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
707 ((BYTE*)bd.Scan0)[0] = 0x12;
708 ((BYTE*)bd.Scan0)[1] = 0x34;
709 ((BYTE*)bd.Scan0)[2] = 0x56;
711 stat = GdipBitmapUnlockBits(bm, &bd);
712 expect(Ok, stat);
715 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
716 expect(Ok, stat);
717 expect(0xff563412, color);
719 stat = GdipBitmapGetPixel(bm, 2, 8, &color);
720 expect(Ok, stat);
721 expect(0xffc30000, color);
723 stat = GdipDisposeImage((GpImage*)bm);
724 expect(Ok, stat);
725 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
726 expect(Ok, stat);
728 /* write, no modification */
729 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
730 expect(Ok, stat);
732 if (stat == Ok) {
733 stat = GdipBitmapUnlockBits(bm, &bd);
734 expect(Ok, stat);
737 /* write, consecutive */
738 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
739 expect(Ok, stat);
741 if (stat == Ok) {
742 stat = GdipBitmapUnlockBits(bm, &bd);
743 expect(Ok, stat);
746 stat = GdipDisposeImage((GpImage*)bm);
747 expect(Ok, stat);
748 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
749 expect(Ok, stat);
751 /* write, modify */
752 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
753 expect(Ok, stat);
755 if (stat == Ok) {
756 if (bd.Scan0)
757 ((char*)bd.Scan0)[2] = 0xff;
759 stat = GdipBitmapUnlockBits(bm, &bd);
760 expect(Ok, stat);
763 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
764 expect(Ok, stat);
765 expect(0xffff0000, color);
767 stat = GdipDisposeImage((GpImage*)bm);
768 expect(Ok, stat);
770 /* dispose locked */
771 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
772 expect(Ok, stat);
773 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
774 expect(Ok, stat);
775 stat = GdipDisposeImage((GpImage*)bm);
776 expect(Ok, stat);
779 static void test_LockBits_UserBuf(void)
781 GpStatus stat;
782 GpBitmap *bm;
783 GpRect rect;
784 BitmapData bd;
785 const INT WIDTH = 10, HEIGHT = 20;
786 DWORD bits[200];
787 ARGB color;
789 bm = NULL;
790 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
791 expect(Ok, stat);
793 memset(bits, 0xaa, sizeof(bits));
795 rect.X = 2;
796 rect.Y = 3;
797 rect.Width = 4;
798 rect.Height = 5;
800 bd.Width = 4;
801 bd.Height = 6;
802 bd.Stride = WIDTH * 4;
803 bd.PixelFormat = PixelFormat32bppARGB;
804 bd.Scan0 = &bits[2+3*WIDTH];
805 bd.Reserved = 0xaaaaaaaa;
807 /* read-only */
808 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
809 expect(Ok, stat);
811 expect(0xaaaaaaaa, bits[0]);
812 expect(0, bits[2+3*WIDTH]);
814 bits[2+3*WIDTH] = 0xdeadbeef;
816 if (stat == Ok) {
817 stat = GdipBitmapUnlockBits(bm, &bd);
818 expect(Ok, stat);
821 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
822 expect(Ok, stat);
823 expect(0, color);
825 /* write-only */
826 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
827 expect(Ok, stat);
829 expect(0xdeadbeef, bits[2+3*WIDTH]);
830 bits[2+3*WIDTH] = 0x12345678;
832 if (stat == Ok) {
833 stat = GdipBitmapUnlockBits(bm, &bd);
834 expect(Ok, stat);
837 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
838 expect(Ok, stat);
839 expect(0x12345678, color);
841 bits[2+3*WIDTH] = 0;
843 /* read/write */
844 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
845 expect(Ok, stat);
847 expect(0x12345678, bits[2+3*WIDTH]);
848 bits[2+3*WIDTH] = 0xdeadbeef;
850 if (stat == Ok) {
851 stat = GdipBitmapUnlockBits(bm, &bd);
852 expect(Ok, stat);
855 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
856 expect(Ok, stat);
857 expect(0xdeadbeef, color);
859 stat = GdipDisposeImage((GpImage*)bm);
860 expect(Ok, stat);
863 struct BITMAPINFOWITHBITFIELDS
865 BITMAPINFOHEADER bmiHeader;
866 DWORD masks[3];
869 union BITMAPINFOUNION
871 BITMAPINFO bi;
872 struct BITMAPINFOWITHBITFIELDS bf;
875 static void test_GdipCreateBitmapFromHBITMAP(void)
877 GpBitmap* gpbm = NULL;
878 HBITMAP hbm = NULL;
879 HPALETTE hpal = NULL;
880 GpStatus stat;
881 BYTE buff[1000];
882 LOGPALETTE* LogPal = NULL;
883 REAL width, height;
884 const REAL WIDTH1 = 5;
885 const REAL HEIGHT1 = 15;
886 const REAL WIDTH2 = 10;
887 const REAL HEIGHT2 = 20;
888 HDC hdc;
889 union BITMAPINFOUNION bmi;
890 BYTE *bits;
891 PixelFormat format;
893 stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
894 expect(InvalidParameter, stat);
896 hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
897 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
898 expect(InvalidParameter, stat);
900 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
901 expect(Ok, stat);
902 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
903 expectf(WIDTH1, width);
904 expectf(HEIGHT1, height);
905 if (stat == Ok)
906 GdipDisposeImage((GpImage*)gpbm);
907 DeleteObject(hbm);
909 memset(buff, 0, sizeof(buff));
910 hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
911 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
912 expect(Ok, stat);
913 /* raw format */
914 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
916 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
917 expectf(WIDTH2, width);
918 expectf(HEIGHT2, height);
919 if (stat == Ok)
920 GdipDisposeImage((GpImage*)gpbm);
921 DeleteObject(hbm);
923 hdc = CreateCompatibleDC(0);
924 ok(hdc != NULL, "CreateCompatibleDC failed\n");
925 bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
926 bmi.bi.bmiHeader.biHeight = HEIGHT1;
927 bmi.bi.bmiHeader.biWidth = WIDTH1;
928 bmi.bi.bmiHeader.biBitCount = 24;
929 bmi.bi.bmiHeader.biPlanes = 1;
930 bmi.bi.bmiHeader.biCompression = BI_RGB;
931 bmi.bi.bmiHeader.biClrUsed = 0;
933 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
934 ok(hbm != NULL, "CreateDIBSection failed\n");
936 bits[0] = 0;
938 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
939 expect(Ok, stat);
940 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
941 expectf(WIDTH1, width);
942 expectf(HEIGHT1, height);
943 if (stat == Ok)
945 /* test whether writing to the bitmap affects the original */
946 stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
947 expect(Ok, stat);
949 expect(0, bits[0]);
951 GdipDisposeImage((GpImage*)gpbm);
954 LogPal = GdipAlloc(sizeof(LOGPALETTE));
955 ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
956 LogPal->palVersion = 0x300;
957 LogPal->palNumEntries = 1;
958 hpal = CreatePalette(LogPal);
959 ok(hpal != NULL, "CreatePalette failed\n");
960 GdipFree(LogPal);
962 stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
963 expect(Ok, stat);
965 if (stat == Ok)
966 GdipDisposeImage((GpImage*)gpbm);
968 DeleteObject(hpal);
969 DeleteObject(hbm);
971 /* 16-bit 555 dib, rgb */
972 bmi.bi.bmiHeader.biBitCount = 16;
973 bmi.bi.bmiHeader.biCompression = BI_RGB;
975 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
976 ok(hbm != NULL, "CreateDIBSection failed\n");
978 bits[0] = 0;
980 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
981 expect(Ok, stat);
983 if (stat == Ok)
985 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
986 expect(Ok, stat);
987 expectf(WIDTH1, width);
988 expectf(HEIGHT1, height);
990 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
991 expect(Ok, stat);
992 expect(PixelFormat16bppRGB555, format);
994 GdipDisposeImage((GpImage*)gpbm);
996 DeleteObject(hbm);
998 /* 16-bit 555 dib, with bitfields */
999 bmi.bi.bmiHeader.biSize = sizeof(bmi);
1000 bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
1001 bmi.bf.masks[0] = 0x7c00;
1002 bmi.bf.masks[1] = 0x3e0;
1003 bmi.bf.masks[2] = 0x1f;
1005 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1006 ok(hbm != NULL, "CreateDIBSection failed\n");
1008 bits[0] = 0;
1010 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1011 expect(Ok, stat);
1013 if (stat == Ok)
1015 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1016 expect(Ok, stat);
1017 expectf(WIDTH1, width);
1018 expectf(HEIGHT1, height);
1020 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1021 expect(Ok, stat);
1022 expect(PixelFormat16bppRGB555, format);
1024 GdipDisposeImage((GpImage*)gpbm);
1026 DeleteObject(hbm);
1028 /* 16-bit 565 dib, with bitfields */
1029 bmi.bf.masks[0] = 0xf800;
1030 bmi.bf.masks[1] = 0x7e0;
1031 bmi.bf.masks[2] = 0x1f;
1033 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1034 ok(hbm != NULL, "CreateDIBSection failed\n");
1036 bits[0] = 0;
1038 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1039 expect(Ok, stat);
1041 if (stat == Ok)
1043 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1044 expect(Ok, stat);
1045 expectf(WIDTH1, width);
1046 expectf(HEIGHT1, height);
1048 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1049 expect(Ok, stat);
1050 expect(PixelFormat16bppRGB565, format);
1052 GdipDisposeImage((GpImage*)gpbm);
1054 DeleteObject(hbm);
1056 DeleteDC(hdc);
1059 static void test_GdipGetImageFlags(void)
1061 GpImage *img;
1062 GpStatus stat;
1063 UINT flags;
1065 img = (GpImage*)0xdeadbeef;
1067 stat = GdipGetImageFlags(NULL, NULL);
1068 expect(InvalidParameter, stat);
1070 stat = GdipGetImageFlags(NULL, &flags);
1071 expect(InvalidParameter, stat);
1073 stat = GdipGetImageFlags(img, NULL);
1074 expect(InvalidParameter, stat);
1076 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1077 expect(Ok, stat);
1078 stat = GdipGetImageFlags(img, &flags);
1079 expect(Ok, stat);
1080 expect(ImageFlagsHasAlpha, flags);
1081 GdipDisposeImage(img);
1083 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1084 expect(Ok, stat);
1085 stat = GdipGetImageFlags(img, &flags);
1086 expect(Ok, stat);
1087 expect(ImageFlagsHasAlpha, flags);
1088 GdipDisposeImage(img);
1090 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1091 expect(Ok, stat);
1092 stat = GdipGetImageFlags(img, &flags);
1093 expect(Ok, stat);
1094 expect(ImageFlagsHasAlpha, flags);
1095 GdipDisposeImage(img);
1097 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1098 expect(Ok, stat);
1099 stat = GdipGetImageFlags(img, &flags);
1100 expect(Ok, stat);
1101 expect(ImageFlagsNone, flags);
1102 GdipDisposeImage(img);
1104 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1105 expect(Ok, stat);
1106 stat = GdipGetImageFlags(img, &flags);
1107 expect(Ok, stat);
1108 expect(ImageFlagsNone, flags);
1109 GdipDisposeImage(img);
1111 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1112 expect(Ok, stat);
1113 stat = GdipGetImageFlags(img, &flags);
1114 expect(Ok, stat);
1115 expect(ImageFlagsNone, flags);
1116 GdipDisposeImage(img);
1118 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1119 expect(Ok, stat);
1120 stat = GdipGetImageFlags(img, &flags);
1121 expect(Ok, stat);
1122 expect(ImageFlagsHasAlpha, flags);
1123 GdipDisposeImage(img);
1125 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1126 expect(Ok, stat);
1127 stat = GdipGetImageFlags(img, &flags);
1128 expect(Ok, stat);
1129 expect(ImageFlagsNone, flags);
1130 GdipDisposeImage(img);
1132 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1133 expect(Ok, stat);
1134 stat = GdipGetImageFlags(img, &flags);
1135 expect(Ok, stat);
1136 expect(ImageFlagsNone, flags);
1137 GdipDisposeImage(img);
1139 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1140 expect(Ok, stat);
1141 stat = GdipGetImageFlags(img, &flags);
1142 expect(Ok, stat);
1143 expect(ImageFlagsHasAlpha, flags);
1144 GdipDisposeImage(img);
1146 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1147 expect(Ok, stat);
1148 stat = GdipGetImageFlags(img, &flags);
1149 expect(Ok, stat);
1150 expect(ImageFlagsHasAlpha, flags);
1151 GdipDisposeImage(img);
1153 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1154 expect(Ok, stat);
1155 if (stat == Ok)
1157 stat = GdipGetImageFlags(img, &flags);
1158 expect(Ok, stat);
1159 expect(ImageFlagsNone, flags);
1160 GdipDisposeImage(img);
1163 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1164 expect(Ok, stat);
1165 if (stat == Ok)
1167 expect(Ok, stat);
1168 stat = GdipGetImageFlags(img, &flags);
1169 expect(Ok, stat);
1170 expect(ImageFlagsHasAlpha, flags);
1171 GdipDisposeImage(img);
1174 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1175 expect(Ok, stat);
1176 if (stat == Ok)
1178 expect(Ok, stat);
1179 stat = GdipGetImageFlags(img, &flags);
1180 expect(Ok, stat);
1181 expect(ImageFlagsHasAlpha, flags);
1182 GdipDisposeImage(img);
1186 static void test_GdipCloneImage(void)
1188 GpStatus stat;
1189 GpRectF rectF;
1190 GpUnit unit;
1191 GpBitmap *bm;
1192 GpImage *image_src, *image_dest = NULL;
1193 const INT WIDTH = 10, HEIGHT = 20;
1195 /* Create an image, clone it, delete the original, make sure the copy works */
1196 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1197 expect(Ok, stat);
1198 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1200 image_src = ((GpImage*)bm);
1201 stat = GdipCloneImage(image_src, &image_dest);
1202 expect(Ok, stat);
1203 expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1205 stat = GdipDisposeImage((GpImage*)bm);
1206 expect(Ok, stat);
1207 stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1208 expect(Ok, stat);
1210 /* Treat FP values carefully */
1211 expectf((REAL)WIDTH, rectF.Width);
1212 expectf((REAL)HEIGHT, rectF.Height);
1214 stat = GdipDisposeImage(image_dest);
1215 expect(Ok, stat);
1218 static void test_testcontrol(void)
1220 GpStatus stat;
1221 DWORD param;
1223 param = 0;
1224 stat = GdipTestControl(TestControlGetBuildNumber, &param);
1225 expect(Ok, stat);
1226 ok(param != 0, "Build number expected, got %u\n", param);
1229 static void test_fromhicon(void)
1231 static const BYTE bmp_bits[1024];
1232 HBITMAP hbmMask, hbmColor;
1233 ICONINFO info;
1234 HICON hIcon;
1235 GpStatus stat;
1236 GpBitmap *bitmap = NULL;
1237 UINT dim;
1238 ImageType type;
1239 PixelFormat format;
1241 /* NULL */
1242 stat = GdipCreateBitmapFromHICON(NULL, NULL);
1243 expect(InvalidParameter, stat);
1244 stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1245 expect(InvalidParameter, stat);
1247 /* color icon 1 bit */
1248 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1249 ok(hbmMask != 0, "CreateBitmap failed\n");
1250 hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1251 ok(hbmColor != 0, "CreateBitmap failed\n");
1252 info.fIcon = TRUE;
1253 info.xHotspot = 8;
1254 info.yHotspot = 8;
1255 info.hbmMask = hbmMask;
1256 info.hbmColor = hbmColor;
1257 hIcon = CreateIconIndirect(&info);
1258 ok(hIcon != 0, "CreateIconIndirect failed\n");
1259 DeleteObject(hbmMask);
1260 DeleteObject(hbmColor);
1262 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1263 ok(stat == Ok ||
1264 broken(stat == InvalidParameter), /* Win98 */
1265 "Expected Ok, got %.8x\n", stat);
1266 if(stat == Ok){
1267 /* check attributes */
1268 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1269 expect(Ok, stat);
1270 expect(16, dim);
1271 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1272 expect(Ok, stat);
1273 expect(16, dim);
1274 stat = GdipGetImageType((GpImage*)bitmap, &type);
1275 expect(Ok, stat);
1276 expect(ImageTypeBitmap, type);
1277 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1278 expect(Ok, stat);
1279 expect(PixelFormat32bppARGB, format);
1280 /* raw format */
1281 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1282 GdipDisposeImage((GpImage*)bitmap);
1284 DestroyIcon(hIcon);
1286 /* color icon 8 bpp */
1287 hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1288 ok(hbmMask != 0, "CreateBitmap failed\n");
1289 hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1290 ok(hbmColor != 0, "CreateBitmap failed\n");
1291 info.fIcon = TRUE;
1292 info.xHotspot = 8;
1293 info.yHotspot = 8;
1294 info.hbmMask = hbmMask;
1295 info.hbmColor = hbmColor;
1296 hIcon = CreateIconIndirect(&info);
1297 ok(hIcon != 0, "CreateIconIndirect failed\n");
1298 DeleteObject(hbmMask);
1299 DeleteObject(hbmColor);
1301 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1302 expect(Ok, stat);
1303 if(stat == Ok){
1304 /* check attributes */
1305 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1306 expect(Ok, stat);
1307 expect(16, dim);
1308 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1309 expect(Ok, stat);
1310 expect(16, dim);
1311 stat = GdipGetImageType((GpImage*)bitmap, &type);
1312 expect(Ok, stat);
1313 expect(ImageTypeBitmap, type);
1314 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1315 expect(Ok, stat);
1316 expect(PixelFormat32bppARGB, format);
1317 /* raw format */
1318 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1319 GdipDisposeImage((GpImage*)bitmap);
1321 DestroyIcon(hIcon);
1324 /* 1x1 pixel png */
1325 static const unsigned char pngimage[285] = {
1326 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1327 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1328 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1329 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1330 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1331 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1332 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1334 /* 1x1 pixel gif */
1335 static const unsigned char gifimage[35] = {
1336 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1337 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1338 0x01,0x00,0x3b
1340 /* 1x1 pixel transparent gif */
1341 static const unsigned char transparentgif[] = {
1342 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
1343 0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,
1344 0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
1346 /* 1x1 pixel bmp */
1347 static const unsigned char bmpimage[66] = {
1348 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1349 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1350 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1351 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1352 0x00,0x00
1354 /* 1x1 pixel jpg */
1355 static const unsigned char jpgimage[285] = {
1356 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1357 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1358 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1359 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1360 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1361 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1362 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1363 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1364 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1365 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1366 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1367 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1368 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1369 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1370 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1371 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1372 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1373 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1375 /* 1x1 pixel tiff */
1376 static const unsigned char tiffimage[] = {
1377 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1378 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1379 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1380 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1381 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1382 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1383 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1384 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1385 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1386 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1387 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1388 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1389 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1390 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1391 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1392 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1393 0x00,0x00,0x00,0x01
1395 /* 320x320 twip wmf */
1396 static const unsigned char wmfimage[180] = {
1397 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1398 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1399 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1400 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1401 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1402 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1403 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1404 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1405 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1406 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1407 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1408 0x00,0x00,0x00,0x00
1410 static void test_getrawformat(void)
1412 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE);
1413 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE);
1414 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE);
1415 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1416 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1417 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1420 static void test_loadwmf(void)
1422 LPSTREAM stream;
1423 HGLOBAL hglob;
1424 LPBYTE data;
1425 HRESULT hres;
1426 GpStatus stat;
1427 GpImage *img;
1428 GpRectF bounds;
1429 GpUnit unit;
1430 REAL res = 12345.0;
1431 MetafileHeader header;
1433 hglob = GlobalAlloc (0, sizeof(wmfimage));
1434 data = GlobalLock (hglob);
1435 memcpy(data, wmfimage, sizeof(wmfimage));
1436 GlobalUnlock(hglob); data = NULL;
1438 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1439 ok(hres == S_OK, "Failed to create a stream\n");
1440 if(hres != S_OK) return;
1442 stat = GdipLoadImageFromStream(stream, &img);
1443 ok(stat == Ok, "Failed to create a Bitmap\n");
1444 if(stat != Ok){
1445 IStream_Release(stream);
1446 return;
1449 IStream_Release(stream);
1451 stat = GdipGetImageBounds(img, &bounds, &unit);
1452 expect(Ok, stat);
1453 expect(UnitPixel, unit);
1454 expectf(0.0, bounds.X);
1455 expectf(0.0, bounds.Y);
1456 expectf(320.0, bounds.Width);
1457 expectf(320.0, bounds.Height);
1459 stat = GdipGetImageHorizontalResolution(img, &res);
1460 expect(Ok, stat);
1461 expectf(1440.0, res);
1463 stat = GdipGetImageVerticalResolution(img, &res);
1464 expect(Ok, stat);
1465 expectf(1440.0, res);
1467 memset(&header, 0, sizeof(header));
1468 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1469 expect(Ok, stat);
1470 if (stat == Ok)
1472 expect(MetafileTypeWmfPlaceable, header.Type);
1473 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1474 todo_wine expect(0x300, header.Version);
1475 expect(0, header.EmfPlusFlags);
1476 expectf(1440.0, header.DpiX);
1477 expectf(1440.0, header.DpiY);
1478 expect(0, header.X);
1479 expect(0, header.Y);
1480 expect(320, header.Width);
1481 expect(320, header.Height);
1482 expect(1, U(header).WmfHeader.mtType);
1483 expect(0, header.EmfPlusHeaderSize);
1484 expect(0, header.LogicalDpiX);
1485 expect(0, header.LogicalDpiY);
1488 GdipDisposeImage(img);
1491 static void test_createfromwmf(void)
1493 HMETAFILE hwmf;
1494 GpImage *img;
1495 GpStatus stat;
1496 GpRectF bounds;
1497 GpUnit unit;
1498 REAL res = 12345.0;
1499 MetafileHeader header;
1501 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1502 wmfimage+sizeof(WmfPlaceableFileHeader));
1503 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1505 stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1506 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1507 expect(Ok, stat);
1509 stat = GdipGetImageBounds(img, &bounds, &unit);
1510 expect(Ok, stat);
1511 expect(UnitPixel, unit);
1512 expectf(0.0, bounds.X);
1513 expectf(0.0, bounds.Y);
1514 expectf(320.0, bounds.Width);
1515 expectf(320.0, bounds.Height);
1517 stat = GdipGetImageHorizontalResolution(img, &res);
1518 expect(Ok, stat);
1519 expectf(1440.0, res);
1521 stat = GdipGetImageVerticalResolution(img, &res);
1522 expect(Ok, stat);
1523 expectf(1440.0, res);
1525 memset(&header, 0, sizeof(header));
1526 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1527 expect(Ok, stat);
1528 if (stat == Ok)
1530 expect(MetafileTypeWmfPlaceable, header.Type);
1531 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1532 todo_wine expect(0x300, header.Version);
1533 expect(0, header.EmfPlusFlags);
1534 expectf(1440.0, header.DpiX);
1535 expectf(1440.0, header.DpiY);
1536 expect(0, header.X);
1537 expect(0, header.Y);
1538 expect(320, header.Width);
1539 expect(320, header.Height);
1540 expect(1, U(header).WmfHeader.mtType);
1541 expect(0, header.EmfPlusHeaderSize);
1542 expect(0, header.LogicalDpiX);
1543 expect(0, header.LogicalDpiY);
1546 GdipDisposeImage(img);
1549 static void test_createfromwmf_noplaceable(void)
1551 HMETAFILE hwmf;
1552 GpImage *img;
1553 GpStatus stat;
1555 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1556 wmfimage+sizeof(WmfPlaceableFileHeader));
1557 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1559 stat = GdipCreateMetafileFromWmf(hwmf, TRUE, NULL, (GpMetafile**)&img);
1560 expect(Ok, stat);
1562 GdipDisposeImage(img);
1565 static void test_resolution(void)
1567 GpStatus stat;
1568 GpBitmap *bitmap;
1569 GpGraphics *graphics;
1570 REAL res=-1.0;
1571 HDC screendc;
1572 int screenxres, screenyres;
1574 /* create Bitmap */
1575 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1576 expect(Ok, stat);
1578 /* test invalid values */
1579 stat = GdipGetImageHorizontalResolution(NULL, &res);
1580 expect(InvalidParameter, stat);
1582 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1583 expect(InvalidParameter, stat);
1585 stat = GdipGetImageVerticalResolution(NULL, &res);
1586 expect(InvalidParameter, stat);
1588 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1589 expect(InvalidParameter, stat);
1591 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1592 expect(InvalidParameter, stat);
1594 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1595 expect(InvalidParameter, stat);
1597 /* defaults to screen resolution */
1598 screendc = GetDC(0);
1600 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1601 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1603 ReleaseDC(0, screendc);
1605 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1606 expect(Ok, stat);
1607 expectf((REAL)screenxres, res);
1609 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1610 expect(Ok, stat);
1611 expectf((REAL)screenyres, res);
1613 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1614 expect(Ok, stat);
1615 stat = GdipGetDpiX(graphics, &res);
1616 expect(Ok, stat);
1617 expectf((REAL)screenxres, res);
1618 stat = GdipGetDpiY(graphics, &res);
1619 expect(Ok, stat);
1620 expectf((REAL)screenyres, res);
1622 /* test changing the resolution */
1623 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1624 expect(Ok, stat);
1626 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1627 expect(Ok, stat);
1628 expectf(screenxres*2.0, res);
1630 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1631 expect(Ok, stat);
1632 expectf(screenyres*3.0, res);
1634 stat = GdipGetDpiX(graphics, &res);
1635 expect(Ok, stat);
1636 expectf((REAL)screenxres, res);
1637 stat = GdipGetDpiY(graphics, &res);
1638 expect(Ok, stat);
1639 expectf((REAL)screenyres, res);
1641 stat = GdipDeleteGraphics(graphics);
1642 expect(Ok, stat);
1644 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1645 expect(Ok, stat);
1646 stat = GdipGetDpiX(graphics, &res);
1647 expect(Ok, stat);
1648 expectf(screenxres*2.0, res);
1649 stat = GdipGetDpiY(graphics, &res);
1650 expect(Ok, stat);
1651 expectf(screenyres*3.0, res);
1652 stat = GdipDeleteGraphics(graphics);
1653 expect(Ok, stat);
1655 stat = GdipDisposeImage((GpImage*)bitmap);
1656 expect(Ok, stat);
1659 static void test_createhbitmap(void)
1661 GpStatus stat;
1662 GpBitmap *bitmap;
1663 HBITMAP hbitmap, oldhbitmap;
1664 BITMAP bm;
1665 int ret;
1666 HDC hdc;
1667 COLORREF pixel;
1668 BYTE bits[640];
1669 BitmapData lockeddata;
1671 memset(bits, 0x68, 640);
1673 /* create Bitmap */
1674 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1675 expect(Ok, stat);
1677 /* test NULL values */
1678 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1679 expect(InvalidParameter, stat);
1681 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1682 expect(InvalidParameter, stat);
1684 /* create HBITMAP */
1685 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1686 expect(Ok, stat);
1688 if (stat == Ok)
1690 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1691 expect(sizeof(BITMAP), ret);
1693 expect(0, bm.bmType);
1694 expect(10, bm.bmWidth);
1695 expect(20, bm.bmHeight);
1696 expect(40, bm.bmWidthBytes);
1697 expect(1, bm.bmPlanes);
1698 expect(32, bm.bmBitsPixel);
1699 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1701 if (bm.bmBits)
1703 DWORD val = *(DWORD*)bm.bmBits;
1704 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1707 hdc = CreateCompatibleDC(NULL);
1709 oldhbitmap = SelectObject(hdc, hbitmap);
1710 pixel = GetPixel(hdc, 5, 5);
1711 SelectObject(hdc, oldhbitmap);
1713 DeleteDC(hdc);
1715 expect(0x686868, pixel);
1717 DeleteObject(hbitmap);
1720 stat = GdipDisposeImage((GpImage*)bitmap);
1721 expect(Ok, stat);
1723 /* make (1,0) have no alpha and (2,0) a different blue value. */
1724 bits[7] = 0x00;
1725 bits[8] = 0x40;
1727 /* create alpha Bitmap */
1728 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1729 expect(Ok, stat);
1731 /* create HBITMAP */
1732 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1733 expect(Ok, stat);
1735 if (stat == Ok)
1737 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1738 expect(sizeof(BITMAP), ret);
1740 expect(0, bm.bmType);
1741 expect(8, bm.bmWidth);
1742 expect(20, bm.bmHeight);
1743 expect(32, bm.bmWidthBytes);
1744 expect(1, bm.bmPlanes);
1745 expect(32, bm.bmBitsPixel);
1746 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1748 if (bm.bmBits)
1750 DWORD val = *(DWORD*)bm.bmBits;
1751 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1752 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1753 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1756 hdc = CreateCompatibleDC(NULL);
1758 oldhbitmap = SelectObject(hdc, hbitmap);
1759 pixel = GetPixel(hdc, 5, 5);
1760 expect(0x2a2a2a, pixel);
1761 pixel = GetPixel(hdc, 1, 0);
1762 expect(0x0, pixel);
1764 SelectObject(hdc, oldhbitmap);
1766 DeleteDC(hdc);
1769 DeleteObject(hbitmap);
1772 /* create HBITMAP with bkgnd colour */
1773 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1774 expect(Ok, stat);
1776 if (stat == Ok)
1778 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1779 expect(sizeof(BITMAP), ret);
1781 expect(0, bm.bmType);
1782 expect(8, bm.bmWidth);
1783 expect(20, bm.bmHeight);
1784 expect(32, bm.bmWidthBytes);
1785 expect(1, bm.bmPlanes);
1786 expect(32, bm.bmBitsPixel);
1787 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1789 if (bm.bmBits)
1791 DWORD val = *(DWORD*)bm.bmBits;
1792 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1793 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1794 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1797 hdc = CreateCompatibleDC(NULL);
1799 oldhbitmap = SelectObject(hdc, hbitmap);
1800 pixel = GetPixel(hdc, 5, 5);
1801 expect(0xc12ac1, pixel);
1802 pixel = GetPixel(hdc, 1, 0);
1803 expect(0xff00ff, pixel);
1804 pixel = GetPixel(hdc, 2, 0);
1805 expect(0xb12ac1, pixel);
1807 SelectObject(hdc, oldhbitmap);
1808 DeleteDC(hdc);
1809 DeleteObject(hbitmap);
1812 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1813 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1814 expect(Ok, stat);
1816 if (stat == Ok)
1818 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1819 expect(sizeof(BITMAP), ret);
1821 expect(0, bm.bmType);
1822 expect(8, bm.bmWidth);
1823 expect(20, bm.bmHeight);
1824 expect(32, bm.bmWidthBytes);
1825 expect(1, bm.bmPlanes);
1826 expect(32, bm.bmBitsPixel);
1827 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1829 if (bm.bmBits)
1831 DWORD val = *(DWORD*)bm.bmBits;
1832 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1833 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1834 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1837 hdc = CreateCompatibleDC(NULL);
1839 oldhbitmap = SelectObject(hdc, hbitmap);
1840 pixel = GetPixel(hdc, 5, 5);
1841 expect(0xc12ac1, pixel);
1842 pixel = GetPixel(hdc, 1, 0);
1843 expect(0xff00ff, pixel);
1844 pixel = GetPixel(hdc, 2, 0);
1845 expect(0xb12ac1, pixel);
1847 SelectObject(hdc, oldhbitmap);
1848 DeleteDC(hdc);
1849 DeleteObject(hbitmap);
1852 stat = GdipDisposeImage((GpImage*)bitmap);
1853 expect(Ok, stat);
1855 /* create HBITMAP from locked data */
1856 memset(bits, 0x68, 640);
1857 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1858 expect(Ok, stat);
1860 memset(&lockeddata, 0, sizeof(lockeddata));
1861 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite,
1862 PixelFormat32bppRGB, &lockeddata);
1863 expect(Ok, stat);
1864 ((DWORD*)lockeddata.Scan0)[0] = 0xff242424;
1865 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1866 expect(Ok, stat);
1867 stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
1868 expect(Ok, stat);
1869 stat = GdipDisposeImage((GpImage*)bitmap);
1870 expect(Ok, stat);
1872 hdc = CreateCompatibleDC(NULL);
1873 oldhbitmap = SelectObject(hdc, hbitmap);
1874 pixel = GetPixel(hdc, 0, 0);
1875 expect(0x686868, pixel);
1876 SelectObject(hdc, oldhbitmap);
1877 DeleteDC(hdc);
1880 static void test_getthumbnail(void)
1882 GpStatus stat;
1883 GpImage *bitmap1, *bitmap2;
1884 UINT width, height;
1886 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1887 expect(InvalidParameter, stat);
1889 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1890 expect(Ok, stat);
1892 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1893 expect(InvalidParameter, stat);
1895 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1896 expect(Ok, stat);
1898 if (stat == Ok)
1900 stat = GdipGetImageWidth(bitmap2, &width);
1901 expect(Ok, stat);
1902 expect(120, width);
1904 stat = GdipGetImageHeight(bitmap2, &height);
1905 expect(Ok, stat);
1906 expect(120, height);
1908 GdipDisposeImage(bitmap2);
1911 GdipDisposeImage(bitmap1);
1914 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1915 expect(Ok, stat);
1917 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1918 expect(Ok, stat);
1920 if (stat == Ok)
1922 stat = GdipGetImageWidth(bitmap2, &width);
1923 expect(Ok, stat);
1924 expect(32, width);
1926 stat = GdipGetImageHeight(bitmap2, &height);
1927 expect(Ok, stat);
1928 expect(32, height);
1930 GdipDisposeImage(bitmap2);
1933 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1934 expect(Ok, stat);
1936 if (stat == Ok)
1938 stat = GdipGetImageWidth(bitmap2, &width);
1939 expect(Ok, stat);
1940 expect(120, width);
1942 stat = GdipGetImageHeight(bitmap2, &height);
1943 expect(Ok, stat);
1944 expect(120, height);
1946 GdipDisposeImage(bitmap2);
1949 GdipDisposeImage(bitmap1);
1952 static void test_getsetpixel(void)
1954 GpStatus stat;
1955 GpBitmap *bitmap;
1956 ARGB color;
1957 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1958 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1960 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1961 expect(Ok, stat);
1963 /* null parameters */
1964 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1965 expect(InvalidParameter, stat);
1967 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1968 expect(InvalidParameter, stat);
1970 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1971 expect(InvalidParameter, stat);
1973 /* out of bounds */
1974 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1975 expect(InvalidParameter, stat);
1977 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1978 expect(InvalidParameter, stat);
1980 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1981 ok(stat == InvalidParameter ||
1982 broken(stat == Ok), /* Older gdiplus */
1983 "Expected InvalidParameter, got %.8x\n", stat);
1985 if (0) /* crashes some gdiplus implementations */
1987 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1988 ok(stat == InvalidParameter ||
1989 broken(stat == Ok), /* Older gdiplus */
1990 "Expected InvalidParameter, got %.8x\n", stat);
1993 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1994 expect(InvalidParameter, stat);
1996 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1997 expect(InvalidParameter, stat);
1999 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
2000 expect(InvalidParameter, stat);
2002 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
2003 expect(InvalidParameter, stat);
2005 /* valid use */
2006 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2007 expect(Ok, stat);
2008 expect(0xffffffff, color);
2010 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2011 expect(Ok, stat);
2012 expect(0xff0000ff, color);
2014 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
2015 expect(Ok, stat);
2017 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
2018 expect(Ok, stat);
2020 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2021 expect(Ok, stat);
2022 expect(0xff676869, color);
2024 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2025 expect(Ok, stat);
2026 expect(0xff474849, color);
2028 stat = GdipDisposeImage((GpImage*)bitmap);
2029 expect(Ok, stat);
2032 static void check_halftone_palette(ColorPalette *palette)
2034 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
2035 UINT i;
2037 for (i=0; i<palette->Count; i++)
2039 ARGB expected=0xff000000;
2040 if (i<8)
2042 if (i&1) expected |= 0x800000;
2043 if (i&2) expected |= 0x8000;
2044 if (i&4) expected |= 0x80;
2046 else if (i == 8)
2048 expected = 0xffc0c0c0;
2050 else if (i < 16)
2052 if (i&1) expected |= 0xff0000;
2053 if (i&2) expected |= 0xff00;
2054 if (i&4) expected |= 0xff;
2056 else if (i < 40)
2058 expected = 0x00000000;
2060 else
2062 expected |= halftone_values[(i-40)%6];
2063 expected |= halftone_values[((i-40)/6)%6] << 8;
2064 expected |= halftone_values[((i-40)/36)%6] << 16;
2066 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2067 expected, palette->Entries[i], i, palette->Count);
2071 static void test_palette(void)
2073 GpStatus stat;
2074 GpBitmap *bitmap;
2075 INT size;
2076 BYTE buffer[1040];
2077 ColorPalette *palette=(ColorPalette*)buffer;
2078 ARGB *entries = palette->Entries;
2079 ARGB color=0;
2081 /* test initial palette from non-indexed bitmap */
2082 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2083 expect(Ok, stat);
2085 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2086 expect(Ok, stat);
2087 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2089 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2090 expect(Ok, stat);
2091 expect(0, palette->Count);
2093 /* test setting palette on not-indexed bitmap */
2094 palette->Count = 3;
2096 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2097 expect(Ok, stat);
2099 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2100 expect(Ok, stat);
2101 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2103 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2104 expect(Ok, stat);
2105 expect(3, palette->Count);
2107 GdipDisposeImage((GpImage*)bitmap);
2109 /* test initial palette on 1-bit bitmap */
2110 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2111 expect(Ok, stat);
2113 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2114 expect(Ok, stat);
2115 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2117 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2118 expect(Ok, stat);
2119 expect(PaletteFlagsGrayScale, palette->Flags);
2120 expect(2, palette->Count);
2122 expect(0xff000000, entries[0]);
2123 expect(0xffffffff, entries[1]);
2125 /* test getting/setting pixels */
2126 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2127 expect(Ok, stat);
2128 expect(0xff000000, color);
2130 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2131 ok((stat == Ok) ||
2132 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2134 if (stat == Ok)
2136 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2137 expect(Ok, stat);
2138 expect(0xffffffff, color);
2141 GdipDisposeImage((GpImage*)bitmap);
2143 /* test initial palette on 4-bit bitmap */
2144 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2145 expect(Ok, stat);
2147 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2148 expect(Ok, stat);
2149 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2151 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2152 expect(Ok, stat);
2153 expect(0, palette->Flags);
2154 expect(16, palette->Count);
2156 check_halftone_palette(palette);
2158 /* test getting/setting pixels */
2159 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2160 expect(Ok, stat);
2161 expect(0xff000000, color);
2163 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2164 ok((stat == Ok) ||
2165 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2167 if (stat == Ok)
2169 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2170 expect(Ok, stat);
2171 expect(0xffff00ff, color);
2174 GdipDisposeImage((GpImage*)bitmap);
2176 /* test initial palette on 8-bit bitmap */
2177 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2178 expect(Ok, stat);
2180 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2181 expect(Ok, stat);
2182 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2184 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2185 expect(Ok, stat);
2186 expect(PaletteFlagsHalftone, palette->Flags);
2187 expect(256, palette->Count);
2189 check_halftone_palette(palette);
2191 /* test getting/setting pixels */
2192 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2193 expect(Ok, stat);
2194 expect(0xff000000, color);
2196 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2197 ok((stat == Ok) ||
2198 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2200 if (stat == Ok)
2202 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2203 expect(Ok, stat);
2204 expect(0xffcccccc, color);
2207 /* test setting/getting a different palette */
2208 entries[1] = 0xffcccccc;
2210 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2211 expect(Ok, stat);
2213 entries[1] = 0;
2215 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2216 expect(Ok, stat);
2217 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2219 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2220 expect(Ok, stat);
2221 expect(PaletteFlagsHalftone, palette->Flags);
2222 expect(256, palette->Count);
2223 expect(0xffcccccc, entries[1]);
2225 /* test count < 256 */
2226 palette->Flags = 12345;
2227 palette->Count = 3;
2229 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2230 expect(Ok, stat);
2232 entries[1] = 0;
2233 entries[3] = 0xdeadbeef;
2235 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2236 expect(Ok, stat);
2237 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2239 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2240 expect(Ok, stat);
2241 expect(12345, palette->Flags);
2242 expect(3, palette->Count);
2243 expect(0xffcccccc, entries[1]);
2244 expect(0xdeadbeef, entries[3]);
2246 /* test count > 256 */
2247 palette->Count = 257;
2249 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2250 ok(stat == InvalidParameter ||
2251 broken(stat == Ok), /* Old gdiplus behavior */
2252 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2254 GdipDisposeImage((GpImage*)bitmap);
2257 static void test_colormatrix(void)
2259 GpStatus stat;
2260 ColorMatrix colormatrix, graymatrix;
2261 GpImageAttributes *imageattr;
2262 const ColorMatrix identity = {{
2263 {1.0,0.0,0.0,0.0,0.0},
2264 {0.0,1.0,0.0,0.0,0.0},
2265 {0.0,0.0,1.0,0.0,0.0},
2266 {0.0,0.0,0.0,1.0,0.0},
2267 {0.0,0.0,0.0,0.0,1.0}}};
2268 const ColorMatrix double_red = {{
2269 {2.0,0.0,0.0,0.0,0.0},
2270 {0.0,1.0,0.0,0.0,0.0},
2271 {0.0,0.0,1.0,0.0,0.0},
2272 {0.0,0.0,0.0,1.0,0.0},
2273 {0.0,0.0,0.0,0.0,1.0}}};
2274 const ColorMatrix asymmetric = {{
2275 {0.0,1.0,0.0,0.0,0.0},
2276 {0.0,0.0,1.0,0.0,0.0},
2277 {0.0,0.0,0.0,1.0,0.0},
2278 {1.0,0.0,0.0,0.0,0.0},
2279 {0.0,0.0,0.0,0.0,1.0}}};
2280 GpBitmap *bitmap1, *bitmap2;
2281 GpGraphics *graphics;
2282 ARGB color;
2284 colormatrix = identity;
2285 graymatrix = identity;
2287 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2288 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2289 expect(InvalidParameter, stat);
2291 stat = GdipCreateImageAttributes(&imageattr);
2292 expect(Ok, stat);
2294 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2295 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2296 expect(Ok, stat);
2298 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2299 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2300 expect(InvalidParameter, stat);
2302 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2303 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2304 expect(Ok, stat);
2306 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2307 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2308 expect(Ok, stat);
2310 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2311 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2312 expect(InvalidParameter, stat);
2314 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2315 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2316 expect(Ok, stat);
2318 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2319 TRUE, &colormatrix, &graymatrix, 3);
2320 expect(InvalidParameter, stat);
2322 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2323 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2324 expect(InvalidParameter, stat);
2326 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2327 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2328 expect(InvalidParameter, stat);
2330 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2331 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2332 expect(Ok, stat);
2334 /* Drawing a bitmap transforms the colors */
2335 colormatrix = double_red;
2336 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2337 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2338 expect(Ok, stat);
2340 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2341 expect(Ok, stat);
2343 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2344 expect(Ok, stat);
2346 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2347 expect(Ok, stat);
2349 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2350 expect(Ok, stat);
2352 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2353 UnitPixel, imageattr, NULL, NULL);
2354 expect(Ok, stat);
2356 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2357 expect(Ok, stat);
2358 expect(0xff80ccee, color);
2360 colormatrix = asymmetric;
2361 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2362 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2363 expect(Ok, stat);
2365 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2366 expect(Ok, stat);
2368 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2369 UnitPixel, imageattr, NULL, NULL);
2370 expect(Ok, stat);
2372 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2373 expect(Ok, stat);
2374 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2376 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2377 expect(Ok, stat);
2379 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2380 UnitPixel, imageattr, NULL, NULL);
2381 expect(Ok, stat);
2383 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2384 expect(Ok, stat);
2385 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2387 GdipDeleteGraphics(graphics);
2388 GdipDisposeImage((GpImage*)bitmap1);
2389 GdipDisposeImage((GpImage*)bitmap2);
2390 GdipDisposeImageAttributes(imageattr);
2393 static void test_gamma(void)
2395 GpStatus stat;
2396 GpImageAttributes *imageattr;
2397 GpBitmap *bitmap1, *bitmap2;
2398 GpGraphics *graphics;
2399 ARGB color;
2401 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2402 expect(InvalidParameter, stat);
2404 stat = GdipCreateImageAttributes(&imageattr);
2405 expect(Ok, stat);
2407 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2408 expect(Ok, stat);
2410 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2411 expect(InvalidParameter, stat);
2413 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2414 expect(InvalidParameter, stat);
2416 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2417 expect(InvalidParameter, stat);
2419 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2420 expect(Ok, stat);
2422 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2423 expect(Ok, stat);
2425 /* Drawing a bitmap transforms the colors */
2426 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2427 expect(Ok, stat);
2429 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2430 expect(Ok, stat);
2432 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2433 expect(Ok, stat);
2435 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2436 expect(Ok, stat);
2438 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2439 expect(Ok, stat);
2441 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2442 UnitPixel, imageattr, NULL, NULL);
2443 expect(Ok, stat);
2445 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2446 expect(Ok, stat);
2447 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2449 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2450 expect(Ok, stat);
2452 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2453 UnitPixel, imageattr, NULL, NULL);
2454 expect(Ok, stat);
2456 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2457 expect(Ok, stat);
2458 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2460 GdipDeleteGraphics(graphics);
2461 GdipDisposeImage((GpImage*)bitmap1);
2462 GdipDisposeImage((GpImage*)bitmap2);
2463 GdipDisposeImageAttributes(imageattr);
2466 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2467 static const unsigned char gifanimation[72] = {
2468 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2469 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2470 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2471 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2472 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2475 /* Generated with ImageMagick:
2476 * convert -transparent black -delay 100 -size 8x2 xc:black \
2477 * -dispose none -page +0+0 -size 2x2 xc:red \
2478 * -dispose background -page +2+0 -size 2x2 xc:blue \
2479 * -dispose previous -page +4+0 -size 2x2 xc:green \
2480 * -dispose undefined -page +6+0 -size 2x2 xc:gray \
2481 * test.gif
2483 static const unsigned char gifanimation2[] = {
2484 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2485 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2486 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2487 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2488 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2489 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2490 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2491 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2492 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2493 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2494 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2495 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2496 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2497 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2498 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2499 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2500 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2501 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2502 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2503 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2504 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2505 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2506 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2507 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2508 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2509 0x3b
2512 static ARGB gifanimation2_pixels[5][4] = {
2513 {0, 0, 0, 0},
2514 {0xffff0000, 0, 0, 0},
2515 {0xffff0000, 0xff0000ff, 0, 0},
2516 {0xffff0000, 0, 0xff008000, 0},
2517 {0xffff0000, 0, 0, 0xff7e7e7e}
2520 static void test_multiframegif(void)
2522 LPSTREAM stream;
2523 HGLOBAL hglob;
2524 LPBYTE data;
2525 HRESULT hres;
2526 GpStatus stat;
2527 GpBitmap *bmp;
2528 ARGB color;
2529 UINT count;
2530 GUID dimension;
2531 PixelFormat pixel_format;
2532 INT palette_size, i, j;
2533 char palette_buf[256];
2534 ColorPalette *palette;
2535 ARGB *palette_entries;
2537 /* Test frame functions with an animated GIF */
2538 hglob = GlobalAlloc (0, sizeof(gifanimation));
2539 data = GlobalLock (hglob);
2540 memcpy(data, gifanimation, sizeof(gifanimation));
2541 GlobalUnlock(hglob);
2543 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2544 ok(hres == S_OK, "Failed to create a stream\n");
2545 if(hres != S_OK) return;
2547 stat = GdipCreateBitmapFromStream(stream, &bmp);
2548 ok(stat == Ok, "Failed to create a Bitmap\n");
2549 if(stat != Ok){
2550 IStream_Release(stream);
2551 return;
2554 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2555 expect(Ok, stat);
2556 expect(PixelFormat32bppARGB, pixel_format);
2558 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2559 expect(Ok, stat);
2560 ok(palette_size == sizeof(ColorPalette) ||
2561 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2562 "palette_size = %d\n", palette_size);
2564 /* Bitmap starts at frame 0 */
2565 color = 0xdeadbeef;
2566 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2567 expect(Ok, stat);
2568 expect(0xffffffff, color);
2570 /* Check that we get correct metadata */
2571 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2572 expect(Ok, stat);
2573 expect(1, count);
2575 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2576 expect(Ok, stat);
2577 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2579 count = 12345;
2580 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2581 expect(Ok, stat);
2582 expect(2, count);
2584 /* SelectActiveFrame overwrites our current data */
2585 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2586 expect(Ok, stat);
2588 color = 0xdeadbeef;
2589 GdipBitmapGetPixel(bmp, 0, 0, &color);
2590 expect(Ok, stat);
2591 expect(0xff000000, color);
2593 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2594 expect(Ok, stat);
2596 color = 0xdeadbeef;
2597 GdipBitmapGetPixel(bmp, 0, 0, &color);
2598 expect(Ok, stat);
2599 expect(0xffffffff, color);
2601 /* Write over the image data */
2602 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2603 expect(Ok, stat);
2605 /* Switching to the same frame does not overwrite our changes */
2606 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2607 expect(Ok, stat);
2609 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2610 expect(Ok, stat);
2611 expect(0xff000000, color);
2613 /* But switching to another frame and back does */
2614 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2615 expect(Ok, stat);
2617 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2618 expect(Ok, stat);
2620 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2621 expect(Ok, stat);
2622 expect(0xffffffff, color);
2624 /* rotate/flip discards the information about other frames */
2625 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2626 expect(Ok, stat);
2628 count = 12345;
2629 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2630 expect(Ok, stat);
2631 expect(1, count);
2633 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2635 GdipDisposeImage((GpImage*)bmp);
2636 IStream_Release(stream);
2638 /* Test with a non-animated gif */
2639 hglob = GlobalAlloc (0, sizeof(gifimage));
2640 data = GlobalLock (hglob);
2641 memcpy(data, gifimage, sizeof(gifimage));
2642 GlobalUnlock(hglob);
2644 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2645 ok(hres == S_OK, "Failed to create a stream\n");
2646 if(hres != S_OK) return;
2648 stat = GdipCreateBitmapFromStream(stream, &bmp);
2649 ok(stat == Ok, "Failed to create a Bitmap\n");
2650 if(stat != Ok){
2651 IStream_Release(stream);
2652 return;
2655 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2656 expect(Ok, stat);
2657 expect(PixelFormat8bppIndexed, pixel_format);
2659 /* Check metadata */
2660 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2661 expect(Ok, stat);
2662 expect(1, count);
2664 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2665 expect(Ok, stat);
2666 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2668 count = 12345;
2669 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2670 expect(Ok, stat);
2671 expect(1, count);
2673 GdipDisposeImage((GpImage*)bmp);
2674 IStream_Release(stream);
2676 /* Test with a non-animated transparent gif */
2677 hglob = GlobalAlloc (0, sizeof(transparentgif));
2678 data = GlobalLock (hglob);
2679 memcpy(data, transparentgif, sizeof(transparentgif));
2680 GlobalUnlock(hglob);
2682 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2683 ok(hres == S_OK, "Failed to create a stream\n");
2685 stat = GdipCreateBitmapFromStream(stream, &bmp);
2686 IStream_Release(stream);
2687 ok(stat == Ok, "Failed to create a Bitmap\n");
2689 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2690 expect(Ok, stat);
2691 expect(PixelFormat8bppIndexed, pixel_format);
2693 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2694 expect(Ok, stat);
2695 expect(0, color);
2697 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2698 expect(Ok, stat);
2699 ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB),
2700 "palette_size = %d\n", palette_size);
2702 memset(palette_buf, 0xfe, sizeof(palette_buf));
2703 palette = (ColorPalette*)palette_buf;
2704 stat = GdipGetImagePalette((GpImage*)bmp, palette,
2705 sizeof(ColorPalette)+sizeof(ARGB));
2706 palette_entries = palette->Entries;
2707 expect(Ok, stat);
2708 expect(PaletteFlagsHasAlpha, palette->Flags);
2709 expect(2, palette->Count);
2710 expect(0, palette_entries[0]);
2711 expect(0xff000000, palette_entries[1]);
2713 count = 12345;
2714 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2715 expect(Ok, stat);
2716 expect(1, count);
2718 GdipDisposeImage((GpImage*)bmp);
2720 /* Test frame dispose methods */
2721 hglob = GlobalAlloc (0, sizeof(gifanimation2));
2722 data = GlobalLock (hglob);
2723 memcpy(data, gifanimation2, sizeof(gifanimation2));
2724 GlobalUnlock(hglob);
2726 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2727 ok(hres == S_OK, "Failed to create a stream\n");
2729 stat = GdipCreateBitmapFromStream(stream, &bmp);
2730 ok(stat == Ok, "Failed to create a Bitmap\n");
2731 IStream_Release(stream);
2733 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2734 expect(Ok, stat);
2735 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2737 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2738 expect(Ok, stat);
2739 expect(5, count);
2741 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2742 expect(Ok, stat);
2743 expect(0, color);
2745 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2746 expect(Ok, stat);
2747 stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2748 expect(Ok, stat);
2749 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2750 if(color != 0) {
2751 win_skip("broken animated gif support\n");
2752 GdipDisposeImage((GpImage*)bmp);
2753 return;
2756 for(i=0; i<6; i++) {
2757 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2758 expect(Ok, stat);
2760 for(j=0; j<4; j++) {
2761 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2762 expect(Ok, stat);
2763 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2767 GdipDisposeImage((GpImage*)bmp);
2770 static void test_rotateflip(void)
2772 GpImage *bitmap;
2773 GpStatus stat;
2774 BYTE bits[24];
2775 static const BYTE orig_bits[24] = {
2776 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2777 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2778 UINT width, height;
2779 ARGB color;
2781 memcpy(bits, orig_bits, sizeof(bits));
2782 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2783 expect(Ok, stat);
2785 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2786 expect(Ok, stat);
2788 stat = GdipGetImageWidth(bitmap, &width);
2789 expect(Ok, stat);
2790 stat = GdipGetImageHeight(bitmap, &height);
2791 expect(Ok, stat);
2792 expect(2, width);
2793 expect(3, height);
2795 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2796 expect(Ok, stat);
2797 expect(0xff00ffff, color);
2799 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2800 expect(Ok, stat);
2801 expect(0xffff0000, color);
2803 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2804 expect(Ok, stat);
2805 expect(0xffffff00, color);
2807 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2808 expect(Ok, stat);
2809 expect(0xff0000ff, color);
2811 expect(0, bits[0]);
2812 expect(0, bits[1]);
2813 expect(0xff, bits[2]);
2815 GdipDisposeImage(bitmap);
2817 memcpy(bits, orig_bits, sizeof(bits));
2818 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2819 expect(Ok, stat);
2821 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2822 expect(Ok, stat);
2824 stat = GdipGetImageWidth(bitmap, &width);
2825 expect(Ok, stat);
2826 stat = GdipGetImageHeight(bitmap, &height);
2827 expect(Ok, stat);
2828 expect(3, width);
2829 expect(2, height);
2831 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2832 expect(Ok, stat);
2833 expect(0xff0000ff, color);
2835 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2836 expect(Ok, stat);
2837 expect(0xffff0000, color);
2839 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2840 expect(Ok, stat);
2841 expect(0xffffff00, color);
2843 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2844 expect(Ok, stat);
2845 expect(0xff00ffff, color);
2847 expect(0, bits[0]);
2848 expect(0, bits[1]);
2849 expect(0xff, bits[2]);
2851 GdipDisposeImage(bitmap);
2853 memcpy(bits, orig_bits, sizeof(bits));
2854 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2855 expect(Ok, stat);
2857 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2858 expect(Ok, stat);
2860 stat = GdipGetImageWidth(bitmap, &width);
2861 expect(Ok, stat);
2862 stat = GdipGetImageHeight(bitmap, &height);
2863 expect(Ok, stat);
2864 expect(3, width);
2865 expect(2, height);
2867 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2868 expect(Ok, stat);
2869 expect(0xff00ffff, color);
2871 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2872 expect(Ok, stat);
2873 expect(0xffffff00, color);
2875 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2876 expect(Ok, stat);
2877 expect(0xffff0000, color);
2879 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2880 expect(Ok, stat);
2881 expect(0xff0000ff, color);
2883 expect(0, bits[0]);
2884 expect(0, bits[1]);
2885 expect(0xff, bits[2]);
2887 GdipDisposeImage(bitmap);
2890 static void test_remaptable(void)
2892 GpStatus stat;
2893 GpImageAttributes *imageattr;
2894 GpBitmap *bitmap1, *bitmap2;
2895 GpGraphics *graphics;
2896 ARGB color;
2897 ColorMap *map;
2899 map = GdipAlloc(sizeof(ColorMap));
2901 map->oldColor.Argb = 0xff00ff00;
2902 map->newColor.Argb = 0xffff00ff;
2904 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2905 expect(InvalidParameter, stat);
2907 stat = GdipCreateImageAttributes(&imageattr);
2908 expect(Ok, stat);
2910 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2911 expect(InvalidParameter, stat);
2913 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2914 expect(InvalidParameter, stat);
2916 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2917 expect(InvalidParameter, stat);
2919 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2920 expect(InvalidParameter, stat);
2922 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2923 expect(Ok, stat);
2925 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2926 expect(Ok, stat);
2928 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2929 expect(Ok, stat);
2931 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2932 expect(Ok, stat);
2934 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2935 expect(Ok, stat);
2937 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2938 expect(Ok, stat);
2940 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2941 UnitPixel, imageattr, NULL, NULL);
2942 expect(Ok, stat);
2944 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2945 expect(Ok, stat);
2946 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2948 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2949 expect(Ok, stat);
2951 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2952 UnitPixel, imageattr, NULL, NULL);
2953 expect(Ok, stat);
2955 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2956 expect(Ok, stat);
2957 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
2959 GdipDeleteGraphics(graphics);
2960 GdipDisposeImage((GpImage*)bitmap1);
2961 GdipDisposeImage((GpImage*)bitmap2);
2962 GdipDisposeImageAttributes(imageattr);
2963 GdipFree(map);
2966 static void test_colorkey(void)
2968 GpStatus stat;
2969 GpImageAttributes *imageattr;
2970 GpBitmap *bitmap1, *bitmap2;
2971 GpGraphics *graphics;
2972 ARGB color;
2974 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2975 expect(InvalidParameter, stat);
2977 stat = GdipCreateImageAttributes(&imageattr);
2978 expect(Ok, stat);
2980 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2981 expect(InvalidParameter, stat);
2983 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2984 expect(InvalidParameter, stat);
2986 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2987 expect(Ok, stat);
2989 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2990 expect(Ok, stat);
2992 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2993 expect(Ok, stat);
2995 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2996 expect(Ok, stat);
2998 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2999 expect(Ok, stat);
3001 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
3002 expect(Ok, stat);
3004 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
3005 expect(Ok, stat);
3007 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
3008 expect(Ok, stat);
3010 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3011 UnitPixel, imageattr, NULL, NULL);
3012 expect(Ok, stat);
3014 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3015 expect(Ok, stat);
3016 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3018 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3019 expect(Ok, stat);
3020 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3022 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3023 expect(Ok, stat);
3024 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3026 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3027 expect(Ok, stat);
3028 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3030 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3031 expect(Ok, stat);
3033 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3034 UnitPixel, imageattr, NULL, NULL);
3035 expect(Ok, stat);
3037 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3038 expect(Ok, stat);
3039 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
3041 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3042 expect(Ok, stat);
3043 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
3045 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3046 expect(Ok, stat);
3047 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
3049 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3050 expect(Ok, stat);
3051 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3054 GdipDeleteGraphics(graphics);
3055 GdipDisposeImage((GpImage*)bitmap1);
3056 GdipDisposeImage((GpImage*)bitmap2);
3057 GdipDisposeImageAttributes(imageattr);
3060 static void test_dispose(void)
3062 GpStatus stat;
3063 GpImage *image;
3064 char invalid_image[256];
3066 stat = GdipDisposeImage(NULL);
3067 expect(InvalidParameter, stat);
3069 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
3070 expect(Ok, stat);
3072 stat = GdipDisposeImage(image);
3073 expect(Ok, stat);
3075 stat = GdipDisposeImage(image);
3076 expect(ObjectBusy, stat);
3078 memset(invalid_image, 0, 256);
3079 stat = GdipDisposeImage((GpImage*)invalid_image);
3080 expect(ObjectBusy, stat);
3083 static LONG obj_refcount(void *obj)
3085 IUnknown_AddRef((IUnknown *)obj);
3086 return IUnknown_Release((IUnknown *)obj);
3089 static GpImage *load_image(const BYTE *image_data, UINT image_size)
3091 IStream *stream;
3092 HGLOBAL hmem;
3093 BYTE *data;
3094 HRESULT hr;
3095 GpStatus status;
3096 GpImage *image = NULL, *clone;
3097 ImageType image_type;
3098 LONG refcount, old_refcount;
3100 hmem = GlobalAlloc(0, image_size);
3101 data = GlobalLock(hmem);
3102 memcpy(data, image_data, image_size);
3103 GlobalUnlock(hmem);
3105 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3106 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3107 if (hr != S_OK) return NULL;
3109 refcount = obj_refcount(stream);
3110 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3112 status = GdipLoadImageFromStream(stream, &image);
3113 ok(status == Ok || broken(status == InvalidParameter), /* XP */
3114 "GdipLoadImageFromStream error %d\n", status);
3115 if (status != Ok)
3117 IStream_Release(stream);
3118 return NULL;
3121 status = GdipGetImageType(image, &image_type);
3122 ok(status == Ok, "GdipGetImageType error %d\n", status);
3124 refcount = obj_refcount(stream);
3125 if (image_type == ImageTypeBitmap)
3126 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3127 else
3128 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3129 old_refcount = refcount;
3131 status = GdipCloneImage(image, &clone);
3132 ok(status == Ok, "GdipCloneImage error %d\n", status);
3133 refcount = obj_refcount(stream);
3134 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3135 status = GdipDisposeImage(clone);
3136 ok(status == Ok, "GdipDisposeImage error %d\n", status);
3137 refcount = obj_refcount(stream);
3138 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3140 refcount = IStream_Release(stream);
3141 if (image_type == ImageTypeBitmap)
3142 ok(refcount >= 1, "expected stream refcount != 0\n");
3143 else
3144 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3146 return image;
3149 static void test_image_properties(void)
3151 static const struct test_data
3153 const BYTE *image_data;
3154 UINT image_size;
3155 ImageType image_type;
3156 UINT prop_count;
3157 UINT prop_count2; /* if win7 behaves differently */
3158 /* 1st property attributes */
3159 UINT prop_size;
3160 UINT prop_size2; /* if win7 behaves differently */
3161 UINT prop_id;
3162 UINT prop_id2; /* if win7 behaves differently */
3164 td[] =
3166 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3167 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3168 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3169 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3170 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3172 GpStatus status;
3173 GpImage *image;
3174 UINT prop_count, prop_size, i;
3175 PROPID prop_id[16] = { 0 };
3176 ImageType image_type;
3177 union
3179 PropertyItem data;
3180 char buf[256];
3181 } item;
3183 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3185 image = load_image(td[i].image_data, td[i].image_size);
3186 if (!image)
3188 trace("%u: failed to load image data\n", i);
3189 continue;
3192 status = GdipGetImageType(image, &image_type);
3193 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3194 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3195 i, td[i].image_type, image_type);
3197 status = GdipGetPropertyCount(image, &prop_count);
3198 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3199 todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage)
3200 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3201 " %u: expected property count %u or %u, got %u\n",
3202 i, td[i].prop_count, td[i].prop_count2, prop_count);
3204 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3205 expect(InvalidParameter, status);
3206 status = GdipGetPropertyItemSize(image, 0, NULL);
3207 expect(InvalidParameter, status);
3208 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3209 if (image_type == ImageTypeMetafile)
3210 expect(NotImplemented, status);
3211 else
3212 expect(PropertyNotFound, status);
3214 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3215 expect(InvalidParameter, status);
3216 status = GdipGetPropertyItem(image, 0, 0, NULL);
3217 expect(InvalidParameter, status);
3218 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3219 if (image_type == ImageTypeMetafile)
3220 expect(NotImplemented, status);
3221 else
3222 expect(PropertyNotFound, status);
3224 /* FIXME: remove once Wine is fixed */
3225 if (td[i].prop_count != prop_count)
3227 GdipDisposeImage(image);
3228 continue;
3231 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3232 expect(InvalidParameter, status);
3233 status = GdipGetPropertyIdList(image, prop_count, NULL);
3234 expect(InvalidParameter, status);
3235 status = GdipGetPropertyIdList(image, 0, prop_id);
3236 if (image_type == ImageTypeMetafile)
3237 expect(NotImplemented, status);
3238 else if (prop_count == 0)
3239 expect(Ok, status);
3240 else
3241 expect(InvalidParameter, status);
3242 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3243 if (image_type == ImageTypeMetafile)
3244 expect(NotImplemented, status);
3245 else
3246 expect(InvalidParameter, status);
3247 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3248 if (image_type == ImageTypeMetafile)
3249 expect(NotImplemented, status);
3250 else
3251 expect(InvalidParameter, status);
3252 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3253 if (image_type == ImageTypeMetafile)
3254 expect(NotImplemented, status);
3255 else
3257 expect(Ok, status);
3258 if (prop_count != 0)
3259 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3260 " %u: expected property id %#x or %#x, got %#x\n",
3261 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3264 if (status == Ok)
3266 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3267 if (prop_count == 0)
3268 expect(PropertyNotFound, status);
3269 else
3271 expect(Ok, status);
3273 assert(sizeof(item) >= prop_size);
3274 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3275 i, prop_size);
3276 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3277 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3278 " %u: expected property size %u or %u, got %u\n",
3279 i, td[i].prop_size, td[i].prop_size2, prop_size);
3281 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3282 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3283 "%u: expected InvalidParameter, got %d\n", i, status);
3284 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3285 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3286 "%u: expected InvalidParameter, got %d\n", i, status);
3287 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3288 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3289 "%u: expected InvalidParameter, got %d\n", i, status);
3290 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3291 expect(Ok, status);
3292 ok(prop_id[0] == item.data.id,
3293 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3297 GdipDisposeImage(image);
3301 #define IFD_BYTE 1
3302 #define IFD_ASCII 2
3303 #define IFD_SHORT 3
3304 #define IFD_LONG 4
3305 #define IFD_RATIONAL 5
3306 #define IFD_SBYTE 6
3307 #define IFD_UNDEFINED 7
3308 #define IFD_SSHORT 8
3309 #define IFD_SLONG 9
3310 #define IFD_SRATIONAL 10
3311 #define IFD_FLOAT 11
3312 #define IFD_DOUBLE 12
3314 #ifndef PropertyTagTypeSByte
3315 #define PropertyTagTypeSByte 6
3316 #define PropertyTagTypeSShort 8
3317 #define PropertyTagTypeFloat 11
3318 #define PropertyTagTypeDouble 12
3319 #endif
3321 static UINT documented_type(UINT type)
3323 switch (type)
3325 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3326 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3327 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3328 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3329 default: return type;
3333 #include "pshpack2.h"
3334 struct IFD_entry
3336 SHORT id;
3337 SHORT type;
3338 ULONG count;
3339 LONG value;
3342 struct IFD_rational
3344 LONG numerator;
3345 LONG denominator;
3348 static const struct tiff_data
3350 USHORT byte_order;
3351 USHORT version;
3352 ULONG dir_offset;
3353 USHORT number_of_entries;
3354 struct IFD_entry entry[40];
3355 ULONG next_IFD;
3356 struct IFD_rational xres;
3357 DOUBLE double_val;
3358 struct IFD_rational srational_val;
3359 char string[14];
3360 SHORT short_val[4];
3361 LONG long_val[2];
3362 FLOAT float_val[2];
3363 struct IFD_rational rational[3];
3364 BYTE pixel_data[4];
3365 } TIFF_data =
3367 #ifdef WORDS_BIGENDIAN
3368 'M' | 'M' << 8,
3369 #else
3370 'I' | 'I' << 8,
3371 #endif
3373 FIELD_OFFSET(struct tiff_data, number_of_entries),
3376 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3377 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3378 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3379 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3380 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3381 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3382 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3383 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3384 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3385 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3386 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3387 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3388 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3389 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3390 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3391 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3392 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3393 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3394 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3395 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3396 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3397 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3398 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3399 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3400 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3401 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3402 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3403 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3404 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3405 /* Some gdiplus versions ignore these fields.
3406 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3407 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3408 { 0xf014, IFD_LONG, 0, 0x11223344 },
3409 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3410 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3411 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3412 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3415 { 900, 3 },
3416 1234567890.0987654321,
3417 { 0x1a2b3c4d, 0x5a6b7c8d },
3418 "Hello World!",
3419 { 0x0101, 0x0202, 0x0303, 0x0404 },
3420 { 0x11223344, 0x55667788 },
3421 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3422 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3423 { 0x11, 0x22, 0x33, 0 }
3425 #include "poppack.h"
3427 static void test_tiff_properties(void)
3429 static const struct test_data
3431 ULONG type, id, length;
3432 const BYTE value[24];
3433 } td[31] =
3435 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3436 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3437 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3438 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3439 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3440 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3441 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3442 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3443 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3444 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3445 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3446 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3447 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3448 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3449 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3450 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3451 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3452 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3453 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3454 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3455 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3456 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3457 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3458 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3459 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3460 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3461 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3462 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3463 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3464 { PropertyTagTypeSRational, 0xf016, 24,
3465 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3466 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3467 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3468 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3469 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3471 GpStatus status;
3472 GpImage *image;
3473 GUID guid;
3474 UINT dim_count, frame_count, prop_count, prop_size, i;
3475 PROPID *prop_id;
3476 PropertyItem *prop_item;
3478 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3479 if (!image)
3481 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3482 return;
3485 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3486 expect(Ok, status);
3487 expect(1, dim_count);
3489 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3490 expect(Ok, status);
3491 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3493 frame_count = 0xdeadbeef;
3494 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3495 expect(Ok, status);
3496 expect(1, frame_count);
3498 prop_count = 0xdeadbeef;
3499 status = GdipGetPropertyCount(image, &prop_count);
3500 expect(Ok, status);
3501 ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3502 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3503 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3505 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3507 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3508 expect(Ok, status);
3510 for (i = 0; i < prop_count; i++)
3512 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3513 expect(Ok, status);
3514 if (status != Ok) break;
3515 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3517 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3518 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3519 expect(Ok, status);
3520 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3521 ok(td[i].type == prop_item->type ||
3522 /* Win7 stopped using proper but not documented types, and it
3523 looks broken since TypeFloat and TypeDouble now reported as
3524 TypeUndefined, and signed types reported as unsigned. */
3525 broken(prop_item->type == documented_type(td[i].type)),
3526 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3527 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3528 prop_size -= sizeof(*prop_item);
3529 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3530 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3531 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3532 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3533 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3534 if (td[i].length == prop_item->length)
3536 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3537 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3538 if (!match)
3540 UINT j;
3541 BYTE *data = prop_item->value;
3542 trace("id %#x:", prop_item->id);
3543 for (j = 0; j < prop_item->length; j++)
3544 trace(" %02x", data[j]);
3545 trace("\n");
3548 HeapFree(GetProcessHeap(), 0, prop_item);
3551 HeapFree(GetProcessHeap(), 0, prop_id);
3553 GdipDisposeImage(image);
3556 static void test_GdipGetAllPropertyItems(void)
3558 static const struct test_data
3560 ULONG type, id, length;
3561 BYTE value[32];
3562 } td[16] =
3564 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3565 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3566 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3567 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3568 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3569 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3570 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3571 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3572 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3573 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3574 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3575 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3576 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3577 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3578 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3579 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3581 GpStatus status;
3582 GpImage *image;
3583 GUID guid;
3584 UINT dim_count, frame_count, prop_count, prop_size, i;
3585 UINT total_size, total_count;
3586 PROPID *prop_id;
3587 PropertyItem *prop_item;
3588 const char *item_data;
3590 image = load_image(tiffimage, sizeof(tiffimage));
3591 ok(image != 0, "Failed to load TIFF image data\n");
3592 if (!image) return;
3594 dim_count = 0xdeadbeef;
3595 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3596 expect(Ok, status);
3597 expect(1, dim_count);
3599 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3600 expect(Ok, status);
3601 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3603 frame_count = 0xdeadbeef;
3604 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3605 expect(Ok, status);
3606 expect(1, frame_count);
3608 prop_count = 0xdeadbeef;
3609 status = GdipGetPropertyCount(image, &prop_count);
3610 expect(Ok, status);
3611 ok(prop_count == sizeof(td)/sizeof(td[0]),
3612 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3614 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3616 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3617 expect(Ok, status);
3619 prop_size = 0;
3620 for (i = 0; i < prop_count; i++)
3622 UINT size;
3623 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3624 expect(Ok, status);
3625 if (status != Ok) break;
3626 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3628 prop_size += size;
3630 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3631 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3632 expect(Ok, status);
3633 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3634 ok(td[i].type == prop_item->type,
3635 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3636 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3637 size -= sizeof(*prop_item);
3638 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3639 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3640 if (td[i].length == prop_item->length)
3642 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3643 ok(match, "%u: data mismatch\n", i);
3644 if (!match)
3646 UINT j;
3647 BYTE *data = prop_item->value;
3648 trace("id %#x:", prop_item->id);
3649 for (j = 0; j < prop_item->length; j++)
3650 trace(" %02x", data[j]);
3651 trace("\n");
3654 HeapFree(GetProcessHeap(), 0, prop_item);
3657 HeapFree(GetProcessHeap(), 0, prop_id);
3659 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3660 expect(InvalidParameter, status);
3661 status = GdipGetPropertySize(image, &total_size, NULL);
3662 expect(InvalidParameter, status);
3663 status = GdipGetPropertySize(image, NULL, &total_count);
3664 expect(InvalidParameter, status);
3665 status = GdipGetPropertySize(image, NULL, NULL);
3666 expect(InvalidParameter, status);
3667 total_size = 0xdeadbeef;
3668 total_count = 0xdeadbeef;
3669 status = GdipGetPropertySize(image, &total_size, &total_count);
3670 expect(Ok, status);
3671 ok(prop_count == total_count,
3672 "expected total property count %u, got %u\n", prop_count, total_count);
3673 ok(prop_size == total_size,
3674 "expected total property size %u, got %u\n", prop_size, total_size);
3676 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3678 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3679 expect(InvalidParameter, status);
3680 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3681 expect(InvalidParameter, status);
3682 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3683 expect(InvalidParameter, status);
3684 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3685 expect(InvalidParameter, status);
3686 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3687 expect(InvalidParameter, status);
3688 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3689 expect(InvalidParameter, status);
3690 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3691 expect(Ok, status);
3693 item_data = (const char *)(prop_item + prop_count);
3694 for (i = 0; i < prop_count; i++)
3696 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3697 i, item_data, prop_item[i].value);
3698 ok(td[i].type == prop_item[i].type,
3699 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3700 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3701 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3702 if (td[i].length == prop_item[i].length)
3704 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3705 ok(match, "%u: data mismatch\n", i);
3706 if (!match)
3708 UINT j;
3709 BYTE *data = prop_item[i].value;
3710 trace("id %#x:", prop_item[i].id);
3711 for (j = 0; j < prop_item[i].length; j++)
3712 trace(" %02x", data[j]);
3713 trace("\n");
3716 item_data += prop_item[i].length;
3719 HeapFree(GetProcessHeap(), 0, prop_item);
3721 GdipDisposeImage(image);
3724 static void test_tiff_palette(void)
3726 GpStatus status;
3727 GpImage *image;
3728 PixelFormat format;
3729 INT size;
3730 struct
3732 ColorPalette pal;
3733 ARGB entry[256];
3734 } palette;
3735 ARGB *entries = palette.pal.Entries;
3737 /* 1bpp TIFF without palette */
3738 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3739 if (!image)
3741 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3742 return;
3745 status = GdipGetImagePixelFormat(image, &format);
3746 expect(Ok, status);
3747 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3749 status = GdipGetImagePaletteSize(image, &size);
3750 ok(status == Ok || broken(status == GenericError), /* XP */
3751 "GdipGetImagePaletteSize error %d\n", status);
3752 if (status == GenericError)
3754 GdipDisposeImage(image);
3755 return;
3757 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3759 status = GdipGetImagePalette(image, &palette.pal, size);
3760 expect(Ok, status);
3761 expect(0, palette.pal.Flags);
3762 expect(2, palette.pal.Count);
3763 if (palette.pal.Count == 2)
3765 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3766 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3769 GdipDisposeImage(image);
3772 static void test_bitmapbits(void)
3774 /* 8 x 2 bitmap */
3775 static const BYTE pixels_24[48] =
3777 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3778 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3779 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3780 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3782 static const BYTE pixels_00[48] =
3784 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3785 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3786 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3787 0,0,0, 0,0,0, 0,0,0, 0,0,0
3789 static const BYTE pixels_24_77[64] =
3791 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3792 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3793 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3794 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3795 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3796 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3798 static const BYTE pixels_77[64] =
3800 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3801 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3802 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3803 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3804 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3805 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3806 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3807 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3809 static const BYTE pixels_8[16] =
3811 0x01,0,0x01,0,0x01,0,0x01,0,
3812 0x01,0,0x01,0,0x01,0,0x01,0
3814 static const BYTE pixels_8_77[64] =
3816 0x01,0,0x01,0,0x01,0,0x01,0,
3817 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3818 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3819 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3820 0x01,0,0x01,0,0x01,0,0x01,0,
3821 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3822 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3823 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3825 static const BYTE pixels_1_77[64] =
3827 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3828 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3829 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3830 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3831 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3832 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3833 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3834 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3836 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3837 static const struct test_data
3839 PixelFormat format;
3840 UINT bpp;
3841 ImageLockMode mode;
3842 UINT stride, size;
3843 const BYTE *pixels;
3844 const BYTE *pixels_unlocked;
3845 } td[] =
3847 /* 0 */
3848 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3850 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3851 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3852 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3853 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3854 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3855 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3856 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3857 /* 8 */
3858 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3859 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3860 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3861 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3862 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3863 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3864 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3865 /* 15 */
3866 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3867 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3868 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3869 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3870 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3871 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3872 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3874 BYTE buf[64];
3875 GpStatus status;
3876 GpBitmap *bitmap;
3877 UINT i;
3878 BitmapData data;
3879 struct
3881 ColorPalette pal;
3882 ARGB entries[1];
3883 } palette;
3884 ARGB *entries = palette.pal.Entries;
3886 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3888 BYTE pixels[sizeof(pixels_24)];
3889 memcpy(pixels, pixels_24, sizeof(pixels_24));
3890 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3891 expect(Ok, status);
3893 /* associate known palette with pixel data */
3894 palette.pal.Flags = PaletteFlagsGrayScale;
3895 palette.pal.Count = 2;
3896 entries[0] = 0xff000000;
3897 entries[1] = 0xffffffff;
3898 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3899 expect(Ok, status);
3901 memset(&data, 0xfe, sizeof(data));
3902 if (td[i].mode & ImageLockModeUserInputBuf)
3904 memset(buf, 0x77, sizeof(buf));
3905 data.Scan0 = buf;
3906 data.Stride = 32;
3908 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3909 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3910 if (status != Ok)
3912 GdipDisposeImage((GpImage *)bitmap);
3913 continue;
3915 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3916 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3917 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3918 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3919 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3920 if (td[i].mode & ImageLockModeUserInputBuf)
3921 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3922 if (td[i].size == data.Height * data.Stride)
3924 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3926 match = 1;
3927 for (j = 0; j < data.Height; j++)
3929 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3931 match = 0;
3932 break;
3935 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3937 ok(match,
3938 "%u: data should match\n", i);
3939 if (!match)
3941 BYTE *bits = data.Scan0;
3942 trace("%u: data mismatch for format %#x:", i, td[i].format);
3943 for (j = 0; j < td[i].size; j++)
3944 trace(" %02x", bits[j]);
3945 trace("\n");
3948 else
3949 ok(!match, "%u: data shouldn't match\n", i);
3951 memset(data.Scan0, 0, td[i].size);
3954 status = GdipBitmapUnlockBits(bitmap, &data);
3955 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3957 memset(&data, 0xfe, sizeof(data));
3958 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3959 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3960 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3961 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3962 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3963 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3964 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3965 if (data.Height * data.Stride == 48)
3967 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3968 ok(match, "%u: data should match\n", i);
3969 if (!match)
3971 UINT j;
3972 BYTE *bits = data.Scan0;
3973 trace("%u: data mismatch for format %#x:", i, td[i].format);
3974 for (j = 0; j < 48; j++)
3975 trace(" %02x", bits[j]);
3976 trace("\n");
3980 status = GdipBitmapUnlockBits(bitmap, &data);
3981 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3983 status = GdipDisposeImage((GpImage *)bitmap);
3984 expect(Ok, status);
3988 static void test_DrawImage(void)
3990 BYTE black_1x1[4] = { 0,0,0,0 };
3991 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3992 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3993 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3994 0,0,0,0,0,0,0xff,0xff };
3995 GpStatus status;
3996 union
3998 GpBitmap *bitmap;
3999 GpImage *image;
4000 } u1, u2;
4001 GpGraphics *graphics;
4002 int match;
4004 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4005 expect(Ok, status);
4006 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4007 expect(Ok, status);
4009 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4010 expect(Ok, status);
4011 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4012 expect(Ok, status);
4013 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4014 expect(Ok, status);
4015 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4016 expect(Ok, status);
4018 status = GdipDrawImageI(graphics, u1.image, 0, 0);
4019 expect(Ok, status);
4021 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4022 ok(match, "data should match\n");
4023 if (!match)
4025 UINT i, size = sizeof(white_2x2);
4026 BYTE *bits = white_2x2;
4027 for (i = 0; i < size; i++)
4028 trace(" %02x", bits[i]);
4029 trace("\n");
4032 status = GdipDeleteGraphics(graphics);
4033 expect(Ok, status);
4034 status = GdipDisposeImage(u1.image);
4035 expect(Ok, status);
4036 status = GdipDisposeImage(u2.image);
4037 expect(Ok, status);
4040 static void test_DrawImage_SourceCopy(void)
4042 DWORD dst_pixels[4] = { 0xffffffff, 0xffffffff,
4043 0xffffffff, 0xffffffff };
4044 DWORD src_pixels[4] = { 0, 0xffff0000,
4045 0, 0xff00ff };
4047 GpStatus status;
4048 union
4050 GpBitmap *bitmap;
4051 GpImage *image;
4052 } u1, u2;
4053 GpGraphics *graphics;
4055 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)dst_pixels, &u1.bitmap);
4056 expect(Ok, status);
4058 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)src_pixels, &u2.bitmap);
4059 expect(Ok, status);
4060 status = GdipGetImageGraphicsContext(u1.image, &graphics);
4061 expect(Ok, status);
4062 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4063 expect(Ok, status);
4065 status = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
4066 expect(Ok, status);
4068 status = GdipDrawImageI(graphics, u2.image, 0, 0);
4069 expect(Ok, status);
4071 todo_wine expect(0, dst_pixels[0]);
4072 expect(0xffff0000, dst_pixels[1]);
4073 todo_wine expect(0, dst_pixels[2]);
4074 todo_wine expect(0, dst_pixels[3]);
4076 status = GdipDeleteGraphics(graphics);
4077 expect(Ok, status);
4078 status = GdipDisposeImage(u1.image);
4079 expect(Ok, status);
4080 status = GdipDisposeImage(u2.image);
4081 expect(Ok, status);
4084 static void test_GdipDrawImagePointRect(void)
4086 BYTE black_1x1[4] = { 0,0,0,0 };
4087 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4088 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4089 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4090 0,0,0,0,0,0,0xff,0xff };
4091 GpStatus status;
4092 union
4094 GpBitmap *bitmap;
4095 GpImage *image;
4096 } u1, u2;
4097 GpGraphics *graphics;
4098 int match;
4100 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4101 expect(Ok, status);
4102 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4103 expect(Ok, status);
4105 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4106 expect(Ok, status);
4107 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4108 expect(Ok, status);
4109 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4110 expect(Ok, status);
4111 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4112 expect(Ok, status);
4114 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
4115 expect(Ok, status);
4117 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4118 ok(match, "data should match\n");
4119 if (!match)
4121 UINT i, size = sizeof(white_2x2);
4122 BYTE *bits = white_2x2;
4123 for (i = 0; i < size; i++)
4124 trace(" %02x", bits[i]);
4125 trace("\n");
4128 status = GdipDeleteGraphics(graphics);
4129 expect(Ok, status);
4130 status = GdipDisposeImage(u1.image);
4131 expect(Ok, status);
4132 status = GdipDisposeImage(u2.image);
4133 expect(Ok, status);
4136 static void test_image_format(void)
4138 static const PixelFormat fmt[] =
4140 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4141 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4142 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4143 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4144 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4146 GpStatus status;
4147 GpBitmap *bitmap;
4148 GpImage *thumb;
4149 HBITMAP hbitmap;
4150 BITMAP bm;
4151 PixelFormat format;
4152 BitmapData data;
4153 UINT i, ret;
4155 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
4157 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4158 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4159 "GdipCreateBitmapFromScan0 error %d\n", status);
4160 if (status != Ok) continue;
4162 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4163 expect(Ok, status);
4164 expect(fmt[i], format);
4166 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4167 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4168 todo_wine expect(InvalidParameter, status);
4169 else
4171 expect(Ok, status);
4172 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4173 expect(sizeof(bm), ret);
4174 expect(0, bm.bmType);
4175 expect(1, bm.bmWidth);
4176 expect(1, bm.bmHeight);
4177 expect(4, bm.bmWidthBytes);
4178 expect(1, bm.bmPlanes);
4179 expect(32, bm.bmBitsPixel);
4180 DeleteObject(hbitmap);
4183 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4184 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4185 todo_wine
4186 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4187 "expected OutOfMemory, got %d\n", status);
4188 else
4189 expect(Ok, status);
4190 if (status == Ok)
4192 status = GdipGetImagePixelFormat(thumb, &format);
4193 expect(Ok, status);
4194 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4195 "expected PixelFormat32bppPARGB, got %#x\n", format);
4196 status = GdipDisposeImage(thumb);
4197 expect(Ok, status);
4200 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4201 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4202 todo_wine expect(InvalidParameter, status);
4203 else
4205 expect(Ok, status);
4206 status = GdipBitmapUnlockBits(bitmap, &data);
4207 expect(Ok, status);
4210 status = GdipDisposeImage((GpImage *)bitmap);
4211 expect(Ok, status);
4215 static void test_DrawImage_scale(void)
4217 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4218 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4219 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4220 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4221 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4222 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4223 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4224 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4225 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4226 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4227 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4228 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4229 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4230 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4231 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4232 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4233 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4234 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4235 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4236 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4237 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4238 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4239 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4240 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4241 static const struct test_data
4243 REAL scale_x;
4244 PixelOffsetMode pixel_offset_mode;
4245 const BYTE *image;
4246 BOOL todo;
4247 } td[] =
4249 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4250 { 1.0, PixelOffsetModeNone, image_100 },
4251 { 1.2, PixelOffsetModeNone, image_120 },
4252 { 1.5, PixelOffsetModeNone, image_150 },
4253 { 1.8, PixelOffsetModeNone, image_180 },
4254 { 2.0, PixelOffsetModeNone, image_200 },
4255 { 2.5, PixelOffsetModeNone, image_250 },
4257 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4258 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4259 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4260 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4261 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4262 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4263 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4265 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4266 { 1.0, PixelOffsetModeHalf, image_100 },
4267 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4268 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4269 { 1.8, PixelOffsetModeHalf, image_180 },
4270 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4271 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4273 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4274 { 1.0, PixelOffsetModeHighQuality, image_100 },
4275 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4276 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4277 { 1.8, PixelOffsetModeHighQuality, image_180 },
4278 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4279 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4281 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4282 BYTE dst_8x1[24];
4283 GpStatus status;
4284 union
4286 GpBitmap *bitmap;
4287 GpImage *image;
4288 } u1, u2;
4289 GpGraphics *graphics;
4290 GpMatrix *matrix;
4291 int i, match;
4293 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4294 expect(Ok, status);
4295 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4296 expect(Ok, status);
4298 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4299 expect(Ok, status);
4300 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4301 expect(Ok, status);
4302 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4303 expect(Ok, status);
4304 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4305 expect(Ok, status);
4307 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4309 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4310 expect(Ok, status);
4312 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4313 expect(Ok, status);
4314 status = GdipSetWorldTransform(graphics, matrix);
4315 expect(Ok, status);
4316 GdipDeleteMatrix(matrix);
4318 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4319 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4320 expect(Ok, status);
4322 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4323 todo_wine_if (!match && td[i].todo)
4324 ok(match, "%d: data should match\n", i);
4325 if (!match)
4327 UINT i, size = sizeof(dst_8x1);
4328 const BYTE *bits = dst_8x1;
4329 for (i = 0; i < size; i++)
4330 trace(" %02x", bits[i]);
4331 trace("\n");
4335 status = GdipDeleteGraphics(graphics);
4336 expect(Ok, status);
4337 status = GdipDisposeImage(u1.image);
4338 expect(Ok, status);
4339 status = GdipDisposeImage(u2.image);
4340 expect(Ok, status);
4343 static const BYTE animatedgif[] = {
4344 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4345 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4346 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4347 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4348 0x03,0x01,0x05,0x00,0x00,
4349 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4350 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4351 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4352 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4353 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4354 0x02,0x02,0x4C,0x01,0x00,
4355 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4356 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4357 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4358 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4359 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4360 0x02,0x02,0x44,0x01,0x00,
4361 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4362 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4365 static void test_gif_properties(void)
4367 static const struct test_data
4369 ULONG type, id, length;
4370 const BYTE value[13];
4371 } td[] =
4373 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4374 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4375 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4376 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4377 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4378 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4380 GpStatus status;
4381 GpImage *image;
4382 GUID guid;
4383 UINT dim_count, frame_count, prop_count, prop_size, i;
4384 UINT total_size, total_count;
4385 PROPID *prop_id;
4386 PropertyItem *prop_item;
4387 const char *item_data;
4389 image = load_image(animatedgif, sizeof(animatedgif));
4390 if (!image) /* XP fails to load this GIF image */
4392 trace("Failed to load GIF image data\n");
4393 return;
4396 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4397 expect(Ok, status);
4398 expect(1, dim_count);
4400 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4401 expect(Ok, status);
4402 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4404 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4405 expect(Ok, status);
4406 expect(2, frame_count);
4408 status = GdipImageSelectActiveFrame(image, &guid, 1);
4409 expect(Ok, status);
4411 status = GdipGetPropertyCount(image, &prop_count);
4412 expect(Ok, status);
4413 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
4414 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
4416 if (prop_count != sizeof(td)/sizeof(td[0]))
4418 GdipDisposeImage(image);
4419 return;
4422 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4424 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4425 expect(Ok, status);
4427 prop_size = 0;
4428 for (i = 0; i < prop_count; i++)
4430 UINT size;
4431 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4432 expect(Ok, status);
4433 if (status != Ok) break;
4434 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4436 prop_size += size;
4438 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4439 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4440 expect(Ok, status);
4441 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4442 ok(td[i].type == prop_item->type,
4443 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4444 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4445 size -= sizeof(*prop_item);
4446 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4447 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4448 if (td[i].length == prop_item->length)
4450 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4451 ok(match, "%u: data mismatch\n", i);
4452 if (!match)
4454 UINT j;
4455 BYTE *data = prop_item->value;
4456 trace("id %#x:", prop_item->id);
4457 for (j = 0; j < prop_item->length; j++)
4458 trace(" %02x", data[j]);
4459 trace("\n");
4462 HeapFree(GetProcessHeap(), 0, prop_item);
4465 HeapFree(GetProcessHeap(), 0, prop_id);
4467 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4468 expect(InvalidParameter, status);
4469 status = GdipGetPropertySize(image, &total_size, NULL);
4470 expect(InvalidParameter, status);
4471 status = GdipGetPropertySize(image, NULL, &total_count);
4472 expect(InvalidParameter, status);
4473 status = GdipGetPropertySize(image, NULL, NULL);
4474 expect(InvalidParameter, status);
4475 total_size = 0xdeadbeef;
4476 total_count = 0xdeadbeef;
4477 status = GdipGetPropertySize(image, &total_size, &total_count);
4478 expect(Ok, status);
4479 ok(prop_count == total_count,
4480 "expected total property count %u, got %u\n", prop_count, total_count);
4481 ok(prop_size == total_size,
4482 "expected total property size %u, got %u\n", prop_size, total_size);
4484 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4486 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4487 expect(InvalidParameter, status);
4488 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4489 expect(InvalidParameter, status);
4490 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4491 expect(InvalidParameter, status);
4492 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4493 expect(InvalidParameter, status);
4494 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4495 expect(InvalidParameter, status);
4496 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4497 expect(InvalidParameter, status);
4498 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4499 expect(Ok, status);
4501 item_data = (const char *)(prop_item + prop_count);
4502 for (i = 0; i < prop_count; i++)
4504 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4505 i, item_data, prop_item[i].value);
4506 ok(td[i].type == prop_item[i].type,
4507 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4508 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4509 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4510 if (td[i].length == prop_item[i].length)
4512 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4513 ok(match, "%u: data mismatch\n", i);
4514 if (!match)
4516 UINT j;
4517 BYTE *data = prop_item[i].value;
4518 trace("id %#x:", prop_item[i].id);
4519 for (j = 0; j < prop_item[i].length; j++)
4520 trace(" %02x", data[j]);
4521 trace("\n");
4524 item_data += prop_item[i].length;
4527 HeapFree(GetProcessHeap(), 0, prop_item);
4529 GdipDisposeImage(image);
4532 static void test_ARGB_conversion(void)
4534 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4535 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4536 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4537 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4538 BYTE *bits;
4539 GpBitmap *bitmap;
4540 BitmapData data;
4541 GpStatus status;
4542 int match;
4544 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4545 expect(Ok, status);
4547 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4548 expect(Ok, status);
4549 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4550 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4551 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4552 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4553 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4554 ok(match, "bits don't match\n");
4555 if (!match)
4557 bits = data.Scan0;
4558 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4559 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4561 status = GdipBitmapUnlockBits(bitmap, &data);
4562 expect(Ok, status);
4564 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4565 expect(Ok, status);
4566 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4567 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4568 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4569 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4570 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4571 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4572 ok(match, "bits don't match\n");
4573 if (!match)
4575 bits = data.Scan0;
4576 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4577 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4579 status = GdipBitmapUnlockBits(bitmap, &data);
4580 expect(Ok, status);
4582 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4583 expect(Ok, status);
4584 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4585 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4586 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4587 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4588 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4589 ok(match, "bits don't match\n");
4590 if (!match)
4592 bits = data.Scan0;
4593 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4594 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4596 status = GdipBitmapUnlockBits(bitmap, &data);
4597 expect(Ok, status);
4599 GdipDisposeImage((GpImage *)bitmap);
4603 static void test_CloneBitmapArea(void)
4605 GpStatus status;
4606 GpBitmap *bitmap, *copy;
4607 BitmapData data, data2;
4609 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4610 expect(Ok, status);
4612 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4613 expect(Ok, status);
4615 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4616 expect(WrongState, status);
4618 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4619 expect(Ok, status);
4621 status = GdipBitmapUnlockBits(bitmap, &data);
4622 expect(Ok, status);
4624 GdipDisposeImage((GpImage *)copy);
4625 GdipDisposeImage((GpImage *)bitmap);
4628 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid)
4630 GpStatus status;
4631 UINT n_codecs, info_size, i;
4632 ImageCodecInfo *info;
4633 BOOL ret = FALSE;
4635 status = GdipGetImageEncodersSize(&n_codecs, &info_size);
4636 expect(Ok, status);
4638 info = GdipAlloc(info_size);
4640 status = GdipGetImageEncoders(n_codecs, info_size, info);
4641 expect(Ok, status);
4643 for (i = 0; i < n_codecs; i++)
4645 if (!lstrcmpW(info[i].MimeType, mime))
4647 *format = info[i].FormatID;
4648 *clsid = info[i].Clsid;
4649 ret = TRUE;
4650 break;
4654 GdipFree(info);
4655 return ret;
4658 static void test_supported_encoders(void)
4660 static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 };
4661 static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 };
4662 static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 };
4663 static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 };
4664 static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 };
4665 static const struct test_data
4667 LPCWSTR mime;
4668 const GUID *format;
4669 BOOL todo;
4670 } td[] =
4672 { bmp_mimetype, &ImageFormatBMP, FALSE },
4673 { jpeg_mimetype, &ImageFormatJPEG, FALSE },
4674 { gif_mimetype, &ImageFormatGIF, TRUE },
4675 { tiff_mimetype, &ImageFormatTIFF, FALSE },
4676 { png_mimetype, &ImageFormatPNG, FALSE }
4678 GUID format, clsid;
4679 BOOL ret;
4680 HRESULT hr;
4681 GpStatus status;
4682 GpBitmap *bm;
4683 IStream *stream;
4684 HGLOBAL hmem;
4685 int i;
4687 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
4688 ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
4690 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4692 ret = get_encoder_clsid(td[i].mime, &format, &clsid);
4693 ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
4694 expect_guid(td[i].format, &format, __LINE__, FALSE);
4696 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
4698 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
4699 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
4701 status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
4702 todo_wine_if (td[i].todo)
4703 ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4705 IStream_Release(stream);
4708 GdipDisposeImage((GpImage *)bm);
4711 static void test_createeffect(void)
4713 static const GUID noneffect = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } };
4714 GpStatus (WINAPI *pGdipCreateEffect)( const GUID guid, CGpEffect **effect);
4715 GpStatus (WINAPI *pGdipDeleteEffect)( CGpEffect *effect);
4716 GpStatus stat;
4717 CGpEffect *effect;
4718 HMODULE mod = GetModuleHandleA("gdiplus.dll");
4719 int i;
4720 const GUID * const effectlist[] =
4721 {&BlurEffectGuid, &SharpenEffectGuid, &ColorMatrixEffectGuid, &ColorLUTEffectGuid,
4722 &BrightnessContrastEffectGuid, &HueSaturationLightnessEffectGuid, &LevelsEffectGuid,
4723 &TintEffectGuid, &ColorBalanceEffectGuid, &RedEyeCorrectionEffectGuid, &ColorCurveEffectGuid};
4725 pGdipCreateEffect = (void*)GetProcAddress( mod, "GdipCreateEffect");
4726 pGdipDeleteEffect = (void*)GetProcAddress( mod, "GdipDeleteEffect");
4727 if(!pGdipCreateEffect || !pGdipDeleteEffect)
4729 /* GdipCreateEffect/GdipDeleteEffect was introduced in Windows Vista. */
4730 win_skip("GDIPlus version 1.1 not available\n");
4731 return;
4734 stat = pGdipCreateEffect(BlurEffectGuid, NULL);
4735 expect(InvalidParameter, stat);
4737 stat = pGdipCreateEffect(noneffect, &effect);
4738 todo_wine expect(Win32Error, stat);
4740 for(i=0; i < sizeof(effectlist) / sizeof(effectlist[0]); i++)
4742 stat = pGdipCreateEffect(*effectlist[i], &effect);
4743 todo_wine expect(Ok, stat);
4744 if(stat == Ok)
4746 stat = pGdipDeleteEffect(effect);
4747 expect(Ok, stat);
4752 static void test_getadjustedpalette(void)
4754 ColorMap colormap;
4755 GpImageAttributes *imageattributes;
4756 ColorPalette *palette;
4757 GpStatus stat;
4759 stat = GdipCreateImageAttributes(&imageattributes);
4760 expect(Ok, stat);
4762 colormap.oldColor.Argb = 0xffffff00;
4763 colormap.newColor.Argb = 0xffff00ff;
4764 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeBitmap,
4765 TRUE, 1, &colormap);
4766 expect(Ok, stat);
4768 colormap.oldColor.Argb = 0xffffff80;
4769 colormap.newColor.Argb = 0xffff80ff;
4770 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeDefault,
4771 TRUE, 1, &colormap);
4772 expect(Ok, stat);
4774 palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 2);
4775 palette->Count = 0;
4777 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4778 expect(InvalidParameter, stat);
4780 palette->Count = 3;
4781 palette->Entries[0] = 0xffffff00;
4782 palette->Entries[1] = 0xffffff80;
4783 palette->Entries[2] = 0xffffffff;
4785 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4786 expect(Ok, stat);
4787 expect(0xffff00ff, palette->Entries[0]);
4788 expect(0xffffff80, palette->Entries[1]);
4789 expect(0xffffffff, palette->Entries[2]);
4791 palette->Entries[0] = 0xffffff00;
4792 palette->Entries[1] = 0xffffff80;
4793 palette->Entries[2] = 0xffffffff;
4795 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBrush);
4796 expect(Ok, stat);
4797 expect(0xffffff00, palette->Entries[0]);
4798 expect(0xffff80ff, palette->Entries[1]);
4799 expect(0xffffffff, palette->Entries[2]);
4801 stat = GdipGetImageAttributesAdjustedPalette(NULL, palette, ColorAdjustTypeBitmap);
4802 expect(InvalidParameter, stat);
4804 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, NULL, ColorAdjustTypeBitmap);
4805 expect(InvalidParameter, stat);
4807 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, -1);
4808 expect(InvalidParameter, stat);
4810 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeDefault);
4811 expect(InvalidParameter, stat);
4813 GdipFree(palette);
4814 GdipDisposeImageAttributes(imageattributes);
4817 static void test_histogram(void)
4819 UINT ch0[256], ch1[256], ch2[256], ch3[256];
4820 HistogramFormat test_formats[] =
4822 HistogramFormatARGB,
4823 HistogramFormatPARGB,
4824 HistogramFormatRGB,
4825 HistogramFormatGray,
4826 HistogramFormatB,
4827 HistogramFormatG,
4828 HistogramFormatR,
4829 HistogramFormatA,
4831 const UINT WIDTH = 8, HEIGHT = 16;
4832 UINT num, i, x;
4833 GpStatus stat;
4834 GpBitmap *bm;
4836 if (!pGdipBitmapGetHistogramSize)
4838 win_skip("GdipBitmapGetHistogramSize is not supported\n");
4839 return;
4842 stat = pGdipBitmapGetHistogramSize(HistogramFormatARGB, NULL);
4843 expect(InvalidParameter, stat);
4845 stat = pGdipBitmapGetHistogramSize(0xff, NULL);
4846 expect(InvalidParameter, stat);
4848 num = 123;
4849 stat = pGdipBitmapGetHistogramSize(10, &num);
4850 expect(Ok, stat);
4851 expect(256, num);
4853 for (i = 0; i < sizeof(test_formats)/sizeof(test_formats[0]); i++)
4855 num = 0;
4856 stat = pGdipBitmapGetHistogramSize(test_formats[i], &num);
4857 expect(Ok, stat);
4858 expect(256, num);
4861 bm = NULL;
4862 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
4863 expect(Ok, stat);
4865 /* Three solid rgb rows, next three rows are rgb shades. */
4866 for (x = 0; x < WIDTH; x++)
4868 GdipBitmapSetPixel(bm, x, 0, 0xffff0000);
4869 GdipBitmapSetPixel(bm, x, 1, 0xff00ff00);
4870 GdipBitmapSetPixel(bm, x, 2, 0xff0000ff);
4872 GdipBitmapSetPixel(bm, x, 3, 0xff010000);
4873 GdipBitmapSetPixel(bm, x, 4, 0xff003f00);
4874 GdipBitmapSetPixel(bm, x, 5, 0xff000020);
4877 stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
4878 expect(InvalidParameter, stat);
4880 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3);
4881 expect(InvalidParameter, stat);
4883 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL);
4884 expect(InvalidParameter, stat);
4886 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL);
4887 expect(InvalidParameter, stat);
4889 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL);
4890 expect(InvalidParameter, stat);
4892 /* Requested format matches bitmap format */
4893 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
4894 expect(InvalidParameter, stat);
4896 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL);
4897 expect(InvalidParameter, stat);
4899 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL);
4900 expect(InvalidParameter, stat);
4902 /* Channel 3 is not used, must be NULL */
4903 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL);
4904 expect(Ok, stat);
4906 ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]);
4907 ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]);
4908 ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]);
4909 ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]);
4910 ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]);
4911 ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]);
4913 /* ARGB histogram from RGB data. */
4914 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL);
4915 expect(InvalidParameter, stat);
4917 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3);
4918 expect(Ok, stat);
4920 ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]);
4921 ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]);
4922 ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]);
4923 ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]);
4924 ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]);
4925 ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]);
4927 ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]);
4929 /* Request grayscale histogram from RGB bitmap. */
4930 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3);
4931 expect(InvalidParameter, stat);
4933 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL);
4934 expect(InvalidParameter, stat);
4936 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL);
4937 expect(InvalidParameter, stat);
4939 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL);
4940 expect(Ok, stat);
4942 GdipDisposeImage((GpImage*)bm);
4945 static void test_imageabort(void)
4947 GpStatus stat;
4948 GpBitmap *bm;
4950 if (!pGdipImageSetAbort)
4952 win_skip("GdipImageSetAbort() is not supported.\n");
4953 return;
4956 bm = NULL;
4957 stat = GdipCreateBitmapFromScan0(8, 8, 0, PixelFormat24bppRGB, NULL, &bm);
4958 expect(Ok, stat);
4960 stat = pGdipImageSetAbort(NULL, NULL);
4961 expect(InvalidParameter, stat);
4963 stat = pGdipImageSetAbort((GpImage*)bm, NULL);
4964 expect(Ok, stat);
4966 GdipDisposeImage((GpImage*)bm);
4969 /* RGB 24 bpp 1x1 pixel PNG image */
4970 static const char png_1x1_data[] = {
4971 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a,
4972 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,0xde,
4973 0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7,
4974 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
4977 static void test_png_color_formats(void)
4979 static const struct
4981 char bit_depth, color_type;
4982 PixelFormat format;
4983 } td[] =
4985 /* 2 - PNG_COLOR_TYPE_RGB */
4986 { 8, 2, PixelFormat24bppRGB },
4987 /* 0 - PNG_COLOR_TYPE_GRAY */
4988 { 1, 0, PixelFormat1bppIndexed },
4989 { 2, 0, PixelFormat32bppARGB },
4990 { 4, 0, PixelFormat32bppARGB },
4991 { 8, 0, PixelFormat32bppARGB },
4992 { 16, 0, PixelFormat32bppARGB },
4994 BYTE buf[sizeof(png_1x1_data)];
4995 GpStatus status;
4996 GpImage *image;
4997 ImageType type;
4998 PixelFormat format;
4999 int i;
5001 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
5003 memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
5004 buf[24] = td[i].bit_depth;
5005 buf[25] = td[i].color_type;
5007 image = load_image(buf, sizeof(buf));
5008 ok(image != NULL, "%d: failed to load image data\n", i);
5009 if (!image) continue;
5011 status = GdipGetImageType(image, &type);
5012 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
5013 ok(type == ImageTypeBitmap, "%d: wrong image type %d\n", i, type);
5015 status = GdipGetImagePixelFormat(image, &format);
5016 expect(Ok, status);
5017 todo_wine_if(td[i].bit_depth == 8 && td[i].color_type == 0)
5018 ok(format == td[i].format ||
5019 broken(td[i].bit_depth == 1 && td[i].color_type == 0 && format == PixelFormat32bppARGB), /* XP */
5020 "%d: expected %#x, got %#x\n", i, td[i].format, format);
5022 GdipDisposeImage(image);
5026 START_TEST(image)
5028 HMODULE mod = GetModuleHandleA("gdiplus.dll");
5029 struct GdiplusStartupInput gdiplusStartupInput;
5030 ULONG_PTR gdiplusToken;
5031 HMODULE hmsvcrt;
5032 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
5034 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
5035 hmsvcrt = LoadLibraryA("msvcrt");
5036 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
5037 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
5039 gdiplusStartupInput.GdiplusVersion = 1;
5040 gdiplusStartupInput.DebugEventCallback = NULL;
5041 gdiplusStartupInput.SuppressBackgroundThread = 0;
5042 gdiplusStartupInput.SuppressExternalCodecs = 0;
5044 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
5046 pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize");
5047 pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram");
5048 pGdipImageSetAbort = (void*)GetProcAddress(mod, "GdipImageSetAbort");
5050 test_png_color_formats();
5051 test_supported_encoders();
5052 test_CloneBitmapArea();
5053 test_ARGB_conversion();
5054 test_DrawImage_scale();
5055 test_image_format();
5056 test_DrawImage();
5057 test_DrawImage_SourceCopy();
5058 test_GdipDrawImagePointRect();
5059 test_bitmapbits();
5060 test_tiff_palette();
5061 test_GdipGetAllPropertyItems();
5062 test_tiff_properties();
5063 test_gif_properties();
5064 test_image_properties();
5065 test_Scan0();
5066 test_FromGdiDib();
5067 test_GetImageDimension();
5068 test_GdipImageGetFrameDimensionsCount();
5069 test_LoadingImages();
5070 test_SavingImages();
5071 test_encoders();
5072 test_LockBits();
5073 test_LockBits_UserBuf();
5074 test_GdipCreateBitmapFromHBITMAP();
5075 test_GdipGetImageFlags();
5076 test_GdipCloneImage();
5077 test_testcontrol();
5078 test_fromhicon();
5079 test_getrawformat();
5080 test_loadwmf();
5081 test_createfromwmf();
5082 test_createfromwmf_noplaceable();
5083 test_resolution();
5084 test_createhbitmap();
5085 test_getthumbnail();
5086 test_getsetpixel();
5087 test_palette();
5088 test_colormatrix();
5089 test_gamma();
5090 test_multiframegif();
5091 test_rotateflip();
5092 test_remaptable();
5093 test_colorkey();
5094 test_dispose();
5095 test_createeffect();
5096 test_getadjustedpalette();
5097 test_histogram();
5098 test_imageabort();
5100 GdiplusShutdown(gdiplusToken);