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