gdiplus: Test also lf.lfEscapement and lf.lfOrientation returned by GdipGetLogFont.
[wine] / dlls / gdiplus / tests / image.c
1 /*
2  * Unit test suite for images
3  *
4  * Copyright (C) 2007 Google (Evan Stade)
5  * Copyright (C) 2012 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define COBJMACROS
23
24 #include <math.h>
25 #include <assert.h>
26 #include <stdio.h>
27
28 #include "initguid.h"
29 #include "windows.h"
30 #include "gdiplus.h"
31 #include "wine/test.h"
32
33 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
34 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
35
36 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
37 {
38     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
39     c1 >>= 8; c2 >>= 8;
40     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
41     c1 >>= 8; c2 >>= 8;
42     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
43     c1 >>= 8; c2 >>= 8;
44     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45     return TRUE;
46 }
47
48 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
49 {
50     WCHAR bufferW[39];
51     char buffer[39];
52     char buffer2[39];
53
54     StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
55     WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
56     StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
57     WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
58     if(todo)
59         todo_wine ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
60     else
61         ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
62 }
63
64 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
65 {
66     GUID raw;
67     GpStatus stat;
68
69     stat = GdipGetImageRawFormat(img, &raw);
70     ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
71     if(stat != Ok) return;
72     expect_guid(expected, &raw, line, todo);
73 }
74
75 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
76 {
77     LPSTREAM stream;
78     HGLOBAL  hglob;
79     LPBYTE   data;
80     HRESULT  hres;
81     GpStatus stat;
82     GpImage *img;
83
84     hglob = GlobalAlloc (0, size);
85     data = GlobalLock (hglob);
86     memcpy(data, buff, size);
87     GlobalUnlock(hglob); data = NULL;
88
89     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
90     ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
91     if(hres != S_OK) return;
92
93     stat = GdipLoadImageFromStream(stream, &img);
94     ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
95     if(stat != Ok){
96         IStream_Release(stream);
97         return;
98     }
99
100     expect_rawformat(expected, img, line, todo);
101
102     GdipDisposeImage(img);
103     IStream_Release(stream);
104 }
105
106 static void test_Scan0(void)
107 {
108     GpBitmap *bm;
109     GpStatus stat;
110     BYTE buff[360];
111
112     bm = NULL;
113     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
114     expect(Ok, stat);
115     ok(NULL != bm, "Expected bitmap to be initialized\n");
116     if (stat == Ok)
117         GdipDisposeImage((GpImage*)bm);
118
119     bm = (GpBitmap*)0xdeadbeef;
120     stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
121     expect(InvalidParameter, stat);
122     ok( !bm, "expected null bitmap\n" );
123
124     bm = (GpBitmap*)0xdeadbeef;
125     stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
126     expect(InvalidParameter, stat);
127     ok( !bm, "expected null bitmap\n" );
128
129     bm = (GpBitmap*)0xdeadbeef;
130     stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
131     expect(InvalidParameter, stat);
132     ok( !bm, "expected null bitmap\n" );
133
134     bm = NULL;
135     stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
136     expect(Ok, stat);
137     ok(NULL != bm, "Expected bitmap to be initialized\n");
138     if (stat == Ok)
139         GdipDisposeImage((GpImage*)bm);
140
141     bm = (GpBitmap*) 0xdeadbeef;
142     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
143     expect(InvalidParameter, stat);
144     ok( !bm, "expected null bitmap\n" );
145
146     bm = (GpBitmap*)0xdeadbeef;
147     stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
148     expect(InvalidParameter, stat);
149     ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
150
151     bm = NULL;
152     stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
153     expect(Ok, stat);
154     ok(NULL != bm, "Expected bitmap to be initialized\n");
155     if (stat == Ok)
156         GdipDisposeImage((GpImage*)bm);
157
158     bm = (GpBitmap*)0xdeadbeef;
159     stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
160     expect(InvalidParameter, stat);
161     ok( !bm, "expected null bitmap\n" );
162 }
163
164 static void test_FromGdiDib(void)
165 {
166     GpBitmap *bm;
167     GpStatus stat;
168     BYTE buff[400];
169     BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
170     BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
171     PixelFormat format;
172
173     bm = NULL;
174
175     memset(rbmi, 0, sizeof(rbmi));
176
177     bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
178     bmi->bmiHeader.biWidth = 10;
179     bmi->bmiHeader.biHeight = 10;
180     bmi->bmiHeader.biPlanes = 1;
181     bmi->bmiHeader.biBitCount = 32;
182     bmi->bmiHeader.biCompression = BI_RGB;
183
184     stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
185     expect(InvalidParameter, stat);
186
187     stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
188     expect(InvalidParameter, stat);
189
190     stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
191     expect(InvalidParameter, stat);
192
193     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
194     expect(Ok, stat);
195     ok(NULL != bm, "Expected bitmap to be initialized\n");
196     if (stat == Ok)
197     {
198         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
199         expect(Ok, stat);
200         expect(PixelFormat32bppRGB, format);
201
202         GdipDisposeImage((GpImage*)bm);
203     }
204
205     bmi->bmiHeader.biBitCount = 24;
206     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
207     expect(Ok, stat);
208     ok(NULL != bm, "Expected bitmap to be initialized\n");
209     if (stat == Ok)
210     {
211         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
212         expect(Ok, stat);
213         expect(PixelFormat24bppRGB, format);
214
215         GdipDisposeImage((GpImage*)bm);
216     }
217
218     bmi->bmiHeader.biBitCount = 16;
219     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
220     expect(Ok, stat);
221     ok(NULL != bm, "Expected bitmap to be initialized\n");
222     if (stat == Ok)
223     {
224         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
225         expect(Ok, stat);
226         expect(PixelFormat16bppRGB555, format);
227
228         GdipDisposeImage((GpImage*)bm);
229     }
230
231     bmi->bmiHeader.biBitCount = 8;
232     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
233     expect(Ok, stat);
234     ok(NULL != bm, "Expected bitmap to be initialized\n");
235     if (stat == Ok)
236     {
237         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
238         expect(Ok, stat);
239         expect(PixelFormat8bppIndexed, format);
240
241         GdipDisposeImage((GpImage*)bm);
242     }
243
244     bmi->bmiHeader.biBitCount = 4;
245     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
246     expect(Ok, stat);
247     ok(NULL != bm, "Expected bitmap to be initialized\n");
248     if (stat == Ok)
249     {
250         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
251         expect(Ok, stat);
252         expect(PixelFormat4bppIndexed, format);
253
254         GdipDisposeImage((GpImage*)bm);
255     }
256
257     bmi->bmiHeader.biBitCount = 1;
258     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
259     expect(Ok, stat);
260     ok(NULL != bm, "Expected bitmap to be initialized\n");
261     if (stat == Ok)
262     {
263         stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
264         expect(Ok, stat);
265         expect(PixelFormat1bppIndexed, format);
266
267         GdipDisposeImage((GpImage*)bm);
268     }
269
270     bmi->bmiHeader.biBitCount = 0;
271     stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
272     expect(InvalidParameter, stat);
273 }
274
275 static void test_GetImageDimension(void)
276 {
277     GpBitmap *bm;
278     GpStatus stat;
279     const REAL WIDTH = 10.0, HEIGHT = 20.0;
280     REAL w,h;
281
282     bm = (GpBitmap*)0xdeadbeef;
283     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
284     expect(Ok,stat);
285     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
286     ok(NULL != bm, "Expected bitmap to not be NULL\n");
287
288     stat = GdipGetImageDimension(NULL,&w,&h);
289     expect(InvalidParameter, stat);
290
291     stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
292     expect(InvalidParameter, stat);
293
294     stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
295     expect(InvalidParameter, stat);
296
297     w = -1;
298     h = -1;
299     stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
300     expect(Ok, stat);
301     expectf(WIDTH,  w);
302     expectf(HEIGHT, h);
303     GdipDisposeImage((GpImage*)bm);
304 }
305
306 static void test_GdipImageGetFrameDimensionsCount(void)
307 {
308     GpBitmap *bm;
309     GpStatus stat;
310     const REAL WIDTH = 10.0, HEIGHT = 20.0;
311     UINT w;
312     GUID dimension = {0};
313     UINT count;
314     ARGB color;
315
316     bm = (GpBitmap*)0xdeadbeef;
317     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
318     expect(Ok,stat);
319     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
320     ok(NULL != bm, "Expected bitmap to not be NULL\n");
321
322     stat = GdipImageGetFrameDimensionsCount(NULL,&w);
323     expect(InvalidParameter, stat);
324
325     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
326     expect(InvalidParameter, stat);
327
328     w = -1;
329     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
330     expect(Ok, stat);
331     expect(1, w);
332
333     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
334     expect(Ok, stat);
335     expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
336
337     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
338     expect(InvalidParameter, stat);
339
340     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
341     expect(InvalidParameter, stat);
342
343     stat = GdipImageGetFrameCount(NULL, &dimension, &count);
344     expect(InvalidParameter, stat);
345
346     /* WinXP crashes on this test */
347     if(0)
348     {
349         stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
350         expect(InvalidParameter, stat);
351     }
352
353     stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
354     expect(Ok, stat);
355
356     count = 12345;
357     stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
358     expect(Ok, stat);
359     expect(1, count);
360
361     GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
362
363     stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
364     expect(Ok, stat);
365
366     /* SelectActiveFrame has no effect on image data of memory bitmaps */
367     color = 0xdeadbeef;
368     GdipBitmapGetPixel(bm, 0, 0, &color);
369     expect(0xffffffff, color);
370
371     GdipDisposeImage((GpImage*)bm);
372 }
373
374 static void test_LoadingImages(void)
375 {
376     GpStatus stat;
377
378     stat = GdipCreateBitmapFromFile(0, 0);
379     expect(InvalidParameter, stat);
380
381     stat = GdipCreateBitmapFromFile(0, (GpBitmap**)0xdeadbeef);
382     expect(InvalidParameter, stat);
383
384     stat = GdipLoadImageFromFile(0, 0);
385     expect(InvalidParameter, stat);
386
387     stat = GdipLoadImageFromFile(0, (GpImage**)0xdeadbeef);
388     expect(InvalidParameter, stat);
389
390     stat = GdipLoadImageFromFileICM(0, 0);
391     expect(InvalidParameter, stat);
392
393     stat = GdipLoadImageFromFileICM(0, (GpImage**)0xdeadbeef);
394     expect(InvalidParameter, stat);
395 }
396
397 static void test_SavingImages(void)
398 {
399     GpStatus stat;
400     GpBitmap *bm;
401     UINT n;
402     UINT s;
403     const REAL WIDTH = 10.0, HEIGHT = 20.0;
404     REAL w, h;
405     ImageCodecInfo *codecs;
406     static const CHAR filenameA[] = "a.bmp";
407     static const WCHAR filename[] = { 'a','.','b','m','p',0 };
408
409     codecs = NULL;
410
411     stat = GdipSaveImageToFile(0, 0, 0, 0);
412     expect(InvalidParameter, stat);
413
414     bm = NULL;
415     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
416     expect(Ok, stat);
417     if (!bm)
418         return;
419
420     /* invalid params */
421     stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
422     expect(InvalidParameter, stat);
423
424     stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
425     expect(InvalidParameter, stat);
426
427     /* encoder tests should succeed -- already tested */
428     stat = GdipGetImageEncodersSize(&n, &s);
429     if (stat != Ok || n == 0) goto cleanup;
430
431     codecs = GdipAlloc(s);
432     if (!codecs) goto cleanup;
433
434     stat = GdipGetImageEncoders(n, s, codecs);
435     if (stat != Ok) goto cleanup;
436
437     stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
438     expect(Ok, stat);
439
440     GdipDisposeImage((GpImage*)bm);
441     bm = 0;
442
443     /* re-load and check image stats */
444     stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
445     expect(Ok, stat);
446     if (stat != Ok) goto cleanup;
447
448     stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
449     if (stat != Ok) goto cleanup;
450
451     expectf(WIDTH, w);
452     expectf(HEIGHT, h);
453
454  cleanup:
455     GdipFree(codecs);
456     if (bm)
457         GdipDisposeImage((GpImage*)bm);
458     ok(DeleteFileA(filenameA), "Delete failed.\n");
459 }
460
461 static void test_encoders(void)
462 {
463     GpStatus stat;
464     UINT n;
465     UINT s;
466     ImageCodecInfo *codecs;
467     int i;
468     int bmp_found;
469
470     static const CHAR bmp_format[] = "BMP";
471
472     stat = GdipGetImageEncodersSize(&n, &s);
473     expect(stat, Ok);
474
475     codecs = GdipAlloc(s);
476     if (!codecs)
477         return;
478
479     stat = GdipGetImageEncoders(n, s, NULL);
480     expect(GenericError, stat);
481
482     stat = GdipGetImageEncoders(0, s, codecs);
483     expect(GenericError, stat);
484
485     stat = GdipGetImageEncoders(n, s-1, codecs);
486     expect(GenericError, stat);
487
488     stat = GdipGetImageEncoders(n, s+1, codecs);
489     expect(GenericError, stat);
490
491     stat = GdipGetImageEncoders(n, s, codecs);
492     expect(stat, Ok);
493
494     bmp_found = FALSE;
495     for (i = 0; i < n; i++)
496         {
497             CHAR desc[32];
498
499             WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
500                                 desc, 32, 0, 0);
501
502             if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
503                                desc, -1,
504                                bmp_format, -1) == CSTR_EQUAL) {
505                 bmp_found = TRUE;
506                 break;
507             }
508         }
509     if (!bmp_found)
510         ok(FALSE, "No BMP codec found.\n");
511
512     GdipFree(codecs);
513 }
514
515 static void test_LockBits(void)
516 {
517     GpStatus stat;
518     GpBitmap *bm;
519     GpRect rect;
520     BitmapData bd;
521     const INT WIDTH = 10, HEIGHT = 20;
522     ARGB color;
523     int y;
524
525     bm = NULL;
526     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
527     expect(Ok, stat);
528
529     rect.X = 2;
530     rect.Y = 3;
531     rect.Width = 4;
532     rect.Height = 5;
533
534     stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
535     expect(Ok, stat);
536
537     stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
538     expect(Ok, stat);
539
540     /* read-only */
541     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
542     expect(Ok, stat);
543
544     if (stat == Ok) {
545         expect(0xc3, ((BYTE*)bd.Scan0)[2]);
546         expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
547
548         ((char*)bd.Scan0)[2] = 0xff;
549
550         stat = GdipBitmapUnlockBits(bm, &bd);
551         expect(Ok, stat);
552     }
553
554     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
555     expect(Ok, stat);
556     expect(0xffff0000, color);
557
558     stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
559     expect(Ok, stat);
560
561     /* read-only, with NULL rect -> whole bitmap lock */
562     stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
563     expect(Ok, stat);
564     expect(bd.Width,  WIDTH);
565     expect(bd.Height, HEIGHT);
566
567     if (stat == Ok) {
568         ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
569
570         stat = GdipBitmapUnlockBits(bm, &bd);
571         expect(Ok, stat);
572     }
573
574     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
575     expect(Ok, stat);
576     expect(0xffff0000, color);
577
578     /* read-only, consecutive */
579     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
580     expect(Ok, stat);
581
582     if (stat == Ok) {
583         stat = GdipBitmapUnlockBits(bm, &bd);
584         expect(Ok, stat);
585     }
586
587     stat = GdipDisposeImage((GpImage*)bm);
588     expect(Ok, stat);
589     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
590     expect(Ok, stat);
591
592     /* read x2 */
593     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
594     expect(Ok, stat);
595     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
596     expect(WrongState, stat);
597
598     stat = GdipBitmapUnlockBits(bm, &bd);
599     expect(Ok, stat);
600
601     stat = GdipDisposeImage((GpImage*)bm);
602     expect(Ok, stat);
603     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
604     expect(Ok, stat);
605
606     stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
607     expect(Ok, stat);
608
609     stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
610     expect(Ok, stat);
611
612     /* write, no conversion */
613     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
614     expect(Ok, stat);
615
616     if (stat == Ok) {
617         /* all bits are readable, inside the rect or not */
618         expect(0xff, ((BYTE*)bd.Scan0)[2]);
619         expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
620
621         stat = GdipBitmapUnlockBits(bm, &bd);
622         expect(Ok, stat);
623     }
624
625     /* read, conversion */
626     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
627     expect(Ok, stat);
628
629     if (stat == Ok) {
630         expect(0xff, ((BYTE*)bd.Scan0)[2]);
631         if (0)
632             /* Areas outside the rectangle appear to be uninitialized */
633             ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
634
635         ((BYTE*)bd.Scan0)[2] = 0xc3;
636
637         stat = GdipBitmapUnlockBits(bm, &bd);
638         expect(Ok, stat);
639     }
640
641     /* writes do not work in read mode if there was a conversion */
642     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
643     expect(Ok, stat);
644     expect(0xffff0000, color);
645
646     /* read/write, conversion */
647     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
648     expect(Ok, stat);
649
650     if (stat == Ok) {
651         expect(0xff, ((BYTE*)bd.Scan0)[2]);
652         ((BYTE*)bd.Scan0)[1] = 0x88;
653         if (0)
654             /* Areas outside the rectangle appear to be uninitialized */
655             ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
656
657         stat = GdipBitmapUnlockBits(bm, &bd);
658         expect(Ok, stat);
659     }
660
661     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
662     expect(Ok, stat);
663     expect(0xffff8800, color);
664
665     /* write, conversion */
666     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
667     expect(Ok, stat);
668
669     if (stat == Ok) {
670         if (0)
671         {
672             /* This is completely uninitialized. */
673             ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
674             ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
675         }
676
677         /* Initialize the buffer so the unlock doesn't access undefined memory */
678         for (y=0; y<5; y++)
679             memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
680
681         ((BYTE*)bd.Scan0)[0] = 0x12;
682         ((BYTE*)bd.Scan0)[1] = 0x34;
683         ((BYTE*)bd.Scan0)[2] = 0x56;
684
685         stat = GdipBitmapUnlockBits(bm, &bd);
686         expect(Ok, stat);
687     }
688
689     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
690     expect(Ok, stat);
691     expect(0xff563412, color);
692
693     stat = GdipBitmapGetPixel(bm, 2, 8, &color);
694     expect(Ok, stat);
695     expect(0xffc30000, color);
696
697     stat = GdipDisposeImage((GpImage*)bm);
698     expect(Ok, stat);
699     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
700     expect(Ok, stat);
701
702     /* write, no modification */
703     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
704     expect(Ok, stat);
705
706     if (stat == Ok) {
707         stat = GdipBitmapUnlockBits(bm, &bd);
708         expect(Ok, stat);
709     }
710
711     /* write, consecutive */
712     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
713     expect(Ok, stat);
714
715     if (stat == Ok) {
716         stat = GdipBitmapUnlockBits(bm, &bd);
717         expect(Ok, stat);
718     }
719
720     stat = GdipDisposeImage((GpImage*)bm);
721     expect(Ok, stat);
722     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
723     expect(Ok, stat);
724
725     /* write, modify */
726     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
727     expect(Ok, stat);
728
729     if (stat == Ok) {
730         if (bd.Scan0)
731             ((char*)bd.Scan0)[2] = 0xff;
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(0xffff0000, color);
740
741     stat = GdipDisposeImage((GpImage*)bm);
742     expect(Ok, stat);
743
744     /* dispose locked */
745     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
746     expect(Ok, stat);
747     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
748     expect(Ok, stat);
749     stat = GdipDisposeImage((GpImage*)bm);
750     expect(Ok, stat);
751 }
752
753 static void test_LockBits_UserBuf(void)
754 {
755     GpStatus stat;
756     GpBitmap *bm;
757     GpRect rect;
758     BitmapData bd;
759     const INT WIDTH = 10, HEIGHT = 20;
760     DWORD bits[200];
761     ARGB color;
762
763     bm = NULL;
764     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
765     expect(Ok, stat);
766
767     memset(bits, 0xaa, sizeof(bits));
768
769     rect.X = 2;
770     rect.Y = 3;
771     rect.Width = 4;
772     rect.Height = 5;
773
774     bd.Width = 4;
775     bd.Height = 6;
776     bd.Stride = WIDTH * 4;
777     bd.PixelFormat = PixelFormat32bppARGB;
778     bd.Scan0 = &bits[2+3*WIDTH];
779     bd.Reserved = 0xaaaaaaaa;
780
781     /* read-only */
782     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
783     expect(Ok, stat);
784
785     expect(0xaaaaaaaa, bits[0]);
786     expect(0, bits[2+3*WIDTH]);
787
788     bits[2+3*WIDTH] = 0xdeadbeef;
789
790     if (stat == Ok) {
791         stat = GdipBitmapUnlockBits(bm, &bd);
792         expect(Ok, stat);
793     }
794
795     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
796     expect(Ok, stat);
797     expect(0, color);
798
799     /* write-only */
800     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
801     expect(Ok, stat);
802
803     expect(0xdeadbeef, bits[2+3*WIDTH]);
804     bits[2+3*WIDTH] = 0x12345678;
805
806     if (stat == Ok) {
807         stat = GdipBitmapUnlockBits(bm, &bd);
808         expect(Ok, stat);
809     }
810
811     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
812     expect(Ok, stat);
813     expect(0x12345678, color);
814
815     bits[2+3*WIDTH] = 0;
816
817     /* read/write */
818     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
819     expect(Ok, stat);
820
821     expect(0x12345678, bits[2+3*WIDTH]);
822     bits[2+3*WIDTH] = 0xdeadbeef;
823
824     if (stat == Ok) {
825         stat = GdipBitmapUnlockBits(bm, &bd);
826         expect(Ok, stat);
827     }
828
829     stat = GdipBitmapGetPixel(bm, 2, 3, &color);
830     expect(Ok, stat);
831     expect(0xdeadbeef, color);
832
833     stat = GdipDisposeImage((GpImage*)bm);
834     expect(Ok, stat);
835 }
836
837 struct BITMAPINFOWITHBITFIELDS
838 {
839     BITMAPINFOHEADER bmiHeader;
840     DWORD masks[3];
841 };
842
843 union BITMAPINFOUNION
844 {
845     BITMAPINFO bi;
846     struct BITMAPINFOWITHBITFIELDS bf;
847 };
848
849 static void test_GdipCreateBitmapFromHBITMAP(void)
850 {
851     GpBitmap* gpbm = NULL;
852     HBITMAP hbm = NULL;
853     HPALETTE hpal = NULL;
854     GpStatus stat;
855     BYTE buff[1000];
856     LOGPALETTE* LogPal = NULL;
857     REAL width, height;
858     const REAL WIDTH1 = 5;
859     const REAL HEIGHT1 = 15;
860     const REAL WIDTH2 = 10;
861     const REAL HEIGHT2 = 20;
862     HDC hdc;
863     union BITMAPINFOUNION bmi;
864     BYTE *bits;
865     PixelFormat format;
866
867     stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
868     expect(InvalidParameter, stat);
869
870     hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
871     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
872     expect(InvalidParameter, stat);
873
874     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
875     expect(Ok, stat);
876     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
877     expectf(WIDTH1,  width);
878     expectf(HEIGHT1, height);
879     if (stat == Ok)
880         GdipDisposeImage((GpImage*)gpbm);
881     DeleteObject(hbm);
882
883     memset(buff, 0, sizeof(buff));
884     hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
885     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
886     expect(Ok, stat);
887     /* raw format */
888     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
889
890     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
891     expectf(WIDTH2,  width);
892     expectf(HEIGHT2, height);
893     if (stat == Ok)
894         GdipDisposeImage((GpImage*)gpbm);
895     DeleteObject(hbm);
896
897     hdc = CreateCompatibleDC(0);
898     ok(hdc != NULL, "CreateCompatibleDC failed\n");
899     bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
900     bmi.bi.bmiHeader.biHeight = HEIGHT1;
901     bmi.bi.bmiHeader.biWidth = WIDTH1;
902     bmi.bi.bmiHeader.biBitCount = 24;
903     bmi.bi.bmiHeader.biPlanes = 1;
904     bmi.bi.bmiHeader.biCompression = BI_RGB;
905     bmi.bi.bmiHeader.biClrUsed = 0;
906
907     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
908     ok(hbm != NULL, "CreateDIBSection failed\n");
909
910     bits[0] = 0;
911
912     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
913     expect(Ok, stat);
914     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
915     expectf(WIDTH1,  width);
916     expectf(HEIGHT1, height);
917     if (stat == Ok)
918     {
919         /* test whether writing to the bitmap affects the original */
920         stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
921         expect(Ok, stat);
922
923         expect(0, bits[0]);
924
925         GdipDisposeImage((GpImage*)gpbm);
926     }
927
928     LogPal = GdipAlloc(sizeof(LOGPALETTE));
929     ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
930     LogPal->palVersion = 0x300;
931     LogPal->palNumEntries = 1;
932     hpal = CreatePalette(LogPal);
933     ok(hpal != NULL, "CreatePalette failed\n");
934     GdipFree(LogPal);
935
936     stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
937     expect(Ok, stat);
938
939     if (stat == Ok)
940         GdipDisposeImage((GpImage*)gpbm);
941
942     DeleteObject(hpal);
943     DeleteObject(hbm);
944
945     /* 16-bit 555 dib, rgb */
946     bmi.bi.bmiHeader.biBitCount = 16;
947     bmi.bi.bmiHeader.biCompression = BI_RGB;
948
949     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
950     ok(hbm != NULL, "CreateDIBSection failed\n");
951
952     bits[0] = 0;
953
954     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
955     expect(Ok, stat);
956
957     if (stat == Ok)
958     {
959         stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
960         expect(Ok, stat);
961         expectf(WIDTH1,  width);
962         expectf(HEIGHT1, height);
963
964         stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
965         expect(Ok, stat);
966         expect(PixelFormat16bppRGB555, format);
967
968         GdipDisposeImage((GpImage*)gpbm);
969     }
970     DeleteObject(hbm);
971
972     /* 16-bit 555 dib, with bitfields */
973     bmi.bi.bmiHeader.biSize = sizeof(bmi);
974     bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
975     bmi.bf.masks[0] = 0x7c00;
976     bmi.bf.masks[1] = 0x3e0;
977     bmi.bf.masks[2] = 0x1f;
978
979     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
980     ok(hbm != NULL, "CreateDIBSection failed\n");
981
982     bits[0] = 0;
983
984     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
985     expect(Ok, stat);
986
987     if (stat == Ok)
988     {
989         stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
990         expect(Ok, stat);
991         expectf(WIDTH1,  width);
992         expectf(HEIGHT1, height);
993
994         stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
995         expect(Ok, stat);
996         expect(PixelFormat16bppRGB555, format);
997
998         GdipDisposeImage((GpImage*)gpbm);
999     }
1000     DeleteObject(hbm);
1001
1002     /* 16-bit 565 dib, with bitfields */
1003     bmi.bf.masks[0] = 0xf800;
1004     bmi.bf.masks[1] = 0x7e0;
1005     bmi.bf.masks[2] = 0x1f;
1006
1007     hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1008     ok(hbm != NULL, "CreateDIBSection failed\n");
1009
1010     bits[0] = 0;
1011
1012     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1013     expect(Ok, stat);
1014
1015     if (stat == Ok)
1016     {
1017         stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1018         expect(Ok, stat);
1019         expectf(WIDTH1,  width);
1020         expectf(HEIGHT1, height);
1021
1022         stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1023         expect(Ok, stat);
1024         expect(PixelFormat16bppRGB565, format);
1025
1026         GdipDisposeImage((GpImage*)gpbm);
1027     }
1028     DeleteObject(hbm);
1029
1030     DeleteDC(hdc);
1031 }
1032
1033 static void test_GdipGetImageFlags(void)
1034 {
1035     GpImage *img;
1036     GpStatus stat;
1037     UINT flags;
1038
1039     img = (GpImage*)0xdeadbeef;
1040
1041     stat = GdipGetImageFlags(NULL, NULL);
1042     expect(InvalidParameter, stat);
1043
1044     stat = GdipGetImageFlags(NULL, &flags);
1045     expect(InvalidParameter, stat);
1046
1047     stat = GdipGetImageFlags(img, NULL);
1048     expect(InvalidParameter, stat);
1049
1050     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1051     expect(Ok, stat);
1052     stat = GdipGetImageFlags(img, &flags);
1053     expect(Ok, stat);
1054     expect(ImageFlagsHasAlpha, flags);
1055     GdipDisposeImage(img);
1056
1057     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1058     expect(Ok, stat);
1059     stat = GdipGetImageFlags(img, &flags);
1060     expect(Ok, stat);
1061     expect(ImageFlagsHasAlpha, flags);
1062     GdipDisposeImage(img);
1063
1064     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1065     expect(Ok, stat);
1066     stat = GdipGetImageFlags(img, &flags);
1067     expect(Ok, stat);
1068     expect(ImageFlagsHasAlpha, flags);
1069     GdipDisposeImage(img);
1070
1071     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1072     expect(Ok, stat);
1073     stat = GdipGetImageFlags(img, &flags);
1074     expect(Ok, stat);
1075     expect(ImageFlagsNone, flags);
1076     GdipDisposeImage(img);
1077
1078     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1079     expect(Ok, stat);
1080     stat = GdipGetImageFlags(img, &flags);
1081     expect(Ok, stat);
1082     expect(ImageFlagsNone, flags);
1083     GdipDisposeImage(img);
1084
1085     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1086     expect(Ok, stat);
1087     stat = GdipGetImageFlags(img, &flags);
1088     expect(Ok, stat);
1089     expect(ImageFlagsNone, flags);
1090     GdipDisposeImage(img);
1091
1092     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1093     expect(Ok, stat);
1094     stat = GdipGetImageFlags(img, &flags);
1095     expect(Ok, stat);
1096     expect(ImageFlagsHasAlpha, flags);
1097     GdipDisposeImage(img);
1098
1099     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1100     expect(Ok, stat);
1101     stat = GdipGetImageFlags(img, &flags);
1102     expect(Ok, stat);
1103     expect(ImageFlagsNone, flags);
1104     GdipDisposeImage(img);
1105
1106     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1107     expect(Ok, stat);
1108     stat = GdipGetImageFlags(img, &flags);
1109     expect(Ok, stat);
1110     expect(ImageFlagsNone, flags);
1111     GdipDisposeImage(img);
1112
1113     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1114     expect(Ok, stat);
1115     stat = GdipGetImageFlags(img, &flags);
1116     expect(Ok, stat);
1117     expect(ImageFlagsHasAlpha, flags);
1118     GdipDisposeImage(img);
1119
1120     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1121     expect(Ok, stat);
1122     stat = GdipGetImageFlags(img, &flags);
1123     expect(Ok, stat);
1124     expect(ImageFlagsHasAlpha, flags);
1125     GdipDisposeImage(img);
1126
1127     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1128     expect(Ok, stat);
1129     if (stat == Ok)
1130     {
1131         stat = GdipGetImageFlags(img, &flags);
1132         expect(Ok, stat);
1133         expect(ImageFlagsNone, flags);
1134         GdipDisposeImage(img);
1135     }
1136
1137     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1138     expect(Ok, stat);
1139     if (stat == Ok)
1140     {
1141         expect(Ok, stat);
1142         stat = GdipGetImageFlags(img, &flags);
1143         expect(Ok, stat);
1144         expect(ImageFlagsHasAlpha, flags);
1145         GdipDisposeImage(img);
1146     }
1147
1148     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1149     expect(Ok, stat);
1150     if (stat == Ok)
1151     {
1152         expect(Ok, stat);
1153         stat = GdipGetImageFlags(img, &flags);
1154         expect(Ok, stat);
1155         expect(ImageFlagsHasAlpha, flags);
1156         GdipDisposeImage(img);
1157     }
1158 }
1159
1160 static void test_GdipCloneImage(void)
1161 {
1162     GpStatus stat;
1163     GpRectF rectF;
1164     GpUnit unit;
1165     GpBitmap *bm;
1166     GpImage *image_src, *image_dest = NULL;
1167     const INT WIDTH = 10, HEIGHT = 20;
1168
1169     /* Create an image, clone it, delete the original, make sure the copy works */
1170     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1171     expect(Ok, stat);
1172     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1173
1174     image_src = ((GpImage*)bm);
1175     stat = GdipCloneImage(image_src, &image_dest);
1176     expect(Ok, stat);
1177     expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1178
1179     stat = GdipDisposeImage((GpImage*)bm);
1180     expect(Ok, stat);
1181     stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1182     expect(Ok, stat);
1183
1184     /* Treat FP values carefully */
1185     expectf((REAL)WIDTH, rectF.Width);
1186     expectf((REAL)HEIGHT, rectF.Height);
1187
1188     stat = GdipDisposeImage(image_dest);
1189     expect(Ok, stat);
1190 }
1191
1192 static void test_testcontrol(void)
1193 {
1194     GpStatus stat;
1195     DWORD param;
1196
1197     param = 0;
1198     stat = GdipTestControl(TestControlGetBuildNumber, &param);
1199     expect(Ok, stat);
1200     ok(param != 0, "Build number expected, got %u\n", param);
1201 }
1202
1203 static void test_fromhicon(void)
1204 {
1205     static const BYTE bmp_bits[1024];
1206     HBITMAP hbmMask, hbmColor;
1207     ICONINFO info;
1208     HICON hIcon;
1209     GpStatus stat;
1210     GpBitmap *bitmap = NULL;
1211     UINT dim;
1212     ImageType type;
1213     PixelFormat format;
1214
1215     /* NULL */
1216     stat = GdipCreateBitmapFromHICON(NULL, NULL);
1217     expect(InvalidParameter, stat);
1218     stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1219     expect(InvalidParameter, stat);
1220
1221     /* color icon 1 bit */
1222     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1223     ok(hbmMask != 0, "CreateBitmap failed\n");
1224     hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1225     ok(hbmColor != 0, "CreateBitmap failed\n");
1226     info.fIcon = TRUE;
1227     info.xHotspot = 8;
1228     info.yHotspot = 8;
1229     info.hbmMask = hbmMask;
1230     info.hbmColor = hbmColor;
1231     hIcon = CreateIconIndirect(&info);
1232     ok(hIcon != 0, "CreateIconIndirect failed\n");
1233     DeleteObject(hbmMask);
1234     DeleteObject(hbmColor);
1235
1236     stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1237     ok(stat == Ok ||
1238        broken(stat == InvalidParameter), /* Win98 */
1239        "Expected Ok, got %.8x\n", stat);
1240     if(stat == Ok){
1241        /* check attributes */
1242        stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1243        expect(Ok, stat);
1244        expect(16, dim);
1245        stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1246        expect(Ok, stat);
1247        expect(16, dim);
1248        stat = GdipGetImageType((GpImage*)bitmap, &type);
1249        expect(Ok, stat);
1250        expect(ImageTypeBitmap, type);
1251        stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1252        expect(Ok, stat);
1253        expect(PixelFormat32bppARGB, format);
1254        /* raw format */
1255        expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1256        GdipDisposeImage((GpImage*)bitmap);
1257     }
1258     DestroyIcon(hIcon);
1259
1260     /* color icon 8 bpp */
1261     hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1262     ok(hbmMask != 0, "CreateBitmap failed\n");
1263     hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1264     ok(hbmColor != 0, "CreateBitmap failed\n");
1265     info.fIcon = TRUE;
1266     info.xHotspot = 8;
1267     info.yHotspot = 8;
1268     info.hbmMask = hbmMask;
1269     info.hbmColor = hbmColor;
1270     hIcon = CreateIconIndirect(&info);
1271     ok(hIcon != 0, "CreateIconIndirect failed\n");
1272     DeleteObject(hbmMask);
1273     DeleteObject(hbmColor);
1274
1275     stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1276     expect(Ok, stat);
1277     if(stat == Ok){
1278         /* check attributes */
1279         stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1280         expect(Ok, stat);
1281         expect(16, dim);
1282         stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1283         expect(Ok, stat);
1284         expect(16, dim);
1285         stat = GdipGetImageType((GpImage*)bitmap, &type);
1286         expect(Ok, stat);
1287         expect(ImageTypeBitmap, type);
1288         stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1289         expect(Ok, stat);
1290         expect(PixelFormat32bppARGB, format);
1291         /* raw format */
1292         expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1293         GdipDisposeImage((GpImage*)bitmap);
1294     }
1295     DestroyIcon(hIcon);
1296 }
1297
1298 /* 1x1 pixel png */
1299 static const unsigned char pngimage[285] = {
1300 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1301 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1302 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1303 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1304 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1305 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1306 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1307 };
1308 /* 1x1 pixel gif */
1309 static const unsigned char gifimage[35] = {
1310 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1311 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1312 0x01,0x00,0x3b
1313 };
1314 /* 1x1 pixel bmp */
1315 static const unsigned char bmpimage[66] = {
1316 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1317 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1318 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1319 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1320 0x00,0x00
1321 };
1322 /* 1x1 pixel jpg */
1323 static const unsigned char jpgimage[285] = {
1324 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1325 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1326 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1327 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1328 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1329 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1330 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1331 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1332 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1333 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1334 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1335 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1336 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1337 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1338 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1339 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1340 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1341 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1342 };
1343 /* 1x1 pixel tiff */
1344 static const unsigned char tiffimage[] = {
1345 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1346 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1347 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1348 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1349 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1350 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1351 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1352 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1353 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1354 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1355 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1356 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1357 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1358 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1359 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1360 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1361 0x00,0x00,0x00,0x01
1362 };
1363 /* 320x320 twip wmf */
1364 static const unsigned char wmfimage[180] = {
1365 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1366 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1367 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1368 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1369 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1370 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1371 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1372 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1373 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1374 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1375 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1376 0x00,0x00,0x00,0x00
1377 };
1378 static void test_getrawformat(void)
1379 {
1380     test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG,  __LINE__, FALSE);
1381     test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF,  __LINE__, FALSE);
1382     test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP,  __LINE__, FALSE);
1383     test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1384     test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1385     test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1386 }
1387
1388 static void test_loadwmf(void)
1389 {
1390     LPSTREAM stream;
1391     HGLOBAL  hglob;
1392     LPBYTE   data;
1393     HRESULT  hres;
1394     GpStatus stat;
1395     GpImage *img;
1396     GpRectF bounds;
1397     GpUnit unit;
1398     REAL res = 12345.0;
1399     MetafileHeader header;
1400
1401     hglob = GlobalAlloc (0, sizeof(wmfimage));
1402     data = GlobalLock (hglob);
1403     memcpy(data, wmfimage, sizeof(wmfimage));
1404     GlobalUnlock(hglob); data = NULL;
1405
1406     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1407     ok(hres == S_OK, "Failed to create a stream\n");
1408     if(hres != S_OK) return;
1409
1410     stat = GdipLoadImageFromStream(stream, &img);
1411     ok(stat == Ok, "Failed to create a Bitmap\n");
1412     if(stat != Ok){
1413         IStream_Release(stream);
1414         return;
1415     }
1416
1417     IStream_Release(stream);
1418
1419     stat = GdipGetImageBounds(img, &bounds, &unit);
1420     expect(Ok, stat);
1421     todo_wine expect(UnitPixel, unit);
1422     expectf(0.0, bounds.X);
1423     expectf(0.0, bounds.Y);
1424     todo_wine expectf(320.0, bounds.Width);
1425     todo_wine expectf(320.0, bounds.Height);
1426
1427     stat = GdipGetImageHorizontalResolution(img, &res);
1428     expect(Ok, stat);
1429     todo_wine expectf(1440.0, res);
1430
1431     stat = GdipGetImageVerticalResolution(img, &res);
1432     expect(Ok, stat);
1433     todo_wine expectf(1440.0, res);
1434
1435     memset(&header, 0, sizeof(header));
1436     stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1437     expect(Ok, stat);
1438     if (stat == Ok)
1439     {
1440         todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1441         todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1442         todo_wine expect(0x300, header.Version);
1443         expect(0, header.EmfPlusFlags);
1444         todo_wine expectf(1440.0, header.DpiX);
1445         todo_wine expectf(1440.0, header.DpiY);
1446         expect(0, header.X);
1447         expect(0, header.Y);
1448         todo_wine expect(320, header.Width);
1449         todo_wine expect(320, header.Height);
1450         todo_wine expect(1, U(header).WmfHeader.mtType);
1451         expect(0, header.EmfPlusHeaderSize);
1452         expect(0, header.LogicalDpiX);
1453         expect(0, header.LogicalDpiY);
1454     }
1455
1456     GdipDisposeImage(img);
1457 }
1458
1459 static void test_createfromwmf(void)
1460 {
1461     HMETAFILE hwmf;
1462     GpImage *img;
1463     GpStatus stat;
1464     GpRectF bounds;
1465     GpUnit unit;
1466     REAL res = 12345.0;
1467     MetafileHeader header;
1468
1469     hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1470         wmfimage+sizeof(WmfPlaceableFileHeader));
1471     ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1472
1473     stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1474         (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1475     expect(Ok, stat);
1476
1477     stat = GdipGetImageBounds(img, &bounds, &unit);
1478     expect(Ok, stat);
1479     expect(UnitPixel, unit);
1480     expectf(0.0, bounds.X);
1481     expectf(0.0, bounds.Y);
1482     expectf(320.0, bounds.Width);
1483     expectf(320.0, bounds.Height);
1484
1485     stat = GdipGetImageHorizontalResolution(img, &res);
1486     expect(Ok, stat);
1487     expectf(1440.0, res);
1488
1489     stat = GdipGetImageVerticalResolution(img, &res);
1490     expect(Ok, stat);
1491     expectf(1440.0, res);
1492
1493     memset(&header, 0, sizeof(header));
1494     stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1495     expect(Ok, stat);
1496     if (stat == Ok)
1497     {
1498         todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1499         todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1500         todo_wine expect(0x300, header.Version);
1501         expect(0, header.EmfPlusFlags);
1502         todo_wine expectf(1440.0, header.DpiX);
1503         todo_wine expectf(1440.0, header.DpiY);
1504         expect(0, header.X);
1505         expect(0, header.Y);
1506         todo_wine expect(320, header.Width);
1507         todo_wine expect(320, header.Height);
1508         todo_wine expect(1, U(header).WmfHeader.mtType);
1509         expect(0, header.EmfPlusHeaderSize);
1510         expect(0, header.LogicalDpiX);
1511         expect(0, header.LogicalDpiY);
1512     }
1513
1514     GdipDisposeImage(img);
1515 }
1516
1517 static void test_resolution(void)
1518 {
1519     GpStatus stat;
1520     GpBitmap *bitmap;
1521     GpGraphics *graphics;
1522     REAL res=-1.0;
1523     HDC screendc;
1524     int screenxres, screenyres;
1525
1526     /* create Bitmap */
1527     stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1528     expect(Ok, stat);
1529
1530     /* test invalid values */
1531     stat = GdipGetImageHorizontalResolution(NULL, &res);
1532     expect(InvalidParameter, stat);
1533
1534     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1535     expect(InvalidParameter, stat);
1536
1537     stat = GdipGetImageVerticalResolution(NULL, &res);
1538     expect(InvalidParameter, stat);
1539
1540     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1541     expect(InvalidParameter, stat);
1542
1543     stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1544     expect(InvalidParameter, stat);
1545
1546     stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1547     expect(InvalidParameter, stat);
1548
1549     /* defaults to screen resolution */
1550     screendc = GetDC(0);
1551
1552     screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1553     screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1554
1555     ReleaseDC(0, screendc);
1556
1557     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1558     expect(Ok, stat);
1559     expectf((REAL)screenxres, res);
1560
1561     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1562     expect(Ok, stat);
1563     expectf((REAL)screenyres, res);
1564
1565     stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1566     expect(Ok, stat);
1567     stat = GdipGetDpiX(graphics, &res);
1568     expect(Ok, stat);
1569     expectf((REAL)screenxres, res);
1570     stat = GdipGetDpiY(graphics, &res);
1571     expect(Ok, stat);
1572     expectf((REAL)screenyres, res);
1573
1574     /* test changing the resolution */
1575     stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1576     expect(Ok, stat);
1577
1578     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1579     expect(Ok, stat);
1580     expectf(screenxres*2.0, res);
1581
1582     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1583     expect(Ok, stat);
1584     expectf(screenyres*3.0, res);
1585
1586     stat = GdipGetDpiX(graphics, &res);
1587     expect(Ok, stat);
1588     expectf((REAL)screenxres, res);
1589     stat = GdipGetDpiY(graphics, &res);
1590     expect(Ok, stat);
1591     expectf((REAL)screenyres, res);
1592
1593     stat = GdipDeleteGraphics(graphics);
1594     expect(Ok, stat);
1595
1596     stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1597     expect(Ok, stat);
1598     stat = GdipGetDpiX(graphics, &res);
1599     expect(Ok, stat);
1600     expectf(screenxres*2.0, res);
1601     stat = GdipGetDpiY(graphics, &res);
1602     expect(Ok, stat);
1603     expectf(screenyres*3.0, res);
1604     stat = GdipDeleteGraphics(graphics);
1605     expect(Ok, stat);
1606
1607     stat = GdipDisposeImage((GpImage*)bitmap);
1608     expect(Ok, stat);
1609 }
1610
1611 static void test_createhbitmap(void)
1612 {
1613     GpStatus stat;
1614     GpBitmap *bitmap;
1615     HBITMAP hbitmap, oldhbitmap;
1616     BITMAP bm;
1617     int ret;
1618     HDC hdc;
1619     COLORREF pixel;
1620     BYTE bits[640];
1621
1622     memset(bits, 0x68, 640);
1623
1624     /* create Bitmap */
1625     stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1626     expect(Ok, stat);
1627
1628     /* test NULL values */
1629     stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1630     expect(InvalidParameter, stat);
1631
1632     stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1633     expect(InvalidParameter, stat);
1634
1635     /* create HBITMAP */
1636     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1637     expect(Ok, stat);
1638
1639     if (stat == Ok)
1640     {
1641         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1642         expect(sizeof(BITMAP), ret);
1643
1644         expect(0, bm.bmType);
1645         expect(10, bm.bmWidth);
1646         expect(20, bm.bmHeight);
1647         expect(40, bm.bmWidthBytes);
1648         expect(1, bm.bmPlanes);
1649         expect(32, bm.bmBitsPixel);
1650         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1651
1652         if (bm.bmBits)
1653         {
1654             DWORD val = *(DWORD*)bm.bmBits;
1655             ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1656         }
1657
1658         hdc = CreateCompatibleDC(NULL);
1659
1660         oldhbitmap = SelectObject(hdc, hbitmap);
1661         pixel = GetPixel(hdc, 5, 5);
1662         SelectObject(hdc, oldhbitmap);
1663
1664         DeleteDC(hdc);
1665
1666         expect(0x686868, pixel);
1667
1668         DeleteObject(hbitmap);
1669     }
1670
1671     stat = GdipDisposeImage((GpImage*)bitmap);
1672     expect(Ok, stat);
1673
1674     /* create alpha Bitmap */
1675     stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1676     expect(Ok, stat);
1677
1678     /* create HBITMAP */
1679     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1680     expect(Ok, stat);
1681
1682     if (stat == Ok)
1683     {
1684         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1685         expect(sizeof(BITMAP), ret);
1686
1687         expect(0, bm.bmType);
1688         expect(8, bm.bmWidth);
1689         expect(20, bm.bmHeight);
1690         expect(32, bm.bmWidthBytes);
1691         expect(1, bm.bmPlanes);
1692         expect(32, bm.bmBitsPixel);
1693         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1694
1695         if (bm.bmBits)
1696         {
1697             DWORD val = *(DWORD*)bm.bmBits;
1698             ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1699         }
1700
1701         hdc = CreateCompatibleDC(NULL);
1702
1703         oldhbitmap = SelectObject(hdc, hbitmap);
1704         pixel = GetPixel(hdc, 5, 5);
1705         SelectObject(hdc, oldhbitmap);
1706
1707         DeleteDC(hdc);
1708
1709         expect(0x2a2a2a, pixel);
1710
1711         DeleteObject(hbitmap);
1712     }
1713
1714     stat = GdipDisposeImage((GpImage*)bitmap);
1715     expect(Ok, stat);
1716 }
1717
1718 static void test_getthumbnail(void)
1719 {
1720     GpStatus stat;
1721     GpImage *bitmap1, *bitmap2;
1722     UINT width, height;
1723
1724     stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1725     expect(InvalidParameter, stat);
1726
1727     stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1728     expect(Ok, stat);
1729
1730     stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1731     expect(InvalidParameter, stat);
1732
1733     stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1734     expect(Ok, stat);
1735
1736     if (stat == Ok)
1737     {
1738         stat = GdipGetImageWidth(bitmap2, &width);
1739         expect(Ok, stat);
1740         expect(120, width);
1741
1742         stat = GdipGetImageHeight(bitmap2, &height);
1743         expect(Ok, stat);
1744         expect(120, height);
1745
1746         GdipDisposeImage(bitmap2);
1747     }
1748
1749     GdipDisposeImage(bitmap1);
1750
1751
1752     stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1753     expect(Ok, stat);
1754
1755     stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1756     expect(Ok, stat);
1757
1758     if (stat == Ok)
1759     {
1760         stat = GdipGetImageWidth(bitmap2, &width);
1761         expect(Ok, stat);
1762         expect(32, width);
1763
1764         stat = GdipGetImageHeight(bitmap2, &height);
1765         expect(Ok, stat);
1766         expect(32, height);
1767
1768         GdipDisposeImage(bitmap2);
1769     }
1770
1771     stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1772     expect(Ok, stat);
1773
1774     if (stat == Ok)
1775     {
1776         stat = GdipGetImageWidth(bitmap2, &width);
1777         expect(Ok, stat);
1778         expect(120, width);
1779
1780         stat = GdipGetImageHeight(bitmap2, &height);
1781         expect(Ok, stat);
1782         expect(120, height);
1783
1784         GdipDisposeImage(bitmap2);
1785     }
1786
1787     GdipDisposeImage(bitmap1);
1788 }
1789
1790 static void test_getsetpixel(void)
1791 {
1792     GpStatus stat;
1793     GpBitmap *bitmap;
1794     ARGB color;
1795     BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1796                      0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1797
1798     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1799     expect(Ok, stat);
1800
1801     /* null parameters */
1802     stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1803     expect(InvalidParameter, stat);
1804
1805     stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1806     expect(InvalidParameter, stat);
1807
1808     stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1809     expect(InvalidParameter, stat);
1810
1811     /* out of bounds */
1812     stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1813     expect(InvalidParameter, stat);
1814
1815     stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1816     expect(InvalidParameter, stat);
1817
1818     stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1819     ok(stat == InvalidParameter ||
1820        broken(stat == Ok), /* Older gdiplus */
1821        "Expected InvalidParameter, got %.8x\n", stat);
1822
1823 if (0) /* crashes some gdiplus implementations */
1824 {
1825     stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1826     ok(stat == InvalidParameter ||
1827        broken(stat == Ok), /* Older gdiplus */
1828        "Expected InvalidParameter, got %.8x\n", stat);
1829 }
1830
1831     stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1832     expect(InvalidParameter, stat);
1833
1834     stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1835     expect(InvalidParameter, stat);
1836
1837     stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1838     expect(InvalidParameter, stat);
1839
1840     stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1841     expect(InvalidParameter, stat);
1842
1843     /* valid use */
1844     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1845     expect(Ok, stat);
1846     expect(0xffffffff, color);
1847
1848     stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1849     expect(Ok, stat);
1850     expect(0xff0000ff, color);
1851
1852     stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1853     expect(Ok, stat);
1854
1855     stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1856     expect(Ok, stat);
1857
1858     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1859     expect(Ok, stat);
1860     expect(0xff676869, color);
1861
1862     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1863     expect(Ok, stat);
1864     expect(0xff474849, color);
1865
1866     stat = GdipDisposeImage((GpImage*)bitmap);
1867     expect(Ok, stat);
1868 }
1869
1870 static void check_halftone_palette(ColorPalette *palette)
1871 {
1872     static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1873     UINT i;
1874
1875     for (i=0; i<palette->Count; i++)
1876     {
1877         ARGB expected=0xff000000;
1878         if (i<8)
1879         {
1880             if (i&1) expected |= 0x800000;
1881             if (i&2) expected |= 0x8000;
1882             if (i&4) expected |= 0x80;
1883         }
1884         else if (i == 8)
1885         {
1886             expected = 0xffc0c0c0;
1887         }
1888         else if (i < 16)
1889         {
1890             if (i&1) expected |= 0xff0000;
1891             if (i&2) expected |= 0xff00;
1892             if (i&4) expected |= 0xff;
1893         }
1894         else if (i < 40)
1895         {
1896             expected = 0x00000000;
1897         }
1898         else
1899         {
1900             expected |= halftone_values[(i-40)%6];
1901             expected |= halftone_values[((i-40)/6)%6] << 8;
1902             expected |= halftone_values[((i-40)/36)%6] << 16;
1903         }
1904         ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
1905             expected, palette->Entries[i], i, palette->Count);
1906     }
1907 }
1908
1909 static void test_palette(void)
1910 {
1911     GpStatus stat;
1912     GpBitmap *bitmap;
1913     INT size;
1914     BYTE buffer[1040];
1915     ColorPalette *palette=(ColorPalette*)buffer;
1916     ARGB *entries = palette->Entries;
1917     ARGB color=0;
1918
1919     /* test initial palette from non-indexed bitmap */
1920     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
1921     expect(Ok, stat);
1922
1923     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1924     expect(Ok, stat);
1925     expect(sizeof(UINT)*2+sizeof(ARGB), size);
1926
1927     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1928     expect(Ok, stat);
1929     expect(0, palette->Count);
1930
1931     /* test setting palette on not-indexed bitmap */
1932     palette->Count = 3;
1933
1934     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
1935     expect(Ok, stat);
1936
1937     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1938     expect(Ok, stat);
1939     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
1940
1941     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1942     expect(Ok, stat);
1943     expect(3, palette->Count);
1944
1945     GdipDisposeImage((GpImage*)bitmap);
1946
1947     /* test initial palette on 1-bit bitmap */
1948     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
1949     expect(Ok, stat);
1950
1951     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1952     expect(Ok, stat);
1953     expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
1954
1955     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1956     expect(Ok, stat);
1957     expect(PaletteFlagsGrayScale, palette->Flags);
1958     expect(2, palette->Count);
1959
1960     expect(0xff000000, entries[0]);
1961     expect(0xffffffff, entries[1]);
1962
1963     /* test getting/setting pixels */
1964     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1965     expect(Ok, stat);
1966     expect(0xff000000, color);
1967
1968     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
1969     ok((stat == Ok) ||
1970        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
1971
1972     if (stat == Ok)
1973     {
1974         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1975         expect(Ok, stat);
1976         expect(0xffffffff, color);
1977     }
1978
1979     GdipDisposeImage((GpImage*)bitmap);
1980
1981     /* test initial palette on 4-bit bitmap */
1982     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
1983     expect(Ok, stat);
1984
1985     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1986     expect(Ok, stat);
1987     expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
1988
1989     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1990     expect(Ok, stat);
1991     expect(0, palette->Flags);
1992     expect(16, palette->Count);
1993
1994     check_halftone_palette(palette);
1995
1996     /* test getting/setting pixels */
1997     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1998     expect(Ok, stat);
1999     expect(0xff000000, color);
2000
2001     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2002     ok((stat == Ok) ||
2003        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2004
2005     if (stat == Ok)
2006     {
2007         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2008         expect(Ok, stat);
2009         expect(0xffff00ff, color);
2010     }
2011
2012     GdipDisposeImage((GpImage*)bitmap);
2013
2014     /* test initial palette on 8-bit bitmap */
2015     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2016     expect(Ok, stat);
2017
2018     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2019     expect(Ok, stat);
2020     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2021
2022     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2023     expect(Ok, stat);
2024     expect(PaletteFlagsHalftone, palette->Flags);
2025     expect(256, palette->Count);
2026
2027     check_halftone_palette(palette);
2028
2029     /* test getting/setting pixels */
2030     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2031     expect(Ok, stat);
2032     expect(0xff000000, color);
2033
2034     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2035     ok((stat == Ok) ||
2036        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2037
2038     if (stat == Ok)
2039     {
2040         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2041         expect(Ok, stat);
2042         expect(0xffcccccc, color);
2043     }
2044
2045     /* test setting/getting a different palette */
2046     entries[1] = 0xffcccccc;
2047
2048     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2049     expect(Ok, stat);
2050
2051     entries[1] = 0;
2052
2053     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2054     expect(Ok, stat);
2055     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2056
2057     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2058     expect(Ok, stat);
2059     expect(PaletteFlagsHalftone, palette->Flags);
2060     expect(256, palette->Count);
2061     expect(0xffcccccc, entries[1]);
2062
2063     /* test count < 256 */
2064     palette->Flags = 12345;
2065     palette->Count = 3;
2066
2067     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2068     expect(Ok, stat);
2069
2070     entries[1] = 0;
2071     entries[3] = 0xdeadbeef;
2072
2073     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2074     expect(Ok, stat);
2075     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2076
2077     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2078     expect(Ok, stat);
2079     expect(12345, palette->Flags);
2080     expect(3, palette->Count);
2081     expect(0xffcccccc, entries[1]);
2082     expect(0xdeadbeef, entries[3]);
2083
2084     /* test count > 256 */
2085     palette->Count = 257;
2086
2087     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2088     ok(stat == InvalidParameter ||
2089        broken(stat == Ok), /* Old gdiplus behavior */
2090        "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2091
2092     GdipDisposeImage((GpImage*)bitmap);
2093 }
2094
2095 static void test_colormatrix(void)
2096 {
2097     GpStatus stat;
2098     ColorMatrix colormatrix, graymatrix;
2099     GpImageAttributes *imageattr;
2100     const ColorMatrix identity = {{
2101         {1.0,0.0,0.0,0.0,0.0},
2102         {0.0,1.0,0.0,0.0,0.0},
2103         {0.0,0.0,1.0,0.0,0.0},
2104         {0.0,0.0,0.0,1.0,0.0},
2105         {0.0,0.0,0.0,0.0,1.0}}};
2106     const ColorMatrix double_red = {{
2107         {2.0,0.0,0.0,0.0,0.0},
2108         {0.0,1.0,0.0,0.0,0.0},
2109         {0.0,0.0,1.0,0.0,0.0},
2110         {0.0,0.0,0.0,1.0,0.0},
2111         {0.0,0.0,0.0,0.0,1.0}}};
2112     const ColorMatrix asymmetric = {{
2113         {0.0,1.0,0.0,0.0,0.0},
2114         {0.0,0.0,1.0,0.0,0.0},
2115         {0.0,0.0,0.0,1.0,0.0},
2116         {1.0,0.0,0.0,0.0,0.0},
2117         {0.0,0.0,0.0,0.0,1.0}}};
2118     GpBitmap *bitmap1, *bitmap2;
2119     GpGraphics *graphics;
2120     ARGB color;
2121
2122     colormatrix = identity;
2123     graymatrix = identity;
2124
2125     stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2126         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2127     expect(InvalidParameter, stat);
2128
2129     stat = GdipCreateImageAttributes(&imageattr);
2130     expect(Ok, stat);
2131
2132     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2133         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2134     expect(Ok, stat);
2135
2136     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2137         TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2138     expect(InvalidParameter, stat);
2139
2140     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2141         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2142     expect(Ok, stat);
2143
2144     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2145         TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2146     expect(Ok, stat);
2147
2148     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2149         TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2150     expect(InvalidParameter, stat);
2151
2152     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2153         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2154     expect(Ok, stat);
2155
2156     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2157         TRUE, &colormatrix, &graymatrix, 3);
2158     expect(InvalidParameter, stat);
2159
2160     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2161         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2162     expect(InvalidParameter, stat);
2163
2164     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2165         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2166     expect(InvalidParameter, stat);
2167
2168     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2169         FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2170     expect(Ok, stat);
2171
2172     /* Drawing a bitmap transforms the colors */
2173     colormatrix = double_red;
2174     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2175         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2176     expect(Ok, stat);
2177
2178     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2179     expect(Ok, stat);
2180
2181     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2182     expect(Ok, stat);
2183
2184     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2185     expect(Ok, stat);
2186
2187     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2188     expect(Ok, stat);
2189
2190     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2191         UnitPixel, imageattr, NULL, NULL);
2192     expect(Ok, stat);
2193
2194     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2195     expect(Ok, stat);
2196     expect(0xff80ccee, color);
2197
2198     colormatrix = asymmetric;
2199     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2200         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2201     expect(Ok, stat);
2202
2203     stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2204     expect(Ok, stat);
2205
2206     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2207         UnitPixel, imageattr, NULL, NULL);
2208     expect(Ok, stat);
2209
2210     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2211     expect(Ok, stat);
2212     ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2213
2214     GdipDeleteGraphics(graphics);
2215     GdipDisposeImage((GpImage*)bitmap1);
2216     GdipDisposeImage((GpImage*)bitmap2);
2217     GdipDisposeImageAttributes(imageattr);
2218 }
2219
2220 static void test_gamma(void)
2221 {
2222     GpStatus stat;
2223     GpImageAttributes *imageattr;
2224     GpBitmap *bitmap1, *bitmap2;
2225     GpGraphics *graphics;
2226     ARGB color;
2227
2228     stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2229     expect(InvalidParameter, stat);
2230
2231     stat = GdipCreateImageAttributes(&imageattr);
2232     expect(Ok, stat);
2233
2234     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2235     expect(Ok, stat);
2236
2237     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2238     expect(InvalidParameter, stat);
2239
2240     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2241     expect(InvalidParameter, stat);
2242
2243     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2244     expect(InvalidParameter, stat);
2245
2246     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2247     expect(Ok, stat);
2248
2249     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2250     expect(Ok, stat);
2251
2252     /* Drawing a bitmap transforms the colors */
2253     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2254     expect(Ok, stat);
2255
2256     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2257     expect(Ok, stat);
2258
2259     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2260     expect(Ok, stat);
2261
2262     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2263     expect(Ok, stat);
2264
2265     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2266     expect(Ok, stat);
2267
2268     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2269         UnitPixel, imageattr, NULL, NULL);
2270     expect(Ok, stat);
2271
2272     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2273     expect(Ok, stat);
2274     ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2275
2276     GdipDeleteGraphics(graphics);
2277     GdipDisposeImage((GpImage*)bitmap1);
2278     GdipDisposeImage((GpImage*)bitmap2);
2279     GdipDisposeImageAttributes(imageattr);
2280 }
2281
2282 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2283 static const unsigned char gifanimation[72] = {
2284 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2285 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2286 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2287 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2288 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2289 };
2290
2291 static void test_multiframegif(void)
2292 {
2293     LPSTREAM stream;
2294     HGLOBAL hglob;
2295     LPBYTE data;
2296     HRESULT hres;
2297     GpStatus stat;
2298     GpBitmap *bmp;
2299     ARGB color;
2300     UINT count;
2301     GUID dimension;
2302
2303     /* Test frame functions with an animated GIF */
2304     hglob = GlobalAlloc (0, sizeof(gifanimation));
2305     data = GlobalLock (hglob);
2306     memcpy(data, gifanimation, sizeof(gifanimation));
2307     GlobalUnlock(hglob);
2308
2309     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2310     ok(hres == S_OK, "Failed to create a stream\n");
2311     if(hres != S_OK) return;
2312
2313     stat = GdipCreateBitmapFromStream(stream, &bmp);
2314     ok(stat == Ok, "Failed to create a Bitmap\n");
2315     if(stat != Ok){
2316         IStream_Release(stream);
2317         return;
2318     }
2319
2320     /* Bitmap starts at frame 0 */
2321     color = 0xdeadbeef;
2322     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2323     expect(Ok, stat);
2324     expect(0xffffffff, color);
2325
2326     /* Check that we get correct metadata */
2327     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2328     expect(Ok, stat);
2329     expect(1, count);
2330
2331     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2332     expect(Ok, stat);
2333     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2334
2335     count = 12345;
2336     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2337     expect(Ok, stat);
2338     expect(2, count);
2339
2340     /* SelectActiveFrame overwrites our current data */
2341     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2342     expect(Ok, stat);
2343
2344     color = 0xdeadbeef;
2345     GdipBitmapGetPixel(bmp, 0, 0, &color);
2346     expect(Ok, stat);
2347     expect(0xff000000, color);
2348
2349     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2350     expect(Ok, stat);
2351
2352     color = 0xdeadbeef;
2353     GdipBitmapGetPixel(bmp, 0, 0, &color);
2354     expect(Ok, stat);
2355     expect(0xffffffff, color);
2356
2357     /* Write over the image data */
2358     stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2359     expect(Ok, stat);
2360
2361     /* Switching to the same frame does not overwrite our changes */
2362     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2363     expect(Ok, stat);
2364
2365     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2366     expect(Ok, stat);
2367     expect(0xff000000, color);
2368
2369     /* But switching to another frame and back does */
2370     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2371     expect(Ok, stat);
2372
2373     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2374     expect(Ok, stat);
2375
2376     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2377     expect(Ok, stat);
2378     expect(0xffffffff, color);
2379
2380     /* rotate/flip discards the information about other frames */
2381     stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2382     expect(Ok, stat);
2383
2384     count = 12345;
2385     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2386     expect(Ok, stat);
2387     expect(1, count);
2388
2389     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2390
2391     GdipDisposeImage((GpImage*)bmp);
2392     IStream_Release(stream);
2393
2394     /* Test with a non-animated gif */
2395     hglob = GlobalAlloc (0, sizeof(gifimage));
2396     data = GlobalLock (hglob);
2397     memcpy(data, gifimage, sizeof(gifimage));
2398     GlobalUnlock(hglob);
2399
2400     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2401     ok(hres == S_OK, "Failed to create a stream\n");
2402     if(hres != S_OK) return;
2403
2404     stat = GdipCreateBitmapFromStream(stream, &bmp);
2405     ok(stat == Ok, "Failed to create a Bitmap\n");
2406     if(stat != Ok){
2407         IStream_Release(stream);
2408         return;
2409     }
2410
2411     /* Check metadata */
2412     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2413     expect(Ok, stat);
2414     expect(1, count);
2415
2416     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2417     expect(Ok, stat);
2418     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2419
2420     count = 12345;
2421     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2422     expect(Ok, stat);
2423     expect(1, count);
2424
2425     GdipDisposeImage((GpImage*)bmp);
2426     IStream_Release(stream);
2427 }
2428
2429 static void test_rotateflip(void)
2430 {
2431     GpImage *bitmap;
2432     GpStatus stat;
2433     BYTE bits[24];
2434     static const BYTE orig_bits[24] = {
2435         0,0,0xff,    0,0xff,0,    0xff,0,0,    23,23,23,
2436         0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2437     UINT width, height;
2438     ARGB color;
2439
2440     memcpy(bits, orig_bits, sizeof(bits));
2441     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2442     expect(Ok, stat);
2443
2444     stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2445     expect(Ok, stat);
2446
2447     stat = GdipGetImageWidth(bitmap, &width);
2448     expect(Ok, stat);
2449     stat = GdipGetImageHeight(bitmap, &height);
2450     expect(Ok, stat);
2451     expect(2, width);
2452     expect(3, height);
2453
2454     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2455     expect(Ok, stat);
2456     expect(0xff00ffff, color);
2457
2458     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2459     expect(Ok, stat);
2460     expect(0xffff0000, color);
2461
2462     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2463     expect(Ok, stat);
2464     expect(0xffffff00, color);
2465
2466     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2467     expect(Ok, stat);
2468     expect(0xff0000ff, color);
2469
2470     expect(0, bits[0]);
2471     expect(0, bits[1]);
2472     expect(0xff, bits[2]);
2473
2474     GdipDisposeImage(bitmap);
2475
2476     memcpy(bits, orig_bits, sizeof(bits));
2477     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2478     expect(Ok, stat);
2479
2480     stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2481     expect(Ok, stat);
2482
2483     stat = GdipGetImageWidth(bitmap, &width);
2484     expect(Ok, stat);
2485     stat = GdipGetImageHeight(bitmap, &height);
2486     expect(Ok, stat);
2487     expect(3, width);
2488     expect(2, height);
2489
2490     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2491     expect(Ok, stat);
2492     expect(0xff0000ff, color);
2493
2494     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2495     expect(Ok, stat);
2496     expect(0xffff0000, color);
2497
2498     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2499     expect(Ok, stat);
2500     expect(0xffffff00, color);
2501
2502     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2503     expect(Ok, stat);
2504     expect(0xff00ffff, color);
2505
2506     expect(0, bits[0]);
2507     expect(0, bits[1]);
2508     expect(0xff, bits[2]);
2509
2510     GdipDisposeImage(bitmap);
2511
2512     memcpy(bits, orig_bits, sizeof(bits));
2513     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2514     expect(Ok, stat);
2515
2516     stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2517     expect(Ok, stat);
2518
2519     stat = GdipGetImageWidth(bitmap, &width);
2520     expect(Ok, stat);
2521     stat = GdipGetImageHeight(bitmap, &height);
2522     expect(Ok, stat);
2523     expect(3, width);
2524     expect(2, height);
2525
2526     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2527     expect(Ok, stat);
2528     expect(0xff00ffff, color);
2529
2530     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2531     expect(Ok, stat);
2532     expect(0xffffff00, color);
2533
2534     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2535     expect(Ok, stat);
2536     expect(0xffff0000, color);
2537
2538     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2539     expect(Ok, stat);
2540     expect(0xff0000ff, color);
2541
2542     expect(0, bits[0]);
2543     expect(0, bits[1]);
2544     expect(0xff, bits[2]);
2545
2546     GdipDisposeImage(bitmap);
2547 }
2548
2549 static void test_remaptable(void)
2550 {
2551     GpStatus stat;
2552     GpImageAttributes *imageattr;
2553     GpBitmap *bitmap1, *bitmap2;
2554     GpGraphics *graphics;
2555     ARGB color;
2556     ColorMap *map;
2557
2558     map = GdipAlloc(sizeof(ColorMap));
2559
2560     map->oldColor.Argb = 0xff00ff00;
2561     map->newColor.Argb = 0xffff00ff;
2562
2563     stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2564     expect(InvalidParameter, stat);
2565
2566     stat = GdipCreateImageAttributes(&imageattr);
2567     expect(Ok, stat);
2568
2569     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2570     expect(InvalidParameter, stat);
2571
2572     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2573     expect(InvalidParameter, stat);
2574
2575     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2576     expect(InvalidParameter, stat);
2577
2578     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2579     expect(InvalidParameter, stat);
2580
2581     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2582     expect(Ok, stat);
2583
2584     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2585     expect(Ok, stat);
2586
2587     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2588     expect(Ok, stat);
2589
2590     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2591     expect(Ok, stat);
2592
2593     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2594     expect(Ok, stat);
2595
2596     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2597     expect(Ok, stat);
2598
2599     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2600         UnitPixel, imageattr, NULL, NULL);
2601     expect(Ok, stat);
2602
2603     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2604     expect(Ok, stat);
2605     ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2606
2607     GdipDeleteGraphics(graphics);
2608     GdipDisposeImage((GpImage*)bitmap1);
2609     GdipDisposeImage((GpImage*)bitmap2);
2610     GdipDisposeImageAttributes(imageattr);
2611     GdipFree(map);
2612 }
2613
2614 static void test_colorkey(void)
2615 {
2616     GpStatus stat;
2617     GpImageAttributes *imageattr;
2618     GpBitmap *bitmap1, *bitmap2;
2619     GpGraphics *graphics;
2620     ARGB color;
2621
2622     stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2623     expect(InvalidParameter, stat);
2624
2625     stat = GdipCreateImageAttributes(&imageattr);
2626     expect(Ok, stat);
2627
2628     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2629     expect(InvalidParameter, stat);
2630
2631     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2632     expect(InvalidParameter, stat);
2633
2634     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2635     expect(Ok, stat);
2636
2637     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2638     expect(Ok, stat);
2639
2640     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2641     expect(Ok, stat);
2642
2643     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2644     expect(Ok, stat);
2645
2646     stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2647     expect(Ok, stat);
2648
2649     stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
2650     expect(Ok, stat);
2651
2652     stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
2653     expect(Ok, stat);
2654
2655     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2656     expect(Ok, stat);
2657
2658     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2659         UnitPixel, imageattr, NULL, NULL);
2660     expect(Ok, stat);
2661
2662     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2663     expect(Ok, stat);
2664     ok(color_match(0x00000000, color, 1), "Expected ffff00ff, got %.8x\n", color);
2665
2666     stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2667     expect(Ok, stat);
2668     ok(color_match(0x00000000, color, 1), "Expected ffff00ff, got %.8x\n", color);
2669
2670     stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2671     expect(Ok, stat);
2672     ok(color_match(0x00000000, color, 1), "Expected ffff00ff, got %.8x\n", color);
2673
2674     stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2675     expect(Ok, stat);
2676     ok(color_match(0xffffffff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2677
2678     GdipDeleteGraphics(graphics);
2679     GdipDisposeImage((GpImage*)bitmap1);
2680     GdipDisposeImage((GpImage*)bitmap2);
2681     GdipDisposeImageAttributes(imageattr);
2682 }
2683
2684 static void test_dispose(void)
2685 {
2686     GpStatus stat;
2687     GpImage *image;
2688     char invalid_image[256];
2689
2690     stat = GdipDisposeImage(NULL);
2691     expect(InvalidParameter, stat);
2692
2693     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
2694     expect(Ok, stat);
2695
2696     stat = GdipDisposeImage(image);
2697     expect(Ok, stat);
2698
2699     stat = GdipDisposeImage(image);
2700     expect(ObjectBusy, stat);
2701
2702     memset(invalid_image, 0, 256);
2703     stat = GdipDisposeImage((GpImage*)invalid_image);
2704     expect(ObjectBusy, stat);
2705 }
2706
2707 static LONG obj_refcount(void *obj)
2708 {
2709     IUnknown_AddRef((IUnknown *)obj);
2710     return IUnknown_Release((IUnknown *)obj);
2711 }
2712
2713 static GpImage *load_image(const BYTE *image_data, UINT image_size)
2714 {
2715     IStream *stream;
2716     HGLOBAL hmem;
2717     BYTE *data;
2718     HRESULT hr;
2719     GpStatus status;
2720     GpImage *image = NULL, *clone;
2721     ImageType image_type;
2722     LONG refcount, old_refcount;
2723
2724     hmem = GlobalAlloc(0, image_size);
2725     data = GlobalLock(hmem);
2726     memcpy(data, image_data, image_size);
2727     GlobalUnlock(hmem);
2728
2729     hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
2730     ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
2731     if (hr != S_OK) return NULL;
2732
2733     refcount = obj_refcount(stream);
2734     ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
2735
2736     status = GdipLoadImageFromStream(stream, &image);
2737     ok(status == Ok || broken(status == InvalidParameter), /* XP */
2738        "GdipLoadImageFromStream error %d\n", status);
2739     if (status != Ok)
2740     {
2741         IStream_Release(stream);
2742         return NULL;
2743     }
2744
2745     status = GdipGetImageType(image, &image_type);
2746     ok(status == Ok, "GdipGetImageType error %d\n", status);
2747
2748     refcount = obj_refcount(stream);
2749     if (image_type == ImageTypeBitmap)
2750         ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
2751     else
2752         ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
2753     old_refcount = refcount;
2754
2755     status = GdipCloneImage(image, &clone);
2756     ok(status == Ok, "GdipCloneImage error %d\n", status);
2757     refcount = obj_refcount(stream);
2758     ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
2759     status = GdipDisposeImage(clone);
2760     ok(status == Ok, "GdipDisposeImage error %d\n", status);
2761     refcount = obj_refcount(stream);
2762     ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
2763
2764     refcount = IStream_Release(stream);
2765     if (image_type == ImageTypeBitmap)
2766         ok(refcount >= 1, "expected stream refcount != 0\n");
2767     else
2768         ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
2769
2770     return image;
2771 }
2772
2773 static void test_image_properties(void)
2774 {
2775     static const struct test_data
2776     {
2777         const BYTE *image_data;
2778         UINT image_size;
2779         ImageType image_type;
2780         UINT prop_count;
2781         UINT prop_count2; /* if win7 behaves differently */
2782         /* 1st property attributes */
2783         UINT prop_size;
2784         UINT prop_size2; /* if win7 behaves differently */
2785         UINT prop_id;
2786         UINT prop_id2; /* if win7 behaves differently */
2787     }
2788     td[] =
2789     {
2790         { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
2791         { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
2792         { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
2793         { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
2794         { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
2795     };
2796     GpStatus status;
2797     GpImage *image;
2798     UINT prop_count, prop_size, i;
2799     PROPID prop_id[16] = { 0 };
2800     ImageType image_type;
2801     union
2802     {
2803         PropertyItem data;
2804         char buf[256];
2805     } item;
2806
2807     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2808     {
2809         image = load_image(td[i].image_data, td[i].image_size);
2810         if (!image)
2811         {
2812             trace("%u: failed to load image data\n", i);
2813             continue;
2814         }
2815
2816         status = GdipGetImageType(image, &image_type);
2817         ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
2818         ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
2819            i, td[i].image_type, image_type);
2820
2821         status = GdipGetPropertyCount(image, &prop_count);
2822         ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
2823         if (td[i].image_data == pngimage || td[i].image_data == jpgimage)
2824         todo_wine
2825         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
2826            " %u: expected property count %u or %u, got %u\n",
2827            i, td[i].prop_count, td[i].prop_count2, prop_count);
2828         else
2829         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
2830            " %u: expected property count %u or %u, got %u\n",
2831            i, td[i].prop_count, td[i].prop_count2, prop_count);
2832
2833         status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
2834         expect(InvalidParameter, status);
2835         status = GdipGetPropertyItemSize(image, 0, NULL);
2836         expect(InvalidParameter, status);
2837         status = GdipGetPropertyItemSize(image, 0, &prop_size);
2838         if (image_type == ImageTypeMetafile)
2839             expect(NotImplemented, status);
2840         else
2841             expect(PropertyNotFound, status);
2842
2843         status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
2844         expect(InvalidParameter, status);
2845         status = GdipGetPropertyItem(image, 0, 0, NULL);
2846         expect(InvalidParameter, status);
2847         status = GdipGetPropertyItem(image, 0, 0, &item.data);
2848         if (image_type == ImageTypeMetafile)
2849             expect(NotImplemented, status);
2850         else
2851             expect(PropertyNotFound, status);
2852
2853         /* FIXME: remove once Wine is fixed */
2854         if (td[i].prop_count != prop_count)
2855         {
2856             GdipDisposeImage(image);
2857             continue;
2858         }
2859
2860         status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
2861         expect(InvalidParameter, status);
2862         status = GdipGetPropertyIdList(image, prop_count, NULL);
2863         expect(InvalidParameter, status);
2864         status = GdipGetPropertyIdList(image, 0, prop_id);
2865         if (image_type == ImageTypeMetafile)
2866             expect(NotImplemented, status);
2867         else if (prop_count == 0)
2868             expect(Ok, status);
2869         else
2870             expect(InvalidParameter, status);
2871         status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
2872         if (image_type == ImageTypeMetafile)
2873             expect(NotImplemented, status);
2874         else
2875             expect(InvalidParameter, status);
2876         status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
2877         if (image_type == ImageTypeMetafile)
2878             expect(NotImplemented, status);
2879         else
2880             expect(InvalidParameter, status);
2881         status = GdipGetPropertyIdList(image, prop_count, prop_id);
2882         if (image_type == ImageTypeMetafile)
2883             expect(NotImplemented, status);
2884         else
2885         {
2886             expect(Ok, status);
2887             if (prop_count != 0)
2888                 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
2889                    " %u: expected property id %#x or %#x, got %#x\n",
2890                    i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
2891         }
2892
2893         if (status == Ok)
2894         {
2895             status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
2896             if (prop_count == 0)
2897                 expect(PropertyNotFound, status);
2898             else
2899             {
2900                 expect(Ok, status);
2901
2902                 assert(sizeof(item) >= prop_size);
2903                 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
2904                    i, prop_size);
2905                 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
2906                    td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
2907                    " %u: expected property size %u or %u, got %u\n",
2908                    i, td[i].prop_size, td[i].prop_size2, prop_size);
2909
2910                 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
2911                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2912                    "%u: expected InvalidParameter, got %d\n", i, status);
2913                 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
2914                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2915                    "%u: expected InvalidParameter, got %d\n", i, status);
2916                 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
2917                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2918                    "%u: expected InvalidParameter, got %d\n", i, status);
2919                 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
2920                 expect(Ok, status);
2921                 ok(prop_id[0] == item.data.id,
2922                    "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
2923             }
2924         }
2925
2926         GdipDisposeImage(image);
2927     }
2928 }
2929
2930 #define IFD_BYTE      1
2931 #define IFD_ASCII     2
2932 #define IFD_SHORT     3
2933 #define IFD_LONG      4
2934 #define IFD_RATIONAL  5
2935 #define IFD_SBYTE     6
2936 #define IFD_UNDEFINED 7
2937 #define IFD_SSHORT    8
2938 #define IFD_SLONG     9
2939 #define IFD_SRATIONAL 10
2940 #define IFD_FLOAT     11
2941 #define IFD_DOUBLE    12
2942
2943 #ifndef PropertyTagTypeSByte
2944 #define PropertyTagTypeSByte  6
2945 #define PropertyTagTypeSShort 8
2946 #define PropertyTagTypeFloat  11
2947 #define PropertyTagTypeDouble 12
2948 #endif
2949
2950 static UINT documented_type(UINT type)
2951 {
2952     switch (type)
2953     {
2954     case PropertyTagTypeSByte: return PropertyTagTypeByte;
2955     case PropertyTagTypeSShort: return PropertyTagTypeShort;
2956     case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
2957     case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
2958     default: return type;
2959     }
2960 }
2961
2962 #include "pshpack2.h"
2963 struct IFD_entry
2964 {
2965     SHORT id;
2966     SHORT type;
2967     ULONG count;
2968     LONG  value;
2969 };
2970
2971 struct IFD_rational
2972 {
2973     LONG numerator;
2974     LONG denominator;
2975 };
2976
2977 static const struct tiff_data
2978 {
2979     USHORT byte_order;
2980     USHORT version;
2981     ULONG  dir_offset;
2982     USHORT number_of_entries;
2983     struct IFD_entry entry[40];
2984     ULONG next_IFD;
2985     struct IFD_rational xres;
2986     DOUBLE double_val;
2987     struct IFD_rational srational_val;
2988     char string[14];
2989     SHORT short_val[4];
2990     LONG long_val[2];
2991     FLOAT float_val[2];
2992     struct IFD_rational rational[3];
2993     BYTE pixel_data[4];
2994 } TIFF_data =
2995 {
2996 #ifdef WORDS_BIGENDIAN
2997     'M' | 'M' << 8,
2998 #else
2999     'I' | 'I' << 8,
3000 #endif
3001     42,
3002     FIELD_OFFSET(struct tiff_data, number_of_entries),
3003     31,
3004     {
3005         { 0xff,  IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3006         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3007         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3008         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3009         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3010         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3011         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3012         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3013         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3014         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3015         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3016         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3017         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3018         { 0xf001, IFD_BYTE, 1, 0x11223344 },
3019         { 0xf002, IFD_BYTE, 4, 0x11223344 },
3020         { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3021         { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3022         { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3023         { 0xf006, IFD_SLONG, 1, 0x11223344 },
3024         { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3025         { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3026         { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3027         { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3028         { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3029         { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3030         { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3031         { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3032         { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3033         { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3034         /* Some gdiplus versions ignore these fields.
3035         { 0xf012, IFD_BYTE, 0, 0x11223344 },
3036         { 0xf013, IFD_SHORT, 0, 0x11223344 },
3037         { 0xf014, IFD_LONG, 0, 0x11223344 },
3038         { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3039         { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3040         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3041         { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3042     },
3043     0,
3044     { 900, 3 },
3045     1234567890.0987654321,
3046     { 0x1a2b3c4d, 0x5a6b7c8d },
3047     "Hello World!",
3048     { 0x0101, 0x0202, 0x0303, 0x0404 },
3049     { 0x11223344, 0x55667788 },
3050     { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3051     { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3052     { 0x11, 0x22, 0x33, 0 }
3053 };
3054 #include "poppack.h"
3055
3056 static void test_tiff_properties(void)
3057 {
3058     static const struct test_data
3059     {
3060         ULONG type, id, length;
3061         const BYTE value[24];
3062     } td[31] =
3063     {
3064         { PropertyTagTypeShort, 0xff, 2, { 0 } },
3065         { PropertyTagTypeLong, 0x100, 4, { 1 } },
3066         { PropertyTagTypeLong, 0x101, 4, { 1 } },
3067         { PropertyTagTypeShort, 0x102, 2, { 1 } },
3068         { PropertyTagTypeShort, 0x103, 2, { 1 } },
3069         { PropertyTagTypeShort, 0x106, 2, { 1 } },
3070         { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3071         { PropertyTagTypeShort, 0x115, 2, { 1 } },
3072         { PropertyTagTypeLong, 0x116, 4, { 1 } },
3073         { PropertyTagTypeLong, 0x117, 4, { 1 } },
3074         { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3075         { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3076         { PropertyTagTypeShort, 0x128, 2, { 2 } },
3077         { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3078         { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3079         { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3080         { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3081         { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3082         { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3083         { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3084         { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3085         { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3086         { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3087         { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3088         { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3089         { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3090         { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3091         { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3092         { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3093         { PropertyTagTypeSRational, 0xf016, 24,
3094           { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3095             0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3096             0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3097         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3098         { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3099     };
3100     GpStatus status;
3101     GpImage *image;
3102     GUID guid;
3103     UINT dim_count, frame_count, prop_count, prop_size, i;
3104     PROPID *prop_id;
3105     PropertyItem *prop_item;
3106
3107     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3108     ok(image != 0, "Failed to load TIFF image data\n");
3109     if (!image) return;
3110
3111     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3112     expect(Ok, status);
3113     expect(1, dim_count);
3114
3115     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3116     expect(Ok, status);
3117     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3118
3119     frame_count = 0xdeadbeef;
3120     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3121     expect(Ok, status);
3122     expect(1, frame_count);
3123
3124     prop_count = 0xdeadbeef;
3125     status = GdipGetPropertyCount(image, &prop_count);
3126     expect(Ok, status);
3127     ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3128        broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3129        "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3130
3131     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3132
3133     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3134     expect(Ok, status);
3135
3136     for (i = 0; i < prop_count; i++)
3137     {
3138         status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3139         expect(Ok, status);
3140         if (status != Ok) break;
3141         ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3142
3143         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3144         status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3145         expect(Ok, status);
3146         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3147         ok(td[i].type == prop_item->type ||
3148            /* Win7 stopped using proper but not documented types, and it
3149               looks broken since TypeFloat and TypeDouble now reported as
3150               TypeUndefined, and signed types reported as unsigned. */
3151            broken(prop_item->type == documented_type(td[i].type)),
3152             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3153         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3154         prop_size -= sizeof(*prop_item);
3155         ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3156         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3157         ok(td[i].length == prop_size, "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3158         if (td[i].length == prop_item->length)
3159         {
3160             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3161             ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3162             if (!match)
3163             {
3164                 UINT j;
3165                 BYTE *data = prop_item->value;
3166                 printf("id %#x:", prop_item->id);
3167                 for (j = 0; j < prop_item->length; j++)
3168                     printf(" %02x", data[j]);
3169                 printf("\n");
3170             }
3171         }
3172         HeapFree(GetProcessHeap(), 0, prop_item);
3173     }
3174
3175     HeapFree(GetProcessHeap(), 0, prop_id);
3176
3177     GdipDisposeImage(image);
3178 }
3179
3180 static void test_GdipGetAllPropertyItems(void)
3181 {
3182     static const struct test_data
3183     {
3184         ULONG type, id, length;
3185         BYTE value[32];
3186     } td[16] =
3187     {
3188         { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3189         { PropertyTagTypeShort, 0x100, 2, { 1 } },
3190         { PropertyTagTypeShort, 0x101, 2, { 1 } },
3191         { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3192         { PropertyTagTypeShort, 0x103, 2, { 1 } },
3193         { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3194         { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3195         { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3196         { PropertyTagTypeShort, 0x112, 2, { 1 } },
3197         { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3198         { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3199         { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3200         { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3201         { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3202         { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3203         { PropertyTagTypeShort, 0x128, 2, { 2 } }
3204     };
3205     GpStatus status;
3206     GpImage *image;
3207     GUID guid;
3208     UINT dim_count, frame_count, prop_count, prop_size, i;
3209     UINT total_size, total_count;
3210     PROPID *prop_id;
3211     PropertyItem *prop_item;
3212     const char *item_data;
3213
3214     image = load_image(tiffimage, sizeof(tiffimage));
3215     ok(image != 0, "Failed to load TIFF image data\n");
3216     if (!image) return;
3217
3218     dim_count = 0xdeadbeef;
3219     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3220     expect(Ok, status);
3221     expect(1, dim_count);
3222
3223     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3224     expect(Ok, status);
3225     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3226
3227     frame_count = 0xdeadbeef;
3228     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3229     expect(Ok, status);
3230     expect(1, frame_count);
3231
3232     prop_count = 0xdeadbeef;
3233     status = GdipGetPropertyCount(image, &prop_count);
3234     expect(Ok, status);
3235     ok(prop_count == sizeof(td)/sizeof(td[0]),
3236        "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3237
3238     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3239
3240     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3241     expect(Ok, status);
3242
3243     prop_size = 0;
3244     for (i = 0; i < prop_count; i++)
3245     {
3246         UINT size;
3247         status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3248         expect(Ok, status);
3249         if (status != Ok) break;
3250         ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3251
3252         prop_size += size;
3253
3254         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3255         status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3256         expect(Ok, status);
3257         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3258         ok(td[i].type == prop_item->type,
3259             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3260         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3261         size -= sizeof(*prop_item);
3262         ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3263         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3264         if (td[i].length == prop_item->length)
3265         {
3266             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3267             ok(match, "%u: data mismatch\n", i);
3268             if (!match)
3269             {
3270                 UINT j;
3271                 BYTE *data = prop_item->value;
3272                 printf("id %#x:", prop_item->id);
3273                 for (j = 0; j < prop_item->length; j++)
3274                     printf(" %02x", data[j]);
3275                 printf("\n");
3276             }
3277         }
3278         HeapFree(GetProcessHeap(), 0, prop_item);
3279     }
3280
3281     HeapFree(GetProcessHeap(), 0, prop_id);
3282
3283     status = GdipGetPropertySize(NULL, &total_size, &total_count);
3284     expect(InvalidParameter, status);
3285     status = GdipGetPropertySize(image, &total_size, NULL);
3286     expect(InvalidParameter, status);
3287     status = GdipGetPropertySize(image, NULL, &total_count);
3288     expect(InvalidParameter, status);
3289     status = GdipGetPropertySize(image, NULL, NULL);
3290     expect(InvalidParameter, status);
3291     total_size = 0xdeadbeef;
3292     total_count = 0xdeadbeef;
3293     status = GdipGetPropertySize(image, &total_size, &total_count);
3294     expect(Ok, status);
3295     ok(prop_count == total_count,
3296        "expected total property count %u, got %u\n", prop_count, total_count);
3297     ok(prop_size == total_size,
3298        "expected total property size %u, got %u\n", prop_size, total_size);
3299
3300     prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3301
3302     status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3303     expect(InvalidParameter, status);
3304     status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3305     expect(InvalidParameter, status);
3306     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3307     expect(InvalidParameter, status);
3308     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3309     expect(InvalidParameter, status);
3310     status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3311     expect(InvalidParameter, status);
3312     status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3313     expect(InvalidParameter, status);
3314     status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3315     expect(Ok, status);
3316
3317     item_data = (const char *)(prop_item + prop_count);
3318     for (i = 0; i < prop_count; i++)
3319     {
3320         ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3321            i, item_data, prop_item[i].value);
3322         ok(td[i].type == prop_item[i].type,
3323             "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3324         ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3325         ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3326         if (td[i].length == prop_item[i].length)
3327         {
3328             int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3329             ok(match, "%u: data mismatch\n", i);
3330             if (!match)
3331             {
3332                 UINT j;
3333                 BYTE *data = prop_item[i].value;
3334                 printf("id %#x:", prop_item[i].id);
3335                 for (j = 0; j < prop_item[i].length; j++)
3336                     printf(" %02x", data[j]);
3337                 printf("\n");
3338             }
3339         }
3340         item_data += prop_item[i].length;
3341     }
3342
3343     HeapFree(GetProcessHeap(), 0, prop_item);
3344
3345     GdipDisposeImage(image);
3346 }
3347
3348 static void test_tiff_palette(void)
3349 {
3350     GpStatus status;
3351     GpImage *image;
3352     PixelFormat format;
3353     INT size;
3354     struct
3355     {
3356         ColorPalette pal;
3357         ARGB entry[256];
3358     } palette;
3359     ARGB *entries = palette.pal.Entries;
3360
3361     /* 1bpp TIFF without palette */
3362     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3363     ok(image != 0, "Failed to load TIFF image data\n");
3364     if (!image) return;
3365
3366     status = GdipGetImagePixelFormat(image, &format);
3367     expect(Ok, status);
3368     ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3369
3370     status = GdipGetImagePaletteSize(image, &size);
3371     ok(status == Ok || broken(status == GenericError), /* XP */
3372        "GdipGetImagePaletteSize error %d\n", status);
3373     if (status == GenericError)
3374     {
3375         GdipDisposeImage(image);
3376         return;
3377     }
3378     expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3379
3380     status = GdipGetImagePalette(image, &palette.pal, size);
3381     expect(Ok, status);
3382     expect(0, palette.pal.Flags);
3383     expect(2, palette.pal.Count);
3384     if (palette.pal.Count == 2)
3385     {
3386         ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3387         ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3388     }
3389
3390     GdipDisposeImage(image);
3391 }
3392
3393 static void test_bitmapbits(void)
3394 {
3395     /* 8 x 2 bitmap */
3396     static const BYTE pixels_24[48] =
3397     {
3398         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3399         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3400         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3401         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3402     };
3403     static const BYTE pixels_00[48] =
3404     {
3405         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3406         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3407         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3408         0,0,0, 0,0,0, 0,0,0, 0,0,0
3409     };
3410     static const BYTE pixels_24_77[64] =
3411     {
3412         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3413         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3414         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3415         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3416         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3417         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3418     };
3419     static const BYTE pixels_77[64] =
3420     {
3421         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3422         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3423         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3424         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3425         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3426         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3427         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3428         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3429     };
3430     static const BYTE pixels_8[16] =
3431     {
3432         0x01,0,0x01,0,0x01,0,0x01,0,
3433         0x01,0,0x01,0,0x01,0,0x01,0
3434     };
3435     static const BYTE pixels_8_77[64] =
3436     {
3437         0x01,0,0x01,0,0x01,0,0x01,0,
3438         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3439         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3440         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3441         0x01,0,0x01,0,0x01,0,0x01,0,
3442         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3443         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3444         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3445     };
3446     static const BYTE pixels_1_77[64] =
3447     {
3448         0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3449         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3450         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3451         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3452         0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3453         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3454         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3455         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3456     };
3457     static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3458     static const struct test_data
3459     {
3460         PixelFormat format;
3461         UINT bpp;
3462         ImageLockMode mode;
3463         UINT stride, size;
3464         const BYTE *pixels;
3465         const BYTE *pixels_unlocked;
3466     } td[] =
3467     {
3468         /* 0 */
3469         { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3470
3471         { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3472         { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3473         { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3474         { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3475         { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3476         { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3477         { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3478         /* 8 */
3479         { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3480         { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3481         { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3482         { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3483         { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3484         { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3485         { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3486         /* 15 */
3487         { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3488         { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3489         { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3490         { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3491         { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3492         { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3493         { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3494     };
3495     BYTE buf[64];
3496     GpStatus status;
3497     GpBitmap *bitmap;
3498     UINT i;
3499     BitmapData data;
3500     struct
3501     {
3502         ColorPalette pal;
3503         ARGB entries[1];
3504     } palette;
3505     ARGB *entries = palette.pal.Entries;
3506
3507     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3508     {
3509         BYTE pixels[sizeof(pixels_24)];
3510         memcpy(pixels, pixels_24, sizeof(pixels_24));
3511         status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3512         expect(Ok, status);
3513
3514         /* associate known palette with pixel data */
3515         palette.pal.Flags = PaletteFlagsGrayScale;
3516         palette.pal.Count = 2;
3517         entries[0] = 0xff000000;
3518         entries[1] = 0xffffffff;
3519         status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3520         expect(Ok, status);
3521
3522         memset(&data, 0xfe, sizeof(data));
3523         if (td[i].mode & ImageLockModeUserInputBuf)
3524         {
3525             memset(buf, 0x77, sizeof(buf));
3526             data.Scan0 = buf;
3527             data.Stride = 32;
3528         }
3529         status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3530         ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3531         if (status != Ok)
3532         {
3533             GdipDisposeImage((GpImage *)bitmap);
3534             continue;
3535         }
3536         ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3537         ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3538         ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3539         ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3540         ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3541         if (td[i].mode & ImageLockModeUserInputBuf)
3542             ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3543         if (td[i].size == data.Height * data.Stride)
3544         {
3545             UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3546
3547             match = 1;
3548             for (j = 0; j < data.Height; j++)
3549             {
3550                 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3551                 {
3552                     match = 0;
3553                     break;
3554                 }
3555             }
3556             if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3557             {
3558                 ok(match,
3559                    "%u: data should match\n", i);
3560                 if (!match)
3561                 {
3562                     BYTE *bits = data.Scan0;
3563                     printf("%u: data mismatch for format %#x:", i, td[i].format);
3564                     for (j = 0; j < td[i].size; j++)
3565                         printf(" %02x", bits[j]);
3566                     printf("\n");
3567                 }
3568             }
3569             else
3570                 ok(!match, "%u: data shouldn't match\n", i);
3571
3572             memset(data.Scan0, 0, td[i].size);
3573         }
3574
3575         status = GdipBitmapUnlockBits(bitmap, &data);
3576         ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3577
3578         memset(&data, 0xfe, sizeof(data));
3579         status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3580         ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3581         ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3582         ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3583         ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3584         ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3585         ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3586         if (data.Height * data.Stride == 48)
3587         {
3588             int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3589             ok(match, "%u: data should match\n", i);
3590             if (!match)
3591             {
3592                 UINT j;
3593                 BYTE *bits = data.Scan0;
3594                 printf("%u: data mismatch for format %#x:", i, td[i].format);
3595                 for (j = 0; j < 48; j++)
3596                     printf(" %02x", bits[j]);
3597                 printf("\n");
3598             }
3599         }
3600
3601         status = GdipBitmapUnlockBits(bitmap, &data);
3602         ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3603
3604         status = GdipDisposeImage((GpImage *)bitmap);
3605         expect(Ok, status);
3606     }
3607 }
3608
3609 static void test_DrawImage(void)
3610 {
3611     BYTE black_1x1[4] = { 0,0,0,0 };
3612     BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3613                            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3614     BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3615                            0,0,0,0,0,0,0xff,0xff };
3616     GpStatus status;
3617     union
3618     {
3619         GpBitmap *bitmap;
3620         GpImage *image;
3621     } u1, u2;
3622     GpGraphics *graphics;
3623     int match;
3624
3625     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3626     expect(Ok, status);
3627     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3628     expect(Ok, status);
3629
3630     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3631     expect(Ok, status);
3632     status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3633     expect(Ok, status);
3634     status = GdipGetImageGraphicsContext(u2.image, &graphics);
3635     expect(Ok, status);
3636     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3637     expect(Ok, status);
3638
3639     status = GdipDrawImageI(graphics, u1.image, 0, 0);
3640     expect(Ok, status);
3641
3642     match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3643     ok(match, "data should match\n");
3644     if (!match)
3645     {
3646         UINT i, size = sizeof(white_2x2);
3647         BYTE *bits = white_2x2;
3648         for (i = 0; i < size; i++)
3649             printf(" %02x", bits[i]);
3650         printf("\n");
3651     }
3652
3653     status = GdipDeleteGraphics(graphics);
3654     expect(Ok, status);
3655     status = GdipDisposeImage(u1.image);
3656     expect(Ok, status);
3657     status = GdipDisposeImage(u2.image);
3658     expect(Ok, status);
3659 }
3660
3661 static void test_GdipDrawImagePointRect(void)
3662 {
3663     BYTE black_1x1[4] = { 0,0,0,0 };
3664     BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3665                            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3666     BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3667                            0,0,0,0,0,0,0xff,0xff };
3668     GpStatus status;
3669     union
3670     {
3671         GpBitmap *bitmap;
3672         GpImage *image;
3673     } u1, u2;
3674     GpGraphics *graphics;
3675     int match;
3676
3677     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3678     expect(Ok, status);
3679     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3680     expect(Ok, status);
3681
3682     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3683     expect(Ok, status);
3684     status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3685     expect(Ok, status);
3686     status = GdipGetImageGraphicsContext(u2.image, &graphics);
3687     expect(Ok, status);
3688     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3689     expect(Ok, status);
3690
3691     status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
3692     expect(Ok, status);
3693
3694     match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3695     ok(match, "data should match\n");
3696     if (!match)
3697     {
3698         UINT i, size = sizeof(white_2x2);
3699         BYTE *bits = white_2x2;
3700         for (i = 0; i < size; i++)
3701             printf(" %02x", bits[i]);
3702         printf("\n");
3703     }
3704
3705     status = GdipDeleteGraphics(graphics);
3706     expect(Ok, status);
3707     status = GdipDisposeImage(u1.image);
3708     expect(Ok, status);
3709     status = GdipDisposeImage(u2.image);
3710     expect(Ok, status);
3711 }
3712
3713 static void test_image_format(void)
3714 {
3715     static const PixelFormat fmt[] =
3716     {
3717         PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
3718         PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
3719         PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
3720         PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
3721         PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
3722     };
3723     GpStatus status;
3724     GpBitmap *bitmap;
3725     GpImage *thumb;
3726     HBITMAP hbitmap;
3727     BITMAP bm;
3728     PixelFormat format;
3729     BitmapData data;
3730     UINT i, ret;
3731
3732     for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
3733     {
3734         status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
3735         ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
3736            "GdipCreateBitmapFromScan0 error %d\n", status);
3737         if (status != Ok) continue;
3738
3739         status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
3740         expect(Ok, status);
3741         expect(fmt[i], format);
3742
3743         status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
3744         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3745             todo_wine expect(InvalidParameter, status);
3746         else
3747         {
3748             expect(Ok, status);
3749             ret = GetObject(hbitmap, sizeof(bm), &bm);
3750             expect(sizeof(bm), ret);
3751             expect(0, bm.bmType);
3752             expect(1, bm.bmWidth);
3753             expect(1, bm.bmHeight);
3754             expect(4, bm.bmWidthBytes);
3755             expect(1, bm.bmPlanes);
3756             expect(32, bm.bmBitsPixel);
3757             DeleteObject(hbitmap);
3758         }
3759
3760         status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
3761         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3762             todo_wine
3763             ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
3764                "expected OutOfMemory, got %d\n", status);
3765         else
3766         {
3767             expect(Ok, status);
3768             status = GdipGetImagePixelFormat(thumb, &format);
3769             expect(Ok, status);
3770             ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
3771                "expected PixelFormat32bppPARGB, got %#x\n", format);
3772             status = GdipDisposeImage(thumb);
3773             expect(Ok, status);
3774         }
3775
3776         status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
3777         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3778             todo_wine expect(InvalidParameter, status);
3779         else
3780         {
3781             expect(Ok, status);
3782             status = GdipBitmapUnlockBits(bitmap, &data);
3783             expect(Ok, status);
3784         }
3785
3786         status = GdipDisposeImage((GpImage *)bitmap);
3787         expect(Ok, status);
3788     }
3789 }
3790
3791 static void test_DrawImage_scale(void)
3792 {
3793     static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
3794                                        0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3795     static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
3796                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3797     static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
3798                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3799     static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
3800                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3801     static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3802                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3803     static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3804                                         0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3805     static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3806                                         0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3807     static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
3808                                         0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
3809     static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
3810                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3811     static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
3812                                         0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3813     static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3814                                         0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
3815     static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3816                                         0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
3817     static const struct test_data
3818     {
3819         REAL scale_x;
3820         PixelOffsetMode pixel_offset_mode;
3821         const BYTE *image;
3822         BOOL todo;
3823     } td[] =
3824     {
3825         { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
3826         { 1.0, PixelOffsetModeNone, image_100 },
3827         { 1.2, PixelOffsetModeNone, image_120 },
3828         { 1.5, PixelOffsetModeNone, image_150 },
3829         { 1.8, PixelOffsetModeNone, image_180 },
3830         { 2.0, PixelOffsetModeNone, image_200 },
3831         { 2.5, PixelOffsetModeNone, image_250 },
3832
3833         { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
3834         { 1.0, PixelOffsetModeHighSpeed, image_100 },
3835         { 1.2, PixelOffsetModeHighSpeed, image_120 },
3836         { 1.5, PixelOffsetModeHighSpeed, image_150 },
3837         { 1.8, PixelOffsetModeHighSpeed, image_180 },
3838         { 2.0, PixelOffsetModeHighSpeed, image_200 },
3839         { 2.5, PixelOffsetModeHighSpeed, image_250 },
3840
3841         { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
3842         { 1.0, PixelOffsetModeHalf, image_100 },
3843         { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
3844         { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
3845         { 1.8, PixelOffsetModeHalf, image_180 },
3846         { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
3847         { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
3848
3849         { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
3850         { 1.0, PixelOffsetModeHighQuality, image_100 },
3851         { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
3852         { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
3853         { 1.8, PixelOffsetModeHighQuality, image_180 },
3854         { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
3855         { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
3856     };
3857     BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
3858     BYTE dst_8x1[24];
3859     GpStatus status;
3860     union
3861     {
3862         GpBitmap *bitmap;
3863         GpImage *image;
3864     } u1, u2;
3865     GpGraphics *graphics;
3866     GpMatrix *matrix;
3867     int i, match;
3868
3869     status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
3870     expect(Ok, status);
3871     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3872     expect(Ok, status);
3873
3874     status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
3875     expect(Ok, status);
3876     status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
3877     expect(Ok, status);
3878     status = GdipGetImageGraphicsContext(u2.image, &graphics);
3879     expect(Ok, status);
3880     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3881     expect(Ok, status);
3882
3883     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3884     {
3885         status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
3886         expect(Ok, status);
3887
3888         status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
3889         expect(Ok, status);
3890         status = GdipSetWorldTransform(graphics, matrix);
3891         expect(Ok, status);
3892         GdipDeleteMatrix(matrix);
3893
3894         memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
3895         status = GdipDrawImageI(graphics, u1.image, 1, 0);
3896         expect(Ok, status);
3897
3898         match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
3899         if (!match && td[i].todo)
3900         todo_wine ok(match, "%d: data should match\n", i);
3901         else
3902         ok(match, "%d: data should match\n", i);
3903         if (!match)
3904         {
3905             UINT i, size = sizeof(dst_8x1);
3906             const BYTE *bits = dst_8x1;
3907             for (i = 0; i < size; i++)
3908                 printf(" %02x", bits[i]);
3909             printf("\n");
3910         }
3911     }
3912
3913     status = GdipDeleteGraphics(graphics);
3914     expect(Ok, status);
3915     status = GdipDisposeImage(u1.image);
3916     expect(Ok, status);
3917     status = GdipDisposeImage(u2.image);
3918     expect(Ok, status);
3919 }
3920
3921 static const BYTE animatedgif[] = {
3922 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
3923 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
3924 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
3925 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
3926 0x03,0x01,0x05,0x00,0x00,
3927 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
3928 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
3929 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
3930 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
3931 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
3932 0x02,0x02,0x4C,0x01,0x00,
3933 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
3934 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
3935 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
3936 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
3937 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
3938 0x02,0x02,0x44,0x01,0x00,
3939 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
3940 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
3941 };
3942
3943 static void test_gif_properties(void)
3944 {
3945     static const struct test_data
3946     {
3947         ULONG type, id, length;
3948         const BYTE value[13];
3949     } td[] =
3950     {
3951         { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
3952         { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3953         { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
3954         { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
3955         { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
3956         { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
3957     };
3958     GpStatus status;
3959     GpImage *image;
3960     GUID guid;
3961     UINT dim_count, frame_count, prop_count, prop_size, i;
3962     UINT total_size, total_count;
3963     PROPID *prop_id;
3964     PropertyItem *prop_item;
3965     const char *item_data;
3966
3967     image = load_image(animatedgif, sizeof(animatedgif));
3968     if (!image) /* XP fails to load this GIF image */
3969     {
3970         trace("Failed to load GIF image data\n");
3971         return;
3972     }
3973
3974     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3975     expect(Ok, status);
3976     expect(1, dim_count);
3977
3978     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3979     expect(Ok, status);
3980     expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
3981
3982     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3983     expect(Ok, status);
3984     expect(2, frame_count);
3985
3986     status = GdipImageSelectActiveFrame(image, &guid, 1);
3987     expect(Ok, status);
3988
3989     status = GdipGetPropertyCount(image, &prop_count);
3990     expect(Ok, status);
3991     ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
3992        "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3993
3994     if (prop_count != sizeof(td)/sizeof(td[0]))
3995     {
3996         GdipDisposeImage(image);
3997         return;
3998     }
3999
4000     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4001
4002     status = GdipGetPropertyIdList(image, prop_count, prop_id);
4003     expect(Ok, status);
4004
4005     prop_size = 0;
4006     for (i = 0; i < prop_count; i++)
4007     {
4008         UINT size;
4009         status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4010         expect(Ok, status);
4011         if (status != Ok) break;
4012         ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4013
4014         prop_size += size;
4015
4016         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4017         status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4018         expect(Ok, status);
4019         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4020         ok(td[i].type == prop_item->type,
4021             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4022         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4023         size -= sizeof(*prop_item);
4024         ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4025         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4026         if (td[i].length == prop_item->length)
4027         {
4028             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4029             ok(match, "%u: data mismatch\n", i);
4030             if (!match)
4031             {
4032                 UINT j;
4033                 BYTE *data = prop_item->value;
4034                 printf("id %#x:", prop_item->id);
4035                 for (j = 0; j < prop_item->length; j++)
4036                     printf(" %02x", data[j]);
4037                 printf("\n");
4038             }
4039         }
4040         HeapFree(GetProcessHeap(), 0, prop_item);
4041     }
4042
4043     HeapFree(GetProcessHeap(), 0, prop_id);
4044
4045     status = GdipGetPropertySize(NULL, &total_size, &total_count);
4046     expect(InvalidParameter, status);
4047     status = GdipGetPropertySize(image, &total_size, NULL);
4048     expect(InvalidParameter, status);
4049     status = GdipGetPropertySize(image, NULL, &total_count);
4050     expect(InvalidParameter, status);
4051     status = GdipGetPropertySize(image, NULL, NULL);
4052     expect(InvalidParameter, status);
4053     total_size = 0xdeadbeef;
4054     total_count = 0xdeadbeef;
4055     status = GdipGetPropertySize(image, &total_size, &total_count);
4056     expect(Ok, status);
4057     ok(prop_count == total_count,
4058        "expected total property count %u, got %u\n", prop_count, total_count);
4059     ok(prop_size == total_size,
4060        "expected total property size %u, got %u\n", prop_size, total_size);
4061
4062     prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4063
4064     status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4065     expect(InvalidParameter, status);
4066     status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4067     expect(InvalidParameter, status);
4068     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4069     expect(InvalidParameter, status);
4070     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4071     expect(InvalidParameter, status);
4072     status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4073     expect(InvalidParameter, status);
4074     status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4075     expect(InvalidParameter, status);
4076     status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4077     expect(Ok, status);
4078
4079     item_data = (const char *)(prop_item + prop_count);
4080     for (i = 0; i < prop_count; i++)
4081     {
4082         ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4083            i, item_data, prop_item[i].value);
4084         ok(td[i].type == prop_item[i].type,
4085             "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4086         ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4087         ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4088         if (td[i].length == prop_item[i].length)
4089         {
4090             int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4091             ok(match, "%u: data mismatch\n", i);
4092             if (!match)
4093             {
4094                 UINT j;
4095                 BYTE *data = prop_item[i].value;
4096                 printf("id %#x:", prop_item[i].id);
4097                 for (j = 0; j < prop_item[i].length; j++)
4098                     printf(" %02x", data[j]);
4099                 printf("\n");
4100             }
4101         }
4102         item_data += prop_item[i].length;
4103     }
4104
4105     HeapFree(GetProcessHeap(), 0, prop_item);
4106
4107     GdipDisposeImage(image);
4108 }
4109
4110 START_TEST(image)
4111 {
4112     struct GdiplusStartupInput gdiplusStartupInput;
4113     ULONG_PTR gdiplusToken;
4114
4115     gdiplusStartupInput.GdiplusVersion              = 1;
4116     gdiplusStartupInput.DebugEventCallback          = NULL;
4117     gdiplusStartupInput.SuppressBackgroundThread    = 0;
4118     gdiplusStartupInput.SuppressExternalCodecs      = 0;
4119
4120     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
4121
4122     test_DrawImage_scale();
4123     test_image_format();
4124     test_DrawImage();
4125     test_GdipDrawImagePointRect();
4126     test_bitmapbits();
4127     test_tiff_palette();
4128     test_GdipGetAllPropertyItems();
4129     test_tiff_properties();
4130     test_gif_properties();
4131     test_image_properties();
4132     test_Scan0();
4133     test_FromGdiDib();
4134     test_GetImageDimension();
4135     test_GdipImageGetFrameDimensionsCount();
4136     test_LoadingImages();
4137     test_SavingImages();
4138     test_encoders();
4139     test_LockBits();
4140     test_LockBits_UserBuf();
4141     test_GdipCreateBitmapFromHBITMAP();
4142     test_GdipGetImageFlags();
4143     test_GdipCloneImage();
4144     test_testcontrol();
4145     test_fromhicon();
4146     test_getrawformat();
4147     test_loadwmf();
4148     test_createfromwmf();
4149     test_resolution();
4150     test_createhbitmap();
4151     test_getthumbnail();
4152     test_getsetpixel();
4153     test_palette();
4154     test_colormatrix();
4155     test_gamma();
4156     test_multiframegif();
4157     test_rotateflip();
4158     test_remaptable();
4159     test_colorkey();
4160     test_dispose();
4161
4162     GdiplusShutdown(gdiplusToken);
4163 }