[GDIPLUS_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
[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 bmp */
1346 static const unsigned char bmpimage[66] = {
1347 0x42,0x4d,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x28,0x00,
1348 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1349 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1350 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0x00,
1351 0x00,0x00
1352 };
1353 /* 1x1 pixel jpg */
1354 static const unsigned char jpgimage[285] = {
1355 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
1356 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
1357 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
1358 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
1359 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
1360 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
1361 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
1362 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1363 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
1364 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1365 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1366 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1367 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1368 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1369 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1370 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1371 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1372 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1373 };
1374 /* 1x1 pixel tiff */
1375 static const unsigned char tiffimage[] = {
1376 0x49,0x49,0x2a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xfe,0x00,
1377 0x04,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x00,0x01,0x00,
1378 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1379 0x00,0x00,0x02,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0xd2,0x00,0x00,0x00,0x03,0x01,
1380 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x01,0x03,0x00,0x01,0x00,
1381 0x00,0x00,0x02,0x00,0x00,0x00,0x0d,0x01,0x02,0x00,0x1b,0x00,0x00,0x00,0xd8,0x00,
1382 0x00,0x00,0x11,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x12,0x01,
1383 0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x15,0x01,0x03,0x00,0x01,0x00,
1384 0x00,0x00,0x03,0x00,0x00,0x00,0x16,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x40,0x00,
1385 0x00,0x00,0x17,0x01,0x04,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1a,0x01,
1386 0x05,0x00,0x01,0x00,0x00,0x00,0xf4,0x00,0x00,0x00,0x1b,0x01,0x05,0x00,0x01,0x00,
1387 0x00,0x00,0xfc,0x00,0x00,0x00,0x1c,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
1388 0x00,0x00,0x28,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
1389 0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x2f,0x68,0x6f,0x6d,0x65,0x2f,0x6d,0x65,
1390 0x68,0x2f,0x44,0x65,0x73,0x6b,0x74,0x6f,0x70,0x2f,0x74,0x65,0x73,0x74,0x2e,0x74,
1391 0x69,0x66,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x48,
1392 0x00,0x00,0x00,0x01
1393 };
1394 /* 320x320 twip wmf */
1395 static const unsigned char wmfimage[180] = {
1396 0xd7,0xcd,0xc6,0x9a,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x01,0x40,0x01,0xa0,0x05,
1397 0x00,0x00,0x00,0x00,0xb1,0x52,0x01,0x00,0x09,0x00,0x00,0x03,0x4f,0x00,0x00,0x00,
1398 0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x0b,0x02,0x00,0x00,
1399 0x00,0x00,0x05,0x00,0x00,0x00,0x0c,0x02,0x40,0x01,0x40,0x01,0x04,0x00,0x00,0x00,
1400 0x02,0x01,0x01,0x00,0x04,0x00,0x00,0x00,0x04,0x01,0x0d,0x00,0x08,0x00,0x00,0x00,
1401 0xfa,0x02,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
1402 0x2d,0x01,0x00,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,0x01,0x00,0x00,0x00,0x00,0x00,
1403 0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x01,0x00,0x07,0x00,0x00,0x00,0xfc,0x02,
1404 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x2d,0x01,0x02,0x00,
1405 0x07,0x00,0x00,0x00,0x1b,0x04,0x40,0x01,0x40,0x01,0x00,0x00,0x00,0x00,0x04,0x00,
1406 0x00,0x00,0xf0,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0xf0,0x01,0x01,0x00,0x03,0x00,
1407 0x00,0x00,0x00,0x00
1408 };
1409 static void test_getrawformat(void)
1410 {
1411 test_bufferrawformat((void*)pngimage, sizeof(pngimage), &ImageFormatPNG, __LINE__, FALSE);
1412 test_bufferrawformat((void*)gifimage, sizeof(gifimage), &ImageFormatGIF, __LINE__, FALSE);
1413 test_bufferrawformat((void*)bmpimage, sizeof(bmpimage), &ImageFormatBMP, __LINE__, FALSE);
1414 test_bufferrawformat((void*)jpgimage, sizeof(jpgimage), &ImageFormatJPEG, __LINE__, FALSE);
1415 test_bufferrawformat((void*)tiffimage, sizeof(tiffimage), &ImageFormatTIFF, __LINE__, FALSE);
1416 test_bufferrawformat((void*)wmfimage, sizeof(wmfimage), &ImageFormatWMF, __LINE__, FALSE);
1417 }
1418
1419 static void test_loadwmf(void)
1420 {
1421 LPSTREAM stream;
1422 HGLOBAL hglob;
1423 LPBYTE data;
1424 HRESULT hres;
1425 GpStatus stat;
1426 GpImage *img;
1427 GpRectF bounds;
1428 GpUnit unit;
1429 REAL res = 12345.0;
1430 MetafileHeader header;
1431
1432 hglob = GlobalAlloc (0, sizeof(wmfimage));
1433 data = GlobalLock (hglob);
1434 memcpy(data, wmfimage, sizeof(wmfimage));
1435 GlobalUnlock(hglob); data = NULL;
1436
1437 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
1438 ok(hres == S_OK, "Failed to create a stream\n");
1439 if(hres != S_OK) return;
1440
1441 stat = GdipLoadImageFromStream(stream, &img);
1442 ok(stat == Ok, "Failed to create a Bitmap\n");
1443 if(stat != Ok){
1444 IStream_Release(stream);
1445 return;
1446 }
1447
1448 IStream_Release(stream);
1449
1450 stat = GdipGetImageBounds(img, &bounds, &unit);
1451 expect(Ok, stat);
1452 todo_wine expect(UnitPixel, unit);
1453 expectf(0.0, bounds.X);
1454 expectf(0.0, bounds.Y);
1455 todo_wine expectf(320.0, bounds.Width);
1456 todo_wine expectf(320.0, bounds.Height);
1457
1458 stat = GdipGetImageHorizontalResolution(img, &res);
1459 expect(Ok, stat);
1460 todo_wine expectf(1440.0, res);
1461
1462 stat = GdipGetImageVerticalResolution(img, &res);
1463 expect(Ok, stat);
1464 todo_wine expectf(1440.0, res);
1465
1466 memset(&header, 0, sizeof(header));
1467 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1468 expect(Ok, stat);
1469 if (stat == Ok)
1470 {
1471 todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1472 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1473 todo_wine expect(0x300, header.Version);
1474 expect(0, header.EmfPlusFlags);
1475 todo_wine expectf(1440.0, header.DpiX);
1476 todo_wine expectf(1440.0, header.DpiY);
1477 expect(0, header.X);
1478 expect(0, header.Y);
1479 todo_wine expect(320, header.Width);
1480 todo_wine expect(320, header.Height);
1481 todo_wine expect(1, U(header).WmfHeader.mtType);
1482 expect(0, header.EmfPlusHeaderSize);
1483 expect(0, header.LogicalDpiX);
1484 expect(0, header.LogicalDpiY);
1485 }
1486
1487 GdipDisposeImage(img);
1488 }
1489
1490 static void test_createfromwmf(void)
1491 {
1492 HMETAFILE hwmf;
1493 GpImage *img;
1494 GpStatus stat;
1495 GpRectF bounds;
1496 GpUnit unit;
1497 REAL res = 12345.0;
1498 MetafileHeader header;
1499
1500 hwmf = SetMetaFileBitsEx(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader),
1501 wmfimage+sizeof(WmfPlaceableFileHeader));
1502 ok(hwmf != 0, "SetMetaFileBitsEx failed\n");
1503
1504 stat = GdipCreateMetafileFromWmf(hwmf, TRUE,
1505 (WmfPlaceableFileHeader*)wmfimage, (GpMetafile**)&img);
1506 expect(Ok, stat);
1507 if (stat != Ok) return; // ReactOS
1508
1509 stat = GdipGetImageBounds(img, &bounds, &unit);
1510 expect(Ok, stat);
1511 expect(UnitPixel, unit);
1512 expectf(0.0, bounds.X);
1513 expectf(0.0, bounds.Y);
1514 expectf(320.0, bounds.Width);
1515 expectf(320.0, bounds.Height);
1516
1517 stat = GdipGetImageHorizontalResolution(img, &res);
1518 expect(Ok, stat);
1519 expectf(1440.0, res);
1520
1521 stat = GdipGetImageVerticalResolution(img, &res);
1522 expect(Ok, stat);
1523 expectf(1440.0, res);
1524
1525 memset(&header, 0, sizeof(header));
1526 stat = GdipGetMetafileHeaderFromMetafile((GpMetafile*)img, &header);
1527 expect(Ok, stat);
1528 if (stat == Ok)
1529 {
1530 todo_wine expect(MetafileTypeWmfPlaceable, header.Type);
1531 todo_wine expect(sizeof(wmfimage)-sizeof(WmfPlaceableFileHeader), header.Size);
1532 todo_wine expect(0x300, header.Version);
1533 expect(0, header.EmfPlusFlags);
1534 todo_wine expectf(1440.0, header.DpiX);
1535 todo_wine expectf(1440.0, header.DpiY);
1536 expect(0, header.X);
1537 expect(0, header.Y);
1538 todo_wine expect(320, header.Width);
1539 todo_wine expect(320, header.Height);
1540 todo_wine expect(1, U(header).WmfHeader.mtType);
1541 expect(0, header.EmfPlusHeaderSize);
1542 expect(0, header.LogicalDpiX);
1543 expect(0, header.LogicalDpiY);
1544 }
1545
1546 GdipDisposeImage(img);
1547 }
1548
1549 static void test_resolution(void)
1550 {
1551 GpStatus stat;
1552 GpBitmap *bitmap;
1553 GpGraphics *graphics;
1554 REAL res=-1.0;
1555 HDC screendc;
1556 int screenxres, screenyres;
1557
1558 /* create Bitmap */
1559 stat = GdipCreateBitmapFromScan0(1, 1, 32, PixelFormat24bppRGB, NULL, &bitmap);
1560 expect(Ok, stat);
1561
1562 /* test invalid values */
1563 stat = GdipGetImageHorizontalResolution(NULL, &res);
1564 expect(InvalidParameter, stat);
1565
1566 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, NULL);
1567 expect(InvalidParameter, stat);
1568
1569 stat = GdipGetImageVerticalResolution(NULL, &res);
1570 expect(InvalidParameter, stat);
1571
1572 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, NULL);
1573 expect(InvalidParameter, stat);
1574
1575 stat = GdipBitmapSetResolution(NULL, 96.0, 96.0);
1576 expect(InvalidParameter, stat);
1577
1578 stat = GdipBitmapSetResolution(bitmap, 0.0, 0.0);
1579 expect(InvalidParameter, stat);
1580
1581 /* defaults to screen resolution */
1582 screendc = GetDC(0);
1583
1584 screenxres = GetDeviceCaps(screendc, LOGPIXELSX);
1585 screenyres = GetDeviceCaps(screendc, LOGPIXELSY);
1586
1587 ReleaseDC(0, screendc);
1588
1589 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1590 expect(Ok, stat);
1591 expectf((REAL)screenxres, res);
1592
1593 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1594 expect(Ok, stat);
1595 expectf((REAL)screenyres, res);
1596
1597 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1598 expect(Ok, stat);
1599 stat = GdipGetDpiX(graphics, &res);
1600 expect(Ok, stat);
1601 expectf((REAL)screenxres, res);
1602 stat = GdipGetDpiY(graphics, &res);
1603 expect(Ok, stat);
1604 expectf((REAL)screenyres, res);
1605
1606 /* test changing the resolution */
1607 stat = GdipBitmapSetResolution(bitmap, screenxres*2.0, screenyres*3.0);
1608 expect(Ok, stat);
1609
1610 stat = GdipGetImageHorizontalResolution((GpImage*)bitmap, &res);
1611 expect(Ok, stat);
1612 expectf(screenxres*2.0, res);
1613
1614 stat = GdipGetImageVerticalResolution((GpImage*)bitmap, &res);
1615 expect(Ok, stat);
1616 expectf(screenyres*3.0, res);
1617
1618 stat = GdipGetDpiX(graphics, &res);
1619 expect(Ok, stat);
1620 expectf((REAL)screenxres, res);
1621 stat = GdipGetDpiY(graphics, &res);
1622 expect(Ok, stat);
1623 expectf((REAL)screenyres, res);
1624
1625 stat = GdipDeleteGraphics(graphics);
1626 expect(Ok, stat);
1627
1628 stat = GdipGetImageGraphicsContext((GpImage*)bitmap, &graphics);
1629 expect(Ok, stat);
1630 stat = GdipGetDpiX(graphics, &res);
1631 expect(Ok, stat);
1632 expectf(screenxres*2.0, res);
1633 stat = GdipGetDpiY(graphics, &res);
1634 expect(Ok, stat);
1635 expectf(screenyres*3.0, res);
1636 stat = GdipDeleteGraphics(graphics);
1637 expect(Ok, stat);
1638
1639 stat = GdipDisposeImage((GpImage*)bitmap);
1640 expect(Ok, stat);
1641 }
1642
1643 static void test_createhbitmap(void)
1644 {
1645 GpStatus stat;
1646 GpBitmap *bitmap;
1647 HBITMAP hbitmap, oldhbitmap;
1648 BITMAP bm;
1649 int ret;
1650 HDC hdc;
1651 COLORREF pixel;
1652 BYTE bits[640];
1653
1654 memset(bits, 0x68, 640);
1655
1656 /* create Bitmap */
1657 stat = GdipCreateBitmapFromScan0(10, 20, 32, PixelFormat24bppRGB, bits, &bitmap);
1658 expect(Ok, stat);
1659
1660 /* test NULL values */
1661 stat = GdipCreateHBITMAPFromBitmap(NULL, &hbitmap, 0);
1662 expect(InvalidParameter, stat);
1663
1664 stat = GdipCreateHBITMAPFromBitmap(bitmap, NULL, 0);
1665 expect(InvalidParameter, stat);
1666
1667 /* create HBITMAP */
1668 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1669 expect(Ok, stat);
1670
1671 if (stat == Ok)
1672 {
1673 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1674 expect(sizeof(BITMAP), ret);
1675
1676 expect(0, bm.bmType);
1677 expect(10, bm.bmWidth);
1678 expect(20, bm.bmHeight);
1679 expect(40, bm.bmWidthBytes);
1680 expect(1, bm.bmPlanes);
1681 expect(32, bm.bmBitsPixel);
1682 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1683
1684 if (bm.bmBits)
1685 {
1686 DWORD val = *(DWORD*)bm.bmBits;
1687 ok(val == 0xff686868, "got %x, expected 0xff686868\n", val);
1688 }
1689
1690 hdc = CreateCompatibleDC(NULL);
1691
1692 oldhbitmap = SelectObject(hdc, hbitmap);
1693 pixel = GetPixel(hdc, 5, 5);
1694 SelectObject(hdc, oldhbitmap);
1695
1696 DeleteDC(hdc);
1697
1698 expect(0x686868, pixel);
1699
1700 DeleteObject(hbitmap);
1701 }
1702
1703 stat = GdipDisposeImage((GpImage*)bitmap);
1704 expect(Ok, stat);
1705
1706 /* make (1,0) have no alpha and (2,0) a different blue value. */
1707 bits[7] = 0x00;
1708 bits[8] = 0x40;
1709
1710 /* create alpha Bitmap */
1711 stat = GdipCreateBitmapFromScan0(8, 20, 32, PixelFormat32bppARGB, bits, &bitmap);
1712 expect(Ok, stat);
1713
1714 /* create HBITMAP */
1715 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
1716 expect(Ok, stat);
1717
1718 if (stat == Ok)
1719 {
1720 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1721 expect(sizeof(BITMAP), ret);
1722
1723 expect(0, bm.bmType);
1724 expect(8, bm.bmWidth);
1725 expect(20, bm.bmHeight);
1726 expect(32, bm.bmWidthBytes);
1727 expect(1, bm.bmPlanes);
1728 expect(32, bm.bmBitsPixel);
1729 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1730
1731 if (bm.bmBits)
1732 {
1733 DWORD val = *(DWORD*)bm.bmBits;
1734 ok(val == 0x682a2a2a, "got %x, expected 0x682a2a2a\n", val);
1735 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1736 ok(val == 0x0, "got %x, expected 0x682a2a2a\n", val);
1737 }
1738
1739 hdc = CreateCompatibleDC(NULL);
1740
1741 oldhbitmap = SelectObject(hdc, hbitmap);
1742 pixel = GetPixel(hdc, 5, 5);
1743 expect(0x2a2a2a, pixel);
1744 pixel = GetPixel(hdc, 1, 0);
1745 expect(0x0, pixel);
1746
1747 SelectObject(hdc, oldhbitmap);
1748
1749 DeleteDC(hdc);
1750
1751
1752 DeleteObject(hbitmap);
1753 }
1754
1755 /* create HBITMAP with bkgnd colour */
1756 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0xff00ff);
1757 expect(Ok, stat);
1758
1759 if (stat == Ok)
1760 {
1761 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1762 expect(sizeof(BITMAP), ret);
1763
1764 expect(0, bm.bmType);
1765 expect(8, bm.bmWidth);
1766 expect(20, bm.bmHeight);
1767 expect(32, bm.bmWidthBytes);
1768 expect(1, bm.bmPlanes);
1769 expect(32, bm.bmBitsPixel);
1770 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1771
1772 if (bm.bmBits)
1773 {
1774 DWORD val = *(DWORD*)bm.bmBits;
1775 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1776 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1777 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1778 }
1779
1780 hdc = CreateCompatibleDC(NULL);
1781
1782 oldhbitmap = SelectObject(hdc, hbitmap);
1783 pixel = GetPixel(hdc, 5, 5);
1784 expect(0xc12ac1, pixel);
1785 pixel = GetPixel(hdc, 1, 0);
1786 expect(0xff00ff, pixel);
1787 pixel = GetPixel(hdc, 2, 0);
1788 expect(0xb12ac1, pixel);
1789
1790 SelectObject(hdc, oldhbitmap);
1791 DeleteDC(hdc);
1792 DeleteObject(hbitmap);
1793 }
1794
1795 /* create HBITMAP with bkgnd colour with alpha and show it behaves with no alpha. */
1796 stat = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0x80ff00ff);
1797 expect(Ok, stat);
1798
1799 if (stat == Ok)
1800 {
1801 ret = GetObjectA(hbitmap, sizeof(BITMAP), &bm);
1802 expect(sizeof(BITMAP), ret);
1803
1804 expect(0, bm.bmType);
1805 expect(8, bm.bmWidth);
1806 expect(20, bm.bmHeight);
1807 expect(32, bm.bmWidthBytes);
1808 expect(1, bm.bmPlanes);
1809 expect(32, bm.bmBitsPixel);
1810 ok(bm.bmBits != NULL, "got DDB, expected DIB\n");
1811
1812 if (bm.bmBits)
1813 {
1814 DWORD val = *(DWORD*)bm.bmBits;
1815 ok(val == 0x68c12ac1, "got %x, expected 0x682a2a2a\n", val);
1816 val = *((DWORD*)bm.bmBits + (bm.bmHeight-1) * bm.bmWidthBytes/4 + 1);
1817 ok(val == 0xff00ff, "got %x, expected 0x682a2a2a\n", val);
1818 }
1819
1820 hdc = CreateCompatibleDC(NULL);
1821
1822 oldhbitmap = SelectObject(hdc, hbitmap);
1823 pixel = GetPixel(hdc, 5, 5);
1824 expect(0xc12ac1, pixel);
1825 pixel = GetPixel(hdc, 1, 0);
1826 expect(0xff00ff, pixel);
1827 pixel = GetPixel(hdc, 2, 0);
1828 expect(0xb12ac1, pixel);
1829
1830 SelectObject(hdc, oldhbitmap);
1831 DeleteDC(hdc);
1832 DeleteObject(hbitmap);
1833 }
1834
1835 stat = GdipDisposeImage((GpImage*)bitmap);
1836 expect(Ok, stat);
1837 }
1838
1839 static void test_getthumbnail(void)
1840 {
1841 GpStatus stat;
1842 GpImage *bitmap1, *bitmap2;
1843 UINT width, height;
1844
1845 stat = GdipGetImageThumbnail(NULL, 0, 0, &bitmap2, NULL, NULL);
1846 expect(InvalidParameter, stat);
1847
1848 stat = GdipCreateBitmapFromScan0(128, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1849 expect(Ok, stat);
1850
1851 stat = GdipGetImageThumbnail(bitmap1, 0, 0, NULL, NULL, NULL);
1852 expect(InvalidParameter, stat);
1853
1854 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1855 expect(Ok, stat);
1856
1857 if (stat == Ok)
1858 {
1859 stat = GdipGetImageWidth(bitmap2, &width);
1860 expect(Ok, stat);
1861 expect(120, width);
1862
1863 stat = GdipGetImageHeight(bitmap2, &height);
1864 expect(Ok, stat);
1865 expect(120, height);
1866
1867 GdipDisposeImage(bitmap2);
1868 }
1869
1870 GdipDisposeImage(bitmap1);
1871
1872
1873 stat = GdipCreateBitmapFromScan0(64, 128, 0, PixelFormat32bppRGB, NULL, (GpBitmap**)&bitmap1);
1874 expect(Ok, stat);
1875
1876 stat = GdipGetImageThumbnail(bitmap1, 32, 32, &bitmap2, NULL, NULL);
1877 expect(Ok, stat);
1878
1879 if (stat == Ok)
1880 {
1881 stat = GdipGetImageWidth(bitmap2, &width);
1882 expect(Ok, stat);
1883 expect(32, width);
1884
1885 stat = GdipGetImageHeight(bitmap2, &height);
1886 expect(Ok, stat);
1887 expect(32, height);
1888
1889 GdipDisposeImage(bitmap2);
1890 }
1891
1892 stat = GdipGetImageThumbnail(bitmap1, 0, 0, &bitmap2, NULL, NULL);
1893 expect(Ok, stat);
1894
1895 if (stat == Ok)
1896 {
1897 stat = GdipGetImageWidth(bitmap2, &width);
1898 expect(Ok, stat);
1899 expect(120, width);
1900
1901 stat = GdipGetImageHeight(bitmap2, &height);
1902 expect(Ok, stat);
1903 expect(120, height);
1904
1905 GdipDisposeImage(bitmap2);
1906 }
1907
1908 GdipDisposeImage(bitmap1);
1909 }
1910
1911 static void test_getsetpixel(void)
1912 {
1913 GpStatus stat;
1914 GpBitmap *bitmap;
1915 ARGB color;
1916 BYTE bits[16] = {0x00,0x00,0x00,0x00, 0x00,0xff,0xff,0x00,
1917 0xff,0x00,0x00,0x00, 0xff,0xff,0xff,0x00};
1918
1919 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, bits, &bitmap);
1920 expect(Ok, stat);
1921
1922 /* null parameters */
1923 stat = GdipBitmapGetPixel(NULL, 1, 1, &color);
1924 expect(InvalidParameter, stat);
1925
1926 stat = GdipBitmapGetPixel(bitmap, 1, 1, NULL);
1927 expect(InvalidParameter, stat);
1928
1929 stat = GdipBitmapSetPixel(NULL, 1, 1, 0);
1930 expect(InvalidParameter, stat);
1931
1932 /* out of bounds */
1933 stat = GdipBitmapGetPixel(bitmap, -1, 1, &color);
1934 expect(InvalidParameter, stat);
1935
1936 stat = GdipBitmapSetPixel(bitmap, -1, 1, 0);
1937 expect(InvalidParameter, stat);
1938
1939 stat = GdipBitmapGetPixel(bitmap, 1, -1, &color);
1940 ok(stat == InvalidParameter ||
1941 broken(stat == Ok), /* Older gdiplus */
1942 "Expected InvalidParameter, got %.8x\n", stat);
1943
1944 if (0) /* crashes some gdiplus implementations */
1945 {
1946 stat = GdipBitmapSetPixel(bitmap, 1, -1, 0);
1947 ok(stat == InvalidParameter ||
1948 broken(stat == Ok), /* Older gdiplus */
1949 "Expected InvalidParameter, got %.8x\n", stat);
1950 }
1951
1952 stat = GdipBitmapGetPixel(bitmap, 2, 1, &color);
1953 expect(InvalidParameter, stat);
1954
1955 stat = GdipBitmapSetPixel(bitmap, 2, 1, 0);
1956 expect(InvalidParameter, stat);
1957
1958 stat = GdipBitmapGetPixel(bitmap, 1, 2, &color);
1959 expect(InvalidParameter, stat);
1960
1961 stat = GdipBitmapSetPixel(bitmap, 1, 2, 0);
1962 expect(InvalidParameter, stat);
1963
1964 /* valid use */
1965 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1966 expect(Ok, stat);
1967 expect(0xffffffff, color);
1968
1969 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
1970 expect(Ok, stat);
1971 expect(0xff0000ff, color);
1972
1973 stat = GdipBitmapSetPixel(bitmap, 1, 1, 0xff676869);
1974 expect(Ok, stat);
1975
1976 stat = GdipBitmapSetPixel(bitmap, 0, 0, 0xff474849);
1977 expect(Ok, stat);
1978
1979 stat = GdipBitmapGetPixel(bitmap, 1, 1, &color);
1980 expect(Ok, stat);
1981 expect(0xff676869, color);
1982
1983 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
1984 expect(Ok, stat);
1985 expect(0xff474849, color);
1986
1987 stat = GdipDisposeImage((GpImage*)bitmap);
1988 expect(Ok, stat);
1989 }
1990
1991 static void check_halftone_palette(ColorPalette *palette)
1992 {
1993 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1994 UINT i;
1995
1996 for (i=0; i<palette->Count; i++)
1997 {
1998 ARGB expected=0xff000000;
1999 if (i<8)
2000 {
2001 if (i&1) expected |= 0x800000;
2002 if (i&2) expected |= 0x8000;
2003 if (i&4) expected |= 0x80;
2004 }
2005 else if (i == 8)
2006 {
2007 expected = 0xffc0c0c0;
2008 }
2009 else if (i < 16)
2010 {
2011 if (i&1) expected |= 0xff0000;
2012 if (i&2) expected |= 0xff00;
2013 if (i&4) expected |= 0xff;
2014 }
2015 else if (i < 40)
2016 {
2017 expected = 0x00000000;
2018 }
2019 else
2020 {
2021 expected |= halftone_values[(i-40)%6];
2022 expected |= halftone_values[((i-40)/6)%6] << 8;
2023 expected |= halftone_values[((i-40)/36)%6] << 16;
2024 }
2025 ok(expected == palette->Entries[i], "Expected %.8x, got %.8x, i=%u/%u\n",
2026 expected, palette->Entries[i], i, palette->Count);
2027 }
2028 }
2029
2030 static void test_palette(void)
2031 {
2032 GpStatus stat;
2033 GpBitmap *bitmap;
2034 INT size;
2035 BYTE buffer[1040];
2036 ColorPalette *palette=(ColorPalette*)buffer;
2037 ARGB *entries = palette->Entries;
2038 ARGB color=0;
2039
2040 /* test initial palette from non-indexed bitmap */
2041 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat32bppRGB, NULL, &bitmap);
2042 expect(Ok, stat);
2043
2044 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2045 expect(Ok, stat);
2046 expect(sizeof(UINT)*2+sizeof(ARGB), size);
2047
2048 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2049 expect(Ok, stat);
2050 expect(0, palette->Count);
2051
2052 /* test setting palette on not-indexed bitmap */
2053 palette->Count = 3;
2054
2055 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2056 expect(Ok, stat);
2057
2058 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2059 expect(Ok, stat);
2060 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2061
2062 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2063 expect(Ok, stat);
2064 expect(3, palette->Count);
2065
2066 GdipDisposeImage((GpImage*)bitmap);
2067
2068 /* test initial palette on 1-bit bitmap */
2069 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat1bppIndexed, NULL, &bitmap);
2070 expect(Ok, stat);
2071
2072 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2073 expect(Ok, stat);
2074 expect(sizeof(UINT)*2+sizeof(ARGB)*2, size);
2075
2076 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2077 expect(Ok, stat);
2078 expect(PaletteFlagsGrayScale, palette->Flags);
2079 expect(2, palette->Count);
2080
2081 expect(0xff000000, entries[0]);
2082 expect(0xffffffff, entries[1]);
2083
2084 /* test getting/setting pixels */
2085 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2086 expect(Ok, stat);
2087 expect(0xff000000, color);
2088
2089 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffffffff);
2090 ok((stat == Ok) ||
2091 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2092
2093 if (stat == Ok)
2094 {
2095 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2096 expect(Ok, stat);
2097 expect(0xffffffff, color);
2098 }
2099
2100 GdipDisposeImage((GpImage*)bitmap);
2101
2102 /* test initial palette on 4-bit bitmap */
2103 stat = GdipCreateBitmapFromScan0(2, 2, 4, PixelFormat4bppIndexed, NULL, &bitmap);
2104 expect(Ok, stat);
2105
2106 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2107 expect(Ok, stat);
2108 expect(sizeof(UINT)*2+sizeof(ARGB)*16, size);
2109
2110 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2111 expect(Ok, stat);
2112 expect(0, palette->Flags);
2113 expect(16, palette->Count);
2114
2115 check_halftone_palette(palette);
2116
2117 /* test getting/setting pixels */
2118 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2119 expect(Ok, stat);
2120 expect(0xff000000, color);
2121
2122 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffff00ff);
2123 ok((stat == Ok) ||
2124 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2125
2126 if (stat == Ok)
2127 {
2128 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2129 expect(Ok, stat);
2130 expect(0xffff00ff, color);
2131 }
2132
2133 GdipDisposeImage((GpImage*)bitmap);
2134
2135 /* test initial palette on 8-bit bitmap */
2136 stat = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat8bppIndexed, NULL, &bitmap);
2137 expect(Ok, stat);
2138
2139 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2140 expect(Ok, stat);
2141 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2142
2143 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2144 expect(Ok, stat);
2145 expect(PaletteFlagsHalftone, palette->Flags);
2146 expect(256, palette->Count);
2147
2148 check_halftone_palette(palette);
2149
2150 /* test getting/setting pixels */
2151 stat = GdipBitmapGetPixel(bitmap, 0, 0, &color);
2152 expect(Ok, stat);
2153 expect(0xff000000, color);
2154
2155 stat = GdipBitmapSetPixel(bitmap, 0, 1, 0xffcccccc);
2156 ok((stat == Ok) ||
2157 broken(stat == InvalidParameter) /* pre-win7 */, "stat=%.8x\n", stat);
2158
2159 if (stat == Ok)
2160 {
2161 stat = GdipBitmapGetPixel(bitmap, 0, 1, &color);
2162 expect(Ok, stat);
2163 expect(0xffcccccc, color);
2164 }
2165
2166 /* test setting/getting a different palette */
2167 entries[1] = 0xffcccccc;
2168
2169 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2170 expect(Ok, stat);
2171
2172 entries[1] = 0;
2173
2174 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2175 expect(Ok, stat);
2176 expect(sizeof(UINT)*2+sizeof(ARGB)*256, size);
2177
2178 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2179 expect(Ok, stat);
2180 expect(PaletteFlagsHalftone, palette->Flags);
2181 expect(256, palette->Count);
2182 expect(0xffcccccc, entries[1]);
2183
2184 /* test count < 256 */
2185 palette->Flags = 12345;
2186 palette->Count = 3;
2187
2188 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2189 expect(Ok, stat);
2190
2191 entries[1] = 0;
2192 entries[3] = 0xdeadbeef;
2193
2194 stat = GdipGetImagePaletteSize((GpImage*)bitmap, &size);
2195 expect(Ok, stat);
2196 expect(sizeof(UINT)*2+sizeof(ARGB)*3, size);
2197
2198 stat = GdipGetImagePalette((GpImage*)bitmap, palette, size);
2199 expect(Ok, stat);
2200 expect(12345, palette->Flags);
2201 expect(3, palette->Count);
2202 expect(0xffcccccc, entries[1]);
2203 expect(0xdeadbeef, entries[3]);
2204
2205 /* test count > 256 */
2206 palette->Count = 257;
2207
2208 stat = GdipSetImagePalette((GpImage*)bitmap, palette);
2209 ok(stat == InvalidParameter ||
2210 broken(stat == Ok), /* Old gdiplus behavior */
2211 "Expected %.8x, got %.8x\n", InvalidParameter, stat);
2212
2213 GdipDisposeImage((GpImage*)bitmap);
2214 }
2215
2216 static void test_colormatrix(void)
2217 {
2218 GpStatus stat;
2219 ColorMatrix colormatrix, graymatrix;
2220 GpImageAttributes *imageattr;
2221 const ColorMatrix identity = {{
2222 {1.0,0.0,0.0,0.0,0.0},
2223 {0.0,1.0,0.0,0.0,0.0},
2224 {0.0,0.0,1.0,0.0,0.0},
2225 {0.0,0.0,0.0,1.0,0.0},
2226 {0.0,0.0,0.0,0.0,1.0}}};
2227 const ColorMatrix double_red = {{
2228 {2.0,0.0,0.0,0.0,0.0},
2229 {0.0,1.0,0.0,0.0,0.0},
2230 {0.0,0.0,1.0,0.0,0.0},
2231 {0.0,0.0,0.0,1.0,0.0},
2232 {0.0,0.0,0.0,0.0,1.0}}};
2233 const ColorMatrix asymmetric = {{
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 {1.0,0.0,0.0,0.0,0.0},
2238 {0.0,0.0,0.0,0.0,1.0}}};
2239 GpBitmap *bitmap1, *bitmap2;
2240 GpGraphics *graphics;
2241 ARGB color;
2242
2243 colormatrix = identity;
2244 graymatrix = identity;
2245
2246 stat = GdipSetImageAttributesColorMatrix(NULL, ColorAdjustTypeDefault,
2247 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2248 expect(InvalidParameter, stat);
2249
2250 stat = GdipCreateImageAttributes(&imageattr);
2251 expect(Ok, stat);
2252
2253 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2254 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2255 expect(Ok, stat);
2256
2257 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2258 TRUE, NULL, NULL, ColorMatrixFlagsDefault);
2259 expect(InvalidParameter, stat);
2260
2261 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2262 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2263 expect(Ok, stat);
2264
2265 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2266 TRUE, &colormatrix, NULL, ColorMatrixFlagsSkipGrays);
2267 expect(Ok, stat);
2268
2269 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2270 TRUE, &colormatrix, NULL, ColorMatrixFlagsAltGray);
2271 expect(InvalidParameter, stat);
2272
2273 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2274 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsAltGray);
2275 expect(Ok, stat);
2276
2277 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2278 TRUE, &colormatrix, &graymatrix, 3);
2279 expect(InvalidParameter, stat);
2280
2281 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeCount,
2282 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2283 expect(InvalidParameter, stat);
2284
2285 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeAny,
2286 TRUE, &colormatrix, &graymatrix, ColorMatrixFlagsDefault);
2287 expect(InvalidParameter, stat);
2288
2289 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2290 FALSE, NULL, NULL, ColorMatrixFlagsDefault);
2291 expect(Ok, stat);
2292
2293 /* Drawing a bitmap transforms the colors */
2294 colormatrix = double_red;
2295 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2296 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2297 expect(Ok, stat);
2298
2299 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2300 expect(Ok, stat);
2301
2302 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2303 expect(Ok, stat);
2304
2305 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff40ccee);
2306 expect(Ok, stat);
2307
2308 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2309 expect(Ok, stat);
2310
2311 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2312 UnitPixel, imageattr, NULL, NULL);
2313 expect(Ok, stat);
2314
2315 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2316 expect(Ok, stat);
2317 expect(0xff80ccee, color);
2318
2319 colormatrix = asymmetric;
2320 stat = GdipSetImageAttributesColorMatrix(imageattr, ColorAdjustTypeDefault,
2321 TRUE, &colormatrix, NULL, ColorMatrixFlagsDefault);
2322 expect(Ok, stat);
2323
2324 stat = GdipBitmapSetPixel(bitmap2, 0, 0, 0);
2325 expect(Ok, stat);
2326
2327 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2328 UnitPixel, imageattr, NULL, NULL);
2329 expect(Ok, stat);
2330
2331 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2332 expect(Ok, stat);
2333 ok(color_match(0xeeff40cc, color, 3), "expected 0xeeff40cc, got 0x%08x\n", color);
2334
2335 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2336 expect(Ok, stat);
2337
2338 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2339 UnitPixel, imageattr, NULL, NULL);
2340 expect(Ok, stat);
2341
2342 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2343 expect(Ok, stat);
2344 ok(color_match(0xff40ccee, color, 1), "Expected ff40ccee, got %.8x\n", color);
2345
2346 GdipDeleteGraphics(graphics);
2347 GdipDisposeImage((GpImage*)bitmap1);
2348 GdipDisposeImage((GpImage*)bitmap2);
2349 GdipDisposeImageAttributes(imageattr);
2350 }
2351
2352 static void test_gamma(void)
2353 {
2354 GpStatus stat;
2355 GpImageAttributes *imageattr;
2356 GpBitmap *bitmap1, *bitmap2;
2357 GpGraphics *graphics;
2358 ARGB color;
2359
2360 stat = GdipSetImageAttributesGamma(NULL, ColorAdjustTypeDefault, TRUE, 1.0);
2361 expect(InvalidParameter, stat);
2362
2363 stat = GdipCreateImageAttributes(&imageattr);
2364 expect(Ok, stat);
2365
2366 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 1.0);
2367 expect(Ok, stat);
2368
2369 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeAny, TRUE, 1.0);
2370 expect(InvalidParameter, stat);
2371
2372 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, -1.0);
2373 expect(InvalidParameter, stat);
2374
2375 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.0);
2376 expect(InvalidParameter, stat);
2377
2378 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 0.5);
2379 expect(Ok, stat);
2380
2381 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, FALSE, 0.0);
2382 expect(Ok, stat);
2383
2384 /* Drawing a bitmap transforms the colors */
2385 stat = GdipSetImageAttributesGamma(imageattr, ColorAdjustTypeDefault, TRUE, 3.0);
2386 expect(Ok, stat);
2387
2388 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2389 expect(Ok, stat);
2390
2391 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2392 expect(Ok, stat);
2393
2394 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff80ffff);
2395 expect(Ok, stat);
2396
2397 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2398 expect(Ok, stat);
2399
2400 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2401 UnitPixel, imageattr, NULL, NULL);
2402 expect(Ok, stat);
2403
2404 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2405 expect(Ok, stat);
2406 ok(color_match(0xff20ffff, color, 1), "Expected ff20ffff, got %.8x\n", color);
2407
2408 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2409 expect(Ok, stat);
2410
2411 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2412 UnitPixel, imageattr, NULL, NULL);
2413 expect(Ok, stat);
2414
2415 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2416 expect(Ok, stat);
2417 ok(color_match(0xff80ffff, color, 1), "Expected ff80ffff, got %.8x\n", color);
2418
2419 GdipDeleteGraphics(graphics);
2420 GdipDisposeImage((GpImage*)bitmap1);
2421 GdipDisposeImage((GpImage*)bitmap2);
2422 GdipDisposeImageAttributes(imageattr);
2423 }
2424
2425 /* 1x1 pixel gif, 2 frames; first frame is white, second is black */
2426 static const unsigned char gifanimation[72] = {
2427 0x47,0x49,0x46,0x38,0x39,0x61,0x01,0x00,0x01,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
2428 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x00,0x0a,0x00,0xff,
2429 0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x4c,0x01,0x00,
2430 0x21,0xf9,0x04,0x01,0x0a,0x00,0x01,0x00,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,
2431 0x00,0x00,0x02,0x02,0x44,0x01,0x00,0x3b
2432 };
2433
2434 static void test_multiframegif(void)
2435 {
2436 LPSTREAM stream;
2437 HGLOBAL hglob;
2438 LPBYTE data;
2439 HRESULT hres;
2440 GpStatus stat;
2441 GpBitmap *bmp;
2442 ARGB color;
2443 UINT count;
2444 GUID dimension;
2445
2446 /* Test frame functions with an animated GIF */
2447 hglob = GlobalAlloc (0, sizeof(gifanimation));
2448 data = GlobalLock (hglob);
2449 memcpy(data, gifanimation, sizeof(gifanimation));
2450 GlobalUnlock(hglob);
2451
2452 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2453 ok(hres == S_OK, "Failed to create a stream\n");
2454 if(hres != S_OK) return;
2455
2456 stat = GdipCreateBitmapFromStream(stream, &bmp);
2457 ok(stat == Ok, "Failed to create a Bitmap\n");
2458 if(stat != Ok){
2459 IStream_Release(stream);
2460 return;
2461 }
2462
2463 /* Bitmap starts at frame 0 */
2464 color = 0xdeadbeef;
2465 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2466 expect(Ok, stat);
2467 expect(0xffffffff, color);
2468
2469 /* Check that we get correct metadata */
2470 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2471 expect(Ok, stat);
2472 expect(1, count);
2473
2474 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2475 expect(Ok, stat);
2476 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2477
2478 count = 12345;
2479 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2480 expect(Ok, stat);
2481 expect(2, count);
2482
2483 /* SelectActiveFrame overwrites our current data */
2484 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2485 expect(Ok, stat);
2486
2487 color = 0xdeadbeef;
2488 GdipBitmapGetPixel(bmp, 0, 0, &color);
2489 expect(Ok, stat);
2490 expect(0xff000000, color);
2491
2492 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2493 expect(Ok, stat);
2494
2495 color = 0xdeadbeef;
2496 GdipBitmapGetPixel(bmp, 0, 0, &color);
2497 expect(Ok, stat);
2498 expect(0xffffffff, color);
2499
2500 /* Write over the image data */
2501 stat = GdipBitmapSetPixel(bmp, 0, 0, 0xff000000);
2502 expect(Ok, stat);
2503
2504 /* Switching to the same frame does not overwrite our changes */
2505 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2506 expect(Ok, stat);
2507
2508 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2509 expect(Ok, stat);
2510 expect(0xff000000, color);
2511
2512 /* But switching to another frame and back does */
2513 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 1);
2514 expect(Ok, stat);
2515
2516 stat = GdipImageSelectActiveFrame((GpImage*)bmp, &dimension, 0);
2517 expect(Ok, stat);
2518
2519 stat = GdipBitmapGetPixel(bmp, 0, 0, &color);
2520 expect(Ok, stat);
2521 expect(0xffffffff, color);
2522
2523 /* rotate/flip discards the information about other frames */
2524 stat = GdipImageRotateFlip((GpImage*)bmp, Rotate90FlipNone);
2525 expect(Ok, stat);
2526
2527 count = 12345;
2528 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2529 expect(Ok, stat);
2530 expect(1, count);
2531
2532 expect_rawformat(&ImageFormatMemoryBMP, (GpImage*)bmp, __LINE__, FALSE);
2533
2534 GdipDisposeImage((GpImage*)bmp);
2535 IStream_Release(stream);
2536
2537 /* Test with a non-animated gif */
2538 hglob = GlobalAlloc (0, sizeof(gifimage));
2539 data = GlobalLock (hglob);
2540 memcpy(data, gifimage, sizeof(gifimage));
2541 GlobalUnlock(hglob);
2542
2543 hres = CreateStreamOnHGlobal(hglob, TRUE, &stream);
2544 ok(hres == S_OK, "Failed to create a stream\n");
2545 if(hres != S_OK) return;
2546
2547 stat = GdipCreateBitmapFromStream(stream, &bmp);
2548 ok(stat == Ok, "Failed to create a Bitmap\n");
2549 if(stat != Ok){
2550 IStream_Release(stream);
2551 return;
2552 }
2553
2554 /* Check metadata */
2555 stat = GdipImageGetFrameDimensionsCount((GpImage*)bmp,&count);
2556 expect(Ok, stat);
2557 expect(1, count);
2558
2559 stat = GdipImageGetFrameDimensionsList((GpImage*)bmp, &dimension, 1);
2560 expect(Ok, stat);
2561 expect_guid(&FrameDimensionTime, &dimension, __LINE__, FALSE);
2562
2563 count = 12345;
2564 stat = GdipImageGetFrameCount((GpImage*)bmp, &dimension, &count);
2565 expect(Ok, stat);
2566 expect(1, count);
2567
2568 GdipDisposeImage((GpImage*)bmp);
2569 IStream_Release(stream);
2570 }
2571
2572 static void test_rotateflip(void)
2573 {
2574 GpImage *bitmap;
2575 GpStatus stat;
2576 BYTE bits[24];
2577 static const BYTE orig_bits[24] = {
2578 0,0,0xff, 0,0xff,0, 0xff,0,0, 23,23,23,
2579 0xff,0xff,0, 0xff,0,0xff, 0,0xff,0xff, 23,23,23};
2580 UINT width, height;
2581 ARGB color;
2582
2583 memcpy(bits, orig_bits, sizeof(bits));
2584 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2585 expect(Ok, stat);
2586
2587 stat = GdipImageRotateFlip(bitmap, Rotate90FlipNone);
2588 expect(Ok, stat);
2589
2590 stat = GdipGetImageWidth(bitmap, &width);
2591 expect(Ok, stat);
2592 stat = GdipGetImageHeight(bitmap, &height);
2593 expect(Ok, stat);
2594 expect(2, width);
2595 expect(3, height);
2596
2597 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2598 expect(Ok, stat);
2599 expect(0xff00ffff, color);
2600
2601 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 0, &color);
2602 expect(Ok, stat);
2603 expect(0xffff0000, color);
2604
2605 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 2, &color);
2606 expect(Ok, stat);
2607 expect(0xffffff00, color);
2608
2609 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 1, 2, &color);
2610 expect(Ok, stat);
2611 expect(0xff0000ff, color);
2612
2613 expect(0, bits[0]);
2614 expect(0, bits[1]);
2615 expect(0xff, bits[2]);
2616
2617 GdipDisposeImage(bitmap);
2618
2619 memcpy(bits, orig_bits, sizeof(bits));
2620 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2621 expect(Ok, stat);
2622
2623 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipX);
2624 expect(Ok, stat);
2625
2626 stat = GdipGetImageWidth(bitmap, &width);
2627 expect(Ok, stat);
2628 stat = GdipGetImageHeight(bitmap, &height);
2629 expect(Ok, stat);
2630 expect(3, width);
2631 expect(2, height);
2632
2633 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2634 expect(Ok, stat);
2635 expect(0xff0000ff, color);
2636
2637 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2638 expect(Ok, stat);
2639 expect(0xffff0000, color);
2640
2641 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2642 expect(Ok, stat);
2643 expect(0xffffff00, color);
2644
2645 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2646 expect(Ok, stat);
2647 expect(0xff00ffff, color);
2648
2649 expect(0, bits[0]);
2650 expect(0, bits[1]);
2651 expect(0xff, bits[2]);
2652
2653 GdipDisposeImage(bitmap);
2654
2655 memcpy(bits, orig_bits, sizeof(bits));
2656 stat = GdipCreateBitmapFromScan0(3, 2, 12, PixelFormat24bppRGB, bits, (GpBitmap**)&bitmap);
2657 expect(Ok, stat);
2658
2659 stat = GdipImageRotateFlip(bitmap, RotateNoneFlipY);
2660 expect(Ok, stat);
2661
2662 stat = GdipGetImageWidth(bitmap, &width);
2663 expect(Ok, stat);
2664 stat = GdipGetImageHeight(bitmap, &height);
2665 expect(Ok, stat);
2666 expect(3, width);
2667 expect(2, height);
2668
2669 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 0, &color);
2670 expect(Ok, stat);
2671 expect(0xff00ffff, color);
2672
2673 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 0, &color);
2674 expect(Ok, stat);
2675 expect(0xffffff00, color);
2676
2677 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 0, 1, &color);
2678 expect(Ok, stat);
2679 expect(0xffff0000, color);
2680
2681 stat = GdipBitmapGetPixel((GpBitmap*)bitmap, 2, 1, &color);
2682 expect(Ok, stat);
2683 expect(0xff0000ff, color);
2684
2685 expect(0, bits[0]);
2686 expect(0, bits[1]);
2687 expect(0xff, bits[2]);
2688
2689 GdipDisposeImage(bitmap);
2690 }
2691
2692 static void test_remaptable(void)
2693 {
2694 GpStatus stat;
2695 GpImageAttributes *imageattr;
2696 GpBitmap *bitmap1, *bitmap2;
2697 GpGraphics *graphics;
2698 ARGB color;
2699 ColorMap *map;
2700
2701 map = GdipAlloc(sizeof(ColorMap));
2702
2703 map->oldColor.Argb = 0xff00ff00;
2704 map->newColor.Argb = 0xffff00ff;
2705
2706 stat = GdipSetImageAttributesRemapTable(NULL, ColorAdjustTypeDefault, TRUE, 1, map);
2707 expect(InvalidParameter, stat);
2708
2709 stat = GdipCreateImageAttributes(&imageattr);
2710 expect(Ok, stat);
2711
2712 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, NULL);
2713 expect(InvalidParameter, stat);
2714
2715 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeCount, TRUE, 1, map);
2716 expect(InvalidParameter, stat);
2717
2718 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeAny, TRUE, 1, map);
2719 expect(InvalidParameter, stat);
2720
2721 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 0, map);
2722 expect(InvalidParameter, stat);
2723
2724 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, FALSE, 0, NULL);
2725 expect(Ok, stat);
2726
2727 stat = GdipSetImageAttributesRemapTable(imageattr, ColorAdjustTypeDefault, TRUE, 1, map);
2728 expect(Ok, stat);
2729
2730 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap1);
2731 expect(Ok, stat);
2732
2733 stat = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat32bppRGB, NULL, &bitmap2);
2734 expect(Ok, stat);
2735
2736 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0xff00ff00);
2737 expect(Ok, stat);
2738
2739 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2740 expect(Ok, stat);
2741
2742 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2743 UnitPixel, imageattr, NULL, NULL);
2744 expect(Ok, stat);
2745
2746 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2747 expect(Ok, stat);
2748 ok(color_match(0xffff00ff, color, 1), "Expected ffff00ff, got %.8x\n", color);
2749
2750 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2751 expect(Ok, stat);
2752
2753 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,1,1, 0,0,1,1,
2754 UnitPixel, imageattr, NULL, NULL);
2755 expect(Ok, stat);
2756
2757 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2758 expect(Ok, stat);
2759 ok(color_match(0xff00ff00, color, 1), "Expected ff00ff00, got %.8x\n", color);
2760
2761 GdipDeleteGraphics(graphics);
2762 GdipDisposeImage((GpImage*)bitmap1);
2763 GdipDisposeImage((GpImage*)bitmap2);
2764 GdipDisposeImageAttributes(imageattr);
2765 GdipFree(map);
2766 }
2767
2768 static void test_colorkey(void)
2769 {
2770 GpStatus stat;
2771 GpImageAttributes *imageattr;
2772 GpBitmap *bitmap1, *bitmap2;
2773 GpGraphics *graphics;
2774 ARGB color;
2775
2776 stat = GdipSetImageAttributesColorKeys(NULL, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2777 expect(InvalidParameter, stat);
2778
2779 stat = GdipCreateImageAttributes(&imageattr);
2780 expect(Ok, stat);
2781
2782 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeCount, TRUE, 0xff405060, 0xff708090);
2783 expect(InvalidParameter, stat);
2784
2785 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeAny, TRUE, 0xff405060, 0xff708090);
2786 expect(InvalidParameter, stat);
2787
2788 stat = GdipSetImageAttributesColorKeys(imageattr, ColorAdjustTypeDefault, TRUE, 0xff405060, 0xff708090);
2789 expect(Ok, stat);
2790
2791 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap1);
2792 expect(Ok, stat);
2793
2794 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, &bitmap2);
2795 expect(Ok, stat);
2796
2797 stat = GdipBitmapSetPixel(bitmap1, 0, 0, 0x20405060);
2798 expect(Ok, stat);
2799
2800 stat = GdipBitmapSetPixel(bitmap1, 0, 1, 0x40506070);
2801 expect(Ok, stat);
2802
2803 stat = GdipBitmapSetPixel(bitmap1, 1, 0, 0x60708090);
2804 expect(Ok, stat);
2805
2806 stat = GdipBitmapSetPixel(bitmap1, 1, 1, 0xffffffff);
2807 expect(Ok, stat);
2808
2809 stat = GdipGetImageGraphicsContext((GpImage*)bitmap2, &graphics);
2810 expect(Ok, stat);
2811
2812 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2813 UnitPixel, imageattr, NULL, NULL);
2814 expect(Ok, stat);
2815
2816 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2817 expect(Ok, stat);
2818 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2819
2820 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2821 expect(Ok, stat);
2822 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2823
2824 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2825 expect(Ok, stat);
2826 ok(color_match(0x00000000, color, 1), "Expected 00000000, got %.8x\n", color);
2827
2828 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2829 expect(Ok, stat);
2830 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
2831
2832 stat = GdipResetImageAttributes(imageattr, ColorAdjustTypeDefault);
2833 expect(Ok, stat);
2834
2835 stat = GdipDrawImageRectRectI(graphics, (GpImage*)bitmap1, 0,0,2,2, 0,0,2,2,
2836 UnitPixel, imageattr, NULL, NULL);
2837 expect(Ok, stat);
2838
2839 stat = GdipBitmapGetPixel(bitmap2, 0, 0, &color);
2840 expect(Ok, stat);
2841 ok(color_match(0x20405060, color, 1), "Expected 20405060, got %.8x\n", color);
2842
2843 stat = GdipBitmapGetPixel(bitmap2, 0, 1, &color);
2844 expect(Ok, stat);
2845 ok(color_match(0x40506070, color, 1), "Expected 40506070, got %.8x\n", color);
2846
2847 stat = GdipBitmapGetPixel(bitmap2, 1, 0, &color);
2848 expect(Ok, stat);
2849 ok(color_match(0x60708090, color, 1), "Expected 60708090, got %.8x\n", color);
2850
2851 stat = GdipBitmapGetPixel(bitmap2, 1, 1, &color);
2852 expect(Ok, stat);
2853 ok(color_match(0xffffffff, color, 1), "Expected ffffffff, got %.8x\n", color);
2854
2855
2856 GdipDeleteGraphics(graphics);
2857 GdipDisposeImage((GpImage*)bitmap1);
2858 GdipDisposeImage((GpImage*)bitmap2);
2859 GdipDisposeImageAttributes(imageattr);
2860 }
2861
2862 static void test_dispose(void)
2863 {
2864 GpStatus stat;
2865 GpImage *image;
2866 char invalid_image[256];
2867
2868 stat = GdipDisposeImage(NULL);
2869 expect(InvalidParameter, stat);
2870
2871 stat = GdipCreateBitmapFromScan0(2, 2, 0, PixelFormat32bppARGB, NULL, (GpBitmap**)&image);
2872 expect(Ok, stat);
2873
2874 stat = GdipDisposeImage(image);
2875 expect(Ok, stat);
2876
2877 stat = GdipDisposeImage(image);
2878 expect(ObjectBusy, stat);
2879
2880 memset(invalid_image, 0, 256);
2881 stat = GdipDisposeImage((GpImage*)invalid_image);
2882 expect(ObjectBusy, stat);
2883 }
2884
2885 static LONG obj_refcount(void *obj)
2886 {
2887 IUnknown_AddRef((IUnknown *)obj);
2888 return IUnknown_Release((IUnknown *)obj);
2889 }
2890
2891 static GpImage *load_image(const BYTE *image_data, UINT image_size)
2892 {
2893 IStream *stream;
2894 HGLOBAL hmem;
2895 BYTE *data;
2896 HRESULT hr;
2897 GpStatus status;
2898 GpImage *image = NULL, *clone;
2899 ImageType image_type;
2900 LONG refcount, old_refcount;
2901
2902 hmem = GlobalAlloc(0, image_size);
2903 data = GlobalLock(hmem);
2904 memcpy(data, image_data, image_size);
2905 GlobalUnlock(hmem);
2906
2907 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
2908 ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
2909 if (hr != S_OK) return NULL;
2910
2911 refcount = obj_refcount(stream);
2912 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
2913
2914 status = GdipLoadImageFromStream(stream, &image);
2915 ok(status == Ok || broken(status == InvalidParameter), /* XP */
2916 "GdipLoadImageFromStream error %d\n", status);
2917 if (status != Ok)
2918 {
2919 IStream_Release(stream);
2920 return NULL;
2921 }
2922
2923 status = GdipGetImageType(image, &image_type);
2924 ok(status == Ok, "GdipGetImageType error %d\n", status);
2925
2926 refcount = obj_refcount(stream);
2927 if (image_type == ImageTypeBitmap)
2928 ok(refcount > 1, "expected stream refcount > 1, got %d\n", refcount);
2929 else
2930 ok(refcount == 1, "expected stream refcount 1, got %d\n", refcount);
2931 old_refcount = refcount;
2932
2933 status = GdipCloneImage(image, &clone);
2934 ok(status == Ok, "GdipCloneImage error %d\n", status);
2935 refcount = obj_refcount(stream);
2936 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
2937 status = GdipDisposeImage(clone);
2938 ok(status == Ok, "GdipDisposeImage error %d\n", status);
2939 refcount = obj_refcount(stream);
2940 ok(refcount == old_refcount, "expected stream refcount %d, got %d\n", old_refcount, refcount);
2941
2942 refcount = IStream_Release(stream);
2943 if (image_type == ImageTypeBitmap)
2944 ok(refcount >= 1, "expected stream refcount != 0\n");
2945 else
2946 ok(refcount == 0, "expected stream refcount 0, got %d\n", refcount);
2947
2948 return image;
2949 }
2950
2951 static void test_image_properties(void)
2952 {
2953 static const struct test_data
2954 {
2955 const BYTE *image_data;
2956 UINT image_size;
2957 ImageType image_type;
2958 UINT prop_count;
2959 UINT prop_count2; /* if win7 behaves differently */
2960 /* 1st property attributes */
2961 UINT prop_size;
2962 UINT prop_size2; /* if win7 behaves differently */
2963 UINT prop_id;
2964 UINT prop_id2; /* if win7 behaves differently */
2965 }
2966 td[] =
2967 {
2968 { pngimage, sizeof(pngimage), ImageTypeBitmap, 4, ~0, 1, 20, 0x5110, 0x132 },
2969 { jpgimage, sizeof(jpgimage), ImageTypeBitmap, 2, ~0, 128, 0, 0x5090, 0x5091 },
2970 { tiffimage, sizeof(tiffimage), ImageTypeBitmap, 16, 0, 4, 0, 0xfe, 0 },
2971 { bmpimage, sizeof(bmpimage), ImageTypeBitmap, 0, 0, 0, 0, 0, 0 },
2972 { wmfimage, sizeof(wmfimage), ImageTypeMetafile, 0, 0, 0, 0, 0, 0 }
2973 };
2974 GpStatus status;
2975 GpImage *image;
2976 UINT prop_count, prop_size, i;
2977 PROPID prop_id[16] = { 0 };
2978 ImageType image_type;
2979 union
2980 {
2981 PropertyItem data;
2982 char buf[256];
2983 } item;
2984
2985 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
2986 {
2987 image = load_image(td[i].image_data, td[i].image_size);
2988 if (!image)
2989 {
2990 trace("%u: failed to load image data\n", i);
2991 continue;
2992 }
2993
2994 status = GdipGetImageType(image, &image_type);
2995 ok(status == Ok, "%u: GdipGetImageType error %d\n", i, status);
2996 ok(td[i].image_type == image_type, "%u: expected image_type %d, got %d\n",
2997 i, td[i].image_type, image_type);
2998
2999 status = GdipGetPropertyCount(image, &prop_count);
3000 ok(status == Ok, "%u: GdipGetPropertyCount error %d\n", i, status);
3001 if (td[i].image_data == pngimage || td[i].image_data == jpgimage)
3002 todo_wine
3003 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3004 " %u: expected property count %u or %u, got %u\n",
3005 i, td[i].prop_count, td[i].prop_count2, prop_count);
3006 else
3007 ok(td[i].prop_count == prop_count || td[i].prop_count2 == prop_count,
3008 " %u: expected property count %u or %u, got %u\n",
3009 i, td[i].prop_count, td[i].prop_count2, prop_count);
3010
3011 status = GdipGetPropertyItemSize(NULL, 0, &prop_size);
3012 expect(InvalidParameter, status);
3013 status = GdipGetPropertyItemSize(image, 0, NULL);
3014 expect(InvalidParameter, status);
3015 status = GdipGetPropertyItemSize(image, 0, &prop_size);
3016 if (image_type == ImageTypeMetafile)
3017 expect(NotImplemented, status);
3018 else
3019 expect(PropertyNotFound, status);
3020
3021 status = GdipGetPropertyItem(NULL, 0, 0, &item.data);
3022 expect(InvalidParameter, status);
3023 status = GdipGetPropertyItem(image, 0, 0, NULL);
3024 expect(InvalidParameter, status);
3025 status = GdipGetPropertyItem(image, 0, 0, &item.data);
3026 if (image_type == ImageTypeMetafile)
3027 expect(NotImplemented, status);
3028 else
3029 expect(PropertyNotFound, status);
3030
3031 /* FIXME: remove once Wine is fixed */
3032 if (td[i].prop_count != prop_count)
3033 {
3034 GdipDisposeImage(image);
3035 continue;
3036 }
3037
3038 status = GdipGetPropertyIdList(NULL, prop_count, prop_id);
3039 expect(InvalidParameter, status);
3040 status = GdipGetPropertyIdList(image, prop_count, NULL);
3041 expect(InvalidParameter, status);
3042 status = GdipGetPropertyIdList(image, 0, prop_id);
3043 if (image_type == ImageTypeMetafile)
3044 expect(NotImplemented, status);
3045 else if (prop_count == 0)
3046 expect(Ok, status);
3047 else
3048 expect(InvalidParameter, status);
3049 status = GdipGetPropertyIdList(image, prop_count - 1, prop_id);
3050 if (image_type == ImageTypeMetafile)
3051 expect(NotImplemented, status);
3052 else
3053 expect(InvalidParameter, status);
3054 status = GdipGetPropertyIdList(image, prop_count + 1, prop_id);
3055 if (image_type == ImageTypeMetafile)
3056 expect(NotImplemented, status);
3057 else
3058 expect(InvalidParameter, status);
3059 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3060 if (image_type == ImageTypeMetafile)
3061 expect(NotImplemented, status);
3062 else
3063 {
3064 expect(Ok, status);
3065 if (prop_count != 0)
3066 ok(td[i].prop_id == prop_id[0] || td[i].prop_id2 == prop_id[0],
3067 " %u: expected property id %#x or %#x, got %#x\n",
3068 i, td[i].prop_id, td[i].prop_id2, prop_id[0]);
3069 }
3070
3071 if (status == Ok)
3072 {
3073 status = GdipGetPropertyItemSize(image, prop_id[0], &prop_size);
3074 if (prop_count == 0)
3075 expect(PropertyNotFound, status);
3076 else
3077 {
3078 expect(Ok, status);
3079
3080 assert(sizeof(item) >= prop_size);
3081 ok(prop_size > sizeof(PropertyItem), "%u: got too small prop_size %u\n",
3082 i, prop_size);
3083 ok(td[i].prop_size + sizeof(PropertyItem) == prop_size ||
3084 td[i].prop_size2 + sizeof(PropertyItem) == prop_size,
3085 " %u: expected property size %u or %u, got %u\n",
3086 i, td[i].prop_size, td[i].prop_size2, prop_size);
3087
3088 status = GdipGetPropertyItem(image, prop_id[0], 0, &item.data);
3089 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3090 "%u: expected InvalidParameter, got %d\n", i, status);
3091 status = GdipGetPropertyItem(image, prop_id[0], prop_size - 1, &item.data);
3092 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3093 "%u: expected InvalidParameter, got %d\n", i, status);
3094 status = GdipGetPropertyItem(image, prop_id[0], prop_size + 1, &item.data);
3095 ok(status == InvalidParameter || status == GenericError /* Win7 */,
3096 "%u: expected InvalidParameter, got %d\n", i, status);
3097 status = GdipGetPropertyItem(image, prop_id[0], prop_size, &item.data);
3098 expect(Ok, status);
3099 ok(prop_id[0] == item.data.id,
3100 "%u: expected property id %#x, got %#x\n", i, prop_id[0], item.data.id);
3101 }
3102 }
3103
3104 GdipDisposeImage(image);
3105 }
3106 }
3107
3108 #define IFD_BYTE 1
3109 #define IFD_ASCII 2
3110 #define IFD_SHORT 3
3111 #define IFD_LONG 4
3112 #define IFD_RATIONAL 5
3113 #define IFD_SBYTE 6
3114 #define IFD_UNDEFINED 7
3115 #define IFD_SSHORT 8
3116 #define IFD_SLONG 9
3117 #define IFD_SRATIONAL 10
3118 #define IFD_FLOAT 11
3119 #define IFD_DOUBLE 12
3120
3121 #ifndef PropertyTagTypeSByte
3122 #define PropertyTagTypeSByte 6
3123 #define PropertyTagTypeSShort 8
3124 #define PropertyTagTypeFloat 11
3125 #define PropertyTagTypeDouble 12
3126 #endif
3127
3128 static UINT documented_type(UINT type)
3129 {
3130 switch (type)
3131 {
3132 case PropertyTagTypeSByte: return PropertyTagTypeByte;
3133 case PropertyTagTypeSShort: return PropertyTagTypeShort;
3134 case PropertyTagTypeFloat: return PropertyTagTypeUndefined;
3135 case PropertyTagTypeDouble: return PropertyTagTypeUndefined;
3136 default: return type;
3137 }
3138 }
3139
3140 #include "pshpack2.h"
3141 struct IFD_entry
3142 {
3143 SHORT id;
3144 SHORT type;
3145 ULONG count;
3146 LONG value;
3147 };
3148
3149 struct IFD_rational
3150 {
3151 LONG numerator;
3152 LONG denominator;
3153 };
3154
3155 static const struct tiff_data
3156 {
3157 USHORT byte_order;
3158 USHORT version;
3159 ULONG dir_offset;
3160 USHORT number_of_entries;
3161 struct IFD_entry entry[40];
3162 ULONG next_IFD;
3163 struct IFD_rational xres;
3164 DOUBLE double_val;
3165 struct IFD_rational srational_val;
3166 char string[14];
3167 SHORT short_val[4];
3168 LONG long_val[2];
3169 FLOAT float_val[2];
3170 struct IFD_rational rational[3];
3171 BYTE pixel_data[4];
3172 } TIFF_data =
3173 {
3174 #ifdef WORDS_BIGENDIAN
3175 'M' | 'M' << 8,
3176 #else
3177 'I' | 'I' << 8,
3178 #endif
3179 42,
3180 FIELD_OFFSET(struct tiff_data, number_of_entries),
3181 31,
3182 {
3183 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
3184 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
3185 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
3186 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
3187 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
3188 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
3189 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_data, pixel_data) }, /* STRIPOFFSETS */
3190 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
3191 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
3192 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
3193 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3194 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_data, xres) },
3195 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
3196 { 0xf001, IFD_BYTE, 1, 0x11223344 },
3197 { 0xf002, IFD_BYTE, 4, 0x11223344 },
3198 { 0xf003, IFD_SBYTE, 1, 0x11223344 },
3199 { 0xf004, IFD_SSHORT, 1, 0x11223344 },
3200 { 0xf005, IFD_SSHORT, 2, 0x11223344 },
3201 { 0xf006, IFD_SLONG, 1, 0x11223344 },
3202 { 0xf007, IFD_FLOAT, 1, 0x11223344 },
3203 { 0xf008, IFD_DOUBLE, 1, FIELD_OFFSET(struct tiff_data, double_val) },
3204 { 0xf009, IFD_SRATIONAL, 1, FIELD_OFFSET(struct tiff_data, srational_val) },
3205 { 0xf00a, IFD_BYTE, 13, FIELD_OFFSET(struct tiff_data, string) },
3206 { 0xf00b, IFD_SSHORT, 4, FIELD_OFFSET(struct tiff_data, short_val) },
3207 { 0xf00c, IFD_SLONG, 2, FIELD_OFFSET(struct tiff_data, long_val) },
3208 { 0xf00e, IFD_ASCII, 13, FIELD_OFFSET(struct tiff_data, string) },
3209 { 0xf00f, IFD_ASCII, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3210 { 0xf010, IFD_UNDEFINED, 13, FIELD_OFFSET(struct tiff_data, string) },
3211 { 0xf011, IFD_UNDEFINED, 4, 'a' | 'b' << 8 | 'c' << 16 | 'd' << 24 },
3212 /* Some gdiplus versions ignore these fields.
3213 { 0xf012, IFD_BYTE, 0, 0x11223344 },
3214 { 0xf013, IFD_SHORT, 0, 0x11223344 },
3215 { 0xf014, IFD_LONG, 0, 0x11223344 },
3216 { 0xf015, IFD_FLOAT, 0, 0x11223344 },*/
3217 { 0xf016, IFD_SRATIONAL, 3, FIELD_OFFSET(struct tiff_data, rational) },
3218 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3219 { 0xf017, IFD_FLOAT, 2, FIELD_OFFSET(struct tiff_data, float_val) },
3220 },
3221 0,
3222 { 900, 3 },
3223 1234567890.0987654321,
3224 { 0x1a2b3c4d, 0x5a6b7c8d },
3225 "Hello World!",
3226 { 0x0101, 0x0202, 0x0303, 0x0404 },
3227 { 0x11223344, 0x55667788 },
3228 { (FLOAT)1234.5678, (FLOAT)8765.4321 },
3229 { { 0x01020304, 0x05060708 }, { 0x10203040, 0x50607080 }, { 0x11223344, 0x55667788 } },
3230 { 0x11, 0x22, 0x33, 0 }
3231 };
3232 #include "poppack.h"
3233
3234 static void test_tiff_properties(void)
3235 {
3236 static const struct test_data
3237 {
3238 ULONG type, id, length;
3239 const BYTE value[24];
3240 } td[31] =
3241 {
3242 { PropertyTagTypeShort, 0xff, 2, { 0 } },
3243 { PropertyTagTypeLong, 0x100, 4, { 1 } },
3244 { PropertyTagTypeLong, 0x101, 4, { 1 } },
3245 { PropertyTagTypeShort, 0x102, 2, { 1 } },
3246 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3247 { PropertyTagTypeShort, 0x106, 2, { 1 } },
3248 { PropertyTagTypeLong, 0x111, 4, { 0x44,0x02 } },
3249 { PropertyTagTypeShort, 0x115, 2, { 1 } },
3250 { PropertyTagTypeLong, 0x116, 4, { 1 } },
3251 { PropertyTagTypeLong, 0x117, 4, { 1 } },
3252 { PropertyTagTypeRational, 0x11a, 8, { 0x84,0x03,0,0,0x03 } },
3253 { PropertyTagTypeRational, 0x11b, 8, { 0x84,0x03,0,0,0x03 } },
3254 { PropertyTagTypeShort, 0x128, 2, { 2 } },
3255 { PropertyTagTypeByte, 0xf001, 1, { 0x44 } },
3256 { PropertyTagTypeByte, 0xf002, 4, { 0x44,0x33,0x22,0x11 } },
3257 { PropertyTagTypeSByte, 0xf003, 1, { 0x44 } },
3258 { PropertyTagTypeSShort, 0xf004, 2, { 0x44,0x33 } },
3259 { PropertyTagTypeSShort, 0xf005, 4, { 0x44,0x33,0x22,0x11 } },
3260 { PropertyTagTypeSLONG, 0xf006, 4, { 0x44,0x33,0x22,0x11 } },
3261 { PropertyTagTypeFloat, 0xf007, 4, { 0x44,0x33,0x22,0x11 } },
3262 { PropertyTagTypeDouble, 0xf008, 8, { 0x2c,0x52,0x86,0xb4,0x80,0x65,0xd2,0x41 } },
3263 { PropertyTagTypeSRational, 0xf009, 8, { 0x4d, 0x3c, 0x2b, 0x1a, 0x8d, 0x7c, 0x6b, 0x5a } },
3264 { PropertyTagTypeByte, 0xf00a, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3265 { PropertyTagTypeSShort, 0xf00b, 8, { 0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04 } },
3266 { PropertyTagTypeSLONG, 0xf00c, 8, { 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3267 { PropertyTagTypeASCII, 0xf00e, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3268 { PropertyTagTypeASCII, 0xf00f, 5, { 'a','b','c','d' } },
3269 { PropertyTagTypeUndefined, 0xf010, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
3270 { PropertyTagTypeUndefined, 0xf011, 4, { 'a','b','c','d' } },
3271 { PropertyTagTypeSRational, 0xf016, 24,
3272 { 0x04,0x03,0x02,0x01,0x08,0x07,0x06,0x05,
3273 0x40,0x30,0x20,0x10,0x80,0x70,0x60,0x50,
3274 0x44,0x33,0x22,0x11,0x88,0x77,0x66,0x55 } },
3275 /* Win7 before SP1 doesn't recognize this field, everybody else does. */
3276 { PropertyTagTypeFloat, 0xf017, 8, { 0x2b,0x52,0x9a,0x44,0xba,0xf5,0x08,0x46 } },
3277 };
3278 GpStatus status;
3279 GpImage *image;
3280 GUID guid;
3281 UINT dim_count, frame_count, prop_count, prop_size, i;
3282 PROPID *prop_id;
3283 PropertyItem *prop_item;
3284
3285 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3286 if (!image)
3287 {
3288 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3289 return;
3290 }
3291
3292 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3293 expect(Ok, status);
3294 expect(1, dim_count);
3295
3296 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3297 expect(Ok, status);
3298 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3299
3300 frame_count = 0xdeadbeef;
3301 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3302 expect(Ok, status);
3303 expect(1, frame_count);
3304
3305 prop_count = 0xdeadbeef;
3306 status = GdipGetPropertyCount(image, &prop_count);
3307 expect(Ok, status);
3308 ok(prop_count == sizeof(td)/sizeof(td[0]) ||
3309 broken(prop_count == sizeof(td)/sizeof(td[0]) - 1) /* Win7 SP0 */,
3310 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3311
3312 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3313
3314 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3315 expect(Ok, status);
3316
3317 for (i = 0; i < prop_count; i++)
3318 {
3319 status = GdipGetPropertyItemSize(image, prop_id[i], &prop_size);
3320 expect(Ok, status);
3321 if (status != Ok) break;
3322 ok(prop_size > sizeof(*prop_item), "%u: too small item length %u\n", i, prop_size);
3323
3324 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, prop_size);
3325 status = GdipGetPropertyItem(image, prop_id[i], prop_size, prop_item);
3326 expect(Ok, status);
3327 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3328 ok(td[i].type == prop_item->type ||
3329 /* Win7 stopped using proper but not documented types, and it
3330 looks broken since TypeFloat and TypeDouble now reported as
3331 TypeUndefined, and signed types reported as unsigned. */
3332 broken(prop_item->type == documented_type(td[i].type)),
3333 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3334 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3335 prop_size -= sizeof(*prop_item);
3336 ok(prop_item->length == prop_size, "%u: expected length %u, got %u\n", i, prop_size, prop_item->length);
3337 ok(td[i].length == prop_item->length || broken(td[i].id == 0xf00f && td[i].length == prop_item->length+1) /* XP */,
3338 "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3339 ok(td[i].length == prop_size || broken(td[i].id == 0xf00f && td[i].length == prop_size+1) /* XP */,
3340 "%u: expected length %u, got %u\n", i, td[i].length, prop_size);
3341 if (td[i].length == prop_item->length)
3342 {
3343 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3344 ok(match || broken(td[i].length <= 4 && !match), "%u: data mismatch\n", i);
3345 if (!match)
3346 {
3347 UINT j;
3348 BYTE *data = prop_item->value;
3349 trace("id %#x:", prop_item->id);
3350 for (j = 0; j < prop_item->length; j++)
3351 trace(" %02x", data[j]);
3352 trace("\n");
3353 }
3354 }
3355 HeapFree(GetProcessHeap(), 0, prop_item);
3356 }
3357
3358 HeapFree(GetProcessHeap(), 0, prop_id);
3359
3360 GdipDisposeImage(image);
3361 }
3362
3363 static void test_GdipGetAllPropertyItems(void)
3364 {
3365 static const struct test_data
3366 {
3367 ULONG type, id, length;
3368 BYTE value[32];
3369 } td[16] =
3370 {
3371 { PropertyTagTypeLong, 0xfe, 4, { 0 } },
3372 { PropertyTagTypeShort, 0x100, 2, { 1 } },
3373 { PropertyTagTypeShort, 0x101, 2, { 1 } },
3374 { PropertyTagTypeShort, 0x102, 6, { 8,0,8,0,8,0 } },
3375 { PropertyTagTypeShort, 0x103, 2, { 1 } },
3376 { PropertyTagTypeShort, 0x106, 2, { 2,0 } },
3377 { PropertyTagTypeASCII, 0x10d, 27, "/home/meh/Desktop/test.tif" },
3378 { PropertyTagTypeLong, 0x111, 4, { 8,0,0,0 } },
3379 { PropertyTagTypeShort, 0x112, 2, { 1 } },
3380 { PropertyTagTypeShort, 0x115, 2, { 3,0 } },
3381 { PropertyTagTypeShort, 0x116, 2, { 0x40,0 } },
3382 { PropertyTagTypeLong, 0x117, 4, { 3,0,0,0 } },
3383 { PropertyTagTypeRational, 0x11a, 8, { 0,0,0,72,0,0,0,1 } },
3384 { PropertyTagTypeRational, 0x11b, 8, { 0,0,0,72,0,0,0,1 } },
3385 { PropertyTagTypeShort, 0x11c, 2, { 1 } },
3386 { PropertyTagTypeShort, 0x128, 2, { 2 } }
3387 };
3388 GpStatus status;
3389 GpImage *image;
3390 GUID guid;
3391 UINT dim_count, frame_count, prop_count, prop_size, i;
3392 UINT total_size, total_count;
3393 PROPID *prop_id;
3394 PropertyItem *prop_item;
3395 const char *item_data;
3396
3397 image = load_image(tiffimage, sizeof(tiffimage));
3398 ok(image != 0, "Failed to load TIFF image data\n");
3399 if (!image) return;
3400
3401 dim_count = 0xdeadbeef;
3402 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
3403 expect(Ok, status);
3404 expect(1, dim_count);
3405
3406 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
3407 expect(Ok, status);
3408 expect_guid(&FrameDimensionPage, &guid, __LINE__, FALSE);
3409
3410 frame_count = 0xdeadbeef;
3411 status = GdipImageGetFrameCount(image, &guid, &frame_count);
3412 expect(Ok, status);
3413 expect(1, frame_count);
3414
3415 prop_count = 0xdeadbeef;
3416 status = GdipGetPropertyCount(image, &prop_count);
3417 expect(Ok, status);
3418 ok(prop_count == sizeof(td)/sizeof(td[0]),
3419 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
3420
3421 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
3422
3423 status = GdipGetPropertyIdList(image, prop_count, prop_id);
3424 expect(Ok, status);
3425
3426 prop_size = 0;
3427 for (i = 0; i < prop_count; i++)
3428 {
3429 UINT size;
3430 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
3431 expect(Ok, status);
3432 if (status != Ok) break;
3433 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
3434
3435 prop_size += size;
3436
3437 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3438 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
3439 expect(Ok, status);
3440 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
3441 ok(td[i].type == prop_item->type,
3442 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
3443 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
3444 size -= sizeof(*prop_item);
3445 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
3446 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
3447 if (td[i].length == prop_item->length)
3448 {
3449 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
3450 ok(match, "%u: data mismatch\n", i);
3451 if (!match)
3452 {
3453 UINT j;
3454 BYTE *data = prop_item->value;
3455 trace("id %#x:", prop_item->id);
3456 for (j = 0; j < prop_item->length; j++)
3457 trace(" %02x", data[j]);
3458 trace("\n");
3459 }
3460 }
3461 HeapFree(GetProcessHeap(), 0, prop_item);
3462 }
3463
3464 HeapFree(GetProcessHeap(), 0, prop_id);
3465
3466 status = GdipGetPropertySize(NULL, &total_size, &total_count);
3467 expect(InvalidParameter, status);
3468 status = GdipGetPropertySize(image, &total_size, NULL);
3469 expect(InvalidParameter, status);
3470 status = GdipGetPropertySize(image, NULL, &total_count);
3471 expect(InvalidParameter, status);
3472 status = GdipGetPropertySize(image, NULL, NULL);
3473 expect(InvalidParameter, status);
3474 total_size = 0xdeadbeef;
3475 total_count = 0xdeadbeef;
3476 status = GdipGetPropertySize(image, &total_size, &total_count);
3477 expect(Ok, status);
3478 ok(prop_count == total_count,
3479 "expected total property count %u, got %u\n", prop_count, total_count);
3480 ok(prop_size == total_size,
3481 "expected total property size %u, got %u\n", prop_size, total_size);
3482
3483 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
3484
3485 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
3486 expect(InvalidParameter, status);
3487 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
3488 expect(InvalidParameter, status);
3489 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3490 expect(InvalidParameter, status);
3491 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
3492 expect(InvalidParameter, status);
3493 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
3494 expect(InvalidParameter, status);
3495 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
3496 expect(InvalidParameter, status);
3497 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
3498 expect(Ok, status);
3499
3500 item_data = (const char *)(prop_item + prop_count);
3501 for (i = 0; i < prop_count; i++)
3502 {
3503 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
3504 i, item_data, prop_item[i].value);
3505 ok(td[i].type == prop_item[i].type,
3506 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
3507 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
3508 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
3509 if (td[i].length == prop_item[i].length)
3510 {
3511 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
3512 ok(match, "%u: data mismatch\n", i);
3513 if (!match)
3514 {
3515 UINT j;
3516 BYTE *data = prop_item[i].value;
3517 trace("id %#x:", prop_item[i].id);
3518 for (j = 0; j < prop_item[i].length; j++)
3519 trace(" %02x", data[j]);
3520 trace("\n");
3521 }
3522 }
3523 item_data += prop_item[i].length;
3524 }
3525
3526 HeapFree(GetProcessHeap(), 0, prop_item);
3527
3528 GdipDisposeImage(image);
3529 }
3530
3531 static void test_tiff_palette(void)
3532 {
3533 GpStatus status;
3534 GpImage *image;
3535 PixelFormat format;
3536 INT size;
3537 struct
3538 {
3539 ColorPalette pal;
3540 ARGB entry[256];
3541 } palette;
3542 ARGB *entries = palette.pal.Entries;
3543
3544 /* 1bpp TIFF without palette */
3545 image = load_image((const BYTE *)&TIFF_data, sizeof(TIFF_data));
3546 if (!image)
3547 {
3548 win_skip("Failed to load TIFF image data. Might not be supported. Skipping.\n");
3549 return;
3550 }
3551
3552 status = GdipGetImagePixelFormat(image, &format);
3553 expect(Ok, status);
3554 ok(format == PixelFormat1bppIndexed, "expected PixelFormat1bppIndexed, got %#x\n", format);
3555
3556 status = GdipGetImagePaletteSize(image, &size);
3557 ok(status == Ok || broken(status == GenericError), /* XP */
3558 "GdipGetImagePaletteSize error %d\n", status);
3559 if (status == GenericError)
3560 {
3561 GdipDisposeImage(image);
3562 return;
3563 }
3564 expect(sizeof(ColorPalette) + sizeof(ARGB), size);
3565
3566 status = GdipGetImagePalette(image, &palette.pal, size);
3567 expect(Ok, status);
3568 expect(0, palette.pal.Flags);
3569 expect(2, palette.pal.Count);
3570 if (palette.pal.Count == 2)
3571 {
3572 ok(entries[0] == 0xff000000, "expected 0xff000000, got %#x\n", entries[0]);
3573 ok(entries[1] == 0xffffffff, "expected 0xffffffff, got %#x\n", entries[1]);
3574 }
3575
3576 GdipDisposeImage(image);
3577 }
3578
3579 static void test_bitmapbits(void)
3580 {
3581 /* 8 x 2 bitmap */
3582 static const BYTE pixels_24[48] =
3583 {
3584 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3585 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3586 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3587 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0
3588 };
3589 static const BYTE pixels_00[48] =
3590 {
3591 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3592 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3593 0,0,0, 0,0,0, 0,0,0, 0,0,0,
3594 0,0,0, 0,0,0, 0,0,0, 0,0,0
3595 };
3596 static const BYTE pixels_24_77[64] =
3597 {
3598 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3599 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3600 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3601 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3602 0xff,0xff,0xff, 0,0,0, 0xff,0xff,0xff, 0,0,0,
3603 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3604 };
3605 static const BYTE pixels_77[64] =
3606 {
3607 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3608 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3609 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3610 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3611 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3612 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3613 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3614 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3615 };
3616 static const BYTE pixels_8[16] =
3617 {
3618 0x01,0,0x01,0,0x01,0,0x01,0,
3619 0x01,0,0x01,0,0x01,0,0x01,0
3620 };
3621 static const BYTE pixels_8_77[64] =
3622 {
3623 0x01,0,0x01,0,0x01,0,0x01,0,
3624 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3625 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3626 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3627 0x01,0,0x01,0,0x01,0,0x01,0,
3628 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3629 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3630 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3631 };
3632 static const BYTE pixels_1_77[64] =
3633 {
3634 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3635 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3636 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3637 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3638 0xaa,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3639 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3640 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,
3641 0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77
3642 };
3643 static const BYTE pixels_1[8] = {0xaa,0,0,0,0xaa,0,0,0};
3644 static const struct test_data
3645 {
3646 PixelFormat format;
3647 UINT bpp;
3648 ImageLockMode mode;
3649 UINT stride, size;
3650 const BYTE *pixels;
3651 const BYTE *pixels_unlocked;
3652 } td[] =
3653 {
3654 /* 0 */
3655 { PixelFormat24bppRGB, 24, 0xfff0, 24, 48, pixels_24, pixels_00 },
3656
3657 { PixelFormat24bppRGB, 24, 0, 24, 48, pixels_24, pixels_00 },
3658 { PixelFormat24bppRGB, 24, ImageLockModeRead, 24, 48, pixels_24, pixels_00 },
3659 { PixelFormat24bppRGB, 24, ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3660 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeWrite, 24, 48, pixels_24, pixels_00 },
3661 { PixelFormat24bppRGB, 24, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_24_77, pixels_24 },
3662 { PixelFormat24bppRGB, 24, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3663 { PixelFormat24bppRGB, 24, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3664 /* 8 */
3665 { PixelFormat8bppIndexed, 8, 0, 8, 16, pixels_8, pixels_24 },
3666 { PixelFormat8bppIndexed, 8, ImageLockModeRead, 8, 16, pixels_8, pixels_24 },
3667 { PixelFormat8bppIndexed, 8, ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3668 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeWrite, 8, 16, pixels_8, pixels_00 },
3669 { PixelFormat8bppIndexed, 8, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_8_77, pixels_24 },
3670 { PixelFormat8bppIndexed, 8, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3671 { PixelFormat8bppIndexed, 8, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3672 /* 15 */
3673 { PixelFormat1bppIndexed, 1, 0, 4, 8, pixels_1, pixels_24 },
3674 { PixelFormat1bppIndexed, 1, ImageLockModeRead, 4, 8, pixels_1, pixels_24 },
3675 { PixelFormat1bppIndexed, 1, ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3676 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeWrite, 4, 8, pixels_1, pixels_00 },
3677 { PixelFormat1bppIndexed, 1, ImageLockModeRead|ImageLockModeUserInputBuf, 32, 64, pixels_1_77, pixels_24 },
3678 { PixelFormat1bppIndexed, 1, ImageLockModeWrite|ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_00 },
3679 { PixelFormat1bppIndexed, 1, ImageLockModeUserInputBuf, 32, 64, pixels_77, pixels_24 },
3680 };
3681 BYTE buf[64];
3682 GpStatus status;
3683 GpBitmap *bitmap;
3684 UINT i;
3685 BitmapData data;
3686 struct
3687 {
3688 ColorPalette pal;
3689 ARGB entries[1];
3690 } palette;
3691 ARGB *entries = palette.pal.Entries;
3692
3693 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
3694 {
3695 BYTE pixels[sizeof(pixels_24)];
3696 memcpy(pixels, pixels_24, sizeof(pixels_24));
3697 status = GdipCreateBitmapFromScan0(8, 2, 24, PixelFormat24bppRGB, pixels, &bitmap);
3698 expect(Ok, status);
3699
3700 /* associate known palette with pixel data */
3701 palette.pal.Flags = PaletteFlagsGrayScale;
3702 palette.pal.Count = 2;
3703 entries[0] = 0xff000000;
3704 entries[1] = 0xffffffff;
3705 status = GdipSetImagePalette((GpImage *)bitmap, &palette.pal);
3706 expect(Ok, status);
3707
3708 memset(&data, 0xfe, sizeof(data));
3709 if (td[i].mode & ImageLockModeUserInputBuf)
3710 {
3711 memset(buf, 0x77, sizeof(buf));
3712 data.Scan0 = buf;
3713 data.Stride = 32;
3714 }
3715 status = GdipBitmapLockBits(bitmap, NULL, td[i].mode, td[i].format, &data);
3716 ok(status == Ok || broken(status == InvalidParameter) /* XP */, "%u: GdipBitmapLockBits error %d\n", i, status);
3717 if (status != Ok)
3718 {
3719 GdipDisposeImage((GpImage *)bitmap);
3720 continue;
3721 }
3722 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3723 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3724 ok(td[i].stride == data.Stride, "%u: expected %d, got %d\n", i, td[i].stride, data.Stride);
3725 ok(td[i].format == data.PixelFormat, "%u: expected %d, got %d\n", i, td[i].format, data.PixelFormat);
3726 ok(td[i].size == data.Height * data.Stride, "%u: expected %d, got %d\n", i, td[i].size, data.Height * data.Stride);
3727 if (td[i].mode & ImageLockModeUserInputBuf)
3728 ok(data.Scan0 == buf, "%u: got wrong buffer\n", i);
3729 if (td[i].size == data.Height * data.Stride)
3730 {
3731 UINT j, match, width_bytes = (data.Width * td[i].bpp) / 8;
3732
3733 match = 1;
3734 for (j = 0; j < data.Height; j++)
3735 {
3736 if (memcmp((const BYTE *)data.Scan0 + j * data.Stride, td[i].pixels + j * data.Stride, width_bytes) != 0)
3737 {
3738 match = 0;
3739 break;
3740 }
3741 }
3742 if ((td[i].mode & (ImageLockModeRead|ImageLockModeUserInputBuf)) || td[i].format == PixelFormat24bppRGB)
3743 {
3744 ok(match,
3745 "%u: data should match\n", i);
3746 if (!match)
3747 {
3748 BYTE *bits = data.Scan0;
3749 trace("%u: data mismatch for format %#x:", i, td[i].format);
3750 for (j = 0; j < td[i].size; j++)
3751 trace(" %02x", bits[j]);
3752 trace("\n");
3753 }
3754 }
3755 else
3756 ok(!match, "%u: data shouldn't match\n", i);
3757
3758 memset(data.Scan0, 0, td[i].size);
3759 }
3760
3761 status = GdipBitmapUnlockBits(bitmap, &data);
3762 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3763
3764 memset(&data, 0xfe, sizeof(data));
3765 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
3766 ok(status == Ok, "%u: GdipBitmapLockBits error %d\n", i, status);
3767 ok(data.Width == 8, "%u: expected 8, got %d\n", i, data.Width);
3768 ok(data.Height == 2, "%u: expected 2, got %d\n", i, data.Height);
3769 ok(data.Stride == 24, "%u: expected 24, got %d\n", i, data.Stride);
3770 ok(data.PixelFormat == PixelFormat24bppRGB, "%u: got wrong pixel format %d\n", i, data.PixelFormat);
3771 ok(data.Height * data.Stride == 48, "%u: expected 48, got %d\n", i, data.Height * data.Stride);
3772 if (data.Height * data.Stride == 48)
3773 {
3774 int match = memcmp(data.Scan0, td[i].pixels_unlocked, 48) == 0;
3775 ok(match, "%u: data should match\n", i);
3776 if (!match)
3777 {
3778 UINT j;
3779 BYTE *bits = data.Scan0;
3780 trace("%u: data mismatch for format %#x:", i, td[i].format);
3781 for (j = 0; j < 48; j++)
3782 trace(" %02x", bits[j]);
3783 trace("\n");
3784 }
3785 }
3786
3787 status = GdipBitmapUnlockBits(bitmap, &data);
3788 ok(status == Ok, "%u: GdipBitmapUnlockBits error %d\n", i, status);
3789
3790 status = GdipDisposeImage((GpImage *)bitmap);
3791 expect(Ok, status);
3792 }
3793 }
3794
3795 static void test_DrawImage(void)
3796 {
3797 BYTE black_1x1[4] = { 0,0,0,0 };
3798 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3799 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3800 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3801 0,0,0,0,0,0,0xff,0xff };
3802 GpStatus status;
3803 union
3804 {
3805 GpBitmap *bitmap;
3806 GpImage *image;
3807 } u1, u2;
3808 GpGraphics *graphics;
3809 int match;
3810
3811 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3812 expect(Ok, status);
3813 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3814 expect(Ok, status);
3815
3816 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3817 expect(Ok, status);
3818 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3819 expect(Ok, status);
3820 status = GdipGetImageGraphicsContext(u2.image, &graphics);
3821 expect(Ok, status);
3822 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3823 expect(Ok, status);
3824
3825 status = GdipDrawImageI(graphics, u1.image, 0, 0);
3826 expect(Ok, status);
3827
3828 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3829 ok(match, "data should match\n");
3830 if (!match)
3831 {
3832 UINT i, size = sizeof(white_2x2);
3833 BYTE *bits = white_2x2;
3834 for (i = 0; i < size; i++)
3835 trace(" %02x", bits[i]);
3836 trace("\n");
3837 }
3838
3839 status = GdipDeleteGraphics(graphics);
3840 expect(Ok, status);
3841 status = GdipDisposeImage(u1.image);
3842 expect(Ok, status);
3843 status = GdipDisposeImage(u2.image);
3844 expect(Ok, status);
3845 }
3846
3847 static void test_GdipDrawImagePointRect(void)
3848 {
3849 BYTE black_1x1[4] = { 0,0,0,0 };
3850 BYTE white_2x2[16] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
3851 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
3852 BYTE black_2x2[16] = { 0,0,0,0,0,0,0xff,0xff,
3853 0,0,0,0,0,0,0xff,0xff };
3854 GpStatus status;
3855 union
3856 {
3857 GpBitmap *bitmap;
3858 GpImage *image;
3859 } u1, u2;
3860 GpGraphics *graphics;
3861 int match;
3862
3863 status = GdipCreateBitmapFromScan0(1, 1, 4, PixelFormat24bppRGB, black_1x1, &u1.bitmap);
3864 expect(Ok, status);
3865 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
3866 expect(Ok, status);
3867
3868 status = GdipCreateBitmapFromScan0(2, 2, 8, PixelFormat24bppRGB, white_2x2, &u2.bitmap);
3869 expect(Ok, status);
3870 status = GdipBitmapSetResolution(u2.bitmap, 300.0, 300.0);
3871 expect(Ok, status);
3872 status = GdipGetImageGraphicsContext(u2.image, &graphics);
3873 expect(Ok, status);
3874 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
3875 expect(Ok, status);
3876
3877 status = GdipDrawImagePointRectI(graphics, u1.image, 0, 0, 0, 0, 1, 1, UnitPixel);
3878 expect(Ok, status);
3879
3880 match = memcmp(white_2x2, black_2x2, sizeof(black_2x2)) == 0;
3881 ok(match, "data should match\n");
3882 if (!match)
3883 {
3884 UINT i, size = sizeof(white_2x2);
3885 BYTE *bits = white_2x2;
3886 for (i = 0; i < size; i++)
3887 trace(" %02x", bits[i]);
3888 trace("\n");
3889 }
3890
3891 status = GdipDeleteGraphics(graphics);
3892 expect(Ok, status);
3893 status = GdipDisposeImage(u1.image);
3894 expect(Ok, status);
3895 status = GdipDisposeImage(u2.image);
3896 expect(Ok, status);
3897 }
3898
3899 static void test_image_format(void)
3900 {
3901 static const PixelFormat fmt[] =
3902 {
3903 PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed,
3904 PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565,
3905 PixelFormat16bppARGB1555, PixelFormat24bppRGB, PixelFormat32bppRGB,
3906 PixelFormat32bppARGB, PixelFormat32bppPARGB, PixelFormat48bppRGB,
3907 PixelFormat64bppARGB, PixelFormat64bppPARGB, PixelFormat32bppCMYK
3908 };
3909 GpStatus status;
3910 GpBitmap *bitmap;
3911 GpImage *thumb;
3912 HBITMAP hbitmap;
3913 BITMAP bm;
3914 PixelFormat format;
3915 BitmapData data;
3916 UINT i, ret;
3917
3918 for (i = 0; i < sizeof(fmt)/sizeof(fmt[0]); i++)
3919 {
3920 status = GdipCreateBitmapFromScan0(1, 1, 0, fmt[i], NULL, &bitmap);
3921 ok(status == Ok || broken(status == InvalidParameter) /* before win7 */,
3922 "GdipCreateBitmapFromScan0 error %d\n", status);
3923 if (status != Ok) continue;
3924
3925 status = GdipGetImagePixelFormat((GpImage *)bitmap, &format);
3926 expect(Ok, status);
3927 expect(fmt[i], format);
3928
3929 status = GdipCreateHBITMAPFromBitmap(bitmap, &hbitmap, 0);
3930 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3931 todo_wine expect(InvalidParameter, status);
3932 else
3933 {
3934 expect(Ok, status);
3935 ret = GetObjectW(hbitmap, sizeof(bm), &bm);
3936 expect(sizeof(bm), ret);
3937 expect(0, bm.bmType);
3938 expect(1, bm.bmWidth);
3939 expect(1, bm.bmHeight);
3940 expect(4, bm.bmWidthBytes);
3941 expect(1, bm.bmPlanes);
3942 expect(32, bm.bmBitsPixel);
3943 DeleteObject(hbitmap);
3944 }
3945
3946 status = GdipGetImageThumbnail((GpImage *)bitmap, 0, 0, &thumb, NULL, NULL);
3947 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3948 todo_wine
3949 ok(status == OutOfMemory || broken(status == InvalidParameter) /* before win7 */,
3950 "expected OutOfMemory, got %d\n", status);
3951 else
3952 {
3953 expect(Ok, status);
3954 status = GdipGetImagePixelFormat(thumb, &format);
3955 expect(Ok, status);
3956 ok(format == PixelFormat32bppPARGB || broken(format != PixelFormat32bppPARGB) /* before win7 */,
3957 "expected PixelFormat32bppPARGB, got %#x\n", format);
3958 status = GdipDisposeImage(thumb);
3959 expect(Ok, status);
3960 }
3961
3962 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
3963 if (fmt[i] == PixelFormat16bppGrayScale || fmt[i] == PixelFormat32bppCMYK)
3964 todo_wine expect(InvalidParameter, status);
3965 else
3966 {
3967 expect(Ok, status);
3968 status = GdipBitmapUnlockBits(bitmap, &data);
3969 expect(Ok, status);
3970 }
3971
3972 status = GdipDisposeImage((GpImage *)bitmap);
3973 expect(Ok, status);
3974 }
3975 }
3976
3977 static void test_DrawImage_scale(void)
3978 {
3979 static const BYTE back_8x1[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
3980 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3981 static const BYTE image_080[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,
3982 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3983 static const BYTE image_100[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,
3984 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3985 static const BYTE image_120[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x40,0x40,0x40,
3986 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3987 static const BYTE image_150[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3988 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3989 static const BYTE image_180[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3990 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3991 static const BYTE image_200[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
3992 0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3993 static const BYTE image_250[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,
3994 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
3995 static const BYTE image_120_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
3996 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3997 static const BYTE image_150_half[24] = { 0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
3998 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40 };
3999 static const BYTE image_200_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4000 0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40,0x40,0x40,0x40 };
4001 static const BYTE image_250_half[24] = { 0x40,0x40,0x40,0x40,0x40,0x40,0x80,0x80,0x80,0x80,0x80,0x80,
4002 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x40,0x40,0x40 };
4003 static const struct test_data
4004 {
4005 REAL scale_x;
4006 PixelOffsetMode pixel_offset_mode;
4007 const BYTE *image;
4008 BOOL todo;
4009 } td[] =
4010 {
4011 { 0.8, PixelOffsetModeNone, image_080 }, /* 0 */
4012 { 1.0, PixelOffsetModeNone, image_100 },
4013 { 1.2, PixelOffsetModeNone, image_120 },
4014 { 1.5, PixelOffsetModeNone, image_150 },
4015 { 1.8, PixelOffsetModeNone, image_180 },
4016 { 2.0, PixelOffsetModeNone, image_200 },
4017 { 2.5, PixelOffsetModeNone, image_250 },
4018
4019 { 0.8, PixelOffsetModeHighSpeed, image_080 }, /* 7 */
4020 { 1.0, PixelOffsetModeHighSpeed, image_100 },
4021 { 1.2, PixelOffsetModeHighSpeed, image_120 },
4022 { 1.5, PixelOffsetModeHighSpeed, image_150 },
4023 { 1.8, PixelOffsetModeHighSpeed, image_180 },
4024 { 2.0, PixelOffsetModeHighSpeed, image_200 },
4025 { 2.5, PixelOffsetModeHighSpeed, image_250 },
4026
4027 { 0.8, PixelOffsetModeHalf, image_080 }, /* 14 */
4028 { 1.0, PixelOffsetModeHalf, image_100 },
4029 { 1.2, PixelOffsetModeHalf, image_120_half, TRUE },
4030 { 1.5, PixelOffsetModeHalf, image_150_half, TRUE },
4031 { 1.8, PixelOffsetModeHalf, image_180 },
4032 { 2.0, PixelOffsetModeHalf, image_200_half, TRUE },
4033 { 2.5, PixelOffsetModeHalf, image_250_half, TRUE },
4034
4035 { 0.8, PixelOffsetModeHighQuality, image_080 }, /* 21 */
4036 { 1.0, PixelOffsetModeHighQuality, image_100 },
4037 { 1.2, PixelOffsetModeHighQuality, image_120_half, TRUE },
4038 { 1.5, PixelOffsetModeHighQuality, image_150_half, TRUE },
4039 { 1.8, PixelOffsetModeHighQuality, image_180 },
4040 { 2.0, PixelOffsetModeHighQuality, image_200_half, TRUE },
4041 { 2.5, PixelOffsetModeHighQuality, image_250_half, TRUE },
4042 };
4043 BYTE src_2x1[6] = { 0x80,0x80,0x80,0x80,0x80,0x80 };
4044 BYTE dst_8x1[24];
4045 GpStatus status;
4046 union
4047 {
4048 GpBitmap *bitmap;
4049 GpImage *image;
4050 } u1, u2;
4051 GpGraphics *graphics;
4052 GpMatrix *matrix;
4053 int i, match;
4054
4055 status = GdipCreateBitmapFromScan0(2, 1, 4, PixelFormat24bppRGB, src_2x1, &u1.bitmap);
4056 expect(Ok, status);
4057 status = GdipBitmapSetResolution(u1.bitmap, 100.0, 100.0);
4058 expect(Ok, status);
4059
4060 status = GdipCreateBitmapFromScan0(8, 1, 24, PixelFormat24bppRGB, dst_8x1, &u2.bitmap);
4061 expect(Ok, status);
4062 status = GdipBitmapSetResolution(u2.bitmap, 100.0, 100.0);
4063 expect(Ok, status);
4064 status = GdipGetImageGraphicsContext(u2.image, &graphics);
4065 expect(Ok, status);
4066 status = GdipSetInterpolationMode(graphics, InterpolationModeNearestNeighbor);
4067 expect(Ok, status);
4068
4069 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
4070 {
4071 status = GdipSetPixelOffsetMode(graphics, td[i].pixel_offset_mode);
4072 expect(Ok, status);
4073
4074 status = GdipCreateMatrix2(td[i].scale_x, 0.0, 0.0, 1.0, 0.0, 0.0, &matrix);
4075 expect(Ok, status);
4076 status = GdipSetWorldTransform(graphics, matrix);
4077 expect(Ok, status);
4078 GdipDeleteMatrix(matrix);
4079
4080 memcpy(dst_8x1, back_8x1, sizeof(dst_8x1));
4081 status = GdipDrawImageI(graphics, u1.image, 1, 0);
4082 expect(Ok, status);
4083
4084 match = memcmp(dst_8x1, td[i].image, sizeof(dst_8x1)) == 0;
4085 if (!match && td[i].todo)
4086 todo_wine ok(match, "%d: data should match\n", i);
4087 else
4088 ok(match, "%d: data should match\n", i);
4089 if (!match)
4090 {
4091 UINT i, size = sizeof(dst_8x1);
4092 const BYTE *bits = dst_8x1;
4093 for (i = 0; i < size; i++)
4094 trace(" %02x", bits[i]);
4095 trace("\n");
4096 }
4097 }
4098
4099 status = GdipDeleteGraphics(graphics);
4100 expect(Ok, status);
4101 status = GdipDisposeImage(u1.image);
4102 expect(Ok, status);
4103 status = GdipDisposeImage(u2.image);
4104 expect(Ok, status);
4105 }
4106
4107 static const BYTE animatedgif[] = {
4108 'G','I','F','8','9','a',0x01,0x00,0x01,0x00,0xA1,0x02,0x00,
4109 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
4110 /*0x21,0xFF,0x0B,'A','N','I','M','E','X','T','S','1','.','0',*/
4111 0x21,0xFF,0x0B,'N','E','T','S','C','A','P','E','2','.','0',
4112 0x03,0x01,0x05,0x00,0x00,
4113 0x21,0xFE,0x0C,'H','e','l','l','o',' ','W','o','r','l','d','!',0x00,
4114 0x21,0x01,0x0D,'a','n','i','m','a','t','i','o','n','.','g','i','f',0x00,
4115 0x21,0xF9,0x04,0xff,0x0A,0x00,0x08,0x00,
4116 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4117 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,
4118 0x02,0x02,0x4C,0x01,0x00,
4119 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','1',0x00,
4120 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','1',0x00,
4121 0x21,0xF9,0x04,0x00,0x14,0x00,0x01,0x00,
4122 0x2C,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,
4123 0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,
4124 0x02,0x02,0x44,0x01,0x00,
4125 0x21,0xFE,0x08,'i','m','a','g','e',' ','#','2',0x00,
4126 0x21,0x01,0x0C,'p','l','a','i','n','t','e','x','t',' ','#','2',0x00,0x3B
4127 };
4128
4129 static void test_gif_properties(void)
4130 {
4131 static const struct test_data
4132 {
4133 ULONG type, id, length;
4134 const BYTE value[13];
4135 } td[] =
4136 {
4137 { PropertyTagTypeLong, PropertyTagFrameDelay, 8, { 10,0,0,0,20,0,0,0 } },
4138 { PropertyTagTypeASCII, PropertyTagExifUserComment, 13, { 'H','e','l','l','o',' ','W','o','r','l','d','!',0 } },
4139 { PropertyTagTypeShort, PropertyTagLoopCount, 2, { 5,0 } },
4140 { PropertyTagTypeByte, PropertyTagGlobalPalette, 12, { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c } },
4141 { PropertyTagTypeByte, PropertyTagIndexBackground, 1, { 2 } },
4142 { PropertyTagTypeByte, PropertyTagIndexTransparent, 1, { 8 } }
4143 };
4144 GpStatus status;
4145 GpImage *image;
4146 GUID guid;
4147 UINT dim_count, frame_count, prop_count, prop_size, i;
4148 UINT total_size, total_count;
4149 PROPID *prop_id;
4150 PropertyItem *prop_item;
4151 const char *item_data;
4152
4153 image = load_image(animatedgif, sizeof(animatedgif));
4154 if (!image) /* XP fails to load this GIF image */
4155 {
4156 trace("Failed to load GIF image data\n");
4157 return;
4158 }
4159
4160 status = GdipImageGetFrameDimensionsCount(image, &dim_count);
4161 expect(Ok, status);
4162 expect(1, dim_count);
4163
4164 status = GdipImageGetFrameDimensionsList(image, &guid, 1);
4165 expect(Ok, status);
4166 expect_guid(&FrameDimensionTime, &guid, __LINE__, FALSE);
4167
4168 status = GdipImageGetFrameCount(image, &guid, &frame_count);
4169 expect(Ok, status);
4170 expect(2, frame_count);
4171
4172 status = GdipImageSelectActiveFrame(image, &guid, 1);
4173 expect(Ok, status);
4174
4175 status = GdipGetPropertyCount(image, &prop_count);
4176 expect(Ok, status);
4177 ok(prop_count == sizeof(td)/sizeof(td[0]) || broken(prop_count == 1) /* before win7 */,
4178 "expected property count %u, got %u\n", (UINT)(sizeof(td)/sizeof(td[0])), prop_count);
4179
4180 if (prop_count != sizeof(td)/sizeof(td[0]))
4181 {
4182 GdipDisposeImage(image);
4183 return;
4184 }
4185
4186 prop_id = HeapAlloc(GetProcessHeap(), 0, prop_count * sizeof(*prop_id));
4187
4188 status = GdipGetPropertyIdList(image, prop_count, prop_id);
4189 expect(Ok, status);
4190
4191 prop_size = 0;
4192 for (i = 0; i < prop_count; i++)
4193 {
4194 UINT size;
4195 status = GdipGetPropertyItemSize(image, prop_id[i], &size);
4196 expect(Ok, status);
4197 if (status != Ok) break;
4198 ok(size > sizeof(*prop_item), "%u: too small item length %u\n", i, size);
4199
4200 prop_size += size;
4201
4202 prop_item = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4203 status = GdipGetPropertyItem(image, prop_id[i], size, prop_item);
4204 expect(Ok, status);
4205 ok(prop_item->value == prop_item + 1, "expected item->value %p, got %p\n", prop_item + 1, prop_item->value);
4206 ok(td[i].type == prop_item->type,
4207 "%u: expected type %u, got %u\n", i, td[i].type, prop_item->type);
4208 ok(td[i].id == prop_item->id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item->id);
4209 size -= sizeof(*prop_item);
4210 ok(prop_item->length == size, "%u: expected length %u, got %u\n", i, size, prop_item->length);
4211 ok(td[i].length == prop_item->length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item->length);
4212 if (td[i].length == prop_item->length)
4213 {
4214 int match = memcmp(td[i].value, prop_item->value, td[i].length) == 0;
4215 ok(match, "%u: data mismatch\n", i);
4216 if (!match)
4217 {
4218 UINT j;
4219 BYTE *data = prop_item->value;
4220 trace("id %#x:", prop_item->id);
4221 for (j = 0; j < prop_item->length; j++)
4222 trace(" %02x", data[j]);
4223 trace("\n");
4224 }
4225 }
4226 HeapFree(GetProcessHeap(), 0, prop_item);
4227 }
4228
4229 HeapFree(GetProcessHeap(), 0, prop_id);
4230
4231 status = GdipGetPropertySize(NULL, &total_size, &total_count);
4232 expect(InvalidParameter, status);
4233 status = GdipGetPropertySize(image, &total_size, NULL);
4234 expect(InvalidParameter, status);
4235 status = GdipGetPropertySize(image, NULL, &total_count);
4236 expect(InvalidParameter, status);
4237 status = GdipGetPropertySize(image, NULL, NULL);
4238 expect(InvalidParameter, status);
4239 total_size = 0xdeadbeef;
4240 total_count = 0xdeadbeef;
4241 status = GdipGetPropertySize(image, &total_size, &total_count);
4242 expect(Ok, status);
4243 ok(prop_count == total_count,
4244 "expected total property count %u, got %u\n", prop_count, total_count);
4245 ok(prop_size == total_size,
4246 "expected total property size %u, got %u\n", prop_size, total_size);
4247
4248 prop_item = HeapAlloc(GetProcessHeap(), 0, prop_size);
4249
4250 status = GdipGetAllPropertyItems(image, 0, prop_count, prop_item);
4251 expect(InvalidParameter, status);
4252 status = GdipGetAllPropertyItems(image, prop_size, 1, prop_item);
4253 expect(InvalidParameter, status);
4254 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4255 expect(InvalidParameter, status);
4256 status = GdipGetAllPropertyItems(image, prop_size, prop_count, NULL);
4257 expect(InvalidParameter, status);
4258 status = GdipGetAllPropertyItems(image, 0, 0, NULL);
4259 expect(InvalidParameter, status);
4260 status = GdipGetAllPropertyItems(image, prop_size + 1, prop_count, prop_item);
4261 expect(InvalidParameter, status);
4262 status = GdipGetAllPropertyItems(image, prop_size, prop_count, prop_item);
4263 expect(Ok, status);
4264
4265 item_data = (const char *)(prop_item + prop_count);
4266 for (i = 0; i < prop_count; i++)
4267 {
4268 ok(prop_item[i].value == item_data, "%u: expected value %p, got %p\n",
4269 i, item_data, prop_item[i].value);
4270 ok(td[i].type == prop_item[i].type,
4271 "%u: expected type %u, got %u\n", i, td[i].type, prop_item[i].type);
4272 ok(td[i].id == prop_item[i].id, "%u: expected id %#x, got %#x\n", i, td[i].id, prop_item[i].id);
4273 ok(td[i].length == prop_item[i].length, "%u: expected length %u, got %u\n", i, td[i].length, prop_item[i].length);
4274 if (td[i].length == prop_item[i].length)
4275 {
4276 int match = memcmp(td[i].value, prop_item[i].value, td[i].length) == 0;
4277 ok(match, "%u: data mismatch\n", i);
4278 if (!match)
4279 {
4280 UINT j;
4281 BYTE *data = prop_item[i].value;
4282 trace("id %#x:", prop_item[i].id);
4283 for (j = 0; j < prop_item[i].length; j++)
4284 trace(" %02x", data[j]);
4285 trace("\n");
4286 }
4287 }
4288 item_data += prop_item[i].length;
4289 }
4290
4291 HeapFree(GetProcessHeap(), 0, prop_item);
4292
4293 GdipDisposeImage(image);
4294 }
4295
4296 static void test_ARGB_conversion(void)
4297 {
4298 BYTE argb[8] = { 0x11,0x22,0x33,0x80, 0xff,0xff,0xff,0 };
4299 BYTE pargb[8] = { 0x09,0x11,0x1a,0x80, 0,0,0,0 };
4300 BYTE rgb32_xp[8] = { 0x11,0x22,0x33,0xff, 0xff,0xff,0xff,0xff };
4301 BYTE rgb24[6] = { 0x11,0x22,0x33, 0xff,0xff,0xff };
4302 BYTE *bits;
4303 GpBitmap *bitmap;
4304 BitmapData data;
4305 GpStatus status;
4306 int match;
4307
4308 status = GdipCreateBitmapFromScan0(2, 1, 8, PixelFormat32bppARGB, argb, &bitmap);
4309 expect(Ok, status);
4310
4311 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppPARGB, &data);
4312 expect(Ok, status);
4313 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4314 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4315 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4316 ok(data.PixelFormat == PixelFormat32bppPARGB, "expected PixelFormat32bppPARGB, got %d\n", data.PixelFormat);
4317 match = !memcmp(data.Scan0, pargb, sizeof(pargb));
4318 ok(match, "bits don't match\n");
4319 if (!match)
4320 {
4321 bits = data.Scan0;
4322 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppPARGB,
4323 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4324 }
4325 status = GdipBitmapUnlockBits(bitmap, &data);
4326 expect(Ok, status);
4327
4328 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat32bppRGB, &data);
4329 expect(Ok, status);
4330 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4331 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4332 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4333 ok(data.PixelFormat == PixelFormat32bppRGB, "expected PixelFormat32bppRGB, got %d\n", data.PixelFormat);
4334 match = !memcmp(data.Scan0, argb, sizeof(argb)) ||
4335 !memcmp(data.Scan0, rgb32_xp, sizeof(rgb32_xp));
4336 ok(match, "bits don't match\n");
4337 if (!match)
4338 {
4339 bits = data.Scan0;
4340 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat32bppRGB,
4341 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4342 }
4343 status = GdipBitmapUnlockBits(bitmap, &data);
4344 expect(Ok, status);
4345
4346 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data);
4347 expect(Ok, status);
4348 ok(data.Width == 2, "expected 2, got %d\n", data.Width);
4349 ok(data.Height == 1, "expected 1, got %d\n", data.Height);
4350 ok(data.Stride == 8, "expected 8, got %d\n", data.Stride);
4351 ok(data.PixelFormat == PixelFormat24bppRGB, "expected PixelFormat24bppRGB, got %d\n", data.PixelFormat);
4352 match = !memcmp(data.Scan0, rgb24, sizeof(rgb24));
4353 ok(match, "bits don't match\n");
4354 if (!match)
4355 {
4356 bits = data.Scan0;
4357 trace("format %#x, bits %02x,%02x,%02x,%02x %02x,%02x,%02x,%02x\n", PixelFormat24bppRGB,
4358 bits[0], bits[1], bits[2], bits[3], bits[4], bits[5], bits[6], bits[7]);
4359 }
4360 status = GdipBitmapUnlockBits(bitmap, &data);
4361 expect(Ok, status);
4362
4363 GdipDisposeImage((GpImage *)bitmap);
4364 }
4365
4366
4367 static void test_CloneBitmapArea(void)
4368 {
4369 GpStatus status;
4370 GpBitmap *bitmap, *copy;
4371 BitmapData data, data2;
4372
4373 status = GdipCreateBitmapFromScan0(1, 1, 0, PixelFormat24bppRGB, NULL, &bitmap);
4374 expect(Ok, status);
4375
4376 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead | ImageLockModeWrite, PixelFormat24bppRGB, &data);
4377 expect(Ok, status);
4378
4379 status = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, PixelFormat24bppRGB, &data2);
4380 expect(WrongState, status);
4381
4382 status = GdipCloneBitmapAreaI(0, 0, 1, 1, PixelFormat24bppRGB, bitmap, &copy);
4383 expect(Ok, status);
4384
4385 status = GdipBitmapUnlockBits(bitmap, &data);
4386 expect(Ok, status);
4387
4388 GdipDisposeImage((GpImage *)copy);
4389 GdipDisposeImage((GpImage *)bitmap);
4390 }
4391
4392 START_TEST(image)
4393 {
4394 struct GdiplusStartupInput gdiplusStartupInput;
4395 ULONG_PTR gdiplusToken;
4396
4397 gdiplusStartupInput.GdiplusVersion = 1;
4398 gdiplusStartupInput.DebugEventCallback = NULL;
4399 gdiplusStartupInput.SuppressBackgroundThread = 0;
4400 gdiplusStartupInput.SuppressExternalCodecs = 0;
4401
4402 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
4403
4404 test_CloneBitmapArea();
4405 test_ARGB_conversion();
4406 test_DrawImage_scale();
4407 test_image_format();
4408 test_DrawImage();
4409 test_GdipDrawImagePointRect();
4410 test_bitmapbits();
4411 test_tiff_palette();
4412 test_GdipGetAllPropertyItems();
4413 test_tiff_properties();
4414 test_gif_properties();
4415 test_image_properties();
4416 test_Scan0();
4417 test_FromGdiDib();
4418 test_GetImageDimension();
4419 test_GdipImageGetFrameDimensionsCount();
4420 test_LoadingImages();
4421 test_SavingImages();
4422 test_encoders();
4423 test_LockBits();
4424 test_LockBits_UserBuf();
4425 test_GdipCreateBitmapFromHBITMAP();
4426 test_GdipGetImageFlags();
4427 test_GdipCloneImage();
4428 test_testcontrol();
4429 test_fromhicon();
4430 test_getrawformat();
4431 test_loadwmf();
4432 test_createfromwmf();
4433 test_resolution();
4434 test_createhbitmap();
4435 test_getthumbnail();
4436 test_getsetpixel();
4437 test_palette();
4438 test_colormatrix();
4439 test_gamma();
4440 test_multiframegif();
4441 test_rotateflip();
4442 test_remaptable();
4443 test_colorkey();
4444 test_dispose();
4445
4446 GdiplusShutdown(gdiplusToken);
4447 }