gdiplus: Stub implementation of GdipImageGetFrameDimensionsCount + test.
[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 #include "windows.h"
22 #include "gdiplus.h"
23 #include "wine/test.h"
24 #include <math.h>
25 #include "wingdi.h"
26
27 #define expect(expected, got) ok(((UINT)got) == ((UINT)expected), "Expected %.8x, got %.8x\n", (UINT)expected, (UINT)got)
28
29 static void test_Scan0(void)
30 {
31     GpBitmap *bm;
32     GpStatus stat;
33     BYTE buff[360];
34
35     bm = NULL;
36     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
37     expect(Ok, stat);
38     ok(NULL != bm, "Expected bitmap to be initialized\n");
39     if (stat == Ok)
40         GdipDisposeImage((GpImage*)bm);
41
42     bm = (GpBitmap*)0xdeadbeef;
43     stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
44     expect(InvalidParameter, stat);
45
46     expect(NULL, bm);
47
48     bm = (GpBitmap*)0xdeadbeef;
49     stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
50     expect(InvalidParameter, stat);
51
52     expect(NULL, bm);
53
54     bm = (GpBitmap*)0xdeadbeef;
55     stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
56     expect(InvalidParameter, stat);
57
58     expect(NULL, bm);
59
60     bm = NULL;
61     stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
62     expect(Ok, stat);
63     ok(NULL != bm, "Expected bitmap to be initialized\n");
64     if (stat == Ok)
65         GdipDisposeImage((GpImage*)bm);
66
67     bm = (GpBitmap*) 0xdeadbeef;
68     stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
69     expect(InvalidParameter, stat);
70     expect(NULL, bm);
71
72     bm = (GpBitmap*)0xdeadbeef;
73     stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
74     expect(InvalidParameter, stat);
75     expect(0xdeadbeef, bm);
76 }
77
78 static void test_GetImageDimension(void)
79 {
80     GpBitmap *bm;
81     GpStatus stat;
82     const REAL WIDTH = 10.0, HEIGHT = 20.0;
83     REAL w,h;
84
85     bm = (GpBitmap*)0xdeadbeef;
86     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
87     expect(Ok,stat);
88     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
89     ok(NULL != bm, "Expected bitmap to not be NULL\n");
90
91     stat = GdipGetImageDimension(NULL,&w,&h);
92     expect(InvalidParameter, stat);
93
94     stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
95     expect(InvalidParameter, stat);
96
97     stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
98     expect(InvalidParameter, stat);
99
100     w = -1;
101     h = -1;
102     stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
103     expect(Ok, stat);
104     ok(fabs(WIDTH - w) < 0.0001, "Width wrong\n");
105     ok(fabs(HEIGHT - h) < 0.0001, "Height wrong\n");
106     GdipDisposeImage((GpImage*)bm);
107 }
108
109 static void test_GdipImageGetFrameDimensionsCount(void)
110 {
111     GpBitmap *bm;
112     GpStatus stat;
113     const REAL WIDTH = 10.0, HEIGHT = 20.0;
114     UINT w;
115
116     bm = (GpBitmap*)0xdeadbeef;
117     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
118     expect(Ok,stat);
119     ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
120     ok(NULL != bm, "Expected bitmap to not be NULL\n");
121
122     stat = GdipImageGetFrameDimensionsCount(NULL,&w);
123     expect(InvalidParameter, stat);
124
125     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
126     expect(InvalidParameter, stat);
127
128     w = -1;
129     stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
130     expect(Ok, stat);
131     expect(1, w);
132     GdipDisposeImage((GpImage*)bm);
133 }
134
135 static void test_LoadingImages(void)
136 {
137     GpStatus stat;
138
139     stat = GdipCreateBitmapFromFile(0, 0);
140     expect(InvalidParameter, stat);
141
142     stat = GdipCreateBitmapFromFile(0, (GpBitmap**)0xdeadbeef);
143     expect(InvalidParameter, stat);
144
145     stat = GdipLoadImageFromFile(0, 0);
146     expect(InvalidParameter, stat);
147
148     stat = GdipLoadImageFromFile(0, (GpImage**)0xdeadbeef);
149     expect(InvalidParameter, stat);
150
151     stat = GdipLoadImageFromFileICM(0, 0);
152     expect(InvalidParameter, stat);
153
154     stat = GdipLoadImageFromFileICM(0, (GpImage**)0xdeadbeef);
155     expect(InvalidParameter, stat);
156 }
157
158 static void test_SavingImages(void)
159 {
160     GpStatus stat;
161     GpBitmap *bm;
162     UINT n;
163     UINT s;
164     const REAL WIDTH = 10.0, HEIGHT = 20.0;
165     REAL w, h;
166     ImageCodecInfo *codecs;
167     static const WCHAR filename[] = { 'a','.','b','m','p',0 };
168
169     codecs = NULL;
170
171     stat = GdipSaveImageToFile(0, 0, 0, 0);
172     expect(InvalidParameter, stat);
173
174     bm = NULL;
175     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
176     expect(Ok, stat);
177     if (!bm)
178         return;
179
180     /* invalid params */
181     stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
182     expect(InvalidParameter, stat);
183
184     stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
185     expect(InvalidParameter, stat);
186
187     /* encoder tests should succeed -- already tested */
188     stat = GdipGetImageEncodersSize(&n, &s);
189     if (stat != Ok || n == 0) goto cleanup;
190
191     codecs = GdipAlloc(s);
192     if (!codecs) goto cleanup;
193
194     stat = GdipGetImageEncoders(n, s, codecs);
195     if (stat != Ok) goto cleanup;
196
197     stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
198     expect(stat, Ok);
199
200     GdipDisposeImage((GpImage*)bm);
201     bm = 0;
202
203     /* re-load and check image stats */
204     stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
205     expect(stat, Ok);
206     if (stat != Ok) goto cleanup;
207
208     stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
209     if (stat != Ok) goto cleanup;
210
211     ok((fabs(w - WIDTH) < 0.01) && (fabs(h - HEIGHT) < 0.01),
212        "Saved image dimensions are different!\n");
213
214  cleanup:
215     GdipFree(codecs);
216     if (bm)
217         GdipDisposeImage((GpImage*)bm);
218     ok(DeleteFileW(filename), "Delete failed.\n");
219 }
220
221 static void test_encoders(void)
222 {
223     GpStatus stat;
224     UINT n;
225     UINT s;
226     ImageCodecInfo *codecs;
227     int i;
228     int bmp_found;
229
230     static const WCHAR bmp_format[] = {'B', 'M', 'P', 0};
231
232     stat = GdipGetImageEncodersSize(&n, &s);
233     expect(stat, Ok);
234
235     codecs = GdipAlloc(s);
236     if (!codecs)
237         return;
238
239     stat = GdipGetImageEncoders(n, s, NULL);
240     expect(GenericError, stat);
241
242     stat = GdipGetImageEncoders(0, s, codecs);
243     expect(GenericError, stat);
244
245     stat = GdipGetImageEncoders(n, s-1, codecs);
246     expect(GenericError, stat);
247
248     stat = GdipGetImageEncoders(n, s+1, codecs);
249     expect(GenericError, stat);
250
251     stat = GdipGetImageEncoders(n, s, codecs);
252     expect(stat, Ok);
253
254     bmp_found = FALSE;
255     for (i = 0; i < n; i++)
256         {
257             if (CompareStringW(LOCALE_SYSTEM_DEFAULT, 0,
258                                codecs[i].FormatDescription, -1,
259                                bmp_format, -1) == CSTR_EQUAL) {
260                 bmp_found = TRUE;
261                 break;
262             }
263         }
264     if (!bmp_found)
265         ok(FALSE, "No BMP codec found.\n");
266
267     GdipFree(codecs);
268 }
269
270 static void test_LockBits(void)
271 {
272     GpStatus stat;
273     GpBitmap *bm;
274     GpRect rect;
275     BitmapData bd;
276     const INT WIDTH = 10, HEIGHT = 20;
277
278     bm = NULL;
279     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
280     expect(Ok, stat);
281
282     rect.X = 2;
283     rect.Y = 3;
284     rect.Width = 4;
285     rect.Height = 5;
286
287     /* read-only */
288     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
289     expect(Ok, stat);
290
291     if (stat == Ok) {
292         stat = GdipBitmapUnlockBits(bm, &bd);
293         expect(Ok, stat);
294     }
295
296     /* read-only, with NULL rect -> whole bitmap lock */
297     stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
298     expect(Ok, stat);
299     expect(bd.Width,  WIDTH);
300     expect(bd.Height, HEIGHT);
301
302     if (stat == Ok) {
303         stat = GdipBitmapUnlockBits(bm, &bd);
304         expect(Ok, stat);
305     }
306
307     /* read-only, consecutive */
308     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
309     expect(Ok, stat);
310
311     if (stat == Ok) {
312         stat = GdipBitmapUnlockBits(bm, &bd);
313         expect(Ok, stat);
314     }
315
316     stat = GdipDisposeImage((GpImage*)bm);
317     expect(Ok, stat);
318     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
319     expect(Ok, stat);
320
321     /* read x2 */
322     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
323     expect(Ok, stat);
324     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
325     expect(WrongState, stat);
326
327     stat = GdipBitmapUnlockBits(bm, &bd);
328     expect(Ok, stat);
329
330     stat = GdipDisposeImage((GpImage*)bm);
331     expect(Ok, stat);
332     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
333     expect(Ok, stat);
334
335     /* write, no modification */
336     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
337     expect(Ok, stat);
338
339     if (stat == Ok) {
340         stat = GdipBitmapUnlockBits(bm, &bd);
341         expect(Ok, stat);
342     }
343
344     /* write, consecutive */
345     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
346     expect(Ok, stat);
347
348     if (stat == Ok) {
349         stat = GdipBitmapUnlockBits(bm, &bd);
350         expect(Ok, stat);
351     }
352
353     stat = GdipDisposeImage((GpImage*)bm);
354     expect(Ok, stat);
355     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
356     expect(Ok, stat);
357
358     /* write, modify */
359     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
360     expect(Ok, stat);
361
362     if (stat == Ok) {
363         if (bd.Scan0)
364             ((char*)bd.Scan0)[2] = 0xff;
365
366         stat = GdipBitmapUnlockBits(bm, &bd);
367         expect(Ok, stat);
368     }
369
370     stat = GdipDisposeImage((GpImage*)bm);
371     expect(Ok, stat);
372
373     /* dispose locked */
374     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
375     expect(Ok, stat);
376     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
377     expect(Ok, stat);
378     stat = GdipDisposeImage((GpImage*)bm);
379     expect(Ok, stat);
380 }
381
382 static void test_GdipCreateBitmapFromHBITMAP(void)
383 {
384     GpBitmap* gpbm = NULL;
385     HBITMAP hbm = NULL;
386     HPALETTE hpal = NULL;
387     GpStatus stat;
388     BYTE buff[1000];
389     LOGPALETTE* LogPal = NULL;
390     REAL width, height;
391     const REAL WIDTH1 = 5;
392     const REAL HEIGHT1 = 15;
393     const REAL WIDTH2 = 10;
394     const REAL HEIGHT2 = 20;
395     HDC hdc;
396     BITMAPINFO bmi;
397
398     stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
399     expect(InvalidParameter, stat);
400
401     hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
402     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
403     expect(InvalidParameter, stat);
404
405     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
406     expect(Ok, stat);
407     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
408     ok(fabs(WIDTH1 - width) < .0001, "width wrong\n");
409     ok(fabs(HEIGHT1 - height) < .0001, "height wrong\n");
410     if (stat == Ok)
411         GdipDisposeImage((GpImage*)gpbm);
412     GlobalFree(hbm);
413
414     hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
415     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
416     expect(Ok, stat);
417     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
418     ok(fabs(WIDTH2 - width) < .0001, "width wrong\n");
419     ok(fabs(HEIGHT2 - height) < .0001, "height wrong\n");
420     if (stat == Ok)
421         GdipDisposeImage((GpImage*)gpbm);
422     GlobalFree(hbm);
423
424     hdc = CreateCompatibleDC(0);
425     ok(hdc != NULL, "CreateCompatibleDC failed\n");
426     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
427     bmi.bmiHeader.biHeight = HEIGHT1;
428     bmi.bmiHeader.biWidth = WIDTH1;
429     bmi.bmiHeader.biBitCount = 24;
430     bmi.bmiHeader.biPlanes = 1;
431     bmi.bmiHeader.biCompression = BI_RGB;
432
433     hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
434     ok(hbm != NULL, "CreateDIBSection failed\n");
435
436     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
437     expect(Ok, stat);
438     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
439     ok(fabs(WIDTH1 - width) < .0001, "width wrong\n");
440     ok(fabs(HEIGHT1 - height) < .0001, "height wrong\n");
441     if (stat == Ok)
442         GdipDisposeImage((GpImage*)gpbm);
443
444     LogPal = GdipAlloc(sizeof(LOGPALETTE));
445     ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
446     LogPal->palVersion = 0x300;
447     hpal = CreatePalette((const LOGPALETTE*) LogPal);
448     ok(hpal != NULL, "CreatePalette failed\n");
449     GdipFree(LogPal);
450
451     stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
452     todo_wine
453     {
454         expect(Ok, stat);
455     }
456     if (stat == Ok)
457         GdipDisposeImage((GpImage*)gpbm);
458
459     GlobalFree(hpal);
460     GlobalFree(hbm);
461 }
462
463 static void test_GdipGetImageFlags(void)
464 {
465     GpImage *img;
466     GpStatus stat;
467     UINT flags;
468
469     img = (GpImage*)0xdeadbeef;
470
471     stat = GdipGetImageFlags(NULL, NULL);
472     expect(InvalidParameter, stat);
473
474     stat = GdipGetImageFlags(NULL, &flags);
475     expect(InvalidParameter, stat);
476
477     stat = GdipGetImageFlags(img, NULL);
478     expect(InvalidParameter, stat);
479 }
480
481 START_TEST(image)
482 {
483     struct GdiplusStartupInput gdiplusStartupInput;
484     ULONG_PTR gdiplusToken;
485
486     gdiplusStartupInput.GdiplusVersion              = 1;
487     gdiplusStartupInput.DebugEventCallback          = NULL;
488     gdiplusStartupInput.SuppressBackgroundThread    = 0;
489     gdiplusStartupInput.SuppressExternalCodecs      = 0;
490
491     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
492
493     test_Scan0();
494     test_GetImageDimension();
495     test_GdipImageGetFrameDimensionsCount();
496     test_LoadingImages();
497     test_SavingImages();
498     test_encoders();
499     test_LockBits();
500     test_GdipCreateBitmapFromHBITMAP();
501     test_GdipGetImageFlags();
502
503     GdiplusShutdown(gdiplusToken);
504 }