1 /*
2  * Unit test suite for images
3  *
4  * Copyright (C) 2007 Google (Evan Stade)
5  * Copyright (C) 2012, 2016 Dmitry Timoshkov
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #define COBJMACROS
23 
24 #include <math.h>
25 #include <assert.h>
26 #include <stdio.h>
27 
28 #include "initguid.h"
29 #include "objbase.h"
30 #include "gdiplus.h"
31 #include "wine/test.h"
32 
33 #ifdef __REACTOS__
34 #include <ole2.h>
35 #endif
36 
37 /* FIXME: They belong to gdipluseffects.h */
38 DEFINE_GUID(BlurEffectGuid, 0x633c80a4, 0x1843, 0x482b, 0x9e, 0xf2, 0xbe, 0x28, 0x34, 0xc5, 0xfd, 0xd4);
39 DEFINE_GUID(SharpenEffectGuid, 0x63cbf3ee, 0xc526, 0x402c, 0x8f, 0x71, 0x62, 0xc5, 0x40, 0xbf, 0x51, 0x42);
40 DEFINE_GUID(ColorMatrixEffectGuid, 0x718f2615, 0x7933, 0x40e3, 0xa5, 0x11, 0x5f, 0x68, 0xfe, 0x14, 0xdd, 0x74);
41 DEFINE_GUID(ColorLUTEffectGuid, 0xa7ce72a9, 0x0f7f, 0x40d7, 0xb3, 0xcc, 0xd0, 0xc0, 0x2d, 0x5c, 0x32, 0x12);
42 DEFINE_GUID(BrightnessContrastEffectGuid, 0xd3a1dbe1, 0x8ec4, 0x4c17, 0x9f, 0x4c, 0xea, 0x97, 0xad, 0x1c, 0x34, 0x3d);
43 DEFINE_GUID(HueSaturationLightnessEffectGuid, 0x8b2dd6c3, 0xeb07, 0x4d87, 0xa5, 0xf0, 0x71, 0x08, 0xe2, 0x6a, 0x9c, 0x5f);
44 DEFINE_GUID(LevelsEffectGuid, 0x99c354ec, 0x2a31, 0x4f3a, 0x8c, 0x34, 0x17, 0xa8, 0x03, 0xb3, 0x3a, 0x25);
45 DEFINE_GUID(TintEffectGuid, 0x1077af00, 0x2848, 0x4441, 0x94, 0x89, 0x44, 0xad, 0x4c, 0x2d, 0x7a, 0x2c);
46 DEFINE_GUID(ColorBalanceEffectGuid, 0x537e597d, 0x251e, 0x48da, 0x96, 0x64, 0x29, 0xca, 0x49, 0x6b, 0x70, 0xf8);
47 DEFINE_GUID(RedEyeCorrectionEffectGuid, 0x74d29d05, 0x69a4, 0x4266, 0x95, 0x49, 0x3c, 0xc5, 0x28, 0x36, 0xb6, 0x32);
48 DEFINE_GUID(ColorCurveEffectGuid, 0xdd6a0022, 0x58e4, 0x4a67, 0x9d, 0x9b, 0xd4, 0x8e, 0xb8, 0x81, 0xa5, 0x3d);
49 
50 static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*);
51 static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
52 static GpStatus (WINAPI *pGdipImageSetAbort)(GpImage*,GdiplusAbort*);
53 
54 static GpStatus (WINGDIPAPI *pGdipInitializePalette)(ColorPalette*,PaletteType,INT,BOOL,GpBitmap*);
55 
56 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
57 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
58 
59 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
60 {
61     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
62     c1 >>= 8; c2 >>= 8;
63     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
64     c1 >>= 8; c2 >>= 8;
65     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
66     c1 >>= 8; c2 >>= 8;
67     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
68     return TRUE;
69 }
70 
71 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
72 {
73     WCHAR bufferW[39];
74     char buffer[39];
75     char buffer2[39];
76 
77     StringFromGUID2(got, bufferW, ARRAY_SIZE(bufferW));
78     WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer, sizeof(buffer), NULL, NULL);
79     StringFromGUID2(expected, bufferW, ARRAY_SIZE(bufferW));
80     WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer2, sizeof(buffer2), NULL, NULL);
81     todo_wine_if (todo)
82         ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
83 }
84 
85 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
86 {
87     GUID raw;
88     GpStatus stat;
89 
90     stat = GdipGetImageRawFormat(img, &raw);
91     ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
92     if(stat != Ok) return;
93     expect_guid(expected, &raw, line, todo);
94 }
95 
96 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
97 {
98     LPSTREAM stream;
99     HGLOBAL  hglob;
100     LPBYTE   data;
101     HRESULT  hres;
102     GpStatus stat;
103     GpImage *img;
104 
105     hglob = GlobalAlloc (0, size);
106     data = GlobalLock (hglob);
107     memcpy(data, buff, size);
108     GlobalUnlock(hglob); data = NULL;
109 
110     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
111     ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
112     if(hres != S_OK) return;
113 
114     stat = GdipLoadImageFromStream(stream, &img);
115     ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
116     if(stat != Ok){
117         IStream_Release(stream);
118         return;
119     }
120 
121     expect_rawformat(expected, img, line, todo);
122 
123     GdipDisposeImage(img);
124     IStream_Release(stream);
125 }
126 
127 static void test_Scan0(void)
128 {
129     GpBitmap *bm;
130     GpStatus stat;
131     BYTE buff[360];
132 
133     bm = NULL;
134     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
135     expect(Ok, stat);
136     ok(NULL != bm, "Expected bitmap to be initialized\n");
137     if (stat == Ok)
138         GdipDisposeImage((GpImage*)bm);
139 
140     bm = (GpBitmap*)0xdeadbeef;
141     stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
142     expect(InvalidParameter, stat);
143     ok( !bm, "expected null bitmap\n" );
144 
145     bm = (GpBitmap*)0xdeadbeef;
146     stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
147     expect(InvalidParameter, stat);
148     ok( !bm, "expected null bitmap\n" );
149 
150     bm = (GpBitmap*)0xdeadbeef;
151     stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
152     expect(InvalidParameter, stat);
153     ok( !bm, "expected null bitmap\n" );
154 
155     bm = NULL;
156     stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
157     expect(Ok, stat);
158     ok(NULL != bm, "Expected bitmap to be initialized\n");
159     if (stat == Ok)
160         GdipDisposeImage((GpImage*)bm);
161 
162     bm = (GpBitmap*) 0xdeadbeef;
163     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
164     expect(InvalidParameter, stat);
165     ok( !bm, "expected null bitmap\n" );
166 
167     bm = (GpBitmap*)0xdeadbeef;
168     stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
169     expect(InvalidParameter, stat);
170     ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
171 
172     bm = NULL;
173     stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
174     expect(Ok, stat);
175     ok(NULL != bm, "Expected bitmap to be initialized\n");
176     if (stat == Ok)
177         GdipDisposeImage((GpImage*)bm);
178 
179     bm = (GpBitmap*)0xdeadbeef;
180     stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
181     expect(InvalidParameter, stat);
182     ok( !bm, "expected null bitmap\n" );
183 }
184 
185 static void test_FromGdiDib(void)
186 {
187     GpBitmap *bm;
188     GpStatus stat;
189     BYTE buff[400];
190     BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
191     BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
192     PixelFormat format;
193 
194     bm = NULL;
195 
196     memset(rbmi, 0, sizeof(rbmi));
197 
198     bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
199     bmi->bmiHeader.biWidth = 10;
200     bmi->bmiHeader.biHeight = 10;
201     bmi->bmiHeader.biPlanes = 1;
202     bmi->bmiHeader.biBitCount = 32;
203     bmi->bmiHeader.biCompression = BI_RGB;
204 
205     stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
206     expect(InvalidParameter, stat);
207 
208     stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
209     expect(InvalidParameter, stat);
210 
211     stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
212     expect(InvalidParameter, stat);
213 
214     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
215     expect(Ok, stat);
216     ok(NULL != bm, "Expected bitmap to be initialized\n");
217     if (stat == Ok)
218     {
219         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
220         expect(Ok, stat);
221         expect(PixelFormat32bppRGB, format);
222 
223         GdipDisposeImage((GpImage*)bm);
224     }
225 
226     bmi->bmiHeader.biBitCount = 24;
227     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
228     expect(Ok, stat);
229     ok(NULL != bm, "Expected bitmap to be initialized\n");
230     if (stat == Ok)
231     {
232         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
233         expect(Ok, stat);
234         expect(PixelFormat24bppRGB, format);
235 
236         GdipDisposeImage((GpImage*)bm);
237     }
238 
239     bmi->bmiHeader.biBitCount = 16;
240     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
241     expect(Ok, stat);
242     ok(NULL != bm, "Expected bitmap to be initialized\n");
243     if (stat == Ok)
244     {
245         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
246         expect(Ok, stat);
247         expect(PixelFormat16bppRGB555, format);
248 
249         GdipDisposeImage((GpImage*)bm);
250     }
251 
252     bmi->bmiHeader.biBitCount = 8;
253     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
254     expect(Ok, stat);
255     ok(NULL != bm, "Expected bitmap to be initialized\n");
256     if (stat == Ok)
257     {
258         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
259         expect(Ok, stat);
260         expect(PixelFormat8bppIndexed, format);
261 
262         GdipDisposeImage((GpImage*)bm);
263     }
264 
265     bmi->bmiHeader.biBitCount = 4;
266     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
267     expect(Ok, stat);
268     ok(NULL != bm, "Expected bitmap to be initialized\n");
269     if (stat == Ok)
270     {
271         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
272         expect(Ok, stat);
273         expect(PixelFormat4bppIndexed, format);
274 
275         GdipDisposeImage((GpImage*)bm);
276     }
277 
278     bmi->bmiHeader.biBitCount = 1;
279     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
280     expect(Ok, stat);
281     ok(NULL != bm, "Expected bitmap to be initialized\n");
282     if (stat == Ok)
283     {
284         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
285         expect(Ok, stat);
286         expect(PixelFormat1bppIndexed, format);
287 
288         GdipDisposeImage((GpImage*)bm);
289     }
290 
291     bmi->bmiHeader.biBitCount = 0;
292     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
293     expect(InvalidParameter, stat);
294 }
295 
296 static void test_GetImageDimension(void)
297 {
298     GpBitmap *bm;
299     GpStatus stat;
300     const REAL WIDTH = 10.0, HEIGHT = 20.0;
301     REAL w,h;
302 
303     bm = (GpBitmap*)0xdeadbeef;
304     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
305     expect(Ok,stat);
306     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
307     ok(NULL != bm, "Expected bitmap to not be NULL\n");
308 
309     stat = GdipGetImageDimension(NULL,&w,&h);
310     expect(InvalidParameter, stat);
311 
312     stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
313     expect(InvalidParameter, stat);
314 
315     stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
316     expect(InvalidParameter, stat);
317 
318     w = -1;
319     h = -1;
320     stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
321     expect(Ok, stat);
322     expectf(WIDTH,  w);
323     expectf(HEIGHT, h);
324     GdipDisposeImage((GpImage*)bm);
325 }
326 
327 static void test_GdipImageGetFrameDimensionsCount(void)
328 {
329     GpBitmap *bm;
330     GpStatus stat;
331     const REAL WIDTH = 10.0, HEIGHT = 20.0;
332     UINT w;
333     GUID dimension = {0};
334     UINT count;
335     ARGB color;
336 
337     bm = (GpBitmap*)0xdeadbeef;
338     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
339     expect(Ok,stat);
340     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
341     ok(NULL != bm, "Expected bitmap to not be NULL\n");
342 
343     stat = GdipImageGetFrameDimensionsCount(NULL,&w);
344     expect(InvalidParameter, stat);
345 
346     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
347     expect(InvalidParameter, stat);
348 
349     w = -1;
350     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
351     expect(Ok, stat);
352     expect(1, w);
353 
354     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
355     expect(Ok, stat);
356     expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
357 
358     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
359     expect(InvalidParameter, stat);
360 
361     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
362     expect(InvalidParameter, stat);
363 
364     stat = GdipImageGetFrameCount(NULL, &dimension, &count);
365     expect(InvalidParameter, stat);
366 
367     /* WinXP crashes on this test */
368     if(0)
369     {
370         stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
371         expect(InvalidParameter, stat);
372     }
373 
374     stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
375     expect(Ok, stat);
376 
377     count = 12345;
378     stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
379     expect(Ok, stat);
380     expect(1, count);
381 
382     GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
383 
384     stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
385     expect(Ok, stat);
386 
387     /* SelectActiveFrame has no effect on image data of memory bitmaps */
388     color = 0xdeadbeef;
389     stat = GdipBitmapGetPixel(bm, 0, 0, &color);
390     expect(Ok, stat);
391     expect(0xffffffff, color);
392 
393     GdipDisposeImage((GpImage*)bm);
394 }
395 
396 static void test_LoadingImages(void)
397 {
398     GpStatus stat;
399     GpBitmap *bm;
400     GpImage *img;
401     static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0};
402 
403     stat = GdipCreateBitmapFromFile(0, 0);
404     expect(InvalidParameter, stat);
405 
406     bm = (GpBitmap *)0xdeadbeef;
407     stat = GdipCreateBitmapFromFile(0, &bm);
408     expect(InvalidParameter, stat);
409     ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm);
410 
411     bm = (GpBitmap *)0xdeadbeef;
412     stat = GdipCreateBitmapFromFile(nonexistentW, &bm);
413     todo_wine expect(InvalidParameter, stat);
414     ok(!bm, "returned %p\n", bm);
415 
416     stat = GdipLoadImageFromFile(0, 0);
417     expect(InvalidParameter, stat);
418 
419     img = (GpImage *)0xdeadbeef;
420     stat = GdipLoadImageFromFile(0, &img);
421     expect(InvalidParameter, stat);
422     ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
423 
424     img = (GpImage *)0xdeadbeef;
425     stat = GdipLoadImageFromFile(nonexistentW, &img);
426     todo_wine expect(OutOfMemory, stat);
427     ok(!img, "returned %p\n", img);
428 
429     stat = GdipLoadImageFromFileICM(0, 0);
430     expect(InvalidParameter, stat);
431 
432     img = (GpImage *)0xdeadbeef;
433     stat = GdipLoadImageFromFileICM(0, &img);
434     expect(InvalidParameter, stat);
435     ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
436 
437     img = (GpImage *)0xdeadbeef;
438     stat = GdipLoadImageFromFileICM(nonexistentW, &img);
439     todo_wine expect(OutOfMemory, stat);
440     ok(!img, "returned %p\n", img);
441 }
442 
443 static void test_SavingImages(void)
444 {
445     GpStatus stat;
446     GpBitmap *bm;
447     UINT n;
448     UINT s;
449     const REAL WIDTH = 10.0, HEIGHT = 20.0;
450     REAL w, h;
451     ImageCodecInfo *codecs;
452     static const CHAR filenameA[] = "a.bmp";
453     static const WCHAR filename[] = { 'a','.','b','m','p',0 };
454 
455     codecs = NULL;
456 
457     stat = GdipSaveImageToFile(0, 0, 0, 0);
458     expect(InvalidParameter, stat);
459 
460     bm = NULL;
461     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
462     expect(Ok, stat);
463     if (!bm)
464         return;
465 
466     /* invalid params */
467     stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
468     expect(InvalidParameter, stat);
469 
470     stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
471     expect(InvalidParameter, stat);
472 
473     /* encoder tests should succeed -- already tested */
474     stat = GdipGetImageEncodersSize(&n, &s);
475     if (stat != Ok || n == 0) goto cleanup;
476 
477     codecs = GdipAlloc(s);
478     if (!codecs) goto cleanup;
479 
480     stat = GdipGetImageEncoders(n, s, codecs);
481     if (stat != Ok) goto cleanup;
482 
483     stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
484     expect(Ok, stat);
485 
486     GdipDisposeImage((GpImage*)bm);
487     bm = 0;
488 
489     /* re-load and check image stats */
490     stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
491     expect(Ok, stat);
492     if (stat != Ok) goto cleanup;
493 
494     stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
495     if (stat != Ok) goto cleanup;
496 
497     expectf(WIDTH, w);
498     expectf(HEIGHT, h);
499 
500  cleanup:
501     GdipFree(codecs);
502     if (bm)
503         GdipDisposeImage((GpImage*)bm);
504     ok(DeleteFileA(filenameA), "Delete failed.\n");
505 }
506 
507 static void test_encoders(void)
508 {
509     GpStatus stat;
510     UINT n;
511     UINT s;
512     ImageCodecInfo *codecs;
513     int i;
514     int bmp_found;
515 
516     static const CHAR bmp_format[] = "BMP";
517 
518     stat = GdipGetImageEncodersSize(&n, &s);
519     expect(stat, Ok);
520 
521     codecs = GdipAlloc(s);
522     if (!codecs)
523         return;
524 
525     stat = GdipGetImageEncoders(n, s, NULL);
526     expect(GenericError, stat);
527 
528     stat = GdipGetImageEncoders(0, s, codecs);
529     expect(GenericError, stat);
530 
531     stat = GdipGetImageEncoders(n, s-1, codecs);
532     expect(GenericError, stat);
533 
534     stat = GdipGetImageEncoders(n, s+1, codecs);
535     expect(GenericError, stat);
536 
537     stat = GdipGetImageEncoders(n, s, codecs);
538     expect(stat, Ok);
539 
540     bmp_found = FALSE;
541     for (i = 0; i < n; i++)
542         {
543             CHAR desc[32];
544 
545             WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
546                                 desc, 32, 0, 0);
547 
548             if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
549                                desc, -1,
550                                bmp_format, -1) == CSTR_EQUAL) {
551                 bmp_found = TRUE;
552                 break;
553             }
554         }
555     if (!bmp_found)
556         ok(FALSE, "No BMP codec found.\n");
557 
558     GdipFree(codecs);
559 }
560 
561 static void test_LockBits(void)
562 {
563     GpStatus stat;
564     GpBitmap *bm;
565     GpRect rect;
566     BitmapData bd;
567     const INT WIDTH = 10, HEIGHT = 20;
568     ARGB color;
569     int y;
570 
571     bm = NULL;
572     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
573     expect(Ok, stat);
574 
575     rect.X = 2;
576     rect.Y = 3;
577     rect.Width = 4;
578     rect.Height = 5;
579 
580     stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
581     expect(Ok, stat);
582 
583     stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
584     expect(Ok, stat);
585 
586     /* read-only */
587     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
588     expect(Ok, stat);
589 
590     if (stat == Ok) {
591         expect(0xc3, ((BYTE*)bd.Scan0)[2]);
592         expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
593 
594         ((char*)bd.Scan0)[2] = 0xff;
595 
596         stat = GdipBitmapUnlockBits(bm, &bd);
597         expect(Ok, stat);
598     }
599 
600     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
601     expect(Ok, stat);
602     expect(0xffff0000, color);
603 
604     stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
605     expect(Ok, stat);
606 
607     /* read-only, with NULL rect -> whole bitmap lock */
608     stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
609     expect(Ok, stat);
610     expect(bd.Width,  WIDTH);
611     expect(bd.Height, HEIGHT);
612 
613     if (stat == Ok) {
614         ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
615 
616         stat = GdipBitmapUnlockBits(bm, &bd);
617         expect(Ok, stat);
618     }
619 
620     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
621     expect(Ok, stat);
622     expect(0xffff0000, color);
623 
624     /* read-only, consecutive */
625     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
626     expect(Ok, stat);
627 
628     if (stat == Ok) {
629         stat = GdipBitmapUnlockBits(bm, &bd);
630         expect(Ok, stat);
631     }
632 
633     stat = GdipDisposeImage((GpImage*)bm);
634     expect(Ok, stat);
635     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
636     expect(Ok, stat);
637 
638     /* read x2 */
639     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
640     expect(Ok, stat);
641     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
642     expect(WrongState, stat);
643 
644     stat = GdipBitmapUnlockBits(bm, &bd);
645     expect(Ok, stat);
646 
647     stat = GdipDisposeImage((GpImage*)bm);
648     expect(Ok, stat);
649     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
650     expect(Ok, stat);
651 
652     stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
653     expect(Ok, stat);
654 
655     stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
656     expect(Ok, stat);
657 
658     /* write, no conversion */
659     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
660     expect(Ok, stat);
661 
662     if (stat == Ok) {
663         /* all bits are readable, inside the rect or not */
664         expect(0xff, ((BYTE*)bd.Scan0)[2]);
665         expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
666 
667         stat = GdipBitmapUnlockBits(bm, &bd);
668         expect(Ok, stat);
669     }
670 
671     /* read, conversion */
672     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
673     expect(Ok, stat);
674 
675     if (stat == Ok) {
676         expect(0xff, ((BYTE*)bd.Scan0)[2]);
677         if (0)
678             /* Areas outside the rectangle appear to be uninitialized */
679             ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
680 
681         ((BYTE*)bd.Scan0)[2] = 0xc3;
682 
683         stat = GdipBitmapUnlockBits(bm, &bd);
684         expect(Ok, stat);
685     }
686 
687     /* writes do not work in read mode if there was a conversion */
688     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
689     expect(Ok, stat);
690     expect(0xffff0000, color);
691 
692     /* read/write, conversion */
693     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
694     expect(Ok, stat);
695 
696     if (stat == Ok) {
697         expect(0xff, ((BYTE*)bd.Scan0)[2]);
698         ((BYTE*)bd.Scan0)[1] = 0x88;
699         if (0)
700             /* Areas outside the rectangle appear to be uninitialized */
701             ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
702 
703         stat = GdipBitmapUnlockBits(bm, &bd);
704         expect(Ok, stat);
705     }
706 
707     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
708     expect(Ok, stat);
709     expect(0xffff8800, color);
710 
711     /* write, conversion */
712     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
713     expect(Ok, stat);
714 
715     if (stat == Ok) {
716         if (0)
717         {
718             /* This is completely uninitialized. */
719             ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
720             ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
721         }
722 
723         /* Initialize the buffer so the unlock doesn't access undefined memory */
724         for (y=0; y<5; y++)
725             memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
726 
727         ((BYTE*)bd.Scan0)[0] = 0x12;
728         ((BYTE*)bd.Scan0)[1] = 0x34;
729         ((BYTE*)bd.Scan0)[2] = 0x56;
730 
731         stat = GdipBitmapUnlockBits(bm, &bd);
732         expect(Ok, stat);
733     }
734 
735     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
736     expect(Ok, stat);
737     expect(0xff563412, color);
738 
739     stat = GdipBitmapGetPixel(bm, 2, 8, &color);
740     expect(Ok, stat);
741     expect(0xffc30000, color);
742 
743     stat = GdipDisposeImage((GpImage*)bm);
744     expect(Ok, stat);
745     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
746     expect(Ok, stat);
747 
748     /* write, no modification */
749     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
750     expect(Ok, stat);
751 
752     if (stat == Ok) {
753         stat = GdipBitmapUnlockBits(bm, &bd);
754         expect(Ok, stat);
755     }
756 
757     /* write, consecutive */
758     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
759     expect(Ok, stat);
760 
761     if (stat == Ok) {
762         stat = GdipBitmapUnlockBits(bm, &bd);
763         expect(Ok, stat);
764     }
765 
766     stat = GdipDisposeImage((GpImage*)bm);
767     expect(Ok, stat);
768     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
769     expect(Ok, stat);
770 
771     /* write, modify */
772     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
773     expect(Ok, stat);
774 
775     if (stat == Ok) {
776         if (bd.Scan0)
777             ((char*)bd.Scan0)[2] = 0xff;
778 
779         stat = GdipBitmapUnlockBits(bm, &bd);
780         expect(Ok, stat);
781     }
782 
783     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
784     expect(Ok, stat);
785     expect(0xffff0000, color);
786 
787     stat = GdipDisposeImage((GpImage*)bm);
788     expect(Ok, stat);
789 
790     /* dispose locked */
791     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
792     expect(Ok, stat);
793     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
794     expect(Ok, stat);
795     stat = GdipDisposeImage((GpImage*)bm);
796     expect(Ok, stat);
797 }
798 
799 static void test_LockBits_UserBuf(void)
800 {
801     GpStatus stat;
802     GpBitmap *bm;
803     GpRect rect;
804     BitmapData bd;
805     const INT WIDTH = 10, HEIGHT = 20;
806     DWORD bits[200];
807     ARGB color;
808 
809     bm = NULL;
810     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
811     expect(Ok, stat);
812 
813     memset(bits, 0xaa, sizeof(bits));
814 
815     rect.X = 2;
816     rect.Y = 3;
817     rect.Width = 4;
818     rect.Height = 5;
819 
820     bd.Width = 4;
821     bd.Height = 6;
822     bd.Stride = WIDTH * 4;
823     bd.PixelFormat = PixelFormat32bppARGB;
824     bd.Scan0 = &bits[2+3*WIDTH];
825     bd.Reserved = 0xaaaaaaaa;
826 
827     /* read-only */
828     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
829     expect(Ok, stat);
830 
831     expect(0xaaaaaaaa, bits[0]);
832     expect(0, bits[2+3*WIDTH]);
833 
834     bits[2+3*WIDTH] = 0xdeadbeef;
835 
836     if (stat == Ok) {
837         stat = GdipBitmapUnlockBits(bm, &bd);
838         expect(Ok, stat);
839     }
840 
841     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
842     expect(Ok, stat);
843     expect(0, color);
844 
845     /* write-only */
846     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
847     expect(Ok, stat);
848 
849     expect(0xdeadbeef, bits[2+3*WIDTH]);
850     bits[2+3*WIDTH] = 0x12345678;
851 
852     if (stat == Ok) {
853         stat = GdipBitmapUnlockBits(bm, &bd);
854         expect(Ok, stat);
855     }
856 
857     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
858     expect(Ok, stat);
859     expect(0x12345678, color);
860 
861     bits[2+3*WIDTH] = 0;
862 
863     /* read/write */
864     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
865     expect(Ok, stat);
866 
867     expect(0x12345678, bits[2+3*WIDTH]);
868     bits[2+3*WIDTH] = 0xdeadbeef;
869 
870     if (stat == Ok) {
871         stat = GdipBitmapUnlockBits(bm, &bd);
872         expect(Ok, stat);
873     }
874 
875     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
876     expect(Ok, stat);
877     expect(0xdeadbeef, color);
878 
879     stat = GdipDisposeImage((GpImage*)bm);
880     expect(Ok, stat);
881 }
882 
883 struct BITMAPINFOWITHBITFIELDS
884 {
885     BITMAPINFOHEADER bmiHeader;
886     DWORD masks[3];
887 };
888 
889 union BITMAPINFOUNION
890 {
891     BITMAPINFO bi;
892     struct BITMAPINFOWITHBITFIELDS bf;
893 };
894 
895 static void test_GdipCreateBitmapFromHBITMAP(void)
896 {
897     GpBitmap* gpbm = NULL;
898     HBITMAP hbm = NULL;
899     HPALETTE hpal = NULL;
900     GpStatus stat;
901     BYTE buff[1000];
902     LOGPALETTE* LogPal = NULL;
903     REAL width, height;
904     const REAL WIDTH1 = 5;
905     const REAL HEIGHT1 = 15;
906     const REAL WIDTH2 = 10;
907     const REAL HEIGHT2 = 20;
908     HDC hdc;
909     union BITMAPINFOUNION bmi;
910     BYTE *bits;
911     PixelFormat format;
912 
913     stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
914     expect(InvalidParameter, stat);
915 
916     hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
917     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
918     expect(InvalidParameter, stat);
919 
920     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
921     expect(Ok, stat);
922     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
923     expectf(WIDTH1,  width);
924     expectf(HEIGHT1, height);
925     if (stat == Ok)
926         GdipDisposeImage((GpImage*)gpbm);
927     DeleteObject(hbm);
928 
929     memset(buff, 0, sizeof(buff));
930     hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
931     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
932     expect(Ok, stat);
933     /* raw format */
934     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
935 
936     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
937     expectf(WIDTH2,  width);
938     expectf(HEIGHT2, height);
939     if (stat == Ok)
940         GdipDisposeImage((GpImage*)gpbm);
941     DeleteObject(hbm);
942 
943     hdc = CreateCompatibleDC(0);
944     ok(hdc != NULL, "CreateCompatibleDC failed\n");
945     bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
946     bmi.bi.bmiHeader.biHeight = HEIGHT1;
947     bmi.bi.bmiHeader.biWidth = WIDTH1;
948     bmi.bi.bmiHeader.biBitCount = 24;
949     bmi.bi.bmiHeader.biPlanes = 1;
950     bmi.bi.bmiHeader.biCompression = BI_RGB;
951     bmi.bi.bmiHeader.biClrUsed = 0;
952 
953     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
954     ok(hbm != NULL, "CreateDIBSection failed\n");
955 
956     bits[0] = 0;
957 
958     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
959     expect(Ok, stat);
960     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
961     expectf(WIDTH1,  width);
962     expectf(HEIGHT1, height);
963     if (stat == Ok)
964     {
965         /* test whether writing to the bitmap affects the original */
966         stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
967         expect(Ok, stat);
968 
969         expect(0, bits[0]);
970 
971         GdipDisposeImage((GpImage*)gpbm);
972     }
973 
974     LogPal = GdipAlloc(sizeof(LOGPALETTE));
975     ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
976     LogPal->palVersion = 0x300;
977     LogPal->palNumEntries = 1;
978     hpal = CreatePalette(LogPal);
979     ok(hpal != NULL, "CreatePalette failed\n");
980     GdipFree(LogPal);
981 
982     stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
983     expect(Ok, stat);
984 
985     if (stat == Ok)
986         GdipDisposeImage((GpImage*)gpbm);
987 
988     DeleteObject(hpal);
989     DeleteObject(hbm);
990 
991     /* 16-bit 555 dib, rgb */
992     bmi.bi.bmiHeader.biBitCount = 16;
993     bmi.bi.bmiHeader.biCompression = BI_RGB;
994 
995     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
996     ok(hbm != NULL, "CreateDIBSection failed\n");
997 
998     bits[0] = 0;
999 
1000     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1001     expect(Ok, stat);
1002 
1003     if (stat == Ok)
1004     {
1005         stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1006         expect(Ok, stat);
1007         expectf(WIDTH1,  width);
1008         expectf(HEIGHT1, height);
1009 
1010         stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1011         expect(Ok, stat);
1012         expect(PixelFormat16bppRGB555, format);
1013 
1014         GdipDisposeImage((GpImage*)gpbm);
1015     }
1016     DeleteObject(hbm);
1017 
1018     /* 16-bit 555 dib, with bitfields */
1019     bmi.bi.bmiHeader.biSize = sizeof(bmi);
1020     bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
1021     bmi.bf.masks[0] = 0x7c00;
1022     bmi.bf.masks[1] = 0x3e0;
1023     bmi.bf.masks[2] = 0x1f;
1024 
1025     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1026     ok(hbm != NULL, "CreateDIBSection failed\n");
1027 
1028     bits[0] = 0;
1029 
1030     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1031     expect(Ok, stat);
1032 
1033     if (stat == Ok)
1034     {
1035         stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1036         expect(Ok, stat);
1037         expectf(WIDTH1,  width);
1038         expectf(HEIGHT1, height);
1039 
1040         stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1041         expect(Ok, stat);
1042         expect(PixelFormat16bppRGB555, format);
1043 
1044         GdipDisposeImage((GpImage*)gpbm);
1045     }
1046     DeleteObject(hbm);
1047 
1048     /* 16-bit 565 dib, with bitfields */
1049     bmi.bf.masks[0] = 0xf800;
1050     bmi.bf.masks[1] = 0x7e0;
1051     bmi.bf.masks[2] = 0x1f;
1052 
1053     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1054     ok(hbm != NULL, "CreateDIBSection failed\n");
1055 
1056     bits[0] = 0;
1057 
1058     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1059     expect(Ok, stat);
1060 
1061     if (stat == Ok)
1062     {
1063         stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1064         expect(Ok, stat);
1065         expectf(WIDTH1,  width);
1066         expectf(HEIGHT1, height);
1067 
1068         stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1069         expect(Ok, stat);
1070         expect(PixelFormat16bppRGB565, format);
1071 
1072         GdipDisposeImage((GpImage*)gpbm);
1073     }
1074     DeleteObject(hbm);
1075 
1076     DeleteDC(hdc);
1077 }
1078 
1079 static void test_GdipGetImageFlags(void)
1080 {
1081     GpImage *img;
1082     GpStatus stat;
1083     UINT flags;
1084 
1085     img = (GpImage*)0xdeadbeef;
1086 
1087     stat = GdipGetImageFlags(NULL, NULL);
1088     expect(InvalidParameter, stat);
1089 
1090     stat = GdipGetImageFlags(NULL, &flags);
1091     expect(InvalidParameter, stat);
1092 
1093     stat = GdipGetImageFlags(img, NULL);
1094     expect(InvalidParameter, stat);
1095 
1096     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1097     expect(Ok, stat);
1098     stat = GdipGetImageFlags(img, &flags);
1099     expect(Ok, stat);
1100     expect(ImageFlagsHasAlpha, flags);
1101     GdipDisposeImage(img);
1102 
1103     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1104     expect(Ok, stat);
1105     stat = GdipGetImageFlags(img, &flags);
1106     expect(Ok, stat);
1107     expect(ImageFlagsHasAlpha, flags);
1108     GdipDisposeImage(img);
1109 
1110     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1111     expect(Ok, stat);
1112     stat = GdipGetImageFlags(img, &flags);
1113     expect(Ok, stat);
1114     expect(ImageFlagsHasAlpha, flags);
1115     GdipDisposeImage(img);
1116 
1117     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1118     expect(Ok, stat);
1119     stat = GdipGetImageFlags(img, &flags);
1120     expect(Ok, stat);
1121     expect(ImageFlagsNone, flags);
1122     GdipDisposeImage(img);
1123 
1124     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1125     expect(Ok, stat);
1126     stat = GdipGetImageFlags(img, &flags);
1127     expect(Ok, stat);
1128     expect(ImageFlagsNone, flags);
1129     GdipDisposeImage(img);
1130 
1131     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1132     expect(Ok, stat);
1133     stat = GdipGetImageFlags(img, &flags);
1134     expect(Ok, stat);
1135     expect(ImageFlagsNone, flags);
1136     GdipDisposeImage(img);
1137 
1138     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1139     expect(Ok, stat);
1140     stat = GdipGetImageFlags(img, &flags);
1141     expect(Ok, stat);
1142     expect(ImageFlagsHasAlpha, flags);
1143     GdipDisposeImage(img);
1144 
1145     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1146     expect(Ok, stat);
1147     stat = GdipGetImageFlags(img, &flags);
1148     expect(Ok, stat);
1149     expect(ImageFlagsNone, flags);
1150     GdipDisposeImage(img);
1151 
1152     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1153     expect(Ok, stat);
1154     stat = GdipGetImageFlags(img, &flags);
1155     expect(Ok, stat);
1156     expect(ImageFlagsNone, flags);
1157     GdipDisposeImage(img);
1158 
1159     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1160     expect(Ok, stat);
1161     stat = GdipGetImageFlags(img, &flags);
1162     expect(Ok, stat);
1163     expect(ImageFlagsHasAlpha, flags);
1164     GdipDisposeImage(img);
1165 
1166     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1167     expect(Ok, stat);
1168     stat = GdipGetImageFlags(img, &flags);
1169     expect(Ok, stat);
1170     expect(ImageFlagsHasAlpha, flags);
1171     GdipDisposeImage(img);
1172 
1173     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1174     expect(Ok, stat);
1175     if (stat == Ok)
1176     {
1177         stat = GdipGetImageFlags(img, &flags);
1178         expect(Ok, stat);
1179         expect(ImageFlagsNone, flags);
1180         GdipDisposeImage(img);
1181     }
1182 
1183     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1184     expect(Ok, stat);
1185     if (stat == Ok)
1186     {
1187         expect(Ok, stat);
1188         stat = GdipGetImageFlags(img, &flags);
1189         expect(Ok, stat);
1190         expect(ImageFlagsHasAlpha, flags);
1191         GdipDisposeImage(img);
1192     }
1193 
1194     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1195     expect(Ok, stat);
1196     if (stat == Ok)
1197     {
1198         expect(Ok, stat);
1199         stat = GdipGetImageFlags(img, &flags);
1200         expect(Ok, stat);
1201         expect(ImageFlagsHasAlpha, flags);
1202         GdipDisposeImage(img);
1203     }
1204 }
1205 
1206 static void test_GdipCloneImage(void)
1207 {
1208     GpStatus stat;
1209     GpRectF rectF;
1210     GpUnit unit;
1211     GpBitmap *bm;
1212     GpImage *image_src, *image_dest = NULL;
1213     const INT WIDTH = 10, HEIGHT = 20;
1214 
1215     /* Create an image, clone it, delete the original, make sure the copy works */
1216     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1217     expect(Ok, stat);
1218     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1219 
1220     image_src = ((GpImage*)bm);
1221     stat = GdipCloneImage(image_src, &image_dest);
1222     expect(Ok, stat);
1223     expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1224 
1225     stat = GdipDisposeImage((GpImage*)bm);
1226     expect(Ok, stat);
1227     stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1228     expect(Ok, stat);
1229 
1230     /* Treat FP values carefully */
1231     expectf((REAL)WIDTH, rectF.Width);
1232     expectf((REAL)HEIGHT, rectF.Height);
1233 
1234     stat = GdipDisposeImage(image_dest);
1235     expect(Ok, stat);
1236 }
1237 
1238 static void test_testcontrol(void)
1239 {
1240     GpStatus stat;
1241     DWORD param;
1242 
1243     param = 0;
1244     stat = GdipTestControl(TestControlGetBuildNumber, &param);
1245     expect(Ok, stat);
1246     ok(param != 0, "Build number expected, got %u\n", param);
1247 }
1248 
1249 static void test_fromhicon(void)
1250 {
1251     static const BYTE bmp_bits[1024];
1252     HBITMAP hbmMask, hbmColor;
1253     ICONINFO info;
1254     HICON hIcon;
1255     GpStatus stat;
1256     GpBitmap *bitmap = NULL;
1257     UINT dim;
1258     ImageType type;
1259     PixelFormat format;
1260 
1261     /* NULL */
1262     stat = GdipCreateBitmapFromHICON(NULL, NULL);
1263     expect(InvalidParameter, stat);
1264     stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1265     expect(InvalidParameter, stat);
1266 
1267     /* color icon 1 bit */
1268     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1269     ok(hbmMask != 0, "CreateBitmap failed\n");
1270     hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1271     ok(hbmColor != 0, "CreateBitmap failed\n");
1272     info.fIcon = TRUE;
1273     info.xHotspot = 8;
1274     info.yHotspot = 8;
1275     info.hbmMask = hbmMask;
1276     info.hbmColor = hbmColor;
1277     hIcon = CreateIconIndirect(&info);
1278     ok(hIcon != 0, "CreateIconIndirect failed\n");
1279     DeleteObject(hbmMask);
1280     DeleteObject(hbmColor);
1281 
1282     stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1283     ok(stat == Ok ||
1284        broken(stat == InvalidParameter), /* Win98 */
1285        "Expected Ok, got %.8x\n", stat);
1286     if(stat == Ok){
1287        /* check attributes */
1288        stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1289        expect(Ok, stat);
1290        expect(16, dim);
1291        stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1292        expect(Ok, stat);
1293        expect(16, dim);
1294        stat = GdipGetImageType((GpImage*)bitmap, &type);
1295        expect(Ok, stat);
1296        expect(ImageTypeBitmap, type);
1297        stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1298        expect(Ok, stat);
1299        expect(PixelFormat32bppARGB, format);
1300        /* raw format */
1301        expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1302        GdipDisposeImage((GpImage*)bitmap);
1303     }
1304     DestroyIcon(hIcon);
1305 
1306     /* color icon 8 bpp */
1307     hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1308     ok(hbmMask != 0, "CreateBitmap failed\n");
1309     hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1310     ok(hbmColor != 0, "CreateBitmap failed\n");
1311     info.fIcon = TRUE;
1312     info.xHotspot = 8;
1313     info.yHotspot = 8;
1314     info.hbmMask = hbmMask;
1315     info.hbmColor = hbmColor;
1316     hIcon = CreateIconIndirect(&info);
1317     ok(hIcon != 0, "CreateIconIndirect failed\n");
1318     DeleteObject(hbmMask);
1319     DeleteObject(hbmColor);
1320 
1321     stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1322     expect(Ok, stat);
1323     if(stat == Ok){
1324         /* check attributes */
1325         stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1326         expect(Ok, stat);
1327         expect(16, dim);
1328         stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1329         expect(Ok, stat);
1330         expect(16, dim);
1331         stat = GdipGetImageType((GpImage*)bitmap, &type);
1332         expect(Ok, stat);
1333         expect(ImageTypeBitmap, type);
1334         stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1335 	expect(Ok, stat);
1336         expect(PixelFormat32bppARGB, format);
1337         /* raw format */
1338         expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1339         GdipDisposeImage((GpImage*)bitmap);
1340     }
1341     DestroyIcon(hIcon);
1342 }
1343 
1344 /* 1x1 pixel png */
1345 static const unsigned char pngimage[285] = {
1346 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1347 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1348 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1349 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1350 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1351 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1352 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1353 };
1354 /* 1x1 pixel gif */
1355 static const unsigned char gifimage[35] = {
1356 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1357 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1358 0x01,0x00,0x3b
1359 };
1360 /* 1x1 pixel transparent gif */
1361 static const unsigned char transparentgif[] = {
1362 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
1363 0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,
1364 0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
1365 };
1366 /* 1x1 pixel bmp */
1367 static const unsigned char bmpimage[66] = {
1368 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1369 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1370 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1371 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1372 0x00,0x00
1373 };
1374 /* 1x1 pixel jpg */
1375 static const unsigned char jpgimage[285] = {
1376 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1377 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1378 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1379 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1380 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1381 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1382 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1383 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1384 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1385 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1386 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1387 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1388 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1389 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1390 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1391 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1392 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1393 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1394 };
1395 /* 1x1 pixel tiff */
1396 static const unsigned char tiffimage[] = {
1397 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1398 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1399 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1400 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1401 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1402 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1403 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1404 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1405 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1406 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1407 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1408 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1409 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1410 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1411 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1412 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1413 0x00,0x00,0x00,0x01
1414 };
1415 /* 320x320 twip wmf */
1416 static const unsigned char wmfimage[180] = {
1417 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1418 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1419 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1420 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1421 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1422 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1423 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1424 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1425 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1426 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1427 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1428 0x00,0x00,0x00,0x00
1429 };
1430 static void test_getrawformat(void)
1431 {
1432     test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG,  __LINE__, FALSE);
1433     test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF,  __LINE__, FALSE);
1434     test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP,  __LINE__, FALSE);
1435     test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1436     test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1437     test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1438 }
1439 
1440 static void test_loadwmf(void)
1441 {
1442     LPSTREAM stream;
1443     HGLOBAL  hglob;
1444     LPBYTE   data;
1445     HRESULT  hres;
1446     GpStatus stat;
1447     GpImage *img;
1448     GpRectF bounds;
1449     GpUnit unit;
1450     REAL res = 12345.0;
1451     MetafileHeader header;
1452 
1453     hglob = GlobalAlloc (0, sizeof(wmfimage));
1454     data = GlobalLock (hglob);
1455     memcpy(data, wmfimage, sizeof(wmfimage));
1456     GlobalUnlock(hglob); data = NULL;
1457 
1458     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1459     ok(hres == S_OK, "Failed to create a stream\n");
1460     if(hres != S_OK) return;
1461 
1462     stat = GdipLoadImageFromStream(stream, &img);
1463     ok(stat == Ok, "Failed to create a Bitmap\n");
1464     if(stat != Ok){
1465         IStream_Release(stream);
1466         return;
1467     }
1468 
1469     IStream_Release(stream);
1470 
1471     stat = GdipGetImageBounds(img, &bounds, &unit);
1472     expect(Ok, stat);
1473     expect(UnitPixel, unit);
1474     expectf(0.0, bounds.X);
1475     expectf(0.0, bounds.Y);
1476     expectf(320.0, bounds.Width);
1477     expectf(320.0, bounds.Height);
1478 
1479     stat = GdipGetImageHorizontalResolution(img, &res);
1480     expect(Ok, stat);
1481     expectf(1440.0, res);
1482 
1483     stat = GdipGetImageVerticalResolution(img, &res);
1484     expect(Ok, stat);
1485     expectf(1440.0, res);
1486 
1487     memset(&header, 0, sizeof(header));
1488     stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1489     expect(Ok, stat);
1490     if (stat == Ok)
1491     {
1492         expect(MetafileTypeWmfPlaceable, header.Type);
1493         todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1494         todo_wine expect(0x300, header.Version);
1495         expect(0, header.EmfPlusFlags);
1496         expectf(1440.0, header.DpiX);
1497         expectf(1440.0, header.DpiY);
1498         expect(0, header.X);
1499         expect(0, header.Y);
1500         expect(320, header.Width);
1501         expect(320, header.Height);
1502         expect(1, U(header).WmfHeader.mtType);
1503         expect(0, header.EmfPlusHeaderSize);
1504         expect(0, header.LogicalDpiX);
1505         expect(0, header.LogicalDpiY);
1506     }
1507 
1508     GdipDisposeImage(img);
1509 }
1510 
1511 static void test_createfromwmf(void)
1512 {
1513     HMETAFILE hwmf;
1514     GpImage *img;
1515     GpStatus stat;
1516     GpRectF bounds;
1517     GpUnit unit;
1518     REAL res = 12345.0;
1519     MetafileHeader header;
1520 
1521     hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1522         wmfimage+sizeof(WmfPlaceableFileHeader));
1523     ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1524 
1525     stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1526         (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1527     expect(Ok, stat);
1528 
1529     stat = GdipGetImageBounds(img, &bounds, &unit);
1530     expect(Ok, stat);
1531     expect(UnitPixel, unit);
1532     expectf(0.0, bounds.X);
1533     expectf(0.0, bounds.Y);
1534     expectf(320.0, bounds.Width);
1535     expectf(320.0, bounds.Height);
1536 
1537     stat = GdipGetImageHorizontalResolution(img, &res);
1538     expect(Ok, stat);
1539     expectf(1440.0, res);
1540 
1541     stat = GdipGetImageVerticalResolution(img, &res);
1542     expect(Ok, stat);
1543     expectf(1440.0, res);
1544 
1545     memset(&header, 0, sizeof(header));
1546     stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1547     expect(Ok, stat);
1548     if (stat == Ok)
1549     {
1550         expect(MetafileTypeWmfPlaceable, header.Type);
1551         todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1552         todo_wine expect(0x300, header.Version);
1553         expect(0, header.EmfPlusFlags);
1554         expectf(1440.0, header.DpiX);
1555         expectf(1440.0, header.DpiY);
1556         expect(0, header.X);
1557         expect(0, header.Y);
1558         expect(320, header.Width);
1559         expect(320, header.Height);
1560         expect(1, U(header).WmfHeader.mtType);
1561         expect(0, header.EmfPlusHeaderSize);
1562         expect(0, header.LogicalDpiX);
1563         expect(0, header.LogicalDpiY);
1564     }
1565 
1566     GdipDisposeImage(img);
1567 }
1568 
1569 static void test_createfromwmf_noplaceable(void)
1570 {
1571     HMETAFILE hwmf;
1572     GpImage *img;
1573     GpStatus stat;
1574 
1575     hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1576         wmfimage+sizeof(WmfPlaceableFileHeader));
1577     ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1578 
1579     stat = GdipCreateMetafileFromWmf(hwmf, TRUE, NULL, (GpMetafile**)&img);
1580     expect(Ok, stat);
1581 
1582     GdipDisposeImage(img);
1583 }
1584 
1585 static void test_resolution(void)
1586 {
1587     GpStatus stat;
1588     GpBitmap *bitmap;
1589     GpGraphics *graphics;
1590     REAL res=-1.0;
1591     HDC screendc;
1592     int screenxres, screenyres;
1593 
1594     /* create Bitmap */
1595     stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1596     expect(Ok, stat);
1597 
1598     /* test invalid values */
1599     stat = GdipGetImageHorizontalResolution(NULL, &res);
1600     expect(InvalidParameter, stat);
1601 
1602     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1603     expect(InvalidParameter, stat);
1604 
1605     stat = GdipGetImageVerticalResolution(NULL, &res);
1606     expect(InvalidParameter, stat);
1607 
1608     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1609     expect(InvalidParameter, stat);
1610 
1611     stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1612     expect(InvalidParameter, stat);
1613 
1614     stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1615     expect(InvalidParameter, stat);
1616 
1617     /* defaults to screen resolution */
1618     screendc = GetDC(0);
1619 
1620     screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1621     screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1622 
1623     ReleaseDC(0, screendc);
1624 
1625     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1626     expect(Ok, stat);
1627     expectf((REAL)screenxres, res);
1628 
1629     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1630     expect(Ok, stat);
1631     expectf((REAL)screenyres, res);
1632 
1633     stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1634     expect(Ok, stat);
1635     stat = GdipGetDpiX(graphics, &res);
1636     expect(Ok, stat);
1637     expectf((REAL)screenxres, res);
1638     stat = GdipGetDpiY(graphics, &res);
1639     expect(Ok, stat);
1640     expectf((REAL)screenyres, res);
1641 
1642     /* test changing the resolution */
1643     stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1644     expect(Ok, stat);
1645 
1646     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1647     expect(Ok, stat);
1648     expectf(screenxres*2.0, res);
1649 
1650     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1651     expect(Ok, stat);
1652     expectf(screenyres*3.0, res);
1653 
1654     stat = GdipGetDpiX(graphics, &res);
1655     expect(Ok, stat);
1656     expectf((REAL)screenxres, res);
1657     stat = GdipGetDpiY(graphics, &res);
1658     expect(Ok, stat);
1659     expectf((REAL)screenyres, res);
1660 
1661     stat = GdipDeleteGraphics(graphics);
1662     expect(Ok, stat);
1663 
1664     stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1665     expect(Ok, stat);
1666     stat = GdipGetDpiX(graphics, &res);
1667     expect(Ok, stat);
1668     expectf(screenxres*2.0, res);
1669     stat = GdipGetDpiY(graphics, &res);
1670     expect(Ok, stat);
1671     expectf(screenyres*3.0, res);
1672     stat = GdipDeleteGraphics(graphics);
1673     expect(Ok, stat);
1674 
1675     stat = GdipDisposeImage((GpImage*)bitmap);
1676     expect(Ok, stat);
1677 }
1678 
1679 static void test_createhbitmap(void)
1680 {
1681     GpStatus stat;
1682     GpBitmap *bitmap;
1683     HBITMAP hbitmap, oldhbitmap;
1684     BITMAP bm;
1685     int ret;
1686     HDC hdc;
1687     COLORREF pixel;
1688     BYTE bits[640];
1689     BitmapData lockeddata;
1690 
1691     memset(bits, 0x68, 640);
1692 
1693     /* create Bitmap */
1694     stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1695     expect(Ok, stat);
1696 
1697     /* test NULL values */
1698     stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1699     expect(InvalidParameter, stat);
1700 
1701     stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1702     expect(InvalidParameter, stat);
1703 
1704     /* create HBITMAP */
1705     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1706     expect(Ok, stat);
1707 
1708     if (stat == Ok)
1709     {
1710         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1711         expect(sizeof(BITMAP), ret);
1712 
1713         expect(0, bm.bmType);
1714         expect(10, bm.bmWidth);
1715         expect(20, bm.bmHeight);
1716         expect(40, bm.bmWidthBytes);
1717         expect(1, bm.bmPlanes);
1718         expect(32, bm.bmBitsPixel);
1719         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1720 
1721         if (bm.bmBits)
1722         {
1723             DWORD val = *(DWORD*)bm.bmBits;
1724             ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1725         }
1726 
1727         hdc = CreateCompatibleDC(NULL);
1728 
1729         oldhbitmap = SelectObject(hdc, hbitmap);
1730         pixel = GetPixel(hdc, 5, 5);
1731         SelectObject(hdc, oldhbitmap);
1732 
1733         DeleteDC(hdc);
1734 
1735         expect(0x686868, pixel);
1736 
1737         DeleteObject(hbitmap);
1738     }
1739 
1740     stat = GdipDisposeImage((GpImage*)bitmap);
1741     expect(Ok, stat);
1742 
1743     /* make (1,0) have no alpha and (2,0) a different blue value. */
1744     bits[7] = 0x00;
1745     bits[8] = 0x40;
1746 
1747     /* create alpha Bitmap */
1748     stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1749     expect(Ok, stat);
1750 
1751     /* create HBITMAP */
1752     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1753     expect(Ok, stat);
1754 
1755     if (stat == Ok)
1756     {
1757         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1758         expect(sizeof(BITMAP), ret);
1759 
1760         expect(0, bm.bmType);
1761         expect(8, bm.bmWidth);
1762         expect(20, bm.bmHeight);
1763         expect(32, bm.bmWidthBytes);
1764         expect(1, bm.bmPlanes);
1765         expect(32, bm.bmBitsPixel);
1766         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1767 
1768         if (bm.bmBits)
1769         {
1770             DWORD val = *(DWORD*)bm.bmBits;
1771             ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1772             val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1773             ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1774         }
1775 
1776         hdc = CreateCompatibleDC(NULL);
1777 
1778         oldhbitmap = SelectObject(hdc, hbitmap);
1779         pixel = GetPixel(hdc, 5, 5);
1780         expect(0x2a2a2a, pixel);
1781         pixel = GetPixel(hdc, 1, 0);
1782         expect(0x0, pixel);
1783 
1784         SelectObject(hdc, oldhbitmap);
1785 
1786         DeleteDC(hdc);
1787 
1788 
1789         DeleteObject(hbitmap);
1790     }
1791 
1792     /* create HBITMAP with bkgnd colour */
1793     /* gdiplus.dll 5.1 is broken and only applies the blue value */
1794     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1795     expect(Ok, stat);
1796 
1797     if (stat == Ok)
1798     {
1799         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1800         expect(sizeof(BITMAP), ret);
1801 
1802         expect(0, bm.bmType);
1803         expect(8, bm.bmWidth);
1804         expect(20, bm.bmHeight);
1805         expect(32, bm.bmWidthBytes);
1806         expect(1, bm.bmPlanes);
1807         expect(32, bm.bmBitsPixel);
1808         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1809 
1810         if (bm.bmBits)
1811         {
1812             DWORD val = *(DWORD*)bm.bmBits;
1813             ok(val == 0x68c12ac1 || broken(val == 0x682a2ac1), "got %x, expected 0x68c12ac1\n", val);
1814             val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1815             ok(val == 0xff00ff || broken(val == 0xff), "got %x, expected 0xff00ff\n", val);
1816         }
1817 
1818         hdc = CreateCompatibleDC(NULL);
1819 
1820         oldhbitmap = SelectObject(hdc, hbitmap);
1821         pixel = GetPixel(hdc, 5, 5);
1822         ok(pixel == 0xc12ac1 || broken(pixel == 0xc12a2a), "got %x, expected 0xc12ac1\n", pixel);
1823         pixel = GetPixel(hdc, 1, 0);
1824         ok(pixel == 0xff00ff || broken(pixel == 0xff0000), "got %x, expected 0xff00ff\n", pixel);
1825         pixel = GetPixel(hdc, 2, 0);
1826         ok(pixel == 0xb12ac1 || broken(pixel == 0xb12a2a), "got %x, expected 0xb12ac1\n", pixel);
1827 
1828         SelectObject(hdc, oldhbitmap);
1829         DeleteDC(hdc);
1830         DeleteObject(hbitmap);
1831     }
1832 
1833     /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1834     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1835     expect(Ok, stat);
1836 
1837     if (stat == Ok)
1838     {
1839         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1840         expect(sizeof(BITMAP), ret);
1841 
1842         expect(0, bm.bmType);
1843         expect(8, bm.bmWidth);
1844         expect(20, bm.bmHeight);
1845         expect(32, bm.bmWidthBytes);
1846         expect(1, bm.bmPlanes);
1847         expect(32, bm.bmBitsPixel);
1848         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1849 
1850         if (bm.bmBits)
1851         {
1852             DWORD val = *(DWORD*)bm.bmBits;
1853             ok(val == 0x68c12ac1 || broken(val == 0x682a2ac1), "got %x, expected 0x68c12ac1\n", val);
1854             val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1855             ok(val == 0xff00ff || broken(val == 0xff), "got %x, expected 0xff00ff\n", val);
1856         }
1857 
1858         hdc = CreateCompatibleDC(NULL);
1859 
1860         oldhbitmap = SelectObject(hdc, hbitmap);
1861         pixel = GetPixel(hdc, 5, 5);
1862         ok(pixel == 0xc12ac1 || broken(pixel == 0xc12a2a), "got %x, expected 0xc12ac1\n", pixel);
1863         pixel = GetPixel(hdc, 1, 0);
1864         ok(pixel == 0xff00ff || broken(pixel == 0xff0000), "got %x, expected 0xff00ff\n", pixel);
1865         pixel = GetPixel(hdc, 2, 0);
1866         ok(pixel == 0xb12ac1 || broken(pixel == 0xb12a2a), "got %x, expected 0xb12ac1\n", pixel);
1867 
1868         SelectObject(hdc, oldhbitmap);
1869         DeleteDC(hdc);
1870         DeleteObject(hbitmap);
1871     }
1872 
1873     stat = GdipDisposeImage((GpImage*)bitmap);
1874     expect(Ok, stat);
1875 
1876     /* create HBITMAP from locked data */
1877     memset(bits, 0x68, 640);
1878     stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1879     expect(Ok, stat);
1880 
1881     memset(&lockeddata, 0, sizeof(lockeddata));
1882     stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite,
1883             PixelFormat32bppRGB, &lockeddata);
1884     expect(Ok, stat);
1885     ((DWORD*)lockeddata.Scan0)[0] = 0xff242424;
1886     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1887     expect(Ok, stat);
1888     stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
1889     expect(Ok, stat);
1890     stat = GdipDisposeImage((GpImage*)bitmap);
1891     expect(Ok, stat);
1892 
1893     hdc = CreateCompatibleDC(NULL);
1894     oldhbitmap = SelectObject(hdc, hbitmap);
1895     pixel = GetPixel(hdc, 0, 0);
1896     expect(0x686868, pixel);
1897     SelectObject(hdc, oldhbitmap);
1898     DeleteDC(hdc);
1899 }
1900 
1901 static void test_getthumbnail(void)
1902 {
1903     GpStatus stat;
1904     GpImage *bitmap1, *bitmap2;
1905     UINT width, height;
1906 
1907     stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1908     expect(InvalidParameter, stat);
1909 
1910     stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1911     expect(Ok, stat);
1912 
1913     stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1914     expect(InvalidParameter, stat);
1915 
1916     stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1917     expect(Ok, stat);
1918 
1919     if (stat == Ok)
1920     {
1921         stat = GdipGetImageWidth(bitmap2, &width);
1922         expect(Ok, stat);
1923         expect(120, width);
1924 
1925         stat = GdipGetImageHeight(bitmap2, &height);
1926         expect(Ok, stat);
1927         expect(120, height);
1928 
1929         GdipDisposeImage(bitmap2);
1930     }
1931 
1932     GdipDisposeImage(bitmap1);
1933 
1934 
1935     stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1936     expect(Ok, stat);
1937 
1938     stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1939     expect(Ok, stat);
1940 
1941     if (stat == Ok)
1942     {
1943         stat = GdipGetImageWidth(bitmap2, &width);
1944         expect(Ok, stat);
1945         expect(32, width);
1946 
1947         stat = GdipGetImageHeight(bitmap2, &height);
1948         expect(Ok, stat);
1949         expect(32, height);
1950 
1951         GdipDisposeImage(bitmap2);
1952     }
1953 
1954     stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1955     expect(Ok, stat);
1956 
1957     if (stat == Ok)
1958     {
1959         stat = GdipGetImageWidth(bitmap2, &width);
1960         expect(Ok, stat);
1961         expect(120, width);
1962 
1963         stat = GdipGetImageHeight(bitmap2, &height);
1964         expect(Ok, stat);
1965         expect(120, height);
1966 
1967         GdipDisposeImage(bitmap2);
1968     }
1969 
1970     GdipDisposeImage(bitmap1);
1971 }
1972 
1973 static void test_getsetpixel(void)
1974 {
1975     GpStatus stat;
1976     GpBitmap *bitmap;
1977     ARGB color;
1978     BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1979                      0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1980 
1981     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1982     expect(Ok, stat);
1983 
1984     /* null parameters */
1985     stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1986     expect(InvalidParameter, stat);
1987 
1988     stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1989     expect(InvalidParameter, stat);
1990 
1991     stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1992     expect(InvalidParameter, stat);
1993 
1994     /* out of bounds */
1995     stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1996     expect(InvalidParameter, stat);
1997 
1998     stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1999     expect(InvalidParameter, stat);
2000 
2001     stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
2002     ok(stat == InvalidParameter ||
2003        broken(stat == Ok), /* Older gdiplus */
2004        "Expected InvalidParameter, got %.8x\n", stat);
2005 
2006 if (0) /* crashes some gdiplus implementations */
2007 {
2008     stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
2009     ok(stat == InvalidParameter ||
2010        broken(stat == Ok), /* Older gdiplus */
2011        "Expected InvalidParameter, got %.8x\n", stat);
2012 }
2013 
2014     stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
2015     expect(InvalidParameter, stat);
2016 
2017     stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
2018     expect(InvalidParameter, stat);
2019 
2020     stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
2021     expect(InvalidParameter, stat);
2022 
2023     stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
2024     expect(InvalidParameter, stat);
2025 
2026     /* valid use */
2027     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2028     expect(Ok, stat);
2029     expect(0xffffffff, color);
2030 
2031     stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2032     expect(Ok, stat);
2033     expect(0xff0000ff, color);
2034 
2035     stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
2036     expect(Ok, stat);
2037 
2038     stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
2039     expect(Ok, stat);
2040 
2041     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2042     expect(Ok, stat);
2043     expect(0xff676869, color);
2044 
2045     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2046     expect(Ok, stat);
2047     expect(0xff474849, color);
2048 
2049     stat = GdipDisposeImage((GpImage*)bitmap);
2050     expect(Ok, stat);
2051 }
2052 
2053 static void check_halftone_palette(ColorPalette *palette)
2054 {
2055     static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
2056     UINT i;
2057 
2058     for (i=0; i<palette->Count; i++)
2059     {
2060         ARGB expected=0xff000000;
2061         if (i<8)
2062         {
2063             if (i&1) expected |= 0x800000;
2064             if (i&2) expected |= 0x8000;
2065             if (i&4) expected |= 0x80;
2066         }
2067         else if (i == 8)
2068         {
2069             expected = 0xffc0c0c0;
2070         }
2071         else if (i < 16)
2072         {
2073             if (i&1) expected |= 0xff0000;
2074             if (i&2) expected |= 0xff00;
2075             if (i&4) expected |= 0xff;
2076         }
2077         else if (i < 40)
2078         {
2079             expected = 0x00000000;
2080         }
2081         else
2082         {
2083             expected |= halftone_values[(i-40)%6];
2084             expected |= halftone_values[((i-40)/6)%6] << 8;
2085             expected |= halftone_values[((i-40)/36)%6] << 16;
2086         }
2087         ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2088             expected, palette->Entries[i], i, palette->Count);
2089     }
2090 }
2091 
2092 static void test_palette(void)
2093 {
2094     GpStatus stat;
2095     GpBitmap *bitmap;
2096     INT size;
2097     BYTE buffer[1040];
2098     ColorPalette *palette=(ColorPalette*)buffer;
2099     ARGB *entries = palette->Entries;
2100     ARGB color=0;
2101 
2102     /* test initial palette from non-indexed bitmap */
2103     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2104     expect(Ok, stat);
2105 
2106     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2107     expect(Ok, stat);
2108     expect(sizeof(UINT)*2+sizeof(ARGB), size);
2109 
2110     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2111     expect(Ok, stat);
2112     expect(0, palette->Count);
2113 
2114     /* test setting palette on not-indexed bitmap */
2115     palette->Count = 3;
2116 
2117     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2118     expect(Ok, stat);
2119 
2120     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2121     expect(Ok, stat);
2122     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2123 
2124     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2125     expect(Ok, stat);
2126     expect(3, palette->Count);
2127 
2128     GdipDisposeImage((GpImage*)bitmap);
2129 
2130     /* test initial palette on 1-bit bitmap */
2131     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2132     expect(Ok, stat);
2133 
2134     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2135     expect(Ok, stat);
2136     expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2137 
2138     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2139     expect(Ok, stat);
2140     expect(PaletteFlagsGrayScale, palette->Flags);
2141     expect(2, palette->Count);
2142 
2143     expect(0xff000000, entries[0]);
2144     expect(0xffffffff, entries[1]);
2145 
2146     /* test getting/setting pixels */
2147     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2148     expect(Ok, stat);
2149     expect(0xff000000, color);
2150 
2151     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2152     ok((stat == Ok) ||
2153        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2154 
2155     if (stat == Ok)
2156     {
2157         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2158         expect(Ok, stat);
2159         expect(0xffffffff, color);
2160     }
2161 
2162     GdipDisposeImage((GpImage*)bitmap);
2163 
2164     /* test initial palette on 4-bit bitmap */
2165     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2166     expect(Ok, stat);
2167 
2168     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2169     expect(Ok, stat);
2170     expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2171 
2172     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2173     expect(Ok, stat);
2174     expect(0, palette->Flags);
2175     expect(16, palette->Count);
2176 
2177     check_halftone_palette(palette);
2178 
2179     /* test getting/setting pixels */
2180     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2181     expect(Ok, stat);
2182     expect(0xff000000, color);
2183 
2184     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2185     ok((stat == Ok) ||
2186        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2187 
2188     if (stat == Ok)
2189     {
2190         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2191         expect(Ok, stat);
2192         expect(0xffff00ff, color);
2193     }
2194 
2195     GdipDisposeImage((GpImage*)bitmap);
2196 
2197     /* test initial palette on 8-bit bitmap */
2198     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2199     expect(Ok, stat);
2200 
2201     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2202     expect(Ok, stat);
2203     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2204 
2205     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2206     expect(Ok, stat);
2207     expect(PaletteFlagsHalftone, palette->Flags);
2208     expect(256, palette->Count);
2209 
2210     check_halftone_palette(palette);
2211 
2212     /* test getting/setting pixels */
2213     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2214     expect(Ok, stat);
2215     expect(0xff000000, color);
2216 
2217     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2218     ok((stat == Ok) ||
2219        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2220 
2221     if (stat == Ok)
2222     {
2223         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2224         expect(Ok, stat);
2225         expect(0xffcccccc, color);
2226     }
2227 
2228     /* test setting/getting a different palette */
2229     entries[1] = 0xffcccccc;
2230 
2231     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2232     expect(Ok, stat);
2233 
2234     entries[1] = 0;
2235 
2236     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2237     expect(Ok, stat);
2238     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2239 
2240     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2241     expect(Ok, stat);
2242     expect(PaletteFlagsHalftone, palette->Flags);
2243     expect(256, palette->Count);
2244     expect(0xffcccccc, entries[1]);
2245 
2246     /* test count < 256 */
2247     palette->Flags = 12345;
2248     palette->Count = 3;
2249 
2250     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2251     expect(Ok, stat);
2252 
2253     entries[1] = 0;
2254     entries[3] = 0xdeadbeef;
2255 
2256     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2257     expect(Ok, stat);
2258     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2259 
2260     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2261     expect(Ok, stat);
2262     expect(12345, palette->Flags);
2263     expect(3, palette->Count);
2264     expect(0xffcccccc, entries[1]);
2265     expect(0xdeadbeef, entries[3]);
2266 
2267     /* test count > 256 */
2268     palette->Count = 257;
2269 
2270     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2271     ok(stat == InvalidParameter ||
2272        broken(stat == Ok), /* Old gdiplus behavior */
2273        "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2274 
2275     GdipDisposeImage((GpImage*)bitmap);
2276 }
2277 
2278 static void test_colormatrix(void)
2279 {
2280     GpStatus stat;
2281     ColorMatrix colormatrix, graymatrix;
2282     GpImageAttributes *imageattr;
2283     const ColorMatrix identity = {{
2284         {1.0,0.0,0.0,0.0,0.0},
2285         {0.0,1.0,0.0,0.0,0.0},
2286         {0.0,0.0,1.0,0.0,0.0},
2287         {0.0,0.0,0.0,1.0,0.0},
2288         {0.0,0.0,0.0,0.0,1.0}}};
2289     const ColorMatrix double_red = {{
2290         {2.0,0.0,0.0,0.0,0.0},
2291         {0.0,1.0,0.0,0.0,0.0},
2292         {0.0,0.0,1.0,0.0,0.0},
2293         {0.0,0.0,0.0,1.0,0.0},
2294         {0.0,0.0,0.0,0.0,1.0}}};
2295     const ColorMatrix asymmetric = {{
2296         {0.0,1.0,0.0,0.0,0.0},
2297         {0.0,0.0,1.0,0.0,0.0},
2298         {0.0,0.0,0.0,1.0,0.0},
2299         {1.0,0.0,0.0,0.0,0.0},
2300         {0.0,0.0,0.0,0.0,1.0}}};
2301     GpBitmap *bitmap1, *bitmap2;
2302     GpGraphics *graphics;
2303     ARGB color;
2304 
2305     colormatrix = identity;
2306     graymatrix = identity;
2307 
2308     stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2309         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2310     expect(InvalidParameter, stat);
2311 
2312     stat = GdipCreateImageAttributes(&imageattr);
2313     expect(Ok, stat);
2314 
2315     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2316         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2317     expect(Ok, stat);
2318 
2319     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2320         TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2321     expect(InvalidParameter, stat);
2322 
2323     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2324         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2325     expect(Ok, stat);
2326 
2327     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2328         TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2329     expect(Ok, stat);
2330 
2331     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2332         TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2333     expect(InvalidParameter, stat);
2334 
2335     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2336         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2337     expect(Ok, stat);
2338 
2339     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2340         TRUE, &colormatrix, &graymatrix, 3);
2341     expect(InvalidParameter, stat);
2342 
2343     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2344         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2345     expect(InvalidParameter, stat);
2346 
2347     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2348         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2349     expect(InvalidParameter, stat);
2350 
2351     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2352         FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2353     expect(Ok, stat);
2354 
2355     /* Drawing a bitmap transforms the colors */
2356     colormatrix = double_red;
2357     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2358         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2359     expect(Ok, stat);
2360 
2361     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2362     expect(Ok, stat);
2363 
2364     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2365     expect(Ok, stat);
2366 
2367     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2368     expect(Ok, stat);
2369 
2370     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2371     expect(Ok, stat);
2372 
2373     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2374         UnitPixel, imageattr, NULL, NULL);
2375     expect(Ok, stat);
2376 
2377     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2378     expect(Ok, stat);
2379     expect(0xff80ccee, color);
2380 
2381     colormatrix = asymmetric;
2382     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2383         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2384     expect(Ok, stat);
2385 
2386     stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2387     expect(Ok, stat);
2388 
2389     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2390         UnitPixel, imageattr, NULL, NULL);
2391     expect(Ok, stat);
2392 
2393     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2394     expect(Ok, stat);
2395     ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2396 
2397     /* Toggle NoOp */
2398     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, FALSE);
2399     expect(Ok, stat);
2400 
2401     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2402         UnitPixel, imageattr, NULL, NULL);
2403     expect(Ok, stat);
2404 
2405     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2406     expect(Ok, stat);
2407     ok(color_match(0xfefe40cc, color, 3), "expected 0xfefe40cc, got 0x%08x\n", color);
2408 
2409     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, TRUE);
2410     expect(Ok, stat);
2411 
2412     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2413         UnitPixel, imageattr, NULL, NULL);
2414     expect(Ok, stat);
2415 
2416     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2417     expect(Ok, stat);
2418     ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2419 
2420     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2421     expect(Ok, stat);
2422 
2423     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, FALSE);
2424     expect(Ok, stat);
2425 
2426     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2427         UnitPixel, imageattr, NULL, NULL);
2428     expect(Ok, stat);
2429 
2430     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2431     expect(Ok, stat);
2432     ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2433 
2434     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2435         UnitPixel, imageattr, NULL, NULL);
2436     expect(Ok, stat);
2437 
2438     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2439     expect(Ok, stat);
2440     ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2441 
2442     /* Disable adjustment, toggle NoOp */
2443     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2444         FALSE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2445     expect(Ok, stat);
2446 
2447     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, FALSE);
2448     expect(Ok, stat);
2449 
2450     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2451         UnitPixel, imageattr, NULL, NULL);
2452     expect(Ok, stat);
2453 
2454     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2455     expect(Ok, stat);
2456     ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2457 
2458     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, TRUE);
2459     expect(Ok, stat);
2460 
2461     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2462         UnitPixel, imageattr, NULL, NULL);
2463     expect(Ok, stat);
2464 
2465     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2466     expect(Ok, stat);
2467     ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2468 
2469     /* Reset with NoOp on, enable adjustment. */
2470     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2471     expect(Ok, stat);
2472 
2473     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2474         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2475     expect(Ok, stat);
2476 
2477     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2478         UnitPixel, imageattr, NULL, NULL);
2479     expect(Ok, stat);
2480 
2481     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2482     expect(Ok, stat);
2483     ok(color_match(0xfff24ace, color, 3), "expected 0xfff24ace, got 0x%08x\n", color);
2484 
2485     /* Now inhibit specific category. */
2486     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2487     expect(Ok, stat);
2488 
2489     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeBitmap,
2490         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2491     expect(Ok, stat);
2492 
2493     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2494         UnitPixel, imageattr, NULL, NULL);
2495     expect(Ok, stat);
2496 
2497     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2498     expect(Ok, stat);
2499     ok(color_match(0xfffe41cc, color, 3), "expected 0xfffe41cc, got 0x%08x\n", color);
2500 
2501     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeBitmap, TRUE);
2502     expect(Ok, stat);
2503 
2504     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2505         UnitPixel, imageattr, NULL, NULL);
2506     expect(Ok, stat);
2507 
2508     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2509     expect(Ok, stat);
2510     ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2511 
2512     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeBitmap, FALSE);
2513     expect(Ok, stat);
2514 
2515     stat = GdipSetImageAttributesNoOp(imageattr, ColorAdjustTypeDefault, TRUE);
2516     expect(Ok, stat);
2517 
2518     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2519         UnitPixel, imageattr, NULL, NULL);
2520     expect(Ok, stat);
2521 
2522     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2523     expect(Ok, stat);
2524     ok(color_match(0xfff24ace, color, 3), "expected 0xfff24ace, got 0x%08x\n", color);
2525 
2526     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeBitmap);
2527     expect(Ok, stat);
2528 
2529     stat = GdipDrawImageRectRectI(graphics, (GpImage *)bitmap1, 0, 0, 1, 1, 0, 0, 1, 1,
2530         UnitPixel, imageattr, NULL, NULL);
2531     expect(Ok, stat);
2532 
2533     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2534     expect(Ok, stat);
2535     ok(color_match(0xff40ccee, color, 3), "expected 0xff40ccee, got 0x%08x\n", color);
2536 
2537     GdipDeleteGraphics(graphics);
2538     GdipDisposeImage((GpImage*)bitmap1);
2539     GdipDisposeImage((GpImage*)bitmap2);
2540     GdipDisposeImageAttributes(imageattr);
2541 }
2542 
2543 static void test_gamma(void)
2544 {
2545     GpStatus stat;
2546     GpImageAttributes *imageattr;
2547     GpBitmap *bitmap1, *bitmap2;
2548     GpGraphics *graphics;
2549     ARGB color;
2550 
2551     stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2552     expect(InvalidParameter, stat);
2553 
2554     stat = GdipCreateImageAttributes(&imageattr);
2555     expect(Ok, stat);
2556 
2557     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2558     expect(Ok, stat);
2559 
2560     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2561     expect(InvalidParameter, stat);
2562 
2563     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2564     expect(InvalidParameter, stat);
2565 
2566     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2567     expect(InvalidParameter, stat);
2568 
2569     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2570     expect(Ok, stat);
2571 
2572     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2573     expect(Ok, stat);
2574 
2575     /* Drawing a bitmap transforms the colors */
2576     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2577     expect(Ok, stat);
2578 
2579     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2580     expect(Ok, stat);
2581 
2582     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2583     expect(Ok, stat);
2584 
2585     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2586     expect(Ok, stat);
2587 
2588     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2589     expect(Ok, stat);
2590 
2591     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2592         UnitPixel, imageattr, NULL, NULL);
2593     expect(Ok, stat);
2594 
2595     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2596     expect(Ok, stat);
2597     ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2598 
2599     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2600     expect(Ok, stat);
2601 
2602     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2603         UnitPixel, imageattr, NULL, NULL);
2604     expect(Ok, stat);
2605 
2606     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2607     expect(Ok, stat);
2608     ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2609 
2610     GdipDeleteGraphics(graphics);
2611     GdipDisposeImage((GpImage*)bitmap1);
2612     GdipDisposeImage((GpImage*)bitmap2);
2613     GdipDisposeImageAttributes(imageattr);
2614 }
2615 
2616 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2617 static const unsigned char gifanimation[72] = {
2618 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2619 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2620 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2621 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2622 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2623 };
2624 
2625 /* Generated with ImageMagick:
2626  * convert -transparent black -delay 100 -size 8x2 xc:black \
2627  *     -dispose none -page +0+0 -size 2x2 xc:red \
2628  *     -dispose background -page +2+0 -size 2x2 xc:blue \
2629  *     -dispose previous -page +4+0 -size 2x2 xc:green \
2630  *     -dispose undefined -page +6+0 -size 2x2 xc:gray \
2631  *     test.gif
2632  */
2633 static const unsigned char gifanimation2[] = {
2634     0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2635     0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2636     0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2637     0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2638     0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2639     0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2640     0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2641     0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2642     0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2643     0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2644     0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2645     0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2646     0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2647     0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2648     0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2649     0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2650     0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2651     0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2652     0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2653     0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2654     0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2655     0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2656     0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2657     0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2658     0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2659     0x3b
2660 };
2661 
2662 static ARGB gifanimation2_pixels[5][4] = {
2663     {0, 0, 0, 0},
2664     {0xffff0000, 0, 0, 0},
2665     {0xffff0000, 0xff0000ff, 0, 0},
2666     {0xffff0000, 0, 0xff008000, 0},
2667     {0xffff0000, 0, 0, 0xff7e7e7e}
2668 };
2669 
2670 static void test_multiframegif(void)
2671 {
2672     LPSTREAM stream;
2673     HGLOBAL hglob;
2674     LPBYTE data;
2675     HRESULT hres;
2676     GpStatus stat;
2677     GpBitmap *bmp;
2678     ARGB color;
2679     UINT count;
2680     GUID dimension;
2681     PixelFormat pixel_format;
2682     INT palette_size, i, j;
2683     char palette_buf[256];
2684     ColorPalette *palette;
2685     ARGB *palette_entries;
2686 
2687     /* Test frame functions with an animated GIF */
2688     hglob = GlobalAlloc (0, sizeof(gifanimation));
2689     data = GlobalLock (hglob);
2690     memcpy(data, gifanimation, sizeof(gifanimation));
2691     GlobalUnlock(hglob);
2692 
2693     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2694     ok(hres == S_OK, "Failed to create a stream\n");
2695     if(hres != S_OK) return;
2696 
2697     stat = GdipCreateBitmapFromStream(stream, &bmp);
2698     ok(stat == Ok, "Failed to create a Bitmap\n");
2699     if(stat != Ok){
2700         IStream_Release(stream);
2701         return;
2702     }
2703 
2704     stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2705     expect(Ok, stat);
2706     expect(PixelFormat32bppARGB, pixel_format);
2707 
2708     stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2709     expect(Ok, stat);
2710     ok(palette_size == sizeof(ColorPalette) ||
2711             broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2712             "palette_size = %d\n", palette_size);
2713 
2714     /* Bitmap starts at frame 0 */
2715     color = 0xdeadbeef;
2716     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2717     expect(Ok, stat);
2718     expect(0xffffffff, color);
2719 
2720     /* Check that we get correct metadata */
2721     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2722     expect(Ok, stat);
2723     expect(1, count);
2724 
2725     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2726     expect(Ok, stat);
2727     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2728 
2729     count = 12345;
2730     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2731     expect(Ok, stat);
2732     expect(2, count);
2733 
2734     /* SelectActiveFrame overwrites our current data */
2735     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2736     expect(Ok, stat);
2737 
2738     color = 0xdeadbeef;
2739     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2740     expect(Ok, stat);
2741     expect(0xff000000, color);
2742 
2743     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2744     expect(Ok, stat);
2745 
2746     color = 0xdeadbeef;
2747     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2748     expect(Ok, stat);
2749     expect(0xffffffff, color);
2750 
2751     /* Write over the image data */
2752     stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2753     expect(Ok, stat);
2754 
2755     /* Switching to the same frame does not overwrite our changes */
2756     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2757     expect(Ok, stat);
2758 
2759     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2760     expect(Ok, stat);
2761     expect(0xff000000, color);
2762 
2763     /* But switching to another frame and back does */
2764     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2765     expect(Ok, stat);
2766 
2767     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2768     expect(Ok, stat);
2769 
2770     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2771     expect(Ok, stat);
2772     expect(0xffffffff, color);
2773 
2774     /* rotate/flip discards the information about other frames */
2775     stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2776     expect(Ok, stat);
2777 
2778     count = 12345;
2779     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2780     expect(Ok, stat);
2781     expect(1, count);
2782 
2783     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2784 
2785     GdipDisposeImage((GpImage*)bmp);
2786     IStream_Release(stream);
2787 
2788     /* Test with a non-animated gif */
2789     hglob = GlobalAlloc (0, sizeof(gifimage));
2790     data = GlobalLock (hglob);
2791     memcpy(data, gifimage, sizeof(gifimage));
2792     GlobalUnlock(hglob);
2793 
2794     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2795     ok(hres == S_OK, "Failed to create a stream\n");
2796     if(hres != S_OK) return;
2797 
2798     stat = GdipCreateBitmapFromStream(stream, &bmp);
2799     ok(stat == Ok, "Failed to create a Bitmap\n");
2800     if(stat != Ok){
2801         IStream_Release(stream);
2802         return;
2803     }
2804 
2805     stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2806     expect(Ok, stat);
2807     expect(PixelFormat8bppIndexed, pixel_format);
2808 
2809     /* Check metadata */
2810     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2811     expect(Ok, stat);
2812     expect(1, count);
2813 
2814     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2815     expect(Ok, stat);
2816     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2817 
2818     count = 12345;
2819     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2820     expect(Ok, stat);
2821     expect(1, count);
2822 
2823     GdipDisposeImage((GpImage*)bmp);
2824     IStream_Release(stream);
2825 
2826     /* Test with a non-animated transparent gif */
2827     hglob = GlobalAlloc (0, sizeof(transparentgif));
2828     data = GlobalLock (hglob);
2829     memcpy(data, transparentgif, sizeof(transparentgif));
2830     GlobalUnlock(hglob);
2831 
2832     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2833     ok(hres == S_OK, "Failed to create a stream\n");
2834 
2835     stat = GdipCreateBitmapFromStream(stream, &bmp);
2836     IStream_Release(stream);
2837     ok(stat == Ok, "Failed to create a Bitmap\n");
2838 
2839     stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2840     expect(Ok, stat);
2841     expect(PixelFormat8bppIndexed, pixel_format);
2842 
2843     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2844     expect(Ok, stat);
2845     expect(0, color);
2846 
2847     stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2848     expect(Ok, stat);
2849     ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB),
2850             "palette_size = %d\n", palette_size);
2851 
2852     memset(palette_buf, 0xfe, sizeof(palette_buf));
2853     palette = (ColorPalette*)palette_buf;
2854     stat = GdipGetImagePalette((GpImage*)bmp, palette,
2855             sizeof(ColorPalette)+sizeof(ARGB));
2856     palette_entries = palette->Entries;
2857     expect(Ok, stat);
2858     expect(PaletteFlagsHasAlpha, palette->Flags);
2859     expect(2, palette->Count);
2860     expect(0, palette_entries[0]);
2861     expect(0xff000000, palette_entries[1]);
2862 
2863     count = 12345;
2864     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2865     expect(Ok, stat);
2866     expect(1, count);
2867 
2868     GdipDisposeImage((GpImage*)bmp);
2869 
2870     /* Test frame dispose methods */
2871     hglob = GlobalAlloc (0, sizeof(gifanimation2));
2872     data = GlobalLock (hglob);
2873     memcpy(data, gifanimation2, sizeof(gifanimation2));
2874     GlobalUnlock(hglob);
2875 
2876     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2877     ok(hres == S_OK, "Failed to create a stream\n");
2878 
2879     stat = GdipCreateBitmapFromStream(stream, &bmp);
2880     ok(stat == Ok, "Failed to create a Bitmap\n");
2881     IStream_Release(stream);
2882 
2883     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2884     expect(Ok, stat);
2885     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2886 
2887     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2888     expect(Ok, stat);
2889     expect(5, count);
2890 
2891     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2892     expect(Ok, stat);
2893     expect(0, color);
2894 
2895     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2896     expect(Ok, stat);
2897     stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2898     expect(Ok, stat);
2899     ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2900     if(color != 0) {
2901         win_skip("broken animated gif support\n");
2902         GdipDisposeImage((GpImage*)bmp);
2903         return;
2904     }
2905 
2906     for(i=0; i<6; i++) {
2907         stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2908         expect(Ok, stat);
2909 
2910         for(j=0; j<4; j++) {
2911             stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2912             expect(Ok, stat);
2913             ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2914         }
2915     }
2916 
2917     GdipDisposeImage((GpImage*)bmp);
2918 }
2919 
2920 static void test_rotateflip(void)
2921 {
2922     GpImage *bitmap;
2923     GpStatus stat;
2924     BYTE bits[24];
2925     static const BYTE orig_bits[24] = {
2926         0,0,0xff,    0,0xff,0,    0xff,0,0,    23,23,23,
2927         0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2928     UINT width, height;
2929     ARGB color;
2930 
2931     memcpy(bits, orig_bits, sizeof(bits));
2932     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2933     expect(Ok, stat);
2934 
2935     stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2936     expect(Ok, stat);
2937 
2938     stat = GdipGetImageWidth(bitmap, &width);
2939     expect(Ok, stat);
2940     stat = GdipGetImageHeight(bitmap, &height);
2941     expect(Ok, stat);
2942     expect(2, width);
2943     expect(3, height);
2944 
2945     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2946     expect(Ok, stat);
2947     expect(0xff00ffff, color);
2948 
2949     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2950     expect(Ok, stat);
2951     expect(0xffff0000, color);
2952 
2953     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2954     expect(Ok, stat);
2955     expect(0xffffff00, color);
2956 
2957     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2958     expect(Ok, stat);
2959     expect(0xff0000ff, color);
2960 
2961     expect(0, bits[0]);
2962     expect(0, bits[1]);
2963     expect(0xff, bits[2]);
2964 
2965     GdipDisposeImage(bitmap);
2966 
2967     memcpy(bits, orig_bits, sizeof(bits));
2968     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2969     expect(Ok, stat);
2970 
2971     stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2972     expect(Ok, stat);
2973 
2974     stat = GdipGetImageWidth(bitmap, &width);
2975     expect(Ok, stat);
2976     stat = GdipGetImageHeight(bitmap, &height);
2977     expect(Ok, stat);
2978     expect(3, width);
2979     expect(2, height);
2980 
2981     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2982     expect(Ok, stat);
2983     expect(0xff0000ff, color);
2984 
2985     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2986     expect(Ok, stat);
2987     expect(0xffff0000, color);
2988 
2989     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2990     expect(Ok, stat);
2991     expect(0xffffff00, color);
2992 
2993     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2994     expect(Ok, stat);
2995     expect(0xff00ffff, color);
2996 
2997     expect(0, bits[0]);
2998     expect(0, bits[1]);
2999     expect(0xff, bits[2]);
3000 
3001     GdipDisposeImage(bitmap);
3002 
3003     memcpy(bits, orig_bits, sizeof(bits));
3004     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
3005     expect(Ok, stat);
3006 
3007     stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
3008     expect(Ok, stat);
3009 
3010     stat = GdipGetImageWidth(bitmap, &width);
3011     expect(Ok, stat);
3012     stat = GdipGetImageHeight(bitmap, &height);
3013     expect(Ok, stat);
3014     expect(3, width);
3015     expect(2, height);
3016 
3017     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
3018     expect(Ok, stat);
3019     expect(0xff00ffff, color);
3020 
3021     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
3022     expect(Ok, stat);
3023     expect(0xffffff00, color);
3024 
3025     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
3026     expect(Ok, stat);
3027     expect(0xffff0000, color);
3028 
3029     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
3030     expect(Ok, stat);
3031     expect(0xff0000ff, color);
3032 
3033     expect(0, bits[0]);
3034     expect(0, bits[1]);
3035     expect(0xff, bits[2]);
3036 
3037     GdipDisposeImage(bitmap);
3038 }
3039 
3040 static void test_remaptable(void)
3041 {
3042     GpStatus stat;
3043     GpImageAttributes *imageattr;
3044     GpBitmap *bitmap1, *bitmap2;
3045     GpGraphics *graphics;
3046     ARGB color;
3047     ColorMap *map;
3048 
3049     map = GdipAlloc(sizeof(ColorMap));
3050 
3051     map->oldColor.Argb = 0xff00ff00;
3052     map->newColor.Argb = 0xffff00ff;
3053 
3054     stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
3055     expect(InvalidParameter, stat);
3056 
3057     stat = GdipCreateImageAttributes(&imageattr);
3058     expect(Ok, stat);
3059 
3060     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
3061     expect(InvalidParameter, stat);
3062 
3063     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
3064     expect(InvalidParameter, stat);
3065 
3066     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
3067     expect(InvalidParameter, stat);
3068 
3069     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
3070     expect(InvalidParameter, stat);
3071 
3072     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
3073     expect(Ok, stat);
3074 
3075     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
3076     expect(Ok, stat);
3077 
3078     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
3079     expect(Ok, stat);
3080 
3081     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
3082     expect(Ok, stat);
3083 
3084     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
3085     expect(Ok, stat);
3086 
3087     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
3088     expect(Ok, stat);
3089 
3090     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
3091 	UnitPixel, imageattr, NULL, NULL);
3092     expect(Ok, stat);
3093 
3094     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3095     expect(Ok, stat);
3096     ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
3097 
3098     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3099     expect(Ok, stat);
3100 
3101     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
3102         UnitPixel, imageattr, NULL, NULL);
3103     expect(Ok, stat);
3104 
3105     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3106     expect(Ok, stat);
3107     ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
3108 
3109     GdipDeleteGraphics(graphics);
3110     GdipDisposeImage((GpImage*)bitmap1);
3111     GdipDisposeImage((GpImage*)bitmap2);
3112     GdipDisposeImageAttributes(imageattr);
3113     GdipFree(map);
3114 }
3115 
3116 static void test_colorkey(void)
3117 {
3118     GpStatus stat;
3119     GpImageAttributes *imageattr;
3120     GpBitmap *bitmap1, *bitmap2;
3121     GpGraphics *graphics;
3122     ARGB color;
3123 
3124     stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
3125     expect(InvalidParameter, stat);
3126 
3127     stat = GdipCreateImageAttributes(&imageattr);
3128     expect(Ok, stat);
3129 
3130     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
3131     expect(InvalidParameter, stat);
3132 
3133     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
3134     expect(InvalidParameter, stat);
3135 
3136     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
3137     expect(Ok, stat);
3138 
3139     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
3140     expect(Ok, stat);
3141 
3142     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
3143     expect(Ok, stat);
3144 
3145     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
3146     expect(Ok, stat);
3147 
3148     stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
3149     expect(Ok, stat);
3150 
3151     stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
3152     expect(Ok, stat);
3153 
3154     stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
3155     expect(Ok, stat);
3156 
3157     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
3158     expect(Ok, stat);
3159 
3160     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3161 	UnitPixel, imageattr, NULL, NULL);
3162     expect(Ok, stat);
3163 
3164     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3165     expect(Ok, stat);
3166     ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3167 
3168     stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3169     expect(Ok, stat);
3170     ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3171 
3172     stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3173     expect(Ok, stat);
3174     ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3175 
3176     stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3177     expect(Ok, stat);
3178     ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3179 
3180     stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3181     expect(Ok, stat);
3182 
3183     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3184 	UnitPixel, imageattr, NULL, NULL);
3185     expect(Ok, stat);
3186 
3187     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3188     expect(Ok, stat);
3189     ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
3190 
3191     stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3192     expect(Ok, stat);
3193     ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
3194 
3195     stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3196     expect(Ok, stat);
3197     ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
3198 
3199     stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3200     expect(Ok, stat);
3201     ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3202 
3203 
3204     GdipDeleteGraphics(graphics);
3205     GdipDisposeImage((GpImage*)bitmap1);
3206     GdipDisposeImage((GpImage*)bitmap2);
3207     GdipDisposeImageAttributes(imageattr);
3208 }
3209 
3210 static void test_dispose(void)
3211 {
3212     GpStatus stat;
3213     GpImage *image;
3214     char invalid_image[256];
3215 
3216     stat = GdipDisposeImage(NULL);
3217     expect(InvalidParameter, stat);
3218 
3219     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
3220     expect(Ok, stat);
3221 
3222     stat = GdipDisposeImage(image);
3223     expect(Ok, stat);
3224 
3225     stat = GdipDisposeImage(image);
3226     expect(ObjectBusy, stat);
3227 
3228     memset(invalid_image, 0, 256);
3229     stat = GdipDisposeImage((GpImage*)invalid_image);
3230     expect(ObjectBusy, stat);
3231 }
3232 
3233 static LONG obj_refcount(void *obj)
3234 {
3235     IUnknown_AddRef((IUnknown *)obj);
3236     return IUnknown_Release((IUnknown *)obj);
3237 }
3238 
3239 static GpImage *load_image(const BYTE *image_data, UINT image_size, BOOL valid_data, BOOL todo_load)
3240 {
3241     IStream *stream;
3242     HGLOBAL hmem;
3243     BYTE *data;
3244     HRESULT hr;
3245     GpStatus status;
3246     GpImage *image = NULL, *clone;
3247     ImageType image_type;
3248     LONG refcount, old_refcount;
3249 
3250     hmem = GlobalAlloc(0, image_size);
3251     data = GlobalLock(hmem);
3252     memcpy(data, image_data, image_size);
3253     GlobalUnlock(hmem);
3254 
3255     hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3256     ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3257     if (hr != S_OK) return NULL;
3258 
3259     refcount = obj_refcount(stream);
3260     ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3261 
3262     status = GdipLoadImageFromStream(stream, &image);
3263     todo_wine_if(todo_load)
3264     if (valid_data)
3265         ok(status == Ok || broken(status == InvalidParameter), /* XP */
3266            "GdipLoadImageFromStream error %d\n", status);
3267     else
3268         ok(status != Ok, "GdipLoadImageFromStream should fail\n");
3269     if (status != Ok)
3270     {
3271         IStream_Release(stream);
3272         return NULL;
3273     }
3274 
3275     status = GdipGetImageType(image, &image_type);
3276     ok(status == Ok, "GdipGetImageType error %d\n", status);
3277 
3278     refcount = obj_refcount(stream);
3279     if (image_type == ImageTypeBitmap)
3280         ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3281     else
3282         ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3283     old_refcount = refcount;
3284 
3285     status = GdipCloneImage(image, &clone);
3286     ok(status == Ok, "GdipCloneImage error %d\n", status);
3287     refcount = obj_refcount(stream);
3288     ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3289     status = GdipDisposeImage(clone);
3290     ok(status == Ok, "GdipDisposeImage error %d\n", status);
3291     refcount = obj_refcount(stream);
3292     ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3293 
3294     refcount = IStream_Release(stream);
3295     if (image_type == ImageTypeBitmap)
3296         ok(refcount >= 1, "expected stream refcount != 0\n");
3297     else
3298         ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3299 
3300     return image;
3301 }
3302 
3303 static void test_image_properties(void)
3304 {
3305     static const struct test_data
3306     {
3307         const BYTE *image_data;
3308         UINT image_size;
3309         ImageType image_type;
3310         UINT prop_count;
3311         UINT prop_count2; /* if win7 behaves differently */
3312         /* 1st property attributes */
3313         UINT prop_size;
3314         UINT prop_size2; /* if win7 behaves differently */
3315         UINT prop_id;
3316         UINT prop_id2; /* if win7 behaves differently */
3317     }
3318     td[] =
3319     {
3320         { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3321         { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3322         { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3323         { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3324         { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3325     };
3326     GpStatus status;
3327     GpImage *image;
3328     UINT prop_count, prop_size, i;
3329     PROPID prop_id[16] = { 0 };
3330     ImageType image_type;
3331     union
3332     {
3333         PropertyItem data;
3334         char buf[256];
3335     } item;
3336 
3337     for (i = 0; i < ARRAY_SIZE(td); i++)
3338     {
3339         image = load_image(td[i].image_data, td[i].image_size, TRUE, FALSE);
3340         if (!image)
3341         {
3342             trace("%u: failed to load image data\n", i);
3343             continue;
3344         }
3345 
3346         status = GdipGetImageType(image, &image_type);
3347         ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3348         ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3349            i, td[i].image_type, image_type);
3350 
3351         status = GdipGetPropertyCount(image, &prop_count);
3352         ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3353         todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage)
3354         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3355            " %u: expected property count %u or %u, got %u\n",
3356            i, td[i].prop_count, td[i].prop_count2, prop_count);
3357 
3358         status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3359         expect(InvalidParameter, status);
3360         status = GdipGetPropertyItemSize(image, 0, NULL);
3361         expect(InvalidParameter, status);
3362         status = GdipGetPropertyItemSize(image, 0, &prop_size);
3363         if (image_type == ImageTypeMetafile)
3364             expect(NotImplemented, status);
3365         else
3366             expect(PropertyNotFound, status);
3367 
3368         status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3369         expect(InvalidParameter, status);
3370         status = GdipGetPropertyItem(image, 0, 0, NULL);
3371         expect(InvalidParameter, status);
3372         status = GdipGetPropertyItem(image, 0, 0, &item.data);
3373         if (image_type == ImageTypeMetafile)
3374             expect(NotImplemented, status);
3375         else
3376             expect(PropertyNotFound, status);
3377 
3378         /* FIXME: remove once Wine is fixed */
3379         if (td[i].prop_count != prop_count)
3380         {
3381             GdipDisposeImage(image);
3382             continue;
3383         }
3384 
3385         status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3386         expect(InvalidParameter, status);
3387         status = GdipGetPropertyIdList(image, prop_count, NULL);
3388         expect(InvalidParameter, status);
3389         status = GdipGetPropertyIdList(image, 0, prop_id);
3390         if (image_type == ImageTypeMetafile)
3391             expect(NotImplemented, status);
3392         else if (prop_count == 0)
3393             expect(Ok, status);
3394         else
3395             expect(InvalidParameter, status);
3396         status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3397         if (image_type == ImageTypeMetafile)
3398             expect(NotImplemented, status);
3399         else
3400             expect(InvalidParameter, status);
3401         status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3402         if (image_type == ImageTypeMetafile)
3403             expect(NotImplemented, status);
3404         else
3405             expect(InvalidParameter, status);
3406         status = GdipGetPropertyIdList(image, prop_count, prop_id);
3407         if (image_type == ImageTypeMetafile)
3408             expect(NotImplemented, status);
3409         else
3410         {
3411             expect(Ok, status);
3412             if (prop_count != 0)
3413                 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3414                    " %u: expected property id %#x or %#x, got %#x\n",
3415                    i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3416         }
3417 
3418         if (status == Ok)
3419         {
3420             status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3421             if (prop_count == 0)
3422                 expect(PropertyNotFound, status);
3423             else
3424             {
3425                 expect(Ok, status);
3426 
3427                 assert(sizeof(item) >= prop_size);
3428                 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3429                    i, prop_size);
3430                 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3431                    td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3432                    " %u: expected property size %u or %u, got %u\n",
3433                    i, td[i].prop_size, td[i].prop_size2, prop_size);
3434 
3435                 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3436                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3437                    "%u: expected InvalidParameter, got %d\n", i, status);
3438                 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3439                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3440                    "%u: expected InvalidParameter, got %d\n", i, status);
3441                 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3442                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3443                    "%u: expected InvalidParameter, got %d\n", i, status);
3444                 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3445                 expect(Ok, status);
3446                 ok(prop_id[0] == item.data.id,
3447                    "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3448             }
3449         }
3450 
3451         GdipDisposeImage(image);
3452     }
3453 }
3454 
3455 #define IFD_BYTE      1
3456 #define IFD_ASCII     2
3457 #define IFD_SHORT     3
3458 #define IFD_LONG      4
3459 #define IFD_RATIONAL  5
3460 #define IFD_SBYTE     6
3461 #define IFD_UNDEFINED 7
3462 #define IFD_SSHORT    8
3463 #define IFD_SLONG     9
3464 #define IFD_SRATIONAL 10
3465 #define IFD_FLOAT     11
3466 #define IFD_DOUBLE    12
3467 
3468 #ifndef PropertyTagTypeSByte
3469 #define PropertyTagTypeSByte  6
3470 #define PropertyTagTypeSShort 8
3471 #define PropertyTagTypeFloat  11
3472 #define PropertyTagTypeDouble 12
3473 #endif
3474 
3475 static UINT documented_type(UINT type)
3476 {
3477     switch (type)
3478     {
3479     case PropertyTagTypeSByte: return PropertyTagTypeByte;
3480     case PropertyTagTypeSShort: return PropertyTagTypeShort;
3481     case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3482     case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3483     default: return type;
3484     }
3485 }
3486 
3487 #include "pshpack2.h"
3488 struct IFD_entry
3489 {
3490     SHORT id;
3491     SHORT type;
3492     ULONG count;
3493     LONG  value;
3494 };
3495 
3496 struct IFD_rational
3497 {
3498     LONG numerator;
3499     LONG denominator;
3500 };
3501 
3502 static const struct tiff_data
3503 {
3504     USHORT byte_order;
3505     USHORT version;
3506     ULONG  dir_offset;
3507     USHORT number_of_entries;
3508     struct IFD_entry entry[40];
3509     ULONG next_IFD;
3510     struct IFD_rational xres;
3511     DOUBLE double_val;
3512     struct IFD_rational srational_val;
3513     char string[14];
3514     SHORT short_val[4];
3515     LONG long_val[2];
3516     FLOAT float_val[2];
3517     struct IFD_rational rational[3];
3518     BYTE pixel_data[4];
3519 } TIFF_data =
3520 {
3521 #ifdef WORDS_BIGENDIAN
3522     'M' | 'M' << 8,
3523 #else
3524     'I' | 'I' << 8,
3525 #endif
3526     42,
3527     FIELD_OFFSET(struct tiff_data, number_of_entries),
3528     31,
3529     {
3530         { 0xff,  IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3531         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3532         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3533         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3534         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3535         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3536         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3537         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3538         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3539         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3540         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3541         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3542         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3543         { 0xf001, IFD_BYTE, 1, 0x11223344 },
3544         { 0xf002, IFD_BYTE, 4, 0x11223344 },
3545         { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3546         { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3547         { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3548         { 0xf006, IFD_SLONG, 1, 0x11223344 },
3549         { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3550         { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3551         { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3552         { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3553         { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3554         { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3555         { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3556         { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3557         { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3558         { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3559         /* Some gdiplus versions ignore these fields.
3560         { 0xf012, IFD_BYTE, 0, 0x11223344 },
3561         { 0xf013, IFD_SHORT, 0, 0x11223344 },
3562         { 0xf014, IFD_LONG, 0, 0x11223344 },
3563         { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3564         { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3565         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3566         { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3567     },
3568     0,
3569     { 900, 3 },
3570     1234567890.0987654321,
3571     { 0x1a2b3c4d, 0x5a6b7c8d },
3572     "Hello World!",
3573     { 0x0101, 0x0202, 0x0303, 0x0404 },
3574     { 0x11223344, 0x55667788 },
3575     { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3576     { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3577     { 0x11, 0x22, 0x33, 0 }
3578 };
3579 #include "poppack.h"
3580 
3581 static void test_tiff_properties(void)
3582 {
3583     static const struct test_data
3584     {
3585         ULONG type, id, length;
3586         const BYTE value[24];
3587     } td[31] =
3588     {
3589         { PropertyTagTypeShort, 0xff, 2, { 0 } },
3590         { PropertyTagTypeLong, 0x100, 4, { 1 } },
3591         { PropertyTagTypeLong, 0x101, 4, { 1 } },
3592         { PropertyTagTypeShort, 0x102, 2, { 1 } },
3593         { PropertyTagTypeShort, 0x103, 2, { 1 } },
3594         { PropertyTagTypeShort, 0x106, 2, { 1 } },
3595         { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3596         { PropertyTagTypeShort, 0x115, 2, { 1 } },
3597         { PropertyTagTypeLong, 0x116, 4, { 1 } },
3598         { PropertyTagTypeLong, 0x117, 4, { 1 } },
3599         { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3600         { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3601         { PropertyTagTypeShort, 0x128, 2, { 2 } },
3602         { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3603         { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3604         { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3605         { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3606         { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3607         { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3608         { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3609         { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3610         { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3611         { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3612         { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3613         { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3614         { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3615         { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3616         { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3617         { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3618         { PropertyTagTypeSRational, 0xf016, 24,
3619           { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3620             0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3621             0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3622         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3623         { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3624     };
3625     GpStatus status;
3626     GpImage *image;
3627     GUID guid;
3628     UINT dim_count, frame_count, prop_count, prop_size, i;
3629     PROPID *prop_id;
3630     PropertyItem *prop_item;
3631 
3632     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data), TRUE, FALSE);
3633     if (!image)
3634     {
3635         win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3636         return;
3637     }
3638 
3639     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3640     expect(Ok, status);
3641     expect(1, dim_count);
3642 
3643     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3644     expect(Ok, status);
3645     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3646 
3647     frame_count = 0xdeadbeef;
3648     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3649     expect(Ok, status);
3650     expect(1, frame_count);
3651 
3652     prop_count = 0xdeadbeef;
3653     status = GdipGetPropertyCount(image, &prop_count);
3654     expect(Ok, status);
3655     ok(prop_count == ARRAY_SIZE(td) ||
3656        broken(prop_count == ARRAY_SIZE(td) - 1) /* Win7 SP0 */,
3657        "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
3658 
3659     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3660 
3661     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3662     expect(Ok, status);
3663 
3664     for (i = 0; i < prop_count; i++)
3665     {
3666         status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3667         expect(Ok, status);
3668         if (status != Ok) break;
3669         ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3670 
3671         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3672         status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3673         expect(Ok, status);
3674         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3675         ok(td[i].type == prop_item->type ||
3676            /* Win7 stopped using proper but not documented types, and it
3677               looks broken since TypeFloat and TypeDouble now reported as
3678               TypeUndefined, and signed types reported as unsigned. */
3679            broken(prop_item->type == documented_type(td[i].type)),
3680             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3681         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3682         prop_size -= sizeof(*prop_item);
3683         ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3684         ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3685            "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3686         ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3687            "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3688         if (td[i].length == prop_item->length)
3689         {
3690             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3691             ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3692             if (!match)
3693             {
3694                 UINT j;
3695                 BYTE *data = prop_item->value;
3696                 trace("id %#x:", prop_item->id);
3697                 for (j = 0; j < prop_item->length; j++)
3698                     trace(" %02x", data[j]);
3699                 trace("\n");
3700             }
3701         }
3702         HeapFree(GetProcessHeap(), 0, prop_item);
3703     }
3704 
3705     HeapFree(GetProcessHeap(), 0, prop_id);
3706 
3707     GdipDisposeImage(image);
3708 }
3709 
3710 static void test_GdipGetAllPropertyItems(void)
3711 {
3712     static const struct test_data
3713     {
3714         ULONG type, id, length;
3715         BYTE value[32];
3716     } td[16] =
3717     {
3718         { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3719         { PropertyTagTypeShort, 0x100, 2, { 1 } },
3720         { PropertyTagTypeShort, 0x101, 2, { 1 } },
3721         { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3722         { PropertyTagTypeShort, 0x103, 2, { 1 } },
3723         { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3724         { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3725         { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3726         { PropertyTagTypeShort, 0x112, 2, { 1 } },
3727         { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3728         { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3729         { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3730         { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3731         { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3732         { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3733         { PropertyTagTypeShort, 0x128, 2, { 2 } }
3734     };
3735     GpStatus status;
3736     GpImage *image;
3737     GUID guid;
3738     UINT dim_count, frame_count, prop_count, prop_size, i;
3739     UINT total_size, total_count;
3740     PROPID *prop_id;
3741     PropertyItem *prop_item;
3742     const char *item_data;
3743 
3744     image = load_image(tiffimage, sizeof(tiffimage), TRUE, FALSE);
3745     ok(image != 0, "Failed to load TIFF image data\n");
3746     if (!image) return;
3747 
3748     dim_count = 0xdeadbeef;
3749     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3750     expect(Ok, status);
3751     expect(1, dim_count);
3752 
3753     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3754     expect(Ok, status);
3755     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3756 
3757     frame_count = 0xdeadbeef;
3758     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3759     expect(Ok, status);
3760     expect(1, frame_count);
3761 
3762     prop_count = 0xdeadbeef;
3763     status = GdipGetPropertyCount(image, &prop_count);
3764     expect(Ok, status);
3765     ok(prop_count == ARRAY_SIZE(td),
3766        "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
3767 
3768     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3769 
3770     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3771     expect(Ok, status);
3772 
3773     prop_size = 0;
3774     for (i = 0; i < prop_count; i++)
3775     {
3776         UINT size;
3777         status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3778         expect(Ok, status);
3779         if (status != Ok) break;
3780         ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3781 
3782         prop_size += size;
3783 
3784         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3785         status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3786         expect(Ok, status);
3787         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3788         ok(td[i].type == prop_item->type,
3789             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3790         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3791         size -= sizeof(*prop_item);
3792         ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3793         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3794         if (td[i].length == prop_item->length)
3795         {
3796             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3797             ok(match, "%u: data mismatch\n", i);
3798             if (!match)
3799             {
3800                 UINT j;
3801                 BYTE *data = prop_item->value;
3802                 trace("id %#x:", prop_item->id);
3803                 for (j = 0; j < prop_item->length; j++)
3804                     trace(" %02x", data[j]);
3805                 trace("\n");
3806             }
3807         }
3808         HeapFree(GetProcessHeap(), 0, prop_item);
3809     }
3810 
3811     HeapFree(GetProcessHeap(), 0, prop_id);
3812 
3813     status = GdipGetPropertySize(NULL, &total_size, &total_count);
3814     expect(InvalidParameter, status);
3815     status = GdipGetPropertySize(image, &total_size, NULL);
3816     expect(InvalidParameter, status);
3817     status = GdipGetPropertySize(image, NULL, &total_count);
3818     expect(InvalidParameter, status);
3819     status = GdipGetPropertySize(image, NULL, NULL);
3820     expect(InvalidParameter, status);
3821     total_size = 0xdeadbeef;
3822     total_count = 0xdeadbeef;
3823     status = GdipGetPropertySize(image, &total_size, &total_count);
3824     expect(Ok, status);
3825     ok(prop_count == total_count,
3826        "expected total property count %u, got %u\n", prop_count, total_count);
3827     ok(prop_size == total_size,
3828        "expected total property size %u, got %u\n", prop_size, total_size);
3829 
3830     prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3831 
3832     status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3833     expect(InvalidParameter, status);
3834     status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3835     expect(InvalidParameter, status);
3836     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3837     expect(InvalidParameter, status);
3838     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3839     expect(InvalidParameter, status);
3840     status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3841     expect(InvalidParameter, status);
3842     status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3843     expect(InvalidParameter, status);
3844     status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3845     expect(Ok, status);
3846 
3847     item_data = (const char *)(prop_item + prop_count);
3848     for (i = 0; i < prop_count; i++)
3849     {
3850         ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3851            i, item_data, prop_item[i].value);
3852         ok(td[i].type == prop_item[i].type,
3853             "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3854         ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3855         ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3856         if (td[i].length == prop_item[i].length)
3857         {
3858             int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3859             ok(match, "%u: data mismatch\n", i);
3860             if (!match)
3861             {
3862                 UINT j;
3863                 BYTE *data = prop_item[i].value;
3864                 trace("id %#x:", prop_item[i].id);
3865                 for (j = 0; j < prop_item[i].length; j++)
3866                     trace(" %02x", data[j]);
3867                 trace("\n");
3868             }
3869         }
3870         item_data += prop_item[i].length;
3871     }
3872 
3873     HeapFree(GetProcessHeap(), 0, prop_item);
3874 
3875     GdipDisposeImage(image);
3876 }
3877 
3878 static void test_tiff_palette(void)
3879 {
3880     GpStatus status;
3881     GpImage *image;
3882     PixelFormat format;
3883     INT size;
3884     struct
3885     {
3886         ColorPalette pal;
3887         ARGB entry[256];
3888     } palette;
3889     ARGB *entries = palette.pal.Entries;
3890 
3891     /* 1bpp TIFF without palette */
3892     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data), TRUE, FALSE);
3893     if (!image)
3894     {
3895         win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3896         return;
3897     }
3898 
3899     status = GdipGetImagePixelFormat(image, &format);
3900     expect(Ok, status);
3901     ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3902 
3903     status = GdipGetImagePaletteSize(image, &size);
3904     ok(status == Ok || broken(status == GenericError), /* XP */
3905        "GdipGetImagePaletteSize error %d\n", status);
3906     if (status == GenericError)
3907     {
3908         GdipDisposeImage(image);
3909         return;
3910     }
3911     expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3912 
3913     status = GdipGetImagePalette(image, &palette.pal, size);
3914     expect(Ok, status);
3915     expect(0, palette.pal.Flags);
3916     expect(2, palette.pal.Count);
3917     if (palette.pal.Count == 2)
3918     {
3919         ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3920         ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3921     }
3922 
3923     GdipDisposeImage(image);
3924 }
3925 
3926 static void test_bitmapbits(void)
3927 {
3928     /* 8 x 2 bitmap */
3929     static const BYTE pixels_24[48] =
3930     {
3931         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3932         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3933         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3934         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3935     };
3936     static const BYTE pixels_00[48] =
3937     {
3938         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3939         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3940         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3941         0,0,0, 0,0,0, 0,0,0, 0,0,0
3942     };
3943     static const BYTE pixels_24_77[64] =
3944     {
3945         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3946         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3947         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3948         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3949         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3950         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3951     };
3952     static const BYTE pixels_77[64] =
3953     {
3954         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3955         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3956         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3957         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3958         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3959         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3960         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3961         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3962     };
3963     static const BYTE pixels_8[16] =
3964     {
3965         0x01,0,0x01,0,0x01,0,0x01,0,
3966         0x01,0,0x01,0,0x01,0,0x01,0
3967     };
3968     static const BYTE pixels_8_77[64] =
3969     {
3970         0x01,0,0x01,0,0x01,0,0x01,0,
3971         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3972         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3973         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3974         0x01,0,0x01,0,0x01,0,0x01,0,
3975         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3976         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3977         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3978     };
3979     static const BYTE pixels_1_77[64] =
3980     {
3981         0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3982         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3983         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3984         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3985         0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3986         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3987         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3988         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3989     };
3990     static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3991     static const struct test_data
3992     {
3993         PixelFormat format;
3994         UINT bpp;
3995         ImageLockMode mode;
3996         UINT stride, size;
3997         const BYTE *pixels;
3998         const BYTE *pixels_unlocked;
3999     } td[] =
4000     {
4001         /* 0 */
4002         { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
4003 
4004         { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
4005         { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
4006         { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
4007         { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
4008         { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
4009         { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
4010         { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
4011         /* 8 */
4012         { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
4013         { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
4014         { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
4015         { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
4016         { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
4017         { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
4018         { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
4019         /* 15 */
4020         { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
4021         { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
4022         { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
4023         { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
4024         { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
4025         { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
4026         { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
4027     };
4028     BYTE buf[64];
4029     GpStatus status;
4030     GpBitmap *bitmap;
4031     UINT i;
4032     BitmapData data;
4033     struct
4034     {
4035         ColorPalette pal;
4036         ARGB entries[1];
4037     } palette;
4038     ARGB *entries = palette.pal.Entries;
4039 
4040     for (i = 0; i < ARRAY_SIZE(td); i++)
4041     {
4042         BYTE pixels[sizeof(pixels_24)];
4043         memcpy(pixels, pixels_24, sizeof(pixels_24));
4044         status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
4045         expect(Ok, status);
4046 
4047         /* associate known palette with pixel data */
4048         palette.pal.Flags = PaletteFlagsGrayScale;
4049         palette.pal.Count = 2;
4050         entries[0] = 0xff000000;
4051         entries[1] = 0xffffffff;
4052         status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
4053         expect(Ok, status);
4054 
4055         memset(&data, 0xfe, sizeof(data));
4056         if (td[i].mode & ImageLockModeUserInputBuf)
4057         {
4058             memset(buf, 0x77, sizeof(buf));
4059             data.Scan0 = buf;
4060             data.Stride = 32;
4061         }
4062         status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
4063         ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
4064         if (status != Ok)
4065         {
4066             GdipDisposeImage((GpImage *)bitmap);
4067             continue;
4068         }
4069         ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
4070         ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
4071         ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
4072         ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
4073         ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
4074         if (td[i].mode & ImageLockModeUserInputBuf)
4075             ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
4076         if (td[i].size == data.Height * data.Stride)
4077         {
4078             UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
4079 
4080             match = 1;
4081             for (j = 0; j < data.Height; j++)
4082             {
4083                 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
4084                 {
4085                     match = 0;
4086                     break;
4087                 }
4088             }
4089             if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
4090             {
4091                 ok(match,
4092                    "%u: data should match\n", i);
4093                 if (!match)
4094                 {
4095                     BYTE *bits = data.Scan0;
4096                     trace("%u: data mismatch for format %#x:", i, td[i].format);
4097                     for (j = 0; j < td[i].size; j++)
4098                         trace(" %02x", bits[j]);
4099                     trace("\n");
4100                 }
4101             }
4102             else
4103                 ok(!match, "%u: data shouldn't match\n", i);
4104 
4105             memset(data.Scan0, 0, td[i].size);
4106         }
4107 
4108         status = GdipBitmapUnlockBits(bitmap, &data);
4109         ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
4110 
4111         memset(&data, 0xfe, sizeof(data));
4112         status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4113         ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
4114         ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
4115         ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
4116         ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
4117         ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
4118         ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
4119         if (data.Height * data.Stride == 48)
4120         {
4121             int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
4122             ok(match, "%u: data should match\n", i);
4123             if (!match)
4124             {
4125                 UINT j;
4126                 BYTE *bits = data.Scan0;
4127                 trace("%u: data mismatch for format %#x:", i, td[i].format);
4128                 for (j = 0; j < 48; j++)
4129                     trace(" %02x", bits[j]);
4130                 trace("\n");
4131             }
4132         }
4133 
4134         status = GdipBitmapUnlockBits(bitmap, &data);
4135         ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
4136 
4137         status = GdipDisposeImage((GpImage *)bitmap);
4138         expect(Ok, status);
4139     }
4140 }
4141 
4142 static void test_DrawImage(void)
4143 {
4144     BYTE black_1x1[4] = { 0,0,0,0 };
4145     BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4146                            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4147     BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4148                            0,0,0,0,0,0,0xff,0xff };
4149     GpStatus status;
4150     union
4151     {
4152         GpBitmap *bitmap;
4153         GpImage *image;
4154     } u1, u2;
4155     GpGraphics *graphics;
4156     int match;
4157 
4158     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4159     expect(Ok, status);
4160     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4161     expect(Ok, status);
4162 
4163     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4164     expect(Ok, status);
4165     status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4166     expect(Ok, status);
4167     status = GdipGetImageGraphicsContext(u2.image, &graphics);
4168     expect(Ok, status);
4169     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4170     expect(Ok, status);
4171 
4172     status = GdipDrawImageI(graphics, u1.image, 0, 0);
4173     expect(Ok, status);
4174 
4175     match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4176     ok(match, "data should match\n");
4177     if (!match)
4178     {
4179         UINT i, size = sizeof(white_2x2);
4180         BYTE *bits = white_2x2;
4181         for (i = 0; i < size; i++)
4182             trace(" %02x", bits[i]);
4183         trace("\n");
4184     }
4185 
4186     status = GdipDeleteGraphics(graphics);
4187     expect(Ok, status);
4188     status = GdipDisposeImage(u1.image);
4189     expect(Ok, status);
4190     status = GdipDisposeImage(u2.image);
4191     expect(Ok, status);
4192 }
4193 
4194 static void test_DrawImage_SourceCopy(void)
4195 {
4196     DWORD dst_pixels[4] = { 0xffffffff, 0xffffffff,
4197                             0xffffffff, 0xffffffff };
4198     DWORD src_pixels[4] = { 0, 0xffff0000,
4199                             0, 0xff00ff };
4200 
4201     GpStatus status;
4202     union
4203     {
4204         GpBitmap *bitmap;
4205         GpImage *image;
4206     } u1, u2;
4207     GpGraphics *graphics;
4208 
4209     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)dst_pixels, &u1.bitmap);
4210     expect(Ok, status);
4211 
4212     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)src_pixels, &u2.bitmap);
4213     expect(Ok, status);
4214     status = GdipGetImageGraphicsContext(u1.image, &graphics);
4215     expect(Ok, status);
4216     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4217     expect(Ok, status);
4218 
4219     status = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
4220     expect(Ok, status);
4221 
4222     status = GdipDrawImageI(graphics, u2.image, 0, 0);
4223     expect(Ok, status);
4224 
4225     todo_wine expect(0, dst_pixels[0]);
4226     expect(0xffff0000, dst_pixels[1]);
4227     todo_wine expect(0, dst_pixels[2]);
4228     todo_wine expect(0, dst_pixels[3]);
4229 
4230     status = GdipDeleteGraphics(graphics);
4231     expect(Ok, status);
4232     status = GdipDisposeImage(u1.image);
4233     expect(Ok, status);
4234     status = GdipDisposeImage(u2.image);
4235     expect(Ok, status);
4236 }
4237 
4238 static void test_GdipDrawImagePointRect(void)
4239 {
4240     BYTE black_1x1[4] = { 0,0,0,0 };
4241     BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4242                            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4243     BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4244                            0,0,0,0,0,0,0xff,0xff };
4245     GpStatus status;
4246     union
4247     {
4248         GpBitmap *bitmap;
4249         GpImage *image;
4250     } u1, u2;
4251     GpGraphics *graphics;
4252     int match;
4253 
4254     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4255     expect(Ok, status);
4256     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4257     expect(Ok, status);
4258 
4259     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4260     expect(Ok, status);
4261     status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4262     expect(Ok, status);
4263     status = GdipGetImageGraphicsContext(u2.image, &graphics);
4264     expect(Ok, status);
4265     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4266     expect(Ok, status);
4267 
4268     status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
4269     expect(Ok, status);
4270 
4271     match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4272     ok(match, "data should match\n");
4273     if (!match)
4274     {
4275         UINT i, size = sizeof(white_2x2);
4276         BYTE *bits = white_2x2;
4277         for (i = 0; i < size; i++)
4278             trace(" %02x", bits[i]);
4279         trace("\n");
4280     }
4281 
4282     status = GdipDeleteGraphics(graphics);
4283     expect(Ok, status);
4284     status = GdipDisposeImage(u1.image);
4285     expect(Ok, status);
4286     status = GdipDisposeImage(u2.image);
4287     expect(Ok, status);
4288 }
4289 
4290 static void test_image_format(void)
4291 {
4292     static const PixelFormat fmt[] =
4293     {
4294         PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4295         PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4296         PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4297         PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4298         PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4299     };
4300     GpStatus status;
4301     GpBitmap *bitmap;
4302     GpImage *thumb;
4303     HBITMAP hbitmap;
4304     BITMAP bm;
4305     PixelFormat format;
4306     BitmapData data;
4307     UINT i, ret;
4308 
4309     for (i = 0; i < ARRAY_SIZE(fmt); i++)
4310     {
4311         status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4312         ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4313            "GdipCreateBitmapFromScan0 error %d\n", status);
4314         if (status != Ok) continue;
4315 
4316         status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4317         expect(Ok, status);
4318         expect(fmt[i], format);
4319 
4320         status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4321         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4322             todo_wine expect(InvalidParameter, status);
4323         else
4324         {
4325             expect(Ok, status);
4326             ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4327             expect(sizeof(bm), ret);
4328             expect(0, bm.bmType);
4329             expect(1, bm.bmWidth);
4330             expect(1, bm.bmHeight);
4331             expect(4, bm.bmWidthBytes);
4332             expect(1, bm.bmPlanes);
4333             expect(32, bm.bmBitsPixel);
4334             DeleteObject(hbitmap);
4335         }
4336 
4337         status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4338         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4339             todo_wine
4340             ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4341                "expected OutOfMemory, got %d\n", status);
4342         else
4343             expect(Ok, status);
4344         if (status == Ok)
4345         {
4346             status = GdipGetImagePixelFormat(thumb, &format);
4347             expect(Ok, status);
4348             ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4349                "expected PixelFormat32bppPARGB, got %#x\n", format);
4350             status = GdipDisposeImage(thumb);
4351             expect(Ok, status);
4352         }
4353 
4354         status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4355         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4356             todo_wine expect(InvalidParameter, status);
4357         else
4358         {
4359             expect(Ok, status);
4360             status = GdipBitmapUnlockBits(bitmap, &data);
4361             expect(Ok, status);
4362         }
4363 
4364         status = GdipDisposeImage((GpImage *)bitmap);
4365         expect(Ok, status);
4366     }
4367 }
4368 
4369 static void test_DrawImage_scale(void)
4370 {
4371     static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4372                                        0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4373     static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4374                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4375     static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4376                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4377     static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4378                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4379     static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4380                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4381     static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4382                                         0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4383     static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4384                                         0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4385     static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4386                                         0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4387     static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4388                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4389     static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4390                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4391     static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4392                                         0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4393     static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4394                                         0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4395     static const struct test_data
4396     {
4397         REAL scale_x;
4398         PixelOffsetMode pixel_offset_mode;
4399         const BYTE *image;
4400         BOOL todo;
4401     } td[] =
4402     {
4403         { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4404         { 1.0, PixelOffsetModeNone, image_100 },
4405         { 1.2, PixelOffsetModeNone, image_120 },
4406         { 1.5, PixelOffsetModeNone, image_150 },
4407         { 1.8, PixelOffsetModeNone, image_180 },
4408         { 2.0, PixelOffsetModeNone, image_200 },
4409         { 2.5, PixelOffsetModeNone, image_250 },
4410 
4411         { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4412         { 1.0, PixelOffsetModeHighSpeed, image_100 },
4413         { 1.2, PixelOffsetModeHighSpeed, image_120 },
4414         { 1.5, PixelOffsetModeHighSpeed, image_150 },
4415         { 1.8, PixelOffsetModeHighSpeed, image_180 },
4416         { 2.0, PixelOffsetModeHighSpeed, image_200 },
4417         { 2.5, PixelOffsetModeHighSpeed, image_250 },
4418 
4419         { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4420         { 1.0, PixelOffsetModeHalf, image_100 },
4421         { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4422         { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4423         { 1.8, PixelOffsetModeHalf, image_180 },
4424         { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4425         { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4426 
4427         { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4428         { 1.0, PixelOffsetModeHighQuality, image_100 },
4429         { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4430         { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4431         { 1.8, PixelOffsetModeHighQuality, image_180 },
4432         { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4433         { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4434     };
4435     BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4436     BYTE dst_8x1[24];
4437     GpStatus status;
4438     union
4439     {
4440         GpBitmap *bitmap;
4441         GpImage *image;
4442     } u1, u2;
4443     GpGraphics *graphics;
4444     GpMatrix *matrix;
4445     int i, match;
4446 
4447     status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4448     expect(Ok, status);
4449     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4450     expect(Ok, status);
4451 
4452     status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4453     expect(Ok, status);
4454     status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4455     expect(Ok, status);
4456     status = GdipGetImageGraphicsContext(u2.image, &graphics);
4457     expect(Ok, status);
4458     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4459     expect(Ok, status);
4460 
4461     for (i = 0; i < ARRAY_SIZE(td); i++)
4462     {
4463         status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4464         expect(Ok, status);
4465 
4466         status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4467         expect(Ok, status);
4468         status = GdipSetWorldTransform(graphics, matrix);
4469         expect(Ok, status);
4470         GdipDeleteMatrix(matrix);
4471 
4472         memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4473         status = GdipDrawImageI(graphics, u1.image, 1, 0);
4474         expect(Ok, status);
4475 
4476         match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4477         todo_wine_if (!match && td[i].todo)
4478             ok(match, "%d: data should match\n", i);
4479         if (!match)
4480         {
4481             UINT i, size = sizeof(dst_8x1);
4482             const BYTE *bits = dst_8x1;
4483             for (i = 0; i < size; i++)
4484                 trace(" %02x", bits[i]);
4485             trace("\n");
4486         }
4487     }
4488 
4489     status = GdipDeleteGraphics(graphics);
4490     expect(Ok, status);
4491     status = GdipDisposeImage(u1.image);
4492     expect(Ok, status);
4493     status = GdipDisposeImage(u2.image);
4494     expect(Ok, status);
4495 }
4496 
4497 static const BYTE animatedgif[] = {
4498 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4499 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4500 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4501 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4502 0x03,0x01,0x05,0x00,0x00,
4503 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4504 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4505 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4506 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4507 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4508 0x02,0x02,0x4C,0x01,0x00,
4509 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4510 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4511 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4512 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4513 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4514 0x02,0x02,0x44,0x01,0x00,
4515 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4516 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4517 };
4518 
4519 static void test_gif_properties(void)
4520 {
4521     static const struct test_data
4522     {
4523         ULONG type, id, length;
4524         const BYTE value[13];
4525     } td[] =
4526     {
4527         { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4528         { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4529         { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4530         { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4531         { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4532         { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4533     };
4534     GpStatus status;
4535     GpImage *image;
4536     GUID guid;
4537     UINT dim_count, frame_count, prop_count, prop_size, i;
4538     UINT total_size, total_count;
4539     PROPID *prop_id;
4540     PropertyItem *prop_item;
4541     const char *item_data;
4542 
4543     image = load_image(animatedgif, sizeof(animatedgif), TRUE, FALSE);
4544     if (!image) /* XP fails to load this GIF image */
4545     {
4546         trace("Failed to load GIF image data\n");
4547         return;
4548     }
4549 
4550     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4551     expect(Ok, status);
4552     expect(1, dim_count);
4553 
4554     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4555     expect(Ok, status);
4556     expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4557 
4558     status = GdipImageGetFrameCount(image, &guid, &frame_count);
4559     expect(Ok, status);
4560     expect(2, frame_count);
4561 
4562     status = GdipImageSelectActiveFrame(image, &guid, 1);
4563     expect(Ok, status);
4564 
4565     status = GdipGetPropertyCount(image, &prop_count);
4566     expect(Ok, status);
4567     ok(prop_count == ARRAY_SIZE(td) || broken(prop_count == 1) /* before win7 */,
4568        "expected property count %u, got %u\n", (UINT) ARRAY_SIZE(td), prop_count);
4569 
4570     if (prop_count != ARRAY_SIZE(td))
4571     {
4572         GdipDisposeImage(image);
4573         return;
4574     }
4575 
4576     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4577 
4578     status = GdipGetPropertyIdList(image, prop_count, prop_id);
4579     expect(Ok, status);
4580 
4581     prop_size = 0;
4582     for (i = 0; i < prop_count; i++)
4583     {
4584         UINT size;
4585         status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4586         expect(Ok, status);
4587         if (status != Ok) break;
4588         ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4589 
4590         prop_size += size;
4591 
4592         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4593         status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4594         expect(Ok, status);
4595         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4596         ok(td[i].type == prop_item->type,
4597             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4598         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4599         size -= sizeof(*prop_item);
4600         ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4601         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4602         if (td[i].length == prop_item->length)
4603         {
4604             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4605             ok(match, "%u: data mismatch\n", i);
4606             if (!match)
4607             {
4608                 UINT j;
4609                 BYTE *data = prop_item->value;
4610                 trace("id %#x:", prop_item->id);
4611                 for (j = 0; j < prop_item->length; j++)
4612                     trace(" %02x", data[j]);
4613                 trace("\n");
4614             }
4615         }
4616         HeapFree(GetProcessHeap(), 0, prop_item);
4617     }
4618 
4619     HeapFree(GetProcessHeap(), 0, prop_id);
4620 
4621     status = GdipGetPropertySize(NULL, &total_size, &total_count);
4622     expect(InvalidParameter, status);
4623     status = GdipGetPropertySize(image, &total_size, NULL);
4624     expect(InvalidParameter, status);
4625     status = GdipGetPropertySize(image, NULL, &total_count);
4626     expect(InvalidParameter, status);
4627     status = GdipGetPropertySize(image, NULL, NULL);
4628     expect(InvalidParameter, status);
4629     total_size = 0xdeadbeef;
4630     total_count = 0xdeadbeef;
4631     status = GdipGetPropertySize(image, &total_size, &total_count);
4632     expect(Ok, status);
4633     ok(prop_count == total_count,
4634        "expected total property count %u, got %u\n", prop_count, total_count);
4635     ok(prop_size == total_size,
4636        "expected total property size %u, got %u\n", prop_size, total_size);
4637 
4638     prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4639 
4640     status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4641     expect(InvalidParameter, status);
4642     status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4643     expect(InvalidParameter, status);
4644     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4645     expect(InvalidParameter, status);
4646     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4647     expect(InvalidParameter, status);
4648     status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4649     expect(InvalidParameter, status);
4650     status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4651     expect(InvalidParameter, status);
4652     status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4653     expect(Ok, status);
4654 
4655     item_data = (const char *)(prop_item + prop_count);
4656     for (i = 0; i < prop_count; i++)
4657     {
4658         ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4659            i, item_data, prop_item[i].value);
4660         ok(td[i].type == prop_item[i].type,
4661             "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4662         ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4663         ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4664         if (td[i].length == prop_item[i].length)
4665         {
4666             int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4667             ok(match, "%u: data mismatch\n", i);
4668             if (!match)
4669             {
4670                 UINT j;
4671                 BYTE *data = prop_item[i].value;
4672                 trace("id %#x:", prop_item[i].id);
4673                 for (j = 0; j < prop_item[i].length; j++)
4674                     trace(" %02x", data[j]);
4675                 trace("\n");
4676             }
4677         }
4678         item_data += prop_item[i].length;
4679     }
4680 
4681     HeapFree(GetProcessHeap(), 0, prop_item);
4682 
4683     GdipDisposeImage(image);
4684 }
4685 
4686 static void test_ARGB_conversion(void)
4687 {
4688     BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4689     BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4690     BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4691     BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4692     BYTE *bits;
4693     GpBitmap *bitmap;
4694     BitmapData data;
4695     GpStatus status;
4696     int match;
4697 
4698     status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4699     expect(Ok, status);
4700 
4701     status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4702     expect(Ok, status);
4703     ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4704     ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4705     ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4706     ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4707     match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4708     ok(match, "bits don't match\n");
4709     if (!match)
4710     {
4711         bits = data.Scan0;
4712         trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4713                bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4714     }
4715     status = GdipBitmapUnlockBits(bitmap, &data);
4716     expect(Ok, status);
4717 
4718     status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4719     expect(Ok, status);
4720     ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4721     ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4722     ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4723     ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4724     match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4725             !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4726     ok(match, "bits don't match\n");
4727     if (!match)
4728     {
4729         bits = data.Scan0;
4730         trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4731                bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4732     }
4733     status = GdipBitmapUnlockBits(bitmap, &data);
4734     expect(Ok, status);
4735 
4736     status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4737     expect(Ok, status);
4738     ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4739     ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4740     ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4741     ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4742     match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4743     ok(match, "bits don't match\n");
4744     if (!match)
4745     {
4746         bits = data.Scan0;
4747         trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4748                bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4749     }
4750     status = GdipBitmapUnlockBits(bitmap, &data);
4751     expect(Ok, status);
4752 
4753     GdipDisposeImage((GpImage *)bitmap);
4754 }
4755 
4756 
4757 static void test_CloneBitmapArea(void)
4758 {
4759     GpStatus status;
4760     GpBitmap *bitmap, *copy;
4761     BitmapData data, data2;
4762 
4763     status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4764     expect(Ok, status);
4765 
4766     status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4767     expect(Ok, status);
4768 
4769     status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4770     expect(WrongState, status);
4771 
4772     status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4773     expect(Ok, status);
4774 
4775     status = GdipBitmapUnlockBits(bitmap, &data);
4776     expect(Ok, status);
4777 
4778     GdipDisposeImage((GpImage *)copy);
4779     GdipDisposeImage((GpImage *)bitmap);
4780 }
4781 
4782 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid)
4783 {
4784     GpStatus status;
4785     UINT n_codecs, info_size, i;
4786     ImageCodecInfo *info;
4787     BOOL ret = FALSE;
4788 
4789     status = GdipGetImageEncodersSize(&n_codecs, &info_size);
4790     expect(Ok, status);
4791 
4792     info = GdipAlloc(info_size);
4793 
4794     status = GdipGetImageEncoders(n_codecs, info_size, info);
4795     expect(Ok, status);
4796 
4797     for (i = 0; i < n_codecs; i++)
4798     {
4799         if (!lstrcmpW(info[i].MimeType, mime))
4800         {
4801             *format = info[i].FormatID;
4802             *clsid = info[i].Clsid;
4803             ret = TRUE;
4804             break;
4805         }
4806     }
4807 
4808     GdipFree(info);
4809     return ret;
4810 }
4811 
4812 static void test_supported_encoders(void)
4813 {
4814     static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 };
4815     static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 };
4816     static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 };
4817     static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 };
4818     static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 };
4819     static const struct test_data
4820     {
4821         LPCWSTR mime;
4822         const GUID *format;
4823     } td[] =
4824     {
4825         { bmp_mimetype, &ImageFormatBMP },
4826         { jpeg_mimetype, &ImageFormatJPEG },
4827         { gif_mimetype, &ImageFormatGIF },
4828         { tiff_mimetype, &ImageFormatTIFF },
4829         { png_mimetype, &ImageFormatPNG }
4830     };
4831     GUID format, clsid;
4832     BOOL ret;
4833     HRESULT hr;
4834     GpStatus status;
4835     GpBitmap *bm;
4836     IStream *stream;
4837     HGLOBAL hmem;
4838     int i;
4839 
4840     status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
4841     ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
4842 
4843     for (i = 0; i < ARRAY_SIZE(td); i++)
4844     {
4845         ret = get_encoder_clsid(td[i].mime, &format, &clsid);
4846         ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
4847         expect_guid(td[i].format, &format, __LINE__, FALSE);
4848 
4849         hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
4850 
4851         hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
4852         ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
4853 
4854         status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
4855         ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4856 
4857         IStream_Release(stream);
4858     }
4859 
4860     GdipDisposeImage((GpImage *)bm);
4861 }
4862 
4863 static void test_createeffect(void)
4864 {
4865     static const GUID noneffect = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } };
4866     GpStatus (WINAPI *pGdipCreateEffect)( const GUID guid, CGpEffect **effect);
4867     GpStatus (WINAPI *pGdipDeleteEffect)( CGpEffect *effect);
4868     GpStatus stat;
4869     CGpEffect *effect;
4870     HMODULE mod = GetModuleHandleA("gdiplus.dll");
4871     int i;
4872     const GUID * const effectlist[] =
4873                {&BlurEffectGuid, &SharpenEffectGuid, &ColorMatrixEffectGuid, &ColorLUTEffectGuid,
4874                 &BrightnessContrastEffectGuid, &HueSaturationLightnessEffectGuid, &LevelsEffectGuid,
4875                 &TintEffectGuid, &ColorBalanceEffectGuid, &RedEyeCorrectionEffectGuid, &ColorCurveEffectGuid};
4876 
4877     pGdipCreateEffect = (void*)GetProcAddress( mod, "GdipCreateEffect");
4878     pGdipDeleteEffect = (void*)GetProcAddress( mod, "GdipDeleteEffect");
4879     if(!pGdipCreateEffect || !pGdipDeleteEffect)
4880     {
4881         /* GdipCreateEffect/GdipDeleteEffect was introduced in Windows Vista. */
4882         win_skip("GDIPlus version 1.1 not available\n");
4883         return;
4884     }
4885 
4886     stat = pGdipCreateEffect(BlurEffectGuid, NULL);
4887     expect(InvalidParameter, stat);
4888 
4889     stat = pGdipCreateEffect(noneffect, &effect);
4890     todo_wine expect(Win32Error, stat);
4891 
4892     for(i=0; i < ARRAY_SIZE(effectlist); i++)
4893     {
4894         stat = pGdipCreateEffect(*effectlist[i], &effect);
4895         todo_wine expect(Ok, stat);
4896         if(stat == Ok)
4897         {
4898             stat = pGdipDeleteEffect(effect);
4899             expect(Ok, stat);
4900         }
4901     }
4902 }
4903 
4904 static void test_getadjustedpalette(void)
4905 {
4906     ColorMap colormap;
4907     GpImageAttributes *imageattributes;
4908     ColorPalette *palette;
4909     GpStatus stat;
4910 
4911     stat = GdipCreateImageAttributes(&imageattributes);
4912     expect(Ok, stat);
4913 
4914     colormap.oldColor.Argb = 0xffffff00;
4915     colormap.newColor.Argb = 0xffff00ff;
4916     stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeBitmap,
4917         TRUE, 1, &colormap);
4918     expect(Ok, stat);
4919 
4920     colormap.oldColor.Argb = 0xffffff80;
4921     colormap.newColor.Argb = 0xffff80ff;
4922     stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeDefault,
4923         TRUE, 1, &colormap);
4924     expect(Ok, stat);
4925 
4926     palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 2);
4927     palette->Count = 0;
4928 
4929     stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4930     expect(InvalidParameter, stat);
4931 
4932     palette->Count = 3;
4933     palette->Entries[0] = 0xffffff00;
4934     palette->Entries[1] = 0xffffff80;
4935     palette->Entries[2] = 0xffffffff;
4936 
4937     stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4938     expect(Ok, stat);
4939     expect(0xffff00ff, palette->Entries[0]);
4940     expect(0xffffff80, palette->Entries[1]);
4941     expect(0xffffffff, palette->Entries[2]);
4942 
4943     palette->Entries[0] = 0xffffff00;
4944     palette->Entries[1] = 0xffffff80;
4945     palette->Entries[2] = 0xffffffff;
4946 
4947     stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBrush);
4948     expect(Ok, stat);
4949     expect(0xffffff00, palette->Entries[0]);
4950     expect(0xffff80ff, palette->Entries[1]);
4951     expect(0xffffffff, palette->Entries[2]);
4952 
4953     stat = GdipGetImageAttributesAdjustedPalette(NULL, palette, ColorAdjustTypeBitmap);
4954     expect(InvalidParameter, stat);
4955 
4956     stat = GdipGetImageAttributesAdjustedPalette(imageattributes, NULL, ColorAdjustTypeBitmap);
4957     expect(InvalidParameter, stat);
4958 
4959     stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, -1);
4960     expect(InvalidParameter, stat);
4961 
4962     stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeDefault);
4963     expect(InvalidParameter, stat);
4964 
4965     GdipFree(palette);
4966     GdipDisposeImageAttributes(imageattributes);
4967 }
4968 
4969 static void test_histogram(void)
4970 {
4971     UINT ch0[256], ch1[256], ch2[256], ch3[256];
4972     HistogramFormat test_formats[] =
4973     {
4974         HistogramFormatARGB,
4975         HistogramFormatPARGB,
4976         HistogramFormatRGB,
4977         HistogramFormatGray,
4978         HistogramFormatB,
4979         HistogramFormatG,
4980         HistogramFormatR,
4981         HistogramFormatA,
4982     };
4983     const UINT WIDTH = 8, HEIGHT = 16;
4984     UINT num, i, x;
4985     GpStatus stat;
4986     GpBitmap *bm;
4987 
4988     if (!pGdipBitmapGetHistogramSize)
4989     {
4990         win_skip("GdipBitmapGetHistogramSize is not supported\n");
4991         return;
4992     }
4993 
4994     stat = pGdipBitmapGetHistogramSize(HistogramFormatARGB, NULL);
4995     expect(InvalidParameter, stat);
4996 
4997     stat = pGdipBitmapGetHistogramSize(0xff, NULL);
4998     expect(InvalidParameter, stat);
4999 
5000     num = 123;
5001     stat = pGdipBitmapGetHistogramSize(10, &num);
5002     expect(Ok, stat);
5003     expect(256, num);
5004 
5005     for (i = 0; i < ARRAY_SIZE(test_formats); i++)
5006     {
5007         num = 0;
5008         stat = pGdipBitmapGetHistogramSize(test_formats[i], &num);
5009         expect(Ok, stat);
5010         expect(256, num);
5011     }
5012 
5013     bm = NULL;
5014     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
5015     expect(Ok, stat);
5016 
5017     /* Three solid rgb rows, next three rows are rgb shades. */
5018     for (x = 0; x < WIDTH; x++)
5019     {
5020         GdipBitmapSetPixel(bm, x, 0, 0xffff0000);
5021         GdipBitmapSetPixel(bm, x, 1, 0xff00ff00);
5022         GdipBitmapSetPixel(bm, x, 2, 0xff0000ff);
5023 
5024         GdipBitmapSetPixel(bm, x, 3, 0xff010000);
5025         GdipBitmapSetPixel(bm, x, 4, 0xff003f00);
5026         GdipBitmapSetPixel(bm, x, 5, 0xff000020);
5027     }
5028 
5029     stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
5030     expect(InvalidParameter, stat);
5031 
5032     stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3);
5033     expect(InvalidParameter, stat);
5034 
5035     stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL);
5036     expect(InvalidParameter, stat);
5037 
5038     stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL);
5039     expect(InvalidParameter, stat);
5040 
5041     stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL);
5042     expect(InvalidParameter, stat);
5043 
5044     /* Requested format matches bitmap format */
5045     stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
5046     expect(InvalidParameter, stat);
5047 
5048     stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL);
5049     expect(InvalidParameter, stat);
5050 
5051     stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL);
5052     expect(InvalidParameter, stat);
5053 
5054     /* Channel 3 is not used, must be NULL */
5055     stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL);
5056     expect(Ok, stat);
5057 
5058     ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]);
5059     ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]);
5060     ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]);
5061     ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]);
5062     ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]);
5063     ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]);
5064 
5065     /* ARGB histogram from RGB data. */
5066     stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL);
5067     expect(InvalidParameter, stat);
5068 
5069     stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3);
5070     expect(Ok, stat);
5071 
5072     ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]);
5073     ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]);
5074     ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]);
5075     ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]);
5076     ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]);
5077     ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]);
5078 
5079     ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]);
5080 
5081     /* Request grayscale histogram from RGB bitmap. */
5082     stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3);
5083     expect(InvalidParameter, stat);
5084 
5085     stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL);
5086     expect(InvalidParameter, stat);
5087 
5088     stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL);
5089     expect(InvalidParameter, stat);
5090 
5091     stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL);
5092     expect(Ok, stat);
5093 
5094     GdipDisposeImage((GpImage*)bm);
5095 }
5096 
5097 static void test_imageabort(void)
5098 {
5099     GpStatus stat;
5100     GpBitmap *bm;
5101 
5102     if (!pGdipImageSetAbort)
5103     {
5104         win_skip("GdipImageSetAbort() is not supported.\n");
5105         return;
5106     }
5107 
5108     bm = NULL;
5109     stat = GdipCreateBitmapFromScan0(8, 8, 0, PixelFormat24bppRGB, NULL, &bm);
5110     expect(Ok, stat);
5111 
5112     stat = pGdipImageSetAbort(NULL, NULL);
5113     expect(InvalidParameter, stat);
5114 
5115     stat = pGdipImageSetAbort((GpImage*)bm, NULL);
5116     expect(Ok, stat);
5117 
5118     GdipDisposeImage((GpImage*)bm);
5119 }
5120 
5121 /* RGB 24 bpp 1x1 pixel PNG image */
5122 static const char png_1x1_data[] = {
5123   0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a,
5124   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,
5125   0x00,0x00,0x03,0x00,'P','L','T','E',
5126   0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
5127   0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,0x10,0x10,
5128   0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,
5129   0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,
5130   0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28,
5131   0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,
5132   0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
5133   0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
5134   0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x48,
5135   0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,
5136   0x51,0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,0x58,
5137   0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,
5138   0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,
5139   0x69,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x70,
5140   0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,
5141   0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,
5142   0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
5143   0x09,0x09,0x09,0x0a,0x0a,0x0a,0x0b,0x0b,0x0b,0x0c,0x0c,0x0c,0x0d,0x0d,0x0d,0x0e,0x0e,0x0e,0x0f,0x0f,0x0f,0x10,0x10,0x10,
5144   0x11,0x11,0x11,0x12,0x12,0x12,0x13,0x13,0x13,0x14,0x14,0x14,0x15,0x15,0x15,0x16,0x16,0x16,0x17,0x17,0x17,0x18,0x18,0x18,
5145   0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1e,0x1e,0x1e,0x1f,0x1f,0x1f,0x20,0x20,0x20,
5146   0x21,0x21,0x21,0x22,0x22,0x22,0x23,0x23,0x23,0x24,0x24,0x24,0x25,0x25,0x25,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28,
5147   0x29,0x29,0x29,0x2a,0x2a,0x2a,0x2b,0x2b,0x2b,0x2c,0x2c,0x2c,0x2d,0x2d,0x2d,0x2e,0x2e,0x2e,0x2f,0x2f,0x2f,0x30,0x30,0x30,
5148   0x31,0x31,0x31,0x32,0x32,0x32,0x33,0x33,0x33,0x34,0x34,0x34,0x35,0x35,0x35,0x36,0x36,0x36,0x37,0x37,0x37,0x38,0x38,0x38,
5149   0x39,0x39,0x39,0x3a,0x3a,0x3a,0x3b,0x3b,0x3b,0x3c,0x3c,0x3c,0x3d,0x3d,0x3d,0x3e,0x3e,0x3e,0x3f,0x3f,0x3f,0x40,0x40,0x40,
5150   0x41,0x41,0x41,0x42,0x42,0x42,0x43,0x43,0x43,0x44,0x44,0x44,0x45,0x45,0x45,0x46,0x46,0x46,0x47,0x47,0x47,0x48,0x48,0x48,
5151   0x49,0x49,0x49,0x4a,0x4a,0x4a,0x4b,0x4b,0x4b,0x4c,0x4c,0x4c,0x4d,0x4d,0x4d,0x4e,0x4e,0x4e,0x4f,0x4f,0x4f,0x50,0x50,0x50,
5152   0x51,0x51,0x51,0x52,0x52,0x52,0x53,0x53,0x53,0x54,0x54,0x54,0x55,0x55,0x55,0x56,0x56,0x56,0x57,0x57,0x57,0x58,0x58,0x58,
5153   0x59,0x59,0x59,0x5a,0x5a,0x5a,0x5b,0x5b,0x5b,0x5c,0x5c,0x5c,0x5d,0x5d,0x5d,0x5e,0x5e,0x5e,0x5f,0x5f,0x5f,0x60,0x60,0x60,
5154   0x61,0x61,0x61,0x62,0x62,0x62,0x63,0x63,0x63,0x64,0x64,0x64,0x65,0x65,0x65,0x66,0x66,0x66,0x67,0x67,0x67,0x68,0x68,0x68,
5155   0x69,0x69,0x69,0x6a,0x6a,0x6a,0x6b,0x6b,0x6b,0x6c,0x6c,0x6c,0x6d,0x6d,0x6d,0x6e,0x6e,0x6e,0x6f,0x6f,0x6f,0x70,0x70,0x70,
5156   0x71,0x71,0x71,0x72,0x72,0x72,0x73,0x73,0x73,0x74,0x74,0x74,0x75,0x75,0x75,0x76,0x76,0x76,0x77,0x77,0x77,0x78,0x78,0x78,
5157   0x79,0x79,0x79,0x7a,0x7a,0x7a,0x7b,0x7b,0x7b,0x7c,0x7c,0x7c,0x7d,0x7d,0x7d,0x7e,0x7e,0x7e,0x7f,0x7f,0x7f,0x80,0x80,0x80,
5158   0x76,0xb6,0x24,0x31,
5159   0x00,0x00,0x00,0x02,'t','R','N','S',0xff,0x00,0xe5,0xb7,0x30,0x4a,
5160   0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7,
5161   0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
5162 };
5163 
5164 #define PNG_COLOR_TYPE_GRAY 0
5165 #define PNG_COLOR_TYPE_RGB 2
5166 #define PNG_COLOR_TYPE_PALETTE 3
5167 #define PNG_COLOR_TYPE_GRAY_ALPHA 4
5168 #define PNG_COLOR_TYPE_RGB_ALPHA 6
5169 
5170 static void test_png_color_formats(void)
5171 {
5172     static const struct
5173     {
5174         char bit_depth, color_type;
5175         struct {
5176             PixelFormat format;
5177             ImageFlags flags;
5178             BOOL todo;
5179             BOOL todo_load;
5180         } t[3];
5181     } td[] =
5182     {
5183         /*  0 */
5184         { 1, PNG_COLOR_TYPE_RGB },
5185         { 2, PNG_COLOR_TYPE_RGB },
5186         { 4, PNG_COLOR_TYPE_RGB },
5187         { 8, PNG_COLOR_TYPE_RGB,
5188           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5189            { PixelFormat24bppRGB, ImageFlagsColorSpaceRGB },
5190            { PixelFormat24bppRGB, ImageFlagsColorSpaceRGB }}},
5191         /* libpng refuses to load our test image complaining about extra compressed data,
5192          * but libpng is still able to load the image with other combination of type/depth
5193          * making RGB 16 bpp case special for some reason. Therefore todo = TRUE.
5194          */
5195         { 16, PNG_COLOR_TYPE_RGB,
5196           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE },
5197            { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE },
5198            { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB, TRUE, TRUE }}},
5199 
5200         /*  5 */
5201         { 1, PNG_COLOR_TYPE_GRAY,
5202           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5203            { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB },
5204            { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB }}},
5205         { 2, PNG_COLOR_TYPE_GRAY,
5206           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5207            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5208            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5209         { 4, PNG_COLOR_TYPE_GRAY,
5210           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5211            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5212            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5213         { 8, PNG_COLOR_TYPE_GRAY,
5214           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5215            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5216            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5217         { 16, PNG_COLOR_TYPE_GRAY,
5218           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5219            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
5220            { PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY }}},
5221 
5222         /* 10 */
5223         { 1, PNG_COLOR_TYPE_PALETTE,
5224           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5225            { PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB },
5226            { 0, 0 }}},
5227         { 2, PNG_COLOR_TYPE_PALETTE,
5228           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5229            { PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5230            { 0, 0 }}},
5231         { 4, PNG_COLOR_TYPE_PALETTE,
5232           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5233            { PixelFormat4bppIndexed, ImageFlagsColorSpaceRGB },
5234            { 0, 0 }}},
5235         { 8, PNG_COLOR_TYPE_PALETTE,
5236           {{ PixelFormat32bppARGB, ImageFlagsColorSpaceRGB },
5237            { PixelFormat8bppIndexed, ImageFlagsColorSpaceRGB },
5238            { 0, 0 }}},
5239         { 16, PNG_COLOR_TYPE_PALETTE },
5240     };
5241     BYTE buf[sizeof(png_1x1_data)];
5242     GpStatus status;
5243     GpImage *image;
5244     ImageType type;
5245     PixelFormat format;
5246     ImageFlags flags;
5247     BOOL valid;
5248     int i, j, PLTE_off = 0, tRNS_off = 0;
5249     const ImageFlags color_space_mask = ImageFlagsColorSpaceRGB | ImageFlagsColorSpaceCMYK | ImageFlagsColorSpaceGRAY | ImageFlagsColorSpaceYCBCR | ImageFlagsColorSpaceYCCK;
5250 
5251     memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
5252     buf[24] = 2;
5253     buf[25] = PNG_COLOR_TYPE_PALETTE;
5254     image = load_image(buf, sizeof(buf), TRUE, FALSE);
5255     status = GdipGetImageFlags(image, &flags);
5256     expect(status, Ok);
5257     ok((flags & color_space_mask) == ImageFlagsColorSpaceRGB || broken(flags == 0x12006) /* before win7 */,
5258        "flags = %#x\n", flags);
5259     if ((flags & color_space_mask) != ImageFlagsColorSpaceRGB) {
5260         GdipDisposeImage(image);
5261         win_skip("broken PNG color space support\n");
5262         return;
5263     }
5264     GdipDisposeImage(image);
5265 
5266     for (i = 0; i < sizeof(png_1x1_data) - 4; i++)
5267     {
5268         if (!memcmp(buf + i, "tRNS", 4))
5269             tRNS_off = i;
5270         else if (!memcmp(buf + i, "PLTE", 4))
5271             PLTE_off = i;
5272     }
5273 
5274     ok(PLTE_off && tRNS_off, "PLTE offset %d, tRNS offset %d\n", PLTE_off, tRNS_off);
5275     if (!PLTE_off || !tRNS_off) return;
5276 
5277     /* In order to test the image data with and without PLTE and tRNS
5278      * chunks, we mask the chunk name with private one (tEST).
5279      */
5280 
5281     for (i = 0; i < ARRAY_SIZE(td); i++)
5282     {
5283         for (j = 0; j < 3; j++)
5284         {
5285             memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
5286             buf[24] = td[i].bit_depth;
5287             buf[25] = td[i].color_type;
5288             if (j >=1) memcpy(buf + tRNS_off, "tEST", 4);
5289             if (j >=2) memcpy(buf + PLTE_off, "tEST", 4);
5290 
5291             valid = (td[i].t[j].format != 0) || (td[i].t[j].flags != 0);
5292             image = load_image(buf, sizeof(buf), valid, td[i].t[j].todo_load);
5293             todo_wine_if(td[i].t[j].todo_load)
5294             if (valid)
5295                 ok(image != NULL, "%d %d: failed to load image data\n", i, j);
5296             else
5297             {
5298                 ok(image == NULL, "%d %d: succeed to load image data\n", i, j);
5299                 if (image) GdipDisposeImage(image);
5300                 image = NULL;
5301             }
5302             if (!image) continue;
5303 
5304             status = GdipGetImageType(image, &type);
5305             ok(status == Ok, "%d %d: GdipGetImageType error %d\n", i, j, status);
5306             ok(type == ImageTypeBitmap, "%d %d: wrong image type %d\n", i, j, type);
5307 
5308             status = GdipGetImagePixelFormat(image, &format);
5309             expect(Ok, status);
5310             todo_wine_if(td[i].t[j].todo)
5311             ok(format == td[i].t[j].format,
5312                "%d %d: expected %#x, got %#x\n", i, j, td[i].t[j].format, format);
5313 
5314             status = GdipGetImageFlags(image, &flags);
5315             expect(Ok, status);
5316             ok((flags & color_space_mask) == td[i].t[j].flags,
5317                "%d %d: expected %#x, got %#x\n", i, j, td[i].t[j].flags, flags);
5318             GdipDisposeImage(image);
5319         }
5320     }
5321 }
5322 #undef PNG_COLOR_TYPE_GRAY
5323 #undef PNG_COLOR_TYPE_RGB
5324 #undef PNG_COLOR_TYPE_PALETTE
5325 #undef PNG_COLOR_TYPE_GRAY_ALPHA
5326 #undef PNG_COLOR_TYPE_RGB_ALPHA
5327 
5328 static void test_GdipLoadImageFromStream(void)
5329 {
5330     IStream *stream;
5331     GpStatus status;
5332     GpImage *image;
5333     HGLOBAL hglob;
5334     BYTE *data;
5335     HRESULT hr;
5336 
5337     status = GdipLoadImageFromStream(NULL, NULL);
5338     ok(status == InvalidParameter, "Unexpected return value %d.\n", status);
5339 
5340     image = (void *)0xdeadbeef;
5341     status = GdipLoadImageFromStream(NULL, &image);
5342     ok(status == InvalidParameter, "Unexpected return value %d.\n", status);
5343     ok(image == (void *)0xdeadbeef, "Unexpected image pointer.\n");
5344 
5345     hglob = GlobalAlloc(0, sizeof(pngimage));
5346     data = GlobalLock (hglob);
5347     memcpy(data, pngimage, sizeof(pngimage));
5348     GlobalUnlock(hglob);
5349 
5350     hr = CreateStreamOnHGlobal(hglob, TRUE, &stream);
5351     ok(hr == S_OK, "Failed to create a stream.\n");
5352 
5353     status = GdipLoadImageFromStream(stream, NULL);
5354     ok(status == InvalidParameter, "Unexpected return value %d.\n", status);
5355 
5356     IStream_Release(stream);
5357 }
5358 
5359 static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride)
5360 {
5361     BYTE *src;
5362     UINT i, j, scale;
5363 
5364     *width = 256;
5365     *height = 256;
5366     *stride = (*width * 3 + 3) & ~3;
5367     trace("width %d, height %d, stride %d\n", *width, *height, *stride);
5368 
5369     src = HeapAlloc(GetProcessHeap(), 0, *stride * *height);
5370 
5371     scale = 256 / *width;
5372     if (!scale) scale = 1;
5373 
5374     for (i = 0; i < *height; i++)
5375     {
5376         for (j = 0; j < *width; j++)
5377         {
5378             src[i * *stride + j*3 + 0] = scale * i;
5379             src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2);
5380             src[i * *stride + j*3 + 2] = scale * j;
5381         }
5382     }
5383 
5384     return src;
5385 }
5386 
5387 static void test_GdipInitializePalette(void)
5388 {
5389     GpStatus status;
5390     BYTE *data;
5391     GpBitmap *bitmap;
5392     ColorPalette *palette;
5393     UINT width, height, stride;
5394 
5395     pGdipInitializePalette = (void *)GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipInitializePalette");
5396     if (!pGdipInitializePalette)
5397     {
5398         win_skip("GdipInitializePalette is not supported on this platform\n");
5399         return;
5400     }
5401 
5402     data = init_bitmap(&width, &height, &stride);
5403 
5404     status = GdipCreateBitmapFromScan0(width, height, stride, PixelFormat24bppRGB, data, &bitmap);
5405     expect(Ok, status);
5406 
5407     palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 255);
5408 
5409     palette->Flags = 0;
5410     palette->Count = 15;
5411     status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap);
5412     expect(GenericError, status);
5413 
5414     palette->Flags = 0;
5415     palette->Count = 256;
5416     status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, NULL);
5417     expect(InvalidParameter, status);
5418 
5419     memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5420     palette->Flags = 0;
5421     palette->Count = 256;
5422     status = pGdipInitializePalette(palette, PaletteTypeCustom, 16, FALSE, NULL);
5423     expect(Ok, status);
5424     expect(0, palette->Flags);
5425     expect(256, palette->Count);
5426     expect(0x11111111, palette->Entries[0]);
5427     expect(0x11111111, palette->Entries[128]);
5428     expect(0x11111111, palette->Entries[255]);
5429 
5430     memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5431     palette->Flags = 0;
5432     palette->Count = 256;
5433     status = pGdipInitializePalette(palette, PaletteTypeFixedBW, 0, FALSE, bitmap);
5434     expect(Ok, status);
5435 todo_wine
5436     expect(0x200, palette->Flags);
5437     expect(2, palette->Count);
5438     expect(0xff000000, palette->Entries[0]);
5439     expect(0xffffffff, palette->Entries[1]);
5440 
5441     memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5442     palette->Flags = 0;
5443     palette->Count = 256;
5444     status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, NULL);
5445     expect(Ok, status);
5446 todo_wine
5447     expect(0x300, palette->Flags);
5448     expect(16, palette->Count);
5449     expect(0xff000000, palette->Entries[0]);
5450     expect(0xffc0c0c0, palette->Entries[8]);
5451     expect(0xff008080, palette->Entries[15]);
5452 
5453     memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5454     palette->Flags = 0;
5455     palette->Count = 256;
5456     status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, bitmap);
5457     expect(Ok, status);
5458 todo_wine
5459     expect(0x300, palette->Flags);
5460     expect(16, palette->Count);
5461     expect(0xff000000, palette->Entries[0]);
5462     expect(0xffc0c0c0, palette->Entries[8]);
5463     expect(0xff008080, palette->Entries[15]);
5464 
5465     memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5466     palette->Flags = 0;
5467     palette->Count = 256;
5468     status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone252, 1, FALSE, bitmap);
5469     expect(Ok, status);
5470 todo_wine
5471     expect(0x800, palette->Flags);
5472     expect(252, palette->Count);
5473     expect(0xff000000, palette->Entries[0]);
5474     expect(0xff990066, palette->Entries[128]);
5475     expect(0xffffffff, palette->Entries[251]);
5476 
5477     palette->Flags = 0;
5478     palette->Count = 256;
5479     status = pGdipInitializePalette(palette, PaletteTypeOptimal, 1, FALSE, bitmap);
5480     expect(InvalidParameter, status);
5481 
5482     palette->Flags = 0;
5483     palette->Count = 256;
5484     status = pGdipInitializePalette(palette, PaletteTypeOptimal, 2, FALSE, bitmap);
5485     expect(Ok, status);
5486     expect(0, palette->Flags);
5487     expect(2, palette->Count);
5488 
5489     palette->Flags = 0;
5490     palette->Count = 256;
5491     status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap);
5492     expect(Ok, status);
5493     expect(0, palette->Flags);
5494     expect(16, palette->Count);
5495 
5496     /* passing invalid enumeration palette type crashes under most Windows versions */
5497 
5498     GdipFree(palette);
5499     GdipDisposeImage((GpImage *)bitmap);
5500 }
5501 
5502 #include "pshpack2.h"
5503 static const struct tiff_1x1_data
5504 {
5505     USHORT byte_order;
5506     USHORT version;
5507     ULONG  dir_offset;
5508     USHORT number_of_entries;
5509     struct IFD_entry entry[12];
5510     ULONG next_IFD;
5511     struct IFD_rational res;
5512     short palette_data[3][256];
5513     short bps_data[4];
5514     BYTE pixel_data[32];
5515 } tiff_1x1_data =
5516 {
5517 #ifdef WORDS_BIGENDIAN
5518     'M' | 'M' << 8,
5519 #else
5520     'I' | 'I' << 8,
5521 #endif
5522     42,
5523     FIELD_OFFSET(struct tiff_1x1_data, number_of_entries),
5524     12,
5525     {
5526         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
5527         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
5528         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
5529         { 0x102, IFD_SHORT, 3, FIELD_OFFSET(struct tiff_1x1_data, bps_data) }, /* BITSPERSAMPLE */
5530         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
5531         { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
5532         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1x1_data, pixel_data) }, /* STRIPOFFSETS */
5533         { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */
5534         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) },
5535         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) },
5536         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
5537         { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_1x1_data, palette_data) } /* COLORMAP */
5538     },
5539     0,
5540     { 96, 1 },
5541     { { 0 } },
5542     { 8,8,8,0 },
5543     { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 }
5544 };
5545 #include "poppack.h"
5546 
5547 static void test_tiff_color_formats(void)
5548 {
5549     static const struct
5550     {
5551         int photometric; /* PhotometricInterpretation */
5552         int samples; /* SamplesPerPixel */
5553         int bps; /* BitsPerSample */
5554         PixelFormat format;
5555     } td[] =
5556     {
5557         /* 2 - RGB */
5558         { 2, 3, 1, PixelFormat24bppRGB },
5559         { 2, 3, 4, PixelFormat24bppRGB },
5560         { 2, 3, 8, PixelFormat24bppRGB },
5561         { 2, 3, 16, PixelFormat48bppRGB },
5562         { 2, 3, 24, 0 },
5563 #if 0 /* FIXME */
5564         { 2, 3, 32, 0 },
5565 #endif
5566         { 2, 4, 1, PixelFormat32bppARGB },
5567         { 2, 4, 4, PixelFormat32bppARGB },
5568         { 2, 4, 8, PixelFormat32bppARGB },
5569         { 2, 4, 16, PixelFormat48bppRGB },
5570         { 2, 4, 24, 0 },
5571         { 2, 4, 32, 0 },
5572         /* 1 - BlackIsZero (Bilevel) */
5573         { 1, 1, 1, PixelFormat1bppIndexed },
5574 #if 0 /* FIXME: PNG vs TIFF mismatch */
5575         { 1, 1, 4, PixelFormat8bppIndexed },
5576 #endif
5577         { 1, 1, 8, PixelFormat8bppIndexed },
5578         { 1, 1, 16, PixelFormat32bppARGB },
5579         { 1, 1, 24, 0 },
5580         { 1, 1, 32, PixelFormat32bppARGB },
5581         /* 3 - Palette Color */
5582         { 3, 1, 1, PixelFormat1bppIndexed },
5583         { 3, 1, 4, PixelFormat4bppIndexed },
5584         { 3, 1, 8, PixelFormat8bppIndexed },
5585 #if 0 /* FIXME: for some reason libtiff replaces photometric 3 by 1 for bps > 8 */
5586         { 3, 1, 16, 0 },
5587         { 3, 1, 24, 0 },
5588         { 3, 1, 32, 0 },
5589 #endif
5590         /* 5 - Separated */
5591         { 5, 4, 1, 0 },
5592         { 5, 4, 4, 0 },
5593         { 5, 4, 8, PixelFormat32bppCMYK },
5594         { 5, 4, 16, PixelFormat48bppRGB },
5595         { 5, 4, 24, 0 },
5596         { 5, 4, 32, 0 },
5597     };
5598     BYTE buf[sizeof(tiff_1x1_data)];
5599     GpStatus status;
5600     GpImage *image;
5601     UINT count, i;
5602     struct IFD_entry *tag, *tag_photo = NULL, *tag_bps = NULL, *tag_samples = NULL, *tag_colormap = NULL;
5603     short *bps;
5604     ImageType type;
5605     PixelFormat format;
5606 
5607     memcpy(buf, &tiff_1x1_data, sizeof(tiff_1x1_data));
5608 
5609     count = *(short *)(buf + tiff_1x1_data.dir_offset);
5610     tag = (struct IFD_entry *)(buf + tiff_1x1_data.dir_offset + sizeof(short));
5611 
5612     /* verify the TIFF structure */
5613     for (i = 0; i < count; i++)
5614     {
5615         if (tag[i].id == 0x102) /* BitsPerSample */
5616             tag_bps = &tag[i];
5617         else if (tag[i].id == 0x106) /* PhotometricInterpretation */
5618             tag_photo = &tag[i];
5619         else if (tag[i].id == 0x115) /* SamplesPerPixel */
5620             tag_samples = &tag[i];
5621         else if (tag[i].id == 0x140) /* ColorMap */
5622             tag_colormap = &tag[i];
5623     }
5624 
5625     ok(tag_bps && tag_photo && tag_samples && tag_colormap, "tag 0x102,0x106,0x115 or 0x140 is missing\n");
5626     if (!tag_bps || !tag_photo || !tag_samples || !tag_colormap) return;
5627 
5628     ok(tag_bps->type == IFD_SHORT, "tag 0x102 should have type IFD_SHORT\n");
5629     bps = (short *)(buf + tag_bps->value);
5630     ok(bps[0] == 8 && bps[1] == 8 && bps[2] == 8 && bps[3] == 0,
5631        "expected bps 8,8,8,0 got %d,%d,%d,%d\n", bps[0], bps[1], bps[2], bps[3]);
5632 
5633     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
5634     {
5635         tag_colormap->count = (1 << td[i].bps) * 3;
5636         tag_photo->value = td[i].photometric;
5637         tag_bps->count = td[i].samples;
5638         tag_samples->value = td[i].samples;
5639 
5640         if (td[i].samples == 1)
5641             tag_bps->value = td[i].bps;
5642         else if (td[i].samples == 2)
5643             tag_bps->value = MAKELONG(td[i].bps, td[i].bps);
5644         else if (td[i].samples == 3)
5645         {
5646             tag_bps->value = (BYTE *)bps - buf;
5647             bps[0] = bps[1] = bps[2] = td[i].bps;
5648         }
5649         else if (td[i].samples == 4)
5650         {
5651             tag_bps->value = (BYTE *)bps - buf;
5652             bps[0] = bps[1] = bps[2] = bps[3] = td[i].bps;
5653         }
5654         else
5655         {
5656             ok(0, "%u: unsupported samples count %d\n", i, td[i].samples);
5657             continue;
5658         }
5659 
5660         image = load_image(buf, sizeof(buf), TRUE, FALSE);
5661         if (!td[i].format)
5662 #ifdef __REACTOS__
5663             ok(!image || (((GetVersion() & 0xFF) < 6) &&
5664                (i == 19 || i == 20)),
5665 #else
5666             ok(!image,
5667 #endif
5668                "%u: (%d,%d,%d) TIFF image loading should have failed\n", i, td[i].photometric, td[i].samples, td[i].bps);
5669         else
5670             ok(image != NULL || broken(!image) /* XP */, "%u: failed to load TIFF image data (%d,%d,%d)\n",
5671                i, td[i].photometric, td[i].samples, td[i].bps);
5672         if (!image) continue;
5673 
5674         status = GdipGetImageType(image, &type);
5675         ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
5676         ok(type == ImageTypeBitmap, "%u: wrong image type %d\n", i, type);
5677 
5678         status = GdipGetImagePixelFormat(image, &format);
5679         expect(Ok, status);
5680 #ifdef __REACTOS__
5681         ok(format == td[i].format || (((GetVersion() & 0xFF) < 6) &&
5682            ((i == 0 && format == 0) ||
5683             (i == 1 && format == 0) ||
5684             (i == 5 && format == 0) ||
5685             (i == 6 && format == 0) ||
5686             (i == 13 && format == 0) ||
5687             (i == 19 && format == PixelFormat32bppARGB) ||
5688             (i == 20 && format == PixelFormat32bppARGB) ||
5689             (i == 21 && format == PixelFormat32bppARGB) ||
5690             (i == 22 && format == PixelFormat32bppARGB))),
5691 #else
5692         ok(format == td[i].format,
5693 #endif
5694            "%u: expected %#x, got %#x\n", i, td[i].format, format);
5695 
5696         GdipDisposeImage(image);
5697     }
5698 }
5699 
5700 START_TEST(image)
5701 {
5702     HMODULE mod = GetModuleHandleA("gdiplus.dll");
5703     struct GdiplusStartupInput gdiplusStartupInput;
5704     ULONG_PTR gdiplusToken;
5705     HMODULE hmsvcrt;
5706     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
5707 
5708     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
5709     hmsvcrt = LoadLibraryA("msvcrt");
5710     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
5711     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
5712 
5713     gdiplusStartupInput.GdiplusVersion              = 1;
5714     gdiplusStartupInput.DebugEventCallback          = NULL;
5715     gdiplusStartupInput.SuppressBackgroundThread    = 0;
5716     gdiplusStartupInput.SuppressExternalCodecs      = 0;
5717 
5718     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
5719 
5720     pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize");
5721     pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram");
5722     pGdipImageSetAbort = (void*)GetProcAddress(mod, "GdipImageSetAbort");
5723 
5724     test_tiff_color_formats();
5725     test_GdipInitializePalette();
5726     test_png_color_formats();
5727     test_supported_encoders();
5728     test_CloneBitmapArea();
5729     test_ARGB_conversion();
5730     test_DrawImage_scale();
5731     test_image_format();
5732     test_DrawImage();
5733     test_DrawImage_SourceCopy();
5734     test_GdipDrawImagePointRect();
5735     test_bitmapbits();
5736     test_tiff_palette();
5737     test_GdipGetAllPropertyItems();
5738     test_tiff_properties();
5739     test_gif_properties();
5740     test_image_properties();
5741     test_Scan0();
5742     test_FromGdiDib();
5743     test_GetImageDimension();
5744     test_GdipImageGetFrameDimensionsCount();
5745     test_LoadingImages();
5746     test_SavingImages();
5747     test_encoders();
5748     test_LockBits();
5749     test_LockBits_UserBuf();
5750     test_GdipCreateBitmapFromHBITMAP();
5751     test_GdipGetImageFlags();
5752     test_GdipCloneImage();
5753     test_testcontrol();
5754     test_fromhicon();
5755     test_getrawformat();
5756     test_loadwmf();
5757     test_createfromwmf();
5758     test_createfromwmf_noplaceable();
5759     test_resolution();
5760     test_createhbitmap();
5761     test_getthumbnail();
5762     test_getsetpixel();
5763     test_palette();
5764     test_colormatrix();
5765     test_gamma();
5766     test_multiframegif();
5767     test_rotateflip();
5768     test_remaptable();
5769     test_colorkey();
5770     test_dispose();
5771     test_createeffect();
5772     test_getadjustedpalette();
5773     test_histogram();
5774     test_imageabort();
5775     test_GdipLoadImageFromStream();
5776 
5777     GdiplusShutdown(gdiplusToken);
5778 }
5779