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