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