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