gdiplus: Implement GdipGetImage*Resolution.
[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
25 #include "initguid.h"
26 #include "windows.h"
27 #include "gdiplus.h"
28 #include "wine/test.h"
29
30 #define expect(expected, got) ok((UINT)(got) == (UINT)(expected), "Expected %.8x, got %.8x\n", (UINT)(expected), (UINT)(got))
31 #define expectf(expected, got) ok(fabs(expected - got) < 0.0001, "Expected %.2f, got %.2f\n", expected, got)
32
33 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
34 {
35     WCHAR bufferW[39];
36     char buffer[39];
37     char buffer2[39];
38
39     StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
40     WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
41     StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
42     WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
43     if(todo)
44         todo_wine ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
45     else
46         ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
47 }
48
49 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
50 {
51     GUID raw;
52     GpStatus stat;
53
54     stat = GdipGetImageRawFormat(img, &raw);
55     ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
56     if(stat != Ok) return;
57     expect_guid(expected, &raw, line, todo);
58 }
59
60 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
61 {
62     LPSTREAM stream;
63     HGLOBAL  hglob;
64     LPBYTE   data;
65     HRESULT  hres;
66     GpStatus stat;
67     GpImage *img;
68
69     hglob = GlobalAlloc (0, size);
70     data = GlobalLock (hglob);
71     memcpy(data, buff, size);
72     GlobalUnlock(hglob); data = NULL;
73
74     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
75     ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
76     if(hres != S_OK) return;
77
78     stat = GdipLoadImageFromStream(stream, &img);
79     ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
80     if(stat != Ok){
81         IStream_Release(stream);
82         return;
83     }
84
85     expect_rawformat(expected, img, line, todo);
86
87     GdipDisposeImage(img);
88     IStream_Release(stream);
89 }
90
91 static void test_Scan0(void)
92 {
93     GpBitmap *bm;
94     GpStatus stat;
95     BYTE buff[360];
96
97     bm = NULL;
98     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
99     expect(Ok, stat);
100     ok(NULL != bm, "Expected bitmap to be initialized\n");
101     if (stat == Ok)
102         GdipDisposeImage((GpImage*)bm);
103
104     bm = (GpBitmap*)0xdeadbeef;
105     stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
106     expect(InvalidParameter, stat);
107     ok( !bm, "expected null bitmap\n" );
108
109     bm = (GpBitmap*)0xdeadbeef;
110     stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
111     expect(InvalidParameter, stat);
112     ok( !bm, "expected null bitmap\n" );
113
114     bm = (GpBitmap*)0xdeadbeef;
115     stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
116     expect(InvalidParameter, stat);
117     ok( !bm, "expected null bitmap\n" );
118
119     bm = NULL;
120     stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
121     expect(Ok, stat);
122     ok(NULL != bm, "Expected bitmap to be initialized\n");
123     if (stat == Ok)
124         GdipDisposeImage((GpImage*)bm);
125
126     bm = (GpBitmap*) 0xdeadbeef;
127     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
128     expect(InvalidParameter, stat);
129     ok( !bm, "expected null bitmap\n" );
130
131     bm = (GpBitmap*)0xdeadbeef;
132     stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
133     expect(InvalidParameter, stat);
134     ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
135
136     bm = NULL;
137     stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
138     expect(Ok, stat);
139     ok(NULL != bm, "Expected bitmap to be initialized\n");
140     if (stat == Ok)
141         GdipDisposeImage((GpImage*)bm);
142
143     bm = (GpBitmap*)0xdeadbeef;
144     stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
145     expect(InvalidParameter, stat);
146     ok( !bm, "expected null bitmap\n" );
147 }
148
149 static void test_GetImageDimension(void)
150 {
151     GpBitmap *bm;
152     GpStatus stat;
153     const REAL WIDTH = 10.0, HEIGHT = 20.0;
154     REAL w,h;
155
156     bm = (GpBitmap*)0xdeadbeef;
157     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
158     expect(Ok,stat);
159     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
160     ok(NULL != bm, "Expected bitmap to not be NULL\n");
161
162     stat = GdipGetImageDimension(NULL,&w,&h);
163     expect(InvalidParameter, stat);
164
165     stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
166     expect(InvalidParameter, stat);
167
168     stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
169     expect(InvalidParameter, stat);
170
171     w = -1;
172     h = -1;
173     stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
174     expect(Ok, stat);
175     expectf(WIDTH,  w);
176     expectf(HEIGHT, h);
177     GdipDisposeImage((GpImage*)bm);
178 }
179
180 static void test_GdipImageGetFrameDimensionsCount(void)
181 {
182     GpBitmap *bm;
183     GpStatus stat;
184     const REAL WIDTH = 10.0, HEIGHT = 20.0;
185     UINT w;
186     GUID dimension = {0};
187     UINT count;
188     ARGB color;
189
190     bm = (GpBitmap*)0xdeadbeef;
191     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
192     expect(Ok,stat);
193     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
194     ok(NULL != bm, "Expected bitmap to not be NULL\n");
195
196     stat = GdipImageGetFrameDimensionsCount(NULL,&w);
197     expect(InvalidParameter, stat);
198
199     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
200     expect(InvalidParameter, stat);
201
202     w = -1;
203     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
204     expect(Ok, stat);
205     expect(1, w);
206
207     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
208     expect(Ok, stat);
209     expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
210
211     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
212     expect(InvalidParameter, stat);
213
214     stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
215     expect(InvalidParameter, stat);
216
217     count = 12345;
218     stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
219     todo_wine expect(Ok, stat);
220     todo_wine expect(1, count);
221
222     GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
223
224     stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
225     expect(Ok, stat);
226
227     /* SelectActiveFrame has no effect on image data of memory bitmaps */
228     color = 0xdeadbeef;
229     GdipBitmapGetPixel(bm, 0, 0, &color);
230     expect(0xffffffff, color);
231
232     GdipDisposeImage((GpImage*)bm);
233 }
234
235 static void test_LoadingImages(void)
236 {
237     GpStatus stat;
238
239     stat = GdipCreateBitmapFromFile(0, 0);
240     expect(InvalidParameter, stat);
241
242     stat = GdipCreateBitmapFromFile(0, (GpBitmap**)0xdeadbeef);
243     expect(InvalidParameter, stat);
244
245     stat = GdipLoadImageFromFile(0, 0);
246     expect(InvalidParameter, stat);
247
248     stat = GdipLoadImageFromFile(0, (GpImage**)0xdeadbeef);
249     expect(InvalidParameter, stat);
250
251     stat = GdipLoadImageFromFileICM(0, 0);
252     expect(InvalidParameter, stat);
253
254     stat = GdipLoadImageFromFileICM(0, (GpImage**)0xdeadbeef);
255     expect(InvalidParameter, stat);
256 }
257
258 static void test_SavingImages(void)
259 {
260     GpStatus stat;
261     GpBitmap *bm;
262     UINT n;
263     UINT s;
264     const REAL WIDTH = 10.0, HEIGHT = 20.0;
265     REAL w, h;
266     ImageCodecInfo *codecs;
267     static const CHAR filenameA[] = "a.bmp";
268     static const WCHAR filename[] = { 'a','.','b','m','p',0 };
269
270     codecs = NULL;
271
272     stat = GdipSaveImageToFile(0, 0, 0, 0);
273     expect(InvalidParameter, stat);
274
275     bm = NULL;
276     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
277     expect(Ok, stat);
278     if (!bm)
279         return;
280
281     /* invalid params */
282     stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
283     expect(InvalidParameter, stat);
284
285     stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
286     expect(InvalidParameter, stat);
287
288     /* encoder tests should succeed -- already tested */
289     stat = GdipGetImageEncodersSize(&n, &s);
290     if (stat != Ok || n == 0) goto cleanup;
291
292     codecs = GdipAlloc(s);
293     if (!codecs) goto cleanup;
294
295     stat = GdipGetImageEncoders(n, s, codecs);
296     if (stat != Ok) goto cleanup;
297
298     stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
299     expect(stat, Ok);
300
301     GdipDisposeImage((GpImage*)bm);
302     bm = 0;
303
304     /* re-load and check image stats */
305     stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
306     expect(stat, Ok);
307     if (stat != Ok) goto cleanup;
308
309     stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
310     if (stat != Ok) goto cleanup;
311
312     expectf(WIDTH, w);
313     expectf(HEIGHT, h);
314
315  cleanup:
316     GdipFree(codecs);
317     if (bm)
318         GdipDisposeImage((GpImage*)bm);
319     ok(DeleteFileA(filenameA), "Delete failed.\n");
320 }
321
322 static void test_encoders(void)
323 {
324     GpStatus stat;
325     UINT n;
326     UINT s;
327     ImageCodecInfo *codecs;
328     int i;
329     int bmp_found;
330
331     static const CHAR bmp_format[] = "BMP";
332
333     stat = GdipGetImageEncodersSize(&n, &s);
334     expect(stat, Ok);
335
336     codecs = GdipAlloc(s);
337     if (!codecs)
338         return;
339
340     stat = GdipGetImageEncoders(n, s, NULL);
341     expect(GenericError, stat);
342
343     stat = GdipGetImageEncoders(0, s, codecs);
344     expect(GenericError, stat);
345
346     stat = GdipGetImageEncoders(n, s-1, codecs);
347     expect(GenericError, stat);
348
349     stat = GdipGetImageEncoders(n, s+1, codecs);
350     expect(GenericError, stat);
351
352     stat = GdipGetImageEncoders(n, s, codecs);
353     expect(stat, Ok);
354
355     bmp_found = FALSE;
356     for (i = 0; i < n; i++)
357         {
358             CHAR desc[32];
359
360             WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
361                                 desc, 32, 0, 0);
362
363             if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
364                                desc, -1,
365                                bmp_format, -1) == CSTR_EQUAL) {
366                 bmp_found = TRUE;
367                 break;
368             }
369         }
370     if (!bmp_found)
371         ok(FALSE, "No BMP codec found.\n");
372
373     GdipFree(codecs);
374 }
375
376 static void test_LockBits(void)
377 {
378     GpStatus stat;
379     GpBitmap *bm;
380     GpRect rect;
381     BitmapData bd;
382     const INT WIDTH = 10, HEIGHT = 20;
383
384     bm = NULL;
385     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
386     expect(Ok, stat);
387
388     rect.X = 2;
389     rect.Y = 3;
390     rect.Width = 4;
391     rect.Height = 5;
392
393     /* read-only */
394     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
395     expect(Ok, stat);
396
397     if (stat == Ok) {
398         stat = GdipBitmapUnlockBits(bm, &bd);
399         expect(Ok, stat);
400     }
401
402     /* read-only, with NULL rect -> whole bitmap lock */
403     stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
404     expect(Ok, stat);
405     expect(bd.Width,  WIDTH);
406     expect(bd.Height, HEIGHT);
407
408     if (stat == Ok) {
409         stat = GdipBitmapUnlockBits(bm, &bd);
410         expect(Ok, stat);
411     }
412
413     /* read-only, consecutive */
414     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
415     expect(Ok, stat);
416
417     if (stat == Ok) {
418         stat = GdipBitmapUnlockBits(bm, &bd);
419         expect(Ok, stat);
420     }
421
422     stat = GdipDisposeImage((GpImage*)bm);
423     expect(Ok, stat);
424     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
425     expect(Ok, stat);
426
427     /* read x2 */
428     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
429     expect(Ok, stat);
430     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
431     expect(WrongState, stat);
432
433     stat = GdipBitmapUnlockBits(bm, &bd);
434     expect(Ok, stat);
435
436     stat = GdipDisposeImage((GpImage*)bm);
437     expect(Ok, stat);
438     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
439     expect(Ok, stat);
440
441     /* write, no modification */
442     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
443     expect(Ok, stat);
444
445     if (stat == Ok) {
446         stat = GdipBitmapUnlockBits(bm, &bd);
447         expect(Ok, stat);
448     }
449
450     /* write, consecutive */
451     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
452     expect(Ok, stat);
453
454     if (stat == Ok) {
455         stat = GdipBitmapUnlockBits(bm, &bd);
456         expect(Ok, stat);
457     }
458
459     stat = GdipDisposeImage((GpImage*)bm);
460     expect(Ok, stat);
461     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
462     expect(Ok, stat);
463
464     /* write, modify */
465     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
466     expect(Ok, stat);
467
468     if (stat == Ok) {
469         if (bd.Scan0)
470             ((char*)bd.Scan0)[2] = 0xff;
471
472         stat = GdipBitmapUnlockBits(bm, &bd);
473         expect(Ok, stat);
474     }
475
476     stat = GdipDisposeImage((GpImage*)bm);
477     expect(Ok, stat);
478
479     /* dispose locked */
480     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
481     expect(Ok, stat);
482     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
483     expect(Ok, stat);
484     stat = GdipDisposeImage((GpImage*)bm);
485     expect(Ok, stat);
486 }
487
488 static void test_GdipCreateBitmapFromHBITMAP(void)
489 {
490     GpBitmap* gpbm = NULL;
491     HBITMAP hbm = NULL;
492     HPALETTE hpal = NULL;
493     GpStatus stat;
494     BYTE buff[1000];
495     LOGPALETTE* LogPal = NULL;
496     REAL width, height;
497     const REAL WIDTH1 = 5;
498     const REAL HEIGHT1 = 15;
499     const REAL WIDTH2 = 10;
500     const REAL HEIGHT2 = 20;
501     HDC hdc;
502     BITMAPINFO bmi;
503     BYTE *bits;
504
505     stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
506     expect(InvalidParameter, stat);
507
508     hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
509     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
510     expect(InvalidParameter, stat);
511
512     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
513     expect(Ok, stat);
514     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
515     expectf(WIDTH1,  width);
516     expectf(HEIGHT1, height);
517     if (stat == Ok)
518         GdipDisposeImage((GpImage*)gpbm);
519     DeleteObject(hbm);
520
521     hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
522     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
523     expect(Ok, stat);
524     /* raw format */
525     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
526
527     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
528     expectf(WIDTH2,  width);
529     expectf(HEIGHT2, height);
530     if (stat == Ok)
531         GdipDisposeImage((GpImage*)gpbm);
532     DeleteObject(hbm);
533
534     hdc = CreateCompatibleDC(0);
535     ok(hdc != NULL, "CreateCompatibleDC failed\n");
536     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
537     bmi.bmiHeader.biHeight = HEIGHT1;
538     bmi.bmiHeader.biWidth = WIDTH1;
539     bmi.bmiHeader.biBitCount = 24;
540     bmi.bmiHeader.biPlanes = 1;
541     bmi.bmiHeader.biCompression = BI_RGB;
542
543     hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
544     ok(hbm != NULL, "CreateDIBSection failed\n");
545
546     bits[0] = 0;
547
548     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
549     expect(Ok, stat);
550     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
551     expectf(WIDTH1,  width);
552     expectf(HEIGHT1, height);
553     if (stat == Ok)
554     {
555         /* test whether writing to the bitmap affects the original */
556         stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
557         expect(Ok, stat);
558
559         expect(0, bits[0]);
560
561         GdipDisposeImage((GpImage*)gpbm);
562     }
563
564     LogPal = GdipAlloc(sizeof(LOGPALETTE));
565     ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
566     LogPal->palVersion = 0x300;
567     LogPal->palNumEntries = 1;
568     hpal = CreatePalette(LogPal);
569     ok(hpal != NULL, "CreatePalette failed\n");
570     GdipFree(LogPal);
571
572     stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
573     todo_wine
574     {
575         expect(Ok, stat);
576     }
577     if (stat == Ok)
578         GdipDisposeImage((GpImage*)gpbm);
579
580     DeleteObject(hpal);
581     DeleteObject(hbm);
582 }
583
584 static void test_GdipGetImageFlags(void)
585 {
586     GpImage *img;
587     GpStatus stat;
588     UINT flags;
589
590     img = (GpImage*)0xdeadbeef;
591
592     stat = GdipGetImageFlags(NULL, NULL);
593     expect(InvalidParameter, stat);
594
595     stat = GdipGetImageFlags(NULL, &flags);
596     expect(InvalidParameter, stat);
597
598     stat = GdipGetImageFlags(img, NULL);
599     expect(InvalidParameter, stat);
600 }
601
602 static void test_GdipCloneImage(void)
603 {
604     GpStatus stat;
605     GpRectF rectF;
606     GpUnit unit;
607     GpBitmap *bm;
608     GpImage *image_src, *image_dest = NULL;
609     const INT WIDTH = 10, HEIGHT = 20;
610
611     /* Create an image, clone it, delete the original, make sure the copy works */
612     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
613     expect(Ok, stat);
614     expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
615
616     image_src = ((GpImage*)bm);
617     stat = GdipCloneImage(image_src, &image_dest);
618     expect(Ok, stat);
619     expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
620
621     stat = GdipDisposeImage((GpImage*)bm);
622     expect(Ok, stat);
623     stat = GdipGetImageBounds(image_dest, &rectF, &unit);
624     expect(Ok, stat);
625
626     /* Treat FP values carefully */
627     expectf((REAL)WIDTH, rectF.Width);
628     expectf((REAL)HEIGHT, rectF.Height);
629
630     stat = GdipDisposeImage(image_dest);
631     expect(Ok, stat);
632 }
633
634 static void test_testcontrol(void)
635 {
636     GpStatus stat;
637     DWORD param;
638
639     param = 0;
640     stat = GdipTestControl(TestControlGetBuildNumber, &param);
641     expect(Ok, stat);
642     ok(param != 0, "Build number expected, got %u\n", param);
643 }
644
645 static void test_fromhicon(void)
646 {
647     static const BYTE bmp_bits[1024];
648     HBITMAP hbmMask, hbmColor;
649     ICONINFO info;
650     HICON hIcon;
651     GpStatus stat;
652     GpBitmap *bitmap = NULL;
653     UINT dim;
654     ImageType type;
655     PixelFormat format;
656
657     /* NULL */
658     stat = GdipCreateBitmapFromHICON(NULL, NULL);
659     expect(InvalidParameter, stat);
660     stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
661     expect(InvalidParameter, stat);
662
663     /* color icon 1 bit */
664     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
665     ok(hbmMask != 0, "CreateBitmap failed\n");
666     hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
667     ok(hbmColor != 0, "CreateBitmap failed\n");
668     info.fIcon = TRUE;
669     info.xHotspot = 8;
670     info.yHotspot = 8;
671     info.hbmMask = hbmMask;
672     info.hbmColor = hbmColor;
673     hIcon = CreateIconIndirect(&info);
674     ok(hIcon != 0, "CreateIconIndirect failed\n");
675     DeleteObject(hbmMask);
676     DeleteObject(hbmColor);
677
678     stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
679     ok(stat == Ok ||
680        broken(stat == InvalidParameter), /* Win98 */
681        "Expected Ok, got %.8x\n", stat);
682     if(stat == Ok){
683        /* check attributes */
684        stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
685        expect(Ok, stat);
686        expect(16, dim);
687        stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
688        expect(Ok, stat);
689        expect(16, dim);
690        stat = GdipGetImageType((GpImage*)bitmap, &type);
691        expect(Ok, stat);
692        expect(ImageTypeBitmap, type);
693        stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
694        expect(PixelFormat32bppARGB, format);
695        /* raw format */
696        expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
697        GdipDisposeImage((GpImage*)bitmap);
698     }
699     DestroyIcon(hIcon);
700
701     /* color icon 8 bpp */
702     hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
703     ok(hbmMask != 0, "CreateBitmap failed\n");
704     hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
705     ok(hbmColor != 0, "CreateBitmap failed\n");
706     info.fIcon = TRUE;
707     info.xHotspot = 8;
708     info.yHotspot = 8;
709     info.hbmMask = hbmMask;
710     info.hbmColor = hbmColor;
711     hIcon = CreateIconIndirect(&info);
712     ok(hIcon != 0, "CreateIconIndirect failed\n");
713     DeleteObject(hbmMask);
714     DeleteObject(hbmColor);
715
716     stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
717     expect(Ok, stat);
718     if(stat == Ok){
719         /* check attributes */
720         stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
721         expect(Ok, stat);
722         expect(16, dim);
723         stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
724         expect(Ok, stat);
725         expect(16, dim);
726         stat = GdipGetImageType((GpImage*)bitmap, &type);
727         expect(Ok, stat);
728         expect(ImageTypeBitmap, type);
729         stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
730         expect(PixelFormat32bppARGB, format);
731         /* raw format */
732         expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
733         GdipDisposeImage((GpImage*)bitmap);
734     }
735     DestroyIcon(hIcon);
736 }
737
738 /* 1x1 pixel png */
739 static const unsigned char pngimage[285] = {
740 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
741 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
742 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
743 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
744 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
745 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
746 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
747 };
748 /* 1x1 pixel gif */
749 static const unsigned char gifimage[35] = {
750 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
751 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
752 0x01,0x00,0x3b
753 };
754 /* 1x1 pixel bmp */
755 static const unsigned char bmpimage[66] = {
756 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
757 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
758 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
759 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
760 0x00,0x00
761 };
762 /* 1x1 pixel jpg */
763 static const unsigned char jpgimage[285] = {
764 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
765 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
766 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
767 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
768 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
769 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
770 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
771 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
772 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
773 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
774 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
775 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
776 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
777 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
778 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
779 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
780 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
781 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
782 };
783 /* 320x320 twip wmf */
784 static const unsigned char wmfimage[180] = {
785 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
786 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
787 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
788 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
789 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
790 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
791 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
792 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
793 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
794 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
795 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
796 0x00,0x00,0x00,0x00
797 };
798 static void test_getrawformat(void)
799 {
800     test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG,  __LINE__, FALSE);
801     test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF,  __LINE__, FALSE);
802     test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP,  __LINE__, FALSE);
803     test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
804     test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
805 }
806
807 static void test_loadwmf(void)
808 {
809     LPSTREAM stream;
810     HGLOBAL  hglob;
811     LPBYTE   data;
812     HRESULT  hres;
813     GpStatus stat;
814     GpImage *img;
815     GpRectF bounds;
816     GpUnit unit;
817     REAL res = 12345.0;
818
819     hglob = GlobalAlloc (0, sizeof(wmfimage));
820     data = GlobalLock (hglob);
821     memcpy(data, wmfimage, sizeof(wmfimage));
822     GlobalUnlock(hglob); data = NULL;
823
824     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
825     ok(hres == S_OK, "Failed to create a stream\n");
826     if(hres != S_OK) return;
827
828     stat = GdipLoadImageFromStream(stream, &img);
829     ok(stat == Ok, "Failed to create a Bitmap\n");
830     if(stat != Ok){
831         IStream_Release(stream);
832         return;
833     }
834
835     IStream_Release(stream);
836
837     stat = GdipGetImageBounds(img, &bounds, &unit);
838     expect(Ok, stat);
839     todo_wine expect(UnitPixel, unit);
840     expectf(0.0, bounds.X);
841     expectf(0.0, bounds.Y);
842     todo_wine expectf(320.0, bounds.Width);
843     todo_wine expectf(320.0, bounds.Height);
844
845     stat = GdipGetImageHorizontalResolution(img, &res);
846     expect(Ok, stat);
847     todo_wine expectf(1440.0, res);
848
849     stat = GdipGetImageVerticalResolution(img, &res);
850     expect(Ok, stat);
851     todo_wine expectf(1440.0, res);
852
853     GdipDisposeImage(img);
854 }
855
856 static void test_createfromwmf(void)
857 {
858     HMETAFILE hwmf;
859     GpImage *img;
860     GpStatus stat;
861     GpRectF bounds;
862     GpUnit unit;
863     REAL res = 12345.0;
864
865     hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
866         wmfimage+sizeof(WmfPlaceableFileHeader));
867     ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
868
869     stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
870         (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
871     expect(Ok, stat);
872
873     stat = GdipGetImageBounds(img, &bounds, &unit);
874     expect(Ok, stat);
875     todo_wine expect(UnitPixel, unit);
876     expectf(0.0, bounds.X);
877     expectf(0.0, bounds.Y);
878     todo_wine expectf(320.0, bounds.Width);
879     todo_wine expectf(320.0, bounds.Height);
880
881     stat = GdipGetImageHorizontalResolution(img, &res);
882     expect(Ok, stat);
883     expectf(1440.0, res);
884
885     stat = GdipGetImageVerticalResolution(img, &res);
886     expect(Ok, stat);
887     expectf(1440.0, res);
888
889     GdipDisposeImage(img);
890 }
891
892 static void test_resolution(void)
893 {
894     GpStatus stat;
895     GpBitmap *bitmap;
896     REAL res=-1.0;
897     HDC screendc;
898     int screenxres, screenyres;
899
900     /* create Bitmap */
901     stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
902     expect(Ok, stat);
903
904     /* test invalid values */
905     stat = GdipGetImageHorizontalResolution(NULL, &res);
906     expect(InvalidParameter, stat);
907
908     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
909     expect(InvalidParameter, stat);
910
911     stat = GdipGetImageVerticalResolution(NULL, &res);
912     expect(InvalidParameter, stat);
913
914     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
915     expect(InvalidParameter, stat);
916
917     stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
918     todo_wine expect(InvalidParameter, stat);
919
920     stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
921     todo_wine expect(InvalidParameter, stat);
922
923     /* defaults to screen resolution */
924     screendc = GetDC(0);
925
926     screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
927     screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
928
929     ReleaseDC(0, screendc);
930
931     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
932     expect(Ok, stat);
933     expectf((REAL)screenxres, res);
934
935     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
936     expect(Ok, stat);
937     expectf((REAL)screenyres, res);
938
939     /* test changing the resolution */
940     stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
941     todo_wine expect(Ok, stat);
942
943     stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
944     expect(Ok, stat);
945     todo_wine expectf(screenxres*2.0, res);
946
947     stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
948     expect(Ok, stat);
949     todo_wine expectf(screenyres*3.0, res);
950
951     stat = GdipDisposeImage((GpImage*)bitmap);
952     expect(Ok, stat);
953 }
954
955 static void test_createhbitmap(void)
956 {
957     GpStatus stat;
958     GpBitmap *bitmap;
959     HBITMAP hbitmap, oldhbitmap;
960     BITMAP bm;
961     int ret;
962     HDC hdc;
963     COLORREF pixel;
964     BYTE bits[640];
965
966     memset(bits, 0x68, 640);
967
968     /* create Bitmap */
969     stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
970     expect(Ok, stat);
971
972     /* test NULL values */
973     stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
974     expect(InvalidParameter, stat);
975
976     stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
977     expect(InvalidParameter, stat);
978
979     /* create HBITMAP */
980     stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
981     expect(Ok, stat);
982
983     if (stat == Ok)
984     {
985         ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
986         expect(sizeof(BITMAP), ret);
987
988         expect(0, bm.bmType);
989         expect(10, bm.bmWidth);
990         expect(20, bm.bmHeight);
991         expect(40, bm.bmWidthBytes);
992         expect(1, bm.bmPlanes);
993         expect(32, bm.bmBitsPixel);
994         ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
995
996         hdc = CreateCompatibleDC(NULL);
997
998         oldhbitmap = SelectObject(hdc, hbitmap);
999         pixel = GetPixel(hdc, 5, 5);
1000         SelectObject(hdc, oldhbitmap);
1001
1002         DeleteDC(hdc);
1003
1004         expect(0x686868, pixel);
1005
1006         DeleteObject(hbitmap);
1007     }
1008
1009     stat = GdipDisposeImage((GpImage*)bitmap);
1010     expect(Ok, stat);
1011 }
1012
1013 static void test_getsetpixel(void)
1014 {
1015     GpStatus stat;
1016     GpBitmap *bitmap;
1017     ARGB color;
1018     BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1019                      0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1020
1021     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1022     expect(Ok, stat);
1023
1024     /* null parameters */
1025     stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1026     expect(InvalidParameter, stat);
1027
1028     stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1029     expect(InvalidParameter, stat);
1030
1031     stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1032     expect(InvalidParameter, stat);
1033
1034     /* out of bounds */
1035     stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1036     expect(InvalidParameter, stat);
1037
1038     stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1039     expect(InvalidParameter, stat);
1040
1041     stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1042     ok(stat == InvalidParameter ||
1043        broken(stat == Ok), /* Older gdiplus */
1044        "Expected InvalidParameter, got %.8x\n", stat);
1045
1046     stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1047     ok(stat == InvalidParameter ||
1048        broken(stat == Ok), /* Older gdiplus */
1049        "Expected InvalidParameter, got %.8x\n", stat);
1050
1051     stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1052     expect(InvalidParameter, stat);
1053
1054     stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1055     expect(InvalidParameter, stat);
1056
1057     stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1058     expect(InvalidParameter, stat);
1059
1060     stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1061     expect(InvalidParameter, stat);
1062
1063     /* valid use */
1064     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1065     expect(Ok, stat);
1066     expect(0xffffffff, color);
1067
1068     stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1069     expect(Ok, stat);
1070     expect(0xff0000ff, color);
1071
1072     stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1073     expect(Ok, stat);
1074
1075     stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1076     expect(Ok, stat);
1077
1078     stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1079     expect(Ok, stat);
1080     expect(0xff676869, color);
1081
1082     stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1083     expect(Ok, stat);
1084     expect(0xff474849, color);
1085
1086     stat = GdipDisposeImage((GpImage*)bitmap);
1087     expect(Ok, stat);
1088 }
1089
1090 static void check_halftone_palette(ColorPalette *palette)
1091 {
1092     static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1093     UINT i;
1094
1095     for (i=0; i<palette->Count; i++)
1096     {
1097         ARGB expected=0xff000000;
1098         if (i<8)
1099         {
1100             if (i&1) expected |= 0x800000;
1101             if (i&2) expected |= 0x8000;
1102             if (i&4) expected |= 0x80;
1103         }
1104         else if (i == 8)
1105         {
1106             expected = 0xffc0c0c0;
1107         }
1108         else if (i < 16)
1109         {
1110             if (i&1) expected |= 0xff0000;
1111             if (i&2) expected |= 0xff00;
1112             if (i&4) expected |= 0xff;
1113         }
1114         else if (i < 40)
1115         {
1116             expected = 0x00000000;
1117         }
1118         else
1119         {
1120             expected |= halftone_values[(i-40)%6];
1121             expected |= halftone_values[((i-40)/6)%6] << 8;
1122             expected |= halftone_values[((i-40)/36)%6] << 16;
1123         }
1124         ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
1125             expected, palette->Entries[i], i, palette->Count);
1126     }
1127 }
1128
1129 static void test_palette(void)
1130 {
1131     GpStatus stat;
1132     GpBitmap *bitmap;
1133     INT size;
1134     BYTE buffer[1040];
1135     ColorPalette *palette=(ColorPalette*)buffer;
1136
1137     /* test initial palette from non-indexed bitmap */
1138     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
1139     expect(Ok, stat);
1140
1141     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1142     expect(Ok, stat);
1143     expect(sizeof(UINT)*2+sizeof(ARGB), size);
1144
1145     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1146     expect(Ok, stat);
1147     expect(0, palette->Count);
1148
1149     /* test setting palette on not-indexed bitmap */
1150     palette->Count = 3;
1151
1152     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
1153     expect(Ok, stat);
1154
1155     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1156     expect(Ok, stat);
1157     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
1158
1159     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1160     expect(Ok, stat);
1161     expect(3, palette->Count);
1162
1163     GdipDisposeImage((GpImage*)bitmap);
1164
1165     /* test initial palette on 1-bit bitmap */
1166     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
1167     expect(Ok, stat);
1168
1169     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1170     expect(Ok, stat);
1171     expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
1172
1173     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1174     expect(Ok, stat);
1175     expect(PaletteFlagsGrayScale, palette->Flags);
1176     expect(2, palette->Count);
1177
1178     expect(0xff000000, palette->Entries[0]);
1179     expect(0xffffffff, palette->Entries[1]);
1180
1181     GdipDisposeImage((GpImage*)bitmap);
1182
1183     /* test initial palette on 4-bit bitmap */
1184     stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
1185     expect(Ok, stat);
1186
1187     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1188     expect(Ok, stat);
1189     expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
1190
1191     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1192     expect(Ok, stat);
1193     expect(0, palette->Flags);
1194     expect(16, palette->Count);
1195
1196     check_halftone_palette(palette);
1197
1198     GdipDisposeImage((GpImage*)bitmap);
1199
1200     /* test initial palette on 8-bit bitmap */
1201     stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
1202     expect(Ok, stat);
1203
1204     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1205     expect(Ok, stat);
1206     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
1207
1208     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1209     expect(Ok, stat);
1210     expect(PaletteFlagsHalftone, palette->Flags);
1211     expect(256, palette->Count);
1212
1213     check_halftone_palette(palette);
1214
1215     /* test setting/getting a different palette */
1216     palette->Entries[1] = 0xffcccccc;
1217
1218     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
1219     expect(Ok, stat);
1220
1221     palette->Entries[1] = 0;
1222
1223     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1224     expect(Ok, stat);
1225     expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
1226
1227     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1228     expect(Ok, stat);
1229     expect(PaletteFlagsHalftone, palette->Flags);
1230     expect(256, palette->Count);
1231     expect(0xffcccccc, palette->Entries[1]);
1232
1233     /* test count < 256 */
1234     palette->Flags = 12345;
1235     palette->Count = 3;
1236
1237     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
1238     expect(Ok, stat);
1239
1240     palette->Entries[1] = 0;
1241     palette->Entries[3] = 0xdeadbeef;
1242
1243     stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
1244     expect(Ok, stat);
1245     expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
1246
1247     stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
1248     expect(Ok, stat);
1249     expect(12345, palette->Flags);
1250     expect(3, palette->Count);
1251     expect(0xffcccccc, palette->Entries[1]);
1252     expect(0xdeadbeef, palette->Entries[3]);
1253
1254     /* test count > 256 */
1255     palette->Count = 257;
1256
1257     stat = GdipSetImagePalette((GpImage*)bitmap, palette);
1258     ok(stat == InvalidParameter ||
1259        broken(stat == Ok), /* Old gdiplus behavior */
1260        "Expected %.8x, got %.8x\n", InvalidParameter, stat);
1261
1262     GdipDisposeImage((GpImage*)bitmap);
1263 }
1264
1265 static void test_colormatrix(void)
1266 {
1267     GpStatus stat;
1268     ColorMatrix colormatrix, graymatrix;
1269     GpImageAttributes *imageattr;
1270     const ColorMatrix identity = {{
1271         {1.0,0.0,0.0,0.0,0.0},
1272         {0.0,1.0,0.0,0.0,0.0},
1273         {0.0,0.0,1.0,0.0,0.0},
1274         {0.0,0.0,0.0,1.0,0.0},
1275         {0.0,0.0,0.0,0.0,1.0}}};
1276     const ColorMatrix double_red = {{
1277         {2.0,0.0,0.0,0.0,0.0},
1278         {0.0,1.0,0.0,0.0,0.0},
1279         {0.0,0.0,1.0,0.0,0.0},
1280         {0.0,0.0,0.0,1.0,0.0},
1281         {0.0,0.0,0.0,0.0,1.0}}};
1282     GpBitmap *bitmap1, *bitmap2;
1283     GpGraphics *graphics;
1284     ARGB color;
1285
1286     colormatrix = identity;
1287     graymatrix = identity;
1288
1289     stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
1290         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
1291     expect(InvalidParameter, stat);
1292
1293     stat = GdipCreateImageAttributes(&imageattr);
1294     expect(Ok, stat);
1295
1296     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1297         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
1298     expect(Ok, stat);
1299
1300     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1301         TRUE, NULL, NULL, ColorMatrixFlagsDefault);
1302     expect(InvalidParameter, stat);
1303
1304     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1305         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
1306     expect(Ok, stat);
1307
1308     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1309         TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
1310     expect(Ok, stat);
1311
1312     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1313         TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
1314     expect(InvalidParameter, stat);
1315
1316     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1317         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
1318     expect(Ok, stat);
1319
1320     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1321         TRUE, &colormatrix, &graymatrix, 3);
1322     expect(InvalidParameter, stat);
1323
1324     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
1325         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
1326     expect(InvalidParameter, stat);
1327
1328     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
1329         TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
1330     expect(InvalidParameter, stat);
1331
1332     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1333         FALSE, NULL, NULL, ColorMatrixFlagsDefault);
1334     expect(Ok, stat);
1335
1336     /* Drawing a bitmap transforms the colors */
1337     colormatrix = double_red;
1338     stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
1339         TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
1340     expect(Ok, stat);
1341
1342     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
1343     expect(Ok, stat);
1344
1345     stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
1346     expect(Ok, stat);
1347
1348     stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ffff);
1349     expect(Ok, stat);
1350
1351     stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
1352     expect(Ok, stat);
1353
1354     stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
1355         UnitPixel, imageattr, NULL, NULL);
1356     expect(Ok, stat);
1357
1358     stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
1359     expect(Ok, stat);
1360     todo_wine expect(0xff80ffff, color);
1361
1362     GdipDeleteGraphics(graphics);
1363     GdipDisposeImage((GpImage*)bitmap1);
1364     GdipDisposeImage((GpImage*)bitmap2);
1365     GdipDisposeImageAttributes(imageattr);
1366 }
1367
1368 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
1369 static const unsigned char gifanimation[72] = {
1370 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
1371 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
1372 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
1373 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
1374 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
1375 };
1376
1377 static void test_multiframegif(void)
1378 {
1379     LPSTREAM stream;
1380     HGLOBAL hglob;
1381     LPBYTE data;
1382     HRESULT hres;
1383     GpStatus stat;
1384     GpBitmap *bmp;
1385     ARGB color;
1386     UINT count;
1387     GUID dimension;
1388
1389     /* Test frame functions with an animated GIF */
1390     hglob = GlobalAlloc (0, sizeof(gifanimation));
1391     data = GlobalLock (hglob);
1392     memcpy(data, gifanimation, sizeof(gifanimation));
1393     GlobalUnlock(hglob);
1394
1395     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1396     ok(hres == S_OK, "Failed to create a stream\n");
1397     if(hres != S_OK) return;
1398
1399     stat = GdipCreateBitmapFromStream(stream, &bmp);
1400     ok(stat == Ok, "Failed to create a Bitmap\n");
1401     if(stat != Ok){
1402         IStream_Release(stream);
1403         return;
1404     }
1405
1406     /* Bitmap starts at frame 0 */
1407     color = 0xdeadbeef;
1408     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
1409     expect(Ok, stat);
1410     expect(0xffffffff, color);
1411
1412     /* Check that we get correct metadata */
1413     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
1414     expect(Ok, stat);
1415     expect(1, count);
1416
1417     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
1418     expect(Ok, stat);
1419     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
1420
1421     count = 12345;
1422     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
1423     todo_wine expect(Ok, stat);
1424     todo_wine expect(2, count);
1425
1426     /* SelectActiveFrame overwrites our current data */
1427     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
1428     expect(Ok, stat);
1429
1430     color = 0xdeadbeef;
1431     GdipBitmapGetPixel(bmp, 0, 0, &color);
1432     expect(Ok, stat);
1433     todo_wine expect(0xff000000, color);
1434
1435     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
1436     expect(Ok, stat);
1437
1438     color = 0xdeadbeef;
1439     GdipBitmapGetPixel(bmp, 0, 0, &color);
1440     expect(Ok, stat);
1441     expect(0xffffffff, color);
1442
1443     /* Write over the image data */
1444     stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
1445     expect(Ok, stat);
1446
1447     /* Switching to the same frame does not overwrite our changes */
1448     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
1449     expect(Ok, stat);
1450
1451     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
1452     expect(Ok, stat);
1453     expect(0xff000000, color);
1454
1455     /* But switching to another frame and back does */
1456     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
1457     expect(Ok, stat);
1458
1459     stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
1460     expect(Ok, stat);
1461
1462     stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
1463     expect(Ok, stat);
1464     todo_wine expect(0xffffffff, color);
1465
1466     GdipDisposeImage((GpImage*)bmp);
1467     IStream_Release(stream);
1468
1469     /* Test with a non-animated gif */
1470     hglob = GlobalAlloc (0, sizeof(gifimage));
1471     data = GlobalLock (hglob);
1472     memcpy(data, gifimage, sizeof(gifimage));
1473     GlobalUnlock(hglob);
1474
1475     hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1476     ok(hres == S_OK, "Failed to create a stream\n");
1477     if(hres != S_OK) return;
1478
1479     stat = GdipCreateBitmapFromStream(stream, &bmp);
1480     ok(stat == Ok, "Failed to create a Bitmap\n");
1481     if(stat != Ok){
1482         IStream_Release(stream);
1483         return;
1484     }
1485
1486     /* Check metadata */
1487     stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
1488     expect(Ok, stat);
1489     expect(1, count);
1490
1491     stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
1492     expect(Ok, stat);
1493     expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
1494
1495     count = 12345;
1496     stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
1497     todo_wine expect(Ok, stat);
1498     todo_wine expect(1, count);
1499
1500     GdipDisposeImage((GpImage*)bmp);
1501     IStream_Release(stream);
1502 }
1503
1504 START_TEST(image)
1505 {
1506     struct GdiplusStartupInput gdiplusStartupInput;
1507     ULONG_PTR gdiplusToken;
1508
1509     gdiplusStartupInput.GdiplusVersion              = 1;
1510     gdiplusStartupInput.DebugEventCallback          = NULL;
1511     gdiplusStartupInput.SuppressBackgroundThread    = 0;
1512     gdiplusStartupInput.SuppressExternalCodecs      = 0;
1513
1514     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
1515
1516     test_Scan0();
1517     test_GetImageDimension();
1518     test_GdipImageGetFrameDimensionsCount();
1519     test_LoadingImages();
1520     test_SavingImages();
1521     test_encoders();
1522     test_LockBits();
1523     test_GdipCreateBitmapFromHBITMAP();
1524     test_GdipGetImageFlags();
1525     test_GdipCloneImage();
1526     test_testcontrol();
1527     test_fromhicon();
1528     test_getrawformat();
1529     test_loadwmf();
1530     test_createfromwmf();
1531     test_resolution();
1532     test_createhbitmap();
1533     test_getsetpixel();
1534     test_palette();
1535     test_colormatrix();
1536     test_multiframegif();
1537
1538     GdiplusShutdown(gdiplusToken);
1539 }