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