[GDIPLUS] Sync with Wine 3.0. CORE-14225
[reactos.git] / modules / rostests / winetests / gdiplus / image.c
1 /*
2 * Unit test suite for images
3 *
4 * Copyright (C) 2007 Google (Evan Stade)
5 * Copyright (C) 2012,2016 Dmitry Timoshkov
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "precomp.h"
23
24 #include <assert.h>
25 #include <ole2.h>
26
27 /* FIXME: They belong to gdipluseffects.h */
28 DEFINE_GUID(BlurEffectGuid, 0x633c80a4, 0x1843, 0x482b, 0x9e, 0xf2, 0xbe, 0x28, 0x34, 0xc5, 0xfd, 0xd4);
29 DEFINE_GUID(SharpenEffectGuid, 0x63cbf3ee, 0xc526, 0x402c, 0x8f, 0x71, 0x62, 0xc5, 0x40, 0xbf, 0x51, 0x42);
30 DEFINE_GUID(ColorMatrixEffectGuid, 0x718f2615, 0x7933, 0x40e3, 0xa5, 0x11, 0x5f, 0x68, 0xfe, 0x14, 0xdd, 0x74);
31 DEFINE_GUID(ColorLUTEffectGuid, 0xa7ce72a9, 0x0f7f, 0x40d7, 0xb3, 0xcc, 0xd0, 0xc0, 0x2d, 0x5c, 0x32, 0x12);
32 DEFINE_GUID(BrightnessContrastEffectGuid, 0xd3a1dbe1, 0x8ec4, 0x4c17, 0x9f, 0x4c, 0xea, 0x97, 0xad, 0x1c, 0x34, 0x3d);
33 DEFINE_GUID(HueSaturationLightnessEffectGuid, 0x8b2dd6c3, 0xeb07, 0x4d87, 0xa5, 0xf0, 0x71, 0x08, 0xe2, 0x6a, 0x9c, 0x5f);
34 DEFINE_GUID(LevelsEffectGuid, 0x99c354ec, 0x2a31, 0x4f3a, 0x8c, 0x34, 0x17, 0xa8, 0x03, 0xb3, 0x3a, 0x25);
35 DEFINE_GUID(TintEffectGuid, 0x1077af00, 0x2848, 0x4441, 0x94, 0x89, 0x44, 0xad, 0x4c, 0x2d, 0x7a, 0x2c);
36 DEFINE_GUID(ColorBalanceEffectGuid, 0x537e597d, 0x251e, 0x48da, 0x96, 0x64, 0x29, 0xca, 0x49, 0x6b, 0x70, 0xf8);
37 DEFINE_GUID(RedEyeCorrectionEffectGuid, 0x74d29d05, 0x69a4, 0x4266, 0x95, 0x49, 0x3c, 0xc5, 0x28, 0x36, 0xb6, 0x32);
38 DEFINE_GUID(ColorCurveEffectGuid, 0xdd6a0022, 0x58e4, 0x4a67, 0x9d, 0x9b, 0xd4, 0x8e, 0xb8, 0x81, 0xa5, 0x3d);
39
40 static GpStatus (WINAPI *pGdipBitmapGetHistogramSize)(HistogramFormat,UINT*);
41 static GpStatus (WINAPI *pGdipBitmapGetHistogram)(GpBitmap*,HistogramFormat,UINT,UINT*,UINT*,UINT*,UINT*);
42 static GpStatus (WINAPI *pGdipImageSetAbort)(GpImage*,GdiplusAbort*);
43
44 static GpStatus (WINGDIPAPI *pGdipInitializePalette)(ColorPalette*,PaletteType,INT,BOOL,GpBitmap*);
45
46 #define expect(expected, got) ok((got) == (expected), "Expected %d, got %d\n", (UINT)(expected), (UINT)(got))
47 #define expectf(expected, got) ok(fabs((expected) - (got)) < 0.0001, "Expected %f, got %f\n", (expected), (got))
48
49 static BOOL color_match(ARGB c1, ARGB c2, BYTE max_diff)
50 {
51 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
52 c1 >>= 8; c2 >>= 8;
53 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
54 c1 >>= 8; c2 >>= 8;
55 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
56 c1 >>= 8; c2 >>= 8;
57 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
58 return TRUE;
59 }
60
61 static void expect_guid(REFGUID expected, REFGUID got, int line, BOOL todo)
62 {
63 WCHAR bufferW[39];
64 char buffer[39];
65 char buffer2[39];
66
67 StringFromGUID2(got, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
68 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
69 StringFromGUID2(expected, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
70 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer2, sizeof(buffer2), NULL, NULL);
71 todo_wine_if (todo)
72 ok_(__FILE__, line)(IsEqualGUID(expected, got), "Expected %s, got %s\n", buffer2, buffer);
73 }
74
75 static void expect_rawformat(REFGUID expected, GpImage *img, int line, BOOL todo)
76 {
77 GUID raw;
78 GpStatus stat;
79
80 stat = GdipGetImageRawFormat(img, &raw);
81 ok_(__FILE__, line)(stat == Ok, "GdipGetImageRawFormat failed with %d\n", stat);
82 if(stat != Ok) return;
83 expect_guid(expected, &raw, line, todo);
84 }
85
86 static void test_bufferrawformat(void* buff, int size, REFGUID expected, int line, BOOL todo)
87 {
88 LPSTREAM stream;
89 HGLOBAL hglob;
90 LPBYTE data;
91 HRESULT hres;
92 GpStatus stat;
93 GpImage *img;
94
95 hglob = GlobalAlloc (0, size);
96 data = GlobalLock (hglob);
97 memcpy(data, buff, size);
98 GlobalUnlock(hglob); data = NULL;
99
100 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
101 ok_(__FILE__, line)(hres == S_OK, "Failed to create a stream\n");
102 if(hres != S_OK) return;
103
104 stat = GdipLoadImageFromStream(stream, &img);
105 ok_(__FILE__, line)(stat == Ok, "Failed to create a Bitmap\n");
106 if(stat != Ok){
107 IStream_Release(stream);
108 return;
109 }
110
111 expect_rawformat(expected, img, line, todo);
112
113 GdipDisposeImage(img);
114 IStream_Release(stream);
115 }
116
117 static void test_Scan0(void)
118 {
119 GpBitmap *bm;
120 GpStatus stat;
121 BYTE buff[360];
122
123 bm = NULL;
124 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
125 expect(Ok, stat);
126 ok(NULL != bm, "Expected bitmap to be initialized\n");
127 if (stat == Ok)
128 GdipDisposeImage((GpImage*)bm);
129
130 bm = (GpBitmap*)0xdeadbeef;
131 stat = GdipCreateBitmapFromScan0(10, -10, 10, PixelFormat24bppRGB, NULL, &bm);
132 expect(InvalidParameter, stat);
133 ok( !bm, "expected null bitmap\n" );
134
135 bm = (GpBitmap*)0xdeadbeef;
136 stat = GdipCreateBitmapFromScan0(-10, 10, 10, PixelFormat24bppRGB, NULL, &bm);
137 expect(InvalidParameter, stat);
138 ok( !bm, "expected null bitmap\n" );
139
140 bm = (GpBitmap*)0xdeadbeef;
141 stat = GdipCreateBitmapFromScan0(10, 0, 10, PixelFormat24bppRGB, NULL, &bm);
142 expect(InvalidParameter, stat);
143 ok( !bm, "expected null bitmap\n" );
144
145 bm = NULL;
146 stat = GdipCreateBitmapFromScan0(10, 10, 12, PixelFormat24bppRGB, buff, &bm);
147 expect(Ok, stat);
148 ok(NULL != bm, "Expected bitmap to be initialized\n");
149 if (stat == Ok)
150 GdipDisposeImage((GpImage*)bm);
151
152 bm = (GpBitmap*) 0xdeadbeef;
153 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, buff, &bm);
154 expect(InvalidParameter, stat);
155 ok( !bm, "expected null bitmap\n" );
156
157 bm = (GpBitmap*)0xdeadbeef;
158 stat = GdipCreateBitmapFromScan0(10, 10, 0, PixelFormat24bppRGB, buff, &bm);
159 expect(InvalidParameter, stat);
160 ok( bm == (GpBitmap*)0xdeadbeef, "expected deadbeef bitmap\n" );
161
162 bm = NULL;
163 stat = GdipCreateBitmapFromScan0(10, 10, -8, PixelFormat24bppRGB, buff, &bm);
164 expect(Ok, stat);
165 ok(NULL != bm, "Expected bitmap to be initialized\n");
166 if (stat == Ok)
167 GdipDisposeImage((GpImage*)bm);
168
169 bm = (GpBitmap*)0xdeadbeef;
170 stat = GdipCreateBitmapFromScan0(10, 10, -10, PixelFormat24bppRGB, buff, &bm);
171 expect(InvalidParameter, stat);
172 ok( !bm, "expected null bitmap\n" );
173 }
174
175 static void test_FromGdiDib(void)
176 {
177 GpBitmap *bm;
178 GpStatus stat;
179 BYTE buff[400];
180 BYTE rbmi[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
181 BITMAPINFO *bmi = (BITMAPINFO*)rbmi;
182 PixelFormat format;
183
184 bm = NULL;
185
186 memset(rbmi, 0, sizeof(rbmi));
187
188 bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
189 bmi->bmiHeader.biWidth = 10;
190 bmi->bmiHeader.biHeight = 10;
191 bmi->bmiHeader.biPlanes = 1;
192 bmi->bmiHeader.biBitCount = 32;
193 bmi->bmiHeader.biCompression = BI_RGB;
194
195 stat = GdipCreateBitmapFromGdiDib(NULL, buff, &bm);
196 expect(InvalidParameter, stat);
197
198 stat = GdipCreateBitmapFromGdiDib(bmi, NULL, &bm);
199 expect(InvalidParameter, stat);
200
201 stat = GdipCreateBitmapFromGdiDib(bmi, buff, NULL);
202 expect(InvalidParameter, stat);
203
204 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
205 expect(Ok, stat);
206 ok(NULL != bm, "Expected bitmap to be initialized\n");
207 if (stat == Ok)
208 {
209 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
210 expect(Ok, stat);
211 expect(PixelFormat32bppRGB, format);
212
213 GdipDisposeImage((GpImage*)bm);
214 }
215
216 bmi->bmiHeader.biBitCount = 24;
217 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
218 expect(Ok, stat);
219 ok(NULL != bm, "Expected bitmap to be initialized\n");
220 if (stat == Ok)
221 {
222 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
223 expect(Ok, stat);
224 expect(PixelFormat24bppRGB, format);
225
226 GdipDisposeImage((GpImage*)bm);
227 }
228
229 bmi->bmiHeader.biBitCount = 16;
230 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
231 expect(Ok, stat);
232 ok(NULL != bm, "Expected bitmap to be initialized\n");
233 if (stat == Ok)
234 {
235 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
236 expect(Ok, stat);
237 expect(PixelFormat16bppRGB555, format);
238
239 GdipDisposeImage((GpImage*)bm);
240 }
241
242 bmi->bmiHeader.biBitCount = 8;
243 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
244 expect(Ok, stat);
245 ok(NULL != bm, "Expected bitmap to be initialized\n");
246 if (stat == Ok)
247 {
248 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
249 expect(Ok, stat);
250 expect(PixelFormat8bppIndexed, format);
251
252 GdipDisposeImage((GpImage*)bm);
253 }
254
255 bmi->bmiHeader.biBitCount = 4;
256 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
257 expect(Ok, stat);
258 ok(NULL != bm, "Expected bitmap to be initialized\n");
259 if (stat == Ok)
260 {
261 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
262 expect(Ok, stat);
263 expect(PixelFormat4bppIndexed, format);
264
265 GdipDisposeImage((GpImage*)bm);
266 }
267
268 bmi->bmiHeader.biBitCount = 1;
269 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
270 expect(Ok, stat);
271 ok(NULL != bm, "Expected bitmap to be initialized\n");
272 if (stat == Ok)
273 {
274 stat = GdipGetImagePixelFormat((GpImage*)bm, &format);
275 expect(Ok, stat);
276 expect(PixelFormat1bppIndexed, format);
277
278 GdipDisposeImage((GpImage*)bm);
279 }
280
281 bmi->bmiHeader.biBitCount = 0;
282 stat = GdipCreateBitmapFromGdiDib(bmi, buff, &bm);
283 expect(InvalidParameter, stat);
284 }
285
286 static void test_GetImageDimension(void)
287 {
288 GpBitmap *bm;
289 GpStatus stat;
290 const REAL WIDTH = 10.0, HEIGHT = 20.0;
291 REAL w,h;
292
293 bm = (GpBitmap*)0xdeadbeef;
294 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
295 expect(Ok,stat);
296 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
297 ok(NULL != bm, "Expected bitmap to not be NULL\n");
298
299 stat = GdipGetImageDimension(NULL,&w,&h);
300 expect(InvalidParameter, stat);
301
302 stat = GdipGetImageDimension((GpImage*)bm,NULL,&h);
303 expect(InvalidParameter, stat);
304
305 stat = GdipGetImageDimension((GpImage*)bm,&w,NULL);
306 expect(InvalidParameter, stat);
307
308 w = -1;
309 h = -1;
310 stat = GdipGetImageDimension((GpImage*)bm,&w,&h);
311 expect(Ok, stat);
312 expectf(WIDTH, w);
313 expectf(HEIGHT, h);
314 GdipDisposeImage((GpImage*)bm);
315 }
316
317 static void test_GdipImageGetFrameDimensionsCount(void)
318 {
319 GpBitmap *bm;
320 GpStatus stat;
321 const REAL WIDTH = 10.0, HEIGHT = 20.0;
322 UINT w;
323 GUID dimension = {0};
324 UINT count;
325 ARGB color;
326
327 bm = (GpBitmap*)0xdeadbeef;
328 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB,NULL, &bm);
329 expect(Ok,stat);
330 ok((GpBitmap*)0xdeadbeef != bm, "Expected bitmap to not be 0xdeadbeef\n");
331 ok(NULL != bm, "Expected bitmap to not be NULL\n");
332
333 stat = GdipImageGetFrameDimensionsCount(NULL,&w);
334 expect(InvalidParameter, stat);
335
336 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,NULL);
337 expect(InvalidParameter, stat);
338
339 w = -1;
340 stat = GdipImageGetFrameDimensionsCount((GpImage*)bm,&w);
341 expect(Ok, stat);
342 expect(1, w);
343
344 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 1);
345 expect(Ok, stat);
346 expect_guid(&FrameDimensionPage, &dimension, __LINE__, FALSE);
347
348 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 2);
349 expect(InvalidParameter, stat);
350
351 stat = GdipImageGetFrameDimensionsList((GpImage*)bm, &dimension, 0);
352 expect(InvalidParameter, stat);
353
354 stat = GdipImageGetFrameCount(NULL, &dimension, &count);
355 expect(InvalidParameter, stat);
356
357 /* WinXP crashes on this test */
358 if(0)
359 {
360 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, NULL);
361 expect(InvalidParameter, stat);
362 }
363
364 stat = GdipImageGetFrameCount((GpImage*)bm, NULL, &count);
365 expect(Ok, stat);
366
367 count = 12345;
368 stat = GdipImageGetFrameCount((GpImage*)bm, &dimension, &count);
369 expect(Ok, stat);
370 expect(1, count);
371
372 GdipBitmapSetPixel(bm, 0, 0, 0xffffffff);
373
374 stat = GdipImageSelectActiveFrame((GpImage*)bm, &dimension, 0);
375 expect(Ok, stat);
376
377 /* SelectActiveFrame has no effect on image data of memory bitmaps */
378 color = 0xdeadbeef;
379 GdipBitmapGetPixel(bm, 0, 0, &color);
380 expect(0xffffffff, color);
381
382 GdipDisposeImage((GpImage*)bm);
383 }
384
385 static void test_LoadingImages(void)
386 {
387 GpStatus stat;
388 GpBitmap *bm;
389 GpImage *img;
390 static const WCHAR nonexistentW[] = {'n','o','n','e','x','i','s','t','e','n','t',0};
391
392 stat = GdipCreateBitmapFromFile(0, 0);
393 expect(InvalidParameter, stat);
394
395 bm = (GpBitmap *)0xdeadbeef;
396 stat = GdipCreateBitmapFromFile(0, &bm);
397 expect(InvalidParameter, stat);
398 ok(bm == (GpBitmap *)0xdeadbeef, "returned %p\n", bm);
399
400 bm = (GpBitmap *)0xdeadbeef;
401 stat = GdipCreateBitmapFromFile(nonexistentW, &bm);
402 todo_wine expect(InvalidParameter, stat);
403 ok(!bm, "returned %p\n", bm);
404
405 stat = GdipLoadImageFromFile(0, 0);
406 expect(InvalidParameter, stat);
407
408 img = (GpImage *)0xdeadbeef;
409 stat = GdipLoadImageFromFile(0, &img);
410 expect(InvalidParameter, stat);
411 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
412
413 img = (GpImage *)0xdeadbeef;
414 stat = GdipLoadImageFromFile(nonexistentW, &img);
415 todo_wine expect(OutOfMemory, stat);
416 ok(!img, "returned %p\n", img);
417
418 stat = GdipLoadImageFromFileICM(0, 0);
419 expect(InvalidParameter, stat);
420
421 img = (GpImage *)0xdeadbeef;
422 stat = GdipLoadImageFromFileICM(0, &img);
423 expect(InvalidParameter, stat);
424 ok(img == (GpImage *)0xdeadbeef, "returned %p\n", img);
425
426 img = (GpImage *)0xdeadbeef;
427 stat = GdipLoadImageFromFileICM(nonexistentW, &img);
428 todo_wine expect(OutOfMemory, stat);
429 ok(!img, "returned %p\n", img);
430 }
431
432 static void test_SavingImages(void)
433 {
434 GpStatus stat;
435 GpBitmap *bm;
436 UINT n;
437 UINT s;
438 const REAL WIDTH = 10.0, HEIGHT = 20.0;
439 REAL w, h;
440 ImageCodecInfo *codecs;
441 static const CHAR filenameA[] = "a.bmp";
442 static const WCHAR filename[] = { 'a','.','b','m','p',0 };
443
444 codecs = NULL;
445
446 stat = GdipSaveImageToFile(0, 0, 0, 0);
447 expect(InvalidParameter, stat);
448
449 bm = NULL;
450 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
451 expect(Ok, stat);
452 if (!bm)
453 return;
454
455 /* invalid params */
456 stat = GdipSaveImageToFile((GpImage*)bm, 0, 0, 0);
457 expect(InvalidParameter, stat);
458
459 stat = GdipSaveImageToFile((GpImage*)bm, filename, 0, 0);
460 expect(InvalidParameter, stat);
461
462 /* encoder tests should succeed -- already tested */
463 stat = GdipGetImageEncodersSize(&n, &s);
464 if (stat != Ok || n == 0) goto cleanup;
465
466 codecs = GdipAlloc(s);
467 if (!codecs) goto cleanup;
468
469 stat = GdipGetImageEncoders(n, s, codecs);
470 if (stat != Ok) goto cleanup;
471
472 stat = GdipSaveImageToFile((GpImage*)bm, filename, &codecs[0].Clsid, 0);
473 expect(Ok, stat);
474
475 GdipDisposeImage((GpImage*)bm);
476 bm = 0;
477
478 /* re-load and check image stats */
479 stat = GdipLoadImageFromFile(filename, (GpImage**)&bm);
480 expect(Ok, stat);
481 if (stat != Ok) goto cleanup;
482
483 stat = GdipGetImageDimension((GpImage*)bm, &w, &h);
484 if (stat != Ok) goto cleanup;
485
486 expectf(WIDTH, w);
487 expectf(HEIGHT, h);
488
489 cleanup:
490 GdipFree(codecs);
491 if (bm)
492 GdipDisposeImage((GpImage*)bm);
493 ok(DeleteFileA(filenameA), "Delete failed.\n");
494 }
495
496 static void test_encoders(void)
497 {
498 GpStatus stat;
499 UINT n;
500 UINT s;
501 ImageCodecInfo *codecs;
502 int i;
503 int bmp_found;
504
505 static const CHAR bmp_format[] = "BMP";
506
507 stat = GdipGetImageEncodersSize(&n, &s);
508 expect(stat, Ok);
509
510 codecs = GdipAlloc(s);
511 if (!codecs)
512 return;
513
514 stat = GdipGetImageEncoders(n, s, NULL);
515 expect(GenericError, stat);
516
517 stat = GdipGetImageEncoders(0, s, codecs);
518 expect(GenericError, stat);
519
520 stat = GdipGetImageEncoders(n, s-1, codecs);
521 expect(GenericError, stat);
522
523 stat = GdipGetImageEncoders(n, s+1, codecs);
524 expect(GenericError, stat);
525
526 stat = GdipGetImageEncoders(n, s, codecs);
527 expect(stat, Ok);
528
529 bmp_found = FALSE;
530 for (i = 0; i < n; i++)
531 {
532 CHAR desc[32];
533
534 WideCharToMultiByte(CP_ACP, 0, codecs[i].FormatDescription, -1,
535 desc, 32, 0, 0);
536
537 if (CompareStringA(LOCALE_SYSTEM_DEFAULT, 0,
538 desc, -1,
539 bmp_format, -1) == CSTR_EQUAL) {
540 bmp_found = TRUE;
541 break;
542 }
543 }
544 if (!bmp_found)
545 ok(FALSE, "No BMP codec found.\n");
546
547 GdipFree(codecs);
548 }
549
550 static void test_LockBits(void)
551 {
552 GpStatus stat;
553 GpBitmap *bm;
554 GpRect rect;
555 BitmapData bd;
556 const INT WIDTH = 10, HEIGHT = 20;
557 ARGB color;
558 int y;
559
560 bm = NULL;
561 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
562 expect(Ok, stat);
563
564 rect.X = 2;
565 rect.Y = 3;
566 rect.Width = 4;
567 rect.Height = 5;
568
569 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
570 expect(Ok, stat);
571
572 stat = GdipBitmapSetPixel(bm, 2, 8, 0xff480000);
573 expect(Ok, stat);
574
575 /* read-only */
576 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
577 expect(Ok, stat);
578
579 if (stat == Ok) {
580 expect(0xc3, ((BYTE*)bd.Scan0)[2]);
581 expect(0x48, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
582
583 ((char*)bd.Scan0)[2] = 0xff;
584
585 stat = GdipBitmapUnlockBits(bm, &bd);
586 expect(Ok, stat);
587 }
588
589 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
590 expect(Ok, stat);
591 expect(0xffff0000, color);
592
593 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffc30000);
594 expect(Ok, stat);
595
596 /* read-only, with NULL rect -> whole bitmap lock */
597 stat = GdipBitmapLockBits(bm, NULL, ImageLockModeRead, PixelFormat24bppRGB, &bd);
598 expect(Ok, stat);
599 expect(bd.Width, WIDTH);
600 expect(bd.Height, HEIGHT);
601
602 if (stat == Ok) {
603 ((char*)bd.Scan0)[2 + 2*3 + 3*bd.Stride] = 0xff;
604
605 stat = GdipBitmapUnlockBits(bm, &bd);
606 expect(Ok, stat);
607 }
608
609 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
610 expect(Ok, stat);
611 expect(0xffff0000, color);
612
613 /* read-only, consecutive */
614 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
615 expect(Ok, stat);
616
617 if (stat == Ok) {
618 stat = GdipBitmapUnlockBits(bm, &bd);
619 expect(Ok, stat);
620 }
621
622 stat = GdipDisposeImage((GpImage*)bm);
623 expect(Ok, stat);
624 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
625 expect(Ok, stat);
626
627 /* read x2 */
628 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
629 expect(Ok, stat);
630 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
631 expect(WrongState, stat);
632
633 stat = GdipBitmapUnlockBits(bm, &bd);
634 expect(Ok, stat);
635
636 stat = GdipDisposeImage((GpImage*)bm);
637 expect(Ok, stat);
638 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
639 expect(Ok, stat);
640
641 stat = GdipBitmapSetPixel(bm, 2, 3, 0xffff0000);
642 expect(Ok, stat);
643
644 stat = GdipBitmapSetPixel(bm, 2, 8, 0xffc30000);
645 expect(Ok, stat);
646
647 /* write, no conversion */
648 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
649 expect(Ok, stat);
650
651 if (stat == Ok) {
652 /* all bits are readable, inside the rect or not */
653 expect(0xff, ((BYTE*)bd.Scan0)[2]);
654 expect(0xc3, ((BYTE*)bd.Scan0)[2 + bd.Stride * 5]);
655
656 stat = GdipBitmapUnlockBits(bm, &bd);
657 expect(Ok, stat);
658 }
659
660 /* read, conversion */
661 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat32bppARGB, &bd);
662 expect(Ok, stat);
663
664 if (stat == Ok) {
665 expect(0xff, ((BYTE*)bd.Scan0)[2]);
666 if (0)
667 /* Areas outside the rectangle appear to be uninitialized */
668 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
669
670 ((BYTE*)bd.Scan0)[2] = 0xc3;
671
672 stat = GdipBitmapUnlockBits(bm, &bd);
673 expect(Ok, stat);
674 }
675
676 /* writes do not work in read mode if there was a conversion */
677 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
678 expect(Ok, stat);
679 expect(0xffff0000, color);
680
681 /* read/write, conversion */
682 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite, PixelFormat32bppARGB, &bd);
683 expect(Ok, stat);
684
685 if (stat == Ok) {
686 expect(0xff, ((BYTE*)bd.Scan0)[2]);
687 ((BYTE*)bd.Scan0)[1] = 0x88;
688 if (0)
689 /* Areas outside the rectangle appear to be uninitialized */
690 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
691
692 stat = GdipBitmapUnlockBits(bm, &bd);
693 expect(Ok, stat);
694 }
695
696 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
697 expect(Ok, stat);
698 expect(0xffff8800, color);
699
700 /* write, conversion */
701 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat32bppARGB, &bd);
702 expect(Ok, stat);
703
704 if (stat == Ok) {
705 if (0)
706 {
707 /* This is completely uninitialized. */
708 ok(0xff != ((BYTE*)bd.Scan0)[2], "original image bits are readable\n");
709 ok(0xc3 != ((BYTE*)bd.Scan0)[2 + bd.Stride * 5], "original image bits are readable\n");
710 }
711
712 /* Initialize the buffer so the unlock doesn't access undefined memory */
713 for (y=0; y<5; y++)
714 memset(((BYTE*)bd.Scan0) + bd.Stride * y, 0, 12);
715
716 ((BYTE*)bd.Scan0)[0] = 0x12;
717 ((BYTE*)bd.Scan0)[1] = 0x34;
718 ((BYTE*)bd.Scan0)[2] = 0x56;
719
720 stat = GdipBitmapUnlockBits(bm, &bd);
721 expect(Ok, stat);
722 }
723
724 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
725 expect(Ok, stat);
726 expect(0xff563412, color);
727
728 stat = GdipBitmapGetPixel(bm, 2, 8, &color);
729 expect(Ok, stat);
730 expect(0xffc30000, color);
731
732 stat = GdipDisposeImage((GpImage*)bm);
733 expect(Ok, stat);
734 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
735 expect(Ok, stat);
736
737 /* write, no modification */
738 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
739 expect(Ok, stat);
740
741 if (stat == Ok) {
742 stat = GdipBitmapUnlockBits(bm, &bd);
743 expect(Ok, stat);
744 }
745
746 /* write, consecutive */
747 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
748 expect(Ok, stat);
749
750 if (stat == Ok) {
751 stat = GdipBitmapUnlockBits(bm, &bd);
752 expect(Ok, stat);
753 }
754
755 stat = GdipDisposeImage((GpImage*)bm);
756 expect(Ok, stat);
757 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
758 expect(Ok, stat);
759
760 /* write, modify */
761 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite, PixelFormat24bppRGB, &bd);
762 expect(Ok, stat);
763
764 if (stat == Ok) {
765 if (bd.Scan0)
766 ((char*)bd.Scan0)[2] = 0xff;
767
768 stat = GdipBitmapUnlockBits(bm, &bd);
769 expect(Ok, stat);
770 }
771
772 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
773 expect(Ok, stat);
774 expect(0xffff0000, color);
775
776 stat = GdipDisposeImage((GpImage*)bm);
777 expect(Ok, stat);
778
779 /* dispose locked */
780 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
781 expect(Ok, stat);
782 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead, PixelFormat24bppRGB, &bd);
783 expect(Ok, stat);
784 stat = GdipDisposeImage((GpImage*)bm);
785 expect(Ok, stat);
786 }
787
788 static void test_LockBits_UserBuf(void)
789 {
790 GpStatus stat;
791 GpBitmap *bm;
792 GpRect rect;
793 BitmapData bd;
794 const INT WIDTH = 10, HEIGHT = 20;
795 DWORD bits[200];
796 ARGB color;
797
798 bm = NULL;
799 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat32bppARGB, NULL, &bm);
800 expect(Ok, stat);
801
802 memset(bits, 0xaa, sizeof(bits));
803
804 rect.X = 2;
805 rect.Y = 3;
806 rect.Width = 4;
807 rect.Height = 5;
808
809 bd.Width = 4;
810 bd.Height = 6;
811 bd.Stride = WIDTH * 4;
812 bd.PixelFormat = PixelFormat32bppARGB;
813 bd.Scan0 = &bits[2+3*WIDTH];
814 bd.Reserved = 0xaaaaaaaa;
815
816 /* read-only */
817 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
818 expect(Ok, stat);
819
820 expect(0xaaaaaaaa, bits[0]);
821 expect(0, bits[2+3*WIDTH]);
822
823 bits[2+3*WIDTH] = 0xdeadbeef;
824
825 if (stat == Ok) {
826 stat = GdipBitmapUnlockBits(bm, &bd);
827 expect(Ok, stat);
828 }
829
830 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
831 expect(Ok, stat);
832 expect(0, color);
833
834 /* write-only */
835 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
836 expect(Ok, stat);
837
838 expect(0xdeadbeef, bits[2+3*WIDTH]);
839 bits[2+3*WIDTH] = 0x12345678;
840
841 if (stat == Ok) {
842 stat = GdipBitmapUnlockBits(bm, &bd);
843 expect(Ok, stat);
844 }
845
846 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
847 expect(Ok, stat);
848 expect(0x12345678, color);
849
850 bits[2+3*WIDTH] = 0;
851
852 /* read/write */
853 stat = GdipBitmapLockBits(bm, &rect, ImageLockModeRead|ImageLockModeWrite|ImageLockModeUserInputBuf, PixelFormat32bppARGB, &bd);
854 expect(Ok, stat);
855
856 expect(0x12345678, bits[2+3*WIDTH]);
857 bits[2+3*WIDTH] = 0xdeadbeef;
858
859 if (stat == Ok) {
860 stat = GdipBitmapUnlockBits(bm, &bd);
861 expect(Ok, stat);
862 }
863
864 stat = GdipBitmapGetPixel(bm, 2, 3, &color);
865 expect(Ok, stat);
866 expect(0xdeadbeef, color);
867
868 stat = GdipDisposeImage((GpImage*)bm);
869 expect(Ok, stat);
870 }
871
872 struct BITMAPINFOWITHBITFIELDS
873 {
874 BITMAPINFOHEADER bmiHeader;
875 DWORD masks[3];
876 };
877
878 union BITMAPINFOUNION
879 {
880 BITMAPINFO bi;
881 struct BITMAPINFOWITHBITFIELDS bf;
882 };
883
884 static void test_GdipCreateBitmapFromHBITMAP(void)
885 {
886 GpBitmap* gpbm = NULL;
887 HBITMAP hbm = NULL;
888 HPALETTE hpal = NULL;
889 GpStatus stat;
890 BYTE buff[1000];
891 LOGPALETTE* LogPal = NULL;
892 REAL width, height;
893 const REAL WIDTH1 = 5;
894 const REAL HEIGHT1 = 15;
895 const REAL WIDTH2 = 10;
896 const REAL HEIGHT2 = 20;
897 HDC hdc;
898 union BITMAPINFOUNION bmi;
899 BYTE *bits;
900 PixelFormat format;
901
902 stat = GdipCreateBitmapFromHBITMAP(NULL, NULL, NULL);
903 expect(InvalidParameter, stat);
904
905 hbm = CreateBitmap(WIDTH1, HEIGHT1, 1, 1, NULL);
906 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, NULL);
907 expect(InvalidParameter, stat);
908
909 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
910 expect(Ok, stat);
911 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
912 expectf(WIDTH1, width);
913 expectf(HEIGHT1, height);
914 if (stat == Ok)
915 GdipDisposeImage((GpImage*)gpbm);
916 DeleteObject(hbm);
917
918 memset(buff, 0, sizeof(buff));
919 hbm = CreateBitmap(WIDTH2, HEIGHT2, 1, 1, &buff);
920 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
921 expect(Ok, stat);
922 /* raw format */
923 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)gpbm, __LINE__, FALSE);
924
925 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
926 expectf(WIDTH2, width);
927 expectf(HEIGHT2, height);
928 if (stat == Ok)
929 GdipDisposeImage((GpImage*)gpbm);
930 DeleteObject(hbm);
931
932 hdc = CreateCompatibleDC(0);
933 ok(hdc != NULL, "CreateCompatibleDC failed\n");
934 bmi.bi.bmiHeader.biSize = sizeof(bmi.bi.bmiHeader);
935 bmi.bi.bmiHeader.biHeight = HEIGHT1;
936 bmi.bi.bmiHeader.biWidth = WIDTH1;
937 bmi.bi.bmiHeader.biBitCount = 24;
938 bmi.bi.bmiHeader.biPlanes = 1;
939 bmi.bi.bmiHeader.biCompression = BI_RGB;
940 bmi.bi.bmiHeader.biClrUsed = 0;
941
942 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
943 ok(hbm != NULL, "CreateDIBSection failed\n");
944
945 bits[0] = 0;
946
947 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
948 expect(Ok, stat);
949 expect(Ok, GdipGetImageDimension((GpImage*) gpbm, &width, &height));
950 expectf(WIDTH1, width);
951 expectf(HEIGHT1, height);
952 if (stat == Ok)
953 {
954 /* test whether writing to the bitmap affects the original */
955 stat = GdipBitmapSetPixel(gpbm, 0, 0, 0xffffffff);
956 expect(Ok, stat);
957
958 expect(0, bits[0]);
959
960 GdipDisposeImage((GpImage*)gpbm);
961 }
962
963 LogPal = GdipAlloc(sizeof(LOGPALETTE));
964 ok(LogPal != NULL, "unable to allocate LOGPALETTE\n");
965 LogPal->palVersion = 0x300;
966 LogPal->palNumEntries = 1;
967 hpal = CreatePalette(LogPal);
968 ok(hpal != NULL, "CreatePalette failed\n");
969 GdipFree(LogPal);
970
971 stat = GdipCreateBitmapFromHBITMAP(hbm, hpal, &gpbm);
972 expect(Ok, stat);
973
974 if (stat == Ok)
975 GdipDisposeImage((GpImage*)gpbm);
976
977 DeleteObject(hpal);
978 DeleteObject(hbm);
979
980 /* 16-bit 555 dib, rgb */
981 bmi.bi.bmiHeader.biBitCount = 16;
982 bmi.bi.bmiHeader.biCompression = BI_RGB;
983
984 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
985 ok(hbm != NULL, "CreateDIBSection failed\n");
986
987 bits[0] = 0;
988
989 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
990 expect(Ok, stat);
991
992 if (stat == Ok)
993 {
994 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
995 expect(Ok, stat);
996 expectf(WIDTH1, width);
997 expectf(HEIGHT1, height);
998
999 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1000 expect(Ok, stat);
1001 expect(PixelFormat16bppRGB555, format);
1002
1003 GdipDisposeImage((GpImage*)gpbm);
1004 }
1005 DeleteObject(hbm);
1006
1007 /* 16-bit 555 dib, with bitfields */
1008 bmi.bi.bmiHeader.biSize = sizeof(bmi);
1009 bmi.bi.bmiHeader.biCompression = BI_BITFIELDS;
1010 bmi.bf.masks[0] = 0x7c00;
1011 bmi.bf.masks[1] = 0x3e0;
1012 bmi.bf.masks[2] = 0x1f;
1013
1014 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1015 ok(hbm != NULL, "CreateDIBSection failed\n");
1016
1017 bits[0] = 0;
1018
1019 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1020 expect(Ok, stat);
1021
1022 if (stat == Ok)
1023 {
1024 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1025 expect(Ok, stat);
1026 expectf(WIDTH1, width);
1027 expectf(HEIGHT1, height);
1028
1029 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1030 expect(Ok, stat);
1031 expect(PixelFormat16bppRGB555, format);
1032
1033 GdipDisposeImage((GpImage*)gpbm);
1034 }
1035 DeleteObject(hbm);
1036
1037 /* 16-bit 565 dib, with bitfields */
1038 bmi.bf.masks[0] = 0xf800;
1039 bmi.bf.masks[1] = 0x7e0;
1040 bmi.bf.masks[2] = 0x1f;
1041
1042 hbm = CreateDIBSection(hdc, &bmi.bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1043 ok(hbm != NULL, "CreateDIBSection failed\n");
1044
1045 bits[0] = 0;
1046
1047 stat = GdipCreateBitmapFromHBITMAP(hbm, NULL, &gpbm);
1048 expect(Ok, stat);
1049
1050 if (stat == Ok)
1051 {
1052 stat = GdipGetImageDimension((GpImage*) gpbm, &width, &height);
1053 expect(Ok, stat);
1054 expectf(WIDTH1, width);
1055 expectf(HEIGHT1, height);
1056
1057 stat = GdipGetImagePixelFormat((GpImage*) gpbm, &format);
1058 expect(Ok, stat);
1059 expect(PixelFormat16bppRGB565, format);
1060
1061 GdipDisposeImage((GpImage*)gpbm);
1062 }
1063 DeleteObject(hbm);
1064
1065 DeleteDC(hdc);
1066 }
1067
1068 static void test_GdipGetImageFlags(void)
1069 {
1070 GpImage *img;
1071 GpStatus stat;
1072 UINT flags;
1073
1074 img = (GpImage*)0xdeadbeef;
1075
1076 stat = GdipGetImageFlags(NULL, NULL);
1077 expect(InvalidParameter, stat);
1078
1079 stat = GdipGetImageFlags(NULL, &flags);
1080 expect(InvalidParameter, stat);
1081
1082 stat = GdipGetImageFlags(img, NULL);
1083 expect(InvalidParameter, stat);
1084
1085 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat1bppIndexed, NULL, (GpBitmap**)&img);
1086 expect(Ok, stat);
1087 stat = GdipGetImageFlags(img, &flags);
1088 expect(Ok, stat);
1089 expect(ImageFlagsHasAlpha, flags);
1090 GdipDisposeImage(img);
1091
1092 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat4bppIndexed, NULL, (GpBitmap**)&img);
1093 expect(Ok, stat);
1094 stat = GdipGetImageFlags(img, &flags);
1095 expect(Ok, stat);
1096 expect(ImageFlagsHasAlpha, flags);
1097 GdipDisposeImage(img);
1098
1099 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat8bppIndexed, NULL, (GpBitmap**)&img);
1100 expect(Ok, stat);
1101 stat = GdipGetImageFlags(img, &flags);
1102 expect(Ok, stat);
1103 expect(ImageFlagsHasAlpha, flags);
1104 GdipDisposeImage(img);
1105
1106 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppGrayScale, NULL, (GpBitmap**)&img);
1107 expect(Ok, stat);
1108 stat = GdipGetImageFlags(img, &flags);
1109 expect(Ok, stat);
1110 expect(ImageFlagsNone, flags);
1111 GdipDisposeImage(img);
1112
1113 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB555, NULL, (GpBitmap**)&img);
1114 expect(Ok, stat);
1115 stat = GdipGetImageFlags(img, &flags);
1116 expect(Ok, stat);
1117 expect(ImageFlagsNone, flags);
1118 GdipDisposeImage(img);
1119
1120 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppRGB565, NULL, (GpBitmap**)&img);
1121 expect(Ok, stat);
1122 stat = GdipGetImageFlags(img, &flags);
1123 expect(Ok, stat);
1124 expect(ImageFlagsNone, flags);
1125 GdipDisposeImage(img);
1126
1127 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat16bppARGB1555, NULL, (GpBitmap**)&img);
1128 expect(Ok, stat);
1129 stat = GdipGetImageFlags(img, &flags);
1130 expect(Ok, stat);
1131 expect(ImageFlagsHasAlpha, flags);
1132 GdipDisposeImage(img);
1133
1134 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat24bppRGB, NULL, (GpBitmap**)&img);
1135 expect(Ok, stat);
1136 stat = GdipGetImageFlags(img, &flags);
1137 expect(Ok, stat);
1138 expect(ImageFlagsNone, flags);
1139 GdipDisposeImage(img);
1140
1141 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppRGB, NULL, (GpBitmap**)&img);
1142 expect(Ok, stat);
1143 stat = GdipGetImageFlags(img, &flags);
1144 expect(Ok, stat);
1145 expect(ImageFlagsNone, flags);
1146 GdipDisposeImage(img);
1147
1148 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppARGB, NULL, (GpBitmap**)&img);
1149 expect(Ok, stat);
1150 stat = GdipGetImageFlags(img, &flags);
1151 expect(Ok, stat);
1152 expect(ImageFlagsHasAlpha, flags);
1153 GdipDisposeImage(img);
1154
1155 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat32bppPARGB, NULL, (GpBitmap**)&img);
1156 expect(Ok, stat);
1157 stat = GdipGetImageFlags(img, &flags);
1158 expect(Ok, stat);
1159 expect(ImageFlagsHasAlpha, flags);
1160 GdipDisposeImage(img);
1161
1162 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat48bppRGB, NULL, (GpBitmap**)&img);
1163 expect(Ok, stat);
1164 if (stat == Ok)
1165 {
1166 stat = GdipGetImageFlags(img, &flags);
1167 expect(Ok, stat);
1168 expect(ImageFlagsNone, flags);
1169 GdipDisposeImage(img);
1170 }
1171
1172 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppARGB, NULL, (GpBitmap**)&img);
1173 expect(Ok, stat);
1174 if (stat == Ok)
1175 {
1176 expect(Ok, stat);
1177 stat = GdipGetImageFlags(img, &flags);
1178 expect(Ok, stat);
1179 expect(ImageFlagsHasAlpha, flags);
1180 GdipDisposeImage(img);
1181 }
1182
1183 stat = GdipCreateBitmapFromScan0(10, 10, 10, PixelFormat64bppPARGB, NULL, (GpBitmap**)&img);
1184 expect(Ok, stat);
1185 if (stat == Ok)
1186 {
1187 expect(Ok, stat);
1188 stat = GdipGetImageFlags(img, &flags);
1189 expect(Ok, stat);
1190 expect(ImageFlagsHasAlpha, flags);
1191 GdipDisposeImage(img);
1192 }
1193 }
1194
1195 static void test_GdipCloneImage(void)
1196 {
1197 GpStatus stat;
1198 GpRectF rectF;
1199 GpUnit unit;
1200 GpBitmap *bm;
1201 GpImage *image_src, *image_dest = NULL;
1202 const INT WIDTH = 10, HEIGHT = 20;
1203
1204 /* Create an image, clone it, delete the original, make sure the copy works */
1205 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
1206 expect(Ok, stat);
1207 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bm, __LINE__, FALSE);
1208
1209 image_src = ((GpImage*)bm);
1210 stat = GdipCloneImage(image_src, &image_dest);
1211 expect(Ok, stat);
1212 expect_rawformat(&ImageFormatMemoryBMP, image_dest, __LINE__, FALSE);
1213
1214 stat = GdipDisposeImage((GpImage*)bm);
1215 expect(Ok, stat);
1216 stat = GdipGetImageBounds(image_dest, &rectF, &unit);
1217 expect(Ok, stat);
1218
1219 /* Treat FP values carefully */
1220 expectf((REAL)WIDTH, rectF.Width);
1221 expectf((REAL)HEIGHT, rectF.Height);
1222
1223 stat = GdipDisposeImage(image_dest);
1224 expect(Ok, stat);
1225 }
1226
1227 static void test_testcontrol(void)
1228 {
1229 GpStatus stat;
1230 DWORD param;
1231
1232 param = 0;
1233 stat = GdipTestControl(TestControlGetBuildNumber, &param);
1234 expect(Ok, stat);
1235 ok(param != 0, "Build number expected, got %u\n", param);
1236 }
1237
1238 static void test_fromhicon(void)
1239 {
1240 static const BYTE bmp_bits[1024];
1241 HBITMAP hbmMask, hbmColor;
1242 ICONINFO info;
1243 HICON hIcon;
1244 GpStatus stat;
1245 GpBitmap *bitmap = NULL;
1246 UINT dim;
1247 ImageType type;
1248 PixelFormat format;
1249
1250 /* NULL */
1251 stat = GdipCreateBitmapFromHICON(NULL, NULL);
1252 expect(InvalidParameter, stat);
1253 stat = GdipCreateBitmapFromHICON(NULL, &bitmap);
1254 expect(InvalidParameter, stat);
1255
1256 /* color icon 1 bit */
1257 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
1258 ok(hbmMask != 0, "CreateBitmap failed\n");
1259 hbmColor = CreateBitmap(16, 16, 1, 1, bmp_bits);
1260 ok(hbmColor != 0, "CreateBitmap failed\n");
1261 info.fIcon = TRUE;
1262 info.xHotspot = 8;
1263 info.yHotspot = 8;
1264 info.hbmMask = hbmMask;
1265 info.hbmColor = hbmColor;
1266 hIcon = CreateIconIndirect(&info);
1267 ok(hIcon != 0, "CreateIconIndirect failed\n");
1268 DeleteObject(hbmMask);
1269 DeleteObject(hbmColor);
1270
1271 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1272 ok(stat == Ok ||
1273 broken(stat == InvalidParameter), /* Win98 */
1274 "Expected Ok, got %.8x\n", stat);
1275 if(stat == Ok){
1276 /* check attributes */
1277 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1278 expect(Ok, stat);
1279 expect(16, dim);
1280 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1281 expect(Ok, stat);
1282 expect(16, dim);
1283 stat = GdipGetImageType((GpImage*)bitmap, &type);
1284 expect(Ok, stat);
1285 expect(ImageTypeBitmap, type);
1286 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1287 expect(Ok, stat);
1288 expect(PixelFormat32bppARGB, format);
1289 /* raw format */
1290 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1291 GdipDisposeImage((GpImage*)bitmap);
1292 }
1293 DestroyIcon(hIcon);
1294
1295 /* color icon 8 bpp */
1296 hbmMask = CreateBitmap(16, 16, 1, 8, bmp_bits);
1297 ok(hbmMask != 0, "CreateBitmap failed\n");
1298 hbmColor = CreateBitmap(16, 16, 1, 8, bmp_bits);
1299 ok(hbmColor != 0, "CreateBitmap failed\n");
1300 info.fIcon = TRUE;
1301 info.xHotspot = 8;
1302 info.yHotspot = 8;
1303 info.hbmMask = hbmMask;
1304 info.hbmColor = hbmColor;
1305 hIcon = CreateIconIndirect(&info);
1306 ok(hIcon != 0, "CreateIconIndirect failed\n");
1307 DeleteObject(hbmMask);
1308 DeleteObject(hbmColor);
1309
1310 stat = GdipCreateBitmapFromHICON(hIcon, &bitmap);
1311 expect(Ok, stat);
1312 if(stat == Ok){
1313 /* check attributes */
1314 stat = GdipGetImageHeight((GpImage*)bitmap, &dim);
1315 expect(Ok, stat);
1316 expect(16, dim);
1317 stat = GdipGetImageWidth((GpImage*)bitmap, &dim);
1318 expect(Ok, stat);
1319 expect(16, dim);
1320 stat = GdipGetImageType((GpImage*)bitmap, &type);
1321 expect(Ok, stat);
1322 expect(ImageTypeBitmap, type);
1323 stat = GdipGetImagePixelFormat((GpImage*)bitmap, &format);
1324 expect(Ok, stat);
1325 expect(PixelFormat32bppARGB, format);
1326 /* raw format */
1327 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bitmap, __LINE__, FALSE);
1328 GdipDisposeImage((GpImage*)bitmap);
1329 }
1330 DestroyIcon(hIcon);
1331 }
1332
1333 /* 1x1 pixel png */
1334 static const unsigned char pngimage[285] = {
1335 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1336 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1337 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1338 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1339 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1340 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1341 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1342 };
1343 /* 1x1 pixel gif */
1344 static const unsigned char gifimage[35] = {
1345 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
1346 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
1347 0x01,0x00,0x3b
1348 };
1349 /* 1x1 pixel transparent gif */
1350 static const unsigned char transparentgif[] = {
1351 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xf0,0x00,0x00,0x00,0x00,0x00,
1352 0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,
1353 0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
1354 };
1355 /* 1x1 pixel bmp */
1356 static const unsigned char bmpimage[66] = {
1357 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1358 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1359 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1360 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1361 0x00,0x00
1362 };
1363 /* 1x1 pixel jpg */
1364 static const unsigned char jpgimage[285] = {
1365 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1366 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1367 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1368 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1369 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1370 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1371 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1372 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1373 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1374 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1375 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1376 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1377 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1378 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1379 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1380 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1381 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1382 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1383 };
1384 /* 1x1 pixel tiff */
1385 static const unsigned char tiffimage[] = {
1386 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1387 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1388 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1389 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1390 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1391 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1392 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1393 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1394 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1395 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1396 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1397 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1398 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1399 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1400 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1401 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1402 0x00,0x00,0x00,0x01
1403 };
1404 /* 320x320 twip wmf */
1405 static const unsigned char wmfimage[180] = {
1406 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1407 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1408 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1409 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1410 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1411 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1412 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1413 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1414 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1415 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1416 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1417 0x00,0x00,0x00,0x00
1418 };
1419 static void test_getrawformat(void)
1420 {
1421 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE);
1422 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE);
1423 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE);
1424 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1425 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1426 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1427 }
1428
1429 static void test_loadwmf(void)
1430 {
1431 LPSTREAM stream;
1432 HGLOBAL hglob;
1433 LPBYTE data;
1434 HRESULT hres;
1435 GpStatus stat;
1436 GpImage *img;
1437 GpRectF bounds;
1438 GpUnit unit;
1439 REAL res = 12345.0;
1440 MetafileHeader header;
1441
1442 hglob = GlobalAlloc (0, sizeof(wmfimage));
1443 data = GlobalLock (hglob);
1444 memcpy(data, wmfimage, sizeof(wmfimage));
1445 GlobalUnlock(hglob); data = NULL;
1446
1447 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1448 ok(hres == S_OK, "Failed to create a stream\n");
1449 if(hres != S_OK) return;
1450
1451 stat = GdipLoadImageFromStream(stream, &img);
1452 ok(stat == Ok, "Failed to create a Bitmap\n");
1453 if(stat != Ok){
1454 IStream_Release(stream);
1455 return;
1456 }
1457
1458 IStream_Release(stream);
1459
1460 stat = GdipGetImageBounds(img, &bounds, &unit);
1461 expect(Ok, stat);
1462 expect(UnitPixel, unit);
1463 expectf(0.0, bounds.X);
1464 expectf(0.0, bounds.Y);
1465 expectf(320.0, bounds.Width);
1466 expectf(320.0, bounds.Height);
1467
1468 stat = GdipGetImageHorizontalResolution(img, &res);
1469 expect(Ok, stat);
1470 expectf(1440.0, res);
1471
1472 stat = GdipGetImageVerticalResolution(img, &res);
1473 expect(Ok, stat);
1474 expectf(1440.0, res);
1475
1476 memset(&header, 0, sizeof(header));
1477 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1478 expect(Ok, stat);
1479 if (stat == Ok)
1480 {
1481 expect(MetafileTypeWmfPlaceable, header.Type);
1482 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1483 todo_wine expect(0x300, header.Version);
1484 expect(0, header.EmfPlusFlags);
1485 expectf(1440.0, header.DpiX);
1486 expectf(1440.0, header.DpiY);
1487 expect(0, header.X);
1488 expect(0, header.Y);
1489 expect(320, header.Width);
1490 expect(320, header.Height);
1491 expect(1, U(header).WmfHeader.mtType);
1492 expect(0, header.EmfPlusHeaderSize);
1493 expect(0, header.LogicalDpiX);
1494 expect(0, header.LogicalDpiY);
1495 }
1496
1497 GdipDisposeImage(img);
1498 }
1499
1500 static void test_createfromwmf(void)
1501 {
1502 HMETAFILE hwmf;
1503 GpImage *img;
1504 GpStatus stat;
1505 GpRectF bounds;
1506 GpUnit unit;
1507 REAL res = 12345.0;
1508 MetafileHeader header;
1509
1510 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1511 wmfimage+sizeof(WmfPlaceableFileHeader));
1512 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1513
1514 stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1515 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1516 expect(Ok, stat);
1517
1518 stat = GdipGetImageBounds(img, &bounds, &unit);
1519 expect(Ok, stat);
1520 expect(UnitPixel, unit);
1521 expectf(0.0, bounds.X);
1522 expectf(0.0, bounds.Y);
1523 expectf(320.0, bounds.Width);
1524 expectf(320.0, bounds.Height);
1525
1526 stat = GdipGetImageHorizontalResolution(img, &res);
1527 expect(Ok, stat);
1528 expectf(1440.0, res);
1529
1530 stat = GdipGetImageVerticalResolution(img, &res);
1531 expect(Ok, stat);
1532 expectf(1440.0, res);
1533
1534 memset(&header, 0, sizeof(header));
1535 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1536 expect(Ok, stat);
1537 if (stat == Ok)
1538 {
1539 expect(MetafileTypeWmfPlaceable, header.Type);
1540 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1541 todo_wine expect(0x300, header.Version);
1542 expect(0, header.EmfPlusFlags);
1543 expectf(1440.0, header.DpiX);
1544 expectf(1440.0, header.DpiY);
1545 expect(0, header.X);
1546 expect(0, header.Y);
1547 expect(320, header.Width);
1548 expect(320, header.Height);
1549 expect(1, U(header).WmfHeader.mtType);
1550 expect(0, header.EmfPlusHeaderSize);
1551 expect(0, header.LogicalDpiX);
1552 expect(0, header.LogicalDpiY);
1553 }
1554
1555 GdipDisposeImage(img);
1556 }
1557
1558 static void test_createfromwmf_noplaceable(void)
1559 {
1560 HMETAFILE hwmf;
1561 GpImage *img;
1562 GpStatus stat;
1563
1564 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1565 wmfimage+sizeof(WmfPlaceableFileHeader));
1566 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1567
1568 stat = GdipCreateMetafileFromWmf(hwmf, TRUE, NULL, (GpMetafile**)&img);
1569 expect(Ok, stat);
1570
1571 GdipDisposeImage(img);
1572 }
1573
1574 static void test_resolution(void)
1575 {
1576 GpStatus stat;
1577 GpBitmap *bitmap;
1578 GpGraphics *graphics;
1579 REAL res=-1.0;
1580 HDC screendc;
1581 int screenxres, screenyres;
1582
1583 /* create Bitmap */
1584 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1585 expect(Ok, stat);
1586
1587 /* test invalid values */
1588 stat = GdipGetImageHorizontalResolution(NULL, &res);
1589 expect(InvalidParameter, stat);
1590
1591 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1592 expect(InvalidParameter, stat);
1593
1594 stat = GdipGetImageVerticalResolution(NULL, &res);
1595 expect(InvalidParameter, stat);
1596
1597 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1598 expect(InvalidParameter, stat);
1599
1600 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1601 expect(InvalidParameter, stat);
1602
1603 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1604 expect(InvalidParameter, stat);
1605
1606 /* defaults to screen resolution */
1607 screendc = GetDC(0);
1608
1609 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1610 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1611
1612 ReleaseDC(0, screendc);
1613
1614 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1615 expect(Ok, stat);
1616 expectf((REAL)screenxres, res);
1617
1618 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1619 expect(Ok, stat);
1620 expectf((REAL)screenyres, res);
1621
1622 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1623 expect(Ok, stat);
1624 stat = GdipGetDpiX(graphics, &res);
1625 expect(Ok, stat);
1626 expectf((REAL)screenxres, res);
1627 stat = GdipGetDpiY(graphics, &res);
1628 expect(Ok, stat);
1629 expectf((REAL)screenyres, res);
1630
1631 /* test changing the resolution */
1632 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1633 expect(Ok, stat);
1634
1635 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1636 expect(Ok, stat);
1637 expectf(screenxres*2.0, res);
1638
1639 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1640 expect(Ok, stat);
1641 expectf(screenyres*3.0, res);
1642
1643 stat = GdipGetDpiX(graphics, &res);
1644 expect(Ok, stat);
1645 expectf((REAL)screenxres, res);
1646 stat = GdipGetDpiY(graphics, &res);
1647 expect(Ok, stat);
1648 expectf((REAL)screenyres, res);
1649
1650 stat = GdipDeleteGraphics(graphics);
1651 expect(Ok, stat);
1652
1653 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1654 expect(Ok, stat);
1655 stat = GdipGetDpiX(graphics, &res);
1656 expect(Ok, stat);
1657 expectf(screenxres*2.0, res);
1658 stat = GdipGetDpiY(graphics, &res);
1659 expect(Ok, stat);
1660 expectf(screenyres*3.0, res);
1661 stat = GdipDeleteGraphics(graphics);
1662 expect(Ok, stat);
1663
1664 stat = GdipDisposeImage((GpImage*)bitmap);
1665 expect(Ok, stat);
1666 }
1667
1668 static void test_createhbitmap(void)
1669 {
1670 GpStatus stat;
1671 GpBitmap *bitmap;
1672 HBITMAP hbitmap, oldhbitmap;
1673 BITMAP bm;
1674 int ret;
1675 HDC hdc;
1676 COLORREF pixel;
1677 BYTE bits[640];
1678 BitmapData lockeddata;
1679
1680 memset(bits, 0x68, 640);
1681
1682 /* create Bitmap */
1683 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1684 expect(Ok, stat);
1685
1686 /* test NULL values */
1687 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1688 expect(InvalidParameter, stat);
1689
1690 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1691 expect(InvalidParameter, stat);
1692
1693 /* create HBITMAP */
1694 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1695 expect(Ok, stat);
1696
1697 if (stat == Ok)
1698 {
1699 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1700 expect(sizeof(BITMAP), ret);
1701
1702 expect(0, bm.bmType);
1703 expect(10, bm.bmWidth);
1704 expect(20, bm.bmHeight);
1705 expect(40, bm.bmWidthBytes);
1706 expect(1, bm.bmPlanes);
1707 expect(32, bm.bmBitsPixel);
1708 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1709
1710 if (bm.bmBits)
1711 {
1712 DWORD val = *(DWORD*)bm.bmBits;
1713 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1714 }
1715
1716 hdc = CreateCompatibleDC(NULL);
1717
1718 oldhbitmap = SelectObject(hdc, hbitmap);
1719 pixel = GetPixel(hdc, 5, 5);
1720 SelectObject(hdc, oldhbitmap);
1721
1722 DeleteDC(hdc);
1723
1724 expect(0x686868, pixel);
1725
1726 DeleteObject(hbitmap);
1727 }
1728
1729 stat = GdipDisposeImage((GpImage*)bitmap);
1730 expect(Ok, stat);
1731
1732 /* make (1,0) have no alpha and (2,0) a different blue value. */
1733 bits[7] = 0x00;
1734 bits[8] = 0x40;
1735
1736 /* create alpha Bitmap */
1737 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1738 expect(Ok, stat);
1739
1740 /* create HBITMAP */
1741 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1742 expect(Ok, stat);
1743
1744 if (stat == Ok)
1745 {
1746 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1747 expect(sizeof(BITMAP), ret);
1748
1749 expect(0, bm.bmType);
1750 expect(8, bm.bmWidth);
1751 expect(20, bm.bmHeight);
1752 expect(32, bm.bmWidthBytes);
1753 expect(1, bm.bmPlanes);
1754 expect(32, bm.bmBitsPixel);
1755 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1756
1757 if (bm.bmBits)
1758 {
1759 DWORD val = *(DWORD*)bm.bmBits;
1760 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1761 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1762 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1763 }
1764
1765 hdc = CreateCompatibleDC(NULL);
1766
1767 oldhbitmap = SelectObject(hdc, hbitmap);
1768 pixel = GetPixel(hdc, 5, 5);
1769 expect(0x2a2a2a, pixel);
1770 pixel = GetPixel(hdc, 1, 0);
1771 expect(0x0, pixel);
1772
1773 SelectObject(hdc, oldhbitmap);
1774
1775 DeleteDC(hdc);
1776
1777
1778 DeleteObject(hbitmap);
1779 }
1780
1781 /* create HBITMAP with bkgnd colour */
1782 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1783 expect(Ok, stat);
1784
1785 if (stat == Ok)
1786 {
1787 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1788 expect(sizeof(BITMAP), ret);
1789
1790 expect(0, bm.bmType);
1791 expect(8, bm.bmWidth);
1792 expect(20, bm.bmHeight);
1793 expect(32, bm.bmWidthBytes);
1794 expect(1, bm.bmPlanes);
1795 expect(32, bm.bmBitsPixel);
1796 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1797
1798 if (bm.bmBits)
1799 {
1800 DWORD val = *(DWORD*)bm.bmBits;
1801 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1802 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1803 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1804 }
1805
1806 hdc = CreateCompatibleDC(NULL);
1807
1808 oldhbitmap = SelectObject(hdc, hbitmap);
1809 pixel = GetPixel(hdc, 5, 5);
1810 expect(0xc12ac1, pixel);
1811 pixel = GetPixel(hdc, 1, 0);
1812 expect(0xff00ff, pixel);
1813 pixel = GetPixel(hdc, 2, 0);
1814 expect(0xb12ac1, pixel);
1815
1816 SelectObject(hdc, oldhbitmap);
1817 DeleteDC(hdc);
1818 DeleteObject(hbitmap);
1819 }
1820
1821 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1822 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1823 expect(Ok, stat);
1824
1825 if (stat == Ok)
1826 {
1827 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1828 expect(sizeof(BITMAP), ret);
1829
1830 expect(0, bm.bmType);
1831 expect(8, bm.bmWidth);
1832 expect(20, bm.bmHeight);
1833 expect(32, bm.bmWidthBytes);
1834 expect(1, bm.bmPlanes);
1835 expect(32, bm.bmBitsPixel);
1836 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1837
1838 if (bm.bmBits)
1839 {
1840 DWORD val = *(DWORD*)bm.bmBits;
1841 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1842 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1843 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1844 }
1845
1846 hdc = CreateCompatibleDC(NULL);
1847
1848 oldhbitmap = SelectObject(hdc, hbitmap);
1849 pixel = GetPixel(hdc, 5, 5);
1850 expect(0xc12ac1, pixel);
1851 pixel = GetPixel(hdc, 1, 0);
1852 expect(0xff00ff, pixel);
1853 pixel = GetPixel(hdc, 2, 0);
1854 expect(0xb12ac1, pixel);
1855
1856 SelectObject(hdc, oldhbitmap);
1857 DeleteDC(hdc);
1858 DeleteObject(hbitmap);
1859 }
1860
1861 stat = GdipDisposeImage((GpImage*)bitmap);
1862 expect(Ok, stat);
1863
1864 /* create HBITMAP from locked data */
1865 memset(bits, 0x68, 640);
1866 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1867 expect(Ok, stat);
1868
1869 memset(&lockeddata, 0, sizeof(lockeddata));
1870 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite,
1871 PixelFormat32bppRGB, &lockeddata);
1872 expect(Ok, stat);
1873 ((DWORD*)lockeddata.Scan0)[0] = 0xff242424;
1874 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1875 expect(Ok, stat);
1876 stat = GdipBitmapUnlockBits(bitmap, &lockeddata);
1877 expect(Ok, stat);
1878 stat = GdipDisposeImage((GpImage*)bitmap);
1879 expect(Ok, stat);
1880
1881 hdc = CreateCompatibleDC(NULL);
1882 oldhbitmap = SelectObject(hdc, hbitmap);
1883 pixel = GetPixel(hdc, 0, 0);
1884 expect(0x686868, pixel);
1885 SelectObject(hdc, oldhbitmap);
1886 DeleteDC(hdc);
1887 }
1888
1889 static void test_getthumbnail(void)
1890 {
1891 GpStatus stat;
1892 GpImage *bitmap1, *bitmap2;
1893 UINT width, height;
1894
1895 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1896 expect(InvalidParameter, stat);
1897
1898 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1899 expect(Ok, stat);
1900
1901 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1902 expect(InvalidParameter, stat);
1903
1904 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1905 expect(Ok, stat);
1906
1907 if (stat == Ok)
1908 {
1909 stat = GdipGetImageWidth(bitmap2, &width);
1910 expect(Ok, stat);
1911 expect(120, width);
1912
1913 stat = GdipGetImageHeight(bitmap2, &height);
1914 expect(Ok, stat);
1915 expect(120, height);
1916
1917 GdipDisposeImage(bitmap2);
1918 }
1919
1920 GdipDisposeImage(bitmap1);
1921
1922
1923 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1924 expect(Ok, stat);
1925
1926 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1927 expect(Ok, stat);
1928
1929 if (stat == Ok)
1930 {
1931 stat = GdipGetImageWidth(bitmap2, &width);
1932 expect(Ok, stat);
1933 expect(32, width);
1934
1935 stat = GdipGetImageHeight(bitmap2, &height);
1936 expect(Ok, stat);
1937 expect(32, height);
1938
1939 GdipDisposeImage(bitmap2);
1940 }
1941
1942 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1943 expect(Ok, stat);
1944
1945 if (stat == Ok)
1946 {
1947 stat = GdipGetImageWidth(bitmap2, &width);
1948 expect(Ok, stat);
1949 expect(120, width);
1950
1951 stat = GdipGetImageHeight(bitmap2, &height);
1952 expect(Ok, stat);
1953 expect(120, height);
1954
1955 GdipDisposeImage(bitmap2);
1956 }
1957
1958 GdipDisposeImage(bitmap1);
1959 }
1960
1961 static void test_getsetpixel(void)
1962 {
1963 GpStatus stat;
1964 GpBitmap *bitmap;
1965 ARGB color;
1966 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1967 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1968
1969 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1970 expect(Ok, stat);
1971
1972 /* null parameters */
1973 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1974 expect(InvalidParameter, stat);
1975
1976 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1977 expect(InvalidParameter, stat);
1978
1979 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1980 expect(InvalidParameter, stat);
1981
1982 /* out of bounds */
1983 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1984 expect(InvalidParameter, stat);
1985
1986 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1987 expect(InvalidParameter, stat);
1988
1989 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1990 ok(stat == InvalidParameter ||
1991 broken(stat == Ok), /* Older gdiplus */
1992 "Expected InvalidParameter, got %.8x\n", stat);
1993
1994 if (0) /* crashes some gdiplus implementations */
1995 {
1996 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1997 ok(stat == InvalidParameter ||
1998 broken(stat == Ok), /* Older gdiplus */
1999 "Expected InvalidParameter, got %.8x\n", stat);
2000 }
2001
2002 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
2003 expect(InvalidParameter, stat);
2004
2005 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
2006 expect(InvalidParameter, stat);
2007
2008 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
2009 expect(InvalidParameter, stat);
2010
2011 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
2012 expect(InvalidParameter, stat);
2013
2014 /* valid use */
2015 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2016 expect(Ok, stat);
2017 expect(0xffffffff, color);
2018
2019 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2020 expect(Ok, stat);
2021 expect(0xff0000ff, color);
2022
2023 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
2024 expect(Ok, stat);
2025
2026 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
2027 expect(Ok, stat);
2028
2029 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
2030 expect(Ok, stat);
2031 expect(0xff676869, color);
2032
2033 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2034 expect(Ok, stat);
2035 expect(0xff474849, color);
2036
2037 stat = GdipDisposeImage((GpImage*)bitmap);
2038 expect(Ok, stat);
2039 }
2040
2041 static void check_halftone_palette(ColorPalette *palette)
2042 {
2043 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
2044 UINT i;
2045
2046 for (i=0; i<palette->Count; i++)
2047 {
2048 ARGB expected=0xff000000;
2049 if (i<8)
2050 {
2051 if (i&1) expected |= 0x800000;
2052 if (i&2) expected |= 0x8000;
2053 if (i&4) expected |= 0x80;
2054 }
2055 else if (i == 8)
2056 {
2057 expected = 0xffc0c0c0;
2058 }
2059 else if (i < 16)
2060 {
2061 if (i&1) expected |= 0xff0000;
2062 if (i&2) expected |= 0xff00;
2063 if (i&4) expected |= 0xff;
2064 }
2065 else if (i < 40)
2066 {
2067 expected = 0x00000000;
2068 }
2069 else
2070 {
2071 expected |= halftone_values[(i-40)%6];
2072 expected |= halftone_values[((i-40)/6)%6] << 8;
2073 expected |= halftone_values[((i-40)/36)%6] << 16;
2074 }
2075 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2076 expected, palette->Entries[i], i, palette->Count);
2077 }
2078 }
2079
2080 static void test_palette(void)
2081 {
2082 GpStatus stat;
2083 GpBitmap *bitmap;
2084 INT size;
2085 BYTE buffer[1040];
2086 ColorPalette *palette=(ColorPalette*)buffer;
2087 ARGB *entries = palette->Entries;
2088 ARGB color=0;
2089
2090 /* test initial palette from non-indexed bitmap */
2091 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2092 expect(Ok, stat);
2093
2094 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2095 expect(Ok, stat);
2096 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2097
2098 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2099 expect(Ok, stat);
2100 expect(0, palette->Count);
2101
2102 /* test setting palette on not-indexed bitmap */
2103 palette->Count = 3;
2104
2105 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2106 expect(Ok, stat);
2107
2108 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2109 expect(Ok, stat);
2110 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2111
2112 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2113 expect(Ok, stat);
2114 expect(3, palette->Count);
2115
2116 GdipDisposeImage((GpImage*)bitmap);
2117
2118 /* test initial palette on 1-bit bitmap */
2119 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2120 expect(Ok, stat);
2121
2122 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2123 expect(Ok, stat);
2124 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2125
2126 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2127 expect(Ok, stat);
2128 expect(PaletteFlagsGrayScale, palette->Flags);
2129 expect(2, palette->Count);
2130
2131 expect(0xff000000, entries[0]);
2132 expect(0xffffffff, entries[1]);
2133
2134 /* test getting/setting pixels */
2135 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2136 expect(Ok, stat);
2137 expect(0xff000000, color);
2138
2139 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2140 ok((stat == Ok) ||
2141 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2142
2143 if (stat == Ok)
2144 {
2145 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2146 expect(Ok, stat);
2147 expect(0xffffffff, color);
2148 }
2149
2150 GdipDisposeImage((GpImage*)bitmap);
2151
2152 /* test initial palette on 4-bit bitmap */
2153 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2154 expect(Ok, stat);
2155
2156 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2157 expect(Ok, stat);
2158 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2159
2160 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2161 expect(Ok, stat);
2162 expect(0, palette->Flags);
2163 expect(16, palette->Count);
2164
2165 check_halftone_palette(palette);
2166
2167 /* test getting/setting pixels */
2168 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2169 expect(Ok, stat);
2170 expect(0xff000000, color);
2171
2172 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2173 ok((stat == Ok) ||
2174 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2175
2176 if (stat == Ok)
2177 {
2178 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2179 expect(Ok, stat);
2180 expect(0xffff00ff, color);
2181 }
2182
2183 GdipDisposeImage((GpImage*)bitmap);
2184
2185 /* test initial palette on 8-bit bitmap */
2186 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2187 expect(Ok, stat);
2188
2189 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2190 expect(Ok, stat);
2191 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2192
2193 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2194 expect(Ok, stat);
2195 expect(PaletteFlagsHalftone, palette->Flags);
2196 expect(256, palette->Count);
2197
2198 check_halftone_palette(palette);
2199
2200 /* test getting/setting pixels */
2201 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2202 expect(Ok, stat);
2203 expect(0xff000000, color);
2204
2205 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2206 ok((stat == Ok) ||
2207 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2208
2209 if (stat == Ok)
2210 {
2211 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2212 expect(Ok, stat);
2213 expect(0xffcccccc, color);
2214 }
2215
2216 /* test setting/getting a different palette */
2217 entries[1] = 0xffcccccc;
2218
2219 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2220 expect(Ok, stat);
2221
2222 entries[1] = 0;
2223
2224 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2225 expect(Ok, stat);
2226 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2227
2228 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2229 expect(Ok, stat);
2230 expect(PaletteFlagsHalftone, palette->Flags);
2231 expect(256, palette->Count);
2232 expect(0xffcccccc, entries[1]);
2233
2234 /* test count < 256 */
2235 palette->Flags = 12345;
2236 palette->Count = 3;
2237
2238 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2239 expect(Ok, stat);
2240
2241 entries[1] = 0;
2242 entries[3] = 0xdeadbeef;
2243
2244 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2245 expect(Ok, stat);
2246 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2247
2248 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2249 expect(Ok, stat);
2250 expect(12345, palette->Flags);
2251 expect(3, palette->Count);
2252 expect(0xffcccccc, entries[1]);
2253 expect(0xdeadbeef, entries[3]);
2254
2255 /* test count > 256 */
2256 palette->Count = 257;
2257
2258 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2259 ok(stat == InvalidParameter ||
2260 broken(stat == Ok), /* Old gdiplus behavior */
2261 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2262
2263 GdipDisposeImage((GpImage*)bitmap);
2264 }
2265
2266 static void test_colormatrix(void)
2267 {
2268 GpStatus stat;
2269 ColorMatrix colormatrix, graymatrix;
2270 GpImageAttributes *imageattr;
2271 const ColorMatrix identity = {{
2272 {1.0,0.0,0.0,0.0,0.0},
2273 {0.0,1.0,0.0,0.0,0.0},
2274 {0.0,0.0,1.0,0.0,0.0},
2275 {0.0,0.0,0.0,1.0,0.0},
2276 {0.0,0.0,0.0,0.0,1.0}}};
2277 const ColorMatrix double_red = {{
2278 {2.0,0.0,0.0,0.0,0.0},
2279 {0.0,1.0,0.0,0.0,0.0},
2280 {0.0,0.0,1.0,0.0,0.0},
2281 {0.0,0.0,0.0,1.0,0.0},
2282 {0.0,0.0,0.0,0.0,1.0}}};
2283 const ColorMatrix asymmetric = {{
2284 {0.0,1.0,0.0,0.0,0.0},
2285 {0.0,0.0,1.0,0.0,0.0},
2286 {0.0,0.0,0.0,1.0,0.0},
2287 {1.0,0.0,0.0,0.0,0.0},
2288 {0.0,0.0,0.0,0.0,1.0}}};
2289 GpBitmap *bitmap1, *bitmap2;
2290 GpGraphics *graphics;
2291 ARGB color;
2292
2293 colormatrix = identity;
2294 graymatrix = identity;
2295
2296 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2297 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2298 expect(InvalidParameter, stat);
2299
2300 stat = GdipCreateImageAttributes(&imageattr);
2301 expect(Ok, stat);
2302
2303 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2304 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2305 expect(Ok, stat);
2306
2307 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2308 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2309 expect(InvalidParameter, stat);
2310
2311 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2312 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2313 expect(Ok, stat);
2314
2315 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2316 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2317 expect(Ok, stat);
2318
2319 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2320 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2321 expect(InvalidParameter, stat);
2322
2323 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2324 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2325 expect(Ok, stat);
2326
2327 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2328 TRUE, &colormatrix, &graymatrix, 3);
2329 expect(InvalidParameter, stat);
2330
2331 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2332 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2333 expect(InvalidParameter, stat);
2334
2335 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2336 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2337 expect(InvalidParameter, stat);
2338
2339 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2340 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2341 expect(Ok, stat);
2342
2343 /* Drawing a bitmap transforms the colors */
2344 colormatrix = double_red;
2345 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2346 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2347 expect(Ok, stat);
2348
2349 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2350 expect(Ok, stat);
2351
2352 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2353 expect(Ok, stat);
2354
2355 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2356 expect(Ok, stat);
2357
2358 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2359 expect(Ok, stat);
2360
2361 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2362 UnitPixel, imageattr, NULL, NULL);
2363 expect(Ok, stat);
2364
2365 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2366 expect(Ok, stat);
2367 expect(0xff80ccee, color);
2368
2369 colormatrix = asymmetric;
2370 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2371 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2372 expect(Ok, stat);
2373
2374 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2375 expect(Ok, stat);
2376
2377 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2378 UnitPixel, imageattr, NULL, NULL);
2379 expect(Ok, stat);
2380
2381 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2382 expect(Ok, stat);
2383 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2384
2385 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2386 expect(Ok, stat);
2387
2388 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2389 UnitPixel, imageattr, NULL, NULL);
2390 expect(Ok, stat);
2391
2392 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2393 expect(Ok, stat);
2394 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2395
2396 GdipDeleteGraphics(graphics);
2397 GdipDisposeImage((GpImage*)bitmap1);
2398 GdipDisposeImage((GpImage*)bitmap2);
2399 GdipDisposeImageAttributes(imageattr);
2400 }
2401
2402 static void test_gamma(void)
2403 {
2404 GpStatus stat;
2405 GpImageAttributes *imageattr;
2406 GpBitmap *bitmap1, *bitmap2;
2407 GpGraphics *graphics;
2408 ARGB color;
2409
2410 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2411 expect(InvalidParameter, stat);
2412
2413 stat = GdipCreateImageAttributes(&imageattr);
2414 expect(Ok, stat);
2415
2416 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2417 expect(Ok, stat);
2418
2419 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2420 expect(InvalidParameter, stat);
2421
2422 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2423 expect(InvalidParameter, stat);
2424
2425 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2426 expect(InvalidParameter, stat);
2427
2428 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2429 expect(Ok, stat);
2430
2431 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2432 expect(Ok, stat);
2433
2434 /* Drawing a bitmap transforms the colors */
2435 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2436 expect(Ok, stat);
2437
2438 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2439 expect(Ok, stat);
2440
2441 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2442 expect(Ok, stat);
2443
2444 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2445 expect(Ok, stat);
2446
2447 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2448 expect(Ok, stat);
2449
2450 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2451 UnitPixel, imageattr, NULL, NULL);
2452 expect(Ok, stat);
2453
2454 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2455 expect(Ok, stat);
2456 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2457
2458 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2459 expect(Ok, stat);
2460
2461 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2462 UnitPixel, imageattr, NULL, NULL);
2463 expect(Ok, stat);
2464
2465 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2466 expect(Ok, stat);
2467 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2468
2469 GdipDeleteGraphics(graphics);
2470 GdipDisposeImage((GpImage*)bitmap1);
2471 GdipDisposeImage((GpImage*)bitmap2);
2472 GdipDisposeImageAttributes(imageattr);
2473 }
2474
2475 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2476 static const unsigned char gifanimation[72] = {
2477 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2478 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2479 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2480 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2481 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2482 };
2483
2484 /* Generated with ImageMagick:
2485 * convert -transparent black -delay 100 -size 8x2 xc:black \
2486 * -dispose none -page +0+0 -size 2x2 xc:red \
2487 * -dispose background -page +2+0 -size 2x2 xc:blue \
2488 * -dispose previous -page +4+0 -size 2x2 xc:green \
2489 * -dispose undefined -page +6+0 -size 2x2 xc:gray \
2490 * test.gif
2491 */
2492 static const unsigned char gifanimation2[] = {
2493 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x08, 0x00,
2494 0x02, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
2495 0x00, 0x00, 0x00, 0x21, 0xf9, 0x04, 0x01, 0x64,
2496 0x00, 0x00, 0x00, 0x21, 0xff, 0x0b, 0x4e, 0x45,
2497 0x54, 0x53, 0x43, 0x41, 0x50, 0x45, 0x32, 0x2e,
2498 0x30, 0x03, 0x01, 0x00, 0x00, 0x00, 0x2c, 0x00,
2499 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
2500 0x02, 0x04, 0x84, 0x8f, 0x09, 0x05, 0x00, 0x21,
2501 0xf9, 0x04, 0x04, 0x64, 0x00, 0x00, 0x00, 0x2c,
2502 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2503 0x81, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
2504 0x00, 0x00, 0xff, 0x00, 0x00, 0x02, 0x03, 0x44,
2505 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x08, 0x64,
2506 0x00, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x00,
2507 0x02, 0x00, 0x02, 0x00, 0x81, 0x00, 0x00, 0xff,
2508 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00,
2509 0xff, 0x02, 0x03, 0x44, 0x34, 0x05, 0x00, 0x21,
2510 0xf9, 0x04, 0x0c, 0x64, 0x00, 0x00, 0x00, 0x2c,
2511 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
2512 0x81, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00,
2513 0x80, 0x00, 0x00, 0x80, 0x00, 0x02, 0x03, 0x44,
2514 0x34, 0x05, 0x00, 0x21, 0xf9, 0x04, 0x00, 0x64,
2515 0x00, 0x00, 0x00, 0x2c, 0x06, 0x00, 0x00, 0x00,
2516 0x02, 0x00, 0x02, 0x00, 0x80, 0x7e, 0x7e, 0x7e,
2517 0x00, 0x00, 0x00, 0x02, 0x02, 0x84, 0x51, 0x00,
2518 0x3b
2519 };
2520
2521 static ARGB gifanimation2_pixels[5][4] = {
2522 {0, 0, 0, 0},
2523 {0xffff0000, 0, 0, 0},
2524 {0xffff0000, 0xff0000ff, 0, 0},
2525 {0xffff0000, 0, 0xff008000, 0},
2526 {0xffff0000, 0, 0, 0xff7e7e7e}
2527 };
2528
2529 static void test_multiframegif(void)
2530 {
2531 LPSTREAM stream;
2532 HGLOBAL hglob;
2533 LPBYTE data;
2534 HRESULT hres;
2535 GpStatus stat;
2536 GpBitmap *bmp;
2537 ARGB color;
2538 UINT count;
2539 GUID dimension;
2540 PixelFormat pixel_format;
2541 INT palette_size, i, j;
2542 char palette_buf[256];
2543 ColorPalette *palette;
2544 ARGB *palette_entries;
2545
2546 /* Test frame functions with an animated GIF */
2547 hglob = GlobalAlloc (0, sizeof(gifanimation));
2548 data = GlobalLock (hglob);
2549 memcpy(data, gifanimation, sizeof(gifanimation));
2550 GlobalUnlock(hglob);
2551
2552 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2553 ok(hres == S_OK, "Failed to create a stream\n");
2554 if(hres != S_OK) return;
2555
2556 stat = GdipCreateBitmapFromStream(stream, &bmp);
2557 ok(stat == Ok, "Failed to create a Bitmap\n");
2558 if(stat != Ok){
2559 IStream_Release(stream);
2560 return;
2561 }
2562
2563 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2564 expect(Ok, stat);
2565 expect(PixelFormat32bppARGB, pixel_format);
2566
2567 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2568 expect(Ok, stat);
2569 ok(palette_size == sizeof(ColorPalette) ||
2570 broken(palette_size == sizeof(ColorPalette)+sizeof(ARGB[3])),
2571 "palette_size = %d\n", palette_size);
2572
2573 /* Bitmap starts at frame 0 */
2574 color = 0xdeadbeef;
2575 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2576 expect(Ok, stat);
2577 expect(0xffffffff, color);
2578
2579 /* Check that we get correct metadata */
2580 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2581 expect(Ok, stat);
2582 expect(1, count);
2583
2584 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2585 expect(Ok, stat);
2586 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2587
2588 count = 12345;
2589 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2590 expect(Ok, stat);
2591 expect(2, count);
2592
2593 /* SelectActiveFrame overwrites our current data */
2594 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2595 expect(Ok, stat);
2596
2597 color = 0xdeadbeef;
2598 GdipBitmapGetPixel(bmp, 0, 0, &color);
2599 expect(Ok, stat);
2600 expect(0xff000000, color);
2601
2602 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2603 expect(Ok, stat);
2604
2605 color = 0xdeadbeef;
2606 GdipBitmapGetPixel(bmp, 0, 0, &color);
2607 expect(Ok, stat);
2608 expect(0xffffffff, color);
2609
2610 /* Write over the image data */
2611 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2612 expect(Ok, stat);
2613
2614 /* Switching to the same frame does not overwrite our changes */
2615 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2616 expect(Ok, stat);
2617
2618 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2619 expect(Ok, stat);
2620 expect(0xff000000, color);
2621
2622 /* But switching to another frame and back does */
2623 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2624 expect(Ok, stat);
2625
2626 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2627 expect(Ok, stat);
2628
2629 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2630 expect(Ok, stat);
2631 expect(0xffffffff, color);
2632
2633 /* rotate/flip discards the information about other frames */
2634 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2635 expect(Ok, stat);
2636
2637 count = 12345;
2638 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2639 expect(Ok, stat);
2640 expect(1, count);
2641
2642 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2643
2644 GdipDisposeImage((GpImage*)bmp);
2645 IStream_Release(stream);
2646
2647 /* Test with a non-animated gif */
2648 hglob = GlobalAlloc (0, sizeof(gifimage));
2649 data = GlobalLock (hglob);
2650 memcpy(data, gifimage, sizeof(gifimage));
2651 GlobalUnlock(hglob);
2652
2653 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2654 ok(hres == S_OK, "Failed to create a stream\n");
2655 if(hres != S_OK) return;
2656
2657 stat = GdipCreateBitmapFromStream(stream, &bmp);
2658 ok(stat == Ok, "Failed to create a Bitmap\n");
2659 if(stat != Ok){
2660 IStream_Release(stream);
2661 return;
2662 }
2663
2664 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2665 expect(Ok, stat);
2666 expect(PixelFormat8bppIndexed, pixel_format);
2667
2668 /* Check metadata */
2669 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2670 expect(Ok, stat);
2671 expect(1, count);
2672
2673 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2674 expect(Ok, stat);
2675 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2676
2677 count = 12345;
2678 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2679 expect(Ok, stat);
2680 expect(1, count);
2681
2682 GdipDisposeImage((GpImage*)bmp);
2683 IStream_Release(stream);
2684
2685 /* Test with a non-animated transparent gif */
2686 hglob = GlobalAlloc (0, sizeof(transparentgif));
2687 data = GlobalLock (hglob);
2688 memcpy(data, transparentgif, sizeof(transparentgif));
2689 GlobalUnlock(hglob);
2690
2691 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2692 ok(hres == S_OK, "Failed to create a stream\n");
2693
2694 stat = GdipCreateBitmapFromStream(stream, &bmp);
2695 IStream_Release(stream);
2696 ok(stat == Ok, "Failed to create a Bitmap\n");
2697
2698 stat = GdipGetImagePixelFormat((GpImage*)bmp, &pixel_format);
2699 expect(Ok, stat);
2700 expect(PixelFormat8bppIndexed, pixel_format);
2701
2702 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2703 expect(Ok, stat);
2704 expect(0, color);
2705
2706 stat = GdipGetImagePaletteSize((GpImage*)bmp, &palette_size);
2707 expect(Ok, stat);
2708 ok(palette_size == sizeof(ColorPalette)+sizeof(ARGB),
2709 "palette_size = %d\n", palette_size);
2710
2711 memset(palette_buf, 0xfe, sizeof(palette_buf));
2712 palette = (ColorPalette*)palette_buf;
2713 stat = GdipGetImagePalette((GpImage*)bmp, palette,
2714 sizeof(ColorPalette)+sizeof(ARGB));
2715 palette_entries = palette->Entries;
2716 expect(Ok, stat);
2717 expect(PaletteFlagsHasAlpha, palette->Flags);
2718 expect(2, palette->Count);
2719 expect(0, palette_entries[0]);
2720 expect(0xff000000, palette_entries[1]);
2721
2722 count = 12345;
2723 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2724 expect(Ok, stat);
2725 expect(1, count);
2726
2727 GdipDisposeImage((GpImage*)bmp);
2728
2729 /* Test frame dispose methods */
2730 hglob = GlobalAlloc (0, sizeof(gifanimation2));
2731 data = GlobalLock (hglob);
2732 memcpy(data, gifanimation2, sizeof(gifanimation2));
2733 GlobalUnlock(hglob);
2734
2735 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2736 ok(hres == S_OK, "Failed to create a stream\n");
2737
2738 stat = GdipCreateBitmapFromStream(stream, &bmp);
2739 ok(stat == Ok, "Failed to create a Bitmap\n");
2740 IStream_Release(stream);
2741
2742 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2743 expect(Ok, stat);
2744 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2745
2746 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2747 expect(Ok, stat);
2748 expect(5, count);
2749
2750 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2751 expect(Ok, stat);
2752 expect(0, color);
2753
2754 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 3);
2755 expect(Ok, stat);
2756 stat = GdipBitmapGetPixel(bmp, 2, 0, &color);
2757 expect(Ok, stat);
2758 ok(color==0 || broken(color==0xff0000ff), "color = %x\n", color);
2759 if(color != 0) {
2760 win_skip("broken animated gif support\n");
2761 GdipDisposeImage((GpImage*)bmp);
2762 return;
2763 }
2764
2765 for(i=0; i<6; i++) {
2766 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, i%5);
2767 expect(Ok, stat);
2768
2769 for(j=0; j<4; j++) {
2770 stat = GdipBitmapGetPixel(bmp, j*2, 0, &color);
2771 expect(Ok, stat);
2772 ok(gifanimation2_pixels[i%5][j] == color, "at %d,%d got %x, expected %x\n", i, j, color, gifanimation2_pixels[i%5][j]);
2773 }
2774 }
2775
2776 GdipDisposeImage((GpImage*)bmp);
2777 }
2778
2779 static void test_rotateflip(void)
2780 {
2781 GpImage *bitmap;
2782 GpStatus stat;
2783 BYTE bits[24];
2784 static const BYTE orig_bits[24] = {
2785 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2786 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2787 UINT width, height;
2788 ARGB color;
2789
2790 memcpy(bits, orig_bits, sizeof(bits));
2791 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2792 expect(Ok, stat);
2793
2794 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2795 expect(Ok, stat);
2796
2797 stat = GdipGetImageWidth(bitmap, &width);
2798 expect(Ok, stat);
2799 stat = GdipGetImageHeight(bitmap, &height);
2800 expect(Ok, stat);
2801 expect(2, width);
2802 expect(3, height);
2803
2804 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2805 expect(Ok, stat);
2806 expect(0xff00ffff, color);
2807
2808 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2809 expect(Ok, stat);
2810 expect(0xffff0000, color);
2811
2812 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2813 expect(Ok, stat);
2814 expect(0xffffff00, color);
2815
2816 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2817 expect(Ok, stat);
2818 expect(0xff0000ff, color);
2819
2820 expect(0, bits[0]);
2821 expect(0, bits[1]);
2822 expect(0xff, bits[2]);
2823
2824 GdipDisposeImage(bitmap);
2825
2826 memcpy(bits, orig_bits, sizeof(bits));
2827 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2828 expect(Ok, stat);
2829
2830 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2831 expect(Ok, stat);
2832
2833 stat = GdipGetImageWidth(bitmap, &width);
2834 expect(Ok, stat);
2835 stat = GdipGetImageHeight(bitmap, &height);
2836 expect(Ok, stat);
2837 expect(3, width);
2838 expect(2, height);
2839
2840 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2841 expect(Ok, stat);
2842 expect(0xff0000ff, color);
2843
2844 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2845 expect(Ok, stat);
2846 expect(0xffff0000, color);
2847
2848 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2849 expect(Ok, stat);
2850 expect(0xffffff00, color);
2851
2852 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2853 expect(Ok, stat);
2854 expect(0xff00ffff, color);
2855
2856 expect(0, bits[0]);
2857 expect(0, bits[1]);
2858 expect(0xff, bits[2]);
2859
2860 GdipDisposeImage(bitmap);
2861
2862 memcpy(bits, orig_bits, sizeof(bits));
2863 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2864 expect(Ok, stat);
2865
2866 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2867 expect(Ok, stat);
2868
2869 stat = GdipGetImageWidth(bitmap, &width);
2870 expect(Ok, stat);
2871 stat = GdipGetImageHeight(bitmap, &height);
2872 expect(Ok, stat);
2873 expect(3, width);
2874 expect(2, height);
2875
2876 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2877 expect(Ok, stat);
2878 expect(0xff00ffff, color);
2879
2880 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2881 expect(Ok, stat);
2882 expect(0xffffff00, color);
2883
2884 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2885 expect(Ok, stat);
2886 expect(0xffff0000, color);
2887
2888 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2889 expect(Ok, stat);
2890 expect(0xff0000ff, color);
2891
2892 expect(0, bits[0]);
2893 expect(0, bits[1]);
2894 expect(0xff, bits[2]);
2895
2896 GdipDisposeImage(bitmap);
2897 }
2898
2899 static void test_remaptable(void)
2900 {
2901 GpStatus stat;
2902 GpImageAttributes *imageattr;
2903 GpBitmap *bitmap1, *bitmap2;
2904 GpGraphics *graphics;
2905 ARGB color;
2906 ColorMap *map;
2907
2908 map = GdipAlloc(sizeof(ColorMap));
2909
2910 map->oldColor.Argb = 0xff00ff00;
2911 map->newColor.Argb = 0xffff00ff;
2912
2913 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2914 expect(InvalidParameter, stat);
2915
2916 stat = GdipCreateImageAttributes(&imageattr);
2917 expect(Ok, stat);
2918
2919 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2920 expect(InvalidParameter, stat);
2921
2922 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2923 expect(InvalidParameter, stat);
2924
2925 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2926 expect(InvalidParameter, stat);
2927
2928 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2929 expect(InvalidParameter, stat);
2930
2931 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2932 expect(Ok, stat);
2933
2934 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2935 expect(Ok, stat);
2936
2937 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2938 expect(Ok, stat);
2939
2940 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2941 expect(Ok, stat);
2942
2943 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2944 expect(Ok, stat);
2945
2946 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2947 expect(Ok, stat);
2948
2949 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2950 UnitPixel, imageattr, NULL, NULL);
2951 expect(Ok, stat);
2952
2953 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2954 expect(Ok, stat);
2955 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2956
2957 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2958 expect(Ok, stat);
2959
2960 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2961 UnitPixel, imageattr, NULL, NULL);
2962 expect(Ok, stat);
2963
2964 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2965 expect(Ok, stat);
2966 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
2967
2968 GdipDeleteGraphics(graphics);
2969 GdipDisposeImage((GpImage*)bitmap1);
2970 GdipDisposeImage((GpImage*)bitmap2);
2971 GdipDisposeImageAttributes(imageattr);
2972 GdipFree(map);
2973 }
2974
2975 static void test_colorkey(void)
2976 {
2977 GpStatus stat;
2978 GpImageAttributes *imageattr;
2979 GpBitmap *bitmap1, *bitmap2;
2980 GpGraphics *graphics;
2981 ARGB color;
2982
2983 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2984 expect(InvalidParameter, stat);
2985
2986 stat = GdipCreateImageAttributes(&imageattr);
2987 expect(Ok, stat);
2988
2989 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2990 expect(InvalidParameter, stat);
2991
2992 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2993 expect(InvalidParameter, stat);
2994
2995 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2996 expect(Ok, stat);
2997
2998 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2999 expect(Ok, stat);
3000
3001 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
3002 expect(Ok, stat);
3003
3004 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
3005 expect(Ok, stat);
3006
3007 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
3008 expect(Ok, stat);
3009
3010 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
3011 expect(Ok, stat);
3012
3013 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
3014 expect(Ok, stat);
3015
3016 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
3017 expect(Ok, stat);
3018
3019 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3020 UnitPixel, imageattr, NULL, NULL);
3021 expect(Ok, stat);
3022
3023 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3024 expect(Ok, stat);
3025 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3026
3027 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3028 expect(Ok, stat);
3029 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3030
3031 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3032 expect(Ok, stat);
3033 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
3034
3035 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3036 expect(Ok, stat);
3037 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3038
3039 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
3040 expect(Ok, stat);
3041
3042 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
3043 UnitPixel, imageattr, NULL, NULL);
3044 expect(Ok, stat);
3045
3046 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
3047 expect(Ok, stat);
3048 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
3049
3050 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
3051 expect(Ok, stat);
3052 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
3053
3054 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
3055 expect(Ok, stat);
3056 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
3057
3058 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
3059 expect(Ok, stat);
3060 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
3061
3062
3063 GdipDeleteGraphics(graphics);
3064 GdipDisposeImage((GpImage*)bitmap1);
3065 GdipDisposeImage((GpImage*)bitmap2);
3066 GdipDisposeImageAttributes(imageattr);
3067 }
3068
3069 static void test_dispose(void)
3070 {
3071 GpStatus stat;
3072 GpImage *image;
3073 char invalid_image[256];
3074
3075 stat = GdipDisposeImage(NULL);
3076 expect(InvalidParameter, stat);
3077
3078 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
3079 expect(Ok, stat);
3080
3081 stat = GdipDisposeImage(image);
3082 expect(Ok, stat);
3083
3084 stat = GdipDisposeImage(image);
3085 expect(ObjectBusy, stat);
3086
3087 memset(invalid_image, 0, 256);
3088 stat = GdipDisposeImage((GpImage*)invalid_image);
3089 expect(ObjectBusy, stat);
3090 }
3091
3092 static LONG obj_refcount(void *obj)
3093 {
3094 IUnknown_AddRef((IUnknown *)obj);
3095 return IUnknown_Release((IUnknown *)obj);
3096 }
3097
3098 static GpImage *load_image(const BYTE *image_data, UINT image_size)
3099 {
3100 IStream *stream;
3101 HGLOBAL hmem;
3102 BYTE *data;
3103 HRESULT hr;
3104 GpStatus status;
3105 GpImage *image = NULL, *clone;
3106 ImageType image_type;
3107 LONG refcount, old_refcount;
3108
3109 hmem = GlobalAlloc(0, image_size);
3110 data = GlobalLock(hmem);
3111 memcpy(data, image_data, image_size);
3112 GlobalUnlock(hmem);
3113
3114 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
3115 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
3116 if (hr != S_OK) return NULL;
3117
3118 refcount = obj_refcount(stream);
3119 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3120
3121 status = GdipLoadImageFromStream(stream, &image);
3122 if (status != Ok)
3123 {
3124 IStream_Release(stream);
3125 return NULL;
3126 }
3127
3128 status = GdipGetImageType(image, &image_type);
3129 ok(status == Ok, "GdipGetImageType error %d\n", status);
3130
3131 refcount = obj_refcount(stream);
3132 if (image_type == ImageTypeBitmap)
3133 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
3134 else
3135 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
3136 old_refcount = refcount;
3137
3138 status = GdipCloneImage(image, &clone);
3139 ok(status == Ok, "GdipCloneImage error %d\n", status);
3140 refcount = obj_refcount(stream);
3141 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3142 status = GdipDisposeImage(clone);
3143 ok(status == Ok, "GdipDisposeImage error %d\n", status);
3144 refcount = obj_refcount(stream);
3145 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
3146
3147 refcount = IStream_Release(stream);
3148 if (image_type == ImageTypeBitmap)
3149 ok(refcount >= 1, "expected stream refcount != 0\n");
3150 else
3151 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
3152
3153 return image;
3154 }
3155
3156 static void test_image_properties(void)
3157 {
3158 static const struct test_data
3159 {
3160 const BYTE *image_data;
3161 UINT image_size;
3162 ImageType image_type;
3163 UINT prop_count;
3164 UINT prop_count2; /* if win7 behaves differently */
3165 /* 1st property attributes */
3166 UINT prop_size;
3167 UINT prop_size2; /* if win7 behaves differently */
3168 UINT prop_id;
3169 UINT prop_id2; /* if win7 behaves differently */
3170 }
3171 td[] =
3172 {
3173 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
3174 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
3175 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
3176 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
3177 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
3178 };
3179 GpStatus status;
3180 GpImage *image;
3181 UINT prop_count, prop_size, i;
3182 PROPID prop_id[16] = { 0 };
3183 ImageType image_type;
3184 union
3185 {
3186 PropertyItem data;
3187 char buf[256];
3188 } item;
3189
3190 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3191 {
3192 image = load_image(td[i].image_data, td[i].image_size);
3193 if (!image)
3194 {
3195 trace("%u: failed to load image data\n", i);
3196 continue;
3197 }
3198
3199 status = GdipGetImageType(image, &image_type);
3200 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
3201 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
3202 i, td[i].image_type, image_type);
3203
3204 status = GdipGetPropertyCount(image, &prop_count);
3205 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3206 todo_wine_if(td[i].image_data == pngimage || td[i].image_data == jpgimage)
3207 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3208 " %u: expected property count %u or %u, got %u\n",
3209 i, td[i].prop_count, td[i].prop_count2, prop_count);
3210
3211 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3212 expect(InvalidParameter, status);
3213 status = GdipGetPropertyItemSize(image, 0, NULL);
3214 expect(InvalidParameter, status);
3215 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3216 if (image_type == ImageTypeMetafile)
3217 expect(NotImplemented, status);
3218 else
3219 expect(PropertyNotFound, status);
3220
3221 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3222 expect(InvalidParameter, status);
3223 status = GdipGetPropertyItem(image, 0, 0, NULL);
3224 expect(InvalidParameter, status);
3225 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3226 if (image_type == ImageTypeMetafile)
3227 expect(NotImplemented, status);
3228 else
3229 expect(PropertyNotFound, status);
3230
3231 /* FIXME: remove once Wine is fixed */
3232 if (td[i].prop_count != prop_count)
3233 {
3234 GdipDisposeImage(image);
3235 continue;
3236 }
3237
3238 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3239 expect(InvalidParameter, status);
3240 status = GdipGetPropertyIdList(image, prop_count, NULL);
3241 expect(InvalidParameter, status);
3242 status = GdipGetPropertyIdList(image, 0, prop_id);
3243 if (image_type == ImageTypeMetafile)
3244 expect(NotImplemented, status);
3245 else if (prop_count == 0)
3246 expect(Ok, status);
3247 else
3248 expect(InvalidParameter, status);
3249 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3250 if (image_type == ImageTypeMetafile)
3251 expect(NotImplemented, status);
3252 else
3253 expect(InvalidParameter, status);
3254 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3255 if (image_type == ImageTypeMetafile)
3256 expect(NotImplemented, status);
3257 else
3258 expect(InvalidParameter, status);
3259 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3260 if (image_type == ImageTypeMetafile)
3261 expect(NotImplemented, status);
3262 else
3263 {
3264 expect(Ok, status);
3265 if (prop_count != 0)
3266 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3267 " %u: expected property id %#x or %#x, got %#x\n",
3268 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3269 }
3270
3271 if (status == Ok)
3272 {
3273 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3274 if (prop_count == 0)
3275 expect(PropertyNotFound, status);
3276 else
3277 {
3278 expect(Ok, status);
3279
3280 assert(sizeof(item) >= prop_size);
3281 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3282 i, prop_size);
3283 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3284 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3285 " %u: expected property size %u or %u, got %u\n",
3286 i, td[i].prop_size, td[i].prop_size2, prop_size);
3287
3288 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3289 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3290 "%u: expected InvalidParameter, got %d\n", i, status);
3291 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3292 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3293 "%u: expected InvalidParameter, got %d\n", i, status);
3294 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3295 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3296 "%u: expected InvalidParameter, got %d\n", i, status);
3297 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3298 expect(Ok, status);
3299 ok(prop_id[0] == item.data.id,
3300 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3301 }
3302 }
3303
3304 GdipDisposeImage(image);
3305 }
3306 }
3307
3308 #define IFD_BYTE 1
3309 #define IFD_ASCII 2
3310 #define IFD_SHORT 3
3311 #define IFD_LONG 4
3312 #define IFD_RATIONAL 5
3313 #define IFD_SBYTE 6
3314 #define IFD_UNDEFINED 7
3315 #define IFD_SSHORT 8
3316 #define IFD_SLONG 9
3317 #define IFD_SRATIONAL 10
3318 #define IFD_FLOAT 11
3319 #define IFD_DOUBLE 12
3320
3321 #ifndef PropertyTagTypeSByte
3322 #define PropertyTagTypeSByte 6
3323 #define PropertyTagTypeSShort 8
3324 #define PropertyTagTypeFloat 11
3325 #define PropertyTagTypeDouble 12
3326 #endif
3327
3328 static UINT documented_type(UINT type)
3329 {
3330 switch (type)
3331 {
3332 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3333 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3334 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3335 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3336 default: return type;
3337 }
3338 }
3339
3340 #include "pshpack2.h"
3341 struct IFD_entry
3342 {
3343 SHORT id;
3344 SHORT type;
3345 ULONG count;
3346 LONG value;
3347 };
3348
3349 struct IFD_rational
3350 {
3351 LONG numerator;
3352 LONG denominator;
3353 };
3354
3355 static const struct tiff_data
3356 {
3357 USHORT byte_order;
3358 USHORT version;
3359 ULONG dir_offset;
3360 USHORT number_of_entries;
3361 struct IFD_entry entry[40];
3362 ULONG next_IFD;
3363 struct IFD_rational xres;
3364 DOUBLE double_val;
3365 struct IFD_rational srational_val;
3366 char string[14];
3367 SHORT short_val[4];
3368 LONG long_val[2];
3369 FLOAT float_val[2];
3370 struct IFD_rational rational[3];
3371 BYTE pixel_data[4];
3372 } TIFF_data =
3373 {
3374 #ifdef WORDS_BIGENDIAN
3375 'M' | 'M' << 8,
3376 #else
3377 'I' | 'I' << 8,
3378 #endif
3379 42,
3380 FIELD_OFFSET(struct tiff_data, number_of_entries),
3381 31,
3382 {
3383 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3384 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3385 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3386 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3387 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3388 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3389 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3390 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3391 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3392 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3393 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3394 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3395 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3396 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3397 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3398 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3399 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3400 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3401 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3402 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3403 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3404 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3405 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3406 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3407 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3408 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3409 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3410 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3411 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3412 /* Some gdiplus versions ignore these fields.
3413 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3414 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3415 { 0xf014, IFD_LONG, 0, 0x11223344 },
3416 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3417 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3418 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3419 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3420 },
3421 0,
3422 { 900, 3 },
3423 1234567890.0987654321,
3424 { 0x1a2b3c4d, 0x5a6b7c8d },
3425 "Hello World!",
3426 { 0x0101, 0x0202, 0x0303, 0x0404 },
3427 { 0x11223344, 0x55667788 },
3428 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3429 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3430 { 0x11, 0x22, 0x33, 0 }
3431 };
3432 #include "poppack.h"
3433
3434 static void test_tiff_properties(void)
3435 {
3436 static const struct test_data
3437 {
3438 ULONG type, id, length;
3439 const BYTE value[24];
3440 } td[31] =
3441 {
3442 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3443 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3444 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3445 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3446 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3447 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3448 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3449 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3450 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3451 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3452 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3453 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3454 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3455 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3456 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3457 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3458 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3459 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3460 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3461 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3462 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3463 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3464 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3465 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3466 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3467 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3468 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3469 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3470 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3471 { PropertyTagTypeSRational, 0xf016, 24,
3472 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3473 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3474 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3475 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3476 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3477 };
3478 GpStatus status;
3479 GpImage *image;
3480 GUID guid;
3481 UINT dim_count, frame_count, prop_count, prop_size, i;
3482 PROPID *prop_id;
3483 PropertyItem *prop_item;
3484
3485 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3486 if (!image)
3487 {
3488 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3489 return;
3490 }
3491
3492 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3493 expect(Ok, status);
3494 expect(1, dim_count);
3495
3496 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3497 expect(Ok, status);
3498 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3499
3500 frame_count = 0xdeadbeef;
3501 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3502 expect(Ok, status);
3503 expect(1, frame_count);
3504
3505 prop_count = 0xdeadbeef;
3506 status = GdipGetPropertyCount(image, &prop_count);
3507 expect(Ok, status);
3508 ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3509 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3510 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3511
3512 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3513
3514 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3515 expect(Ok, status);
3516
3517 for (i = 0; i < prop_count; i++)
3518 {
3519 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3520 expect(Ok, status);
3521 if (status != Ok) break;
3522 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3523
3524 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3525 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3526 expect(Ok, status);
3527 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3528 ok(td[i].type == prop_item->type ||
3529 /* Win7 stopped using proper but not documented types, and it
3530 looks broken since TypeFloat and TypeDouble now reported as
3531 TypeUndefined, and signed types reported as unsigned. */
3532 broken(prop_item->type == documented_type(td[i].type)),
3533 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3534 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3535 prop_size -= sizeof(*prop_item);
3536 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3537 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3538 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3539 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3540 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3541 if (td[i].length == prop_item->length)
3542 {
3543 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3544 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3545 if (!match)
3546 {
3547 UINT j;
3548 BYTE *data = prop_item->value;
3549 trace("id %#x:", prop_item->id);
3550 for (j = 0; j < prop_item->length; j++)
3551 trace(" %02x", data[j]);
3552 trace("\n");
3553 }
3554 }
3555 HeapFree(GetProcessHeap(), 0, prop_item);
3556 }
3557
3558 HeapFree(GetProcessHeap(), 0, prop_id);
3559
3560 GdipDisposeImage(image);
3561 }
3562
3563 static void test_GdipGetAllPropertyItems(void)
3564 {
3565 static const struct test_data
3566 {
3567 ULONG type, id, length;
3568 BYTE value[32];
3569 } td[16] =
3570 {
3571 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3572 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3573 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3574 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3575 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3576 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3577 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3578 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3579 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3580 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3581 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3582 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3583 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3584 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3585 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3586 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3587 };
3588 GpStatus status;
3589 GpImage *image;
3590 GUID guid;
3591 UINT dim_count, frame_count, prop_count, prop_size, i;
3592 UINT total_size, total_count;
3593 PROPID *prop_id;
3594 PropertyItem *prop_item;
3595 const char *item_data;
3596
3597 image = load_image(tiffimage, sizeof(tiffimage));
3598 ok(image != 0, "Failed to load TIFF image data\n");
3599 if (!image) return;
3600
3601 dim_count = 0xdeadbeef;
3602 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3603 expect(Ok, status);
3604 expect(1, dim_count);
3605
3606 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3607 expect(Ok, status);
3608 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3609
3610 frame_count = 0xdeadbeef;
3611 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3612 expect(Ok, status);
3613 expect(1, frame_count);
3614
3615 prop_count = 0xdeadbeef;
3616 status = GdipGetPropertyCount(image, &prop_count);
3617 expect(Ok, status);
3618 ok(prop_count == sizeof(td)/sizeof(td[0]),
3619 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3620
3621 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3622
3623 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3624 expect(Ok, status);
3625
3626 prop_size = 0;
3627 for (i = 0; i < prop_count; i++)
3628 {
3629 UINT size;
3630 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3631 expect(Ok, status);
3632 if (status != Ok) break;
3633 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3634
3635 prop_size += size;
3636
3637 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3638 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3639 expect(Ok, status);
3640 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3641 ok(td[i].type == prop_item->type,
3642 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3643 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3644 size -= sizeof(*prop_item);
3645 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3646 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3647 if (td[i].length == prop_item->length)
3648 {
3649 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3650 ok(match, "%u: data mismatch\n", i);
3651 if (!match)
3652 {
3653 UINT j;
3654 BYTE *data = prop_item->value;
3655 trace("id %#x:", prop_item->id);
3656 for (j = 0; j < prop_item->length; j++)
3657 trace(" %02x", data[j]);
3658 trace("\n");
3659 }
3660 }
3661 HeapFree(GetProcessHeap(), 0, prop_item);
3662 }
3663
3664 HeapFree(GetProcessHeap(), 0, prop_id);
3665
3666 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3667 expect(InvalidParameter, status);
3668 status = GdipGetPropertySize(image, &total_size, NULL);
3669 expect(InvalidParameter, status);
3670 status = GdipGetPropertySize(image, NULL, &total_count);
3671 expect(InvalidParameter, status);
3672 status = GdipGetPropertySize(image, NULL, NULL);
3673 expect(InvalidParameter, status);
3674 total_size = 0xdeadbeef;
3675 total_count = 0xdeadbeef;
3676 status = GdipGetPropertySize(image, &total_size, &total_count);
3677 expect(Ok, status);
3678 ok(prop_count == total_count,
3679 "expected total property count %u, got %u\n", prop_count, total_count);
3680 ok(prop_size == total_size,
3681 "expected total property size %u, got %u\n", prop_size, total_size);
3682
3683 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3684
3685 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3686 expect(InvalidParameter, status);
3687 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3688 expect(InvalidParameter, status);
3689 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3690 expect(InvalidParameter, status);
3691 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3692 expect(InvalidParameter, status);
3693 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3694 expect(InvalidParameter, status);
3695 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3696 expect(InvalidParameter, status);
3697 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3698 expect(Ok, status);
3699
3700 item_data = (const char *)(prop_item + prop_count);
3701 for (i = 0; i < prop_count; i++)
3702 {
3703 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3704 i, item_data, prop_item[i].value);
3705 ok(td[i].type == prop_item[i].type,
3706 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3707 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3708 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3709 if (td[i].length == prop_item[i].length)
3710 {
3711 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3712 ok(match, "%u: data mismatch\n", i);
3713 if (!match)
3714 {
3715 UINT j;
3716 BYTE *data = prop_item[i].value;
3717 trace("id %#x:", prop_item[i].id);
3718 for (j = 0; j < prop_item[i].length; j++)
3719 trace(" %02x", data[j]);
3720 trace("\n");
3721 }
3722 }
3723 item_data += prop_item[i].length;
3724 }
3725
3726 HeapFree(GetProcessHeap(), 0, prop_item);
3727
3728 GdipDisposeImage(image);
3729 }
3730
3731 static void test_tiff_palette(void)
3732 {
3733 GpStatus status;
3734 GpImage *image;
3735 PixelFormat format;
3736 INT size;
3737 struct
3738 {
3739 ColorPalette pal;
3740 ARGB entry[256];
3741 } palette;
3742 ARGB *entries = palette.pal.Entries;
3743
3744 /* 1bpp TIFF without palette */
3745 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3746 if (!image)
3747 {
3748 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3749 return;
3750 }
3751
3752 status = GdipGetImagePixelFormat(image, &format);
3753 expect(Ok, status);
3754 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3755
3756 status = GdipGetImagePaletteSize(image, &size);
3757 ok(status == Ok || broken(status == GenericError), /* XP */
3758 "GdipGetImagePaletteSize error %d\n", status);
3759 if (status == GenericError)
3760 {
3761 GdipDisposeImage(image);
3762 return;
3763 }
3764 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3765
3766 status = GdipGetImagePalette(image, &palette.pal, size);
3767 expect(Ok, status);
3768 expect(0, palette.pal.Flags);
3769 expect(2, palette.pal.Count);
3770 if (palette.pal.Count == 2)
3771 {
3772 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3773 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3774 }
3775
3776 GdipDisposeImage(image);
3777 }
3778
3779 static void test_bitmapbits(void)
3780 {
3781 /* 8 x 2 bitmap */
3782 static const BYTE pixels_24[48] =
3783 {
3784 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3785 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3786 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3787 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3788 };
3789 static const BYTE pixels_00[48] =
3790 {
3791 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3792 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3793 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3794 0,0,0, 0,0,0, 0,0,0, 0,0,0
3795 };
3796 static const BYTE pixels_24_77[64] =
3797 {
3798 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3799 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3800 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3801 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3802 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3803 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3804 };
3805 static const BYTE pixels_77[64] =
3806 {
3807 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3808 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3809 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3810 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3811 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3812 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3813 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3814 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3815 };
3816 static const BYTE pixels_8[16] =
3817 {
3818 0x01,0,0x01,0,0x01,0,0x01,0,
3819 0x01,0,0x01,0,0x01,0,0x01,0
3820 };
3821 static const BYTE pixels_8_77[64] =
3822 {
3823 0x01,0,0x01,0,0x01,0,0x01,0,
3824 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3825 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3826 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3827 0x01,0,0x01,0,0x01,0,0x01,0,
3828 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3829 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3830 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3831 };
3832 static const BYTE pixels_1_77[64] =
3833 {
3834 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3835 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3836 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3837 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3838 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3839 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3840 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3841 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3842 };
3843 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3844 static const struct test_data
3845 {
3846 PixelFormat format;
3847 UINT bpp;
3848 ImageLockMode mode;
3849 UINT stride, size;
3850 const BYTE *pixels;
3851 const BYTE *pixels_unlocked;
3852 } td[] =
3853 {
3854 /* 0 */
3855 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3856
3857 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3858 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3859 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3860 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3861 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3862 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3863 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3864 /* 8 */
3865 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3866 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3867 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3868 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3869 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3870 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3871 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3872 /* 15 */
3873 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3874 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3875 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3876 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3877 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3878 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3879 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3880 };
3881 BYTE buf[64];
3882 GpStatus status;
3883 GpBitmap *bitmap;
3884 UINT i;
3885 BitmapData data;
3886 struct
3887 {
3888 ColorPalette pal;
3889 ARGB entries[1];
3890 } palette;
3891 ARGB *entries = palette.pal.Entries;
3892
3893 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3894 {
3895 BYTE pixels[sizeof(pixels_24)];
3896 memcpy(pixels, pixels_24, sizeof(pixels_24));
3897 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3898 expect(Ok, status);
3899
3900 /* associate known palette with pixel data */
3901 palette.pal.Flags = PaletteFlagsGrayScale;
3902 palette.pal.Count = 2;
3903 entries[0] = 0xff000000;
3904 entries[1] = 0xffffffff;
3905 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3906 expect(Ok, status);
3907
3908 memset(&data, 0xfe, sizeof(data));
3909 if (td[i].mode & ImageLockModeUserInputBuf)
3910 {
3911 memset(buf, 0x77, sizeof(buf));
3912 data.Scan0 = buf;
3913 data.Stride = 32;
3914 }
3915 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3916 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3917 if (status != Ok)
3918 {
3919 GdipDisposeImage((GpImage *)bitmap);
3920 continue;
3921 }
3922 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3923 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3924 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3925 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3926 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3927 if (td[i].mode & ImageLockModeUserInputBuf)
3928 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3929 if (td[i].size == data.Height * data.Stride)
3930 {
3931 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3932
3933 match = 1;
3934 for (j = 0; j < data.Height; j++)
3935 {
3936 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3937 {
3938 match = 0;
3939 break;
3940 }
3941 }
3942 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3943 {
3944 ok(match,
3945 "%u: data should match\n", i);
3946 if (!match)
3947 {
3948 BYTE *bits = data.Scan0;
3949 trace("%u: data mismatch for format %#x:", i, td[i].format);
3950 for (j = 0; j < td[i].size; j++)
3951 trace(" %02x", bits[j]);
3952 trace("\n");
3953 }
3954 }
3955 else
3956 ok(!match, "%u: data shouldn't match\n", i);
3957
3958 memset(data.Scan0, 0, td[i].size);
3959 }
3960
3961 status = GdipBitmapUnlockBits(bitmap, &data);
3962 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3963
3964 memset(&data, 0xfe, sizeof(data));
3965 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3966 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3967 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3968 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3969 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3970 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3971 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3972 if (data.Height * data.Stride == 48)
3973 {
3974 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3975 ok(match, "%u: data should match\n", i);
3976 if (!match)
3977 {
3978 UINT j;
3979 BYTE *bits = data.Scan0;
3980 trace("%u: data mismatch for format %#x:", i, td[i].format);
3981 for (j = 0; j < 48; j++)
3982 trace(" %02x", bits[j]);
3983 trace("\n");
3984 }
3985 }
3986
3987 status = GdipBitmapUnlockBits(bitmap, &data);
3988 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3989
3990 status = GdipDisposeImage((GpImage *)bitmap);
3991 expect(Ok, status);
3992 }
3993 }
3994
3995 static void test_DrawImage(void)
3996 {
3997 BYTE black_1x1[4] = { 0,0,0,0 };
3998 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3999 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4000 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4001 0,0,0,0,0,0,0xff,0xff };
4002 GpStatus status;
4003 union
4004 {
4005 GpBitmap *bitmap;
4006 GpImage *image;
4007 } u1, u2;
4008 GpGraphics *graphics;
4009 int match;
4010
4011 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4012 expect(Ok, status);
4013 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4014 expect(Ok, status);
4015
4016 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4017 expect(Ok, status);
4018 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4019 expect(Ok, status);
4020 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4021 expect(Ok, status);
4022 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4023 expect(Ok, status);
4024
4025 status = GdipDrawImageI(graphics, u1.image, 0, 0);
4026 expect(Ok, status);
4027
4028 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4029 ok(match, "data should match\n");
4030 if (!match)
4031 {
4032 UINT i, size = sizeof(white_2x2);
4033 BYTE *bits = white_2x2;
4034 for (i = 0; i < size; i++)
4035 trace(" %02x", bits[i]);
4036 trace("\n");
4037 }
4038
4039 status = GdipDeleteGraphics(graphics);
4040 expect(Ok, status);
4041 status = GdipDisposeImage(u1.image);
4042 expect(Ok, status);
4043 status = GdipDisposeImage(u2.image);
4044 expect(Ok, status);
4045 }
4046
4047 static void test_DrawImage_SourceCopy(void)
4048 {
4049 DWORD dst_pixels[4] = { 0xffffffff, 0xffffffff,
4050 0xffffffff, 0xffffffff };
4051 DWORD src_pixels[4] = { 0, 0xffff0000,
4052 0, 0xff00ff };
4053
4054 GpStatus status;
4055 union
4056 {
4057 GpBitmap *bitmap;
4058 GpImage *image;
4059 } u1, u2;
4060 GpGraphics *graphics;
4061
4062 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)dst_pixels, &u1.bitmap);
4063 expect(Ok, status);
4064
4065 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppARGB, (BYTE*)src_pixels, &u2.bitmap);
4066 expect(Ok, status);
4067 status = GdipGetImageGraphicsContext(u1.image, &graphics);
4068 expect(Ok, status);
4069 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4070 expect(Ok, status);
4071
4072 status = GdipSetCompositingMode(graphics, CompositingModeSourceCopy);
4073 expect(Ok, status);
4074
4075 status = GdipDrawImageI(graphics, u2.image, 0, 0);
4076 expect(Ok, status);
4077
4078 todo_wine expect(0, dst_pixels[0]);
4079 expect(0xffff0000, dst_pixels[1]);
4080 todo_wine expect(0, dst_pixels[2]);
4081 todo_wine expect(0, dst_pixels[3]);
4082
4083 status = GdipDeleteGraphics(graphics);
4084 expect(Ok, status);
4085 status = GdipDisposeImage(u1.image);
4086 expect(Ok, status);
4087 status = GdipDisposeImage(u2.image);
4088 expect(Ok, status);
4089 }
4090
4091 static void test_GdipDrawImagePointRect(void)
4092 {
4093 BYTE black_1x1[4] = { 0,0,0,0 };
4094 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
4095 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
4096 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
4097 0,0,0,0,0,0,0xff,0xff };
4098 GpStatus status;
4099 union
4100 {
4101 GpBitmap *bitmap;
4102 GpImage *image;
4103 } u1, u2;
4104 GpGraphics *graphics;
4105 int match;
4106
4107 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
4108 expect(Ok, status);
4109 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4110 expect(Ok, status);
4111
4112 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
4113 expect(Ok, status);
4114 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
4115 expect(Ok, status);
4116 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4117 expect(Ok, status);
4118 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4119 expect(Ok, status);
4120
4121 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
4122 expect(Ok, status);
4123
4124 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
4125 ok(match, "data should match\n");
4126 if (!match)
4127 {
4128 UINT i, size = sizeof(white_2x2);
4129 BYTE *bits = white_2x2;
4130 for (i = 0; i < size; i++)
4131 trace(" %02x", bits[i]);
4132 trace("\n");
4133 }
4134
4135 status = GdipDeleteGraphics(graphics);
4136 expect(Ok, status);
4137 status = GdipDisposeImage(u1.image);
4138 expect(Ok, status);
4139 status = GdipDisposeImage(u2.image);
4140 expect(Ok, status);
4141 }
4142
4143 static void test_image_format(void)
4144 {
4145 static const PixelFormat fmt[] =
4146 {
4147 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
4148 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
4149 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
4150 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
4151 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
4152 };
4153 GpStatus status;
4154 GpBitmap *bitmap;
4155 GpImage *thumb;
4156 HBITMAP hbitmap;
4157 BITMAP bm;
4158 PixelFormat format;
4159 BitmapData data;
4160 UINT i, ret;
4161
4162 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
4163 {
4164 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
4165 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
4166 "GdipCreateBitmapFromScan0 error %d\n", status);
4167 if (status != Ok) continue;
4168
4169 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
4170 expect(Ok, status);
4171 expect(fmt[i], format);
4172
4173 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
4174 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4175 todo_wine expect(InvalidParameter, status);
4176 else
4177 {
4178 expect(Ok, status);
4179 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
4180 expect(sizeof(bm), ret);
4181 expect(0, bm.bmType);
4182 expect(1, bm.bmWidth);
4183 expect(1, bm.bmHeight);
4184 expect(4, bm.bmWidthBytes);
4185 expect(1, bm.bmPlanes);
4186 expect(32, bm.bmBitsPixel);
4187 DeleteObject(hbitmap);
4188 }
4189
4190 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
4191 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4192 todo_wine
4193 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
4194 "expected OutOfMemory, got %d\n", status);
4195 else
4196 expect(Ok, status);
4197 if (status == Ok)
4198 {
4199 status = GdipGetImagePixelFormat(thumb, &format);
4200 expect(Ok, status);
4201 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
4202 "expected PixelFormat32bppPARGB, got %#x\n", format);
4203 status = GdipDisposeImage(thumb);
4204 expect(Ok, status);
4205 }
4206
4207 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4208 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
4209 todo_wine expect(InvalidParameter, status);
4210 else
4211 {
4212 expect(Ok, status);
4213 status = GdipBitmapUnlockBits(bitmap, &data);
4214 expect(Ok, status);
4215 }
4216
4217 status = GdipDisposeImage((GpImage *)bitmap);
4218 expect(Ok, status);
4219 }
4220 }
4221
4222 static void test_DrawImage_scale(void)
4223 {
4224 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
4225 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4226 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
4227 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4228 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
4229 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4230 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
4231 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4232 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4233 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4234 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4235 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4236 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4237 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4238 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
4239 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4240 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4241 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4242 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
4243 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
4244 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4245 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4246 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4247 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4248 static const struct test_data
4249 {
4250 REAL scale_x;
4251 PixelOffsetMode pixel_offset_mode;
4252 const BYTE *image;
4253 BOOL todo;
4254 } td[] =
4255 {
4256 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4257 { 1.0, PixelOffsetModeNone, image_100 },
4258 { 1.2, PixelOffsetModeNone, image_120 },
4259 { 1.5, PixelOffsetModeNone, image_150 },
4260 { 1.8, PixelOffsetModeNone, image_180 },
4261 { 2.0, PixelOffsetModeNone, image_200 },
4262 { 2.5, PixelOffsetModeNone, image_250 },
4263
4264 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4265 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4266 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4267 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4268 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4269 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4270 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4271
4272 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4273 { 1.0, PixelOffsetModeHalf, image_100 },
4274 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4275 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4276 { 1.8, PixelOffsetModeHalf, image_180 },
4277 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4278 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4279
4280 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4281 { 1.0, PixelOffsetModeHighQuality, image_100 },
4282 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4283 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4284 { 1.8, PixelOffsetModeHighQuality, image_180 },
4285 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4286 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4287 };
4288 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4289 BYTE dst_8x1[24];
4290 GpStatus status;
4291 union
4292 {
4293 GpBitmap *bitmap;
4294 GpImage *image;
4295 } u1, u2;
4296 GpGraphics *graphics;
4297 GpMatrix *matrix;
4298 int i, match;
4299
4300 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4301 expect(Ok, status);
4302 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4303 expect(Ok, status);
4304
4305 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4306 expect(Ok, status);
4307 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4308 expect(Ok, status);
4309 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4310 expect(Ok, status);
4311 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4312 expect(Ok, status);
4313
4314 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4315 {
4316 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4317 expect(Ok, status);
4318
4319 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4320 expect(Ok, status);
4321 status = GdipSetWorldTransform(graphics, matrix);
4322 expect(Ok, status);
4323 GdipDeleteMatrix(matrix);
4324
4325 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4326 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4327 expect(Ok, status);
4328
4329 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4330 todo_wine_if (!match && td[i].todo)
4331 ok(match, "%d: data should match\n", i);
4332 if (!match)
4333 {
4334 UINT i, size = sizeof(dst_8x1);
4335 const BYTE *bits = dst_8x1;
4336 for (i = 0; i < size; i++)
4337 trace(" %02x", bits[i]);
4338 trace("\n");
4339 }
4340 }
4341
4342 status = GdipDeleteGraphics(graphics);
4343 expect(Ok, status);
4344 status = GdipDisposeImage(u1.image);
4345 expect(Ok, status);
4346 status = GdipDisposeImage(u2.image);
4347 expect(Ok, status);
4348 }
4349
4350 static const BYTE animatedgif[] = {
4351 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4352 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4353 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4354 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4355 0x03,0x01,0x05,0x00,0x00,
4356 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4357 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4358 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4359 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4360 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4361 0x02,0x02,0x4C,0x01,0x00,
4362 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4363 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4364 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4365 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4366 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4367 0x02,0x02,0x44,0x01,0x00,
4368 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4369 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4370 };
4371
4372 static void test_gif_properties(void)
4373 {
4374 static const struct test_data
4375 {
4376 ULONG type, id, length;
4377 const BYTE value[13];
4378 } td[] =
4379 {
4380 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4381 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4382 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4383 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4384 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4385 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4386 };
4387 GpStatus status;
4388 GpImage *image;
4389 GUID guid;
4390 UINT dim_count, frame_count, prop_count, prop_size, i;
4391 UINT total_size, total_count;
4392 PROPID *prop_id;
4393 PropertyItem *prop_item;
4394 const char *item_data;
4395
4396 image = load_image(animatedgif, sizeof(animatedgif));
4397 if (!image) /* XP fails to load this GIF image */
4398 {
4399 trace("Failed to load GIF image data\n");
4400 return;
4401 }
4402
4403 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4404 expect(Ok, status);
4405 expect(1, dim_count);
4406
4407 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4408 expect(Ok, status);
4409 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4410
4411 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4412 expect(Ok, status);
4413 expect(2, frame_count);
4414
4415 status = GdipImageSelectActiveFrame(image, &guid, 1);
4416 expect(Ok, status);
4417
4418 status = GdipGetPropertyCount(image, &prop_count);
4419 expect(Ok, status);
4420 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
4421 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
4422
4423 if (prop_count != sizeof(td)/sizeof(td[0]))
4424 {
4425 GdipDisposeImage(image);
4426 return;
4427 }
4428
4429 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4430
4431 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4432 expect(Ok, status);
4433
4434 prop_size = 0;
4435 for (i = 0; i < prop_count; i++)
4436 {
4437 UINT size;
4438 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4439 expect(Ok, status);
4440 if (status != Ok) break;
4441 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4442
4443 prop_size += size;
4444
4445 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4446 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4447 expect(Ok, status);
4448 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4449 ok(td[i].type == prop_item->type,
4450 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4451 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4452 size -= sizeof(*prop_item);
4453 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4454 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4455 if (td[i].length == prop_item->length)
4456 {
4457 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4458 ok(match, "%u: data mismatch\n", i);
4459 if (!match)
4460 {
4461 UINT j;
4462 BYTE *data = prop_item->value;
4463 trace("id %#x:", prop_item->id);
4464 for (j = 0; j < prop_item->length; j++)
4465 trace(" %02x", data[j]);
4466 trace("\n");
4467 }
4468 }
4469 HeapFree(GetProcessHeap(), 0, prop_item);
4470 }
4471
4472 HeapFree(GetProcessHeap(), 0, prop_id);
4473
4474 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4475 expect(InvalidParameter, status);
4476 status = GdipGetPropertySize(image, &total_size, NULL);
4477 expect(InvalidParameter, status);
4478 status = GdipGetPropertySize(image, NULL, &total_count);
4479 expect(InvalidParameter, status);
4480 status = GdipGetPropertySize(image, NULL, NULL);
4481 expect(InvalidParameter, status);
4482 total_size = 0xdeadbeef;
4483 total_count = 0xdeadbeef;
4484 status = GdipGetPropertySize(image, &total_size, &total_count);
4485 expect(Ok, status);
4486 ok(prop_count == total_count,
4487 "expected total property count %u, got %u\n", prop_count, total_count);
4488 ok(prop_size == total_size,
4489 "expected total property size %u, got %u\n", prop_size, total_size);
4490
4491 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4492
4493 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4494 expect(InvalidParameter, status);
4495 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4496 expect(InvalidParameter, status);
4497 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4498 expect(InvalidParameter, status);
4499 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4500 expect(InvalidParameter, status);
4501 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4502 expect(InvalidParameter, status);
4503 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4504 expect(InvalidParameter, status);
4505 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4506 expect(Ok, status);
4507
4508 item_data = (const char *)(prop_item + prop_count);
4509 for (i = 0; i < prop_count; i++)
4510 {
4511 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4512 i, item_data, prop_item[i].value);
4513 ok(td[i].type == prop_item[i].type,
4514 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4515 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4516 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4517 if (td[i].length == prop_item[i].length)
4518 {
4519 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4520 ok(match, "%u: data mismatch\n", i);
4521 if (!match)
4522 {
4523 UINT j;
4524 BYTE *data = prop_item[i].value;
4525 trace("id %#x:", prop_item[i].id);
4526 for (j = 0; j < prop_item[i].length; j++)
4527 trace(" %02x", data[j]);
4528 trace("\n");
4529 }
4530 }
4531 item_data += prop_item[i].length;
4532 }
4533
4534 HeapFree(GetProcessHeap(), 0, prop_item);
4535
4536 GdipDisposeImage(image);
4537 }
4538
4539 static void test_ARGB_conversion(void)
4540 {
4541 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4542 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4543 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4544 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4545 BYTE *bits;
4546 GpBitmap *bitmap;
4547 BitmapData data;
4548 GpStatus status;
4549 int match;
4550
4551 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4552 expect(Ok, status);
4553
4554 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4555 expect(Ok, status);
4556 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4557 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4558 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4559 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4560 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4561 ok(match, "bits don't match\n");
4562 if (!match)
4563 {
4564 bits = data.Scan0;
4565 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4566 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4567 }
4568 status = GdipBitmapUnlockBits(bitmap, &data);
4569 expect(Ok, status);
4570
4571 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4572 expect(Ok, status);
4573 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4574 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4575 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4576 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4577 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4578 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4579 ok(match, "bits don't match\n");
4580 if (!match)
4581 {
4582 bits = data.Scan0;
4583 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4584 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4585 }
4586 status = GdipBitmapUnlockBits(bitmap, &data);
4587 expect(Ok, status);
4588
4589 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4590 expect(Ok, status);
4591 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4592 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4593 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4594 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4595 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4596 ok(match, "bits don't match\n");
4597 if (!match)
4598 {
4599 bits = data.Scan0;
4600 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4601 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4602 }
4603 status = GdipBitmapUnlockBits(bitmap, &data);
4604 expect(Ok, status);
4605
4606 GdipDisposeImage((GpImage *)bitmap);
4607 }
4608
4609
4610 static void test_CloneBitmapArea(void)
4611 {
4612 GpStatus status;
4613 GpBitmap *bitmap, *copy;
4614 BitmapData data, data2;
4615
4616 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4617 expect(Ok, status);
4618
4619 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4620 expect(Ok, status);
4621
4622 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4623 expect(WrongState, status);
4624
4625 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4626 expect(Ok, status);
4627
4628 status = GdipBitmapUnlockBits(bitmap, &data);
4629 expect(Ok, status);
4630
4631 GdipDisposeImage((GpImage *)copy);
4632 GdipDisposeImage((GpImage *)bitmap);
4633 }
4634
4635 static BOOL get_encoder_clsid(LPCWSTR mime, GUID *format, CLSID *clsid)
4636 {
4637 GpStatus status;
4638 UINT n_codecs, info_size, i;
4639 ImageCodecInfo *info;
4640 BOOL ret = FALSE;
4641
4642 status = GdipGetImageEncodersSize(&n_codecs, &info_size);
4643 expect(Ok, status);
4644
4645 info = GdipAlloc(info_size);
4646
4647 status = GdipGetImageEncoders(n_codecs, info_size, info);
4648 expect(Ok, status);
4649
4650 for (i = 0; i < n_codecs; i++)
4651 {
4652 if (!lstrcmpW(info[i].MimeType, mime))
4653 {
4654 *format = info[i].FormatID;
4655 *clsid = info[i].Clsid;
4656 ret = TRUE;
4657 break;
4658 }
4659 }
4660
4661 GdipFree(info);
4662 return ret;
4663 }
4664
4665 static void test_supported_encoders(void)
4666 {
4667 static const WCHAR bmp_mimetype[] = { 'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p',0 };
4668 static const WCHAR jpeg_mimetype[] = { 'i','m','a','g','e','/','j','p','e','g',0 };
4669 static const WCHAR gif_mimetype[] = { 'i','m','a','g','e','/','g','i','f',0 };
4670 static const WCHAR tiff_mimetype[] = { 'i','m','a','g','e','/','t','i','f','f',0 };
4671 static const WCHAR png_mimetype[] = { 'i','m','a','g','e','/','p','n','g',0 };
4672 static const struct test_data
4673 {
4674 LPCWSTR mime;
4675 const GUID *format;
4676 } td[] =
4677 {
4678 { bmp_mimetype, &ImageFormatBMP },
4679 { jpeg_mimetype, &ImageFormatJPEG },
4680 { gif_mimetype, &ImageFormatGIF },
4681 { tiff_mimetype, &ImageFormatTIFF },
4682 { png_mimetype, &ImageFormatPNG }
4683 };
4684 GUID format, clsid;
4685 BOOL ret;
4686 HRESULT hr;
4687 GpStatus status;
4688 GpBitmap *bm;
4689 IStream *stream;
4690 HGLOBAL hmem;
4691 int i;
4692
4693 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bm);
4694 ok(status == Ok, "GdipCreateBitmapFromScan0 error %d\n", status);
4695
4696 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4697 {
4698 ret = get_encoder_clsid(td[i].mime, &format, &clsid);
4699 ok(ret, "%s encoder is not in the list\n", wine_dbgstr_w(td[i].mime));
4700 expect_guid(td[i].format, &format, __LINE__, FALSE);
4701
4702 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
4703
4704 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
4705 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
4706
4707 status = GdipSaveImageToStream((GpImage *)bm, stream, &clsid, NULL);
4708 ok(status == Ok, "GdipSaveImageToStream error %d\n", status);
4709
4710 IStream_Release(stream);
4711 }
4712
4713 GdipDisposeImage((GpImage *)bm);
4714 }
4715
4716 static void test_createeffect(void)
4717 {
4718 static const GUID noneffect = { 0xcd0c3d4b, 0xe15e, 0x4cf2, { 0x9e, 0xa8, 0x6e, 0x1d, 0x65, 0x48, 0xc5, 0xa5 } };
4719 GpStatus (WINAPI *pGdipCreateEffect)( const GUID guid, CGpEffect **effect);
4720 GpStatus (WINAPI *pGdipDeleteEffect)( CGpEffect *effect);
4721 GpStatus stat;
4722 CGpEffect *effect;
4723 HMODULE mod = GetModuleHandleA("gdiplus.dll");
4724 int i;
4725 const GUID * const effectlist[] =
4726 {&BlurEffectGuid, &SharpenEffectGuid, &ColorMatrixEffectGuid, &ColorLUTEffectGuid,
4727 &BrightnessContrastEffectGuid, &HueSaturationLightnessEffectGuid, &LevelsEffectGuid,
4728 &TintEffectGuid, &ColorBalanceEffectGuid, &RedEyeCorrectionEffectGuid, &ColorCurveEffectGuid};
4729
4730 pGdipCreateEffect = (void*)GetProcAddress( mod, "GdipCreateEffect");
4731 pGdipDeleteEffect = (void*)GetProcAddress( mod, "GdipDeleteEffect");
4732 if(!pGdipCreateEffect || !pGdipDeleteEffect)
4733 {
4734 /* GdipCreateEffect/GdipDeleteEffect was introduced in Windows Vista. */
4735 win_skip("GDIPlus version 1.1 not available\n");
4736 return;
4737 }
4738
4739 stat = pGdipCreateEffect(BlurEffectGuid, NULL);
4740 expect(InvalidParameter, stat);
4741
4742 stat = pGdipCreateEffect(noneffect, &effect);
4743 todo_wine expect(Win32Error, stat);
4744
4745 for(i=0; i < sizeof(effectlist) / sizeof(effectlist[0]); i++)
4746 {
4747 stat = pGdipCreateEffect(*effectlist[i], &effect);
4748 todo_wine expect(Ok, stat);
4749 if(stat == Ok)
4750 {
4751 stat = pGdipDeleteEffect(effect);
4752 expect(Ok, stat);
4753 }
4754 }
4755 }
4756
4757 static void test_getadjustedpalette(void)
4758 {
4759 ColorMap colormap;
4760 GpImageAttributes *imageattributes;
4761 ColorPalette *palette;
4762 GpStatus stat;
4763
4764 stat = GdipCreateImageAttributes(&imageattributes);
4765 expect(Ok, stat);
4766
4767 colormap.oldColor.Argb = 0xffffff00;
4768 colormap.newColor.Argb = 0xffff00ff;
4769 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeBitmap,
4770 TRUE, 1, &colormap);
4771 expect(Ok, stat);
4772
4773 colormap.oldColor.Argb = 0xffffff80;
4774 colormap.newColor.Argb = 0xffff80ff;
4775 stat = GdipSetImageAttributesRemapTable(imageattributes, ColorAdjustTypeDefault,
4776 TRUE, 1, &colormap);
4777 expect(Ok, stat);
4778
4779 palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 2);
4780 palette->Count = 0;
4781
4782 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4783 expect(InvalidParameter, stat);
4784
4785 palette->Count = 3;
4786 palette->Entries[0] = 0xffffff00;
4787 palette->Entries[1] = 0xffffff80;
4788 palette->Entries[2] = 0xffffffff;
4789
4790 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBitmap);
4791 expect(Ok, stat);
4792 expect(0xffff00ff, palette->Entries[0]);
4793 expect(0xffffff80, palette->Entries[1]);
4794 expect(0xffffffff, palette->Entries[2]);
4795
4796 palette->Entries[0] = 0xffffff00;
4797 palette->Entries[1] = 0xffffff80;
4798 palette->Entries[2] = 0xffffffff;
4799
4800 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeBrush);
4801 expect(Ok, stat);
4802 expect(0xffffff00, palette->Entries[0]);
4803 expect(0xffff80ff, palette->Entries[1]);
4804 expect(0xffffffff, palette->Entries[2]);
4805
4806 stat = GdipGetImageAttributesAdjustedPalette(NULL, palette, ColorAdjustTypeBitmap);
4807 expect(InvalidParameter, stat);
4808
4809 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, NULL, ColorAdjustTypeBitmap);
4810 expect(InvalidParameter, stat);
4811
4812 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, -1);
4813 expect(InvalidParameter, stat);
4814
4815 stat = GdipGetImageAttributesAdjustedPalette(imageattributes, palette, ColorAdjustTypeDefault);
4816 expect(InvalidParameter, stat);
4817
4818 GdipFree(palette);
4819 GdipDisposeImageAttributes(imageattributes);
4820 }
4821
4822 static void test_histogram(void)
4823 {
4824 UINT ch0[256], ch1[256], ch2[256], ch3[256];
4825 HistogramFormat test_formats[] =
4826 {
4827 HistogramFormatARGB,
4828 HistogramFormatPARGB,
4829 HistogramFormatRGB,
4830 HistogramFormatGray,
4831 HistogramFormatB,
4832 HistogramFormatG,
4833 HistogramFormatR,
4834 HistogramFormatA,
4835 };
4836 const UINT WIDTH = 8, HEIGHT = 16;
4837 UINT num, i, x;
4838 GpStatus stat;
4839 GpBitmap *bm;
4840
4841 if (!pGdipBitmapGetHistogramSize)
4842 {
4843 win_skip("GdipBitmapGetHistogramSize is not supported\n");
4844 return;
4845 }
4846
4847 stat = pGdipBitmapGetHistogramSize(HistogramFormatARGB, NULL);
4848 expect(InvalidParameter, stat);
4849
4850 stat = pGdipBitmapGetHistogramSize(0xff, NULL);
4851 expect(InvalidParameter, stat);
4852
4853 num = 123;
4854 stat = pGdipBitmapGetHistogramSize(10, &num);
4855 expect(Ok, stat);
4856 expect(256, num);
4857
4858 for (i = 0; i < sizeof(test_formats)/sizeof(test_formats[0]); i++)
4859 {
4860 num = 0;
4861 stat = pGdipBitmapGetHistogramSize(test_formats[i], &num);
4862 expect(Ok, stat);
4863 expect(256, num);
4864 }
4865
4866 bm = NULL;
4867 stat = GdipCreateBitmapFromScan0(WIDTH, HEIGHT, 0, PixelFormat24bppRGB, NULL, &bm);
4868 expect(Ok, stat);
4869
4870 /* Three solid rgb rows, next three rows are rgb shades. */
4871 for (x = 0; x < WIDTH; x++)
4872 {
4873 GdipBitmapSetPixel(bm, x, 0, 0xffff0000);
4874 GdipBitmapSetPixel(bm, x, 1, 0xff00ff00);
4875 GdipBitmapSetPixel(bm, x, 2, 0xff0000ff);
4876
4877 GdipBitmapSetPixel(bm, x, 3, 0xff010000);
4878 GdipBitmapSetPixel(bm, x, 4, 0xff003f00);
4879 GdipBitmapSetPixel(bm, x, 5, 0xff000020);
4880 }
4881
4882 stat = pGdipBitmapGetHistogram(NULL, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
4883 expect(InvalidParameter, stat);
4884
4885 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, ch3);
4886 expect(InvalidParameter, stat);
4887
4888 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, ch2, NULL);
4889 expect(InvalidParameter, stat);
4890
4891 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, ch1, NULL, NULL);
4892 expect(InvalidParameter, stat);
4893
4894 stat = pGdipBitmapGetHistogram(bm, 123, 256, ch0, NULL, NULL, NULL);
4895 expect(InvalidParameter, stat);
4896
4897 /* Requested format matches bitmap format */
4898 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, ch3);
4899 expect(InvalidParameter, stat);
4900
4901 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 100, ch0, ch1, ch2, NULL);
4902 expect(InvalidParameter, stat);
4903
4904 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 257, ch0, ch1, ch2, NULL);
4905 expect(InvalidParameter, stat);
4906
4907 /* Channel 3 is not used, must be NULL */
4908 stat = pGdipBitmapGetHistogram(bm, HistogramFormatRGB, 256, ch0, ch1, ch2, NULL);
4909 expect(Ok, stat);
4910
4911 ok(ch0[0xff] == WIDTH, "Got red (0xff) %u\n", ch0[0xff]);
4912 ok(ch1[0xff] == WIDTH, "Got green (0xff) %u\n", ch1[0xff]);
4913 ok(ch2[0xff] == WIDTH, "Got blue (0xff) %u\n", ch1[0xff]);
4914 ok(ch0[0x01] == WIDTH, "Got red (0x01) %u\n", ch0[0x01]);
4915 ok(ch1[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch1[0x3f]);
4916 ok(ch2[0x20] == WIDTH, "Got blue (0x20) %u\n", ch1[0x20]);
4917
4918 /* ARGB histogram from RGB data. */
4919 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, NULL);
4920 expect(InvalidParameter, stat);
4921
4922 stat = pGdipBitmapGetHistogram(bm, HistogramFormatARGB, 256, ch0, ch1, ch2, ch3);
4923 expect(Ok, stat);
4924
4925 ok(ch1[0xff] == WIDTH, "Got red (0xff) %u\n", ch1[0xff]);
4926 ok(ch2[0xff] == WIDTH, "Got green (0xff) %u\n", ch2[0xff]);
4927 ok(ch3[0xff] == WIDTH, "Got blue (0xff) %u\n", ch3[0xff]);
4928 ok(ch1[0x01] == WIDTH, "Got red (0x01) %u\n", ch1[0x01]);
4929 ok(ch2[0x3f] == WIDTH, "Got green (0x3f) %u\n", ch2[0x3f]);
4930 ok(ch3[0x20] == WIDTH, "Got blue (0x20) %u\n", ch3[0x20]);
4931
4932 ok(ch0[0xff] == WIDTH * HEIGHT, "Got alpha (0xff) %u\n", ch0[0xff]);
4933
4934 /* Request grayscale histogram from RGB bitmap. */
4935 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, ch3);
4936 expect(InvalidParameter, stat);
4937
4938 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, ch2, NULL);
4939 expect(InvalidParameter, stat);
4940
4941 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, ch1, NULL, NULL);
4942 expect(InvalidParameter, stat);
4943
4944 stat = pGdipBitmapGetHistogram(bm, HistogramFormatGray, 256, ch0, NULL, NULL, NULL);
4945 expect(Ok, stat);
4946
4947 GdipDisposeImage((GpImage*)bm);
4948 }
4949
4950 static void test_imageabort(void)
4951 {
4952 GpStatus stat;
4953 GpBitmap *bm;
4954
4955 if (!pGdipImageSetAbort)
4956 {
4957 win_skip("GdipImageSetAbort() is not supported.\n");
4958 return;
4959 }
4960
4961 bm = NULL;
4962 stat = GdipCreateBitmapFromScan0(8, 8, 0, PixelFormat24bppRGB, NULL, &bm);
4963 expect(Ok, stat);
4964
4965 stat = pGdipImageSetAbort(NULL, NULL);
4966 expect(InvalidParameter, stat);
4967
4968 stat = pGdipImageSetAbort((GpImage*)bm, NULL);
4969 expect(Ok, stat);
4970
4971 GdipDisposeImage((GpImage*)bm);
4972 }
4973
4974 /* RGB 24 bpp 1x1 pixel PNG image */
4975 static const char png_1x1_data[] = {
4976 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a,
4977 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,0xde,
4978 0x00,0x00,0x00,0x0c,'I','D','A','T',0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,0xe7,
4979 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82
4980 };
4981
4982 static void test_png_color_formats(void)
4983 {
4984 static const struct
4985 {
4986 char bit_depth, color_type;
4987 PixelFormat format;
4988 UINT flags;
4989 } td[] =
4990 {
4991 /* 2 - PNG_COLOR_TYPE_RGB */
4992 { 8, 2, PixelFormat24bppRGB, ImageFlagsColorSpaceRGB },
4993 /* 0 - PNG_COLOR_TYPE_GRAY */
4994 { 1, 0, PixelFormat1bppIndexed, ImageFlagsColorSpaceRGB },
4995 { 2, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
4996 { 4, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
4997 { 8, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
4998 { 16, 0, PixelFormat32bppARGB, ImageFlagsColorSpaceGRAY },
4999 };
5000 BYTE buf[sizeof(png_1x1_data)];
5001 GpStatus status;
5002 GpImage *image;
5003 ImageType type;
5004 PixelFormat format;
5005 UINT flags;
5006 int i;
5007
5008 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
5009 {
5010 memcpy(buf, png_1x1_data, sizeof(png_1x1_data));
5011 buf[24] = td[i].bit_depth;
5012 buf[25] = td[i].color_type;
5013
5014 image = load_image(buf, sizeof(buf));
5015 ok(image != NULL, "%d: failed to load image data\n", i);
5016 if (!image) continue;
5017
5018 status = GdipGetImageType(image, &type);
5019 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
5020 ok(type == ImageTypeBitmap, "%d: wrong image type %d\n", i, type);
5021
5022 status = GdipGetImagePixelFormat(image, &format);
5023 expect(Ok, status);
5024 ok(format == td[i].format ||
5025 broken(td[i].bit_depth == 1 && td[i].color_type == 0 && format == PixelFormat32bppARGB), /* XP */
5026 "%d: expected %#x, got %#x\n", i, td[i].format, format);
5027
5028 status = GdipGetImageFlags(image, &flags);
5029 expect(Ok, status);
5030 ok((flags & td[i].flags) == td[i].flags ||
5031 broken(td[i].bit_depth == 1 && td[i].color_type == 0 && (flags & ImageFlagsColorSpaceGRAY)), /* XP */
5032 "%d: expected %#x, got %#x\n", i, td[i].flags, flags);
5033
5034 GdipDisposeImage(image);
5035 }
5036 }
5037
5038 static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride)
5039 {
5040 BYTE *src;
5041 UINT i, j, scale;
5042
5043 *width = 256;
5044 *height = 256;
5045 *stride = (*width * 3 + 3) & ~3;
5046 trace("width %d, height %d, stride %d\n", *width, *height, *stride);
5047
5048 src = HeapAlloc(GetProcessHeap(), 0, *stride * *height);
5049
5050 scale = 256 / *width;
5051 if (!scale) scale = 1;
5052
5053 for (i = 0; i < *height; i++)
5054 {
5055 for (j = 0; j < *width; j++)
5056 {
5057 src[i * *stride + j*3 + 0] = scale * i;
5058 src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2);
5059 src[i * *stride + j*3 + 2] = scale * j;
5060 }
5061 }
5062
5063 return src;
5064 }
5065
5066 static void test_GdipInitializePalette(void)
5067 {
5068 GpStatus status;
5069 BYTE *data;
5070 GpBitmap *bitmap;
5071 ColorPalette *palette;
5072 UINT width, height, stride;
5073
5074 pGdipInitializePalette = (void *)GetProcAddress(GetModuleHandleA("gdiplus.dll"), "GdipInitializePalette");
5075 if (!pGdipInitializePalette)
5076 {
5077 win_skip("GdipInitializePalette is not supported on this platform\n");
5078 return;
5079 }
5080
5081 data = init_bitmap(&width, &height, &stride);
5082
5083 status = GdipCreateBitmapFromScan0(width, height, stride, PixelFormat24bppRGB, data, &bitmap);
5084 expect(Ok, status);
5085
5086 palette = GdipAlloc(sizeof(*palette) + sizeof(ARGB) * 255);
5087
5088 palette->Flags = 0;
5089 palette->Count = 15;
5090 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap);
5091 expect(GenericError, status);
5092
5093 palette->Flags = 0;
5094 palette->Count = 256;
5095 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, NULL);
5096 expect(InvalidParameter, status);
5097
5098 memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5099 palette->Flags = 0;
5100 palette->Count = 256;
5101 status = pGdipInitializePalette(palette, PaletteTypeCustom, 16, FALSE, NULL);
5102 expect(Ok, status);
5103 expect(0, palette->Flags);
5104 expect(256, palette->Count);
5105 expect(0x11111111, palette->Entries[0]);
5106 expect(0x11111111, palette->Entries[128]);
5107 expect(0x11111111, palette->Entries[255]);
5108
5109 memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5110 palette->Flags = 0;
5111 palette->Count = 256;
5112 status = pGdipInitializePalette(palette, PaletteTypeFixedBW, 0, FALSE, bitmap);
5113 expect(Ok, status);
5114 todo_wine
5115 expect(0x200, palette->Flags);
5116 expect(2, palette->Count);
5117 expect(0xff000000, palette->Entries[0]);
5118 expect(0xffffffff, palette->Entries[1]);
5119
5120 memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5121 palette->Flags = 0;
5122 palette->Count = 256;
5123 status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, NULL);
5124 expect(Ok, status);
5125 todo_wine
5126 expect(0x300, palette->Flags);
5127 expect(16, palette->Count);
5128 expect(0xff000000, palette->Entries[0]);
5129 expect(0xffc0c0c0, palette->Entries[8]);
5130 expect(0xff008080, palette->Entries[15]);
5131
5132 memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5133 palette->Flags = 0;
5134 palette->Count = 256;
5135 status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone8, 1, FALSE, bitmap);
5136 expect(Ok, status);
5137 todo_wine
5138 expect(0x300, palette->Flags);
5139 expect(16, palette->Count);
5140 expect(0xff000000, palette->Entries[0]);
5141 expect(0xffc0c0c0, palette->Entries[8]);
5142 expect(0xff008080, palette->Entries[15]);
5143
5144 memset(palette->Entries, 0x11, sizeof(ARGB) * 256);
5145 palette->Flags = 0;
5146 palette->Count = 256;
5147 status = pGdipInitializePalette(palette, PaletteTypeFixedHalftone252, 1, FALSE, bitmap);
5148 expect(Ok, status);
5149 todo_wine
5150 expect(0x800, palette->Flags);
5151 expect(252, palette->Count);
5152 expect(0xff000000, palette->Entries[0]);
5153 expect(0xff990066, palette->Entries[128]);
5154 expect(0xffffffff, palette->Entries[251]);
5155
5156 palette->Flags = 0;
5157 palette->Count = 256;
5158 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 1, FALSE, bitmap);
5159 expect(InvalidParameter, status);
5160
5161 palette->Flags = 0;
5162 palette->Count = 256;
5163 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 2, FALSE, bitmap);
5164 expect(Ok, status);
5165 expect(0, palette->Flags);
5166 expect(2, palette->Count);
5167
5168 palette->Flags = 0;
5169 palette->Count = 256;
5170 status = pGdipInitializePalette(palette, PaletteTypeOptimal, 16, FALSE, bitmap);
5171 expect(Ok, status);
5172 expect(0, palette->Flags);
5173 expect(16, palette->Count);
5174
5175 /* passing invalid enumeration palette type crashes under most Windows versions */
5176
5177 GdipFree(palette);
5178 GdipDisposeImage((GpImage *)bitmap);
5179 }
5180
5181 #include "pshpack2.h"
5182 static const struct tiff_1x1_data
5183 {
5184 USHORT byte_order;
5185 USHORT version;
5186 ULONG dir_offset;
5187 USHORT number_of_entries;
5188 struct IFD_entry entry[12];
5189 ULONG next_IFD;
5190 struct IFD_rational res;
5191 short palette_data[3][256];
5192 short bps_data[4];
5193 BYTE pixel_data[32];
5194 } tiff_1x1_data =
5195 {
5196 #ifdef WORDS_BIGENDIAN
5197 'M' | 'M' << 8,
5198 #else
5199 'I' | 'I' << 8,
5200 #endif
5201 42,
5202 FIELD_OFFSET(struct tiff_1x1_data, number_of_entries),
5203 12,
5204 {
5205 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
5206 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
5207 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
5208 { 0x102, IFD_SHORT, 3, FIELD_OFFSET(struct tiff_1x1_data, bps_data) }, /* BITSPERSAMPLE */
5209 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
5210 { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
5211 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1x1_data, pixel_data) }, /* STRIPOFFSETS */
5212 { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */
5213 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) },
5214 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) },
5215 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
5216 { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_1x1_data, palette_data) } /* COLORMAP */
5217 },
5218 0,
5219 { 96, 1 },
5220 { { 0 } },
5221 { 8,8,8,0 },
5222 { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 }
5223 };
5224 #include "poppack.h"
5225
5226 static void test_tiff_color_formats(void)
5227 {
5228 static const struct
5229 {
5230 int photometric; /* PhotometricInterpretation */
5231 int samples; /* SamplesPerPixel */
5232 int bps; /* BitsPerSample */
5233 PixelFormat format;
5234 } td[] =
5235 {
5236 /* 2 - RGB */
5237 { 2, 3, 1, PixelFormat24bppRGB },
5238 { 2, 3, 4, PixelFormat24bppRGB },
5239 { 2, 3, 8, PixelFormat24bppRGB },
5240 { 2, 3, 16, PixelFormat48bppRGB },
5241 { 2, 3, 24, 0 },
5242 #if 0 /* FIXME */
5243 { 2, 3, 32, 0 },
5244 #endif
5245 { 2, 4, 1, PixelFormat32bppARGB },
5246 { 2, 4, 4, PixelFormat32bppARGB },
5247 { 2, 4, 8, PixelFormat32bppARGB },
5248 { 2, 4, 16, PixelFormat48bppRGB },
5249 { 2, 4, 24, 0 },
5250 { 2, 4, 32, 0 },
5251 /* 1 - BlackIsZero (Bilevel) */
5252 { 1, 1, 1, PixelFormat1bppIndexed },
5253 #if 0 /* FIXME: PNG vs TIFF mismatch */
5254 { 1, 1, 4, PixelFormat8bppIndexed },
5255 #endif
5256 { 1, 1, 8, PixelFormat8bppIndexed },
5257 { 1, 1, 16, PixelFormat32bppARGB },
5258 { 1, 1, 24, 0 },
5259 { 1, 1, 32, PixelFormat32bppARGB },
5260 /* 3 - Palette Color */
5261 { 3, 1, 1, PixelFormat1bppIndexed },
5262 { 3, 1, 4, PixelFormat4bppIndexed },
5263 { 3, 1, 8, PixelFormat8bppIndexed },
5264 #if 0 /* FIXME: for some reason libtiff replaces photometric 3 by 1 for bps > 8 */
5265 { 3, 1, 16, 0 },
5266 { 3, 1, 24, 0 },
5267 { 3, 1, 32, 0 },
5268 #endif
5269 /* 5 - Separated */
5270 { 5, 4, 1, 0 },
5271 { 5, 4, 4, 0 },
5272 { 5, 4, 8, PixelFormat32bppCMYK },
5273 { 5, 4, 16, PixelFormat48bppRGB },
5274 { 5, 4, 24, 0 },
5275 { 5, 4, 32, 0 },
5276 };
5277 BYTE buf[sizeof(tiff_1x1_data)];
5278 GpStatus status;
5279 GpImage *image;
5280 UINT count, i;
5281 struct IFD_entry *tag, *tag_photo = NULL, *tag_bps = NULL, *tag_samples = NULL, *tag_colormap = NULL;
5282 short *bps;
5283 ImageType type;
5284 PixelFormat format;
5285
5286 memcpy(buf, &tiff_1x1_data, sizeof(tiff_1x1_data));
5287
5288 count = *(short *)(buf + tiff_1x1_data.dir_offset);
5289 tag = (struct IFD_entry *)(buf + tiff_1x1_data.dir_offset + sizeof(short));
5290
5291 /* verify the TIFF structure */
5292 for (i = 0; i < count; i++)
5293 {
5294 if (tag[i].id == 0x102) /* BitsPerSample */
5295 tag_bps = &tag[i];
5296 else if (tag[i].id == 0x106) /* PhotometricInterpretation */
5297 tag_photo = &tag[i];
5298 else if (tag[i].id == 0x115) /* SamplesPerPixel */
5299 tag_samples = &tag[i];
5300 else if (tag[i].id == 0x140) /* ColorMap */
5301 tag_colormap = &tag[i];
5302 }
5303
5304 ok(tag_bps && tag_photo && tag_samples && tag_colormap, "tag 0x102,0x106,0x115 or 0x140 is missing\n");
5305 if (!tag_bps || !tag_photo || !tag_samples || !tag_colormap) return;
5306
5307 ok(tag_bps->type == IFD_SHORT, "tag 0x102 should have type IFD_SHORT\n");
5308 bps = (short *)(buf + tag_bps->value);
5309 ok(bps[0] == 8 && bps[1] == 8 && bps[2] == 8 && bps[3] == 0,
5310 "expected bps 8,8,8,0 got %d,%d,%d,%d\n", bps[0], bps[1], bps[2], bps[3]);
5311
5312 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
5313 {
5314 tag_colormap->count = (1 << td[i].bps) * 3;
5315 tag_photo->value = td[i].photometric;
5316 tag_bps->count = td[i].samples;
5317 tag_samples->value = td[i].samples;
5318
5319 if (td[i].samples == 1)
5320 tag_bps->value = td[i].bps;
5321 else if (td[i].samples == 2)
5322 tag_bps->value = MAKELONG(td[i].bps, td[i].bps);
5323 else if (td[i].samples == 3)
5324 {
5325 tag_bps->value = (BYTE *)bps - buf;
5326 bps[0] = bps[1] = bps[2] = td[i].bps;
5327 }
5328 else if (td[i].samples == 4)
5329 {
5330 tag_bps->value = (BYTE *)bps - buf;
5331 bps[0] = bps[1] = bps[2] = bps[3] = td[i].bps;
5332 }
5333 else
5334 {
5335 ok(0, "%u: unsupported samples count %d\n", i, td[i].samples);
5336 continue;
5337 }
5338
5339 image = load_image(buf, sizeof(buf));
5340 if (!td[i].format)
5341 ok(!image,
5342 "%u: (%d,%d,%d) TIFF image loading should have failed\n", i, td[i].photometric, td[i].samples, td[i].bps);
5343 else
5344 ok(image != NULL || broken(!image) /* XP */, "%u: failed to load TIFF image data (%d,%d,%d)\n",
5345 i, td[i].photometric, td[i].samples, td[i].bps);
5346 if (!image) continue;
5347
5348 status = GdipGetImageType(image, &type);
5349 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
5350 ok(type == ImageTypeBitmap, "%u: wrong image type %d\n", i, type);
5351
5352 status = GdipGetImagePixelFormat(image, &format);
5353 expect(Ok, status);
5354 ok(format == td[i].format,
5355 "%u: expected %#x, got %#x\n", i, td[i].format, format);
5356
5357 GdipDisposeImage(image);
5358 }
5359 }
5360
5361 START_TEST(image)
5362 {
5363 HMODULE mod = GetModuleHandleA("gdiplus.dll");
5364 struct GdiplusStartupInput gdiplusStartupInput;
5365 ULONG_PTR gdiplusToken;
5366 HMODULE hmsvcrt;
5367 int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
5368
5369 /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
5370 hmsvcrt = LoadLibraryA("msvcrt");
5371 _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
5372 if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
5373
5374 gdiplusStartupInput.GdiplusVersion = 1;
5375 gdiplusStartupInput.DebugEventCallback = NULL;
5376 gdiplusStartupInput.SuppressBackgroundThread = 0;
5377 gdiplusStartupInput.SuppressExternalCodecs = 0;
5378
5379 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
5380
5381 pGdipBitmapGetHistogramSize = (void*)GetProcAddress(mod, "GdipBitmapGetHistogramSize");
5382 pGdipBitmapGetHistogram = (void*)GetProcAddress(mod, "GdipBitmapGetHistogram");
5383 pGdipImageSetAbort = (void*)GetProcAddress(mod, "GdipImageSetAbort");
5384
5385 test_tiff_color_formats();
5386 test_GdipInitializePalette();
5387 test_png_color_formats();
5388 test_supported_encoders();
5389 test_CloneBitmapArea();
5390 test_ARGB_conversion();
5391 test_DrawImage_scale();
5392 test_image_format();
5393 test_DrawImage();
5394 test_DrawImage_SourceCopy();
5395 test_GdipDrawImagePointRect();
5396 test_bitmapbits();
5397 test_tiff_palette();
5398 test_GdipGetAllPropertyItems();
5399 test_tiff_properties();
5400 test_gif_properties();
5401 test_image_properties();
5402 test_Scan0();
5403 test_FromGdiDib();
5404 test_GetImageDimension();
5405 test_GdipImageGetFrameDimensionsCount();
5406 test_LoadingImages();
5407 test_SavingImages();
5408 test_encoders();
5409 test_LockBits();
5410 test_LockBits_UserBuf();
5411 test_GdipCreateBitmapFromHBITMAP();
5412 test_GdipGetImageFlags();
5413 test_GdipCloneImage();
5414 test_testcontrol();
5415 test_fromhicon();
5416 test_getrawformat();
5417 test_loadwmf();
5418 test_createfromwmf();
5419 test_createfromwmf_noplaceable();
5420 test_resolution();
5421 test_createhbitmap();
5422 test_getthumbnail();
5423 test_getsetpixel();
5424 test_palette();
5425 test_colormatrix();
5426 test_gamma();
5427 test_multiframegif();
5428 test_rotateflip();
5429 test_remaptable();
5430 test_colorkey();
5431 test_dispose();
5432 test_createeffect();
5433 test_getadjustedpalette();
5434 test_histogram();
5435 test_imageabort();
5436
5437 GdiplusShutdown(gdiplusToken);
5438 }