mshtml: Added IHTMLWindow6::get_sessionStorage implementation.
[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         { gifimage, sizeof(gifimage), ImageTypeBitmap, 1, 4, 4, 0, 0x5100, 0 },
2792         { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
2793         { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
2794         { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
2795         { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
2796     };
2797     GpStatus status;
2798     GpImage *image;
2799     UINT prop_count, prop_size, i;
2800     PROPID prop_id[16] = { 0 };
2801     ImageType image_type;
2802     union
2803     {
2804         PropertyItem data;
2805         char buf[256];
2806     } item;
2807
2808     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2809     {
2810         image = load_image(td[i].image_data, td[i].image_size);
2811         if (!image)
2812         {
2813             trace("%u: failed to load image data\n", i);
2814             continue;
2815         }
2816
2817         status = GdipGetImageType(image, &image_type);
2818         ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
2819         ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
2820            i, td[i].image_type, image_type);
2821
2822         status = GdipGetPropertyCount(image, &prop_count);
2823         ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
2824         if (td[i].image_data == pngimage || td[i].image_data == gifimage ||
2825             td[i].image_data == jpgimage)
2826         todo_wine
2827         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
2828            " %u: expected property count %u or %u, got %u\n",
2829            i, td[i].prop_count, td[i].prop_count2, prop_count);
2830         else
2831         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
2832            " %u: expected property count %u or %u, got %u\n",
2833            i, td[i].prop_count, td[i].prop_count2, prop_count);
2834
2835         status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
2836         expect(InvalidParameter, status);
2837         status = GdipGetPropertyItemSize(image, 0, NULL);
2838         expect(InvalidParameter, status);
2839         status = GdipGetPropertyItemSize(image, 0, &prop_size);
2840         if (image_type == ImageTypeMetafile)
2841             expect(NotImplemented, status);
2842         else
2843             expect(PropertyNotFound, status);
2844
2845         status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
2846         expect(InvalidParameter, status);
2847         status = GdipGetPropertyItem(image, 0, 0, NULL);
2848         expect(InvalidParameter, status);
2849         status = GdipGetPropertyItem(image, 0, 0, &item.data);
2850         if (image_type == ImageTypeMetafile)
2851             expect(NotImplemented, status);
2852         else
2853             expect(PropertyNotFound, status);
2854
2855         /* FIXME: remove once Wine is fixed */
2856         if (td[i].prop_count != prop_count)
2857         {
2858             GdipDisposeImage(image);
2859             continue;
2860         }
2861
2862         status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
2863         expect(InvalidParameter, status);
2864         status = GdipGetPropertyIdList(image, prop_count, NULL);
2865         expect(InvalidParameter, status);
2866         status = GdipGetPropertyIdList(image, 0, prop_id);
2867         if (image_type == ImageTypeMetafile)
2868             expect(NotImplemented, status);
2869         else if (prop_count == 0)
2870             expect(Ok, status);
2871         else
2872             expect(InvalidParameter, status);
2873         status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
2874         if (image_type == ImageTypeMetafile)
2875             expect(NotImplemented, status);
2876         else
2877             expect(InvalidParameter, status);
2878         status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
2879         if (image_type == ImageTypeMetafile)
2880             expect(NotImplemented, status);
2881         else
2882             expect(InvalidParameter, status);
2883         status = GdipGetPropertyIdList(image, prop_count, prop_id);
2884         if (image_type == ImageTypeMetafile)
2885             expect(NotImplemented, status);
2886         else
2887         {
2888             expect(Ok, status);
2889             if (prop_count != 0)
2890                 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
2891                    " %u: expected property id %#x or %#x, got %#x\n",
2892                    i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
2893         }
2894
2895         if (status == Ok)
2896         {
2897             status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
2898             if (prop_count == 0)
2899                 expect(PropertyNotFound, status);
2900             else
2901             {
2902                 expect(Ok, status);
2903
2904                 assert(sizeof(item) >= prop_size);
2905                 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
2906                    i, prop_size);
2907                 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
2908                    td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
2909                    " %u: expected property size %u or %u, got %u\n",
2910                    i, td[i].prop_size, td[i].prop_size2, prop_size);
2911
2912                 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
2913                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2914                    "%u: expected InvalidParameter, got %d\n", i, status);
2915                 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
2916                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2917                    "%u: expected InvalidParameter, got %d\n", i, status);
2918                 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
2919                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2920                    "%u: expected InvalidParameter, got %d\n", i, status);
2921                 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
2922                 expect(Ok, status);
2923                 ok(prop_id[0] == item.data.id,
2924                    "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
2925             }
2926         }
2927
2928         GdipDisposeImage(image);
2929     }
2930 }
2931
2932 #define IFD_BYTE      1
2933 #define IFD_ASCII     2
2934 #define IFD_SHORT     3
2935 #define IFD_LONG      4
2936 #define IFD_RATIONAL  5
2937 #define IFD_SBYTE     6
2938 #define IFD_UNDEFINED 7
2939 #define IFD_SSHORT    8
2940 #define IFD_SLONG     9
2941 #define IFD_SRATIONAL 10
2942 #define IFD_FLOAT     11
2943 #define IFD_DOUBLE    12
2944
2945 #ifndef PropertyTagTypeSByte
2946 #define PropertyTagTypeSByte  6
2947 #define PropertyTagTypeSShort 8
2948 #define PropertyTagTypeFloat  11
2949 #define PropertyTagTypeDouble 12
2950 #endif
2951
2952 static UINT documented_type(UINT type)
2953 {
2954     switch (type)
2955     {
2956     case PropertyTagTypeSByte: return PropertyTagTypeByte;
2957     case PropertyTagTypeSShort: return PropertyTagTypeShort;
2958     case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
2959     case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
2960     default: return type;
2961     }
2962 }
2963
2964 #include "pshpack2.h"
2965 struct IFD_entry
2966 {
2967     SHORT id;
2968     SHORT type;
2969     ULONG count;
2970     LONG  value;
2971 };
2972
2973 struct IFD_rational
2974 {
2975     LONG numerator;
2976     LONG denominator;
2977 };
2978
2979 static const struct tiff_data
2980 {
2981     USHORT byte_order;
2982     USHORT version;
2983     ULONG  dir_offset;
2984     USHORT number_of_entries;
2985     struct IFD_entry entry[40];
2986     ULONG next_IFD;
2987     struct IFD_rational xres;
2988     DOUBLE double_val;
2989     struct IFD_rational srational_val;
2990     char string[14];
2991     SHORT short_val[4];
2992     LONG long_val[2];
2993     FLOAT float_val[2];
2994     struct IFD_rational rational[3];
2995     BYTE pixel_data[4];
2996 } TIFF_data =
2997 {
2998 #ifdef WORDS_BIGENDIAN
2999     'M' | 'M' << 8,
3000 #else
3001     'I' | 'I' << 8,
3002 #endif
3003     42,
3004     FIELD_OFFSET(struct tiff_data, number_of_entries),
3005     31,
3006     {
3007         { 0xff,  IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3008         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3009         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3010         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3011         { 0x103, IFD_LONG, 1, 1 }, /* COMPRESSION */
3012         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3013         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3014         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3015         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3016         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3017         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3018         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3019         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3020         { 0xf001, IFD_BYTE, 1, 0x11223344 },
3021         { 0xf002, IFD_BYTE, 4, 0x11223344 },
3022         { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3023         { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3024         { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3025         { 0xf006, IFD_SLONG, 1, 0x11223344 },
3026         { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3027         { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3028         { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3029         { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3030         { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3031         { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3032         { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3033         { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3034         { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3035         { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3036         /* Some gdiplus versions ignore these fields.
3037         { 0xf012, IFD_BYTE, 0, 0x11223344 },
3038         { 0xf013, IFD_SHORT, 0, 0x11223344 },
3039         { 0xf014, IFD_LONG, 0, 0x11223344 },
3040         { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3041         { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3042         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3043         { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3044     },
3045     0,
3046     { 900, 3 },
3047     1234567890.0987654321,
3048     { 0x1a2b3c4d, 0x5a6b7c8d },
3049     "Hello World!",
3050     { 0x0101, 0x0202, 0x0303, 0x0404 },
3051     { 0x11223344, 0x55667788 },
3052     { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3053     { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3054     { 0x11, 0x22, 0x33, 0 }
3055 };
3056 #include "poppack.h"
3057
3058 static void test_tiff_properties(void)
3059 {
3060     static const struct test_data
3061     {
3062         ULONG type, id, length;
3063         const BYTE value[24];
3064     } td[31] =
3065     {
3066         { PropertyTagTypeShort, 0xff, 2, { 0 } },
3067         { PropertyTagTypeLong, 0x100, 4, { 1 } },
3068         { PropertyTagTypeLong, 0x101, 4, { 1 } },
3069         { PropertyTagTypeShort, 0x102, 2, { 1 } },
3070         { PropertyTagTypeLong, 0x103, 4, { 1 } },
3071         { PropertyTagTypeShort, 0x106, 2, { 1 } },
3072         { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3073         { PropertyTagTypeShort, 0x115, 2, { 1 } },
3074         { PropertyTagTypeLong, 0x116, 4, { 1 } },
3075         { PropertyTagTypeLong, 0x117, 4, { 1 } },
3076         { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3077         { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3078         { PropertyTagTypeShort, 0x128, 2, { 2 } },
3079         { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3080         { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3081         { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3082         { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3083         { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3084         { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3085         { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3086         { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3087         { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3088         { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3089         { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3090         { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3091         { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3092         { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3093         { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3094         { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3095         { PropertyTagTypeSRational, 0xf016, 24,
3096           { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3097             0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3098             0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3099         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3100         { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3101     };
3102     GpStatus status;
3103     GpImage *image;
3104     GUID guid;
3105     UINT dim_count, frame_count, prop_count, prop_size, i;
3106     PROPID *prop_id;
3107     PropertyItem *prop_item;
3108
3109     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3110     ok(image != 0, "Failed to load TIFF image data\n");
3111     if (!image) return;
3112
3113     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3114     expect(Ok, status);
3115     expect(1, dim_count);
3116
3117     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3118     expect(Ok, status);
3119     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3120
3121     frame_count = 0xdeadbeef;
3122     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3123     expect(Ok, status);
3124     expect(1, frame_count);
3125
3126     prop_count = 0xdeadbeef;
3127     status = GdipGetPropertyCount(image, &prop_count);
3128     expect(Ok, status);
3129     ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3130        broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3131        "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3132
3133     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3134
3135     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3136     expect(Ok, status);
3137
3138     for (i = 0; i < prop_count; i++)
3139     {
3140         status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3141         expect(Ok, status);
3142         if (status != Ok) break;
3143         ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3144
3145         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3146         status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3147         expect(Ok, status);
3148         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3149         ok(td[i].type == prop_item->type ||
3150            /* Win7 stopped using proper but not documented types, and it
3151               looks broken since TypeFloat and TypeDouble now reported as
3152               TypeUndefined, and signed types reported as unsigned. */
3153            broken(prop_item->type == documented_type(td[i].type)),
3154             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3155         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3156         prop_size -= sizeof(*prop_item);
3157         ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3158         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3159         ok(td[i].length == prop_size, "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3160         if (td[i].length == prop_item->length)
3161         {
3162             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3163             ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3164             if (!match)
3165             {
3166                 UINT j;
3167                 BYTE *data = prop_item->value;
3168                 printf("id %#x:", prop_item->id);
3169                 for (j = 0; j < prop_item->length; j++)
3170                     printf(" %02x", data[j]);
3171                 printf("\n");
3172             }
3173         }
3174         HeapFree(GetProcessHeap(), 0, prop_item);
3175     }
3176
3177     HeapFree(GetProcessHeap(), 0, prop_id);
3178
3179     GdipDisposeImage(image);
3180 }
3181
3182 static void test_GdipGetAllPropertyItems(void)
3183 {
3184     static const struct test_data
3185     {
3186         ULONG type, id, length;
3187         BYTE value[32];
3188     } td[16] =
3189     {
3190         { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3191         { PropertyTagTypeShort, 0x100, 2, { 1 } },
3192         { PropertyTagTypeShort, 0x101, 2, { 1 } },
3193         { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3194         { PropertyTagTypeShort, 0x103, 2, { 1 } },
3195         { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3196         { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3197         { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3198         { PropertyTagTypeShort, 0x112, 2, { 1 } },
3199         { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3200         { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3201         { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3202         { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3203         { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3204         { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3205         { PropertyTagTypeShort, 0x128, 2, { 2 } }
3206     };
3207     GpStatus status;
3208     GpImage *image;
3209     GUID guid;
3210     UINT dim_count, frame_count, prop_count, prop_size, i;
3211     UINT total_size, total_count;
3212     PROPID *prop_id;
3213     PropertyItem *prop_item;
3214     const char *item_data;
3215
3216     image = load_image(tiffimage, sizeof(tiffimage));
3217     ok(image != 0, "Failed to load TIFF image data\n");
3218     if (!image) return;
3219
3220     dim_count = 0xdeadbeef;
3221     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3222     expect(Ok, status);
3223     expect(1, dim_count);
3224
3225     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3226     expect(Ok, status);
3227     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3228
3229     frame_count = 0xdeadbeef;
3230     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3231     expect(Ok, status);
3232     expect(1, frame_count);
3233
3234     prop_count = 0xdeadbeef;
3235     status = GdipGetPropertyCount(image, &prop_count);
3236     expect(Ok, status);
3237     ok(prop_count == sizeof(td)/sizeof(td[0]),
3238        "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3239
3240     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3241
3242     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3243     expect(Ok, status);
3244
3245     prop_size = 0;
3246     for (i = 0; i < prop_count; i++)
3247     {
3248         UINT size;
3249         status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3250         expect(Ok, status);
3251         if (status != Ok) break;
3252         ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3253
3254         prop_size += size;
3255
3256         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3257         status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3258         expect(Ok, status);
3259         ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3260         ok(td[i].type == prop_item->type,
3261             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3262         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3263         size -= sizeof(*prop_item);
3264         ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3265         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3266         if (td[i].length == prop_item->length)
3267         {
3268             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3269             ok(match, "%u: data mismatch\n", i);
3270             if (!match)
3271             {
3272                 UINT j;
3273                 BYTE *data = prop_item->value;
3274                 printf("id %#x:", prop_item->id);
3275                 for (j = 0; j < prop_item->length; j++)
3276                     printf(" %02x", data[j]);
3277                 printf("\n");
3278             }
3279         }
3280         HeapFree(GetProcessHeap(), 0, prop_item);
3281     }
3282
3283     HeapFree(GetProcessHeap(), 0, prop_id);
3284
3285     status = GdipGetPropertySize(NULL, &total_size, &total_count);
3286     expect(InvalidParameter, status);
3287     status = GdipGetPropertySize(image, &total_size, NULL);
3288     expect(InvalidParameter, status);
3289     status = GdipGetPropertySize(image, NULL, &total_count);
3290     expect(InvalidParameter, status);
3291     status = GdipGetPropertySize(image, NULL, NULL);
3292     expect(InvalidParameter, status);
3293     total_size = 0xdeadbeef;
3294     total_count = 0xdeadbeef;
3295     status = GdipGetPropertySize(image, &total_size, &total_count);
3296     expect(Ok, status);
3297     ok(prop_count == total_count,
3298        "expected total property count %u, got %u\n", prop_count, total_count);
3299     ok(prop_size == total_size,
3300        "expected total property size %u, got %u\n", prop_size, total_size);
3301
3302     prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3303
3304     status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3305     expect(InvalidParameter, status);
3306     status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3307     expect(InvalidParameter, status);
3308     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3309     expect(InvalidParameter, status);
3310     status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3311     expect(InvalidParameter, status);
3312     status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3313     expect(InvalidParameter, status);
3314     status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3315     expect(InvalidParameter, status);
3316     status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3317     expect(Ok, status);
3318
3319     item_data = (const char *)(prop_item + prop_count);
3320     for (i = 0; i < prop_count; i++)
3321     {
3322         ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3323            i, item_data, prop_item[i].value);
3324         ok(td[i].type == prop_item[i].type,
3325             "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3326         ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3327         ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3328         if (td[i].length == prop_item[i].length)
3329         {
3330             int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3331             ok(match, "%u: data mismatch\n", i);
3332             if (!match)
3333             {
3334                 UINT j;
3335                 BYTE *data = prop_item[i].value;
3336                 printf("id %#x:", prop_item[i].id);
3337                 for (j = 0; j < prop_item[i].length; j++)
3338                     printf(" %02x", data[j]);
3339                 printf("\n");
3340             }
3341         }
3342         item_data += prop_item[i].length;
3343     }
3344
3345     HeapFree(GetProcessHeap(), 0, prop_item);
3346
3347     GdipDisposeImage(image);
3348 }
3349
3350 static void test_tiff_palette(void)
3351 {
3352     GpStatus status;
3353     GpImage *image;
3354     PixelFormat format;
3355     INT size;
3356     struct
3357     {
3358         ColorPalette pal;
3359         ARGB entry[256];
3360     } palette;
3361     ARGB *entries = palette.pal.Entries;
3362
3363     /* 1bpp TIFF without palette */
3364     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3365     ok(image != 0, "Failed to load TIFF image data\n");
3366     if (!image) return;
3367
3368     status = GdipGetImagePixelFormat(image, &format);
3369     expect(Ok, status);
3370     ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3371
3372     status = GdipGetImagePaletteSize(image, &size);
3373     ok(status == Ok || broken(status == GenericError), /* XP */
3374        "GdipGetImagePaletteSize error %d\n", status);
3375     if (status == GenericError)
3376     {
3377         GdipDisposeImage(image);
3378         return;
3379     }
3380     expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3381
3382     status = GdipGetImagePalette(image, &palette.pal, size);
3383     expect(Ok, status);
3384     expect(0, palette.pal.Flags);
3385     expect(2, palette.pal.Count);
3386     if (palette.pal.Count == 2)
3387     {
3388         ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3389         ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3390     }
3391
3392     GdipDisposeImage(image);
3393 }
3394
3395 static void test_bitmapbits(void)
3396 {
3397     /* 8 x 2 bitmap */
3398     static const BYTE pixels_24[48] =
3399     {
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         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3403         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3404     };
3405     static const BYTE pixels_00[48] =
3406     {
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         0,0,0, 0,0,0, 0,0,0, 0,0,0,
3410         0,0,0, 0,0,0, 0,0,0, 0,0,0
3411     };
3412     static const BYTE pixels_24_77[64] =
3413     {
3414         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3415         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3416         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3417         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3418         0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3419         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3420     };
3421     static const BYTE pixels_77[64] =
3422     {
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         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3430         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3431     };
3432     static const BYTE pixels_8[16] =
3433     {
3434         0x01,0,0x01,0,0x01,0,0x01,0,
3435         0x01,0,0x01,0,0x01,0,0x01,0
3436     };
3437     static const BYTE pixels_8_77[64] =
3438     {
3439         0x01,0,0x01,0,0x01,0,0x01,0,
3440         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3441         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3442         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3443         0x01,0,0x01,0,0x01,0,0x01,0,
3444         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3445         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3446         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3447     };
3448     static const BYTE pixels_1_77[64] =
3449     {
3450         0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3451         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3452         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3453         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3454         0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3455         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3456         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3457         0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3458     };
3459     static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3460     static const struct test_data
3461     {
3462         PixelFormat format;
3463         UINT bpp;
3464         ImageLockMode mode;
3465         UINT stride, size;
3466         const BYTE *pixels;
3467         const BYTE *pixels_unlocked;
3468     } td[] =
3469     {
3470         /* 0 */
3471         { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3472
3473         { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3474         { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3475         { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3476         { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3477         { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3478         { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3479         { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3480         /* 8 */
3481         { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3482         { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3483         { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3484         { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3485         { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3486         { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3487         { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3488         /* 15 */
3489         { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3490         { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3491         { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3492         { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3493         { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3494         { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3495         { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3496     };
3497     BYTE buf[64];
3498     GpStatus status;
3499     GpBitmap *bitmap;
3500     UINT i;
3501     BitmapData data;
3502     struct
3503     {
3504         ColorPalette pal;
3505         ARGB entries[1];
3506     } palette;
3507     ARGB *entries = palette.pal.Entries;
3508
3509     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3510     {
3511         BYTE pixels[sizeof(pixels_24)];
3512         memcpy(pixels, pixels_24, sizeof(pixels_24));
3513         status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3514         expect(Ok, status);
3515
3516         /* associate known palette with pixel data */
3517         palette.pal.Flags = PaletteFlagsGrayScale;
3518         palette.pal.Count = 2;
3519         entries[0] = 0xff000000;
3520         entries[1] = 0xffffffff;
3521         status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3522         expect(Ok, status);
3523
3524         memset(&data, 0xfe, sizeof(data));
3525         if (td[i].mode & ImageLockModeUserInputBuf)
3526         {
3527             memset(buf, 0x77, sizeof(buf));
3528             data.Scan0 = buf;
3529             data.Stride = 32;
3530         }
3531         status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3532         ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3533         if (status != Ok)
3534         {
3535             GdipDisposeImage((GpImage *)bitmap);
3536             continue;
3537         }
3538         ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3539         ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3540         ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3541         ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3542         ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3543         if (td[i].mode & ImageLockModeUserInputBuf)
3544             ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3545         if (td[i].size == data.Height * data.Stride)
3546         {
3547             UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3548
3549             match = 1;
3550             for (j = 0; j < data.Height; j++)
3551             {
3552                 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3553                 {
3554                     match = 0;
3555                     break;
3556                 }
3557             }
3558             if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3559             {
3560                 ok(match,
3561                    "%u: data should match\n", i);
3562                 if (!match)
3563                 {
3564                     BYTE *bits = data.Scan0;
3565                     printf("%u: data mismatch for format %#x:", i, td[i].format);
3566                     for (j = 0; j < td[i].size; j++)
3567                         printf(" %02x", bits[j]);
3568                     printf("\n");
3569                 }
3570             }
3571             else
3572                 ok(!match, "%u: data shouldn't match\n", i);
3573
3574             memset(data.Scan0, 0, td[i].size);
3575         }
3576
3577         status = GdipBitmapUnlockBits(bitmap, &data);
3578         ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3579
3580         memset(&data, 0xfe, sizeof(data));
3581         status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3582         ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3583         ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3584         ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3585         ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3586         ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3587         ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3588         if (data.Height * data.Stride == 48)
3589         {
3590             int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3591             ok(match, "%u: data should match\n", i);
3592             if (!match)
3593             {
3594                 UINT j;
3595                 BYTE *bits = data.Scan0;
3596                 printf("%u: data mismatch for format %#x:", i, td[i].format);
3597                 for (j = 0; j < 48; j++)
3598                     printf(" %02x", bits[j]);
3599                 printf("\n");
3600             }
3601         }
3602
3603         status = GdipBitmapUnlockBits(bitmap, &data);
3604         ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3605
3606         status = GdipDisposeImage((GpImage *)bitmap);
3607         expect(Ok, status);
3608     }
3609 }
3610
3611 static void test_DrawImage(void)
3612 {
3613     BYTE black_1x1[4] = { 0,0,0,0 };
3614     BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3615                            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3616     BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3617                            0,0,0,0,0,0,0xff,0xff };
3618     GpStatus status;
3619     union
3620     {
3621         GpBitmap *bitmap;
3622         GpImage *image;
3623     } u1, u2;
3624     GpGraphics *graphics;
3625     int match;
3626
3627     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3628     expect(Ok, status);
3629     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3630     expect(Ok, status);
3631
3632     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3633     expect(Ok, status);
3634     status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3635     expect(Ok, status);
3636     status = GdipGetImageGraphicsContext(u2.image, &graphics);
3637     expect(Ok, status);
3638     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3639     expect(Ok, status);
3640
3641     status = GdipDrawImageI(graphics, u1.image, 0, 0);
3642     expect(Ok, status);
3643
3644     match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3645     ok(match, "data should match\n");
3646     if (!match)
3647     {
3648         UINT i, size = sizeof(white_2x2);
3649         BYTE *bits = white_2x2;
3650         for (i = 0; i < size; i++)
3651             printf(" %02x", bits[i]);
3652         printf("\n");
3653     }
3654
3655     status = GdipDeleteGraphics(graphics);
3656     expect(Ok, status);
3657     status = GdipDisposeImage(u1.image);
3658     expect(Ok, status);
3659     status = GdipDisposeImage(u2.image);
3660     expect(Ok, status);
3661 }
3662
3663 static void test_GdipDrawImagePointRect(void)
3664 {
3665     BYTE black_1x1[4] = { 0,0,0,0 };
3666     BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3667                            0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3668     BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3669                            0,0,0,0,0,0,0xff,0xff };
3670     GpStatus status;
3671     union
3672     {
3673         GpBitmap *bitmap;
3674         GpImage *image;
3675     } u1, u2;
3676     GpGraphics *graphics;
3677     int match;
3678
3679     status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3680     expect(Ok, status);
3681     status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3682     expect(Ok, status);
3683
3684     status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3685     expect(Ok, status);
3686     status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3687     expect(Ok, status);
3688     status = GdipGetImageGraphicsContext(u2.image, &graphics);
3689     expect(Ok, status);
3690     status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3691     expect(Ok, status);
3692
3693     status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
3694     expect(Ok, status);
3695
3696     match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3697     ok(match, "data should match\n");
3698     if (!match)
3699     {
3700         UINT i, size = sizeof(white_2x2);
3701         BYTE *bits = white_2x2;
3702         for (i = 0; i < size; i++)
3703             printf(" %02x", bits[i]);
3704         printf("\n");
3705     }
3706
3707     status = GdipDeleteGraphics(graphics);
3708     expect(Ok, status);
3709     status = GdipDisposeImage(u1.image);
3710     expect(Ok, status);
3711     status = GdipDisposeImage(u2.image);
3712     expect(Ok, status);
3713 }
3714
3715 static void test_image_format(void)
3716 {
3717     static const PixelFormat fmt[] =
3718     {
3719         PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
3720         PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
3721         PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
3722         PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
3723         PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
3724     };
3725     GpStatus status;
3726     GpBitmap *bitmap;
3727     GpImage *thumb;
3728     HBITMAP hbitmap;
3729     BITMAP bm;
3730     PixelFormat format;
3731     BitmapData data;
3732     UINT i, ret;
3733
3734     for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
3735     {
3736         status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
3737         ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
3738            "GdipCreateBitmapFromScan0 error %d\n", status);
3739         if (status != Ok) continue;
3740
3741         status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
3742         expect(Ok, status);
3743         expect(fmt[i], format);
3744
3745         status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
3746         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3747             todo_wine expect(InvalidParameter, status);
3748         else
3749         {
3750             expect(Ok, status);
3751             ret = GetObject(hbitmap, sizeof(bm), &bm);
3752             expect(sizeof(bm), ret);
3753             expect(0, bm.bmType);
3754             expect(1, bm.bmWidth);
3755             expect(1, bm.bmHeight);
3756             expect(4, bm.bmWidthBytes);
3757             expect(1, bm.bmPlanes);
3758             expect(32, bm.bmBitsPixel);
3759             DeleteObject(hbitmap);
3760         }
3761
3762         status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
3763         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3764             todo_wine
3765             ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
3766                "expected OutOfMemory, got %d\n", status);
3767         else
3768         {
3769             expect(Ok, status);
3770             status = GdipGetImagePixelFormat(thumb, &format);
3771             expect(Ok, status);
3772             ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
3773                "expected PixelFormat32bppPARGB, got %#x\n", format);
3774             status = GdipDisposeImage(thumb);
3775             expect(Ok, status);
3776         }
3777
3778         status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
3779         if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3780             todo_wine expect(InvalidParameter, status);
3781         else
3782         {
3783             expect(Ok, status);
3784             status = GdipBitmapUnlockBits(bitmap, &data);
3785             expect(Ok, status);
3786         }
3787
3788         status = GdipDisposeImage((GpImage *)bitmap);
3789         expect(Ok, status);
3790     }
3791 }
3792
3793 START_TEST(image)
3794 {
3795     struct GdiplusStartupInput gdiplusStartupInput;
3796     ULONG_PTR gdiplusToken;
3797
3798     gdiplusStartupInput.GdiplusVersion              = 1;
3799     gdiplusStartupInput.DebugEventCallback          = NULL;
3800     gdiplusStartupInput.SuppressBackgroundThread    = 0;
3801     gdiplusStartupInput.SuppressExternalCodecs      = 0;
3802
3803     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
3804
3805     test_image_format();
3806     test_DrawImage();
3807     test_GdipDrawImagePointRect();
3808     test_bitmapbits();
3809     test_tiff_palette();
3810     test_GdipGetAllPropertyItems();
3811     test_tiff_properties();
3812     test_image_properties();
3813     test_Scan0();
3814     test_FromGdiDib();
3815     test_GetImageDimension();
3816     test_GdipImageGetFrameDimensionsCount();
3817     test_LoadingImages();
3818     test_SavingImages();
3819     test_encoders();
3820     test_LockBits();
3821     test_LockBits_UserBuf();
3822     test_GdipCreateBitmapFromHBITMAP();
3823     test_GdipGetImageFlags();
3824     test_GdipCloneImage();
3825     test_testcontrol();
3826     test_fromhicon();
3827     test_getrawformat();
3828     test_loadwmf();
3829     test_createfromwmf();
3830     test_resolution();
3831     test_createhbitmap();
3832     test_getthumbnail();
3833     test_getsetpixel();
3834     test_palette();
3835     test_colormatrix();
3836     test_gamma();
3837     test_multiframegif();
3838     test_rotateflip();
3839     test_remaptable();
3840     test_colorkey();
3841     test_dispose();
3842
3843     GdiplusShutdown(gdiplusToken);
3844 }