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