gdiplus: Add a stub for GdipSetImageAttributesNoOp.
[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_LoadingImages(void)
110 {
111     GpStatus stat;
112
113     stat = GdipCreateBitmapFromFile(0, 0);
114     expect(InvalidParameter, stat);
115
116     stat = GdipCreateBitmapFromFile(0, (GpBitmap**)0xdeadbeef);
117     expect(InvalidParameter, stat);
118
119     stat = GdipLoadImageFromFile(0, 0);
120     expect(InvalidParameter, stat);
121
122     stat = GdipLoadImageFromFile(0, (GpImage**)0xdeadbeef);
123     expect(InvalidParameter, stat);
124 }
125
126 static void test_SavingImages(void)
127 {
128     GpStatus stat;
129     GpBitmap *bm;
130     UINT n;
131     UINT s;
132     const REAL WIDTH = 10.0, HEIGHT = 20.0;
133     REAL w, h;
134     ImageCodecInfo *codecs;
135     static const WCHAR filename[] = { 'a','.','b','m','p',0 };
136
137     codecs = NULL;
138
139     stat = GdipSaveImageToFile(0, 0, 0, 0);
140     expect(InvalidParameter, stat);
141
142     bm = NULL;
143     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
144     expect(Ok, stat);
145     if (!bm)
146         return;
147
148     /* invalid params */
149     stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
150     expect(InvalidParameter, stat);
151
152     stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
153     expect(InvalidParameter, stat);
154
155     /* encoder tests should succeed -- already tested */
156     stat = GdipGetImageEncodersSize(&n, &s);
157     if (stat != Ok || n == 0) goto cleanup;
158
159     codecs = GdipAlloc(s);
160     if (!codecs) goto cleanup;
161
162     stat = GdipGetImageEncoders(n, s, codecs);
163     if (stat != Ok) goto cleanup;
164
165     stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
166     expect(stat, Ok);
167
168     GdipDisposeImage((GpImage*)bm);
169     bm = 0;
170
171     /* re-load and check image stats */
172     stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
173     expect(stat, Ok);
174     if (stat != Ok) goto cleanup;
175
176     stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
177     if (stat != Ok) goto cleanup;
178
179     ok((fabs(w - WIDTH) < 0.01) && (fabs(h - HEIGHT) < 0.01),
180        "Saved image dimensions are different!\n");
181
182  cleanup:
183     GdipFree(codecs);
184     if (bm)
185         GdipDisposeImage((GpImage*)bm);
186     ok(DeleteFileW(filename), "Delete failed.\n");
187 }
188
189 static void test_encoders(void)
190 {
191     GpStatus stat;
192     UINT n;
193     UINT s;
194     ImageCodecInfo *codecs;
195     int i;
196     int bmp_found;
197
198     static const WCHAR bmp_format[] = {'B', 'M', 'P', 0};
199
200     stat = GdipGetImageEncodersSize(&n, &s);
201     expect(stat, Ok);
202
203     codecs = GdipAlloc(s);
204     if (!codecs)
205         return;
206
207     stat = GdipGetImageEncoders(n, s, NULL);
208     expect(GenericError, stat);
209
210     stat = GdipGetImageEncoders(0, s, codecs);
211     expect(GenericError, stat);
212
213     stat = GdipGetImageEncoders(n, s-1, codecs);
214     expect(GenericError, stat);
215
216     stat = GdipGetImageEncoders(n, s+1, codecs);
217     expect(GenericError, stat);
218
219     stat = GdipGetImageEncoders(n, s, codecs);
220     expect(stat, Ok);
221
222     bmp_found = FALSE;
223     for (i = 0; i < n; i++)
224         {
225             if (CompareStringW(LOCALE_SYSTEM_DEFAULT, 0,
226                                codecs[i].FormatDescription, -1,
227                                bmp_format, -1) == CSTR_EQUAL) {
228                 bmp_found = TRUE;
229                 break;
230             }
231         }
232     if (!bmp_found)
233         ok(FALSE, "No BMP codec found.\n");
234
235     GdipFree(codecs);
236 }
237
238 static void test_LockBits(void)
239 {
240     GpStatus stat;
241     GpBitmap *bm;
242     GpRect rect;
243     BitmapData bd;
244     const REAL WIDTH = 10.0, HEIGHT = 20.0;
245
246     bm = NULL;
247     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
248     expect(Ok, stat);
249
250     rect.X = 2;
251     rect.Y = 3;
252     rect.Width = 4;
253     rect.Height = 5;
254
255     /* read-only */
256     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
257     expect(Ok, stat);
258
259     if (stat == Ok) {
260         stat = GdipBitmapUnlockBits(bm, &bd);
261         expect(Ok, stat);
262     }
263
264     /* read-only, consecutive */
265     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
266     expect(Ok, stat);
267
268     if (stat == Ok) {
269         stat = GdipBitmapUnlockBits(bm, &bd);
270         expect(Ok, stat);
271     }
272
273     stat = GdipDisposeImage((GpImage*)bm);
274     expect(Ok, stat);
275     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
276     expect(Ok, stat);
277
278     /* read x2 */
279     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
280     expect(Ok, stat);
281     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
282     expect(WrongState, stat);
283
284     stat = GdipBitmapUnlockBits(bm, &bd);
285     expect(Ok, stat);
286
287     stat = GdipDisposeImage((GpImage*)bm);
288     expect(Ok, stat);
289     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
290     expect(Ok, stat);
291
292     /* write, no modification */
293     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
294     expect(Ok, stat);
295
296     if (stat == Ok) {
297         stat = GdipBitmapUnlockBits(bm, &bd);
298         expect(Ok, stat);
299     }
300
301     /* write, consecutive */
302     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
303     expect(Ok, stat);
304
305     if (stat == Ok) {
306         stat = GdipBitmapUnlockBits(bm, &bd);
307         expect(Ok, stat);
308     }
309
310     stat = GdipDisposeImage((GpImage*)bm);
311     expect(Ok, stat);
312     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
313     expect(Ok, stat);
314
315     /* write, modify */
316     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
317     expect(Ok, stat);
318
319     if (stat == Ok) {
320         if (bd.Scan0)
321             ((char*)bd.Scan0)[2] = 0xff;
322
323         stat = GdipBitmapUnlockBits(bm, &bd);
324         expect(Ok, stat);
325     }
326
327     stat = GdipDisposeImage((GpImage*)bm);
328     expect(Ok, stat);
329
330     /* dispose locked */
331     stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
332     expect(Ok, stat);
333     stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
334     expect(Ok, stat);
335     stat = GdipDisposeImage((GpImage*)bm);
336     expect(Ok, stat);
337 }
338
339 static void test_GdipCreateBitmapFromHBITMAP(void)
340 {
341     GpBitmap* gpbm = NULL;
342     HBITMAP hbm = NULL;
343     HPALETTE hpal = NULL;
344     GpStatus stat;
345     BYTE buff[1000];
346     LOGPALETTE* LogPal = NULL;
347     REAL width, height;
348     const REAL WIDTH1 = 5;
349     const REAL HEIGHT1 = 15;
350     const REAL WIDTH2 = 10;
351     const REAL HEIGHT2 = 20;
352     HDC hdc;
353     BITMAPINFO bmi;
354
355     stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
356     expect(InvalidParameter, stat);
357
358     hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
359     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
360     expect(InvalidParameter, stat);
361
362     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
363     expect(Ok, stat);
364     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
365     ok(fabs(WIDTH1 - width) < .0001, "width wrong\n");
366     ok(fabs(HEIGHT1 - height) < .0001, "height wrong\n");
367     if (stat == Ok)
368         GdipDisposeImage((GpImage*)gpbm);
369     GlobalFree(hbm);
370
371     hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
372     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
373     expect(Ok, stat);
374     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
375     ok(fabs(WIDTH2 - width) < .0001, "width wrong\n");
376     ok(fabs(HEIGHT2 - height) < .0001, "height wrong\n");
377     if (stat == Ok)
378         GdipDisposeImage((GpImage*)gpbm);
379     GlobalFree(hbm);
380
381     hdc = CreateCompatibleDC(0);
382     ok(hdc != NULL, "CreateCompatibleDC failed\n");
383     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
384     bmi.bmiHeader.biHeight = HEIGHT1;
385     bmi.bmiHeader.biWidth = WIDTH1;
386     bmi.bmiHeader.biBitCount = 24;
387     bmi.bmiHeader.biPlanes = 1;
388     bmi.bmiHeader.biCompression = BI_RGB;
389
390     hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
391     ok(hbm != NULL, "CreateDIBSection failed\n");
392
393     stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
394     expect(Ok, stat);
395     expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
396     ok(fabs(WIDTH1 - width) < .0001, "width wrong\n");
397     ok(fabs(HEIGHT1 - height) < .0001, "height wrong\n");
398     if (stat == Ok)
399         GdipDisposeImage((GpImage*)gpbm);
400
401     LogPal = GdipAlloc(sizeof(LOGPALETTE));
402     ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
403     LogPal->palVersion = 0x300;
404     hpal = CreatePalette((const LOGPALETTE*) LogPal);
405     ok(hpal != NULL, "CreatePalette failed\n");
406     GdipFree(LogPal);
407
408     stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
409     todo_wine
410     {
411         expect(Ok, stat);
412     }
413     if (stat == Ok)
414         GdipDisposeImage((GpImage*)gpbm);
415
416     GlobalFree(hpal);
417     GlobalFree(hbm);
418 }
419
420 START_TEST(image)
421 {
422     struct GdiplusStartupInput gdiplusStartupInput;
423     ULONG_PTR gdiplusToken;
424
425     gdiplusStartupInput.GdiplusVersion              = 1;
426     gdiplusStartupInput.DebugEventCallback          = NULL;
427     gdiplusStartupInput.SuppressBackgroundThread    = 0;
428     gdiplusStartupInput.SuppressExternalCodecs      = 0;
429
430     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
431
432     test_Scan0();
433     test_GetImageDimension();
434     test_LoadingImages();
435     test_SavingImages();
436     test_encoders();
437     test_LockBits();
438     test_GdipCreateBitmapFromHBITMAP();
439
440     GdiplusShutdown(gdiplusToken);
441 }