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