ReactOS 0.4.17-dev-218-g5635d24
image.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Google (Evan Stade)
3 * Copyright (C) 2012,2016 Dmitry Timoshkov
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20#include <stdarg.h>
21#include <assert.h>
22
23#include "windef.h"
24#include "winbase.h"
25#include "winuser.h"
26#include "wingdi.h"
27
28#define COBJMACROS
29#include "objbase.h"
30#include "olectl.h"
31#include "ole2.h"
32
33#include "initguid.h"
34#include "wincodec.h"
35#include "gdiplus.h"
36#include "gdiplus_private.h"
37#include "wine/debug.h"
38
40
42
43#define WMF_PLACEABLE_KEY 0x9ac6cdd7
44
45static const struct
46{
49 /* predefined palette type to use for pixel format conversions */
51} pixel_formats[] =
52{
53 { &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
54 { &GUID_WICPixelFormatBlackWhite, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
55 { &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 },
56 { &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 },
57 { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 },
58 { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, 0 },
59 { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, 0 },
60 { &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, 0 },
61 { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, 0 },
62 { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, 0 },
63 { NULL }
64};
65
67{
68 HRESULT hr;
70 IWICPalette *wic_palette;
72
73 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
74 if (hr != S_OK) return NULL;
75
76 hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
77 if (hr == S_OK)
78 {
80 if (frame)
81 hr = IWICBitmapFrameDecode_CopyPalette(frame, wic_palette);
82 if (hr != S_OK && palette_type != 0)
83 {
84 TRACE("using predefined palette %#x\n", palette_type);
85 hr = IWICPalette_InitializePredefined(wic_palette, palette_type, FALSE);
86 }
87 if (hr == S_OK)
88 {
90 BOOL alpha;
91 UINT count;
92
93 IWICPalette_GetColorCount(wic_palette, &count);
94 palette = malloc(2 * sizeof(UINT) + count * sizeof(ARGB));
95 IWICPalette_GetColors(wic_palette, count, (UINT *)palette->Entries, &palette->Count);
96
97 IWICPalette_GetType(wic_palette, &type);
98 switch(type) {
103 break;
112 break;
113 default:
114 palette->Flags = 0;
115 }
116 IWICPalette_HasAlpha(wic_palette, &alpha);
117 if(alpha)
119 }
120 IWICPalette_Release(wic_palette);
121 }
122 IWICImagingFactory_Release(factory);
123 return palette;
124}
125
127{
128 HRESULT hr;
130 IWICPalette *wic_palette;
131
132 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
133 if (FAILED(hr))
134 return hr;
135
136 hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
137 IWICImagingFactory_Release(factory);
138 if (SUCCEEDED(hr))
139 {
140 hr = IWICPalette_InitializeCustom(wic_palette, (UINT *)palette->Entries, palette->Count);
141
142 if (SUCCEEDED(hr))
143 hr = IWICBitmapFrameEncode_SetPalette(frame, wic_palette);
144
145 IWICPalette_Release(wic_palette);
146 }
147
148 return hr;
149}
150
152 RECT* roi, BOOL useAuxData, VOID** auxData, INT* auxDataSize)
153{
154 FIXME("(%p %p %p %d %p %p): stub\n", bitmap, effect, roi, useAuxData, auxData, auxDataSize);
155 /*
156 * Note: According to Jose Roca's GDI+ docs, this function is not
157 * implemented in Windows's GDI+.
158 */
159 return NotImplemented;
160}
161
163 INT numInputs, CGpEffect* effect, RECT* roi, RECT* outputRect,
164 GpBitmap** outputBitmap, BOOL useAuxData, VOID** auxData, INT* auxDataSize)
165{
166 FIXME("(%p %d %p %p %p %p %d %p %p): stub\n", inputBitmaps, numInputs, effect, roi, outputRect, outputBitmap, useAuxData, auxData, auxDataSize);
167 /*
168 * Note: According to Jose Roca's GDI+ docs, this function is not
169 * implemented in Windows's GDI+.
170 */
171 return NotImplemented;
172}
173
174static inline void getpixel_1bppIndexed(BYTE *index, const BYTE *row, UINT x)
175{
176 *index = (row[x/8]>>(7-x%8)) & 1;
177}
178
179static inline void getpixel_4bppIndexed(BYTE *index, const BYTE *row, UINT x)
180{
181 if (x & 1)
182 *index = row[x/2]&0xf;
183 else
184 *index = row[x/2]>>4;
185}
186
187static inline void getpixel_8bppIndexed(BYTE *index, const BYTE *row, UINT x)
188{
189 *index = row[x];
190}
191
192static inline void getpixel_16bppGrayScale(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
193 const BYTE *row, UINT x)
194{
195 *r = *g = *b = row[x*2+1];
196 *a = 255;
197}
198
199static inline void getpixel_16bppRGB555(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
200 const BYTE *row, UINT x)
201{
202 WORD pixel = *((const WORD*)(row)+x);
203 *r = (pixel>>7&0xf8)|(pixel>>12&0x7);
204 *g = (pixel>>2&0xf8)|(pixel>>6&0x7);
205 *b = (pixel<<3&0xf8)|(pixel>>2&0x7);
206 *a = 255;
207}
208
209static inline void getpixel_16bppRGB565(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
210 const BYTE *row, UINT x)
211{
212 WORD pixel = *((const WORD*)(row)+x);
213 *r = (pixel>>8&0xf8)|(pixel>>13&0x7);
214 *g = (pixel>>3&0xfc)|(pixel>>9&0x3);
215 *b = (pixel<<3&0xf8)|(pixel>>2&0x7);
216 *a = 255;
217}
218
219static inline void getpixel_16bppARGB1555(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
220 const BYTE *row, UINT x)
221{
222 WORD pixel = *((const WORD*)(row)+x);
223 *r = (pixel>>7&0xf8)|(pixel>>12&0x7);
224 *g = (pixel>>2&0xf8)|(pixel>>6&0x7);
225 *b = (pixel<<3&0xf8)|(pixel>>2&0x7);
226 if ((pixel&0x8000) == 0x8000)
227 *a = 255;
228 else
229 *a = 0;
230}
231
232static inline void getpixel_24bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
233 const BYTE *row, UINT x)
234{
235 *r = row[x*3+2];
236 *g = row[x*3+1];
237 *b = row[x*3];
238 *a = 255;
239}
240
241static inline void getpixel_32bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
242 const BYTE *row, UINT x)
243{
244 *r = row[x*4+2];
245 *g = row[x*4+1];
246 *b = row[x*4];
247 *a = 255;
248}
249
250static inline void getpixel_32bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
251 const BYTE *row, UINT x)
252{
253 *r = row[x*4+2];
254 *g = row[x*4+1];
255 *b = row[x*4];
256 *a = row[x*4+3];
257}
258
259static inline void getpixel_32bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
260 const BYTE *row, UINT x)
261{
262 *a = row[x*4+3];
263 if (*a == 0)
264 {
265 *r = row[x*4+2];
266 *g = row[x*4+1];
267 *b = row[x*4];
268 }
269 else
270 {
271 DWORD scaled_q = (255 << 15) / *a;
272 *r = (row[x*4+2] > *a) ? 0xff : (row[x*4+2] * scaled_q) >> 15;
273 *g = (row[x*4+1] > *a) ? 0xff : (row[x*4+1] * scaled_q) >> 15;
274 *b = (row[x*4] > *a) ? 0xff : (row[x*4] * scaled_q) >> 15;
275 }
276}
277
278static inline void getpixel_48bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
279 const BYTE *row, UINT x)
280{
281 *r = row[x*6+5];
282 *g = row[x*6+3];
283 *b = row[x*6+1];
284 *a = 255;
285}
286
287static inline void getpixel_64bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
288 const BYTE *row, UINT x)
289{
290 *r = row[x*8+5];
291 *g = row[x*8+3];
292 *b = row[x*8+1];
293 *a = row[x*8+7];
294}
295
296static inline void getpixel_64bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
297 const BYTE *row, UINT x)
298{
299 *a = row[x*8+7];
300 if (*a == 0)
301 *r = *g = *b = 0;
302 else
303 {
304 *r = row[x*8+5] * 255 / *a;
305 *g = row[x*8+3] * 255 / *a;
306 *b = row[x*8+1] * 255 / *a;
307 }
308}
309
311 ARGB *color)
312{
313 BYTE r, g, b, a;
314 BYTE index;
315 BYTE *row;
316
317 if(!bitmap || !color ||
318 x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
319 return InvalidParameter;
320
321 row = bitmap->bits+bitmap->stride*y;
322
323 switch (bitmap->format)
324 {
327 break;
330 break;
333 break;
336 break;
339 break;
342 break;
345 break;
347 getpixel_24bppRGB(&r,&g,&b,&a,row,x);
348 break;
350 getpixel_32bppRGB(&r,&g,&b,&a,row,x);
351 break;
354 break;
357 break;
359 getpixel_48bppRGB(&r,&g,&b,&a,row,x);
360 break;
363 break;
366 break;
367 default:
368 FIXME("not implemented for format 0x%x\n", bitmap->format);
369 return NotImplemented;
370 }
371
372 if (bitmap->format & PixelFormatIndexed)
373 *color = bitmap->image.palette->Entries[index];
374 else
375 *color = a<<24|r<<16|g<<8|b;
376
377 return Ok;
378}
379
380static unsigned int absdiff(unsigned int x, unsigned int y)
381{
382 return x > y ? x - y : y - x;
383}
384
386{
387 BYTE index = 0;
388 int best_distance = 0x7fff;
389 int distance;
390 UINT i;
391
392 if (!palette) return 0;
393 /* This algorithm scans entire palette,
394 computes difference from desired color (all color components have equal weight)
395 and returns the index of color with least difference.
396
397 Note: Maybe it could be replaced with a better algorithm for better image quality
398 and performance, though better algorithm would probably need some pre-built lookup
399 tables and thus may actually be slower if this method is called only few times per
400 every image.
401 */
402 for(i=0;i<palette->Count;i++) {
403 ARGB color=palette->Entries[i];
404 distance=absdiff(b, color & 0xff) + absdiff(g, color>>8 & 0xff) + absdiff(r, color>>16 & 0xff) + absdiff(a, color>>24 & 0xff);
405 if (distance<best_distance) {
406 best_distance=distance;
407 index=i;
408 }
409 }
410 return index;
411}
412
413static inline void setpixel_8bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a,
415{
417 row[x]=index;
418}
419
420static inline void setpixel_1bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a,
422{
423 row[x/8] = (row[x/8] & ~(1<<(7-x%8))) | (get_palette_index(r,g,b,a,palette)<<(7-x%8));
424}
425
426static inline void setpixel_4bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a,
428{
429 if (x & 1)
430 row[x/2] = (row[x/2] & 0xf0) | get_palette_index(r,g,b,a,palette);
431 else
432 row[x/2] = (row[x/2] & 0x0f) | get_palette_index(r,g,b,a,palette)<<4;
433}
434
436 BYTE *row, UINT x)
437{
438 *((WORD*)(row)+x) = (r+g+b)*85;
439}
440
441static inline void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a,
442 BYTE *row, UINT x)
443{
444 *((WORD*)(row)+x) = (r<<7&0x7c00)|
445 (g<<2&0x03e0)|
446 (b>>3&0x001f);
447}
448
449static inline void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a,
450 BYTE *row, UINT x)
451{
452 *((WORD*)(row)+x) = (r<<8&0xf800)|
453 (g<<3&0x07e0)|
454 (b>>3&0x001f);
455}
456
457static inline void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a,
458 BYTE *row, UINT x)
459{
460 *((WORD*)(row)+x) = (a<<8&0x8000)|
461 (r<<7&0x7c00)|
462 (g<<2&0x03e0)|
463 (b>>3&0x001f);
464}
465
466static inline void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
467 BYTE *row, UINT x)
468{
469 row[x*3+2] = r;
470 row[x*3+1] = g;
471 row[x*3] = b;
472}
473
474static inline void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
475 BYTE *row, UINT x)
476{
477 *((DWORD*)(row)+x) = (r<<16)|(g<<8)|b;
478}
479
480static inline void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
481 BYTE *row, UINT x)
482{
483 *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
484}
485
486static inline void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
487 BYTE *row, UINT x)
488{
489 r = (r * a + 127) / 255;
490 g = (g * a + 127) / 255;
491 b = (b * a + 127) / 255;
492 *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
493}
494
495static inline void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
496 BYTE *row, UINT x)
497{
498 row[x*6+5] = row[x*6+4] = r;
499 row[x*6+3] = row[x*6+2] = g;
500 row[x*6+1] = row[x*6] = b;
501}
502
503static inline void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
504 BYTE *row, UINT x)
505{
506 UINT64 a64=a, r64=r, g64=g, b64=b;
507 *((UINT64*)(row)+x) = (a64<<56)|(a64<<48)|(r64<<40)|(r64<<32)|(g64<<24)|(g64<<16)|(b64<<8)|b64;
508}
509
510static inline void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
511 BYTE *row, UINT x)
512{
513 UINT64 a64, r64, g64, b64;
514 a64 = a * 257;
515 r64 = r * a / 255;
516 g64 = g * a / 255;
517 b64 = b * a / 255;
518 *((UINT64*)(row)+x) = (a64<<48)|(r64<<32)|(g64<<16)|b64;
519}
520
522 ARGB color)
523{
524 BYTE a, r, g, b;
525 BYTE *row;
526
527 if(!bitmap || x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
528 return InvalidParameter;
529
530 a = color>>24;
531 r = color>>16;
532 g = color>>8;
533 b = color;
534
535 row = bitmap->bits + bitmap->stride * y;
536
537 switch (bitmap->format)
538 {
541 break;
544 break;
547 break;
550 break;
553 break;
556 break;
559 break;
562 break;
565 break;
568 break;
571 break;
573 setpixel_8bppIndexed(r,g,b,a,row,x,bitmap->image.palette);
574 break;
576 setpixel_4bppIndexed(r,g,b,a,row,x,bitmap->image.palette);
577 break;
579 setpixel_1bppIndexed(r,g,b,a,row,x,bitmap->image.palette);
580 break;
581 default:
582 FIXME("not implemented for format 0x%x\n", bitmap->format);
583 return NotImplemented;
584 }
585
586 return Ok;
587}
588
590 INT dst_stride, BYTE *dst_bits, PixelFormat dst_format,
591 ColorPalette *dst_palette,
592 INT src_stride, const BYTE *src_bits, PixelFormat src_format,
593 ColorPalette *src_palette)
594{
595 INT x, y;
596
597 if (src_format == dst_format ||
598 (dst_format == PixelFormat32bppRGB && PIXELFORMATBPP(src_format) == 32))
599 {
600 UINT widthbytes = PIXELFORMATBPP(src_format) * width / 8;
601 for (y=0; y<height; y++)
602 memcpy(dst_bits+dst_stride*y, src_bits+src_stride*y, widthbytes);
603 return Ok;
604 }
605
606#define convert_indexed_to_rgb(getpixel_function, setpixel_function) do { \
607 for (y=0; y<height; y++) \
608 for (x=0; x<width; x++) { \
609 BYTE index; \
610 ARGB argb; \
611 BYTE *color = (BYTE *)&argb; \
612 getpixel_function(&index, src_bits+src_stride*y, x); \
613 argb = (src_palette && index < src_palette->Count) ? src_palette->Entries[index] : 0; \
614 setpixel_function(color[2], color[1], color[0], color[3], dst_bits+dst_stride*y, x); \
615 } \
616 return Ok; \
617} while (0);
618
619#define convert_indexed_to_indexed(getpixel_function, setpixel_function) do { \
620 for (y=0; y<height; y++) \
621 for (x=0; x<width; x++) { \
622 BYTE index; \
623 ARGB argb; \
624 BYTE *color = (BYTE *)&argb; \
625 getpixel_function(&index, src_bits+src_stride*y, x); \
626 argb = (src_palette && index < src_palette->Count) ? src_palette->Entries[index] : 0; \
627 setpixel_function(color[2], color[1], color[0], color[3], dst_bits+dst_stride*y, x, dst_palette); \
628 } \
629 return Ok; \
630} while (0);
631
632#define convert_rgb_to_rgb(getpixel_function, setpixel_function) do { \
633 for (y=0; y<height; y++) \
634 for (x=0; x<width; x++) { \
635 BYTE r, g, b, a; \
636 getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
637 setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x); \
638 } \
639 return Ok; \
640} while (0);
641
642#define convert_rgb_to_indexed(getpixel_function, setpixel_function) do { \
643 for (y=0; y<height; y++) \
644 for (x=0; x<width; x++) { \
645 BYTE r, g, b, a; \
646 getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
647 setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x, dst_palette); \
648 } \
649 return Ok; \
650} while (0);
651
652 switch (src_format)
653 {
655 switch (dst_format)
656 {
681 default:
682 break;
683 }
684 break;
686 switch (dst_format)
687 {
712 default:
713 break;
714 }
715 break;
717 switch (dst_format)
718 {
743 default:
744 break;
745 }
746 break;
748 switch (dst_format)
749 {
774 default:
775 break;
776 }
777 break;
779 switch (dst_format)
780 {
805 default:
806 break;
807 }
808 break;
810 switch (dst_format)
811 {
836 default:
837 break;
838 }
839 break;
841 switch (dst_format)
842 {
867 default:
868 break;
869 }
870 break;
872 switch (dst_format)
873 {
898 default:
899 break;
900 }
901 break;
903 switch (dst_format)
904 {
929 default:
930 break;
931 }
932 break;
934 switch (dst_format)
935 {
953 convert_32bppARGB_to_32bppPARGB(width, height, dst_bits, dst_stride, src_bits, src_stride);
954 return Ok;
959 default:
960 break;
961 }
962 break;
964 switch (dst_format)
965 {
990 default:
991 break;
992 }
993 break;
995 switch (dst_format)
996 {
1021 default:
1022 break;
1023 }
1024 break;
1026 switch (dst_format)
1027 {
1052 default:
1053 break;
1054 }
1055 break;
1057 switch (dst_format)
1058 {
1085 default:
1086 break;
1087 }
1088 break;
1089 default:
1090 break;
1091 }
1092
1093#undef convert_indexed_to_rgb
1094#undef convert_indexed_to_indexed
1095#undef convert_rgb_to_rgb
1096#undef convert_rgb_to_indexed
1097
1098 return NotImplemented;
1099}
1100
1101/* This function returns a pointer to an array of pixels that represents the
1102 * bitmap. The *entire* bitmap is locked according to the lock mode specified by
1103 * flags. It is correct behavior that a user who calls this function with write
1104 * privileges can write to the whole bitmap (not just the area in rect).
1105 *
1106 * FIXME: only used portion of format is bits per pixel. */
1108 UINT flags, PixelFormat format, BitmapData* lockeddata)
1109{
1110 INT bitspp = PIXELFORMATBPP(format);
1111 GpRect act_rect; /* actual rect to be used */
1112 GpStatus stat;
1113
1114 TRACE("%p %p %d 0x%x %p\n", bitmap, rect, flags, format, lockeddata);
1115
1116 if(!lockeddata || !bitmap)
1117 return InvalidParameter;
1118 if(!image_lock(&bitmap->image))
1119 return ObjectBusy;
1120
1121 if(rect){
1122 if(rect->X < 0 || rect->Y < 0 || (rect->X + rect->Width > bitmap->width) ||
1123 (rect->Y + rect->Height > bitmap->height) || !flags)
1124 {
1125 image_unlock(&bitmap->image);
1126 return InvalidParameter;
1127 }
1128
1129 act_rect = *rect;
1130 }
1131 else{
1132 act_rect.X = act_rect.Y = 0;
1133 act_rect.Width = bitmap->width;
1134 act_rect.Height = bitmap->height;
1135 }
1136
1137 if(bitmap->lockmode)
1138 {
1139 WARN("bitmap is already locked and cannot be locked again\n");
1140 image_unlock(&bitmap->image);
1141 return WrongState;
1142 }
1143
1144 if (bitmap->bits && bitmap->format == format && !(flags & ImageLockModeUserInputBuf))
1145 {
1146 /* no conversion is necessary; just use the bits directly */
1147 lockeddata->Width = act_rect.Width;
1148 lockeddata->Height = act_rect.Height;
1149 lockeddata->PixelFormat = format;
1150 lockeddata->Reserved = flags;
1151 lockeddata->Stride = bitmap->stride;
1152 lockeddata->Scan0 = bitmap->bits + (bitspp / 8) * act_rect.X +
1153 bitmap->stride * act_rect.Y;
1154
1155 bitmap->lockmode = flags | ImageLockModeRead;
1156
1157 image_unlock(&bitmap->image);
1158 return Ok;
1159 }
1160
1161 /* Make sure we can convert to the requested format. */
1163 {
1164 stat = convert_pixels(0, 0, 0, NULL, format, NULL, 0, NULL, bitmap->format, NULL);
1165 if (stat == NotImplemented)
1166 {
1167 FIXME("cannot read bitmap from %x to %x\n", bitmap->format, format);
1168 image_unlock(&bitmap->image);
1169 return NotImplemented;
1170 }
1171 }
1172
1173 /* If we're opening for writing, make sure we'll be able to write back in
1174 * the original format. */
1176 {
1177 stat = convert_pixels(0, 0, 0, NULL, bitmap->format, NULL, 0, NULL, format, NULL);
1178 if (stat == NotImplemented)
1179 {
1180 FIXME("cannot write bitmap from %x to %x\n", format, bitmap->format);
1181 image_unlock(&bitmap->image);
1182 return NotImplemented;
1183 }
1184 }
1185
1186 lockeddata->Width = act_rect.Width;
1187 lockeddata->Height = act_rect.Height;
1188 lockeddata->PixelFormat = format;
1189 lockeddata->Reserved = flags;
1190
1192 {
1193 lockeddata->Stride = (((act_rect.Width * bitspp + 7) / 8) + 3) & ~3;
1194
1195 bitmap->bitmapbits = calloc(lockeddata->Stride, act_rect.Height);
1196
1197 if (!bitmap->bitmapbits)
1198 {
1199 image_unlock(&bitmap->image);
1200 return OutOfMemory;
1201 }
1202
1203 lockeddata->Scan0 = bitmap->bitmapbits;
1204 }
1205
1207 {
1208 static BOOL fixme = FALSE;
1209
1210 if (!fixme && (PIXELFORMATBPP(bitmap->format) * act_rect.X) % 8 != 0)
1211 {
1212 FIXME("Cannot copy rows that don't start at a whole byte.\n");
1213 fixme = TRUE;
1214 }
1215
1216 stat = convert_pixels(act_rect.Width, act_rect.Height,
1217 lockeddata->Stride, lockeddata->Scan0, format, bitmap->image.palette,
1218 bitmap->stride,
1219 bitmap->bits + bitmap->stride * act_rect.Y + PIXELFORMATBPP(bitmap->format) * act_rect.X / 8,
1220 bitmap->format, bitmap->image.palette);
1221
1222 if (stat != Ok)
1223 {
1224 free(bitmap->bitmapbits);
1225 bitmap->bitmapbits = NULL;
1226 image_unlock(&bitmap->image);
1227 return stat;
1228 }
1229 }
1230
1231 bitmap->lockmode = flags | ImageLockModeRead;
1232 bitmap->lockx = act_rect.X;
1233 bitmap->locky = act_rect.Y;
1234
1235 image_unlock(&bitmap->image);
1236 return Ok;
1237}
1238
1240{
1241 TRACE("(%p, %.2f, %.2f)\n", bitmap, xdpi, ydpi);
1242
1243 if (!bitmap || xdpi == 0.0 || ydpi == 0.0)
1244 return InvalidParameter;
1245
1246 bitmap->image.xres = xdpi;
1247 bitmap->image.yres = ydpi;
1248
1249 return Ok;
1250}
1251
1253 BitmapData* lockeddata)
1254{
1255 GpStatus stat;
1256 static BOOL fixme = FALSE;
1257
1258 TRACE("(%p,%p)\n", bitmap, lockeddata);
1259
1260 if(!bitmap || !lockeddata)
1261 return InvalidParameter;
1262 if(!image_lock(&bitmap->image))
1263 return ObjectBusy;
1264
1265 if(!bitmap->lockmode)
1266 {
1267 image_unlock(&bitmap->image);
1268 return WrongState;
1269 }
1270
1271 if(!(lockeddata->Reserved & ImageLockModeWrite)){
1272 bitmap->lockmode = 0;
1273 free(bitmap->bitmapbits);
1274 bitmap->bitmapbits = NULL;
1275 image_unlock(&bitmap->image);
1276 return Ok;
1277 }
1278
1279 if (!bitmap->bitmapbits && !(lockeddata->Reserved & ImageLockModeUserInputBuf))
1280 {
1281 /* we passed a direct reference; no need to do anything */
1282 bitmap->lockmode = 0;
1283 image_unlock(&bitmap->image);
1284 return Ok;
1285 }
1286
1287 if (!fixme && (PIXELFORMATBPP(bitmap->format) * bitmap->lockx) % 8 != 0)
1288 {
1289 FIXME("Cannot copy rows that don't start at a whole byte.\n");
1290 fixme = TRUE;
1291 }
1292
1293 /* FIXME: Pass src_palette generated from lockeddata->PixelFormat. */
1294 stat = convert_pixels(lockeddata->Width, lockeddata->Height,
1295 bitmap->stride,
1296 bitmap->bits + bitmap->stride * bitmap->locky + PIXELFORMATBPP(bitmap->format) * bitmap->lockx / 8,
1297 bitmap->format, bitmap->image.palette,
1298 lockeddata->Stride, lockeddata->Scan0, lockeddata->PixelFormat, NULL);
1299
1300 if (stat != Ok)
1301 {
1302 ERR("failed to convert pixels; this should never happen\n");
1303 }
1304
1305 free(bitmap->bitmapbits);
1306 bitmap->bitmapbits = NULL;
1307 bitmap->lockmode = 0;
1308
1309 image_unlock(&bitmap->image);
1310 return stat;
1311}
1312
1314 PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap)
1315{
1316 Rect area;
1317 GpStatus stat;
1318
1319 TRACE("(%f,%f,%f,%f,0x%x,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap);
1320
1321 if (!srcBitmap || !dstBitmap || srcBitmap->image.type != ImageTypeBitmap ||
1322 x < 0 || y < 0 ||
1323 x + width > srcBitmap->width || y + height > srcBitmap->height)
1324 {
1325 TRACE("<-- InvalidParameter\n");
1326 return InvalidParameter;
1327 }
1328
1330 format = srcBitmap->format;
1331
1332 area.X = gdip_round(x);
1333 area.Y = gdip_round(y);
1334 area.Width = gdip_round(width);
1335 area.Height = gdip_round(height);
1336
1337 stat = GdipCreateBitmapFromScan0(area.Width, area.Height, 0, format, NULL, dstBitmap);
1338 if (stat == Ok)
1339 {
1340 memcpy(&(*dstBitmap)->image.format, &srcBitmap->image.format, sizeof(GUID));
1341 stat = convert_pixels(area.Width, area.Height, (*dstBitmap)->stride, (*dstBitmap)->bits, (*dstBitmap)->format,
1342 (*dstBitmap)->image.palette, srcBitmap->stride,
1343 srcBitmap->bits + srcBitmap->stride * area.Y + PIXELFORMATBPP(srcBitmap->format) * area.X / 8,
1344 srcBitmap->format, srcBitmap->image.palette);
1345
1346 if (stat == Ok && srcBitmap->image.palette)
1347 {
1348 ColorPalette *src_palette, *dst_palette;
1349
1350 src_palette = srcBitmap->image.palette;
1351
1352 dst_palette = calloc(1, sizeof(UINT) * 2 + sizeof(ARGB) * src_palette->Count);
1353
1354 if (dst_palette)
1355 {
1356 dst_palette->Flags = src_palette->Flags;
1357 dst_palette->Count = src_palette->Count;
1358 memcpy(dst_palette->Entries, src_palette->Entries, sizeof(ARGB) * src_palette->Count);
1359
1360 free((*dstBitmap)->image.palette);
1361 (*dstBitmap)->image.palette = dst_palette;
1362 }
1363 else
1364 stat = OutOfMemory;
1365 }
1366
1367 if (stat != Ok)
1368 GdipDisposeImage(&(*dstBitmap)->image);
1369 }
1370
1371 if (stat != Ok)
1372 *dstBitmap = NULL;
1373
1374 return stat;
1375}
1376
1378 PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap)
1379{
1380 TRACE("(%i,%i,%i,%i,0x%x,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap);
1381
1382 return GdipCloneBitmapArea(x, y, width, height, format, srcBitmap, dstBitmap);
1383}
1384
1386{
1387 TRACE("%p, %p\n", image, cloneImage);
1388
1389 if (!image || !cloneImage)
1390 return InvalidParameter;
1391
1392 if (image->type == ImageTypeBitmap)
1393 {
1395
1397 bitmap->format, bitmap, (GpBitmap **)cloneImage);
1398 }
1399 else if (image->type == ImageTypeMetafile && ((GpMetafile*)image)->hemf)
1400 {
1402
1404
1405 result = calloc(1, sizeof(*result));
1406 if (!result)
1407 return OutOfMemory;
1408
1409 result->image.type = ImageTypeMetafile;
1410 result->image.format = image->format;
1411 result->image.flags = image->flags;
1412 result->image.frame_count = 1;
1413 result->image.xres = image->xres;
1414 result->image.yres = image->yres;
1415 result->bounds = metafile->bounds;
1416 result->unit = metafile->unit;
1417 result->metafile_type = metafile->metafile_type;
1418 result->hemf = CopyEnhMetaFileW(metafile->hemf, NULL);
1419 list_init(&result->containers);
1420
1421 if (!result->hemf)
1422 {
1423 free(result);
1424 return OutOfMemory;
1425 }
1426
1427 *cloneImage = &result->image;
1428 return Ok;
1429 }
1430 else
1431 {
1432 WARN("GpImage with no image data (metafile in wrong state?)\n");
1433 return InvalidParameter;
1434 }
1435}
1436
1438 GpBitmap **bitmap)
1439{
1440 GpStatus stat;
1441 IStream *stream;
1442
1443 TRACE("(%s) %p\n", debugstr_w(filename), bitmap);
1444
1445 if(!filename || !bitmap)
1446 return InvalidParameter;
1447
1448 *bitmap = NULL;
1449
1451
1452 if(stat != Ok)
1453 return stat;
1454
1456
1457 IStream_Release(stream);
1458
1459 return stat;
1460}
1461
1464{
1466 HBITMAP hbm;
1467 void *bmbits;
1469
1470 TRACE("(%p, %p, %p)\n", info, bits, bitmap);
1471
1472 if (!info || !bits || !bitmap)
1473 return InvalidParameter;
1474
1475 hbm = CreateDIBSection(0, info, DIB_RGB_COLORS, &bmbits, NULL, 0);
1476 if (!hbm)
1477 return InvalidParameter;
1478
1479 height = abs(info->bmiHeader.biHeight);
1480 stride = ((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) >> 3) & ~3;
1481 TRACE("height %lu, stride %lu, image size %lu\n", height, stride, height * stride);
1482
1483 memcpy(bmbits, bits, height * stride);
1484
1487
1488 return status;
1489}
1490
1491/* FIXME: no icm */
1493 GpBitmap **bitmap)
1494{
1495 TRACE("(%s) %p\n", debugstr_w(filename), bitmap);
1496
1498}
1499
1501 GDIPCONST WCHAR* lpBitmapName, GpBitmap** bitmap)
1502{
1503 HBITMAP hbm;
1505
1506 TRACE("%p (%s) %p\n", hInstance, debugstr_w(lpBitmapName), bitmap);
1507
1508 if(!lpBitmapName || !bitmap)
1509 return InvalidParameter;
1510
1511 /* load DIB */
1512 hbm = LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0,
1514
1515 if(hbm){
1518 }
1519
1520 return stat;
1521}
1522
1524{
1525 BYTE b = (BYTE)src;
1526 BYTE g = (BYTE)(src >> 8);
1527 BYTE r = (BYTE)(src >> 16);
1528 DWORD alpha = (BYTE)(src >> 24);
1529 return ((b + ((BYTE)bkgnd * (255 - alpha) + 127) / 255) |
1530 (g + ((BYTE)(bkgnd >> 8) * (255 - alpha) + 127) / 255) << 8 |
1531 (r + ((BYTE)(bkgnd >> 16) * (255 - alpha) + 127) / 255) << 16 |
1532 (alpha << 24));
1533}
1534
1536 HBITMAP* hbmReturn, ARGB background)
1537{
1538 GpStatus stat;
1540 UINT width, height;
1541 BITMAPINFOHEADER bih;
1542 LPBYTE bits;
1543
1544 TRACE("(%p,%p,%lx)\n", bitmap, hbmReturn, background);
1545
1546 if (!bitmap || !hbmReturn) return InvalidParameter;
1547 if (!image_lock(&bitmap->image)) return ObjectBusy;
1548
1549 GdipGetImageWidth(&bitmap->image, &width);
1550 GdipGetImageHeight(&bitmap->image, &height);
1551
1552 bih.biSize = sizeof(bih);
1553 bih.biWidth = width;
1554 bih.biHeight = height;
1555 bih.biPlanes = 1;
1556 bih.biBitCount = 32;
1557 bih.biCompression = BI_RGB;
1558 bih.biSizeImage = 0;
1559 bih.biXPelsPerMeter = 0;
1560 bih.biYPelsPerMeter = 0;
1561 bih.biClrUsed = 0;
1562 bih.biClrImportant = 0;
1563
1564 result = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1565 if (!result)
1566 {
1567 image_unlock(&bitmap->image);
1568 return GenericError;
1569 }
1570
1572 bits + (width * 4 * (height - 1)), PixelFormat32bppPARGB, bitmap->image.palette,
1573 bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette);
1574 if (stat != Ok)
1575 {
1577 image_unlock(&bitmap->image);
1578 return stat;
1579 }
1580
1581 if (background & 0xffffff)
1582 {
1583 DWORD *ptr;
1584 UINT i;
1585 for (ptr = (DWORD*)bits, i = 0; i < width * height; ptr++, i++)
1586 {
1587 if ((*ptr & 0xff000000) == 0xff000000) continue;
1588 *ptr = blend_argb_no_bkgnd_alpha(*ptr, background);
1589 }
1590 }
1591
1592 *hbmReturn = result;
1593 image_unlock(&bitmap->image);
1594 return Ok;
1595}
1596
1599{
1600 GpStatus ret;
1601
1602 TRACE("(%d, %d, %p, %p)\n", width, height, target, bitmap);
1603
1604 if(!target || !bitmap)
1605 return InvalidParameter;
1606
1608 NULL, bitmap);
1609
1610 if (ret == Ok)
1611 {
1612 GdipGetDpiX(target, &(*bitmap)->image.xres);
1613 GdipGetDpiY(target, &(*bitmap)->image.yres);
1614 }
1615
1616 return ret;
1617}
1618
1620{
1621 GpStatus stat;
1622 ICONINFO iinfo;
1623 BITMAP bm;
1624 int ret;
1626 GpRect rect;
1627 BitmapData lockeddata;
1628 HDC screendc;
1629 int x, y;
1630 BITMAPINFOHEADER bih;
1631 DWORD *src;
1632 BYTE *dst_row;
1633 DWORD *dst;
1634 BYTE *bits;
1635 int mask_scanlines = 0, color_scanlines = 0;
1636
1637 TRACE("%p, %p\n", hicon, bitmap);
1638
1639 if(!bitmap || !GetIconInfo(hicon, &iinfo) || !iinfo.hbmColor || !iinfo.fIcon)
1640 return InvalidParameter;
1641
1642 /* get the size of the icon */
1643 ret = GetObjectA(iinfo.hbmColor, sizeof(bm), &bm);
1644 if (ret == 0) {
1645 DeleteObject(iinfo.hbmColor);
1646 DeleteObject(iinfo.hbmMask);
1647 return GenericError;
1648 }
1649
1650 width = bm.bmWidth;
1651 height = abs(bm.bmHeight);
1652 stride = width * 4;
1653
1655 if (stat != Ok) {
1656 DeleteObject(iinfo.hbmColor);
1657 DeleteObject(iinfo.hbmMask);
1658 return stat;
1659 }
1660
1661 rect.X = 0;
1662 rect.Y = 0;
1663 rect.Width = width;
1664 rect.Height = height;
1665
1667 if (stat != Ok) {
1668 DeleteObject(iinfo.hbmColor);
1669 DeleteObject(iinfo.hbmMask);
1670 GdipDisposeImage(&(*bitmap)->image);
1671 return stat;
1672 }
1673
1674 bih.biSize = sizeof(bih);
1675 bih.biWidth = width;
1676 bih.biHeight = -height;
1677 bih.biPlanes = 1;
1678 bih.biBitCount = 32;
1679 bih.biCompression = BI_RGB;
1680 bih.biSizeImage = 0;
1681 bih.biXPelsPerMeter = 0;
1682 bih.biYPelsPerMeter = 0;
1683 bih.biClrUsed = 0;
1684 bih.biClrImportant = 0;
1685
1686 bits = malloc(height * stride);
1687 if (!bits)
1688 {
1689 DeleteObject(iinfo.hbmColor);
1690 DeleteObject(iinfo.hbmMask);
1691 GdipBitmapUnlockBits(*bitmap, &lockeddata);
1692 GdipDisposeImage(&(*bitmap)->image);
1693 return OutOfMemory;
1694 }
1695
1696 screendc = CreateCompatibleDC(0);
1697 if (screendc)
1698 {
1699 color_scanlines = GetDIBits(screendc, iinfo.hbmColor, 0, height, lockeddata.Scan0,
1700 (BITMAPINFO*)&bih, DIB_RGB_COLORS);
1701 mask_scanlines = GetDIBits(screendc, iinfo.hbmMask, 0, height, bits,
1702 (BITMAPINFO*)&bih, DIB_RGB_COLORS);
1703 DeleteDC(screendc);
1704 }
1705
1706 DeleteObject(iinfo.hbmColor);
1707 DeleteObject(iinfo.hbmMask);
1708
1709 if (!screendc || ((color_scanlines == 0 || mask_scanlines == 0) &&
1711 {
1712 free(bits);
1713 GdipBitmapUnlockBits(*bitmap, &lockeddata);
1714 GdipDisposeImage(&(*bitmap)->image);
1715 return GenericError;
1716 }
1717
1718 src = (DWORD*)bits;
1719 dst_row = lockeddata.Scan0;
1720 for (y=0; y<height; y++)
1721 {
1722 dst = (DWORD*)dst_row;
1723 for (x=0; x<width; x++)
1724 {
1725 DWORD src_value = *src++;
1726 if (src_value)
1727 *dst++ = 0;
1728 else
1729 *dst++ |= 0xff000000;
1730 }
1731 dst_row += lockeddata.Stride;
1732 }
1733
1734 free(bits);
1735
1736 GdipBitmapUnlockBits(*bitmap, &lockeddata);
1737
1738 return Ok;
1739}
1740
1742{
1743 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1744 UINT i;
1745
1746 for (i=0; i<8 && i<count; i++)
1747 {
1748 entries[i] = 0xff000000;
1749 if (i&1) entries[i] |= 0x800000;
1750 if (i&2) entries[i] |= 0x8000;
1751 if (i&4) entries[i] |= 0x80;
1752 }
1753
1754 if (8 < count)
1755 entries[i] = 0xffc0c0c0;
1756
1757 for (i=9; i<16 && i<count; i++)
1758 {
1759 entries[i] = 0xff000000;
1760 if (i&1) entries[i] |= 0xff0000;
1761 if (i&2) entries[i] |= 0xff00;
1762 if (i&4) entries[i] |= 0xff;
1763 }
1764
1765 for (i=16; i<40 && i<count; i++)
1766 {
1767 entries[i] = 0;
1768 }
1769
1770 for (i=40; i<256 && i<count; i++)
1771 {
1772 entries[i] = 0xff000000;
1773 entries[i] |= halftone_values[(i-40)%6];
1774 entries[i] |= halftone_values[((i-40)/6)%6] << 8;
1775 entries[i] |= halftone_values[((i-40)/36)%6] << 16;
1776 }
1777}
1778
1780{
1781 HDC screendc = CreateCompatibleDC(0);
1782
1783 if (!screendc) return GenericError;
1784
1785 *xres = (REAL)GetDeviceCaps(screendc, LOGPIXELSX);
1786 *yres = (REAL)GetDeviceCaps(screendc, LOGPIXELSY);
1787
1788 DeleteDC(screendc);
1789
1790 return Ok;
1791}
1792
1795{
1796 INT row_size;
1797 BYTE *bits=NULL, *own_bits=NULL;
1798 REAL xres, yres;
1799 GpStatus stat;
1800
1801 TRACE("%d %d %d 0x%x %p %p\n", width, height, stride, format, scan0, bitmap);
1802
1803 if (!bitmap) return InvalidParameter;
1804
1805 if(width <= 0 || height <= 0 || (scan0 && (stride % 4))){
1806 *bitmap = NULL;
1807 return InvalidParameter;
1808 }
1809
1810 if(scan0 && !stride)
1811 return InvalidParameter;
1812
1813 stat = get_screen_resolution(&xres, &yres);
1814 if (stat != Ok) return stat;
1815
1816 row_size = (width * PIXELFORMATBPP(format)+7) / 8;
1817
1818 if (scan0)
1819 bits = scan0;
1820 else
1821 {
1822 stride = (row_size + 3) & ~3;
1823
1824 own_bits = bits = calloc(1, stride * height);
1825 if (!own_bits) return OutOfMemory;
1826 }
1827
1828 *bitmap = calloc(1, sizeof(GpBitmap));
1829 if(!*bitmap)
1830 {
1831 free(own_bits);
1832 return OutOfMemory;
1833 }
1834
1835 (*bitmap)->image.type = ImageTypeBitmap;
1836 memcpy(&(*bitmap)->image.format, &ImageFormatMemoryBMP, sizeof(GUID));
1837 (*bitmap)->image.flags = ImageFlagsNone;
1838 (*bitmap)->image.frame_count = 1;
1839 (*bitmap)->image.current_frame = 0;
1840 (*bitmap)->image.palette = NULL;
1841 (*bitmap)->image.xres = xres;
1842 (*bitmap)->image.yres = yres;
1843 (*bitmap)->width = width;
1844 (*bitmap)->height = height;
1845 (*bitmap)->format = format;
1846 (*bitmap)->image.decoder = NULL;
1847 (*bitmap)->image.encoder = NULL;
1848 (*bitmap)->bits = bits;
1849 (*bitmap)->stride = stride;
1850 (*bitmap)->own_bits = own_bits;
1851 (*bitmap)->metadata_reader = NULL;
1852 (*bitmap)->prop_count = 0;
1853 (*bitmap)->prop_item = NULL;
1854
1855 /* set format-related flags */
1857 (*bitmap)->image.flags |= ImageFlagsHasAlpha;
1858
1862 {
1863 (*bitmap)->image.palette = calloc(1, sizeof(UINT) * 2 + sizeof(ARGB) * (1 << PIXELFORMATBPP(format)));
1864
1865 if (!(*bitmap)->image.palette)
1866 {
1867 GdipDisposeImage(&(*bitmap)->image);
1868 *bitmap = NULL;
1869 return OutOfMemory;
1870 }
1871
1872 (*bitmap)->image.palette->Count = 1 << PIXELFORMATBPP(format);
1873
1875 {
1876 (*bitmap)->image.palette->Flags = PaletteFlagsGrayScale;
1877 (*bitmap)->image.palette->Entries[0] = 0xff000000;
1878 (*bitmap)->image.palette->Entries[1] = 0xffffffff;
1879 }
1880 else
1881 {
1883 (*bitmap)->image.palette->Flags = PaletteFlagsHalftone;
1884
1885 generate_halftone_palette((*bitmap)->image.palette->Entries,
1886 (*bitmap)->image.palette->Count);
1887 }
1888 }
1889
1890 TRACE("<-- %p\n", *bitmap);
1891
1892 return Ok;
1893}
1894
1896 GpBitmap **bitmap)
1897{
1898 GpStatus stat;
1899
1900 TRACE("%p %p\n", stream, bitmap);
1901
1903
1904 if(stat != Ok)
1905 return stat;
1906
1907 if((*bitmap)->image.type != ImageTypeBitmap){
1908 GdipDisposeImage(&(*bitmap)->image);
1909 *bitmap = NULL;
1910 return GenericError; /* FIXME: what error to return? */
1911 }
1912
1913 return Ok;
1914}
1915
1916/* FIXME: no icm */
1918 GpBitmap **bitmap)
1919{
1920 TRACE("%p %p\n", stream, bitmap);
1921
1923}
1924
1926 GpCachedBitmap **cachedbmp)
1927{
1928 GpStatus stat;
1929
1930 TRACE("%p %p %p\n", bitmap, graphics, cachedbmp);
1931
1932 if(!bitmap || !graphics || !cachedbmp)
1933 return InvalidParameter;
1934
1935 *cachedbmp = calloc(1, sizeof(GpCachedBitmap));
1936 if(!*cachedbmp)
1937 return OutOfMemory;
1938
1939 stat = GdipCloneImage(&(bitmap->image), &(*cachedbmp)->image);
1940 if(stat != Ok){
1941 free(*cachedbmp);
1942 return stat;
1943 }
1944
1945 return Ok;
1946}
1947
1949{
1950 GpStatus stat;
1951 BitmapData lockeddata;
1952 ULONG andstride, xorstride, bitssize;
1953 LPBYTE andbits, xorbits, androw, xorrow, srcrow;
1954 UINT x, y;
1955
1956 TRACE("(%p, %p)\n", bitmap, hicon);
1957
1958 if (!bitmap || !hicon)
1959 return InvalidParameter;
1960
1962 PixelFormat32bppPARGB, &lockeddata);
1963 if (stat == Ok)
1964 {
1965 andstride = ((lockeddata.Width+31)/32)*4;
1966 xorstride = lockeddata.Width*4;
1967 bitssize = (andstride + xorstride) * lockeddata.Height;
1968
1969 andbits = calloc(1, bitssize);
1970
1971 if (andbits)
1972 {
1973 xorbits = andbits + andstride * lockeddata.Height;
1974
1975 for (y=0; y<lockeddata.Height; y++)
1976 {
1977 srcrow = ((LPBYTE)lockeddata.Scan0) + lockeddata.Stride * y;
1978
1979 androw = andbits + andstride * y;
1980 for (x=0; x<lockeddata.Width; x++)
1981 if (srcrow[3+4*x] >= 128)
1982 androw[x/8] |= 1 << (7-x%8);
1983
1984 xorrow = xorbits + xorstride * y;
1985 memcpy(xorrow, srcrow, xorstride);
1986 }
1987
1988 *hicon = CreateIcon(NULL, lockeddata.Width, lockeddata.Height, 1, 32,
1989 andbits, xorbits);
1990
1991 free(andbits);
1992 }
1993 else
1994 stat = OutOfMemory;
1995
1996 GdipBitmapUnlockBits(bitmap, &lockeddata);
1997 }
1998
1999 return stat;
2000}
2001
2003{
2004 TRACE("%p\n", cachedbmp);
2005
2006 if(!cachedbmp)
2007 return InvalidParameter;
2008
2009 GdipDisposeImage(cachedbmp->image);
2010 free(cachedbmp);
2011
2012 return Ok;
2013}
2014
2016 GpCachedBitmap *cachedbmp, INT x, INT y)
2017{
2018 TRACE("%p %p %d %d\n", graphics, cachedbmp, x, y);
2019
2020 if(!graphics || !cachedbmp)
2021 return InvalidParameter;
2022
2023 return GdipDrawImage(graphics, cachedbmp->image, (REAL)x, (REAL)y);
2024}
2025
2026/* Internal utility function: Replace the image data of dst with that of src,
2027 * and free src. */
2028static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
2029{
2030 assert(src->image.type == ImageTypeBitmap);
2031 assert(dst->image.type == ImageTypeBitmap);
2032
2033 free(dst->bitmapbits);
2034 free(dst->own_bits);
2035
2036 if (clobber_palette)
2037 {
2038 free(dst->image.palette);
2039 dst->image.palette = src->image.palette;
2040 }
2041 else
2042 free(src->image.palette);
2043
2044 dst->image.xres = src->image.xres;
2045 dst->image.yres = src->image.yres;
2046 dst->width = src->width;
2047 dst->height = src->height;
2048 dst->format = src->format;
2049 dst->bits = src->bits;
2050 dst->stride = src->stride;
2051 dst->own_bits = src->own_bits;
2052 if (dst->metadata_reader)
2053 IWICMetadataReader_Release(dst->metadata_reader);
2054 dst->metadata_reader = src->metadata_reader;
2055 free(dst->prop_item);
2056 dst->prop_item = src->prop_item;
2057 dst->prop_count = src->prop_count;
2058 if (dst->image.decoder)
2059 IWICBitmapDecoder_Release(dst->image.decoder);
2060 dst->image.decoder = src->image.decoder;
2061 terminate_encoder_wic(&dst->image); /* terminate active encoder before overwriting with src */
2062 dst->image.encoder = src->image.encoder;
2063 dst->image.frame_count = src->image.frame_count;
2064 dst->image.current_frame = src->image.current_frame;
2065 dst->image.format = src->image.format;
2066
2067 src->image.type = ~0;
2068 free(src);
2069}
2070
2072{
2073 if(!image)
2074 return InvalidParameter;
2075
2076 if (image->type == ImageTypeBitmap)
2077 {
2078 free(((GpBitmap*)image)->bitmapbits);
2079 free(((GpBitmap*)image)->own_bits);
2080 if (((GpBitmap*)image)->metadata_reader)
2081 IWICMetadataReader_Release(((GpBitmap*)image)->metadata_reader);
2082 free(((GpBitmap*)image)->prop_item);
2083 }
2084 else if (image->type == ImageTypeMetafile)
2086 else
2087 {
2088 WARN("invalid image: %p\n", image);
2089 return ObjectBusy;
2090 }
2091 if (image->decoder)
2092 IWICBitmapDecoder_Release(image->decoder);
2094 free(image->palette);
2095
2096 return Ok;
2097}
2098
2100{
2102
2103 TRACE("%p\n", image);
2104
2106 if (status != Ok) return status;
2107 image->type = ~0;
2108 free(image);
2109
2110 return Ok;
2111}
2112
2114{
2115 static int calls;
2116
2117 TRACE("(%p,%p)\n", image, item);
2118
2119 if(!image || !item)
2120 return InvalidParameter;
2121
2122 if (!(calls++))
2123 FIXME("not implemented\n");
2124
2125 return NotImplemented;
2126}
2127
2129{
2130 static int calls;
2131
2132 TRACE("(%p,%p)\n", image, item);
2133
2134 if (!(calls++))
2135 FIXME("not implemented\n");
2136
2137 return NotImplemented;
2138}
2139
2141 GpUnit *srcUnit)
2142{
2143 TRACE("%p %p %p\n", image, srcRect, srcUnit);
2144
2145 if(!image || !srcRect || !srcUnit)
2146 return InvalidParameter;
2147 if(image->type == ImageTypeMetafile){
2148 *srcRect = ((GpMetafile*)image)->bounds;
2149 *srcUnit = ((GpMetafile*)image)->unit;
2150 }
2151 else if(image->type == ImageTypeBitmap){
2152 srcRect->X = srcRect->Y = 0.0;
2153 srcRect->Width = (REAL) ((GpBitmap*)image)->width;
2154 srcRect->Height = (REAL) ((GpBitmap*)image)->height;
2155 *srcUnit = UnitPixel;
2156 }
2157 else{
2158 WARN("GpImage with no image data\n");
2159 return InvalidParameter;
2160 }
2161
2162 TRACE("returning (%f, %f) (%f, %f) unit type %d\n", srcRect->X, srcRect->Y,
2163 srcRect->Width, srcRect->Height, *srcUnit);
2164
2165 return Ok;
2166}
2167
2169 REAL *height)
2170{
2171 TRACE("%p %p %p\n", image, width, height);
2172
2173 if(!image || !height || !width)
2174 return InvalidParameter;
2175
2176 if(image->type == ImageTypeMetafile){
2177 *height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit,
2178 image->yres, ((GpMetafile*)image)->printer_display);
2179 *width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit,
2180 image->xres, ((GpMetafile*)image)->printer_display);
2181 }
2182 else if(image->type == ImageTypeBitmap){
2183 *height = ((GpBitmap*)image)->height;
2184 *width = ((GpBitmap*)image)->width;
2185 }
2186 else{
2187 WARN("GpImage with no image data\n");
2188 return InvalidParameter;
2189 }
2190
2191 TRACE("returning (%f, %f)\n", *height, *width);
2192 return Ok;
2193}
2194
2196 GpGraphics **graphics)
2197{
2198 GpStatus stat;
2199
2200 TRACE("%p %p\n", image, graphics);
2201
2202 if(!image || !graphics)
2203 return InvalidParameter;
2204
2205 if (image->type == ImageTypeMetafile)
2207 else
2208 stat = graphics_from_image(image, graphics);
2209
2210 return stat;
2211}
2212
2214{
2215 TRACE("%p %p\n", image, height);
2216
2217 if(!image || !height)
2218 return InvalidParameter;
2219
2220 if(image->type == ImageTypeMetafile)
2221 *height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit,
2222 image->yres, ((GpMetafile*)image)->printer_display);
2223 else if(image->type == ImageTypeBitmap)
2224 *height = ((GpBitmap*)image)->height;
2225 else
2226 {
2227 WARN("GpImage with no image data\n");
2228 return InvalidParameter;
2229 }
2230
2231 TRACE("returning %d\n", *height);
2232
2233 return Ok;
2234}
2235
2237{
2238 if(!image || !res)
2239 return InvalidParameter;
2240
2241 *res = image->xres;
2242
2243 TRACE("(%p) <-- %0.2f\n", image, *res);
2244
2245 return Ok;
2246}
2247
2249{
2250 TRACE("%p %p\n", image, size);
2251
2252 if(!image || !size)
2253 return InvalidParameter;
2254
2255 if (image->type == ImageTypeMetafile)
2256 {
2257 *size = 0;
2258 return GenericError;
2259 }
2260
2261 if (!image->palette || image->palette->Count == 0)
2262 *size = sizeof(ColorPalette);
2263 else
2264 *size = sizeof(UINT)*2 + sizeof(ARGB)*image->palette->Count;
2265
2266 TRACE("<-- %u\n", *size);
2267
2268 return Ok;
2269}
2270
2271/* FIXME: test this function for non-bitmap types */
2273{
2274 TRACE("%p %p\n", image, format);
2275
2276 if(!image || !format)
2277 return InvalidParameter;
2278
2279 if(image->type != ImageTypeBitmap)
2281 else
2282 *format = ((GpBitmap*) image)->format;
2283
2284 return Ok;
2285}
2286
2288{
2289 TRACE("(%p, %p)\n", image, format);
2290
2291 if(!image || !format)
2292 return InvalidParameter;
2293
2294 memcpy(format, &image->format, sizeof(GUID));
2295
2296 return Ok;
2297}
2298
2300{
2301 TRACE("%p %p\n", image, type);
2302
2303 if(!image || !type)
2304 return InvalidParameter;
2305
2306 *type = image->type;
2307
2308 return Ok;
2309}
2310
2312{
2313 if(!image || !res)
2314 return InvalidParameter;
2315
2316 *res = image->yres;
2317
2318 TRACE("(%p) <-- %0.2f\n", image, *res);
2319
2320 return Ok;
2321}
2322
2324{
2325 TRACE("%p %p\n", image, width);
2326
2327 if(!image || !width)
2328 return InvalidParameter;
2329
2330 if(image->type == ImageTypeMetafile)
2331 *width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit,
2332 image->xres, ((GpMetafile*)image)->printer_display);
2333 else if(image->type == ImageTypeBitmap)
2334 *width = ((GpBitmap*)image)->width;
2335 else
2336 {
2337 WARN("GpImage with no image data\n");
2338 return InvalidParameter;
2339 }
2340
2341 TRACE("returning %d\n", *width);
2342
2343 return Ok;
2344}
2345
2347{
2348 TRACE("(%p, %p)\n", image, num);
2349
2350 if (!image || !num) return InvalidParameter;
2351
2352 *num = 0;
2353
2354 if (image->type == ImageTypeBitmap)
2355 {
2356 if (((GpBitmap *)image)->prop_item)
2357 {
2358 *num = ((GpBitmap *)image)->prop_count;
2359 return Ok;
2360 }
2361
2362 if (((GpBitmap *)image)->metadata_reader)
2363 IWICMetadataReader_GetCount(((GpBitmap *)image)->metadata_reader, num);
2364 }
2365
2366 return Ok;
2367}
2368
2370{
2371 HRESULT hr;
2373 IWICEnumMetadataItem *enumerator;
2374 UINT prop_count, i;
2375 ULONG items_returned;
2376
2377 TRACE("(%p, %u, %p)\n", image, num, list);
2378
2379 if (!image || !list) return InvalidParameter;
2380
2381 if (image->type != ImageTypeBitmap)
2382 {
2383 FIXME("Not implemented for type %d\n", image->type);
2384 return NotImplemented;
2385 }
2386
2387 if (((GpBitmap *)image)->prop_item)
2388 {
2389 if (num != ((GpBitmap *)image)->prop_count) return InvalidParameter;
2390
2391 for (i = 0; i < num; i++)
2392 {
2393 list[i] = ((GpBitmap *)image)->prop_item[i].id;
2394 }
2395
2396 return Ok;
2397 }
2398
2399 reader = ((GpBitmap *)image)->metadata_reader;
2400 if (!reader)
2401 {
2402 if (num != 0) return InvalidParameter;
2403 return Ok;
2404 }
2405
2406 hr = IWICMetadataReader_GetCount(reader, &prop_count);
2407 if (FAILED(hr)) return hresult_to_status(hr);
2408
2409 if (num != prop_count) return InvalidParameter;
2410
2411 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
2412 if (FAILED(hr)) return hresult_to_status(hr);
2413
2414 IWICEnumMetadataItem_Reset(enumerator);
2415
2416 for (i = 0; i < num; i++)
2417 {
2418 PROPVARIANT id;
2419
2420 hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, NULL, &items_returned);
2421 if (hr != S_OK) break;
2422
2423 if (id.vt != VT_UI2)
2424 {
2425 FIXME("not supported propvariant type for id: %u\n", id.vt);
2426 list[i] = 0;
2427 continue;
2428 }
2429 list[i] = id.uiVal;
2430 }
2431
2432 IWICEnumMetadataItem_Release(enumerator);
2433
2434 return hr == S_OK ? Ok : hresult_to_status(hr);
2435}
2436
2437static UINT propvariant_size(PROPVARIANT *value)
2438{
2439 switch (value->vt & ~VT_VECTOR)
2440 {
2441 case VT_EMPTY:
2442 return 0;
2443 case VT_I1:
2444 case VT_UI1:
2445 if (!(value->vt & VT_VECTOR)) return 1;
2446 return value->caub.cElems;
2447 case VT_I2:
2448 case VT_UI2:
2449 if (!(value->vt & VT_VECTOR)) return 2;
2450 return value->caui.cElems * 2;
2451 case VT_I4:
2452 case VT_UI4:
2453 case VT_R4:
2454 if (!(value->vt & VT_VECTOR)) return 4;
2455 return value->caul.cElems * 4;
2456 case VT_I8:
2457 case VT_UI8:
2458 case VT_R8:
2459 if (!(value->vt & VT_VECTOR)) return 8;
2460 return value->cauh.cElems * 8;
2461 case VT_LPSTR:
2462 return value->pszVal ? strlen(value->pszVal) + 1 : 0;
2463 case VT_BLOB:
2464 return value->blob.cbSize;
2465 default:
2466 FIXME("not supported variant type %d\n", value->vt);
2467 return 0;
2468 }
2469}
2470
2472{
2473 HRESULT hr;
2475 PROPVARIANT id, value;
2476
2477 TRACE("(%p,%#lx,%p)\n", image, propid, size);
2478
2479 if (!size || !image) return InvalidParameter;
2480
2481 if (image->type != ImageTypeBitmap)
2482 {
2483 FIXME("Not implemented for type %d\n", image->type);
2484 return NotImplemented;
2485 }
2486
2487 if (((GpBitmap *)image)->prop_item)
2488 {
2489 UINT i;
2490
2491 for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
2492 {
2493 if (propid == ((GpBitmap *)image)->prop_item[i].id)
2494 {
2495 *size = sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length;
2496 return Ok;
2497 }
2498 }
2499
2500 return PropertyNotFound;
2501 }
2502
2503 reader = ((GpBitmap *)image)->metadata_reader;
2504 if (!reader) return PropertyNotFound;
2505
2506 id.vt = VT_UI2;
2507 id.uiVal = propid;
2508 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2509 if (FAILED(hr)) return PropertyNotFound;
2510
2512 if (*size) *size += sizeof(PropertyItem);
2514
2515 return Ok;
2516}
2517
2518#ifndef PropertyTagTypeSByte
2519#define PropertyTagTypeSByte 6
2520#define PropertyTagTypeSShort 8
2521#define PropertyTagTypeFloat 11
2522#define PropertyTagTypeDouble 12
2523#endif
2524
2526{
2527 static const struct
2528 {
2529 UINT vt, type;
2530 } vt2type[] =
2531 {
2544 };
2545 UINT i;
2546 for (i = 0; i < ARRAY_SIZE(vt2type); i++)
2547 {
2548 if (vt2type[i].vt == vt) return vt2type[i].type;
2549 }
2550 FIXME("not supported variant type %u\n", vt);
2551 return 0;
2552}
2553
2555 UINT size, PROPID id)
2556{
2557 UINT item_size, item_type;
2558
2559 item_size = propvariant_size(value);
2560 if (size != item_size + sizeof(PropertyItem)) return InvalidParameter;
2561
2563 if (!item_type) return InvalidParameter;
2564
2565 item->value = item + 1;
2566
2567 switch (value->vt & ~VT_VECTOR)
2568 {
2569 case VT_I1:
2570 case VT_UI1:
2571 if (!(value->vt & VT_VECTOR))
2572 *(BYTE *)item->value = value->bVal;
2573 else
2574 memcpy(item->value, value->caub.pElems, item_size);
2575 break;
2576 case VT_I2:
2577 case VT_UI2:
2578 if (!(value->vt & VT_VECTOR))
2579 *(USHORT *)item->value = value->uiVal;
2580 else
2581 memcpy(item->value, value->caui.pElems, item_size);
2582 break;
2583 case VT_I4:
2584 case VT_UI4:
2585 case VT_R4:
2586 if (!(value->vt & VT_VECTOR))
2587 *(ULONG *)item->value = value->ulVal;
2588 else
2589 memcpy(item->value, value->caul.pElems, item_size);
2590 break;
2591 case VT_I8:
2592 case VT_UI8:
2593 case VT_R8:
2594 if (!(value->vt & VT_VECTOR))
2595 *(ULONGLONG *)item->value = value->uhVal.QuadPart;
2596 else
2597 memcpy(item->value, value->cauh.pElems, item_size);
2598 break;
2599 case VT_LPSTR:
2600 memcpy(item->value, value->pszVal, item_size);
2601 break;
2602 case VT_BLOB:
2603 memcpy(item->value, value->blob.pBlobData, item_size);
2604 break;
2605 default:
2606 FIXME("not supported variant type %d\n", value->vt);
2607 return InvalidParameter;
2608 }
2609
2610 item->length = item_size;
2611 item->type = item_type;
2612 item->id = id;
2613
2614 return Ok;
2615}
2616
2619{
2620 GpStatus stat;
2621 HRESULT hr;
2623 PROPVARIANT id, value;
2624
2625 TRACE("(%p,%#lx,%u,%p)\n", image, propid, size, buffer);
2626
2627 if (!image || !buffer) return InvalidParameter;
2628
2629 if (image->type != ImageTypeBitmap)
2630 {
2631 FIXME("Not implemented for type %d\n", image->type);
2632 return NotImplemented;
2633 }
2634
2635 if (((GpBitmap *)image)->prop_item)
2636 {
2637 UINT i;
2638
2639 for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
2640 {
2641 if (propid == ((GpBitmap *)image)->prop_item[i].id)
2642 {
2643 if (size != sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length)
2644 return InvalidParameter;
2645
2646 *buffer = ((GpBitmap *)image)->prop_item[i];
2647 buffer->value = buffer + 1;
2648 memcpy(buffer->value, ((GpBitmap *)image)->prop_item[i].value, buffer->length);
2649 return Ok;
2650 }
2651 }
2652
2653 return PropertyNotFound;
2654 }
2655
2656 reader = ((GpBitmap *)image)->metadata_reader;
2657 if (!reader) return PropertyNotFound;
2658
2659 id.vt = VT_UI2;
2660 id.uiVal = propid;
2661 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2662 if (FAILED(hr)) return PropertyNotFound;
2663
2666
2667 return stat;
2668}
2669
2671{
2672 HRESULT hr;
2674 IWICEnumMetadataItem *enumerator;
2675 UINT prop_count, prop_size, i;
2676 PROPVARIANT id, value;
2677
2678 TRACE("(%p,%p,%p)\n", image, size, count);
2679
2680 if (!image || !size || !count) return InvalidParameter;
2681
2682 if (image->type != ImageTypeBitmap)
2683 {
2684 FIXME("Not implemented for type %d\n", image->type);
2685 return NotImplemented;
2686 }
2687
2688 if (((GpBitmap *)image)->prop_item)
2689 {
2690 *count = ((GpBitmap *)image)->prop_count;
2691 *size = 0;
2692
2693 for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
2694 {
2695 *size += sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length;
2696 }
2697
2698 return Ok;
2699 }
2700
2701 reader = ((GpBitmap *)image)->metadata_reader;
2702 if (!reader)
2703 {
2704 *count = 0;
2705 *size = 0;
2706 return Ok;
2707 }
2708
2709 hr = IWICMetadataReader_GetCount(reader, &prop_count);
2710 if (FAILED(hr)) return hresult_to_status(hr);
2711
2712 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
2713 if (FAILED(hr)) return hresult_to_status(hr);
2714
2715 IWICEnumMetadataItem_Reset(enumerator);
2716
2717 prop_size = 0;
2718
2719 PropVariantInit(&id);
2720 PropVariantInit(&value);
2721
2722 for (i = 0; i < prop_count; i++)
2723 {
2724 ULONG items_returned;
2725 UINT item_size;
2726
2727 hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, &value, &items_returned);
2728 if (hr != S_OK) break;
2729
2730 item_size = propvariant_size(&value);
2731 if (item_size) prop_size += sizeof(PropertyItem) + item_size;
2732
2733 PropVariantClear(&id);
2735 }
2736
2737 IWICEnumMetadataItem_Release(enumerator);
2738
2739 if (hr != S_OK) return PropertyNotFound;
2740
2741 *count = prop_count;
2742 *size = prop_size;
2743 return Ok;
2744}
2745
2748{
2750 HRESULT hr;
2752 IWICEnumMetadataItem *enumerator;
2753 UINT prop_count, prop_size, i;
2754 PROPVARIANT id, value;
2755 char *item_value;
2756
2757 TRACE("(%p,%u,%u,%p)\n", image, size, count, buf);
2758
2759 if (!image || !buf) return InvalidParameter;
2760
2761 if (image->type != ImageTypeBitmap)
2762 {
2763 FIXME("Not implemented for type %d\n", image->type);
2764 return NotImplemented;
2765 }
2766
2767 status = GdipGetPropertySize(image, &prop_size, &prop_count);
2768 if (status != Ok) return status;
2769
2770 if (prop_count != count || prop_size != size) return InvalidParameter;
2771
2772 if (((GpBitmap *)image)->prop_item)
2773 {
2774 memcpy(buf, ((GpBitmap *)image)->prop_item, prop_size);
2775
2776 item_value = (char *)(buf + prop_count);
2777
2778 for (i = 0; i < prop_count; i++)
2779 {
2780 buf[i].value = item_value;
2781 item_value += buf[i].length;
2782 }
2783
2784 return Ok;
2785 }
2786
2787 reader = ((GpBitmap *)image)->metadata_reader;
2788 if (!reader) return GenericError;
2789
2790 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
2791 if (FAILED(hr)) return hresult_to_status(hr);
2792
2793 IWICEnumMetadataItem_Reset(enumerator);
2794
2795 item_value = (char *)(buf + prop_count);
2796
2797 PropVariantInit(&id);
2798 PropVariantInit(&value);
2799
2800 for (i = 0; i < prop_count; i++)
2801 {
2803 ULONG items_returned;
2804 UINT item_size;
2805
2806 hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, &value, &items_returned);
2807 if (hr != S_OK) break;
2808
2809 if (id.vt != VT_UI2)
2810 {
2811 FIXME("not supported propvariant type for id: %u\n", id.vt);
2812 continue;
2813 }
2814
2815 item_size = propvariant_size(&value);
2816 if (item_size)
2817 {
2818 item = malloc(item_size + sizeof(*item));
2819
2820 propvariant_to_item(&value, item, item_size + sizeof(*item), id.uiVal);
2821 buf[i].id = item->id;
2822 buf[i].type = item->type;
2823 buf[i].length = item_size;
2824 buf[i].value = item_value;
2825 memcpy(item_value, item->value, item_size);
2826 item_value += item_size;
2827
2828 free(item);
2829 }
2830
2831 PropVariantClear(&id);
2833 }
2834
2835 IWICEnumMetadataItem_Release(enumerator);
2836
2837 if (hr != S_OK) return PropertyNotFound;
2838
2839 return Ok;
2840}
2841
2843{
2844 const GUID *format;
2846};
2847
2849{
2850 {&ImageFormatGIF, &FrameDimensionTime},
2851 {&ImageFormatIcon, &FrameDimensionResolution},
2852 {NULL}
2853};
2854
2856 GDIPCONST GUID* dimensionID, UINT* count)
2857{
2858 TRACE("(%p,%s,%p)\n", image, debugstr_guid(dimensionID), count);
2859
2860 if(!image || !count)
2861 return InvalidParameter;
2862
2863 if (!dimensionID ||
2864 IsEqualGUID(dimensionID, &image->format) ||
2865 IsEqualGUID(dimensionID, &FrameDimensionPage) ||
2866 IsEqualGUID(dimensionID, &FrameDimensionTime))
2867 {
2868 *count = image->frame_count;
2869 return Ok;
2870 }
2871
2872 return InvalidParameter;
2873}
2874
2876 UINT* count)
2877{
2878 TRACE("(%p, %p)\n", image, count);
2879
2880 /* Native gdiplus 1.1 does not yet support multiple frame dimensions. */
2881
2882 if(!image || !count)
2883 return InvalidParameter;
2884
2885 *count = 1;
2886
2887 return Ok;
2888}
2889
2891 GUID* dimensionIDs, UINT count)
2892{
2893 int i;
2894 const GUID *result=NULL;
2895
2896 TRACE("(%p,%p,%u)\n", image, dimensionIDs, count);
2897
2898 if(!image || !dimensionIDs || count != 1)
2899 return InvalidParameter;
2900
2901 for (i=0; image_format_dimensions[i].format; i++)
2902 {
2903 if (IsEqualGUID(&image->format, image_format_dimensions[i].format))
2904 {
2905 result = image_format_dimensions[i].dimension;
2906 break;
2907 }
2908 }
2909
2910 if (!result)
2911 result = &FrameDimensionPage;
2912
2913 memcpy(dimensionIDs, result, sizeof(GUID));
2914
2915 return Ok;
2916}
2917
2919 GpImage **image)
2920{
2921 GpStatus stat;
2922 IStream *stream;
2923
2924 TRACE("(%s) %p\n", debugstr_w(filename), image);
2925
2926 if (!filename || !image)
2927 return InvalidParameter;
2928
2929 *image = NULL;
2930
2932
2933 if (stat != Ok)
2934 return stat;
2935
2937
2938 IStream_Release(stream);
2939
2940 return stat;
2941}
2942
2943/* FIXME: no icm handling */
2945{
2946 TRACE("(%s) %p\n", debugstr_w(filename), image);
2947
2949}
2950
2952{
2953 UINT prop_size, prop_count;
2954 PropertyItem *prop_item;
2955
2956 if (bitmap->prop_item == NULL)
2957 {
2958 prop_size = prop_count = 0;
2959 prop_item = calloc(1, item->length + sizeof(PropertyItem));
2960 if (!prop_item) return;
2961 }
2962 else
2963 {
2964 UINT i;
2965 char *item_value;
2966
2967 GdipGetPropertySize(&bitmap->image, &prop_size, &prop_count);
2968
2969 prop_item = calloc(1, prop_size + item->length + sizeof(PropertyItem));
2970 if (!prop_item) return;
2971 memcpy(prop_item, bitmap->prop_item, sizeof(PropertyItem) * bitmap->prop_count);
2972 prop_size -= sizeof(PropertyItem) * bitmap->prop_count;
2973 memcpy(prop_item + prop_count + 1, bitmap->prop_item + prop_count, prop_size);
2974
2975 item_value = (char *)(prop_item + prop_count + 1);
2976
2977 for (i = 0; i < prop_count; i++)
2978 {
2979 prop_item[i].value = item_value;
2980 item_value += prop_item[i].length;
2981 }
2982 }
2983
2984 prop_item[prop_count].id = item->id;
2985 prop_item[prop_count].type = item->type;
2986 prop_item[prop_count].length = item->length;
2987 prop_item[prop_count].value = (char *)(prop_item + prop_count + 1) + prop_size;
2988 memcpy(prop_item[prop_count].value, item->value, item->length);
2989
2990 free(bitmap->prop_item);
2991 bitmap->prop_item = prop_item;
2992 bitmap->prop_count++;
2993}
2994
2996{
2997 HRESULT hr;
2998 GUID format;
2999 PROPVARIANT id, value;
3000 BOOL ret = FALSE;
3001
3002 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
3003 if (FAILED(hr) || !IsEqualGUID(&format, guid)) return FALSE;
3004
3005 PropVariantInit(&id);
3006 PropVariantInit(&value);
3007
3008 id.vt = VT_LPWSTR;
3009 id.pwszVal = CoTaskMemAlloc((lstrlenW(prop_name) + 1) * sizeof(WCHAR));
3010 if (!id.pwszVal) return FALSE;
3011 lstrcpyW(id.pwszVal, prop_name);
3012 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
3013 if (hr == S_OK && value.vt == VT_BOOL)
3014 ret = value.boolVal;
3015
3016 PropVariantClear(&id);
3018
3019 return ret;
3020}
3021
3023{
3024 HRESULT hr;
3025 GUID format;
3026 PROPVARIANT id, value;
3028
3029 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
3030 if (FAILED(hr) || !IsEqualGUID(&format, guid)) return NULL;
3031
3032 PropVariantInit(&id);
3033 PropVariantInit(&value);
3034
3035 id.vt = VT_LPWSTR;
3036 id.pwszVal = CoTaskMemAlloc((lstrlenW(prop_name) + 1) * sizeof(WCHAR));
3037 if (!id.pwszVal) return NULL;
3038 lstrcpyW(id.pwszVal, prop_name);
3039 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
3040 if (hr == S_OK)
3041 {
3042 UINT item_size = propvariant_size(&value);
3043 if (item_size)
3044 {
3045 item_size += sizeof(*item);
3046 item = calloc(1, item_size);
3047 if (propvariant_to_item(&value, item, item_size, 0) != Ok)
3048 {
3049 free(item);
3050 item = NULL;
3051 }
3052 }
3053 }
3054
3055 PropVariantClear(&id);
3057
3058 return item;
3059}
3060
3062{
3064
3065 comment = get_property(reader, &GUID_MetadataFormatGifComment, L"TextEntry");
3066 if (comment)
3068
3069 return comment;
3070}
3071
3073{
3074 PropertyItem *appext = NULL, *appdata = NULL, *loop = NULL;
3075
3076 appext = get_property(reader, &GUID_MetadataFormatAPE, L"Application");
3077 if (appext)
3078 {
3079 if (appext->type == PropertyTagTypeByte && appext->length == 11 &&
3080 (!memcmp(appext->value, "NETSCAPE2.0", 11) || !memcmp(appext->value, "ANIMEXTS1.0", 11)))
3081 {
3082 appdata = get_property(reader, &GUID_MetadataFormatAPE, L"Data");
3083 if (appdata)
3084 {
3085 if (appdata->type == PropertyTagTypeByte && appdata->length == 4)
3086 {
3087 BYTE *data = appdata->value;
3088 if (data[0] == 3 && data[1] == 1)
3089 {
3090 loop = calloc(1, sizeof(*loop) + sizeof(SHORT));
3091 if (loop)
3092 {
3093 loop->type = PropertyTagTypeShort;
3094 loop->id = PropertyTagLoopCount;
3095 loop->length = sizeof(SHORT);
3096 loop->value = loop + 1;
3097 *(SHORT *)loop->value = data[2] | (data[3] << 8);
3098 }
3099 }
3100 }
3101 }
3102 }
3103 }
3104
3105 free(appext);
3106 free(appdata);
3107
3108 return loop;
3109}
3110
3112{
3113 PropertyItem *background = NULL;
3114
3115 if (get_bool_property(reader, &GUID_MetadataFormatLSD, L"GlobalColorTableFlag"))
3116 {
3117 background = get_property(reader, &GUID_MetadataFormatLSD, L"BackgroundColorIndex");
3118 if (background)
3119 background->id = PropertyTagIndexBackground;
3120 }
3121
3122 return background;
3123}
3124
3126{
3127 HRESULT hr;
3130 UINT count = 0;
3131 WICColor colors[256];
3132
3133 if (!get_bool_property(reader, &GUID_MetadataFormatLSD, L"GlobalColorTableFlag"))
3134 return NULL;
3135
3136 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
3137 if (hr != S_OK) return NULL;
3138
3139 hr = IWICImagingFactory_CreatePalette(factory, &palette);
3140 if (hr == S_OK)
3141 {
3142 hr = IWICBitmapDecoder_CopyPalette(decoder, palette);
3143 if (hr == S_OK)
3144 IWICPalette_GetColors(palette, 256, colors, &count);
3145
3146 IWICPalette_Release(palette);
3147 }
3148
3149 IWICImagingFactory_Release(factory);
3150
3151 if (count)
3152 {
3153 PropertyItem *pal;
3154 UINT i;
3155 BYTE *rgb;
3156
3157 pal = calloc(1, sizeof(*pal) + count * 3);
3158 if (!pal) return NULL;
3161 pal->value = pal + 1;
3162 pal->length = count * 3;
3163
3164 rgb = pal->value;
3165
3166 for (i = 0; i < count; i++)
3167 {
3168 rgb[i*3] = (colors[i] >> 16) & 0xff;
3169 rgb[i*3 + 1] = (colors[i] >> 8) & 0xff;
3170 rgb[i*3 + 2] = colors[i] & 0xff;
3171 }
3172
3173 return pal;
3174 }
3175
3176 return NULL;
3177}
3178
3180{
3182
3183 if (get_bool_property(reader, &GUID_MetadataFormatGCE, L"TransparencyFlag"))
3184 {
3185 index = get_property(reader, &GUID_MetadataFormatGCE, L"TransparentColorIndex");
3186 if (index)
3188 }
3189 return index;
3190}
3191
3193{
3194 HRESULT hr;
3195 IWICMetadataBlockReader *block_reader;
3197 UINT block_count, i;
3198 PropertyItem *prop;
3199
3200 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3201 if (hr == S_OK)
3202 {
3203 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3204 if (hr == S_OK)
3205 {
3206 for (i = 0; i < block_count; i++)
3207 {
3208 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3209 if (hr == S_OK)
3210 {
3212 if (prop)
3213 {
3214 if (prop->type == PropertyTagTypeByte && prop->length == 1)
3215 *value = *(BYTE *)prop->value;
3216 else if (prop->type == PropertyTagTypeShort && prop->length == 2)
3217 *value = *(SHORT *)prop->value;
3218
3219 free(prop);
3220 }
3221 IWICMetadataReader_Release(reader);
3222 }
3223 }
3224 }
3225 IWICMetadataBlockReader_Release(block_reader);
3226 }
3227}
3228
3230{
3231 HRESULT hr;
3232 IWICBitmapFrameDecode *frame;
3233 IWICMetadataBlockReader *block_reader;
3235 UINT frame_count, block_count, i;
3236 PropertyItem *delay = NULL, *comment = NULL, *background = NULL;
3237 PropertyItem *transparent_idx = NULL, *loop = NULL, *palette = NULL;
3238
3239 IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
3240 delay = calloc(1, sizeof(*delay) + frame_count * sizeof(LONG));
3241 if (delay)
3242 {
3243 LONG *value;
3244 LONG frame_delay = 0;
3245
3246 delay->type = PropertyTagTypeLong;
3247 delay->id = PropertyTagFrameDelay;
3248 delay->length = frame_count * sizeof(LONG);
3249 delay->value = delay + 1;
3250
3251 value = delay->value;
3252
3253 for (i = 0; i < frame_count; i++)
3254 {
3255 hr = IWICBitmapDecoder_GetFrame(decoder, i, &frame);
3256 if (hr == S_OK)
3257 {
3258 get_gif_frame_property(frame, &GUID_MetadataFormatGCE, L"Delay", &frame_delay);
3259 IWICBitmapFrameDecode_Release(frame);
3260 }
3261 value[i] = frame_delay;
3262 }
3263 }
3264
3265 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3266 if (hr == S_OK)
3267 {
3268 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3269 if (hr == S_OK)
3270 {
3271 for (i = 0; i < block_count; i++)
3272 {
3273 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3274 if (hr == S_OK)
3275 {
3276 if (!comment)
3278
3279 if (!loop)
3280 loop = get_gif_loopcount(reader);
3281
3282 if (!background)
3283 background = get_gif_background(reader);
3284
3285 if (!palette)
3287
3288 IWICMetadataReader_Release(reader);
3289 }
3290 }
3291 }
3292 IWICMetadataBlockReader_Release(block_reader);
3293 }
3294
3295 if (!loop)
3296 {
3297 loop = calloc(1, sizeof(*loop) + sizeof(SHORT));
3298 if (loop)
3299 {
3300 loop->type = PropertyTagTypeShort;
3301 loop->id = PropertyTagLoopCount;
3302 loop->length = sizeof(SHORT);
3303 loop->value = loop + 1;
3304 *(SHORT *)loop->value = 1;
3305 }
3306 }
3307
3308 if (delay) add_property(bitmap, delay);
3310 if (loop) add_property(bitmap, loop);
3312 if (background) add_property(bitmap, background);
3313
3314 free(delay);
3315 free(comment);
3316 free(loop);
3317 free(palette);
3318 free(background);
3319
3320 /* Win7 gdiplus always returns transparent color index from frame 0 */
3321 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
3322 if (hr != S_OK) return;
3323
3324 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3325 if (hr == S_OK)
3326 {
3327 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3328 if (hr == S_OK)
3329 {
3330 for (i = 0; i < block_count; i++)
3331 {
3332 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3333 if (hr == S_OK)
3334 {
3335 if (!transparent_idx)
3336 transparent_idx = get_gif_transparent_idx(reader);
3337
3338 IWICMetadataReader_Release(reader);
3339 }
3340 }
3341 }
3342 IWICMetadataBlockReader_Release(block_reader);
3343 }
3344
3345 if (transparent_idx) add_property(bitmap, transparent_idx);
3346 free(transparent_idx);
3347
3348 IWICBitmapFrameDecode_Release(frame);
3349}
3350
3351static PropertyItem* create_prop(PROPID propid, PROPVARIANT* value)
3352{
3354 UINT item_size = propvariant_size(value);
3355
3356 if (item_size)
3357 {
3358 item_size += sizeof(*item);
3359 item = calloc(1, item_size);
3360 if (propvariant_to_item(value, item, item_size, propid) != Ok)
3361 {
3362 free(item);
3363 item = NULL;
3364 }
3365 }
3366
3367 return item;
3368}
3369
3371{
3372 PROPVARIANT value;
3373 HRESULT hr;
3374 ULONG result=0;
3375
3376 hr = IWICMetadataReader_GetValueByIndex(reader, index, NULL, NULL, &value);
3377 if (SUCCEEDED(hr))
3378 {
3379 switch (value.vt)
3380 {
3381 case VT_UI4:
3382 result = value.ulVal;
3383 break;
3384 default:
3385 ERR("unhandled case %u\n", value.vt);
3386 break;
3387 }
3389 }
3390 return result;
3391}
3392
3394{
3395 HRESULT hr;
3396 UINT i;
3397 PROPVARIANT name, value;
3399 static const struct keyword_info {
3400 const char* name;
3401 PROPID propid;
3402 } keywords[] = {
3403 { "Title", PropertyTagImageTitle },
3404 { "Author", PropertyTagArtist },
3405 { "Description", PropertyTagImageDescription },
3406 { "Copyright", PropertyTagCopyright },
3407 { "Software", PropertyTagSoftwareUsed },
3408 { "Source", PropertyTagEquipModel },
3409 { "Comment", PropertyTagExifUserComment },
3410 };
3411
3412 if (*seen_text == NULL)
3413 *seen_text = calloc(ARRAY_SIZE(keywords), sizeof(BOOL));
3414 if (*seen_text == NULL)
3415 return E_OUTOFMEMORY;
3416
3417 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &name, &value);
3418 if (FAILED(hr))
3419 return hr;
3420
3421 if (name.vt == VT_LPSTR)
3422 {
3423 for (i = 0; i < ARRAY_SIZE(keywords); i++)
3424 {
3425 if (!strcmp(keywords[i].name, name.pszVal))
3426 break;
3427 }
3428 if (i < ARRAY_SIZE(keywords) && !(*seen_text)[i])
3429 {
3430 (*seen_text)[i] = TRUE;
3431 item = create_prop(keywords[i].propid, &value);
3432 if (item)
3434 free(item);
3435 }
3436 }
3437
3440
3441 return S_OK;
3442}
3443
3445{
3447 ULONG *rational;
3448
3449 item = calloc(1, sizeof(*item) + sizeof(ULONG) * 2);
3450 if (!item)
3451 return E_OUTOFMEMORY;
3452
3453 item->length = sizeof(ULONG) * 2;
3455 item->id = PropertyTagGamma;
3456 rational = item->value = item + 1;
3457 rational[0] = 100000;
3458 rational[1] = get_ulong_by_index(reader, 0);
3460 free(item);
3461
3462 return S_OK;
3463}
3464
3466{
3468 ULONG *rational;
3469
3470 item = calloc(1, sizeof(*item) + sizeof(ULONG) * 4);
3471 if (!item)
3472 return E_OUTOFMEMORY;
3473
3474 item->length = sizeof(ULONG) * 4;
3477 rational = item->value = item + 1;
3478 rational[0] = get_ulong_by_index(reader, 0);
3479 rational[1] = 100000;
3480 rational[2] = get_ulong_by_index(reader, 1);
3481 rational[3] = 100000;
3483 free(item);
3484
3485 return S_OK;
3486}
3487
3489{
3491 ULONG *rational;
3492
3493 item = calloc(1, sizeof(*item) + sizeof(ULONG) * 12);
3494 if (!item)
3495 return E_OUTOFMEMORY;
3496
3497 item->length = sizeof(ULONG) * 12;
3500 rational = item->value = item + 1;
3501 rational[0] = get_ulong_by_index(reader, 2);
3502 rational[1] = 100000;
3503 rational[2] = get_ulong_by_index(reader, 3);
3504 rational[3] = 100000;
3505 rational[4] = get_ulong_by_index(reader, 4);
3506 rational[5] = 100000;
3507 rational[6] = get_ulong_by_index(reader, 5);
3508 rational[7] = 100000;
3509 rational[8] = get_ulong_by_index(reader, 6);
3510 rational[9] = 100000;
3511 rational[10] = get_ulong_by_index(reader, 7);
3512 rational[11] = 100000;
3514 free(item);
3515
3516 return S_OK;
3517}
3518
3520{
3521 HRESULT hr;
3522 UINT item_size, i;
3524 PROPVARIANT value;
3525 USHORT datetime[6];
3526
3527 for (i = 0; i < 6; i++)
3528 {
3529 hr = IWICMetadataReader_GetValueByIndex(reader, i, NULL, NULL, &value);
3530 if (FAILED(hr))
3531 return hr;
3532 if (i == 0 && value.vt == VT_UI2)
3533 datetime[0] = value.uiVal;
3534 else if (i > 0 && value.vt == VT_UI1)
3535 datetime[i] = value.bVal;
3536 else
3537 {
3539 return E_FAIL;
3540 }
3542 }
3543
3544 item_size = 20;
3545 item = calloc(1, sizeof(*item) + item_size);
3546 if (!item)
3547 return E_OUTOFMEMORY;
3548
3551 item->length = item_size;
3552 item->value = item + 1;
3553 snprintf(item->value, item_size, "%04u:%02u:%02u %02u:%02u:%02u",
3554 datetime[0], datetime[1], datetime[2], datetime[3], datetime[4], datetime[5]);
3555
3557 free(item);
3558
3559 return S_OK;
3560}
3561
3563{
3564 HRESULT hr;
3566 PROPVARIANT value;
3567
3568 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, NULL, &value);
3569 if (FAILED(hr))
3570 return hr;
3571
3573 if (item)
3575 free(item);
3576
3578
3579 return S_OK;
3580}
3581
3583{
3584 HRESULT hr;
3585 double dpiX, dpiY;
3586 PropertyItem *unit, *unitX, *unitY;
3587
3588 hr = IWICBitmapFrameDecode_GetResolution(frame, &dpiX, &dpiY);
3589 if (FAILED(hr))
3590 return hr;
3591
3592 unit = calloc(1, sizeof(*unit) + 1);
3593 unitX = calloc(1, sizeof(*unitX) + 4);
3594 unitY = calloc(1, sizeof(*unitY) + 4);
3595
3596 if (!unit || !unitX || !unitY)
3597 {
3598 free(unit);
3599 free(unitX);
3600 free(unitY);
3601 return E_OUTOFMEMORY;
3602 }
3603
3604 unit->type = PropertyTagTypeByte;
3606 unit->length = 1;
3607 unit->value = unit + 1;
3608 *(BYTE *)unit->value = 1;
3610 free(unit);
3611
3612 unitX->type = PropertyTagTypeLong;
3614 unitX->length = 4;
3615 unitX->value = unitX + 1;
3616 *(ULONG *)unitX->value = (dpiX == 96.0) ? 0 : gdip_round(dpiX / 0.0254);
3617 add_property(bitmap, unitX);
3618 free(unitX);
3619
3620 unitY->type = PropertyTagTypeLong;
3622 unitY->length = 4;
3623 unitY->value = unitY + 1;
3624 *(ULONG *)unitY->value = (dpiY == 96.0) ? 0 : gdip_round(dpiY / 0.0254);
3625 add_property(bitmap, unitY);
3626 free(unitY);
3627
3628 return S_OK;
3629}
3630
3632{
3633 HRESULT hr;
3634 IWICBitmapFrameDecode *frame;
3635 IWICMetadataBlockReader *block_reader;
3636 UINT block_count, i;
3637 BOOL seen_gamma=FALSE, seen_whitepoint=FALSE, seen_chrm=FALSE, seen_time=FALSE, seen_histogram=FALSE;
3638 BOOL *seen_text = NULL;
3639
3640 hr = IWICBitmapDecoder_GetFrame(decoder, active_frame, &frame);
3641 if (hr != S_OK)
3642 return;
3643
3644 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3645 if (hr != S_OK)
3646 {
3647 IWICBitmapFrameDecode_Release(frame);
3648 return;
3649 }
3650
3651 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3652 if (hr != S_OK)
3653 {
3654 IWICMetadataBlockReader_Release(block_reader);
3655 IWICBitmapFrameDecode_Release(frame);
3656 return;
3657 }
3658
3659 for (i = 0; i < block_count; i++)
3660 {
3662 GUID format;
3663
3664 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3665 if (hr != S_OK)
3666 continue;
3667
3668 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
3669 if (FAILED(hr))
3670 {
3671 IWICMetadataReader_Release(reader);
3672 continue;
3673 }
3674
3675 if (IsEqualGUID(&GUID_MetadataFormatChunktEXt, &format))
3676 png_read_text(reader, bitmap, &seen_text);
3677 else if (IsEqualGUID(&GUID_MetadataFormatChunkgAMA, &format))
3678 {
3679 if (!seen_gamma)
3680 {
3682 seen_gamma = SUCCEEDED(hr);
3683 }
3684 }
3685 else if (IsEqualGUID(&GUID_MetadataFormatChunkcHRM, &format))
3686 {
3687 if (!seen_whitepoint)
3688 {
3690 seen_whitepoint = SUCCEEDED(hr);
3691 }
3692 if (!seen_chrm)
3693 {
3695 seen_chrm = SUCCEEDED(hr);
3696 }
3697 }
3698 else if (IsEqualGUID(&GUID_MetadataFormatChunktIME, &format))
3699 {
3700 if (!seen_time)
3701 {
3703 seen_time = SUCCEEDED(hr);
3704 }
3705 }
3706 else if (IsEqualGUID(&GUID_MetadataFormatChunkhIST, &format))
3707 {
3708 if (!seen_histogram)
3709 {
3711 seen_histogram = SUCCEEDED(hr);
3712 }
3713 }
3714
3715 IWICMetadataReader_Release(reader);
3716 }
3717 free(seen_text);
3718
3720
3721 IWICMetadataBlockReader_Release(block_reader);
3722
3723 IWICBitmapFrameDecode_Release(frame);
3724}
3725
3727{
3729 HRESULT hr;
3730
3731 TRACE("%p,%s\n", stream, wine_dbgstr_guid(container));
3732
3733 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
3734 if (FAILED(hr)) return hresult_to_status(hr);
3735 hr = IWICImagingFactory_CreateDecoder(factory, container, NULL, decoder);
3736 IWICImagingFactory_Release(factory);
3737 if (FAILED(hr)) return hresult_to_status(hr);
3738
3739 hr = IWICBitmapDecoder_Initialize(*decoder, stream, WICDecodeMetadataCacheOnLoad);
3740 if (FAILED(hr))
3741 {
3742 IWICBitmapDecoder_Release(*decoder);
3743 return hresult_to_status(hr);
3744 }
3745 return Ok;
3746}
3747
3749
3751 UINT active_frame, metadata_reader_func metadata_reader, GpImage **image)
3752{
3755 HRESULT hr;
3756 IWICBitmapFrameDecode *frame;
3758 IWICMetadataBlockReader *block_reader;
3763 int i;
3764 UINT width, height, frame_count;
3765 BitmapData lockeddata;
3766 WICRect wrc;
3767
3768 TRACE("%p,%u,%p\n", decoder, active_frame, image);
3769
3770 IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
3771 hr = IWICBitmapDecoder_GetFrame(decoder, active_frame, &frame);
3772 if (SUCCEEDED(hr)) /* got frame */
3773 {
3774 hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &wic_format);
3775
3776 if (SUCCEEDED(hr))
3777 {
3778 if (!force_conversion)
3779 {
3780 for (i=0; pixel_formats[i].wic_format; i++)
3781 {
3783 {
3784 source = (IWICBitmapSource*)frame;
3785 IWICBitmapSource_AddRef(source);
3786 gdip_format = pixel_formats[i].gdip_format;
3787 palette_type = pixel_formats[i].palette_type;
3788 break;
3789 }
3790 }
3791 }
3792 if (!source)
3793 {
3794 /* unknown format; fall back on 32bppARGB */
3795 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source);
3797 }
3798 TRACE("%s => %#x\n", wine_dbgstr_guid(&wic_format), gdip_format);
3799 }
3800
3801 if (SUCCEEDED(hr)) /* got source */
3802 {
3803 hr = IWICBitmapSource_GetSize(source, &width, &height);
3804
3805 if (SUCCEEDED(hr))
3807 NULL, &bitmap);
3808
3809 if (SUCCEEDED(hr) && status == Ok) /* created bitmap */
3810 {
3812 gdip_format, &lockeddata);
3813 if (status == Ok) /* locked bitmap */
3814 {
3815 wrc.X = 0;
3816 wrc.Width = width;
3817 wrc.Height = 1;
3818 for (i=0; i<height; i++)
3819 {
3820 wrc.Y = i;
3821 hr = IWICBitmapSource_CopyPixels(source, &wrc, abs(lockeddata.Stride),
3822 abs(lockeddata.Stride), (BYTE*)lockeddata.Scan0+lockeddata.Stride*i);
3823 if (FAILED(hr)) break;
3824 }
3825
3826 GdipBitmapUnlockBits(bitmap, &lockeddata);
3827 }
3828
3829 if (SUCCEEDED(hr) && status == Ok)
3830 *image = &bitmap->image;
3831 else
3832 {
3833 *image = NULL;
3834 GdipDisposeImage(&bitmap->image);
3835 }
3836
3837 if (SUCCEEDED(hr) && status == Ok)
3838 {
3839 double dpix, dpiy;
3840 hr = IWICBitmapSource_GetResolution(source, &dpix, &dpiy);
3841 if (SUCCEEDED(hr))
3842 {
3843 bitmap->image.xres = dpix;
3844 bitmap->image.yres = dpiy;
3845 }
3846 hr = S_OK;
3847 }
3848 }
3849
3850 IWICBitmapSource_Release(source);
3851 }
3852
3853 if (SUCCEEDED(hr) && status == Ok) {
3854 bitmap->metadata_reader = NULL;
3855
3856 if (metadata_reader)
3857 metadata_reader(bitmap, decoder, active_frame);
3858 else if (IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader) == S_OK)
3859 {
3860 UINT block_count = 0;
3861 if (IWICMetadataBlockReader_GetCount(block_reader, &block_count) == S_OK && block_count)
3862 IWICMetadataBlockReader_GetReaderByIndex(block_reader, 0, &bitmap->metadata_reader);
3863 IWICMetadataBlockReader_Release(block_reader);
3864 }
3865
3867 }
3868 IWICBitmapFrameDecode_Release(frame);
3869 }
3870
3871 if (FAILED(hr) && status == Ok) status = hresult_to_status(hr);
3872
3873 if (status == Ok)
3874 {
3875 /* Native GDI+ used to be smarter, but since Win7 it just sets these flags. */
3877 if (IsEqualGUID(&wic_format, &GUID_WICPixelFormat2bppGray) ||
3878 IsEqualGUID(&wic_format, &GUID_WICPixelFormat4bppGray) ||
3879 IsEqualGUID(&wic_format, &GUID_WICPixelFormat8bppGray) ||
3880 IsEqualGUID(&wic_format, &GUID_WICPixelFormat16bppGray))
3881 bitmap->image.flags |= ImageFlagsColorSpaceGRAY;
3882 else
3883 bitmap->image.flags |= ImageFlagsColorSpaceRGB;
3884 bitmap->image.frame_count = frame_count;
3885 bitmap->image.current_frame = active_frame;
3886 bitmap->image.decoder = decoder;
3887 IWICBitmapDecoder_AddRef(decoder);
3888 if (palette)
3889 {
3890 free(bitmap->image.palette);
3891 bitmap->image.palette = palette;
3892 }
3893 else
3894 {
3895 if (IsEqualGUID(&wic_format, &GUID_WICPixelFormatBlackWhite))
3896 bitmap->image.palette->Flags = 0;
3897 }
3898 TRACE("=> %p\n", *image);
3899 }
3900
3901 return status;
3902}
3903
3905 metadata_reader_func metadata_reader, GpImage **image)
3906{
3909
3911 if(status != Ok)
3912 return status;
3913
3914 status = decode_frame_wic(decoder, FALSE, 0, metadata_reader, image);
3915 IWICBitmapDecoder_Release(decoder);
3916 return status;
3917}
3918
3920{
3921 size_t obj_size, body_offset;
3922 GpImage *new_image;
3924
3925 status = decode_frame_wic(image->decoder, FALSE, active_frame, NULL, &new_image);
3926 if(status != Ok)
3927 return status;
3928
3929 if (image->type == ImageTypeBitmap)
3930 obj_size = sizeof(GpBitmap);
3931 else if (image->type == ImageTypeMetafile)
3932 obj_size = sizeof(GpMetafile);
3933 else
3934 {
3935 ERR("unknown image type: %d\n", image->type);
3936 GdipDisposeImage(new_image);
3937 return GenericError;
3938 }
3939
3940 memcpy(&new_image->format, &image->format, sizeof(GUID));
3941 new_image->encoder = image->encoder;
3942 image->encoder = NULL;
3944 memcpy(image, new_image, FIELD_OFFSET(GpImage, lock));
3945 body_offset = RTL_SIZEOF_THROUGH_FIELD(GpImage, lock);
3946 memcpy((char *)image + body_offset, (char *)new_image + body_offset, obj_size - body_offset);
3947 new_image->type = ~0;
3948 free(new_image);
3949 return Ok;
3950}
3951
3954{
3955 LONG frame_left = 0, frame_top = 0;
3956 get_gif_frame_property(frame, &GUID_MetadataFormatIMD, L"Left", &frame_left);
3957 get_gif_frame_property(frame, &GUID_MetadataFormatIMD, L"Top", &frame_top);
3958 *left = frame_left;
3959 *top = frame_top;
3960
3961 return IWICBitmapFrameDecode_GetSize(frame, width, height);
3962}
3963
3965{
3966 UINT i, j, left, top, width, height;
3968 BYTE *new_bits;
3969 HRESULT hr;
3970
3971 hr = get_gif_frame_rect(frame, &left, &top, &width, &height);
3972 if(FAILED(hr))
3973 return hr;
3974
3975 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source);
3976 if(FAILED(hr))
3977 return hr;
3978
3979 new_bits = calloc(width * height, 4);
3980 if(!new_bits)
3981 return E_OUTOFMEMORY;
3982
3983 hr = IWICBitmapSource_CopyPixels(source, NULL, width*4, width*height*4, new_bits);
3984 IWICBitmapSource_Release(source);
3985 if(FAILED(hr)) {
3986 free(new_bits);
3987 return hr;
3988 }
3989
3990 for(i=0; i<height && i+top<bitmap->height; i++) {
3991 for(j=0; j<width && j+left<bitmap->width; j++) {
3992 DWORD *src = (DWORD*)(new_bits+i*width*4+j*4);
3993 DWORD *dst = (DWORD*)(bitmap->bits+(i+top)*bitmap->stride+(j+left)*4);
3994
3995 if(first_frame || *src>>24 != 0)
3996 *dst = *src;
3997 }
3998 }
3999 free(new_bits);
4000 return hr;
4001}
4002
4004{
4005 BYTE bgcolor_idx = 0;
4006 UINT i;
4007
4008 for(i=0; i<bitmap->prop_count; i++) {
4009 if(bitmap->prop_item[i].id == PropertyTagIndexBackground)
4010 bgcolor_idx = *(BYTE*)bitmap->prop_item[i].value;
4011 else if(bitmap->prop_item[i].id == PropertyTagIndexTransparent)
4012 return 0;
4013 }
4014
4015 for(i=0; i<bitmap->prop_count; i++) {
4016 if(bitmap->prop_item[i].id == PropertyTagGlobalPalette) {
4017 if(bitmap->prop_item[i].length/3 > bgcolor_idx) {
4018 BYTE *color = ((BYTE*)bitmap->prop_item[i].value)+bgcolor_idx*3;
4019 return color[2] + (color[1]<<8) + (color[0]<<16) + (0xffu<<24);
4020 }
4021 break;
4022 }
4023 }
4024
4025 FIXME("can't get gif background color\n");
4026 return 0xffffffff;
4027}
4028
4030{
4032 IWICBitmapFrameDecode *frame;
4033 int cur_frame=0;
4034 LONG disposal;
4035 BOOL bgcolor_set = FALSE;
4036 DWORD bgcolor = 0;
4037 HRESULT hr;
4038
4039 if(active_frame > image->current_frame) {
4040 hr = IWICBitmapDecoder_GetFrame(bitmap->image.decoder, image->current_frame, &frame);
4041 if(FAILED(hr))
4042 return hresult_to_status(hr);
4043 disposal = 0;
4044 get_gif_frame_property(frame, &GUID_MetadataFormatGCE, L"Disposal", &disposal);
4045 IWICBitmapFrameDecode_Release(frame);
4046
4047 if(disposal == GIF_DISPOSE_RESTORE_TO_BKGND)
4048 cur_frame = image->current_frame;
4049 else if(disposal != GIF_DISPOSE_RESTORE_TO_PREV)
4050 cur_frame = image->current_frame+1;
4051 }
4052
4053 while(cur_frame != active_frame) {
4054 hr = IWICBitmapDecoder_GetFrame(bitmap->image.decoder, cur_frame, &frame);
4055 if(FAILED(hr))
4056 return hresult_to_status(hr);
4057 disposal = 0;
4058 get_gif_frame_property(frame, &GUID_MetadataFormatGCE, L"Disposal", &disposal);
4059
4060 if(disposal==GIF_DISPOSE_UNSPECIFIED || disposal==GIF_DISPOSE_DO_NOT_DISPOSE) {
4061 hr = blit_gif_frame(bitmap, frame, cur_frame==0);
4062 if(FAILED(hr))
4063 return hresult_to_status(hr);
4064 }else if(disposal == GIF_DISPOSE_RESTORE_TO_BKGND) {
4065 UINT left, top, width, height, i, j;
4066
4067 if(!bgcolor_set) {
4069 bgcolor_set = TRUE;
4070 }
4071
4072 hr = get_gif_frame_rect(frame, &left, &top, &width, &height);
4073 if(FAILED(hr))
4074 return hresult_to_status(hr);
4075 for(i=top; i<top+height && i<bitmap->height; i++) {
4076 DWORD *bits = (DWORD*)(bitmap->bits+i*bitmap->stride);
4077 for(j=left; j<left+width && j<bitmap->width; j++)
4078 bits[j] = bgcolor;
4079 }
4080 }
4081
4082 IWICBitmapFrameDecode_Release(frame);
4083 cur_frame++;
4084 }
4085
4086 hr = IWICBitmapDecoder_GetFrame(bitmap->image.decoder, active_frame, &frame);
4087 if(FAILED(hr))
4088 return hresult_to_status(hr);
4089
4090 hr = blit_gif_frame(bitmap, frame, cur_frame==0);
4091 IWICBitmapFrameDecode_Release(frame);
4092 if(FAILED(hr))
4093 return hresult_to_status(hr);
4094
4095 image->current_frame = active_frame;
4096 return Ok;
4097}
4098
4100{
4101 return decode_image_wic(stream, &GUID_ContainerFormatIco, NULL, image);
4102}
4103
4105{
4108
4109 status = decode_image_wic(stream, &GUID_ContainerFormatBmp, NULL, image);
4110
4111 bitmap = (GpBitmap*)*image;
4112
4113 if (status == Ok && bitmap->format == PixelFormat32bppARGB)
4114 {
4115 /* WIC supports bmp files with alpha, but gdiplus does not */
4116 bitmap->format = PixelFormat32bppRGB;
4117 }
4118
4119 return status;
4120}
4121
4123{
4124 return decode_image_wic(stream, &GUID_ContainerFormatJpeg, NULL, image);
4125}
4126
4128{
4130 BOOL has_tRNS = FALSE;
4131 HRESULT hr;
4132 BYTE header[8];
4133
4134 seek.QuadPart = 8;
4135 do
4136 {
4137 ULARGE_INTEGER chunk_start;
4138 ULONG bytesread, chunk_size;
4139
4140 hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
4141 if (FAILED(hr)) break;
4142
4143 hr = IStream_Read(pIStream, header, 8, &bytesread);
4144 if (FAILED(hr) || bytesread < 8) break;
4145
4146 chunk_size = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
4147 if (!memcmp(&header[4], "tRNS", 4))
4148 {
4149 has_tRNS = TRUE;
4150 break;
4151 }
4152
4153 seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */
4154 } while (memcmp(&header[4], "IDAT", 4) && memcmp(&header[4], "IEND", 4));
4155
4156 TRACE("has_tRNS = %d\n", has_tRNS);
4157 return has_tRNS;
4158}
4159
4161{
4163 IWICBitmapFrameDecode *frame;
4165 HRESULT hr;
4166 GUID format;
4167 BOOL force_conversion = FALSE;
4168
4169 status = initialize_decoder_wic(stream, &GUID_ContainerFormatPng, &decoder);
4170 if (status != Ok)
4171 return status;
4172
4173 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
4174 if (hr == S_OK)
4175 {
4176 hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
4177 if (hr == S_OK)
4178 {
4179 if (IsEqualGUID(&format, &GUID_WICPixelFormat8bppGray))
4180 force_conversion = TRUE;
4181 else if ((IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed) ||
4182 IsEqualGUID(&format, &GUID_WICPixelFormat4bppIndexed) ||
4183 IsEqualGUID(&format, &GUID_WICPixelFormat2bppIndexed) ||
4184 IsEqualGUID(&format, &GUID_WICPixelFormat1bppIndexed) ||
4185 IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR)) &&
4187 force_conversion = TRUE;
4188
4189 status = decode_frame_wic(decoder, force_conversion, 0, png_metadata_reader, image);
4190 }
4191 else
4193
4194 IWICBitmapFrameDecode_Release(frame);
4195 }
4196 else
4198
4199 IWICBitmapDecoder_Release(decoder);
4200 return status;
4201}
4202
4204{
4206 UINT frame_count;
4208 HRESULT hr;
4209
4210 status = initialize_decoder_wic(stream, &GUID_ContainerFormatGif, &decoder);
4211 if(status != Ok)
4212 return status;
4213
4214 hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
4215 if(FAILED(hr))
4216 return hresult_to_status(hr);
4217
4218 status = decode_frame_wic(decoder, frame_count > 1, 0, gif_metadata_reader, image);
4219 IWICBitmapDecoder_Release(decoder);
4220 if(status != Ok)
4221 return status;
4222
4223 if(frame_count > 1) {
4224 free((*image)->palette);
4225 (*image)->palette = NULL;
4226 }
4227 return Ok;
4228}
4229
4231{
4232 return decode_image_wic(stream, &GUID_ContainerFormatTiff, NULL, image);
4233}
4234
4236
4238{
4240 BOOL is_placeable = FALSE;
4243 METAHEADER mh;
4244 HMETAFILE hmf;
4245 HRESULT hr;
4246 ULONG size;
4247 void *buf;
4248
4249 hr = IStream_Read(stream, &mh, sizeof(mh), &size);
4250 if (hr != S_OK || size != sizeof(mh))
4251 return GenericError;
4252
4253 /* detect whether stream starts with a WmfPlaceablefileheader */
4254 if (*(UINT32 *)&mh == WMF_PLACEABLE_KEY)
4255 {
4256 seek.QuadPart = 0;
4257 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4258 if (FAILED(hr)) return hresult_to_status(hr);
4259
4260 hr = IStream_Read(stream, &pfh, sizeof(pfh), &size);
4261 if (hr != S_OK || size != sizeof(pfh))
4262 return GenericError;
4263
4264 hr = IStream_Read(stream, &mh, sizeof(mh), &size);
4265 if (hr != S_OK || size != sizeof(mh))
4266 return GenericError;
4267
4268 is_placeable = TRUE;
4269 }
4270
4271 seek.QuadPart = is_placeable ? sizeof(pfh) : 0;
4272 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4273 if (FAILED(hr)) return hresult_to_status(hr);
4274
4275 buf = malloc(mh.mtSize * 2);
4276 if (!buf) return OutOfMemory;
4277
4278 hr = IStream_Read(stream, buf, mh.mtSize * 2, &size);
4279 if (hr != S_OK || size != mh.mtSize * 2)
4280 {
4281 free(buf);
4282 return GenericError;
4283 }
4284
4285 hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf);
4286 free(buf);
4287 if (!hmf)
4288 return GenericError;
4289
4290 status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile);
4291 if (status != Ok)
4292 DeleteMetaFile(hmf);
4293 return status;
4294}
4295
4297{
4300
4301 TRACE("%p %p\n", stream, image);
4302
4303 if (!stream || !image)
4304 return InvalidParameter;
4305
4307 if (status != Ok)
4308 {
4309 TRACE("Could not load metafile\n");
4310 return status;
4311 }
4312
4313 *image = (GpImage *)metafile;
4314 TRACE("<-- %p\n", *image);
4315
4316 return Ok;
4317}
4318
4320{
4322 ENHMETAHEADER emh;
4323 HENHMETAFILE hemf;
4325 HRESULT hr;
4326 ULONG size;
4327 void *buf;
4328
4329 hr = IStream_Read(stream, &emh, sizeof(emh), &size);
4330 if (hr != S_OK || size != sizeof(emh) || emh.dSignature != ENHMETA_SIGNATURE)
4331 return GenericError;
4332
4333 seek.QuadPart = 0;
4334 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4335 if (FAILED(hr)) return hresult_to_status(hr);
4336
4337 buf = malloc(emh.nBytes);
4338 if (!buf) return OutOfMemory;
4339
4340 hr = IStream_Read(stream, buf, emh.nBytes, &size);
4341 if (hr != S_OK || size != emh.nBytes)
4342 {
4343 free(buf);
4344 return GenericError;
4345 }
4346
4347 hemf = SetEnhMetaFileBits(emh.nBytes, buf);
4348 free(buf);
4349 if (!hemf)
4350 return GenericError;
4351
4353 if (status != Ok)
4354 DeleteEnhMetaFile(hemf);
4355 return status;
4356}
4357
4359{
4362
4363 TRACE("%p %p\n", stream, image);
4364
4365 if (!stream || !image)
4366 return InvalidParameter;
4367
4369 if (status != Ok)
4370 {
4371 TRACE("Could not load metafile\n");
4372 return status;
4373 }
4374
4375 *image = (GpImage *)metafile;
4376 TRACE("<-- %p\n", *image);
4377
4378 return Ok;
4379}
4380
4383
4385
4386typedef GpStatus (*select_image_func)(GpImage *image, UINT active_frame);
4387
4388typedef struct image_codec {
4394
4395typedef enum {
4406
4407static const struct image_codec codecs[NUM_CODECS];
4408
4410{
4411 BYTE signature[8];
4412 const BYTE *pattern, *mask;
4414 HRESULT hr;
4415 ULONG bytesread;
4416 int i;
4417 DWORD j, sig;
4418
4419 /* seek to the start of the stream */
4420 seek.QuadPart = 0;
4421 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4422 if (FAILED(hr)) return hresult_to_status(hr);
4423
4424 /* read the first 8 bytes */
4425 /* FIXME: This assumes all codecs have signatures <= 8 bytes in length */
4426 hr = IStream_Read(stream, signature, 8, &bytesread);
4427 if (FAILED(hr)) return hresult_to_status(hr);
4428 if (hr == S_FALSE || bytesread == 0) return GenericError;
4429
4430 for (i = 0; i < NUM_CODECS; i++) {
4431 if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) &&
4432 bytesread >= codecs[i].info.SigSize)
4433 {
4434 for (sig=0; sig<codecs[i].info.SigCount; sig++)
4435 {
4436 pattern = &codecs[i].info.SigPattern[codecs[i].info.SigSize*sig];
4437 mask = &codecs[i].info.SigMask[codecs[i].info.SigSize*sig];
4438 for (j=0; j<codecs[i].info.SigSize; j++)
4439 if ((signature[j] & mask[j]) != pattern[j])
4440 break;
4441 if (j == codecs[i].info.SigSize)
4442 {
4443 *result = &codecs[i];
4444 return Ok;
4445 }
4446 }
4447 }
4448 }
4449
4450 TRACE("no match for %lu byte signature %x %x %x %x %x %x %x %x\n", bytesread,
4453
4454 return GenericError;
4455}
4456
4458{
4459 int i;
4460
4461 for (i = 0; i < NUM_CODECS; i++) {
4462 if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) &&
4463 IsEqualIID(&codecs[i].info.FormatID, &image->format))
4464 {
4465 *result = &codecs[i];
4466 return Ok;
4467 }
4468 }
4469
4470 TRACE("no match for format: %s\n", wine_dbgstr_guid(&image->format));
4471 return GenericError;
4472}
4473
4475 UINT frame)
4476{
4477 GpStatus stat;
4478 const struct image_codec *codec = NULL;
4479
4480 TRACE("(%p,%s,%u)\n", image, debugstr_guid(dimensionID), frame);
4481
4482 if (!image || !dimensionID)
4483 return InvalidParameter;
4484 if(!image_lock(image))
4485 return ObjectBusy;
4486
4487 if (frame >= image->frame_count)
4488 WARN("requested frame %u, but image has only %u\n", frame, image->frame_count);
4489 /* rely on codec->select_func() to fail */
4490
4491 if (image->type != ImageTypeBitmap && image->type != ImageTypeMetafile)
4492 {
4493 WARN("invalid image type %d\n", image->type);
4495 return InvalidParameter;
4496 }
4497
4498 if (image->current_frame == frame)
4499 {
4501 return Ok;
4502 }
4503
4504 if (!image->decoder)
4505 {
4506 TRACE("image doesn't have an associated decoder\n");
4508 return Ok;
4509 }
4510
4511 /* choose an appropriate image decoder */
4513 if (stat != Ok)
4514 {
4515 WARN("can't find decoder info\n");
4517 return stat;
4518 }
4519
4520 stat = codec->select_func(image, frame);
4522 return stat;
4523}
4524
4526{
4527 GpStatus stat;
4529 HRESULT hr;
4530 const struct image_codec *codec=NULL;
4531
4532 TRACE("%p %p\n", stream, image);
4533
4534 if (!stream || !image)
4535 return InvalidParameter;
4536
4537 /* choose an appropriate image decoder */
4538 stat = get_decoder_info(stream, &codec);
4539 if (stat != Ok) return stat;
4540
4541 /* seek to the start of the stream */
4542 seek.QuadPart = 0;
4543 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4544 if (FAILED(hr)) return hresult_to_status(hr);
4545
4546 /* call on the image decoder to do the real work */
4547 stat = codec->decode_func(stream, image);
4548
4549 /* take note of the original data format */
4550 if (stat == Ok)
4551 {
4552 memcpy(&(*image)->format, &codec->info.FormatID, sizeof(GUID));
4553 return Ok;
4554 }
4555
4556 return stat;
4557}
4558
4559/* FIXME: no ICM */
4561{
4562 TRACE("%p %p\n", stream, image);
4563
4565}
4566
4568{
4569 static int calls;
4570
4571 TRACE("(%p,%lu)\n", image, propId);
4572
4573 if(!image)
4574 return InvalidParameter;
4575
4576 if(!(calls++))
4577 FIXME("not implemented\n");
4578
4579 return NotImplemented;
4580}
4581
4583{
4584 static int calls;
4585
4586 if (!image || !item) return InvalidParameter;
4587
4588 TRACE("(%p,%p:%#lx,%u,%lu,%p)\n", image, item, item->id, item->type, item->length, item->value);
4589
4590 if(!(calls++))
4591 FIXME("not implemented\n");
4592
4593 return Ok;
4594}
4595
4597 GDIPCONST CLSID *clsidEncoder,
4598 GDIPCONST EncoderParameters *encoderParams)
4599{
4600 GpStatus stat;
4601 IStream *stream;
4602
4603 TRACE("%p (%s) %p %p\n", image, debugstr_w(filename), clsidEncoder, encoderParams);
4604
4605 if (!image || !filename|| !clsidEncoder)
4606 return InvalidParameter;
4607
4608 /* this might release an old file stream held by the encoder so we can re-create it below */
4610
4612 if (stat != Ok)
4613 return GenericError;
4614
4615 stat = GdipSaveImageToStream(image, stream, clsidEncoder, encoderParams);
4616
4617 IStream_Release(stream);
4618 return stat;
4619}
4620
4621/*************************************************************************
4622 * Encoding functions -
4623 * These functions encode an image in different image file formats.
4624 */
4625
4627{
4629 HRESULT hr;
4630
4631 TRACE("%p,%s\n", stream, wine_dbgstr_guid(container));
4632
4633 terminate_encoder_wic(image); /* terminate previous encoder if it exists */
4634
4635 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
4636 if (FAILED(hr)) return hresult_to_status(hr);
4637 hr = IWICImagingFactory_CreateEncoder(factory, container, NULL, &image->encoder);
4638 IWICImagingFactory_Release(factory);
4639 if (FAILED(hr))
4640 {
4641 image->encoder = NULL;
4642 return hresult_to_status(hr);
4643 }
4644
4645 hr = IWICBitmapEncoder_Initialize(image->encoder, stream, WICBitmapEncoderNoCache);
4646 if (FAILED(hr))
4647 {
4648 IWICBitmapEncoder_Release(image->encoder);
4649 image->encoder = NULL;
4650 return hresult_to_status(hr);
4651 }
4652 return Ok;
4653}
4654
4656{
4657 if (!image->encoder)
4658 return Ok;
4659 else
4660 {
4661 HRESULT hr = IWICBitmapEncoder_Commit(image->encoder);
4662 IWICBitmapEncoder_Release(image->encoder);
4663 image->encoder = NULL;
4664 return hresult_to_status(hr);
4665 }
4666}
4667
4669{
4670 GpStatus stat;
4672 IWICBitmapFrameEncode *frameencode;
4673 IPropertyBag2 *encoderoptions;
4674 GUID container_format;
4675 HRESULT hr;
4676 UINT width, height;
4677 PixelFormat gdipformat=0;
4678 const WICPixelFormatGUID *desired_wicformat;
4679 WICPixelFormatGUID wicformat;
4680 GpRect rc;
4681 BitmapData lockeddata;
4682 UINT i;
4683
4684 if (image->type != ImageTypeBitmap)
4685 return GenericError;
4686
4687 bitmap = (GpBitmap*)image;
4688
4691
4692 rc.X = 0;
4693 rc.Y = 0;
4694 rc.Width = width;
4695 rc.Height = height;
4696
4697 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &encoderoptions);
4698
4699 if (SUCCEEDED(hr)) /* created frame */
4700 {
4701 hr = IWICBitmapEncoder_GetContainerFormat(encoder, &container_format);
4702 if (SUCCEEDED(hr) && IsEqualGUID(&container_format, &GUID_ContainerFormatPng))
4703 {
4704 /* disable PNG filters for faster encoding */
4705 PROPBAG2 filter_option = { .pstrName = (LPOLESTR) L"FilterOption" };
4706 VARIANT filter_value;
4707 VariantInit(&filter_value);
4708 V_VT(&filter_value) = VT_UI1;
4709 V_UI1(&filter_value) = WICPngFilterNone;
4710 hr = IPropertyBag2_Write(encoderoptions, 1, &filter_option, &filter_value);
4711 }
4712
4713 if (SUCCEEDED(hr))
4714 hr = IWICBitmapFrameEncode_Initialize(frameencode, encoderoptions);
4715
4716 if (SUCCEEDED(hr))
4717 hr = IWICBitmapFrameEncode_SetSize(frameencode, width, height);
4718
4719 if (SUCCEEDED(hr))
4720 hr = IWICBitmapFrameEncode_SetResolution(frameencode, image->xres, image->yres);
4721
4722 if (SUCCEEDED(hr))
4723 {
4724 for (i=0; pixel_formats[i].wic_format; i++)
4725 {
4726 if (pixel_formats[i].gdip_format == bitmap->format)
4727 {
4728 desired_wicformat = pixel_formats[i].wic_format;
4729 gdipformat = bitmap->format;
4730 break;
4731 }
4732 }
4733 if (!gdipformat)
4734 {
4735 desired_wicformat = &GUID_WICPixelFormat32bppBGRA;
4736 gdipformat = PixelFormat32bppARGB;
4737 }
4738
4739 memcpy(&wicformat, desired_wicformat, sizeof(GUID));
4740 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &wicformat);
4741 }
4742
4743 if (SUCCEEDED(hr) && !IsEqualGUID(desired_wicformat, &wicformat))
4744 {
4745 /* Encoder doesn't support this bitmap's format. */
4746 gdipformat = 0;
4747 for (i=0; pixel_formats[i].wic_format; i++)
4748 {
4749 if (IsEqualGUID(&wicformat, pixel_formats[i].wic_format))
4750 {
4751 gdipformat = pixel_formats[i].gdip_format;
4752 break;
4753 }
4754 }
4755 if (!gdipformat)
4756 {
4757 ERR("Cannot support encoder format %s\n", debugstr_guid(&wicformat));
4758 hr = E_FAIL;
4759 }
4760 }
4761
4762 if (SUCCEEDED(hr) && IsIndexedPixelFormat(gdipformat) && image->palette)
4763 hr = set_palette(frameencode, image->palette);
4764
4765 if (SUCCEEDED(hr))
4766 {
4767 stat = GdipBitmapLockBits(bitmap, &rc, ImageLockModeRead, gdipformat,
4768 &lockeddata);
4769
4770 if (stat == Ok)
4771 {
4772 UINT row_size = (lockeddata.Width * PIXELFORMATBPP(gdipformat) + 7)/8;
4773 BYTE *row;
4774
4775 /* write one row at a time in case stride is negative */
4776 row = lockeddata.Scan0;
4777 for (i=0; i<lockeddata.Height; i++)
4778 {
4779 hr = IWICBitmapFrameEncode_WritePixels(frameencode, 1, row_size, row_size, row);
4780 if (FAILED(hr)) break;
4781 row += lockeddata.Stride;
4782 }
4783
4784 GdipBitmapUnlockBits(bitmap, &lockeddata);
4785 }
4786 else
4787 hr = E_FAIL;
4788 }
4789
4790 if (SUCCEEDED(hr))
4791 hr = IWICBitmapFrameEncode_Commit(frameencode);
4792
4793 IWICBitmapFrameEncode_Release(frameencode);
4794 IPropertyBag2_Release(encoderoptions);
4795 }
4796
4797 return hresult_to_status(hr);
4798}
4799
4801{
4802 int param_idx, value_idx;
4803
4804 if (!params)
4805 return FALSE;
4806
4807 for (param_idx = 0; param_idx < params->Count; param_idx++)
4808 {
4809 EncoderParameter param = params->Parameter[param_idx];
4810 if (param.Type == EncoderParameterValueTypeLong && IsEqualCLSID(&param.Guid, &param_guid))
4811 {
4812 ULONG *value_array = (ULONG*) param.Value;
4813 for (value_idx = 0; value_idx < param.NumberOfValues; value_idx++)
4814 {
4815 if (value_array[value_idx] == val)
4816 return TRUE;
4817 }
4818 }
4819 }
4820 return FALSE;
4821}
4822
4825{
4826 GpStatus status, terminate_status;
4827
4828 if (image->type != ImageTypeBitmap)
4829 return GenericError;
4830
4832
4833 if (status == Ok)
4834 status = encode_frame_wic(image->encoder, image);
4835
4837 {
4838 /* always try to terminate, but if something already failed earlier, keep the old status. */
4839 terminate_status = terminate_encoder_wic(image);
4840 if (status == Ok)
4841 status = terminate_status;
4842 }
4843
4844 return status;
4845}
4846
4849{
4850 return encode_image_wic(image, stream, &GUID_ContainerFormatBmp, params);
4851}
4852
4855{
4856 return encode_image_wic(image, stream, &GUID_ContainerFormatTiff, params);
4857}
4858
4861{
4862 return encode_image_wic(image, stream, &GUID_ContainerFormatPng, params);
4863}
4864
4867{
4868 return encode_image_wic(image, stream, &GUID_ContainerFormatJpeg, params);
4869}
4870
4873{
4874 return encode_image_wic(image, stream, &GUID_ContainerFormatGif, params);
4875}
4876
4877/*****************************************************************************
4878 * GdipSaveImageToStream [GDIPLUS.@]
4879 */
4882{
4883 GpStatus stat;
4884 encode_image_func encode_image;
4885 int i;
4886
4887 TRACE("%p, %p, %s, %p\n", image, stream, wine_dbgstr_guid(clsid), params);
4888
4889 if(!image || !stream)
4890 return InvalidParameter;
4891
4892 /* select correct encoder */
4893 encode_image = NULL;
4894 for (i = 0; i < NUM_CODECS; i++) {
4895 if ((codecs[i].info.Flags & ImageCodecFlagsEncoder) &&
4896 IsEqualCLSID(clsid, &codecs[i].info.Clsid))
4897 encode_image = codecs[i].encode_func;
4898 }
4899 if (encode_image == NULL)
4900 return UnknownImageFormat;
4901
4902 stat = encode_image(image, stream, params);
4903
4904 return stat;
4905}
4906
4907/*****************************************************************************
4908 * GdipSaveAdd [GDIPLUS.@]
4909 *
4910 * Like GdipSaveAddImage(), but encode the currently active frame of the given image into the file
4911 * or stream that is currently being encoded.
4912 */
4914{
4916}
4917
4918/*****************************************************************************
4919 * GdipSaveAddImage [GDIPLUS.@]
4920 *
4921 * Encode the currently active frame of additional_image into the file or stream that is currently
4922 * being encoded by the image given in the image parameter. The first frame of a multi-frame image
4923 * must be encoded using the normal GdipSaveImageToStream() or GdipSaveImageToFile() functions,
4924 * but with the "MultiFrame" encoding parameter set. The multi-frame encoding process must be
4925 * finished after adding the last frame by calling GdipSaveAdd() with the "Flush" encoding parameter
4926 * set.
4927 */
4930{
4931 TRACE("%p, %p, %p\n", image, additional_image, params);
4932
4933 if (!image || !additional_image || !params)
4934 return InvalidParameter;
4935
4936 if (!image->encoder)
4937 return Win32Error;
4938
4939 if (has_encoder_param_long(params, EncoderSaveFlag, EncoderValueFlush))
4942 return encode_frame_wic(image->encoder, additional_image);
4943 else
4944 return InvalidParameter;
4945}
4946
4947/*****************************************************************************
4948 * GdipGetImagePalette [GDIPLUS.@]
4949 */
4951{
4952 INT count;
4953
4954 TRACE("(%p,%p,%i)\n", image, palette, size);
4955
4956 if (!image || !palette)
4957 return InvalidParameter;
4958
4959 count = image->palette ? image->palette->Count : 0;
4960
4961 if (size < (sizeof(UINT)*2+sizeof(ARGB)*count))
4962 {
4963 TRACE("<-- InsufficientBuffer\n");
4964 return InsufficientBuffer;
4965 }
4966
4967 if (image->palette)
4968 {
4969 palette->Flags = image->palette->Flags;
4970 palette->Count = image->palette->Count;
4971 memcpy(palette->Entries, image->palette->Entries, sizeof(ARGB)*image->palette->Count);
4972 }
4973 else
4974 {
4975 palette->Flags = 0;
4976 palette->Count = 0;
4977 }
4978 return Ok;
4979}
4980
4981/*****************************************************************************
4982 * GdipSetImagePalette [GDIPLUS.@]
4983 */
4986{
4987 ColorPalette *new_palette;
4988
4989 TRACE("(%p,%p)\n", image, palette);
4990
4991 if(!image || !palette || palette->Count > 256)
4992 return InvalidParameter;
4993
4994 new_palette = calloc(1, 2 * sizeof(UINT) + palette->Count * sizeof(ARGB));
4995 if (!new_palette) return OutOfMemory;
4996
4997 free(image->palette);
4998 image->palette = new_palette;
4999 image->palette->Flags = palette->Flags;
5000 image->palette->Count = palette->Count;
5001 memcpy(image->palette->Entries, palette->Entries, sizeof(ARGB)*palette->Count);
5002
5003 return Ok;
5004}
5005
5006/*************************************************************************
5007 * Encoders -
5008 * Structures that represent which formats we support for encoding.
5009 */
5010
5011/* ImageCodecInfo creation routines taken from libgdiplus */
5012static const WCHAR bmp_codecname[] = L"Built-in BMP";
5013static const WCHAR bmp_extension[] = L"*.BMP;*.DIB;*.RLE";
5014static const WCHAR bmp_mimetype[] = L"image/bmp";
5015static const WCHAR bmp_format[] = L"BMP";
5016static const BYTE bmp_sig_pattern[] = { 0x42, 0x4D };
5017static const BYTE bmp_sig_mask[] = { 0xFF, 0xFF };
5018
5019static const WCHAR jpeg_codecname[] = L"Built-in JPEG";
5020static const WCHAR jpeg_extension[] = L"*.JPG;*.JPEG;*.JPE;*.JFIF";
5021static const WCHAR jpeg_mimetype[] = L"image/jpeg";
5022static const WCHAR jpeg_format[] = L"JPEG";
5023static const BYTE jpeg_sig_pattern[] = { 0xFF, 0xD8 };
5024static const BYTE jpeg_sig_mask[] = { 0xFF, 0xFF };
5025
5026static const WCHAR gif_codecname[] = L"Built-in GIF";
5027static const WCHAR gif_extension[] = L"*.GIF";
5028static const WCHAR gif_mimetype[] = L"image/gif";
5029static const WCHAR gif_format[] = L"GIF";
5030static const BYTE gif_sig_pattern[12] = "GIF87aGIF89a";
5031static const BYTE gif_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5032
5033static const WCHAR tiff_codecname[] = L"Built-in TIFF";
5034static const WCHAR tiff_extension[] = L"*.TIFF;*.TIF";
5035static const WCHAR tiff_mimetype[] = L"image/tiff";
5036static const WCHAR tiff_format[] = L"TIFF";
5037static const BYTE tiff_sig_pattern[] = {0x49,0x49,42,0,0x4d,0x4d,0,42};
5038static const BYTE tiff_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5039
5040static const WCHAR emf_codecname[] = L"Built-in EMF";
5041static const WCHAR emf_extension[] = L"*.EMF";
5042static const WCHAR emf_mimetype[] = L"image/x-emf";
5043static const WCHAR emf_format[] = L"EMF";
5044static const BYTE emf_sig_pattern[] = { 0x01, 0x00, 0x00, 0x00 };
5045static const BYTE emf_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF };
5046
5047static const WCHAR wmf_codecname[] = L"Built-in WMF";
5048static const WCHAR wmf_extension[] = L"*.WMF";
5049static const WCHAR wmf_mimetype[] = L"image/x-wmf";
5050static const WCHAR wmf_format[] = L"WMF";
5051static const BYTE wmf_sig_pattern[] = { 0xd7, 0xcd };
5052static const BYTE wmf_sig_mask[] = { 0xFF, 0xFF };
5053
5054static const WCHAR png_codecname[] = L"Built-in PNG";
5055static const WCHAR png_extension[] = L"*.PNG";
5056static const WCHAR png_mimetype[] = L"image/png";
5057static const WCHAR png_format[] = L"PNG";
5058static const BYTE png_sig_pattern[] = { 137, 80, 78, 71, 13, 10, 26, 10, };
5059static const BYTE png_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
5060
5061static const WCHAR ico_codecname[] = L"Built-in ICO";
5062static const WCHAR ico_extension[] = L"*.ICO";
5063static const WCHAR ico_mimetype[] = L"image/x-icon";
5064static const WCHAR ico_format[] = L"ICO";
5065static const BYTE ico_sig_pattern[] = { 0x00, 0x00, 0x01, 0x00 };
5066static const BYTE ico_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF };
5067
5068static const struct image_codec codecs[NUM_CODECS] = {
5069 {
5070 { /* BMP */
5071 /* Clsid */ { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5072 /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5073 /* CodecName */ bmp_codecname,
5074 /* DllName */ NULL,
5075 /* FormatDescription */ bmp_format,
5076 /* FilenameExtension */ bmp_extension,
5077 /* MimeType */ bmp_mimetype,
5079 /* Version */ 1,
5080 /* SigCount */ 1,
5081 /* SigSize */ 2,
5082 /* SigPattern */ bmp_sig_pattern,
5083 /* SigMask */ bmp_sig_mask,
5084 },
5088 },
5089 {
5090 { /* JPEG */
5091 /* Clsid */ { 0x557cf401, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5092 /* FormatID */ { 0xb96b3caeU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5093 /* CodecName */ jpeg_codecname,
5094 /* DllName */ NULL,
5095 /* FormatDescription */ jpeg_format,
5096 /* FilenameExtension */ jpeg_extension,
5097 /* MimeType */ jpeg_mimetype,
5099 /* Version */ 1,
5100 /* SigCount */ 1,
5101 /* SigSize */ 2,
5102 /* SigPattern */ jpeg_sig_pattern,
5103 /* SigMask */ jpeg_sig_mask,
5104 },
5108 },
5109 {
5110 { /* GIF */
5111 /* Clsid */ { 0x557cf402, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5112 /* FormatID */ { 0xb96b3cb0U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5113 /* CodecName */ gif_codecname,
5114 /* DllName */ NULL,
5115 /* FormatDescription */ gif_format,
5116 /* FilenameExtension */ gif_extension,
5117 /* MimeType */ gif_mimetype,
5119 /* Version */ 1,
5120 /* SigCount */ 2,
5121 /* SigSize */ 6,
5122 /* SigPattern */ gif_sig_pattern,
5123 /* SigMask */ gif_sig_mask,
5124 },
5128 },
5129 {
5130 { /* TIFF */
5131 /* Clsid */ { 0x557cf405, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5132 /* FormatID */ { 0xb96b3cb1U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5133 /* CodecName */ tiff_codecname,
5134 /* DllName */ NULL,
5135 /* FormatDescription */ tiff_format,
5136 /* FilenameExtension */ tiff_extension,
5137 /* MimeType */ tiff_mimetype,
5139 /* Version */ 1,
5140 /* SigCount */ 2,
5141 /* SigSize */ 4,
5142 /* SigPattern */ tiff_sig_pattern,
5143 /* SigMask */ tiff_sig_mask,
5144 },
5148 },
5149 {
5150 { /* EMF */
5151 /* Clsid */ { 0x557cf403, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5152 /* FormatID */ { 0xb96b3cacU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5153 /* CodecName */ emf_codecname,
5154 /* DllName */ NULL,
5155 /* FormatDescription */ emf_format,
5156 /* FilenameExtension */ emf_extension,
5157 /* MimeType */ emf_mimetype,
5159 /* Version */ 1,
5160 /* SigCount */ 1,
5161 /* SigSize */ 4,
5162 /* SigPattern */ emf_sig_pattern,
5163 /* SigMask */ emf_sig_mask,
5164 },
5165 NULL,
5167 NULL
5168 },
5169 {
5170 { /* WMF */
5171 /* Clsid */ { 0x557cf404, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5172 /* FormatID */ { 0xb96b3cadU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5173 /* CodecName */ wmf_codecname,
5174 /* DllName */ NULL,
5175 /* FormatDescription */ wmf_format,
5176 /* FilenameExtension */ wmf_extension,
5177 /* MimeType */ wmf_mimetype,
5179 /* Version */ 1,
5180 /* SigCount */ 1,
5181 /* SigSize */ 2,
5182 /* SigPattern */ wmf_sig_pattern,
5183 /* SigMask */ wmf_sig_mask,
5184 },
5185 NULL,
5187 NULL
5188 },
5189 {
5190 { /* PNG */
5191 /* Clsid */ { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5192 /* FormatID */ { 0xb96b3cafU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5193 /* CodecName */ png_codecname,
5194 /* DllName */ NULL,
5195 /* FormatDescription */ png_format,
5196 /* FilenameExtension */ png_extension,
5197 /* MimeType */ png_mimetype,
5199 /* Version */ 1,
5200 /* SigCount */ 1,
5201 /* SigSize */ 8,
5202 /* SigPattern */ png_sig_pattern,
5203 /* SigMask */ png_sig_mask,
5204 },
5208 },
5209 {
5210 { /* ICO */
5211 /* Clsid */ { 0x557cf407, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
5212 /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
5213 /* CodecName */ ico_codecname,
5214 /* DllName */ NULL,
5215 /* FormatDescription */ ico_format,
5216 /* FilenameExtension */ ico_extension,
5217 /* MimeType */ ico_mimetype,
5219 /* Version */ 1,
5220 /* SigCount */ 1,
5221 /* SigSize */ 4,
5222 /* SigPattern */ ico_sig_pattern,
5223 /* SigMask */ ico_sig_mask,
5224 },
5225 NULL,
5228 },
5229};
5230
5231/*****************************************************************************
5232 * GdipGetImageDecodersSize [GDIPLUS.@]
5233 */
5235{
5236 int decoder_count=0;
5237 int i;
5238 TRACE("%p %p\n", numDecoders, size);
5239
5240 if (!numDecoders || !size)
5241 return InvalidParameter;
5242
5243 for (i=0; i<NUM_CODECS; i++)
5244 {
5245 if (codecs[i].info.Flags & ImageCodecFlagsDecoder)
5246 decoder_count++;
5247 }
5248
5249 *numDecoders = decoder_count;
5250 *size = decoder_count * sizeof(ImageCodecInfo);
5251
5252 return Ok;
5253}
5254
5255/*****************************************************************************
5256 * GdipGetImageDecoders [GDIPLUS.@]
5257 */
5259{
5260 int i, decoder_count=0;
5261 TRACE("%u %u %p\n", numDecoders, size, decoders);
5262
5263 if (!decoders ||
5264 size != numDecoders * sizeof(ImageCodecInfo))
5265 return GenericError;
5266
5267 for (i=0; i<NUM_CODECS; i++)
5268 {
5269 if (codecs[i].info.Flags & ImageCodecFlagsDecoder)
5270 {
5271 if (decoder_count == numDecoders) return GenericError;
5272 memcpy(&decoders[decoder_count], &codecs[i].info, sizeof(ImageCodecInfo));
5273 decoder_count++;
5274 }
5275 }
5276
5277 if (decoder_count < numDecoders) return GenericError;
5278
5279 return Ok;
5280}
5281
5282/*****************************************************************************
5283 * GdipGetImageEncodersSize [GDIPLUS.@]
5284 */
5286{
5287 int encoder_count=0;
5288 int i;
5289 TRACE("%p %p\n", numEncoders, size);
5290
5291 if (!numEncoders || !size)
5292 return InvalidParameter;
5293
5294 for (i=0; i<NUM_CODECS; i++)
5295 {
5296 if (codecs[i].info.Flags & ImageCodecFlagsEncoder)
5297 encoder_count++;
5298 }
5299
5300 *numEncoders = encoder_count;
5301 *size = encoder_count * sizeof(ImageCodecInfo);
5302
5303 return Ok;
5304}
5305
5306/*****************************************************************************
5307 * GdipGetImageEncoders [GDIPLUS.@]
5308 */
5310{
5311 int i, encoder_count=0;
5312 TRACE("%u %u %p\n", numEncoders, size, encoders);
5313
5314 if (!encoders ||
5315 size != numEncoders * sizeof(ImageCodecInfo))
5316 return GenericError;
5317
5318 for (i=0; i<NUM_CODECS; i++)
5319 {
5320 if (codecs[i].info.Flags & ImageCodecFlagsEncoder)
5321 {
5322 if (encoder_count == numEncoders) return GenericError;
5323 memcpy(&encoders[encoder_count], &codecs[i].info, sizeof(ImageCodecInfo));
5324 encoder_count++;
5325 }
5326 }
5327
5328 if (encoder_count < numEncoders) return GenericError;
5329
5330 return Ok;
5331}
5332
5334 GDIPCONST CLSID* clsidEncoder, UINT *size)
5335{
5336 static int calls;
5337
5338 TRACE("(%p,%s,%p)\n", image, debugstr_guid(clsidEncoder), size);
5339
5340 if(!(calls++))
5341 FIXME("not implemented\n");
5342
5343 *size = 0;
5344
5345 return NotImplemented;
5346}
5347
5349{
5350 BITMAPV4HEADER bmh;
5351 HDC hdc;
5353
5355
5356 memset(&bmh, 0, sizeof(bmh));
5357 bmh.bV4Size = sizeof(bmh);
5358 bmh.bV4Width = 1;
5359 bmh.bV4Height = 1;
5361 bmh.bV4BitCount = 16;
5362
5363 GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO*)&bmh, DIB_RGB_COLORS);
5364
5365 if (bmh.bV4RedMask == 0x7c00 &&
5366 bmh.bV4GreenMask == 0x3e0 &&
5367 bmh.bV4BlueMask == 0x1f)
5368 {
5370 }
5371 else if (bmh.bV4RedMask == 0xf800 &&
5372 bmh.bV4GreenMask == 0x7e0 &&
5373 bmh.bV4BlueMask == 0x1f)
5374 {
5376 }
5377 else
5378 {
5379 FIXME("unrecognized bitfields %lx,%lx,%lx\n", bmh.bV4RedMask,
5380 bmh.bV4GreenMask, bmh.bV4BlueMask);
5382 }
5383
5384 DeleteDC(hdc);
5385
5386 return result;
5387}
5388
5389/*****************************************************************************
5390 * GdipCreateBitmapFromHBITMAP [GDIPLUS.@]
5391 */
5393{
5394 BITMAP bm;
5397 BitmapData lockeddata;
5398#ifdef __REACTOS__
5399 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
5400#else
5401 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
5402#endif
5403 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
5404
5405 TRACE("%p %p %p\n", hbm, hpal, bitmap);
5406
5407 if(!hbm || !bitmap)
5408 return InvalidParameter;
5409
5410 if (GetObjectA(hbm, sizeof(bm), &bm) != sizeof(bm))
5411 return InvalidParameter;
5412
5413 /* TODO: Figure out the correct format for 16, 32, 64 bpp */
5414 switch(bm.bmBitsPixel) {
5415 case 1:
5417 break;
5418 case 4:
5420 break;
5421 case 8:
5423 break;
5424 case 16:
5427 return InvalidParameter;
5428 break;
5429 case 24:
5431 break;
5432 case 32:
5434 break;
5435 case 48:
5437 break;
5438 default:
5439 FIXME("don't know how to handle %d bpp\n", bm.bmBitsPixel);
5440 return InvalidParameter;
5441 }
5442
5444 format, NULL, bitmap);
5445
5446 if (retval == Ok)
5447 {
5449 format, &lockeddata);
5450 if (retval == Ok)
5451 {
5452 HDC hdc;
5453 INT src_height;
5454
5456
5459
5461
5462 src_height = abs(pbmi->bmiHeader.biHeight);
5463 pbmi->bmiHeader.biHeight = -src_height;
5464
5465 GetDIBits(hdc, hbm, 0, src_height, lockeddata.Scan0, pbmi, DIB_RGB_COLORS);
5466
5467 DeleteDC(hdc);
5468
5469 GdipBitmapUnlockBits(*bitmap, &lockeddata);
5470 }
5471
5472 /* According to the tests hpal is ignored */
5473 if (retval == Ok && pbmi->bmiHeader.biBitCount <= 8)
5474 {
5476 int i, num_palette_entries;
5477
5478 num_palette_entries = pbmi->bmiHeader.biClrUsed;
5479 if (!num_palette_entries)
5480 num_palette_entries = 1 << pbmi->bmiHeader.biBitCount;
5481
5482 palette = calloc(1, sizeof(ColorPalette) + sizeof(ARGB) * (num_palette_entries - 1));
5483 if (!palette)
5485 else
5486 {
5487 palette->Flags = 0;
5488 palette->Count = num_palette_entries;
5489
5490 for (i=0; i<num_palette_entries; i++)
5491 {
5492 palette->Entries[i] = 0xff000000 | pbmi->bmiColors[i].rgbRed << 16 |
5494 }
5495
5496 retval = GdipSetImagePalette(&(*bitmap)->image, palette);
5497 }
5498
5499 free(palette);
5500 }
5501
5502 if (retval != Ok)
5503 {
5504 GdipDisposeImage(&(*bitmap)->image);
5505 *bitmap = NULL;
5506 }
5507 }
5508
5509 return retval;
5510}
5511
5512/*****************************************************************************
5513 * GdipCreateEffect [GDIPLUS.@]
5514 */
5516{
5517 CGpEffect *ef = NULL;
5519
5520 TRACE("(%s, %p)\n", debugstr_guid(&guid), effect);
5521
5522 if(!effect)
5523 return InvalidParameter;
5524
5525 if (IsEqualGUID(&guid, &BlurEffectGuid))
5526 {
5527 type = BlurEffect;
5528 }
5529 else if (IsEqualGUID(&guid, &SharpenEffectGuid))
5530 {
5532 }
5533 else if (IsEqualGUID(&guid, &TintEffectGuid))
5534 {
5535 type = TintEffect;
5536 }
5537 else if (IsEqualGUID(&guid, &RedEyeCorrectionEffectGuid))
5538 {
5540 }
5541 else if (IsEqualGUID(&guid, &ColorMatrixEffectGuid))
5542 {
5544 }
5545 else if (IsEqualGUID(&guid, &ColorLUTEffectGuid))
5546 {
5548 }
5549 else if (IsEqualGUID(&guid, &BrightnessContrastEffectGuid))
5550 {
5552 }
5553 else if (IsEqualGUID(&guid, &HueSaturationLightnessEffectGuid))
5554 {
5556 }
5557 else if (IsEqualGUID(&guid, &ColorBalanceEffectGuid))
5558 {
5560 }
5561 else if (IsEqualGUID(&guid, &LevelsEffectGuid))
5562 {
5564 }
5565 else if (IsEqualGUID(&guid, &ColorCurveEffectGuid))
5566 {
5568 }
5569 else
5570 {
5571 *effect = NULL;
5572 return Win32Error;
5573 }
5574
5575 ef = malloc(sizeof(CGpEffect));
5576 ef->type = type;
5577 *effect = ef;
5578
5579 return Ok;
5580}
5581
5582/*****************************************************************************
5583 * GdipDeleteEffect [GDIPLUS.@]
5584 */
5586{
5587 TRACE("(%p)\n", effect);
5588
5589 if (!effect)
5590 return InvalidParameter;
5591
5592 free(effect);
5593 return Ok;
5594}
5595
5596/*****************************************************************************
5597 * GdipGetEffectParameterSize [GDIPLUS.@]
5598 */
5600{
5601 UINT sz = 0;
5602 GpStatus status = Ok;
5603
5604 TRACE("(%p,%p)\n", effect, size);
5605
5606 if (!effect || !size)
5607 return InvalidParameter;
5608
5609 switch (effect->type)
5610 {
5611 case BlurEffect:
5612 sz = sizeof(struct BlurParams);
5613 break;
5614 case SharpenEffect:
5615 sz = sizeof(struct SharpenParams);
5616 break;
5617 case TintEffect:
5618 sz = sizeof(struct TintParams);
5619 break;
5621 sz = sizeof(struct RedEyeCorrectionParams);
5622 break;
5623 case ColorMatrixEffect:
5624 sz = sizeof(ColorMatrix);
5625 break;
5626 case ColorLUTEffect:
5627 sz = sizeof(struct ColorLUTParams);
5628 break;
5630 sz = sizeof(struct BrightnessContrastParams);
5631 break;
5633 sz = sizeof(struct HueSaturationLightnessParams);
5634 break;
5635 case ColorBalanceEffect:
5636 sz = sizeof(struct ColorBalanceParams);
5637 break;
5638 case LevelsEffect:
5639 sz = sizeof(struct LevelsParams);
5640 break;
5641 case ColorCurveEffect:
5642 sz = sizeof(struct ColorCurveParams);
5643 break;
5644 default:
5646 break;
5647 }
5648
5649 *size = sz;
5650 return status;
5651}
5652
5653/*****************************************************************************
5654 * GdipSetEffectParameters [GDIPLUS.@]
5655 */
5657 const VOID *params, const UINT size)
5658{
5659 static int calls;
5660
5661 TRACE("(%p,%p,%u)\n", effect, params, size);
5662
5663 if(!(calls++))
5664 FIXME("not implemented\n");
5665
5666 return NotImplemented;
5667}
5668
5669/*****************************************************************************
5670 * GdipGetImageFlags [GDIPLUS.@]
5671 */
5673{
5674 TRACE("%p %p\n", image, flags);
5675
5676 if(!image || !flags)
5677 return InvalidParameter;
5678
5679 *flags = image->flags;
5680
5681 return Ok;
5682}
5683
5685{
5686 TRACE("(%d, %p)\n", control, param);
5687
5688 switch(control){
5690 if(param)
5691 FIXME("TestControlForceBilinear not handled\n");
5692 break;
5693 case TestControlNoICM:
5694 if(param)
5695 FIXME("TestControlNoICM not handled\n");
5696 break;
5698 *((DWORD*)param) = 3102;
5699 break;
5700 }
5701
5702 return Ok;
5703}
5704
5706{
5707 TRACE("%p\n", image);
5708
5709 return Ok;
5710}
5711
5712/*****************************************************************************
5713 * GdipGetImageThumbnail [GDIPLUS.@]
5714 */
5716 GpImage **ret_image, GetThumbnailImageAbort cb,
5717 VOID * cb_data)
5718{
5719 GpStatus stat;
5720 GpGraphics *graphics;
5721 UINT srcwidth, srcheight;
5722
5723 TRACE("(%p %u %u %p %p %p)\n",
5724 image, width, height, ret_image, cb, cb_data);
5725
5726 if (!image || !ret_image)
5727 return InvalidParameter;
5728
5729 if (!width) width = 120;
5730 if (!height) height = 120;
5731
5732 GdipGetImageWidth(image, &srcwidth);
5733 GdipGetImageHeight(image, &srcheight);
5734
5736 NULL, (GpBitmap**)ret_image);
5737
5738 if (stat == Ok)
5739 {
5740 stat = GdipGetImageGraphicsContext(*ret_image, &graphics);
5741
5742 if (stat == Ok)
5743 {
5744 stat = GdipDrawImageRectRectI(graphics, image,
5745 0, 0, width, height, 0, 0, srcwidth, srcheight, UnitPixel,
5746 NULL, NULL, NULL);
5747
5748 GdipDeleteGraphics(graphics);
5749 }
5750
5751 if (stat != Ok)
5752 {
5753 GdipDisposeImage(*ret_image);
5754 *ret_image = NULL;
5755 }
5756 }
5757
5758 return stat;
5759}
5760
5761/*****************************************************************************
5762 * GdipImageRotateFlip [GDIPLUS.@]
5763 */
5765{
5766 GpBitmap *new_bitmap;
5768 int bpp, bytesperpixel;
5769 BOOL rotate_90, flip_x, flip_y;
5770 int src_x_offset, src_y_offset;
5771 LPBYTE src_origin;
5772 UINT x, y, width, height;
5773 BitmapData dst_lock;
5774 GpStatus stat;
5775
5776 TRACE("(%p, %u)\n", image, type);
5777
5778 if (!image)
5779 return InvalidParameter;
5780 if (!image_lock(image))
5781 return ObjectBusy;
5782
5783 rotate_90 = type&1;
5784 flip_x = (type&6) == 2 || (type&6) == 4;
5785 flip_y = (type&3) == 1 || (type&3) == 2;
5786
5787 if (image->type != ImageTypeBitmap)
5788 {
5789 FIXME("Not implemented for type %i\n", image->type);
5791 return NotImplemented;
5792 }
5793
5794 bitmap = (GpBitmap*)image;
5795 bpp = PIXELFORMATBPP(bitmap->format);
5796
5797 if (bpp < 8)
5798 {
5799 FIXME("Not implemented for %i bit images\n", bpp);
5801 return NotImplemented;
5802 }
5803
5804 if (rotate_90)
5805 {
5806 width = bitmap->height;
5807 height = bitmap->width;
5808 }
5809 else
5810 {
5811 width = bitmap->width;
5812 height = bitmap->height;
5813 }
5814
5815 bytesperpixel = bpp/8;
5816
5817 stat = GdipCreateBitmapFromScan0(width, height, 0, bitmap->format, NULL, &new_bitmap);
5818
5819 if (stat == Ok)
5820 {
5821 stat = GdipBitmapLockBits(new_bitmap, NULL, ImageLockModeWrite, bitmap->format, &dst_lock);
5822
5823 if (stat == Ok)
5824 {
5825 LPBYTE src_row, src_pixel;
5826 LPBYTE dst_row, dst_pixel;
5827
5828 src_origin = bitmap->bits;
5829 if (flip_x) src_origin += bytesperpixel * (bitmap->width - 1);
5830 if (flip_y) src_origin += bitmap->stride * (bitmap->height - 1);
5831
5832 if (rotate_90)
5833 {
5834 if (flip_y) src_x_offset = -bitmap->stride;
5835 else src_x_offset = bitmap->stride;
5836 if (flip_x) src_y_offset = -bytesperpixel;
5837 else src_y_offset = bytesperpixel;
5838 }
5839 else
5840 {
5841 if (flip_x) src_x_offset = -bytesperpixel;
5842 else src_x_offset = bytesperpixel;
5843 if (flip_y) src_y_offset = -bitmap->stride;
5844 else src_y_offset = bitmap->stride;
5845 }
5846
5847 src_row = src_origin;
5848 dst_row = dst_lock.Scan0;
5849 for (y=0; y<height; y++)
5850 {
5851 src_pixel = src_row;
5852 dst_pixel = dst_row;
5853 for (x=0; x<width; x++)
5854 {
5855 /* FIXME: This could probably be faster without memcpy. */
5856 memcpy(dst_pixel, src_pixel, bytesperpixel);
5857 dst_pixel += bytesperpixel;
5858 src_pixel += src_x_offset;
5859 }
5860 src_row += src_y_offset;
5861 dst_row += dst_lock.Stride;
5862 }
5863
5864 GdipBitmapUnlockBits(new_bitmap, &dst_lock);
5865 move_bitmap(bitmap, new_bitmap, FALSE);
5866 }
5867 else GdipDisposeImage(&new_bitmap->image);
5868 }
5869
5871 return stat;
5872}
5873
5874/*****************************************************************************
5875 * GdipImageSetAbort [GDIPLUS.@]
5876 */
5878{
5879 TRACE("(%p, %p)\n", image, pabort);
5880
5881 if (!image)
5882 return InvalidParameter;
5883
5884 if (pabort)
5885 FIXME("Abort callback is not supported.\n");
5886
5887 return Ok;
5888}
5889
5890/*****************************************************************************
5891 * GdipBitmapConvertFormat [GDIPLUS.@]
5892 */
5894 PaletteType palettetype, ColorPalette *palette, REAL alphathreshold)
5895{
5896 FIXME("(%p, 0x%08x, %d, %d, %p, %f): stub\n", bitmap, format, dithertype, palettetype, palette, alphathreshold);
5897 return NotImplemented;
5898}
5899
5900static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5901{
5902 ch0[ color >> 24 ]++;
5903 ch1[(color >> 16) & 0xff]++;
5904 ch2[(color >> 8) & 0xff]++;
5905 ch3[ color & 0xff]++;
5906}
5907
5908static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5909{
5910 BYTE alpha = color >> 24;
5911
5912 ch0[alpha]++;
5913 ch1[(((color >> 16) & 0xff) * alpha) / 0xff]++;
5914 ch2[(((color >> 8) & 0xff) * alpha) / 0xff]++;
5915 ch3[(( color & 0xff) * alpha) / 0xff]++;
5916}
5917
5918static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5919{
5920 ch0[(color >> 16) & 0xff]++;
5921 ch1[(color >> 8) & 0xff]++;
5922 ch2[ color & 0xff]++;
5923}
5924
5925static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5926{
5927 ch0[(76 * ((color >> 16) & 0xff) + 150 * ((color >> 8) & 0xff) + 29 * (color & 0xff)) / 0xff]++;
5928}
5929
5930static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5931{
5932 ch0[color & 0xff]++;
5933}
5934
5935static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5936{
5937 ch0[(color >> 8) & 0xff]++;
5938}
5939
5940static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5941{
5942 ch0[(color >> 16) & 0xff]++;
5943}
5944
5945static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5946{
5947 ch0[(color >> 24) & 0xff]++;
5948}
5949
5950/*****************************************************************************
5951 * GdipBitmapGetHistogram [GDIPLUS.@]
5952 */
5954 UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5955{
5956 static void (* const set_histogram_point[])(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) =
5957 {
5966 };
5967 UINT width, height, x, y;
5968
5969 TRACE("(%p, %d, %u, %p, %p, %p, %p)\n", bitmap, format, num_of_entries,
5970 ch0, ch1, ch2, ch3);
5971
5972 if (!bitmap || num_of_entries != 256)
5973 return InvalidParameter;
5974
5975 /* Make sure passed channel pointers match requested format */
5976 switch (format)
5977 {
5980 if (!ch0 || !ch1 || !ch2 || !ch3)
5981 return InvalidParameter;
5982 memset(ch0, 0, num_of_entries * sizeof(UINT));
5983 memset(ch1, 0, num_of_entries * sizeof(UINT));
5984 memset(ch2, 0, num_of_entries * sizeof(UINT));
5985 memset(ch3, 0, num_of_entries * sizeof(UINT));
5986 break;
5987 case HistogramFormatRGB:
5988 if (!ch0 || !ch1 || !ch2 || ch3)
5989 return InvalidParameter;
5990 memset(ch0, 0, num_of_entries * sizeof(UINT));
5991 memset(ch1, 0, num_of_entries * sizeof(UINT));
5992 memset(ch2, 0, num_of_entries * sizeof(UINT));
5993 break;
5995 case HistogramFormatB:
5996 case HistogramFormatG:
5997 case HistogramFormatR:
5998 case HistogramFormatA:
5999 if (!ch0 || ch1 || ch2 || ch3)
6000 return InvalidParameter;
6001 memset(ch0, 0, num_of_entries * sizeof(UINT));
6002 break;
6003 default:
6004 WARN("Invalid histogram format requested, %d\n", format);
6005 return InvalidParameter;
6006 }
6007
6008 GdipGetImageWidth(&bitmap->image, &width);
6009 GdipGetImageHeight(&bitmap->image, &height);
6010
6011 for (y = 0; y < height; y++)
6012 for (x = 0; x < width; x++)
6013 {
6014 ARGB color;
6015
6017 set_histogram_point[format](color, ch0, ch1, ch2, ch3);
6018 }
6019
6020 return Ok;
6021}
6022
6023/*****************************************************************************
6024 * GdipBitmapGetHistogramSize [GDIPLUS.@]
6025 */
6027{
6028 TRACE("(%d, %p)\n", format, num_of_entries);
6029
6030 if (!num_of_entries)
6031 return InvalidParameter;
6032
6033 *num_of_entries = 256;
6034 return Ok;
6035}
6036
6038 BOOL transparent, GpBitmap *bitmap)
6039{
6042 HRESULT hr;
6044 IWICPalette *wic_palette;
6045
6046 if (!bitmap) return InvalidParameter;
6047 if (palette->Count < desired) return GenericError;
6048
6050 if (status != Ok) return status;
6051
6052 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
6053 if (hr != S_OK)
6054 {
6056 return hresult_to_status(hr);
6057 }
6058
6059 hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
6060 if (hr == S_OK)
6061 {
6063
6064 /* PixelFormat24bppRGB actually stores the bitmap bits as BGR. */
6065 hr = IWICImagingFactory_CreateBitmapFromMemory(factory, data.Width, data.Height,
6066 &GUID_WICPixelFormat24bppBGR, data.Stride, data.Stride * data.Width, data.Scan0, &bitmap);
6067 if (hr == S_OK)
6068 {
6069 hr = IWICPalette_InitializeFromBitmap(wic_palette, (IWICBitmapSource *)bitmap, desired, transparent);
6070 if (hr == S_OK)
6071 {
6072 palette->Flags = 0;
6073 IWICPalette_GetColorCount(wic_palette, &palette->Count);
6074 IWICPalette_GetColors(wic_palette, palette->Count, (UINT *)palette->Entries, &palette->Count);
6075 }
6076
6077 IWICBitmap_Release(bitmap);
6078 }
6079
6080 IWICPalette_Release(wic_palette);
6081 }
6082
6083 IWICImagingFactory_Release(factory);
6085
6086 return hresult_to_status(hr);
6087}
6088
6089/*****************************************************************************
6090 * GdipInitializePalette [GDIPLUS.@]
6091 */
6093 PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap)
6094{
6095 TRACE("(%p,%d,%d,%d,%p)\n", palette, type, desired, transparent, bitmap);
6096
6097 if (!palette) return InvalidParameter;
6098
6099 switch (type)
6100 {
6101 case PaletteTypeCustom:
6102 return Ok;
6103
6104 case PaletteTypeOptimal:
6105 return create_optimal_palette(palette, desired, transparent, bitmap);
6106
6107 /* WIC palette type enumeration matches these gdiplus enums */
6108 case PaletteTypeFixedBW:
6116 {
6117 ColorPalette *wic_palette;
6118 GpStatus status = Ok;
6119
6120 wic_palette = get_palette(NULL, (WICBitmapPaletteType)type);
6121 if (!wic_palette) return OutOfMemory;
6122
6123 if (palette->Count >= wic_palette->Count)
6124 {
6125 palette->Flags = wic_palette->Flags;
6126 palette->Count = wic_palette->Count;
6127 memcpy(palette->Entries, wic_palette->Entries, wic_palette->Count * sizeof(wic_palette->Entries[0]));
6128 }
6129 else
6131
6132 free(wic_palette);
6133
6134 return status;
6135 }
6136
6137 default:
6138 FIXME("unknown palette type %d\n", type);
6139 break;
6140 }
6141
6142 return InvalidParameter;
6143}
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
#define stat
Definition: acwin.h:100
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
HINSTANCE hInstance
Definition: charmap.c:19
Definition: list.h:37
RECT rect
Definition: combotst.c:67
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:582
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
DWORD bpp
Definition: surface.c:185
float REAL
Definition: types.h:41
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: combase.c:709
static const char b64[]
Definition: base64.c:67
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GENERIC_READ
Definition: compat.h:135
#define lstrcpyW
Definition: compat.h:749
@ VT_BLOB
Definition: compat.h:2330
@ VT_UI8
Definition: compat.h:2315
@ VT_LPSTR
Definition: compat.h:2324
@ VT_R4
Definition: compat.h:2299
@ VT_UI2
Definition: compat.h:2312
@ VT_LPWSTR
Definition: compat.h:2325
@ VT_R8
Definition: compat.h:2300
@ VT_I8
Definition: compat.h:2314
@ VT_I1
Definition: compat.h:2310
@ VT_I4
Definition: compat.h:2298
@ VT_BOOL
Definition: compat.h:2306
@ VT_I2
Definition: compat.h:2297
@ VT_UI4
Definition: compat.h:2313
@ VT_EMPTY
Definition: compat.h:2295
@ VT_VECTOR
Definition: compat.h:2340
@ VT_UI1
Definition: compat.h:2311
#define lstrlenW
Definition: compat.h:750
GpStatus WINGDIPAPI GdipGetDpiX(GpGraphics *graphics, REAL *dpi)
Definition: graphics.c:6988
GpStatus WINGDIPAPI GdipCreateStreamOnFile(GDIPCONST WCHAR *filename, UINT access, IStream **stream)
Definition: graphics.c:2593
GpStatus WINGDIPAPI GdipGetDpiY(GpGraphics *graphics, REAL *dpi)
Definition: graphics.c:7002
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2616
GpStatus WINGDIPAPI GdipDrawImageRectRectI(GpGraphics *graphics, GpImage *image, INT dstx, INT dsty, INT dstwidth, INT dstheight, INT srcx, INT srcy, INT srcwidth, INT srcheight, GpUnit srcUnit, GDIPCONST GpImageAttributes *imageAttributes, DrawImageAbort callback, VOID *callbackData)
Definition: graphics.c:3574
GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y)
Definition: graphics.c:3026
static const WCHAR emf_codecname[]
Definition: image.c:5040
static GpStatus load_wmf(IStream *stream, GpMetafile **metafile)
Definition: image.c:4237
GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR *filename, GpBitmap **bitmap)
Definition: image.c:1437
static PropertyItem * create_prop(PROPID propid, PROPVARIANT *value)
Definition: image.c:3351
static PropertyItem * get_gif_comment(IWICMetadataReader *reader)
Definition: image.c:3061
static HRESULT png_read_chromaticity(IWICMetadataReader *reader, GpBitmap *bitmap)
Definition: image.c:3488
static const BYTE bmp_sig_mask[]
Definition: image.c:5017
GpStatus WINGDIPAPI GdipGetPropertySize(GpImage *image, UINT *size, UINT *count)
Definition: image.c:2670
static void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:457
static const BYTE wmf_sig_pattern[]
Definition: image.c:5051
GpStatus encode_image_png(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4859
static const BYTE tiff_sig_mask[]
Definition: image.c:5038
GpStatus WINGDIPAPI GdipDeleteEffect(CGpEffect *effect)
Definition: image.c:5585
GpStatus WINGDIPAPI GdipSaveAddImage(GpImage *image, GpImage *additional_image, GDIPCONST EncoderParameters *params)
Definition: image.c:4928
GpStatus WINGDIPAPI GdipGetImageVerticalResolution(GpImage *image, REAL *res)
Definition: image.c:2311
static GpStatus decode_image_wmf(IStream *stream, GpImage **image)
Definition: image.c:4296
static void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:495
static HRESULT png_read_whitepoint(IWICMetadataReader *reader, GpBitmap *bitmap)
Definition: image.c:3465
GpStatus WINGDIPAPI GdipGetImageRawFormat(GpImage *image, GUID *format)
Definition: image.c:2287
GpStatus WINGDIPAPI GdipGetImagePalette(GpImage *image, ColorPalette *palette, INT size)
Definition: image.c:4950
GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size)
Definition: image.c:5285
static void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:486
static const WCHAR tiff_format[]
Definition: image.c:5036
GpStatus WINGDIPAPI GdipGetImageFlags(GpImage *image, UINT *flags)
Definition: image.c:5672
GpStatus WINGDIPAPI GdipBitmapConvertFormat(GpBitmap *bitmap, PixelFormat format, DitherType dithertype, PaletteType palettetype, ColorPalette *palette, REAL alphathreshold)
Definition: image.c:5893
GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream *stream, GDIPCONST CLSID *clsid, GDIPCONST EncoderParameters *params)
Definition: image.c:4880
static GpStatus decode_image_icon(IStream *stream, GpImage **image)
Definition: image.c:4099
static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5935
static DWORD blend_argb_no_bkgnd_alpha(DWORD src, DWORD bkgnd)
Definition: image.c:1523
GpStatus WINGDIPAPI GdipBitmapGetHistogramSize(HistogramFormat format, UINT *num_of_entries)
Definition: image.c:6026
GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height, PixelFormat format, GpBitmap *srcBitmap, GpBitmap **dstBitmap)
Definition: image.c:1377
GpStatus WINGDIPAPI GdipGetAllPropertyItems(GpImage *image, UINT size, UINT count, PropertyItem *buf)
Definition: image.c:2746
static const WCHAR bmp_extension[]
Definition: image.c:5013
GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width)
Definition: image.c:2323
GpStatus terminate_encoder_wic(GpImage *image)
Definition: image.c:4655
static const WCHAR wmf_mimetype[]
Definition: image.c:5049
GpStatus WINGDIPAPI GdipGetEffectParameterSize(CGpEffect *effect, UINT *size)
Definition: image.c:5599
GpStatus WINGDIPAPI GdipGetImageItemData(GpImage *image, ImageItemData *item)
Definition: image.c:2128
ImageFormat
Definition: image.c:4395
@ EMF
Definition: image.c:4400
@ WMF
Definition: image.c:4401
@ NUM_CODECS
Definition: image.c:4404
@ BMP
Definition: image.c:4396
@ TIFF
Definition: image.c:4399
@ ICO
Definition: image.c:4403
@ PNG
Definition: image.c:4402
@ GIF
Definition: image.c:4398
@ JPEG
Definition: image.c:4397
static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5918
static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5900
static HRESULT png_read_gamma(IWICMetadataReader *reader, GpBitmap *bitmap)
Definition: image.c:3444
static GpStatus decode_image_jpeg(IStream *stream, GpImage **image)
Definition: image.c:4122
static GpStatus decode_image_png(IStream *stream, GpImage **image)
Definition: image.c:4160
GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height)
Definition: image.c:2213
GpStatus WINGDIPAPI GdipGetImageDimension(GpImage *image, REAL *width, REAL *height)
Definition: image.c:2168
GpStatus(* decode_image_func)(IStream *stream, GpImage **image)
Definition: image.c:4384
GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, PixelFormat format, BYTE *scan0, GpBitmap **bitmap)
Definition: image.c:1793
static void getpixel_16bppARGB1555(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:219
GpStatus WINGDIPAPI GdipGetImageDecodersSize(UINT *numDecoders, UINT *size)
Definition: image.c:5234
static GpStatus decode_image_emf(IStream *stream, GpImage **image)
Definition: image.c:4358
static void getpixel_64bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:296
#define PropertyTagTypeSShort
Definition: image.c:2520
static void generate_halftone_palette(ARGB *entries, UINT count)
Definition: image.c:1741
static void getpixel_16bppRGB565(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:209
static const WCHAR png_mimetype[]
Definition: image.c:5056
static GpStatus load_emf(IStream *stream, GpMetafile **metafile)
Definition: image.c:4319
static void getpixel_4bppIndexed(BYTE *index, const BYTE *row, UINT x)
Definition: image.c:179
GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image, GDIPCONST ColorPalette *palette)
Definition: image.c:4984
static const WCHAR jpeg_mimetype[]
Definition: image.c:5021
GpStatus WINGDIPAPI GdipCreateBitmapFromResource(HINSTANCE hInstance, GDIPCONST WCHAR *lpBitmapName, GpBitmap **bitmap)
Definition: image.c:1500
static HRESULT get_gif_frame_rect(IWICBitmapFrameDecode *frame, UINT *left, UINT *top, UINT *width, UINT *height)
Definition: image.c:3952
GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage *image, GDIPCONST GUID *dimensionID, UINT *count)
Definition: image.c:2855
static void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:441
static void get_gif_frame_property(IWICBitmapFrameDecode *frame, const GUID *format, const WCHAR *property, LONG *value)
Definition: image.c:3192
static const WCHAR bmp_format[]
Definition: image.c:5015
#define PropertyTagTypeFloat
Definition: image.c:2521
static DWORD get_gif_background_color(GpBitmap *bitmap)
Definition: image.c:4003
static const BYTE ico_sig_pattern[]
Definition: image.c:5065
GpStatus WINGDIPAPI GdipCreateCachedBitmap(GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedbmp)
Definition: image.c:1925
GpStatus WINGDIPAPI GdipSetPropertyItem(GpImage *image, GDIPCONST PropertyItem *item)
Definition: image.c:4582
GpStatus WINGDIPAPI GdipRemovePropertyItem(GpImage *image, PROPID propId)
Definition: image.c:4567
static void add_property(GpBitmap *bitmap, PropertyItem *item)
Definition: image.c:2951
static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5908
GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image, GpGraphics **graphics)
Definition: image.c:2195
static void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:510
static GpStatus encode_image_tiff(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4853
void(* metadata_reader_func)(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT frame)
Definition: image.c:3748
static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5945
static const WCHAR wmf_format[]
Definition: image.c:5050
static HRESULT set_palette(IWICBitmapFrameEncode *frame, ColorPalette *palette)
Definition: image.c:126
#define convert_rgb_to_indexed(getpixel_function, setpixel_function)
#define PropertyTagTypeDouble
Definition: image.c:2522
GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR *filename, GDIPCONST CLSID *clsidEncoder, GDIPCONST EncoderParameters *encoderParams)
Definition: image.c:4596
static void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:474
GpStatus WINGDIPAPI GdipBitmapGetHistogram(GpBitmap *bitmap, HistogramFormat format, UINT num_of_entries, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5953
GpStatus WINGDIPAPI GdipImageGetFrameDimensionsCount(GpImage *image, UINT *count)
Definition: image.c:2875
static GpStatus encode_image_gif(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4871
static void getpixel_1bppIndexed(BYTE *index, const BYTE *row, UINT x)
Definition: image.c:174
GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height, GpGraphics *target, GpBitmap **bitmap)
Definition: image.c:1597
GpStatus WINGDIPAPI GdipBitmapSetResolution(GpBitmap *bitmap, REAL xdpi, REAL ydpi)
Definition: image.c:1239
static const WCHAR bmp_mimetype[]
Definition: image.c:5014
GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO *info, VOID *bits, GpBitmap **bitmap)
Definition: image.c:1462
static const WCHAR tiff_mimetype[]
Definition: image.c:5035
static GpStatus get_decoder_info(IStream *stream, const struct image_codec **result)
Definition: image.c:4409
static GpStatus free_image_data(GpImage *image)
Definition: image.c:2071
static void getpixel_32bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:241
static const BYTE emf_sig_pattern[]
Definition: image.c:5044
GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap *bitmap, GDIPCONST GpRect *rect, UINT flags, PixelFormat format, BitmapData *lockeddata)
Definition: image.c:1107
static const BYTE jpeg_sig_mask[]
Definition: image.c:5024
GpStatus convert_pixels(INT width, INT height, INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, ColorPalette *dst_palette, INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *src_palette)
Definition: image.c:589
static void getpixel_8bppIndexed(BYTE *index, const BYTE *row, UINT x)
Definition: image.c:187
GpStatus WINGDIPAPI GdipDeleteCachedBitmap(GpCachedBitmap *cachedbmp)
Definition: image.c:2002
GpStatus WINGDIPAPI GdipGetPropertyCount(GpImage *image, UINT *num)
Definition: image.c:2346
GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap *bitmap, CGpEffect *effect, RECT *roi, BOOL useAuxData, VOID **auxData, INT *auxDataSize)
Definition: image.c:151
GpStatus WINGDIPAPI GdipGetEncoderParameterListSize(GpImage *image, GDIPCONST CLSID *clsidEncoder, UINT *size)
Definition: image.c:5333
static const BYTE png_sig_pattern[]
Definition: image.c:5058
static const WCHAR jpeg_format[]
Definition: image.c:5022
GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image)
Definition: image.c:2099
#define convert_indexed_to_rgb(getpixel_function, setpixel_function)
static void getpixel_64bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:287
GpStatus WINGDIPAPI GdipGetImagePixelFormat(GpImage *image, PixelFormat *format)
Definition: image.c:2272
static const WCHAR gif_format[]
Definition: image.c:5029
static GpStatus encode_image_BMP(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4847
GpStatus WINGDIPAPI GdipLoadImageFromFile(GDIPCONST WCHAR *filename, GpImage **image)
Definition: image.c:2918
static void getpixel_48bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:278
static const BYTE gif_sig_mask[]
Definition: image.c:5031
static HRESULT png_read_time(IWICMetadataReader *reader, GpBitmap *bitmap)
Definition: image.c:3519
static GpStatus decode_image_bmp(IStream *stream, GpImage **image)
Definition: image.c:4104
static void setpixel_16bppGrayScale(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:435
GpStatus WINGDIPAPI GdipGetImageThumbnail(GpImage *image, UINT width, UINT height, GpImage **ret_image, GetThumbnailImageAbort cb, VOID *cb_data)
Definition: image.c:5715
GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap *bitmap, INT x, INT y, ARGB *color)
Definition: image.c:310
static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
Definition: image.c:2028
static const WCHAR emf_mimetype[]
Definition: image.c:5042
const WICPixelFormatGUID * wic_format
Definition: image.c:47
GpStatus(* encode_image_func)(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4381
GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap *bitmap, INT x, INT y, ARGB color)
Definition: image.c:521
#define PropertyTagTypeSByte
Definition: image.c:2519
static GpStatus decode_image_gif(IStream *stream, GpImage **image)
Definition: image.c:4203
GpStatus WINGDIPAPI GdipCreateHICONFromBitmap(GpBitmap *bitmap, HICON *hicon)
Definition: image.c:1948
GpStatus WINGDIPAPI GdipSetEffectParameters(CGpEffect *effect, const VOID *params, const UINT size)
Definition: image.c:5656
GpStatus WINGDIPAPI GdipDrawCachedBitmap(GpGraphics *graphics, GpCachedBitmap *cachedbmp, INT x, INT y)
Definition: image.c:2015
static void getpixel_16bppGrayScale(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:192
static const struct @407 pixel_formats[]
static void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:503
GpStatus WINGDIPAPI GdipImageSetAbort(GpImage *image, GdiplusAbort *pabort)
Definition: image.c:5877
static UINT propvariant_size(PROPVARIANT *value)
Definition: image.c:2437
static const WCHAR gif_extension[]
Definition: image.c:5027
GpStatus(* select_image_func)(GpImage *image, UINT active_frame)
Definition: image.c:4386
static GpStatus encode_frame_wic(IWICBitmapEncoder *encoder, GpImage *image)
Definition: image.c:4668
WICBitmapPaletteType palette_type
Definition: image.c:50
static const BYTE png_sig_mask[]
Definition: image.c:5059
static void getpixel_24bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:232
static GpStatus select_frame_gif(GpImage *image, UINT active_frame)
Definition: image.c:4029
static PropertyItem * get_gif_transparent_idx(IWICMetadataReader *reader)
Definition: image.c:3179
static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT active_frame)
Definition: image.c:3631
static const WCHAR ico_format[]
Definition: image.c:5064
static PropertyItem * get_gif_background(IWICMetadataReader *reader)
Definition: image.c:3111
PixelFormat gdip_format
Definition: image.c:48
static GpStatus create_optimal_palette(ColorPalette *palette, INT desired, BOOL transparent, GpBitmap *bitmap)
Definition: image.c:6037
GpStatus WINGDIPAPI GdipGetImagePaletteSize(GpImage *image, INT *size)
Definition: image.c:2248
static void setpixel_4bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x, ColorPalette *palette)
Definition: image.c:426
static const WCHAR ico_extension[]
Definition: image.c:5062
GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *dimensionID, UINT frame)
Definition: image.c:4474
static BOOL has_png_transparency_chunk(IStream *pIStream)
Definition: image.c:4127
GpStatus WINGDIPAPI GdipGetPropertyIdList(GpImage *image, UINT num, PROPID *list)
Definition: image.c:2369
static const WCHAR tiff_extension[]
Definition: image.c:5034
static GpStatus encode_image_jpeg(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4865
#define convert_rgb_to_rgb(getpixel_function, setpixel_function)
#define convert_indexed_to_indexed(getpixel_function, setpixel_function)
static PixelFormat get_16bpp_format(HBITMAP hbm)
Definition: image.c:5348
static const WCHAR png_codecname[]
Definition: image.c:5054
static const WCHAR jpeg_codecname[]
Definition: image.c:5019
static void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:480
GpStatus WINGDIPAPI GdipGetImageType(GpImage *image, ImageType *type)
Definition: image.c:2299
static const struct image_format_dimension image_format_dimensions[]
Definition: image.c:2848
GpStatus WINGDIPAPI GdipFindFirstImageItem(GpImage *image, ImageItemData *item)
Definition: image.c:2113
static HRESULT png_read_text(IWICMetadataReader *reader, GpBitmap *bitmap, BOOL **seen_text)
Definition: image.c:3393
GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream *stream, GpImage **image)
Definition: image.c:4525
static const WCHAR emf_extension[]
Definition: image.c:5041
static const WCHAR wmf_extension[]
Definition: image.c:5048
static ColorPalette * get_palette(IWICBitmapFrameDecode *frame, WICBitmapPaletteType palette_type)
Definition: image.c:66
GpStatus WINGDIPAPI GdipCreateBitmapFromStream(IStream *stream, GpBitmap **bitmap)
Definition: image.c:1895
GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette *palette, PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap)
Definition: image.c:6092
static GpStatus initialize_decoder_wic(IStream *stream, REFGUID container, IWICBitmapDecoder **decoder)
Definition: image.c:3726
static void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:449
static const WCHAR bmp_codecname[]
Definition: image.c:5012
static const WCHAR tiff_codecname[]
Definition: image.c:5033
static GpStatus get_screen_resolution(REAL *xres, REAL *yres)
Definition: image.c:1779
static void getpixel_16bppRGB555(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:199
static BOOL get_bool_property(IWICMetadataReader *reader, const GUID *guid, const WCHAR *prop_name)
Definition: image.c:2995
static void setpixel_1bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x, ColorPalette *palette)
Definition: image.c:420
GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
Definition: image.c:5764
GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height, PixelFormat format, GpBitmap *srcBitmap, GpBitmap **dstBitmap)
Definition: image.c:1313
GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodecInfo *encoders)
Definition: image.c:5309
GpStatus WINGDIPAPI GdipGetPropertyItem(GpImage *image, PROPID propid, UINT size, PropertyItem *buffer)
Definition: image.c:2617
static ULONG get_ulong_by_index(IWICMetadataReader *reader, ULONG index)
Definition: image.c:3370
GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR *filename, GpImage **image)
Definition: image.c:2944
GpStatus WINGDIPAPI GdipGetImageDecoders(UINT numDecoders, UINT size, ImageCodecInfo *decoders)
Definition: image.c:5258
GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap *bitmap, HBITMAP *hbmReturn, ARGB background)
Definition: image.c:1535
GpStatus WINGDIPAPI GdipTestControl(GpTestControlEnum control, void *param)
Definition: image.c:5684
static const WCHAR png_format[]
Definition: image.c:5057
static GpStatus select_frame_wic(GpImage *image, UINT active_frame)
Definition: image.c:3919
static void getpixel_32bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:250
GpStatus WINGDIPAPI GdipGetImageBounds(GpImage *image, GpRectF *srcRect, GpUnit *srcUnit)
Definition: image.c:2140
static const struct image_codec codecs[NUM_CODECS]
Definition: image.c:4407
static const BYTE wmf_sig_mask[]
Definition: image.c:5052
static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5940
GpStatus WINGDIPAPI GdipCreateBitmapFromFileICM(GDIPCONST WCHAR *filename, GpBitmap **bitmap)
Definition: image.c:1492
static const BYTE jpeg_sig_pattern[]
Definition: image.c:5023
static PropertyItem * get_gif_loopcount(IWICMetadataReader *reader)
Definition: image.c:3072
GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap **bitmap)
Definition: image.c:1619
static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5925
static const WCHAR png_extension[]
Definition: image.c:5055
GpStatus WINGDIPAPI GdipImageForceValidation(GpImage *image)
Definition: image.c:5705
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory **)
Definition: proxy.c:649
static unsigned int absdiff(unsigned int x, unsigned int y)
Definition: image.c:380
static const BYTE bmp_sig_pattern[]
Definition: image.c:5016
static void setpixel_8bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x, ColorPalette *palette)
Definition: image.c:413
static const BYTE tiff_sig_pattern[]
Definition: image.c:5037
static const BYTE ico_sig_mask[]
Definition: image.c:5066
GpStatus WINGDIPAPI GdipCreateEffect(const GUID guid, CGpEffect **effect)
Definition: image.c:5515
GpStatus WINGDIPAPI GdipGetImageHorizontalResolution(GpImage *image, REAL *res)
Definition: image.c:2236
GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
Definition: image.c:1385
GpStatus WINGDIPAPI GdipGetPropertyItemSize(GpImage *image, PROPID propid, UINT *size)
Definition: image.c:2471
static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5930
GpStatus WINGDIPAPI GdipCreateBitmapFromStreamICM(IStream *stream, GpBitmap **bitmap)
Definition: image.c:1917
static GpStatus decode_image_tiff(IStream *stream, GpImage **image)
Definition: image.c:4230
static PropertyItem * get_gif_palette(IWICBitmapDecoder *decoder, IWICMetadataReader *reader)
Definition: image.c:3125
static GpStatus decode_image_wic(IStream *stream, REFGUID container, metadata_reader_func metadata_reader, GpImage **image)
Definition: image.c:3904
static GpStatus get_decoder_info_from_image(GpImage *image, const struct image_codec **result)
Definition: image.c:4457
static UINT vt_to_itemtype(UINT vt)
Definition: image.c:2525
static HRESULT png_read_histogram(IWICMetadataReader *reader, GpBitmap *bitmap)
Definition: image.c:3562
GpStatus WINGDIPAPI GdipImageGetFrameDimensionsList(GpImage *image, GUID *dimensionIDs, UINT count)
Definition: image.c:2890
static const WCHAR gif_mimetype[]
Definition: image.c:5028
GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap *bitmap, BitmapData *lockeddata)
Definition: image.c:1252
#define WMF_PLACEABLE_KEY
Definition: image.c:43
static GpStatus decode_frame_wic(IWICBitmapDecoder *decoder, BOOL force_conversion, UINT active_frame, metadata_reader_func metadata_reader, GpImage **image)
Definition: image.c:3750
static const WCHAR ico_mimetype[]
Definition: image.c:5063
static const BYTE gif_sig_pattern[12]
Definition: image.c:5030
GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap **bitmap)
Definition: image.c:5392
static GpStatus initialize_encoder_wic(IStream *stream, REFGUID container, GpImage *image)
Definition: image.c:4626
GpStatus WINGDIPAPI GdipLoadImageFromStreamICM(IStream *stream, GpImage **image)
Definition: image.c:4560
GpStatus WINGDIPAPI GdipSaveAdd(GpImage *image, GDIPCONST EncoderParameters *params)
Definition: image.c:4913
static const WCHAR jpeg_extension[]
Definition: image.c:5020
static BOOL has_encoder_param_long(GDIPCONST EncoderParameters *params, GUID param_guid, ULONG val)
Definition: image.c:4800
static GpStatus encode_image_wic(GpImage *image, IStream *stream, REFGUID container, GDIPCONST EncoderParameters *params)
Definition: image.c:4823
static void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:466
static UINT get_palette_index(BYTE r, BYTE g, BYTE b, BYTE a, ColorPalette *palette)
Definition: image.c:385
static HRESULT png_add_unit_properties(IWICBitmapFrameDecode *frame, GpBitmap *bitmap)
Definition: image.c:3582
static const WCHAR wmf_codecname[]
Definition: image.c:5047
GpStatus WINGDIPAPI GdipBitmapCreateApplyEffect(GpBitmap **inputBitmaps, INT numInputs, CGpEffect *effect, RECT *roi, RECT *outputRect, GpBitmap **outputBitmap, BOOL useAuxData, VOID **auxData, INT *auxDataSize)
Definition: image.c:162
static void gif_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT active_frame)
Definition: image.c:3229
static const WCHAR ico_codecname[]
Definition: image.c:5061
static HRESULT blit_gif_frame(GpBitmap *bitmap, IWICBitmapFrameDecode *frame, BOOL first_frame)
Definition: image.c:3964
static GpStatus propvariant_to_item(PROPVARIANT *value, PropertyItem *item, UINT size, PROPID id)
Definition: image.c:2554
static PropertyItem * get_property(IWICMetadataReader *reader, const GUID *guid, const WCHAR *prop_name)
Definition: image.c:3022
static const WCHAR emf_format[]
Definition: image.c:5043
static void getpixel_32bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:259
static const WCHAR gif_codecname[]
Definition: image.c:5026
static const BYTE emf_sig_mask[]
Definition: image.c:5045
GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, GDIPCONST WmfPlaceableFileHeader *placeable, GpMetafile **metafile)
Definition: metafile.c:4290
GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete, GpMetafile **metafile)
Definition: metafile.c:4244
GUID guid
Definition: version.c:147
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
#define assert(_expr)
Definition: assert.h:32
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2802
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
Definition: info.c:2437
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
ULONG RGBQUAD
Definition: precomp.h:47
item_type
Definition: interpreter.c:23
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
#define abs(i)
Definition: fconv.c:206
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GpStatus hresult_to_status(HRESULT res)
Definition: gdiplus.c:314
void convert_32bppARGB_to_32bppPARGB(UINT width, UINT height, BYTE *dst_bits, INT dst_stride, const BYTE *src_bits, INT src_stride)
Definition: gdiplus.c:445
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi, BOOL printer_display)
Definition: gdiplus.c:329
#define GIF_DISPOSE_RESTORE_TO_PREV
static BOOL image_lock(GpImage *image)
#define PIXELFORMATBPP(x)
GpStatus METAFILE_GetGraphicsContext(GpMetafile *metafile, GpGraphics **result)
Definition: metafile.c:921
#define GIF_DISPOSE_DO_NOT_DISPOSE
static INT gdip_round(REAL x)
#define GIF_DISPOSE_UNSPECIFIED
EffectType
@ ColorMatrixEffect
@ ColorLUTEffect
@ ColorBalanceEffect
@ BlurEffect
@ SharpenEffect
@ BrightnessContrastEffect
@ HueSaturationLightnessEffect
@ TintEffect
@ RedEyeCorrectionEffect
@ LevelsEffect
@ ColorCurveEffect
GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics)
Definition: graphics.c:2520
static void image_unlock(GpImage *image)
void METAFILE_Free(GpMetafile *metafile)
Definition: metafile.c:687
#define GIF_DISPOSE_RESTORE_TO_BKGND
HistogramFormat
@ HistogramFormatRGB
@ HistogramFormatPARGB
@ HistogramFormatB
@ HistogramFormatA
@ HistogramFormatARGB
@ HistogramFormatR
@ HistogramFormatGray
@ HistogramFormatG
@ EncoderValueFlush
Definition: gdiplusenums.h:380
@ EncoderValueMultiFrame
Definition: gdiplusenums.h:378
@ EncoderValueFrameDimensionPage
Definition: gdiplusenums.h:383
ImageType
Definition: gdiplusenums.h:192
@ ImageTypeBitmap
Definition: gdiplusenums.h:194
@ ImageTypeMetafile
Definition: gdiplusenums.h:195
@ ImageFlagsHasRealDPI
Definition: gdiplusenums.h:341
@ ImageFlagsNone
Definition: gdiplusenums.h:331
@ ImageFlagsHasAlpha
Definition: gdiplusenums.h:333
@ ImageFlagsHasRealPixelSize
Definition: gdiplusenums.h:342
@ ImageFlagsReadOnly
Definition: gdiplusenums.h:343
@ ImageFlagsColorSpaceRGB
Definition: gdiplusenums.h:336
@ ImageFlagsColorSpaceGRAY
Definition: gdiplusenums.h:338
@ ImageCodecFlagsBuiltin
Definition: gdiplusenums.h:324
@ ImageCodecFlagsSupportBitmap
Definition: gdiplusenums.h:320
@ ImageCodecFlagsEncoder
Definition: gdiplusenums.h:318
@ ImageCodecFlagsDecoder
Definition: gdiplusenums.h:319
@ ImageCodecFlagsSupportVector
Definition: gdiplusenums.h:321
@ EncoderParameterValueTypeLong
Definition: gdiplusenums.h:351
GpTestControlEnum
Definition: gdiplusenums.h:410
@ TestControlNoICM
Definition: gdiplusenums.h:412
@ TestControlForceBilinear
Definition: gdiplusenums.h:411
@ TestControlGetBuildNumber
Definition: gdiplusenums.h:413
Unit
Definition: gdiplusenums.h:26
@ UnitPixel
Definition: gdiplusenums.h:29
#define GDIPCONST
Definition: gdiplusflat.h:24
#define WINGDIPAPI
Definition: gdiplusflat.h:22
Status GpStatus
#define PropertyTagIndexTransparent
#define PropertyTagFrameDelay
#define PropertyTagTypeShort
#define PropertyTagIndexBackground
@ ImageLockModeUserInputBuf
@ ImageLockModeRead
@ ImageLockModeWrite
#define PropertyTagCopyright
#define PropertyTagTypeLong
#define PropertyTagGlobalPalette
#define PropertyTagImageTitle
#define PropertyTagPrimaryChromaticities
#define PropertyTagWhitePoint
#define PropertyTagTypeUndefined
#define PropertyTagImageDescription
#define PropertyTagPixelUnit
#define PropertyTagTypeSLONG
#define PropertyTagTypeRational
#define PropertyTagPaletteHistogram
#define PropertyTagTypeByte
#define PropertyTagPixelPerUnitX
#define PropertyTagEquipModel
#define PropertyTagGamma
#define PropertyTagDateTime
#define PropertyTagPixelPerUnitY
#define PropertyTagTypeSRational
RotateFlipType
#define PropertyTagArtist
#define PropertyTagLoopCount
#define PropertyTagSoftwareUsed
#define PropertyTagTypeASCII
#define PropertyTagExifUserComment
DWORD ARGB
#define PixelFormat32bppPARGB
#define PixelFormat64bppARGB
#define PixelFormat32bppRGB
#define PixelFormatDontCare
static BOOL IsIndexedPixelFormat(PixelFormat format)
#define PixelFormat4bppIndexed
#define PixelFormat64bppPARGB
#define PixelFormat16bppRGB555
@ PaletteFlagsGrayScale
@ PaletteFlagsHalftone
@ PaletteFlagsHasAlpha
#define PixelFormat16bppARGB1555
@ PaletteTypeOptimal
@ PaletteTypeCustom
@ PaletteTypeFixedHalftone27
@ PaletteTypeFixedHalftone125
@ PaletteTypeFixedHalftone64
@ PaletteTypeFixedHalftone256
@ PaletteTypeFixedHalftone8
@ PaletteTypeFixedHalftone252
@ PaletteTypeFixedHalftone216
@ PaletteTypeFixedBW
#define PixelFormat16bppGrayScale
#define PixelFormat8bppIndexed
INT PixelFormat
#define PixelFormatIndexed
#define PixelFormatPAlpha
#define PixelFormat24bppRGB
#define PixelFormat16bppRGB565
#define PixelFormat1bppIndexed
#define PixelFormat32bppARGB
#define PixelFormatUndefined
#define PixelFormatAlpha
#define PixelFormat48bppRGB
struct GdiplusAbort GdiplusAbort
Definition: gdiplustypes.h:57
ImageAbort GetThumbnailImageAbort
Definition: gdiplustypes.h:56
Status
Definition: gdiplustypes.h:24
@ Ok
Definition: gdiplustypes.h:25
@ WrongState
Definition: gdiplustypes.h:33
@ ObjectBusy
Definition: gdiplustypes.h:29
@ InvalidParameter
Definition: gdiplustypes.h:27
@ OutOfMemory
Definition: gdiplustypes.h:28
@ PropertyNotFound
Definition: gdiplustypes.h:44
@ Win32Error
Definition: gdiplustypes.h:32
@ InsufficientBuffer
Definition: gdiplustypes.h:30
@ NotImplemented
Definition: gdiplustypes.h:31
@ GenericError
Definition: gdiplustypes.h:26
@ UnknownImageFormat
Definition: gdiplustypes.h:38
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLeglImageOES image
Definition: gl.h:2204
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizei stride
Definition: glext.h:5848
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLuint color
Definition: glext.h:6243
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLubyte * pattern
Definition: glext.h:7787
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLsizei GLsizei GLfloat distance
Definition: glext.h:11755
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLint left
Definition: glext.h:7726
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLboolean GLboolean g
Definition: glext.h:6204
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLuint GLuint num
Definition: glext.h:9618
GLfloat param
Definition: glext.h:5796
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define bits
Definition: infblock.c:15
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define C_ASSERT(e)
Definition: intsafe.h:73
const char * filename
Definition: ioapi.h:137
int desired
Definition: jpeglib.h:1121
static const struct @438 keywords[]
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define BI_BITFIELDS
Definition: mmreg.h:507
static PVOID ptr
Definition: dispmode.c:27
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
static HICON
Definition: imagelist.c:80
#define comment(fmt, arg1)
Definition: rebar.c:847
static const char * dst_format
Definition: dib.c:1339
static const unsigned char metafile[]
Definition: olepicture.c:138
static BSTR *static LPOLESTR
Definition: varformat.c:44
static const CLSID IPropertyStorage UINT *static const PROPSPEC PROPVARIANT *static UINT const PROPSPEC PROPVARIANT PROPID
Definition: shellole.c:78
static HPALETTE palette
Definition: clipboard.c:1457
const CLSID * clsid
Definition: msctf.cpp:50
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
#define RTL_SIZEOF_THROUGH_FIELD(type, field)
Definition: ntbasedef.h:684
#define V_UI1(A)
Definition: oleauto.h:266
#define V_VT(A)
Definition: oleauto.h:211
short WCHAR
Definition: pedump.c:58
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
png_const_structrp png_const_inforp int * unit
Definition: png.h:2392
static Real area(Real A[2], Real B[2], Real C[2])
Definition: polyDBG.cc:50
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define IsEqualCLSID(rclsid1, rclsid2)
Definition: guiddef.h:96
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
_In_ HBITMAP _In_ UINT _In_ UINT _Inout_ LPBITMAPINFO pbmi
Definition: ntgdi.h:2780
for(i=0;i< sizeof(testsuite)/sizeof(testsuite[0]);++i) ok(call_test(testsuite[i].func)
#define calloc
Definition: rosglue.h:14
#define offsetof(TYPE, MEMBER)
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:171
int seek(void *fd, ulong off, int mode)
Definition: pe.c:51
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
LONG biYPelsPerMeter
Definition: amvideo.idl:38
DWORD biCompression
Definition: amvideo.idl:35
DWORD biClrImportant
Definition: amvideo.idl:40
LONG biXPelsPerMeter
Definition: amvideo.idl:37
DWORD biSizeImage
Definition: amvideo.idl:36
DWORD bV4GreenMask
Definition: wingdi.h:1950
DWORD bV4V4Compression
Definition: wingdi.h:1943
LONG bV4Height
Definition: wingdi.h:1940
DWORD bV4RedMask
Definition: wingdi.h:1949
LONG bV4Width
Definition: wingdi.h:1939
WORD bV4BitCount
Definition: wingdi.h:1942
DWORD bV4BlueMask
Definition: wingdi.h:1951
DWORD bV4Size
Definition: wingdi.h:1938
UINT_PTR Reserved
PixelFormat PixelFormat
EffectType type
GpImage image
PixelFormat format
ColorPalette * palette
IWICBitmapEncoder * encoder
ImageType type
REAL Height
Definition: gdiplustypes.h:659
REAL X
Definition: gdiplustypes.h:656
REAL Width
Definition: gdiplustypes.h:658
REAL Y
Definition: gdiplustypes.h:657
INT Width
Definition: gdiplustypes.h:666
INT Height
Definition: gdiplustypes.h:667
INT X
Definition: gdiplustypes.h:664
INT Y
Definition: gdiplustypes.h:665
INT Height
Definition: wincodec.idl:335
INT Width
Definition: wincodec.idl:334
Definition: scsiwmi.h:51
BOOL fIcon
Definition: winuser.h:3231
HBITMAP hbmColor
Definition: winuser.h:3235
HBITMAP hbmMask
Definition: winuser.h:3234
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: uimain.c:89
uint32 width
Definition: uimain.c:91
uint32 height
Definition: uimain.c:92
Definition: dialog.c:52
char * value
Definition: compiler.c:67
Definition: main.c:439
Definition: format.c:58
select_image_func select_func
Definition: image.c:4392
decode_image_func decode_func
Definition: image.c:4391
encode_image_func encode_func
Definition: image.c:4390
ImageCodecInfo info
Definition: image.c:4389
const GUID * format
Definition: image.c:2844
const GUID * dimension
Definition: image.c:2845
uacpi_u8 type
Definition: interpreter.c:38
Definition: name.c:39
Definition: reader.h:84
Definition: stat.h:66
Definition: ps.c:97
Definition: parse.h:23
USHORT biBitCount
Definition: precomp.h:34
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1922
RGBQUAD bmiColors[1]
Definition: wingdi.h:1923
LONG bmHeight
Definition: wingdi.h:1869
LONG bmWidth
Definition: wingdi.h:1868
WORD bmBitsPixel
Definition: wingdi.h:1872
DWORD dSignature
Definition: wingdi.h:2770
DWORD mtSize
Definition: wingdi.h:2759
UCHAR rgbBlue
Definition: bootanim.c:103
UCHAR rgbRed
Definition: bootanim.c:105
UCHAR rgbGreen
Definition: bootanim.c:104
Definition: tools.h:99
rwlock_t lock
Definition: tcpcore.h:0
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
#define BI_RGB
Definition: uefivid.c:46
Definition: pdh_main.c:96
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
int retval
Definition: wcstombs.cpp:91
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
@ WICBitmapEncoderNoCache
Definition: wincodec.idl:73
@ WICPngFilterNone
Definition: wincodec.idl:182
@ WICDecodeMetadataCacheOnLoad
Definition: wincodec.idl:30
WICBitmapPaletteType
Definition: wincodec.idl:91
@ WICBitmapPaletteTypeFixedHalftone256
Definition: wincodec.idl:102
@ WICBitmapPaletteTypeFixedGray256
Definition: wincodec.idl:105
@ WICBitmapPaletteTypeFixedBW
Definition: wincodec.idl:94
@ WICBitmapPaletteTypeFixedHalftone64
Definition: wincodec.idl:97
@ WICBitmapPaletteTypeFixedGray16
Definition: wincodec.idl:104
@ WICBitmapPaletteTypeFixedGray4
Definition: wincodec.idl:103
@ WICBitmapPaletteTypeFixedHalftone216
Definition: wincodec.idl:99
@ WICBitmapPaletteTypeFixedHalftone27
Definition: wincodec.idl:96
@ WICBitmapPaletteTypeFixedHalftone125
Definition: wincodec.idl:98
@ WICBitmapPaletteTypeFixedHalftone8
Definition: wincodec.idl:95
@ WICBitmapPaletteTypeFixedHalftone252
Definition: wincodec.idl:101
UINT32 WICColor
Definition: wincodec.idl:364
_In_ ULONG _In_ ULONG rgb
Definition: winddi.h:3521
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
#define WINCODEC_ERR_PALETTEUNAVAILABLE
Definition: winerror.h:7303
static const char appdata[]
Definition: shdocvw.c:39
BOOL WINAPI DeleteMetaFile(_In_ HMETAFILE)
#define DIB_RGB_COLORS
Definition: wingdi.h:367
BOOL WINAPI DeleteEnhMetaFile(_In_opt_ HENHMETAFILE)
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
int WINAPI GetObjectA(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
int WINAPI GetDIBits(_In_ HDC hdc, _In_ HBITMAP hbm, _In_ UINT start, _In_ UINT cLines, _Out_opt_ LPVOID lpvBits, _At_((LPBITMAPINFOHEADER) lpbmi, _Inout_) LPBITMAPINFO lpbmi, _In_ UINT usage)
#define LOGPIXELSY
Definition: wingdi.h:719
HENHMETAFILE WINAPI CopyEnhMetaFileW(_In_ HENHMETAFILE hemfSrc, _In_opt_ LPCWSTR pszFile)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define ENHMETA_SIGNATURE
Definition: wingdi.h:204
HMETAFILE WINAPI SetMetaFileBitsEx(_In_ UINT cbBuffer, _In_reads_bytes_(cbBuffer) CONST BYTE *lpData)
#define LOGPIXELSX
Definition: wingdi.h:718
HENHMETAFILE WINAPI SetEnhMetaFileBits(_In_ UINT nSize, _In_reads_bytes_(nSize) const BYTE *pb)
BOOL WINAPI DeleteDC(_In_ HDC)
#define snprintf
Definition: wintirpc.h:48
#define IMAGE_BITMAP
Definition: winuser.h:211
HICON WINAPI CreateIcon(_In_opt_ HINSTANCE, _In_ int, _In_ int, _In_ BYTE, _In_ BYTE, _In_ const BYTE *, _In_ const BYTE *)
Definition: cursoricon.c:2764
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2414
#define LR_CREATEDIBSECTION
Definition: winuser.h:1109
HANDLE WINAPI LoadImageW(_In_opt_ HINSTANCE hInst, _In_ LPCWSTR name, _In_ UINT type, _In_ int cx, _In_ int cy, _In_ UINT fuLoad)
Definition: cursoricon.c:2572
unsigned char BYTE
Definition: xxhash.c:193