gdiplus: Add a bunch of tests for TIFF image 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     REAL res=-1.0;
1521     HDC screendc;
1522     int screenxres, screenyres;
1523
1524     /* create Bitmap */
1525     stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1526     expect(Ok, stat);
1527
1528     /* test invalid values */
1529     stat = GdipGetImageHorizontalResolution(NULL, &res);
1530     expect(InvalidParameter, stat);
1531
1532     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1533     expect(InvalidParameter, stat);
1534
1535     stat = GdipGetImageVerticalResolution(NULL, &res);
1536     expect(InvalidParameter, stat);
1537
1538     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1539     expect(InvalidParameter, stat);
1540
1541     stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1542     expect(InvalidParameter, stat);
1543
1544     stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1545     expect(InvalidParameter, stat);
1546
1547     /* defaults to screen resolution */
1548     screendc = GetDC(0);
1549
1550     screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1551     screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1552
1553     ReleaseDC(0, screendc);
1554
1555     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1556     expect(Ok, stat);
1557     expectf((REAL)screenxres, res);
1558
1559     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1560     expect(Ok, stat);
1561     expectf((REAL)screenyres, res);
1562
1563     /* test changing the resolution */
1564     stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1565     expect(Ok, stat);
1566
1567     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1568     expect(Ok, stat);
1569     expectf(screenxres*2.0, res);
1570
1571     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1572     expect(Ok, stat);
1573     expectf(screenyres*3.0, res);
1574
1575     stat = GdipDisposeImage((GpImage*)bitmap);
1576     expect(Ok, stat);
1577 }
1578
1579 static void test_createhbitmap(void)
1580 {
1581     GpStatus stat;
1582     GpBitmap *bitmap;
1583     HBITMAP hbitmap, oldhbitmap;
1584     BITMAP bm;
1585     int ret;
1586     HDC hdc;
1587     COLORREF pixel;
1588     BYTE bits[640];
1589
1590     memset(bits, 0x68, 640);
1591
1592     /* create Bitmap */
1593     stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1594     expect(Ok, stat);
1595
1596     /* test NULL values */
1597     stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1598     expect(InvalidParameter, stat);
1599
1600     stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1601     expect(InvalidParameter, stat);
1602
1603     /* create HBITMAP */
1604     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1605     expect(Ok, stat);
1606
1607     if (stat == Ok)
1608     {
1609         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1610         expect(sizeof(BITMAP), ret);
1611
1612         expect(0, bm.bmType);
1613         expect(10, bm.bmWidth);
1614         expect(20, bm.bmHeight);
1615         expect(40, bm.bmWidthBytes);
1616         expect(1, bm.bmPlanes);
1617         expect(32, bm.bmBitsPixel);
1618         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1619
1620         if (bm.bmBits)
1621         {
1622             DWORD val = *(DWORD*)bm.bmBits;
1623             ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1624         }
1625
1626         hdc = CreateCompatibleDC(NULL);
1627
1628         oldhbitmap = SelectObject(hdc, hbitmap);
1629         pixel = GetPixel(hdc, 5, 5);
1630         SelectObject(hdc, oldhbitmap);
1631
1632         DeleteDC(hdc);
1633
1634         expect(0x686868, pixel);
1635
1636         DeleteObject(hbitmap);
1637     }
1638
1639     stat = GdipDisposeImage((GpImage*)bitmap);
1640     expect(Ok, stat);
1641
1642     /* create alpha Bitmap */
1643     stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1644     expect(Ok, stat);
1645
1646     /* create HBITMAP */
1647     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1648     expect(Ok, stat);
1649
1650     if (stat == Ok)
1651     {
1652         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1653         expect(sizeof(BITMAP), ret);
1654
1655         expect(0, bm.bmType);
1656         expect(8, bm.bmWidth);
1657         expect(20, bm.bmHeight);
1658         expect(32, bm.bmWidthBytes);
1659         expect(1, bm.bmPlanes);
1660         expect(32, bm.bmBitsPixel);
1661         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1662
1663         if (bm.bmBits)
1664         {
1665             DWORD val = *(DWORD*)bm.bmBits;
1666             ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1667         }
1668
1669         hdc = CreateCompatibleDC(NULL);
1670
1671         oldhbitmap = SelectObject(hdc, hbitmap);
1672         pixel = GetPixel(hdc, 5, 5);
1673         SelectObject(hdc, oldhbitmap);
1674
1675         DeleteDC(hdc);
1676
1677         expect(0x2a2a2a, pixel);
1678
1679         DeleteObject(hbitmap);
1680     }
1681
1682     stat = GdipDisposeImage((GpImage*)bitmap);
1683     expect(Ok, stat);
1684 }
1685
1686 static void test_getthumbnail(void)
1687 {
1688     GpStatus stat;
1689     GpImage *bitmap1, *bitmap2;
1690     UINT width, height;
1691
1692     stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1693     expect(InvalidParameter, stat);
1694
1695     stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1696     expect(Ok, stat);
1697
1698     stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1699     expect(InvalidParameter, stat);
1700
1701     stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1702     expect(Ok, stat);
1703
1704     if (stat == Ok)
1705     {
1706         stat = GdipGetImageWidth(bitmap2, &width);
1707         expect(Ok, stat);
1708         expect(120, width);
1709
1710         stat = GdipGetImageHeight(bitmap2, &height);
1711         expect(Ok, stat);
1712         expect(120, height);
1713
1714         GdipDisposeImage(bitmap2);
1715     }
1716
1717     GdipDisposeImage(bitmap1);
1718
1719
1720     stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1721     expect(Ok, stat);
1722
1723     stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1724     expect(Ok, stat);
1725
1726     if (stat == Ok)
1727     {
1728         stat = GdipGetImageWidth(bitmap2, &width);
1729         expect(Ok, stat);
1730         expect(32, width);
1731
1732         stat = GdipGetImageHeight(bitmap2, &height);
1733         expect(Ok, stat);
1734         expect(32, height);
1735
1736         GdipDisposeImage(bitmap2);
1737     }
1738
1739     stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1740     expect(Ok, stat);
1741
1742     if (stat == Ok)
1743     {
1744         stat = GdipGetImageWidth(bitmap2, &width);
1745         expect(Ok, stat);
1746         expect(120, width);
1747
1748         stat = GdipGetImageHeight(bitmap2, &height);
1749         expect(Ok, stat);
1750         expect(120, height);
1751
1752         GdipDisposeImage(bitmap2);
1753     }
1754
1755     GdipDisposeImage(bitmap1);
1756 }
1757
1758 static void test_getsetpixel(void)
1759 {
1760     GpStatus stat;
1761     GpBitmap *bitmap;
1762     ARGB color;
1763     BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1764                      0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1765
1766     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1767     expect(Ok, stat);
1768
1769     /* null parameters */
1770     stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1771     expect(InvalidParameter, stat);
1772
1773     stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1774     expect(InvalidParameter, stat);
1775
1776     stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1777     expect(InvalidParameter, stat);
1778
1779     /* out of bounds */
1780     stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1781     expect(InvalidParameter, stat);
1782
1783     stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1784     expect(InvalidParameter, stat);
1785
1786     stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1787     ok(stat == InvalidParameter ||
1788        broken(stat == Ok), /* Older gdiplus */
1789        "Expected InvalidParameter, got %.8x\n", stat);
1790
1791 if (0) /* crashes some gdiplus implementations */
1792 {
1793     stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1794     ok(stat == InvalidParameter ||
1795        broken(stat == Ok), /* Older gdiplus */
1796        "Expected InvalidParameter, got %.8x\n", stat);
1797 }
1798
1799     stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1800     expect(InvalidParameter, stat);
1801
1802     stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1803     expect(InvalidParameter, stat);
1804
1805     stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1806     expect(InvalidParameter, stat);
1807
1808     stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1809     expect(InvalidParameter, stat);
1810
1811     /* valid use */
1812     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1813     expect(Ok, stat);
1814     expect(0xffffffff, color);
1815
1816     stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1817     expect(Ok, stat);
1818     expect(0xff0000ff, color);
1819
1820     stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1821     expect(Ok, stat);
1822
1823     stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1824     expect(Ok, stat);
1825
1826     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1827     expect(Ok, stat);
1828     expect(0xff676869, color);
1829
1830     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1831     expect(Ok, stat);
1832     expect(0xff474849, color);
1833
1834     stat = GdipDisposeImage((GpImage*)bitmap);
1835     expect(Ok, stat);
1836 }
1837
1838 static void check_halftone_palette(ColorPalette *palette)
1839 {
1840     static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1841     UINT i;
1842
1843     for (i=0; i<palette->Count; i++)
1844     {
1845         ARGB expected=0xff000000;
1846         if (i<8)
1847         {
1848             if (i&1) expected |= 0x800000;
1849             if (i&2) expected |= 0x8000;
1850             if (i&4) expected |= 0x80;
1851         }
1852         else if (i == 8)
1853         {
1854             expected = 0xffc0c0c0;
1855         }
1856         else if (i < 16)
1857         {
1858             if (i&1) expected |= 0xff0000;
1859             if (i&2) expected |= 0xff00;
1860             if (i&4) expected |= 0xff;
1861         }
1862         else if (i < 40)
1863         {
1864             expected = 0x00000000;
1865         }
1866         else
1867         {
1868             expected |= halftone_values[(i-40)%6];
1869             expected |= halftone_values[((i-40)/6)%6] << 8;
1870             expected |= halftone_values[((i-40)/36)%6] << 16;
1871         }
1872         ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
1873             expected, palette->Entries[i], i, palette->Count);
1874     }
1875 }
1876
1877 static void test_palette(void)
1878 {
1879     GpStatus stat;
1880     GpBitmap *bitmap;
1881     INT size;
1882     BYTE buffer[1040];
1883     ColorPalette *palette=(ColorPalette*)buffer;
1884     ARGB *entries = palette->Entries;
1885     ARGB color=0;
1886
1887     /* test initial palette from non-indexed bitmap */
1888     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
1889     expect(Ok, stat);
1890
1891     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1892     expect(Ok, stat);
1893     expect(sizeof(UINT)*2+sizeof(ARGB), size);
1894
1895     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1896     expect(Ok, stat);
1897     expect(0, palette->Count);
1898
1899     /* test setting palette on not-indexed bitmap */
1900     palette->Count = 3;
1901
1902     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
1903     expect(Ok, stat);
1904
1905     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1906     expect(Ok, stat);
1907     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
1908
1909     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1910     expect(Ok, stat);
1911     expect(3, palette->Count);
1912
1913     GdipDisposeImage((GpImage*)bitmap);
1914
1915     /* test initial palette on 1-bit bitmap */
1916     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
1917     expect(Ok, stat);
1918
1919     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1920     expect(Ok, stat);
1921     expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
1922
1923     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1924     expect(Ok, stat);
1925     expect(PaletteFlagsGrayScale, palette->Flags);
1926     expect(2, palette->Count);
1927
1928     expect(0xff000000, entries[0]);
1929     expect(0xffffffff, entries[1]);
1930
1931     /* test getting/setting pixels */
1932     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1933     expect(Ok, stat);
1934     expect(0xff000000, color);
1935
1936     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
1937     ok((stat == Ok) ||
1938        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
1939
1940     if (stat == Ok)
1941     {
1942         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1943         expect(Ok, stat);
1944         expect(0xffffffff, color);
1945     }
1946
1947     GdipDisposeImage((GpImage*)bitmap);
1948
1949     /* test initial palette on 4-bit bitmap */
1950     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
1951     expect(Ok, stat);
1952
1953     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1954     expect(Ok, stat);
1955     expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
1956
1957     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1958     expect(Ok, stat);
1959     expect(0, palette->Flags);
1960     expect(16, palette->Count);
1961
1962     check_halftone_palette(palette);
1963
1964     /* test getting/setting pixels */
1965     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1966     expect(Ok, stat);
1967     expect(0xff000000, color);
1968
1969     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
1970     ok((stat == Ok) ||
1971        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
1972
1973     if (stat == Ok)
1974     {
1975         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1976         expect(Ok, stat);
1977         expect(0xffff00ff, color);
1978     }
1979
1980     GdipDisposeImage((GpImage*)bitmap);
1981
1982     /* test initial palette on 8-bit bitmap */
1983     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
1984     expect(Ok, stat);
1985
1986     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1987     expect(Ok, stat);
1988     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
1989
1990     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1991     expect(Ok, stat);
1992     expect(PaletteFlagsHalftone, palette->Flags);
1993     expect(256, palette->Count);
1994
1995     check_halftone_palette(palette);
1996
1997     /* test getting/setting pixels */
1998     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1999     expect(Ok, stat);
2000     expect(0xff000000, color);
2001
2002     stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2003     ok((stat == Ok) ||
2004        broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2005
2006     if (stat == Ok)
2007     {
2008         stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2009         expect(Ok, stat);
2010         expect(0xffcccccc, color);
2011     }
2012
2013     /* test setting/getting a different palette */
2014     entries[1] = 0xffcccccc;
2015
2016     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2017     expect(Ok, stat);
2018
2019     entries[1] = 0;
2020
2021     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2022     expect(Ok, stat);
2023     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2024
2025     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2026     expect(Ok, stat);
2027     expect(PaletteFlagsHalftone, palette->Flags);
2028     expect(256, palette->Count);
2029     expect(0xffcccccc, entries[1]);
2030
2031     /* test count < 256 */
2032     palette->Flags = 12345;
2033     palette->Count = 3;
2034
2035     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2036     expect(Ok, stat);
2037
2038     entries[1] = 0;
2039     entries[3] = 0xdeadbeef;
2040
2041     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2042     expect(Ok, stat);
2043     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2044
2045     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2046     expect(Ok, stat);
2047     expect(12345, palette->Flags);
2048     expect(3, palette->Count);
2049     expect(0xffcccccc, entries[1]);
2050     expect(0xdeadbeef, entries[3]);
2051
2052     /* test count > 256 */
2053     palette->Count = 257;
2054
2055     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2056     ok(stat == InvalidParameter ||
2057        broken(stat == Ok), /* Old gdiplus behavior */
2058        "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2059
2060     GdipDisposeImage((GpImage*)bitmap);
2061 }
2062
2063 static void test_colormatrix(void)
2064 {
2065     GpStatus stat;
2066     ColorMatrix colormatrix, graymatrix;
2067     GpImageAttributes *imageattr;
2068     const ColorMatrix identity = {{
2069         {1.0,0.0,0.0,0.0,0.0},
2070         {0.0,1.0,0.0,0.0,0.0},
2071         {0.0,0.0,1.0,0.0,0.0},
2072         {0.0,0.0,0.0,1.0,0.0},
2073         {0.0,0.0,0.0,0.0,1.0}}};
2074     const ColorMatrix double_red = {{
2075         {2.0,0.0,0.0,0.0,0.0},
2076         {0.0,1.0,0.0,0.0,0.0},
2077         {0.0,0.0,1.0,0.0,0.0},
2078         {0.0,0.0,0.0,1.0,0.0},
2079         {0.0,0.0,0.0,0.0,1.0}}};
2080     const ColorMatrix asymmetric = {{
2081         {0.0,1.0,0.0,0.0,0.0},
2082         {0.0,0.0,1.0,0.0,0.0},
2083         {0.0,0.0,0.0,1.0,0.0},
2084         {1.0,0.0,0.0,0.0,0.0},
2085         {0.0,0.0,0.0,0.0,1.0}}};
2086     GpBitmap *bitmap1, *bitmap2;
2087     GpGraphics *graphics;
2088     ARGB color;
2089
2090     colormatrix = identity;
2091     graymatrix = identity;
2092
2093     stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2094         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2095     expect(InvalidParameter, stat);
2096
2097     stat = GdipCreateImageAttributes(&imageattr);
2098     expect(Ok, stat);
2099
2100     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2101         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2102     expect(Ok, stat);
2103
2104     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2105         TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2106     expect(InvalidParameter, stat);
2107
2108     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2109         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2110     expect(Ok, stat);
2111
2112     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2113         TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2114     expect(Ok, stat);
2115
2116     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2117         TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2118     expect(InvalidParameter, stat);
2119
2120     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2121         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2122     expect(Ok, stat);
2123
2124     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2125         TRUE, &colormatrix, &graymatrix, 3);
2126     expect(InvalidParameter, stat);
2127
2128     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2129         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2130     expect(InvalidParameter, stat);
2131
2132     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2133         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2134     expect(InvalidParameter, stat);
2135
2136     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2137         FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2138     expect(Ok, stat);
2139
2140     /* Drawing a bitmap transforms the colors */
2141     colormatrix = double_red;
2142     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2143         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2144     expect(Ok, stat);
2145
2146     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2147     expect(Ok, stat);
2148
2149     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2150     expect(Ok, stat);
2151
2152     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2153     expect(Ok, stat);
2154
2155     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2156     expect(Ok, stat);
2157
2158     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2159         UnitPixel, imageattr, NULL, NULL);
2160     expect(Ok, stat);
2161
2162     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2163     expect(Ok, stat);
2164     expect(0xff80ccee, color);
2165
2166     colormatrix = asymmetric;
2167     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2168         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2169     expect(Ok, stat);
2170
2171     stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2172     expect(Ok, stat);
2173
2174     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2175         UnitPixel, imageattr, NULL, NULL);
2176     expect(Ok, stat);
2177
2178     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2179     expect(Ok, stat);
2180     ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2181
2182     GdipDeleteGraphics(graphics);
2183     GdipDisposeImage((GpImage*)bitmap1);
2184     GdipDisposeImage((GpImage*)bitmap2);
2185     GdipDisposeImageAttributes(imageattr);
2186 }
2187
2188 static void test_gamma(void)
2189 {
2190     GpStatus stat;
2191     GpImageAttributes *imageattr;
2192     GpBitmap *bitmap1, *bitmap2;
2193     GpGraphics *graphics;
2194     ARGB color;
2195
2196     stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2197     expect(InvalidParameter, stat);
2198
2199     stat = GdipCreateImageAttributes(&imageattr);
2200     expect(Ok, stat);
2201
2202     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2203     expect(Ok, stat);
2204
2205     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2206     expect(InvalidParameter, stat);
2207
2208     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2209     expect(InvalidParameter, stat);
2210
2211     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2212     expect(InvalidParameter, stat);
2213
2214     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2215     expect(Ok, stat);
2216
2217     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2218     expect(Ok, stat);
2219
2220     /* Drawing a bitmap transforms the colors */
2221     stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2222     expect(Ok, stat);
2223
2224     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2225     expect(Ok, stat);
2226
2227     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2228     expect(Ok, stat);
2229
2230     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2231     expect(Ok, stat);
2232
2233     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2234     expect(Ok, stat);
2235
2236     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2237         UnitPixel, imageattr, NULL, NULL);
2238     expect(Ok, stat);
2239
2240     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2241     expect(Ok, stat);
2242     ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2243
2244     GdipDeleteGraphics(graphics);
2245     GdipDisposeImage((GpImage*)bitmap1);
2246     GdipDisposeImage((GpImage*)bitmap2);
2247     GdipDisposeImageAttributes(imageattr);
2248 }
2249
2250 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2251 static const unsigned char gifanimation[72] = {
2252 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2253 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2254 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2255 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2256 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2257 };
2258
2259 static void test_multiframegif(void)
2260 {
2261     LPSTREAM stream;
2262     HGLOBAL hglob;
2263     LPBYTE data;
2264     HRESULT hres;
2265     GpStatus stat;
2266     GpBitmap *bmp;
2267     ARGB color;
2268     UINT count;
2269     GUID dimension;
2270
2271     /* Test frame functions with an animated GIF */
2272     hglob = GlobalAlloc (0, sizeof(gifanimation));
2273     data = GlobalLock (hglob);
2274     memcpy(data, gifanimation, sizeof(gifanimation));
2275     GlobalUnlock(hglob);
2276
2277     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2278     ok(hres == S_OK, "Failed to create a stream\n");
2279     if(hres != S_OK) return;
2280
2281     stat = GdipCreateBitmapFromStream(stream, &bmp);
2282     ok(stat == Ok, "Failed to create a Bitmap\n");
2283     if(stat != Ok){
2284         IStream_Release(stream);
2285         return;
2286     }
2287
2288     /* Bitmap starts at frame 0 */
2289     color = 0xdeadbeef;
2290     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2291     expect(Ok, stat);
2292     expect(0xffffffff, color);
2293
2294     /* Check that we get correct metadata */
2295     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2296     expect(Ok, stat);
2297     expect(1, count);
2298
2299     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2300     expect(Ok, stat);
2301     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2302
2303     count = 12345;
2304     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2305     expect(Ok, stat);
2306     expect(2, count);
2307
2308     /* SelectActiveFrame overwrites our current data */
2309     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2310     expect(Ok, stat);
2311
2312     color = 0xdeadbeef;
2313     GdipBitmapGetPixel(bmp, 0, 0, &color);
2314     expect(Ok, stat);
2315     expect(0xff000000, color);
2316
2317     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2318     expect(Ok, stat);
2319
2320     color = 0xdeadbeef;
2321     GdipBitmapGetPixel(bmp, 0, 0, &color);
2322     expect(Ok, stat);
2323     expect(0xffffffff, color);
2324
2325     /* Write over the image data */
2326     stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2327     expect(Ok, stat);
2328
2329     /* Switching to the same frame does not overwrite our changes */
2330     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2331     expect(Ok, stat);
2332
2333     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2334     expect(Ok, stat);
2335     expect(0xff000000, color);
2336
2337     /* But switching to another frame and back does */
2338     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2339     expect(Ok, stat);
2340
2341     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2342     expect(Ok, stat);
2343
2344     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2345     expect(Ok, stat);
2346     expect(0xffffffff, color);
2347
2348     GdipDisposeImage((GpImage*)bmp);
2349     IStream_Release(stream);
2350
2351     /* Test with a non-animated gif */
2352     hglob = GlobalAlloc (0, sizeof(gifimage));
2353     data = GlobalLock (hglob);
2354     memcpy(data, gifimage, sizeof(gifimage));
2355     GlobalUnlock(hglob);
2356
2357     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2358     ok(hres == S_OK, "Failed to create a stream\n");
2359     if(hres != S_OK) return;
2360
2361     stat = GdipCreateBitmapFromStream(stream, &bmp);
2362     ok(stat == Ok, "Failed to create a Bitmap\n");
2363     if(stat != Ok){
2364         IStream_Release(stream);
2365         return;
2366     }
2367
2368     /* Check metadata */
2369     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2370     expect(Ok, stat);
2371     expect(1, count);
2372
2373     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2374     expect(Ok, stat);
2375     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2376
2377     count = 12345;
2378     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2379     expect(Ok, stat);
2380     expect(1, count);
2381
2382     GdipDisposeImage((GpImage*)bmp);
2383     IStream_Release(stream);
2384 }
2385
2386 static void test_rotateflip(void)
2387 {
2388     GpImage *bitmap;
2389     GpStatus stat;
2390     BYTE bits[24];
2391     static const BYTE orig_bits[24] = {
2392         0,0,0xff,    0,0xff,0,    0xff,0,0,    23,23,23,
2393         0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2394     UINT width, height;
2395     ARGB color;
2396
2397     memcpy(bits, orig_bits, sizeof(bits));
2398     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2399     expect(Ok, stat);
2400
2401     stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2402     expect(Ok, stat);
2403
2404     stat = GdipGetImageWidth(bitmap, &width);
2405     expect(Ok, stat);
2406     stat = GdipGetImageHeight(bitmap, &height);
2407     expect(Ok, stat);
2408     expect(2, width);
2409     expect(3, height);
2410
2411     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2412     expect(Ok, stat);
2413     expect(0xff00ffff, color);
2414
2415     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2416     expect(Ok, stat);
2417     expect(0xffff0000, color);
2418
2419     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2420     expect(Ok, stat);
2421     expect(0xffffff00, color);
2422
2423     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2424     expect(Ok, stat);
2425     expect(0xff0000ff, color);
2426
2427     expect(0, bits[0]);
2428     expect(0, bits[1]);
2429     expect(0xff, bits[2]);
2430
2431     GdipDisposeImage(bitmap);
2432
2433     memcpy(bits, orig_bits, sizeof(bits));
2434     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2435     expect(Ok, stat);
2436
2437     stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2438     expect(Ok, stat);
2439
2440     stat = GdipGetImageWidth(bitmap, &width);
2441     expect(Ok, stat);
2442     stat = GdipGetImageHeight(bitmap, &height);
2443     expect(Ok, stat);
2444     expect(3, width);
2445     expect(2, height);
2446
2447     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2448     expect(Ok, stat);
2449     expect(0xff0000ff, color);
2450
2451     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2452     expect(Ok, stat);
2453     expect(0xffff0000, color);
2454
2455     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2456     expect(Ok, stat);
2457     expect(0xffffff00, color);
2458
2459     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2460     expect(Ok, stat);
2461     expect(0xff00ffff, color);
2462
2463     expect(0, bits[0]);
2464     expect(0, bits[1]);
2465     expect(0xff, bits[2]);
2466
2467     GdipDisposeImage(bitmap);
2468
2469     memcpy(bits, orig_bits, sizeof(bits));
2470     stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2471     expect(Ok, stat);
2472
2473     stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2474     expect(Ok, stat);
2475
2476     stat = GdipGetImageWidth(bitmap, &width);
2477     expect(Ok, stat);
2478     stat = GdipGetImageHeight(bitmap, &height);
2479     expect(Ok, stat);
2480     expect(3, width);
2481     expect(2, height);
2482
2483     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2484     expect(Ok, stat);
2485     expect(0xff00ffff, color);
2486
2487     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2488     expect(Ok, stat);
2489     expect(0xffffff00, color);
2490
2491     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2492     expect(Ok, stat);
2493     expect(0xffff0000, color);
2494
2495     stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2496     expect(Ok, stat);
2497     expect(0xff0000ff, color);
2498
2499     expect(0, bits[0]);
2500     expect(0, bits[1]);
2501     expect(0xff, bits[2]);
2502
2503     GdipDisposeImage(bitmap);
2504 }
2505
2506 static void test_remaptable(void)
2507 {
2508     GpStatus stat;
2509     GpImageAttributes *imageattr;
2510     GpBitmap *bitmap1, *bitmap2;
2511     GpGraphics *graphics;
2512     ARGB color;
2513     ColorMap *map;
2514
2515     map = GdipAlloc(sizeof(ColorMap));
2516
2517     map->oldColor.Argb = 0xff00ff00;
2518     map->newColor.Argb = 0xffff00ff;
2519
2520     stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2521     expect(InvalidParameter, stat);
2522
2523     stat = GdipCreateImageAttributes(&imageattr);
2524     expect(Ok, stat);
2525
2526     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2527     expect(InvalidParameter, stat);
2528
2529     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2530     expect(InvalidParameter, stat);
2531
2532     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2533     expect(InvalidParameter, stat);
2534
2535     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2536     expect(InvalidParameter, stat);
2537
2538     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2539     expect(Ok, stat);
2540
2541     stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2542     expect(Ok, stat);
2543
2544     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2545     expect(Ok, stat);
2546
2547     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2548     expect(Ok, stat);
2549
2550     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2551     expect(Ok, stat);
2552
2553     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2554     expect(Ok, stat);
2555
2556     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2557         UnitPixel, imageattr, NULL, NULL);
2558     expect(Ok, stat);
2559
2560     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2561     expect(Ok, stat);
2562     ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2563
2564     GdipDeleteGraphics(graphics);
2565     GdipDisposeImage((GpImage*)bitmap1);
2566     GdipDisposeImage((GpImage*)bitmap2);
2567     GdipDisposeImageAttributes(imageattr);
2568     GdipFree(map);
2569 }
2570
2571 static void test_colorkey(void)
2572 {
2573     GpStatus stat;
2574     GpImageAttributes *imageattr;
2575     GpBitmap *bitmap1, *bitmap2;
2576     GpGraphics *graphics;
2577     ARGB color;
2578
2579     stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2580     expect(InvalidParameter, stat);
2581
2582     stat = GdipCreateImageAttributes(&imageattr);
2583     expect(Ok, stat);
2584
2585     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2586     expect(InvalidParameter, stat);
2587
2588     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2589     expect(InvalidParameter, stat);
2590
2591     stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2592     expect(Ok, stat);
2593
2594     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2595     expect(Ok, stat);
2596
2597     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2598     expect(Ok, stat);
2599
2600     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2601     expect(Ok, stat);
2602
2603     stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2604     expect(Ok, stat);
2605
2606     stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
2607     expect(Ok, stat);
2608
2609     stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
2610     expect(Ok, stat);
2611
2612     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2613     expect(Ok, stat);
2614
2615     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2616         UnitPixel, imageattr, NULL, NULL);
2617     expect(Ok, stat);
2618
2619     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2620     expect(Ok, stat);
2621     ok(color_match(0x00000000, color, 1), "Expected ffff00ff, got %.8x\n", color);
2622
2623     stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2624     expect(Ok, stat);
2625     ok(color_match(0x00000000, color, 1), "Expected ffff00ff, got %.8x\n", color);
2626
2627     stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2628     expect(Ok, stat);
2629     ok(color_match(0x00000000, color, 1), "Expected ffff00ff, got %.8x\n", color);
2630
2631     stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2632     expect(Ok, stat);
2633     ok(color_match(0xffffffff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2634
2635     GdipDeleteGraphics(graphics);
2636     GdipDisposeImage((GpImage*)bitmap1);
2637     GdipDisposeImage((GpImage*)bitmap2);
2638     GdipDisposeImageAttributes(imageattr);
2639 }
2640
2641 static void test_dispose(void)
2642 {
2643     GpStatus stat;
2644     GpImage *image;
2645     char invalid_image[256];
2646
2647     stat = GdipDisposeImage(NULL);
2648     expect(InvalidParameter, stat);
2649
2650     stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
2651     expect(Ok, stat);
2652
2653     stat = GdipDisposeImage(image);
2654     expect(Ok, stat);
2655
2656     stat = GdipDisposeImage(image);
2657     expect(ObjectBusy, stat);
2658
2659     memset(invalid_image, 0, 256);
2660     stat = GdipDisposeImage((GpImage*)invalid_image);
2661     expect(ObjectBusy, stat);
2662 }
2663
2664 static LONG obj_refcount(void *obj)
2665 {
2666     IUnknown_AddRef((IUnknown *)obj);
2667     return IUnknown_Release((IUnknown *)obj);
2668 }
2669
2670 static GpImage *load_image(const BYTE *image_data, UINT image_size)
2671 {
2672     IStream *stream;
2673     HGLOBAL hmem;
2674     BYTE *data;
2675     HRESULT hr;
2676     GpStatus status;
2677     GpImage *image = NULL;
2678     ImageType image_type;
2679     LONG refcount;
2680
2681     hmem = GlobalAlloc(0, image_size);
2682     data = GlobalLock(hmem);
2683     memcpy(data, image_data, image_size);
2684     GlobalUnlock(hmem);
2685
2686     hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
2687     ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
2688     if (hr != S_OK) return NULL;
2689
2690     refcount = obj_refcount(stream);
2691     ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
2692
2693     status = GdipLoadImageFromStream(stream, &image);
2694     ok(status == Ok, "GdipLoadImageFromStream error %d\n", status);
2695
2696     status = GdipGetImageType(image, &image_type);
2697     ok(status == Ok, "GdipGetImageType error %d\n", status);
2698
2699     refcount = IStream_Release(stream);
2700     if (image_type == ImageTypeBitmap)
2701         ok(refcount >= 1, "expected stream refcount != 0\n");
2702     else
2703         ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
2704
2705     return image;
2706 }
2707
2708 static void test_image_properties(void)
2709 {
2710     static const struct test_data
2711     {
2712         const BYTE *image_data;
2713         UINT image_size;
2714         ImageType image_type;
2715         UINT prop_count;
2716         UINT prop_count2; /* if win7 behaves differently */
2717         /* 1st property attributes */
2718         UINT prop_size;
2719         UINT prop_size2; /* if win7 behaves differently */
2720         UINT prop_id;
2721         UINT prop_id2; /* if win7 behaves differently */
2722     }
2723     td[] =
2724     {
2725         { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
2726         { gifimage, sizeof(gifimage), ImageTypeBitmap, 1, 4, 4, 0, 0x5100, 0 },
2727         { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
2728         { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
2729         { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
2730         { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
2731     };
2732     GpStatus status;
2733     GpImage *image;
2734     UINT prop_count, prop_size, i;
2735     PROPID prop_id[16] = { 0 };
2736     ImageType image_type;
2737     union
2738     {
2739         PropertyItem data;
2740         char buf[256];
2741     } item;
2742
2743     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2744     {
2745         image = load_image(td[i].image_data, td[i].image_size);
2746         ok(image != 0, "%u: failed to load image data\n", i);
2747         if (!image) continue;
2748
2749         status = GdipGetImageType(image, &image_type);
2750         ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
2751         ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
2752            i, td[i].image_type, image_type);
2753
2754         status = GdipGetPropertyCount(image, &prop_count);
2755         ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
2756         if (td[i].image_data == pngimage || td[i].image_data == gifimage ||
2757             td[i].image_data == jpgimage)
2758         todo_wine
2759         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
2760            " %u: expected property count %u or %u, got %u\n",
2761            i, td[i].prop_count, td[i].prop_count2, prop_count);
2762         else
2763         ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
2764            " %u: expected property count %u or %u, got %u\n",
2765            i, td[i].prop_count, td[i].prop_count2, prop_count);
2766
2767         status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
2768         expect(InvalidParameter, status);
2769         status = GdipGetPropertyItemSize(image, 0, NULL);
2770         expect(InvalidParameter, status);
2771         status = GdipGetPropertyItemSize(image, 0, &prop_size);
2772         if (image_type == ImageTypeMetafile)
2773             expect(NotImplemented, status);
2774         else
2775             expect(PropertyNotFound, status);
2776
2777         status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
2778         expect(InvalidParameter, status);
2779         status = GdipGetPropertyItem(image, 0, 0, NULL);
2780         expect(InvalidParameter, status);
2781         status = GdipGetPropertyItem(image, 0, 0, &item.data);
2782         if (image_type == ImageTypeMetafile)
2783             expect(NotImplemented, status);
2784         else
2785             expect(PropertyNotFound, status);
2786
2787         /* FIXME: remove once Wine is fixed */
2788         if (td[i].prop_count != prop_count)
2789         {
2790             GdipDisposeImage(image);
2791             continue;
2792         }
2793
2794         status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
2795         expect(InvalidParameter, status);
2796         status = GdipGetPropertyIdList(image, prop_count, NULL);
2797         expect(InvalidParameter, status);
2798         status = GdipGetPropertyIdList(image, 0, prop_id);
2799         if (image_type == ImageTypeMetafile)
2800             expect(NotImplemented, status);
2801         else if (prop_count == 0)
2802             expect(Ok, status);
2803         else
2804             expect(InvalidParameter, status);
2805         status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
2806         if (image_type == ImageTypeMetafile)
2807             expect(NotImplemented, status);
2808         else
2809             expect(InvalidParameter, status);
2810         status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
2811         if (image_type == ImageTypeMetafile)
2812             expect(NotImplemented, status);
2813         else
2814             expect(InvalidParameter, status);
2815         status = GdipGetPropertyIdList(image, prop_count, prop_id);
2816         if (image_type == ImageTypeMetafile)
2817             expect(NotImplemented, status);
2818         else
2819         {
2820             expect(Ok, status);
2821             if (prop_count != 0)
2822                 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
2823                    " %u: expected property id %#x or %#x, got %#x\n",
2824                    i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
2825         }
2826
2827         if (status == Ok)
2828         {
2829             status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
2830             if (prop_count == 0)
2831                 expect(PropertyNotFound, status);
2832             else
2833             {
2834                 expect(Ok, status);
2835
2836                 assert(sizeof(item) >= prop_size);
2837                 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
2838                    i, prop_size);
2839                 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
2840                    td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
2841                    " %u: expected property size %u or %u, got %u\n",
2842                    i, td[i].prop_size, td[i].prop_size2, prop_size);
2843
2844                 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
2845                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2846                    "%u: expected InvalidParameter, got %d\n", i, status);
2847                 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
2848                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2849                    "%u: expected InvalidParameter, got %d\n", i, status);
2850                 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
2851                 ok(status == InvalidParameter || status == GenericError /* Win7 */,
2852                    "%u: expected InvalidParameter, got %d\n", i, status);
2853                 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
2854                 expect(Ok, status);
2855                 ok(prop_id[0] == item.data.id,
2856                    "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
2857             }
2858         }
2859
2860         GdipDisposeImage(image);
2861     }
2862 }
2863
2864 #define IFD_BYTE      1
2865 #define IFD_ASCII     2
2866 #define IFD_SHORT     3
2867 #define IFD_LONG      4
2868 #define IFD_RATIONAL  5
2869 #define IFD_SBYTE     6
2870 #define IFD_UNDEFINED 7
2871 #define IFD_SSHORT    8
2872 #define IFD_SLONG     9
2873 #define IFD_SRATIONAL 10
2874 #define IFD_FLOAT     11
2875 #define IFD_DOUBLE    12
2876
2877 #ifndef PropertyTagTypeSByte
2878 #define PropertyTagTypeSByte  6
2879 #define PropertyTagTypeSShort 8
2880 #define PropertyTagTypeFloat  11
2881 #define PropertyTagTypeDouble 12
2882 #endif
2883
2884 static UINT documented_type(UINT type)
2885 {
2886     switch (type)
2887     {
2888     case PropertyTagTypeSByte: return PropertyTagTypeByte;
2889     case PropertyTagTypeSShort: return PropertyTagTypeShort;
2890     case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
2891     case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
2892     default: return type;
2893     }
2894 }
2895
2896 #include "pshpack2.h"
2897 struct IFD_entry
2898 {
2899     SHORT id;
2900     SHORT type;
2901     ULONG count;
2902     LONG  value;
2903 };
2904
2905 struct IFD_rational
2906 {
2907     LONG numerator;
2908     LONG denominator;
2909 };
2910
2911 static const struct tiff_data
2912 {
2913     USHORT byte_order;
2914     USHORT version;
2915     ULONG  dir_offset;
2916     USHORT number_of_entries;
2917     struct IFD_entry entry[40];
2918     ULONG next_IFD;
2919     struct IFD_rational xres;
2920     DOUBLE double_val;
2921     struct IFD_rational srational_val;
2922     char string[14];
2923     SHORT short_val[4];
2924     LONG long_val[2];
2925     FLOAT float_val[2];
2926     struct IFD_rational rational[3];
2927     BYTE pixel_data[4];
2928 } TIFF_data =
2929 {
2930 #ifdef WORDS_BIGENDIAN
2931     'M' | 'M' << 8,
2932 #else
2933     'I' | 'I' << 8,
2934 #endif
2935     42,
2936     FIELD_OFFSET(struct tiff_data, number_of_entries),
2937     31,
2938     {
2939         { 0xff,  IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
2940         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
2941         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
2942         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
2943         { 0x103, IFD_LONG, 1, 1 }, /* COMPRESSION */
2944         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
2945         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
2946         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
2947         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
2948         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
2949         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
2950         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
2951         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
2952         { 0xf001, IFD_BYTE, 1, 0x11223344 },
2953         { 0xf002, IFD_BYTE, 4, 0x11223344 },
2954         { 0xf003, IFD_SBYTE, 1, 0x11223344 },
2955         { 0xf004, IFD_SSHORT, 1, 0x11223344 },
2956         { 0xf005, IFD_SSHORT, 2, 0x11223344 },
2957         { 0xf006, IFD_SLONG, 1, 0x11223344 },
2958         { 0xf007, IFD_FLOAT, 1, 0x11223344 },
2959         { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
2960         { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
2961         { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
2962         { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
2963         { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
2964         { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
2965         { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
2966         { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
2967         { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
2968         /* Some gdiplus versions ignore these fields.
2969         { 0xf012, IFD_BYTE, 0, 0x11223344 },
2970         { 0xf013, IFD_SHORT, 0, 0x11223344 },
2971         { 0xf014, IFD_LONG, 0, 0x11223344 },
2972         { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
2973         { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
2974         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
2975         { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
2976     },
2977     0,
2978     { 900, 3 },
2979     1234567890.0987654321,
2980     { 0x1a2b3c4d, 0x5a6b7c8d },
2981     "Hello World!",
2982     { 0x0101, 0x0202, 0x0303, 0x0404 },
2983     { 0x11223344, 0x55667788 },
2984     { (FLOAT)1234.5678, (FLOAT)8765.4321 },
2985     { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
2986     { 0x11, 0x22, 0x33, 0 }
2987 };
2988 #include "poppack.h"
2989
2990 static void test_tiff_properties(void)
2991 {
2992     static const struct test_data
2993     {
2994         ULONG type, id, length;
2995         const BYTE value[24];
2996     } td[31] =
2997     {
2998         { PropertyTagTypeShort, 0xff, 2, { 0 } },
2999         { PropertyTagTypeLong, 0x100, 4, { 1 } },
3000         { PropertyTagTypeLong, 0x101, 4, { 1 } },
3001         { PropertyTagTypeShort, 0x102, 2, { 1 } },
3002         { PropertyTagTypeLong, 0x103, 4, { 1 } },
3003         { PropertyTagTypeShort, 0x106, 2, { 1 } },
3004         { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3005         { PropertyTagTypeShort, 0x115, 2, { 1 } },
3006         { PropertyTagTypeLong, 0x116, 4, { 1 } },
3007         { PropertyTagTypeLong, 0x117, 4, { 1 } },
3008         { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3009         { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3010         { PropertyTagTypeShort, 0x128, 2, { 2 } },
3011         { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3012         { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3013         { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3014         { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3015         { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3016         { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3017         { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3018         { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3019         { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3020         { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3021         { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3022         { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3023         { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3024         { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3025         { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3026         { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3027         { PropertyTagTypeSRational, 0xf016, 24,
3028           { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3029             0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3030             0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3031         /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3032         { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3033     };
3034     GpStatus status;
3035     GpImage *image;
3036     GUID guid;
3037     UINT dim_count, frame_count, prop_count, prop_size, i;
3038     PROPID *prop_id;
3039     PropertyItem *prop_item;
3040
3041     image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3042     ok(image != 0, "Failed to load TIFF image data\n");
3043     if (!image) return;
3044
3045     status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3046     expect(Ok, status);
3047     expect(1, dim_count);
3048
3049     status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3050     expect(Ok, status);
3051     expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3052
3053     frame_count = 0xdeadbeef;
3054     status = GdipImageGetFrameCount(image, &guid, &frame_count);
3055     expect(Ok, status);
3056     expect(1, frame_count);
3057
3058     prop_count = 0xdeadbeef;
3059     status = GdipGetPropertyCount(image, &prop_count);
3060     expect(Ok, status);
3061     ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3062        broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3063        "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3064
3065     prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3066
3067     status = GdipGetPropertyIdList(image, prop_count, prop_id);
3068     expect(Ok, status);
3069
3070     for (i = 0; i < prop_count; i++)
3071     {
3072         status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3073         expect(Ok, status);
3074         if (status != Ok) break;
3075         ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3076
3077         prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3078         status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3079         expect(Ok, status);
3080         ok(td[i].type == prop_item->type ||
3081            /* Win7 stopped using proper but not documented types, and it's
3082               looks broken since TypeFloat and TypeDouble now reported as
3083               TypeUndefined, and signed types reported as unsigned. */
3084            broken(prop_item->type == documented_type(td[i].type)),
3085             "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3086         ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3087         prop_size -= sizeof(*prop_item);
3088         ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3089         ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3090         ok(td[i].length == prop_size, "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3091         if (td[i].length == prop_item->length)
3092         {
3093             int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3094             ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3095             if (!match)
3096             {
3097                 UINT j;
3098                 BYTE *data = prop_item->value;
3099                 printf("id %#x:", prop_item->id);
3100                 for (j = 0; j < prop_item->length; j++)
3101                     printf(" %02x", data[j]);
3102                 printf("\n");
3103             }
3104         }
3105         HeapFree(GetProcessHeap(), 0, prop_item);
3106     }
3107
3108     HeapFree(GetProcessHeap(), 0, prop_id);
3109
3110     GdipDisposeImage(image);
3111 }
3112
3113 START_TEST(image)
3114 {
3115     struct GdiplusStartupInput gdiplusStartupInput;
3116     ULONG_PTR gdiplusToken;
3117
3118     gdiplusStartupInput.GdiplusVersion              = 1;
3119     gdiplusStartupInput.DebugEventCallback          = NULL;
3120     gdiplusStartupInput.SuppressBackgroundThread    = 0;
3121     gdiplusStartupInput.SuppressExternalCodecs      = 0;
3122
3123     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
3124
3125     test_tiff_properties();
3126     test_image_properties();
3127     test_Scan0();
3128     test_FromGdiDib();
3129     test_GetImageDimension();
3130     test_GdipImageGetFrameDimensionsCount();
3131     test_LoadingImages();
3132     test_SavingImages();
3133     test_encoders();
3134     test_LockBits();
3135     test_LockBits_UserBuf();
3136     test_GdipCreateBitmapFromHBITMAP();
3137     test_GdipGetImageFlags();
3138     test_GdipCloneImage();
3139     test_testcontrol();
3140     test_fromhicon();
3141     test_getrawformat();
3142     test_loadwmf();
3143     test_createfromwmf();
3144     test_resolution();
3145     test_createhbitmap();
3146     test_getthumbnail();
3147     test_getsetpixel();
3148     test_palette();
3149     test_colormatrix();
3150     test_gamma();
3151     test_multiframegif();
3152     test_rotateflip();
3153     test_remaptable();
3154     test_colorkey();
3155     test_dispose();
3156
3157     GdiplusShutdown(gdiplusToken);
3158 }