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