ReactOS 0.4.15-dev-7788-g1ad9096
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#define NONAMELESSUNION
24
25#include "windef.h"
26#include "winbase.h"
27#include "winuser.h"
28#include "wingdi.h"
29
30#define COBJMACROS
31#include "objbase.h"
32#include "olectl.h"
33#include "ole2.h"
34
35#include "initguid.h"
36#include "wincodec.h"
37#include "gdiplus.h"
38#include "gdiplus_private.h"
39#include "wine/debug.h"
40
42
44
45#define PIXELFORMATBPP(x) ((x) ? ((x) >> 8) & 255 : 24)
46#define WMF_PLACEABLE_KEY 0x9ac6cdd7
47
48static const struct
49{
52 /* predefined palette type to use for pixel format conversions */
54} pixel_formats[] =
55{
56 { &GUID_WICPixelFormatBlackWhite, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
57 { &GUID_WICPixelFormat1bppIndexed, PixelFormat1bppIndexed, WICBitmapPaletteTypeFixedBW },
58 { &GUID_WICPixelFormat4bppIndexed, PixelFormat4bppIndexed, WICBitmapPaletteTypeFixedHalftone8 },
59 { &GUID_WICPixelFormat8bppGray, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedGray256 },
60 { &GUID_WICPixelFormat8bppIndexed, PixelFormat8bppIndexed, WICBitmapPaletteTypeFixedHalftone256 },
61 { &GUID_WICPixelFormat16bppBGR555, PixelFormat16bppRGB555, WICBitmapPaletteTypeFixedHalftone256 },
62 { &GUID_WICPixelFormat24bppBGR, PixelFormat24bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
63 { &GUID_WICPixelFormat32bppBGR, PixelFormat32bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
64 { &GUID_WICPixelFormat48bppRGB, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
65 { &GUID_WICPixelFormat32bppBGRA, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedHalftone256 },
66 { &GUID_WICPixelFormat32bppPBGRA, PixelFormat32bppPARGB, WICBitmapPaletteTypeFixedHalftone256 },
67 { &GUID_WICPixelFormat32bppCMYK, PixelFormat32bppCMYK, WICBitmapPaletteTypeFixedHalftone256 },
68 { &GUID_WICPixelFormat32bppGrayFloat, PixelFormat32bppARGB, WICBitmapPaletteTypeFixedGray256 },
69 { &GUID_WICPixelFormat64bppCMYK, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
70 { &GUID_WICPixelFormat64bppRGBA, PixelFormat48bppRGB, WICBitmapPaletteTypeFixedHalftone256 },
71 { NULL }
72};
73
75{
76 HRESULT hr;
78 IWICPalette *wic_palette;
80
81 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
82 if (hr != S_OK) return NULL;
83
84 hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
85 if (hr == S_OK)
86 {
88 if (frame)
89 hr = IWICBitmapFrameDecode_CopyPalette(frame, wic_palette);
90 if (hr != S_OK)
91 {
92 TRACE("using predefined palette %#x\n", palette_type);
93 hr = IWICPalette_InitializePredefined(wic_palette, palette_type, FALSE);
94 }
95 if (hr == S_OK)
96 {
98 BOOL alpha;
99 UINT count;
100
101 IWICPalette_GetColorCount(wic_palette, &count);
102 palette = heap_alloc(2 * sizeof(UINT) + count * sizeof(ARGB));
103 IWICPalette_GetColors(wic_palette, count, palette->Entries, &palette->Count);
104
105 IWICPalette_GetType(wic_palette, &type);
106 switch(type) {
111 break;
120 break;
121 default:
122 palette->Flags = 0;
123 }
124 IWICPalette_HasAlpha(wic_palette, &alpha);
125 if(alpha)
127 }
128 IWICPalette_Release(wic_palette);
129 }
130 IWICImagingFactory_Release(factory);
131 return palette;
132}
133
135 RECT* roi, BOOL useAuxData, VOID** auxData, INT* auxDataSize)
136{
137 FIXME("(%p %p %p %d %p %p): stub\n", bitmap, effect, roi, useAuxData, auxData, auxDataSize);
138 /*
139 * Note: According to Jose Roca's GDI+ docs, this function is not
140 * implemented in Windows's GDI+.
141 */
142 return NotImplemented;
143}
144
146 INT numInputs, CGpEffect* effect, RECT* roi, RECT* outputRect,
147 GpBitmap** outputBitmap, BOOL useAuxData, VOID** auxData, INT* auxDataSize)
148{
149 FIXME("(%p %d %p %p %p %p %d %p %p): stub\n", inputBitmaps, numInputs, effect, roi, outputRect, outputBitmap, useAuxData, auxData, auxDataSize);
150 /*
151 * Note: According to Jose Roca's GDI+ docs, this function is not
152 * implemented in Windows's GDI+.
153 */
154 return NotImplemented;
155}
156
157static inline void getpixel_1bppIndexed(BYTE *index, const BYTE *row, UINT x)
158{
159 *index = (row[x/8]>>(7-x%8)) & 1;
160}
161
162static inline void getpixel_4bppIndexed(BYTE *index, const BYTE *row, UINT x)
163{
164 if (x & 1)
165 *index = row[x/2]&0xf;
166 else
167 *index = row[x/2]>>4;
168}
169
170static inline void getpixel_8bppIndexed(BYTE *index, const BYTE *row, UINT x)
171{
172 *index = row[x];
173}
174
175static inline void getpixel_16bppGrayScale(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
176 const BYTE *row, UINT x)
177{
178 *r = *g = *b = row[x*2+1];
179 *a = 255;
180}
181
182static inline void getpixel_16bppRGB555(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
183 const BYTE *row, UINT x)
184{
185 WORD pixel = *((const WORD*)(row)+x);
186 *r = (pixel>>7&0xf8)|(pixel>>12&0x7);
187 *g = (pixel>>2&0xf8)|(pixel>>6&0x7);
188 *b = (pixel<<3&0xf8)|(pixel>>2&0x7);
189 *a = 255;
190}
191
192static inline void getpixel_16bppRGB565(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
193 const BYTE *row, UINT x)
194{
195 WORD pixel = *((const WORD*)(row)+x);
196 *r = (pixel>>8&0xf8)|(pixel>>13&0x7);
197 *g = (pixel>>3&0xfc)|(pixel>>9&0x3);
198 *b = (pixel<<3&0xf8)|(pixel>>2&0x7);
199 *a = 255;
200}
201
202static inline void getpixel_16bppARGB1555(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
203 const BYTE *row, UINT x)
204{
205 WORD pixel = *((const WORD*)(row)+x);
206 *r = (pixel>>7&0xf8)|(pixel>>12&0x7);
207 *g = (pixel>>2&0xf8)|(pixel>>6&0x7);
208 *b = (pixel<<3&0xf8)|(pixel>>2&0x7);
209 if ((pixel&0x8000) == 0x8000)
210 *a = 255;
211 else
212 *a = 0;
213}
214
215static inline void getpixel_24bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
216 const BYTE *row, UINT x)
217{
218 *r = row[x*3+2];
219 *g = row[x*3+1];
220 *b = row[x*3];
221 *a = 255;
222}
223
224static inline void getpixel_32bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
225 const BYTE *row, UINT x)
226{
227 *r = row[x*4+2];
228 *g = row[x*4+1];
229 *b = row[x*4];
230 *a = 255;
231}
232
233static inline void getpixel_32bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
234 const BYTE *row, UINT x)
235{
236 *r = row[x*4+2];
237 *g = row[x*4+1];
238 *b = row[x*4];
239 *a = row[x*4+3];
240}
241
242static inline void getpixel_32bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
243 const BYTE *row, UINT x)
244{
245 *a = row[x*4+3];
246 if (*a == 0)
247 *r = *g = *b = 0;
248 else
249 {
250 *r = row[x*4+2] * 255 / *a;
251 *g = row[x*4+1] * 255 / *a;
252 *b = row[x*4] * 255 / *a;
253 }
254}
255
256static inline void getpixel_48bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
257 const BYTE *row, UINT x)
258{
259 *r = row[x*6+5];
260 *g = row[x*6+3];
261 *b = row[x*6+1];
262 *a = 255;
263}
264
265static inline void getpixel_64bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
266 const BYTE *row, UINT x)
267{
268 *r = row[x*8+5];
269 *g = row[x*8+3];
270 *b = row[x*8+1];
271 *a = row[x*8+7];
272}
273
274static inline void getpixel_64bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a,
275 const BYTE *row, UINT x)
276{
277 *a = row[x*8+7];
278 if (*a == 0)
279 *r = *g = *b = 0;
280 else
281 {
282 *r = row[x*8+5] * 255 / *a;
283 *g = row[x*8+3] * 255 / *a;
284 *b = row[x*8+1] * 255 / *a;
285 }
286}
287
289 ARGB *color)
290{
291 BYTE r, g, b, a;
292 BYTE index;
293 BYTE *row;
294
295 if(!bitmap || !color ||
296 x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
297 return InvalidParameter;
298
299 row = bitmap->bits+bitmap->stride*y;
300
301 switch (bitmap->format)
302 {
305 break;
308 break;
311 break;
314 break;
317 break;
320 break;
323 break;
325 getpixel_24bppRGB(&r,&g,&b,&a,row,x);
326 break;
328 getpixel_32bppRGB(&r,&g,&b,&a,row,x);
329 break;
332 break;
335 break;
337 getpixel_48bppRGB(&r,&g,&b,&a,row,x);
338 break;
341 break;
344 break;
345 default:
346 FIXME("not implemented for format 0x%x\n", bitmap->format);
347 return NotImplemented;
348 }
349
350 if (bitmap->format & PixelFormatIndexed)
351 *color = bitmap->image.palette->Entries[index];
352 else
353 *color = a<<24|r<<16|g<<8|b;
354
355 return Ok;
356}
357
359{
360 BYTE index = 0;
361 int best_distance = 0x7fff;
362 int distance;
363 UINT i;
364
365 if (!palette) return 0;
366 /* This algorithm scans entire palette,
367 computes difference from desired color (all color components have equal weight)
368 and returns the index of color with least difference.
369
370 Note: Maybe it could be replaced with a better algorithm for better image quality
371 and performance, though better algorithm would probably need some pre-built lookup
372 tables and thus may actually be slower if this method is called only few times per
373 every image.
374 */
375 for(i=0;i<palette->Count;i++) {
376 ARGB color=palette->Entries[i];
377 distance=abs(b-(color & 0xff)) + abs(g-(color>>8 & 0xff)) + abs(r-(color>>16 & 0xff)) + abs(a-(color>>24 & 0xff));
378 if (distance<best_distance) {
379 best_distance=distance;
380 index=i;
381 }
382 }
383 return index;
384}
385
386static inline void setpixel_8bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a,
388{
390 row[x]=index;
391}
392
393static inline void setpixel_1bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a,
395{
396 row[x/8] = (row[x/8] & ~(1<<(7-x%8))) | (get_palette_index(r,g,b,a,palette)<<(7-x%8));
397}
398
399static inline void setpixel_4bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a,
401{
402 if (x & 1)
403 row[x/2] = (row[x/2] & 0xf0) | get_palette_index(r,g,b,a,palette);
404 else
405 row[x/2] = (row[x/2] & 0x0f) | get_palette_index(r,g,b,a,palette)<<4;
406}
407
409 BYTE *row, UINT x)
410{
411 *((WORD*)(row)+x) = (r+g+b)*85;
412}
413
414static inline void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a,
415 BYTE *row, UINT x)
416{
417 *((WORD*)(row)+x) = (r<<7&0x7c00)|
418 (g<<2&0x03e0)|
419 (b>>3&0x001f);
420}
421
422static inline void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a,
423 BYTE *row, UINT x)
424{
425 *((WORD*)(row)+x) = (r<<8&0xf800)|
426 (g<<3&0x07e0)|
427 (b>>3&0x001f);
428}
429
430static inline void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a,
431 BYTE *row, UINT x)
432{
433 *((WORD*)(row)+x) = (a<<8&0x8000)|
434 (r<<7&0x7c00)|
435 (g<<2&0x03e0)|
436 (b>>3&0x001f);
437}
438
439static inline void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
440 BYTE *row, UINT x)
441{
442 row[x*3+2] = r;
443 row[x*3+1] = g;
444 row[x*3] = b;
445}
446
447static inline void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
448 BYTE *row, UINT x)
449{
450 *((DWORD*)(row)+x) = (r<<16)|(g<<8)|b;
451}
452
453static inline void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
454 BYTE *row, UINT x)
455{
456 *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
457}
458
459static inline void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
460 BYTE *row, UINT x)
461{
462 r = r * a / 255;
463 g = g * a / 255;
464 b = b * a / 255;
465 *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
466}
467
468static inline void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
469 BYTE *row, UINT x)
470{
471 row[x*6+5] = row[x*6+4] = r;
472 row[x*6+3] = row[x*6+2] = g;
473 row[x*6+1] = row[x*6] = b;
474}
475
476static inline void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
477 BYTE *row, UINT x)
478{
479 UINT64 a64=a, r64=r, g64=g, b64=b;
480 *((UINT64*)(row)+x) = (a64<<56)|(a64<<48)|(r64<<40)|(r64<<32)|(g64<<24)|(g64<<16)|(b64<<8)|b64;
481}
482
483static inline void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
484 BYTE *row, UINT x)
485{
486 UINT64 a64, r64, g64, b64;
487 a64 = a * 257;
488 r64 = r * a / 255;
489 g64 = g * a / 255;
490 b64 = b * a / 255;
491 *((UINT64*)(row)+x) = (a64<<48)|(r64<<32)|(g64<<16)|b64;
492}
493
495 ARGB color)
496{
497 BYTE a, r, g, b;
498 BYTE *row;
499
500 if(!bitmap || x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
501 return InvalidParameter;
502
503 a = color>>24;
504 r = color>>16;
505 g = color>>8;
506 b = color;
507
508 row = bitmap->bits + bitmap->stride * y;
509
510 switch (bitmap->format)
511 {
514 break;
517 break;
520 break;
523 break;
526 break;
529 break;
532 break;
535 break;
538 break;
541 break;
544 break;
546 setpixel_8bppIndexed(r,g,b,a,row,x,bitmap->image.palette);
547 break;
549 setpixel_4bppIndexed(r,g,b,a,row,x,bitmap->image.palette);
550 break;
552 setpixel_1bppIndexed(r,g,b,a,row,x,bitmap->image.palette);
553 break;
554 default:
555 FIXME("not implemented for format 0x%x\n", bitmap->format);
556 return NotImplemented;
557 }
558
559 return Ok;
560}
561
563 INT dst_stride, BYTE *dst_bits, PixelFormat dst_format,
564 INT src_stride, const BYTE *src_bits, PixelFormat src_format,
566{
567 INT x, y;
568
569 if (src_format == dst_format ||
570 (dst_format == PixelFormat32bppRGB && PIXELFORMATBPP(src_format) == 32))
571 {
572 UINT widthbytes = PIXELFORMATBPP(src_format) * width / 8;
573 for (y=0; y<height; y++)
574 memcpy(dst_bits+dst_stride*y, src_bits+src_stride*y, widthbytes);
575 return Ok;
576 }
577
578#define convert_indexed_to_rgb(getpixel_function, setpixel_function) do { \
579 for (y=0; y<height; y++) \
580 for (x=0; x<width; x++) { \
581 BYTE index; \
582 ARGB argb; \
583 BYTE *color = (BYTE *)&argb; \
584 getpixel_function(&index, src_bits+src_stride*y, x); \
585 argb = (palette && index < palette->Count) ? palette->Entries[index] : 0; \
586 setpixel_function(color[2], color[1], color[0], color[3], dst_bits+dst_stride*y, x); \
587 } \
588 return Ok; \
589} while (0);
590
591#define convert_rgb_to_rgb(getpixel_function, setpixel_function) do { \
592 for (y=0; y<height; y++) \
593 for (x=0; x<width; x++) { \
594 BYTE r, g, b, a; \
595 getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
596 setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x); \
597 } \
598 return Ok; \
599} while (0);
600
601#define convert_rgb_to_indexed(getpixel_function, setpixel_function) do { \
602 for (y=0; y<height; y++) \
603 for (x=0; x<width; x++) { \
604 BYTE r, g, b, a; \
605 getpixel_function(&r, &g, &b, &a, src_bits+src_stride*y, x); \
606 setpixel_function(r, g, b, a, dst_bits+dst_stride*y, x, palette); \
607 } \
608 return Ok; \
609} while (0);
610
611 switch (src_format)
612 {
614 switch (dst_format)
615 {
636 default:
637 break;
638 }
639 break;
641 switch (dst_format)
642 {
663 default:
664 break;
665 }
666 break;
668 switch (dst_format)
669 {
690 default:
691 break;
692 }
693 break;
695 switch (dst_format)
696 {
719 default:
720 break;
721 }
722 break;
724 switch (dst_format)
725 {
748 default:
749 break;
750 }
751 break;
753 switch (dst_format)
754 {
777 default:
778 break;
779 }
780 break;
782 switch (dst_format)
783 {
806 default:
807 break;
808 }
809 break;
811 switch (dst_format)
812 {
835 default:
836 break;
837 }
838 break;
840 switch (dst_format)
841 {
864 default:
865 break;
866 }
867 break;
869 switch (dst_format)
870 {
886 convert_32bppARGB_to_32bppPARGB(width, height, dst_bits, dst_stride, src_bits, src_stride);
887 return Ok;
892 default:
893 break;
894 }
895 break;
897 switch (dst_format)
898 {
921 default:
922 break;
923 }
924 break;
926 switch (dst_format)
927 {
950 default:
951 break;
952 }
953 break;
955 switch (dst_format)
956 {
979 default:
980 break;
981 }
982 break;
984 switch (dst_format)
985 {
1010 default:
1011 break;
1012 }
1013 break;
1014 default:
1015 break;
1016 }
1017
1018#undef convert_indexed_to_rgb
1019#undef convert_rgb_to_rgb
1020
1021 return NotImplemented;
1022}
1023
1024/* This function returns a pointer to an array of pixels that represents the
1025 * bitmap. The *entire* bitmap is locked according to the lock mode specified by
1026 * flags. It is correct behavior that a user who calls this function with write
1027 * privileges can write to the whole bitmap (not just the area in rect).
1028 *
1029 * FIXME: only used portion of format is bits per pixel. */
1031 UINT flags, PixelFormat format, BitmapData* lockeddata)
1032{
1033 INT bitspp = PIXELFORMATBPP(format);
1034 GpRect act_rect; /* actual rect to be used */
1035 GpStatus stat;
1036 BOOL unlock;
1037
1038 TRACE("%p %p %d 0x%x %p\n", bitmap, rect, flags, format, lockeddata);
1039
1040 if(!lockeddata || !bitmap)
1041 return InvalidParameter;
1042 if(!image_lock(&bitmap->image, &unlock))
1043 return ObjectBusy;
1044
1045 if(rect){
1046 if(rect->X < 0 || rect->Y < 0 || (rect->X + rect->Width > bitmap->width) ||
1047 (rect->Y + rect->Height > bitmap->height) || !flags)
1048 {
1049 image_unlock(&bitmap->image, unlock);
1050 return InvalidParameter;
1051 }
1052
1053 act_rect = *rect;
1054 }
1055 else{
1056 act_rect.X = act_rect.Y = 0;
1057 act_rect.Width = bitmap->width;
1058 act_rect.Height = bitmap->height;
1059 }
1060
1061 if(bitmap->lockmode)
1062 {
1063 WARN("bitmap is already locked and cannot be locked again\n");
1064 image_unlock(&bitmap->image, unlock);
1065 return WrongState;
1066 }
1067
1068 if (bitmap->bits && bitmap->format == format && !(flags & ImageLockModeUserInputBuf))
1069 {
1070 /* no conversion is necessary; just use the bits directly */
1071 lockeddata->Width = act_rect.Width;
1072 lockeddata->Height = act_rect.Height;
1073 lockeddata->PixelFormat = format;
1074 lockeddata->Reserved = flags;
1075 lockeddata->Stride = bitmap->stride;
1076 lockeddata->Scan0 = bitmap->bits + (bitspp / 8) * act_rect.X +
1077 bitmap->stride * act_rect.Y;
1078
1079 bitmap->lockmode = flags | ImageLockModeRead;
1080
1081 image_unlock(&bitmap->image, unlock);
1082 return Ok;
1083 }
1084
1085 /* Make sure we can convert to the requested format. */
1087 {
1088 stat = convert_pixels(0, 0, 0, NULL, format, 0, NULL, bitmap->format, NULL);
1089 if (stat == NotImplemented)
1090 {
1091 FIXME("cannot read bitmap from %x to %x\n", bitmap->format, format);
1092 image_unlock(&bitmap->image, unlock);
1093 return NotImplemented;
1094 }
1095 }
1096
1097 /* If we're opening for writing, make sure we'll be able to write back in
1098 * the original format. */
1100 {
1101 stat = convert_pixels(0, 0, 0, NULL, bitmap->format, 0, NULL, format, NULL);
1102 if (stat == NotImplemented)
1103 {
1104 FIXME("cannot write bitmap from %x to %x\n", format, bitmap->format);
1105 image_unlock(&bitmap->image, unlock);
1106 return NotImplemented;
1107 }
1108 }
1109
1110 lockeddata->Width = act_rect.Width;
1111 lockeddata->Height = act_rect.Height;
1112 lockeddata->PixelFormat = format;
1113 lockeddata->Reserved = flags;
1114
1116 {
1117 lockeddata->Stride = (((act_rect.Width * bitspp + 7) / 8) + 3) & ~3;
1118
1119 bitmap->bitmapbits = heap_alloc_zero(lockeddata->Stride * act_rect.Height);
1120
1121 if (!bitmap->bitmapbits)
1122 {
1123 image_unlock(&bitmap->image, unlock);
1124 return OutOfMemory;
1125 }
1126
1127 lockeddata->Scan0 = bitmap->bitmapbits;
1128 }
1129
1131 {
1132 static BOOL fixme = FALSE;
1133
1134 if (!fixme && (PIXELFORMATBPP(bitmap->format) * act_rect.X) % 8 != 0)
1135 {
1136 FIXME("Cannot copy rows that don't start at a whole byte.\n");
1137 fixme = TRUE;
1138 }
1139
1140 stat = convert_pixels(act_rect.Width, act_rect.Height,
1141 lockeddata->Stride, lockeddata->Scan0, format,
1142 bitmap->stride,
1143 bitmap->bits + bitmap->stride * act_rect.Y + PIXELFORMATBPP(bitmap->format) * act_rect.X / 8,
1144 bitmap->format, bitmap->image.palette);
1145
1146 if (stat != Ok)
1147 {
1148 heap_free(bitmap->bitmapbits);
1149 bitmap->bitmapbits = NULL;
1150 image_unlock(&bitmap->image, unlock);
1151 return stat;
1152 }
1153 }
1154
1155 bitmap->lockmode = flags | ImageLockModeRead;
1156 bitmap->lockx = act_rect.X;
1157 bitmap->locky = act_rect.Y;
1158
1159 image_unlock(&bitmap->image, unlock);
1160 return Ok;
1161}
1162
1164{
1165 TRACE("(%p, %.2f, %.2f)\n", bitmap, xdpi, ydpi);
1166
1167 if (!bitmap || xdpi == 0.0 || ydpi == 0.0)
1168 return InvalidParameter;
1169
1170 bitmap->image.xres = xdpi;
1171 bitmap->image.yres = ydpi;
1172
1173 return Ok;
1174}
1175
1177 BitmapData* lockeddata)
1178{
1179 GpStatus stat;
1180 static BOOL fixme = FALSE;
1181 BOOL unlock;
1182
1183 TRACE("(%p,%p)\n", bitmap, lockeddata);
1184
1185 if(!bitmap || !lockeddata)
1186 return InvalidParameter;
1187 if(!image_lock(&bitmap->image, &unlock))
1188 return ObjectBusy;
1189
1190 if(!bitmap->lockmode)
1191 {
1192 image_unlock(&bitmap->image, unlock);
1193 return WrongState;
1194 }
1195
1196 if(!(lockeddata->Reserved & ImageLockModeWrite)){
1197 bitmap->lockmode = 0;
1198 heap_free(bitmap->bitmapbits);
1199 bitmap->bitmapbits = NULL;
1200 image_unlock(&bitmap->image, unlock);
1201 return Ok;
1202 }
1203
1204 if (!bitmap->bitmapbits && !(lockeddata->Reserved & ImageLockModeUserInputBuf))
1205 {
1206 /* we passed a direct reference; no need to do anything */
1207 bitmap->lockmode = 0;
1208 image_unlock(&bitmap->image, unlock);
1209 return Ok;
1210 }
1211
1212 if (!fixme && (PIXELFORMATBPP(bitmap->format) * bitmap->lockx) % 8 != 0)
1213 {
1214 FIXME("Cannot copy rows that don't start at a whole byte.\n");
1215 fixme = TRUE;
1216 }
1217
1218 stat = convert_pixels(lockeddata->Width, lockeddata->Height,
1219 bitmap->stride,
1220 bitmap->bits + bitmap->stride * bitmap->locky + PIXELFORMATBPP(bitmap->format) * bitmap->lockx / 8,
1221 bitmap->format,
1222 lockeddata->Stride, lockeddata->Scan0, lockeddata->PixelFormat, NULL);
1223
1224 if (stat != Ok)
1225 {
1226 ERR("failed to convert pixels; this should never happen\n");
1227 }
1228
1229 heap_free(bitmap->bitmapbits);
1230 bitmap->bitmapbits = NULL;
1231 bitmap->lockmode = 0;
1232
1233 image_unlock(&bitmap->image, unlock);
1234 return stat;
1235}
1236
1238 PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap)
1239{
1240 Rect area;
1241 GpStatus stat;
1242
1243 TRACE("(%f,%f,%f,%f,0x%x,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap);
1244
1245 if (!srcBitmap || !dstBitmap || srcBitmap->image.type != ImageTypeBitmap ||
1246 x < 0 || y < 0 ||
1247 x + width > srcBitmap->width || y + height > srcBitmap->height)
1248 {
1249 TRACE("<-- InvalidParameter\n");
1250 return InvalidParameter;
1251 }
1252
1254 format = srcBitmap->format;
1255
1256 area.X = gdip_round(x);
1257 area.Y = gdip_round(y);
1258 area.Width = gdip_round(width);
1259 area.Height = gdip_round(height);
1260
1261 stat = GdipCreateBitmapFromScan0(area.Width, area.Height, 0, format, NULL, dstBitmap);
1262 if (stat == Ok)
1263 {
1264 stat = convert_pixels(area.Width, area.Height, (*dstBitmap)->stride, (*dstBitmap)->bits, (*dstBitmap)->format,
1265 srcBitmap->stride,
1266 srcBitmap->bits + srcBitmap->stride * area.Y + PIXELFORMATBPP(srcBitmap->format) * area.X / 8,
1267 srcBitmap->format, srcBitmap->image.palette);
1268
1269 if (stat == Ok && srcBitmap->image.palette)
1270 {
1271 ColorPalette *src_palette, *dst_palette;
1272
1273 src_palette = srcBitmap->image.palette;
1274
1275 dst_palette = heap_alloc_zero(sizeof(UINT) * 2 + sizeof(ARGB) * src_palette->Count);
1276
1277 if (dst_palette)
1278 {
1279 dst_palette->Flags = src_palette->Flags;
1280 dst_palette->Count = src_palette->Count;
1281 memcpy(dst_palette->Entries, src_palette->Entries, sizeof(ARGB) * src_palette->Count);
1282
1283 heap_free((*dstBitmap)->image.palette);
1284 (*dstBitmap)->image.palette = dst_palette;
1285 }
1286 else
1287 stat = OutOfMemory;
1288 }
1289
1290 if (stat != Ok)
1291 GdipDisposeImage(&(*dstBitmap)->image);
1292 }
1293
1294 if (stat != Ok)
1295 *dstBitmap = NULL;
1296
1297 return stat;
1298}
1299
1301 PixelFormat format, GpBitmap* srcBitmap, GpBitmap** dstBitmap)
1302{
1303 TRACE("(%i,%i,%i,%i,0x%x,%p,%p)\n", x, y, width, height, format, srcBitmap, dstBitmap);
1304
1305 return GdipCloneBitmapArea(x, y, width, height, format, srcBitmap, dstBitmap);
1306}
1307
1309{
1310 TRACE("%p, %p\n", image, cloneImage);
1311
1312 if (!image || !cloneImage)
1313 return InvalidParameter;
1314
1315 if (image->type == ImageTypeBitmap)
1316 {
1318
1320 bitmap->format, bitmap, (GpBitmap **)cloneImage);
1321 }
1322 else if (image->type == ImageTypeMetafile && ((GpMetafile*)image)->hemf)
1323 {
1325
1327
1328 result = heap_alloc_zero(sizeof(*result));
1329 if (!result)
1330 return OutOfMemory;
1331
1332 result->image.type = ImageTypeMetafile;
1333 result->image.format = image->format;
1334 result->image.flags = image->flags;
1335 result->image.frame_count = 1;
1336 result->image.xres = image->xres;
1337 result->image.yres = image->yres;
1338 result->bounds = metafile->bounds;
1339 result->unit = metafile->unit;
1340 result->metafile_type = metafile->metafile_type;
1341 result->hemf = CopyEnhMetaFileW(metafile->hemf, NULL);
1342 list_init(&result->containers);
1343
1344 if (!result->hemf)
1345 {
1347 return OutOfMemory;
1348 }
1349
1350 *cloneImage = &result->image;
1351 return Ok;
1352 }
1353 else
1354 {
1355 WARN("GpImage with no image data (metafile in wrong state?)\n");
1356 return InvalidParameter;
1357 }
1358}
1359
1361 GpBitmap **bitmap)
1362{
1363 GpStatus stat;
1364 IStream *stream;
1365
1366 TRACE("(%s) %p\n", debugstr_w(filename), bitmap);
1367
1368 if(!filename || !bitmap)
1369 return InvalidParameter;
1370
1371 *bitmap = NULL;
1372
1374
1375 if(stat != Ok)
1376 return stat;
1377
1379
1380 IStream_Release(stream);
1381
1382 return stat;
1383}
1384
1387{
1390
1391 FIXME("(%p, %p, %p) - partially implemented\n", info, bits, bitmap);
1392
1393 if (!info || !bits || !bitmap)
1394 return InvalidParameter;
1395
1396 height = abs(info->bmiHeader.biHeight);
1397 stride = ((info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) >> 3) & ~3;
1398
1399 if(info->bmiHeader.biHeight > 0) /* bottom-up */
1400 {
1401 bits = (BYTE*)bits + (height - 1) * stride;
1402 stride = -stride;
1403 }
1404
1405 switch(info->bmiHeader.biBitCount) {
1406 case 1:
1408 break;
1409 case 4:
1411 break;
1412 case 8:
1414 break;
1415 case 16:
1417 break;
1418 case 24:
1420 break;
1421 case 32:
1423 break;
1424 default:
1425 FIXME("don't know how to handle %d bpp\n", info->bmiHeader.biBitCount);
1426 *bitmap = NULL;
1427 return InvalidParameter;
1428 }
1429
1430 return GdipCreateBitmapFromScan0(info->bmiHeader.biWidth, height, stride, format,
1431 bits, bitmap);
1432
1433}
1434
1435/* FIXME: no icm */
1437 GpBitmap **bitmap)
1438{
1439 TRACE("(%s) %p\n", debugstr_w(filename), bitmap);
1440
1442}
1443
1445 GDIPCONST WCHAR* lpBitmapName, GpBitmap** bitmap)
1446{
1447 HBITMAP hbm;
1449
1450 TRACE("%p (%s) %p\n", hInstance, debugstr_w(lpBitmapName), bitmap);
1451
1452 if(!lpBitmapName || !bitmap)
1453 return InvalidParameter;
1454
1455 /* load DIB */
1456 hbm = LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0,
1458
1459 if(hbm){
1462 }
1463
1464 return stat;
1465}
1466
1468{
1469 BYTE b = (BYTE)src;
1470 BYTE g = (BYTE)(src >> 8);
1471 BYTE r = (BYTE)(src >> 16);
1472 DWORD alpha = (BYTE)(src >> 24);
1473 return ((b + ((BYTE)bkgnd * (255 - alpha) + 127) / 255) |
1474 (g + ((BYTE)(bkgnd >> 8) * (255 - alpha) + 127) / 255) << 8 |
1475 (r + ((BYTE)(bkgnd >> 16) * (255 - alpha) + 127) / 255) << 16 |
1476 (alpha << 24));
1477}
1478
1480 HBITMAP* hbmReturn, ARGB background)
1481{
1482 GpStatus stat;
1484 UINT width, height;
1485 BITMAPINFOHEADER bih;
1486 LPBYTE bits;
1487 BOOL unlock;
1488
1489 TRACE("(%p,%p,%x)\n", bitmap, hbmReturn, background);
1490
1491 if (!bitmap || !hbmReturn) return InvalidParameter;
1492 if (!image_lock(&bitmap->image, &unlock)) return ObjectBusy;
1493
1494 GdipGetImageWidth(&bitmap->image, &width);
1495 GdipGetImageHeight(&bitmap->image, &height);
1496
1497 bih.biSize = sizeof(bih);
1498 bih.biWidth = width;
1499 bih.biHeight = height;
1500 bih.biPlanes = 1;
1501 bih.biBitCount = 32;
1502 bih.biCompression = BI_RGB;
1503 bih.biSizeImage = 0;
1504 bih.biXPelsPerMeter = 0;
1505 bih.biYPelsPerMeter = 0;
1506 bih.biClrUsed = 0;
1507 bih.biClrImportant = 0;
1508
1509 result = CreateDIBSection(0, (BITMAPINFO*)&bih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1510 if (!result)
1511 {
1512 image_unlock(&bitmap->image, unlock);
1513 return GenericError;
1514 }
1515
1517 bits + (width * 4 * (height - 1)), PixelFormat32bppPARGB,
1518 bitmap->stride, bitmap->bits, bitmap->format, bitmap->image.palette);
1519 if (stat != Ok)
1520 {
1522 image_unlock(&bitmap->image, unlock);
1523 return stat;
1524 }
1525
1526 if (background & 0xffffff)
1527 {
1528 DWORD *ptr;
1529 UINT i;
1530 for (ptr = (DWORD*)bits, i = 0; i < width * height; ptr++, i++)
1531 {
1532 if ((*ptr & 0xff000000) == 0xff000000) continue;
1533 *ptr = blend_argb_no_bkgnd_alpha(*ptr, background);
1534 }
1535 }
1536
1537 *hbmReturn = result;
1538 image_unlock(&bitmap->image, unlock);
1539 return Ok;
1540}
1541
1544{
1545 GpStatus ret;
1546
1547 TRACE("(%d, %d, %p, %p)\n", width, height, target, bitmap);
1548
1549 if(!target || !bitmap)
1550 return InvalidParameter;
1551
1553 NULL, bitmap);
1554
1555 if (ret == Ok)
1556 {
1557 GdipGetDpiX(target, &(*bitmap)->image.xres);
1558 GdipGetDpiY(target, &(*bitmap)->image.yres);
1559 }
1560
1561 return ret;
1562}
1563
1565{
1566 GpStatus stat;
1567 ICONINFO iinfo;
1568 BITMAP bm;
1569 int ret;
1571 GpRect rect;
1572 BitmapData lockeddata;
1573 HDC screendc;
1574 BOOL has_alpha;
1575 int x, y;
1576 BITMAPINFOHEADER bih;
1577 DWORD *src;
1578 BYTE *dst_row;
1579 DWORD *dst;
1580
1581 TRACE("%p, %p\n", hicon, bitmap);
1582
1583 if(!bitmap || !GetIconInfo(hicon, &iinfo))
1584 return InvalidParameter;
1585
1586 /* get the size of the icon */
1587 ret = GetObjectA(iinfo.hbmColor ? iinfo.hbmColor : iinfo.hbmMask, sizeof(bm), &bm);
1588 if (ret == 0) {
1589 DeleteObject(iinfo.hbmColor);
1590 DeleteObject(iinfo.hbmMask);
1591 return GenericError;
1592 }
1593
1594 width = bm.bmWidth;
1595 height = iinfo.hbmColor ? abs(bm.bmHeight) : abs(bm.bmHeight) / 2;
1596 stride = width * 4;
1597
1599 if (stat != Ok) {
1600 DeleteObject(iinfo.hbmColor);
1601 DeleteObject(iinfo.hbmMask);
1602 return stat;
1603 }
1604
1605 rect.X = 0;
1606 rect.Y = 0;
1607 rect.Width = width;
1608 rect.Height = height;
1609
1611 if (stat != Ok) {
1612 DeleteObject(iinfo.hbmColor);
1613 DeleteObject(iinfo.hbmMask);
1614 GdipDisposeImage(&(*bitmap)->image);
1615 return stat;
1616 }
1617
1618 bih.biSize = sizeof(bih);
1619 bih.biWidth = width;
1620 bih.biHeight = iinfo.hbmColor ? -height: -height * 2;
1621 bih.biPlanes = 1;
1622 bih.biBitCount = 32;
1623 bih.biCompression = BI_RGB;
1624 bih.biSizeImage = 0;
1625 bih.biXPelsPerMeter = 0;
1626 bih.biYPelsPerMeter = 0;
1627 bih.biClrUsed = 0;
1628 bih.biClrImportant = 0;
1629
1630 screendc = CreateCompatibleDC(0);
1631 if (iinfo.hbmColor)
1632 {
1633 GetDIBits(screendc, iinfo.hbmColor, 0, height, lockeddata.Scan0, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
1634
1635 if (bm.bmBitsPixel == 32)
1636 {
1637 has_alpha = FALSE;
1638
1639 /* If any pixel has a non-zero alpha, ignore hbmMask */
1640 src = (DWORD*)lockeddata.Scan0;
1641 for (x=0; x<width && !has_alpha; x++)
1642 for (y=0; y<height && !has_alpha; y++)
1643 if ((*src++ & 0xff000000) != 0)
1644 has_alpha = TRUE;
1645 }
1646 else has_alpha = FALSE;
1647 }
1648 else
1649 {
1650 GetDIBits(screendc, iinfo.hbmMask, 0, height, lockeddata.Scan0, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
1651 has_alpha = FALSE;
1652 }
1653
1654 if (!has_alpha)
1655 {
1656 if (iinfo.hbmMask)
1657 {
1659
1660 /* read alpha data from the mask */
1661 if (iinfo.hbmColor)
1662 GetDIBits(screendc, iinfo.hbmMask, 0, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
1663 else
1664 GetDIBits(screendc, iinfo.hbmMask, height, height, bits, (BITMAPINFO*)&bih, DIB_RGB_COLORS);
1665
1666 src = (DWORD*)bits;
1667 dst_row = lockeddata.Scan0;
1668 for (y=0; y<height; y++)
1669 {
1670 dst = (DWORD*)dst_row;
1671 for (x=0; x<height; x++)
1672 {
1673 DWORD src_value = *src++;
1674 if (src_value)
1675 *dst++ = 0;
1676 else
1677 *dst++ |= 0xff000000;
1678 }
1679 dst_row += lockeddata.Stride;
1680 }
1681
1682 heap_free(bits);
1683 }
1684 else
1685 {
1686 /* set constant alpha of 255 */
1687 dst_row = lockeddata.Scan0;
1688 for (y=0; y<height; y++)
1689 {
1690 dst = (DWORD*)dst_row;
1691 for (x=0; x<height; x++)
1692 *dst++ |= 0xff000000;
1693 dst_row += lockeddata.Stride;
1694 }
1695 }
1696 }
1697
1698 DeleteDC(screendc);
1699
1700 DeleteObject(iinfo.hbmColor);
1701 DeleteObject(iinfo.hbmMask);
1702
1703 GdipBitmapUnlockBits(*bitmap, &lockeddata);
1704
1705 return Ok;
1706}
1707
1709{
1710 static const BYTE halftone_values[6]={0x00,0x33,0x66,0x99,0xcc,0xff};
1711 UINT i;
1712
1713 for (i=0; i<8 && i<count; i++)
1714 {
1715 entries[i] = 0xff000000;
1716 if (i&1) entries[i] |= 0x800000;
1717 if (i&2) entries[i] |= 0x8000;
1718 if (i&4) entries[i] |= 0x80;
1719 }
1720
1721 if (8 < count)
1722 entries[i] = 0xffc0c0c0;
1723
1724 for (i=9; i<16 && i<count; i++)
1725 {
1726 entries[i] = 0xff000000;
1727 if (i&1) entries[i] |= 0xff0000;
1728 if (i&2) entries[i] |= 0xff00;
1729 if (i&4) entries[i] |= 0xff;
1730 }
1731
1732 for (i=16; i<40 && i<count; i++)
1733 {
1734 entries[i] = 0;
1735 }
1736
1737 for (i=40; i<256 && i<count; i++)
1738 {
1739 entries[i] = 0xff000000;
1740 entries[i] |= halftone_values[(i-40)%6];
1741 entries[i] |= halftone_values[((i-40)/6)%6] << 8;
1742 entries[i] |= halftone_values[((i-40)/36)%6] << 16;
1743 }
1744}
1745
1747{
1748 HDC screendc = CreateCompatibleDC(0);
1749
1750 if (!screendc) return GenericError;
1751
1752 *xres = (REAL)GetDeviceCaps(screendc, LOGPIXELSX);
1753 *yres = (REAL)GetDeviceCaps(screendc, LOGPIXELSY);
1754
1755 DeleteDC(screendc);
1756
1757 return Ok;
1758}
1759
1762{
1764 INT row_size, dib_stride;
1765 BYTE *bits=NULL, *own_bits=NULL;
1766 REAL xres, yres;
1767 GpStatus stat;
1768
1769 TRACE("%d %d %d 0x%x %p %p\n", width, height, stride, format, scan0, bitmap);
1770
1771 if (!bitmap) return InvalidParameter;
1772
1773 if(width <= 0 || height <= 0 || (scan0 && (stride % 4))){
1774 *bitmap = NULL;
1775 return InvalidParameter;
1776 }
1777
1778 if(scan0 && !stride)
1779 return InvalidParameter;
1780
1781 stat = get_screen_resolution(&xres, &yres);
1782 if (stat != Ok) return stat;
1783
1784 row_size = (width * PIXELFORMATBPP(format)+7) / 8;
1785 dib_stride = (row_size + 3) & ~3;
1786
1787 if(stride == 0)
1788 stride = dib_stride;
1789
1791 {
1792 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
1793 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
1794
1798 pbmi->bmiHeader.biPlanes = 1;
1799 /* FIXME: use the rest of the data from format */
1807
1808 hbitmap = CreateDIBSection(0, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1809
1810 if (!hbitmap) return GenericError;
1811
1812 stride = dib_stride;
1813 }
1814 else
1815 {
1816 /* Not a GDI format; don't try to make an HBITMAP. */
1817 if (scan0)
1818 bits = scan0;
1819 else
1820 {
1821 INT size = abs(stride) * height;
1822
1823 own_bits = bits = heap_alloc_zero(size);
1824 if (!own_bits) return OutOfMemory;
1825
1826 if (stride < 0)
1827 bits += stride * (1 - height);
1828 }
1829 }
1830
1831 *bitmap = heap_alloc_zero(sizeof(GpBitmap));
1832 if(!*bitmap)
1833 {
1835 heap_free(own_bits);
1836 return OutOfMemory;
1837 }
1838
1839 (*bitmap)->image.type = ImageTypeBitmap;
1840 memcpy(&(*bitmap)->image.format, &ImageFormatMemoryBMP, sizeof(GUID));
1841 (*bitmap)->image.flags = ImageFlagsNone;
1842 (*bitmap)->image.frame_count = 1;
1843 (*bitmap)->image.current_frame = 0;
1844 (*bitmap)->image.palette = NULL;
1845 (*bitmap)->image.xres = xres;
1846 (*bitmap)->image.yres = yres;
1847 (*bitmap)->width = width;
1848 (*bitmap)->height = height;
1849 (*bitmap)->format = format;
1850 (*bitmap)->image.decoder = NULL;
1851 (*bitmap)->hbitmap = hbitmap;
1852 (*bitmap)->hdc = NULL;
1853 (*bitmap)->bits = bits;
1854 (*bitmap)->stride = stride;
1855 (*bitmap)->own_bits = own_bits;
1856 (*bitmap)->metadata_reader = NULL;
1857 (*bitmap)->prop_count = 0;
1858 (*bitmap)->prop_item = NULL;
1859
1860 /* set format-related flags */
1862 (*bitmap)->image.flags |= ImageFlagsHasAlpha;
1863
1867 {
1868 (*bitmap)->image.palette = heap_alloc_zero(sizeof(UINT) * 2 + sizeof(ARGB) * (1 << PIXELFORMATBPP(format)));
1869
1870 if (!(*bitmap)->image.palette)
1871 {
1872 GdipDisposeImage(&(*bitmap)->image);
1873 *bitmap = NULL;
1874 return OutOfMemory;
1875 }
1876
1877 (*bitmap)->image.palette->Count = 1 << PIXELFORMATBPP(format);
1878
1880 {
1881 (*bitmap)->image.palette->Flags = PaletteFlagsGrayScale;
1882 (*bitmap)->image.palette->Entries[0] = 0xff000000;
1883 (*bitmap)->image.palette->Entries[1] = 0xffffffff;
1884 }
1885 else
1886 {
1888 (*bitmap)->image.palette->Flags = PaletteFlagsHalftone;
1889
1890 generate_halftone_palette((*bitmap)->image.palette->Entries,
1891 (*bitmap)->image.palette->Count);
1892 }
1893 }
1894
1895 TRACE("<-- %p\n", *bitmap);
1896
1897 return Ok;
1898}
1899
1900#ifdef __REACTOS__
1901static HBITMAP hbitmap_from_emf(HENHMETAFILE hemf)
1902{
1903 BITMAPINFO bmi;
1904 HBITMAP hbm;
1905 SIZE size;
1907 HGDIOBJ hbmOld;
1908 RECT rc;
1909 HDC hdc;
1910
1911 GetEnhMetaFileHeader(hemf, sizeof(header), &header);
1912 size.cx = header.rclBounds.right - header.rclBounds.left + 1;
1913 size.cy = header.rclBounds.bottom - header.rclBounds.top + 1;
1914
1915 ZeroMemory(&bmi, sizeof(bmi));
1916 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
1917 bmi.bmiHeader.biWidth = size.cx;
1918 bmi.bmiHeader.biHeight = size.cy;
1919 bmi.bmiHeader.biPlanes = 1;
1920 bmi.bmiHeader.biBitCount = 24;
1921
1924
1925 hbmOld = SelectObject(hdc, hbm);
1926 SetRect(&rc, 0, 0, size.cx, size.cy);
1927 PlayEnhMetaFile(hdc, hemf, &rc);
1928 SelectObject(hdc, hbmOld);
1929
1930 DeleteDC(hdc);
1931 return hbm;
1932}
1933
1934#endif
1936 GpBitmap **bitmap)
1937{
1938 GpStatus stat;
1939
1940 TRACE("%p %p\n", stream, bitmap);
1941
1943
1944 if(stat != Ok)
1945 return stat;
1946
1947#ifdef __REACTOS__
1948 if ((*bitmap)->image.type == ImageTypeMetafile)
1949 {
1950 HBITMAP hbm = hbitmap_from_emf(((GpMetafile*)*bitmap)->hemf);
1951 GdipDisposeImage(&(*bitmap)->image);
1952 if (!hbm)
1953 return GenericError; /* FIXME: what error to return? */
1954
1957 }
1958 else
1959#endif
1960 if((*bitmap)->image.type != ImageTypeBitmap){
1961 GdipDisposeImage(&(*bitmap)->image);
1962 *bitmap = NULL;
1963 return GenericError; /* FIXME: what error to return? */
1964 }
1965
1966 return Ok;
1967}
1968
1969/* FIXME: no icm */
1971 GpBitmap **bitmap)
1972{
1973 TRACE("%p %p\n", stream, bitmap);
1974
1976}
1977
1979 GpCachedBitmap **cachedbmp)
1980{
1981 GpStatus stat;
1982
1983 TRACE("%p %p %p\n", bitmap, graphics, cachedbmp);
1984
1985 if(!bitmap || !graphics || !cachedbmp)
1986 return InvalidParameter;
1987
1988 *cachedbmp = heap_alloc_zero(sizeof(GpCachedBitmap));
1989 if(!*cachedbmp)
1990 return OutOfMemory;
1991
1992 stat = GdipCloneImage(&(bitmap->image), &(*cachedbmp)->image);
1993 if(stat != Ok){
1994 heap_free(*cachedbmp);
1995 return stat;
1996 }
1997
1998 return Ok;
1999}
2000
2002{
2003 GpStatus stat;
2004 BitmapData lockeddata;
2005 ULONG andstride, xorstride, bitssize;
2006 LPBYTE andbits, xorbits, androw, xorrow, srcrow;
2007 UINT x, y;
2008
2009 TRACE("(%p, %p)\n", bitmap, hicon);
2010
2011 if (!bitmap || !hicon)
2012 return InvalidParameter;
2013
2015 PixelFormat32bppPARGB, &lockeddata);
2016 if (stat == Ok)
2017 {
2018 andstride = ((lockeddata.Width+31)/32)*4;
2019 xorstride = lockeddata.Width*4;
2020 bitssize = (andstride + xorstride) * lockeddata.Height;
2021
2022 andbits = heap_alloc_zero(bitssize);
2023
2024 if (andbits)
2025 {
2026 xorbits = andbits + andstride * lockeddata.Height;
2027
2028 for (y=0; y<lockeddata.Height; y++)
2029 {
2030 srcrow = ((LPBYTE)lockeddata.Scan0) + lockeddata.Stride * y;
2031
2032 androw = andbits + andstride * y;
2033 for (x=0; x<lockeddata.Width; x++)
2034 if (srcrow[3+4*x] >= 128)
2035 androw[x/8] |= 1 << (7-x%8);
2036
2037 xorrow = xorbits + xorstride * y;
2038 memcpy(xorrow, srcrow, xorstride);
2039 }
2040
2041 *hicon = CreateIcon(NULL, lockeddata.Width, lockeddata.Height, 1, 32,
2042 andbits, xorbits);
2043
2044 heap_free(andbits);
2045 }
2046 else
2047 stat = OutOfMemory;
2048
2049 GdipBitmapUnlockBits(bitmap, &lockeddata);
2050 }
2051
2052 return stat;
2053}
2054
2056{
2057 TRACE("%p\n", cachedbmp);
2058
2059 if(!cachedbmp)
2060 return InvalidParameter;
2061
2062 GdipDisposeImage(cachedbmp->image);
2063 heap_free(cachedbmp);
2064
2065 return Ok;
2066}
2067
2069 GpCachedBitmap *cachedbmp, INT x, INT y)
2070{
2071 TRACE("%p %p %d %d\n", graphics, cachedbmp, x, y);
2072
2073 if(!graphics || !cachedbmp)
2074 return InvalidParameter;
2075
2076 return GdipDrawImage(graphics, cachedbmp->image, (REAL)x, (REAL)y);
2077}
2078
2079/* Internal utility function: Replace the image data of dst with that of src,
2080 * and free src. */
2081static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
2082{
2083 assert(src->image.type == ImageTypeBitmap);
2084 assert(dst->image.type == ImageTypeBitmap);
2085
2086 heap_free(dst->bitmapbits);
2087 heap_free(dst->own_bits);
2088 DeleteDC(dst->hdc);
2089 DeleteObject(dst->hbitmap);
2090
2091 if (clobber_palette)
2092 {
2093 heap_free(dst->image.palette);
2094 dst->image.palette = src->image.palette;
2095 }
2096 else
2097 heap_free(src->image.palette);
2098
2099 dst->image.xres = src->image.xres;
2100 dst->image.yres = src->image.yres;
2101 dst->width = src->width;
2102 dst->height = src->height;
2103 dst->format = src->format;
2104 dst->hbitmap = src->hbitmap;
2105 dst->hdc = src->hdc;
2106 dst->bits = src->bits;
2107 dst->stride = src->stride;
2108 dst->own_bits = src->own_bits;
2109 if (dst->metadata_reader)
2110 IWICMetadataReader_Release(dst->metadata_reader);
2111 dst->metadata_reader = src->metadata_reader;
2112 heap_free(dst->prop_item);
2113 dst->prop_item = src->prop_item;
2114 dst->prop_count = src->prop_count;
2115 if (dst->image.decoder)
2116 IWICBitmapDecoder_Release(dst->image.decoder);
2117 dst->image.decoder = src->image.decoder;
2118 dst->image.frame_count = src->image.frame_count;
2119 dst->image.current_frame = src->image.current_frame;
2120 dst->image.format = src->image.format;
2121
2122 src->image.type = ~0;
2123 heap_free(src);
2124}
2125
2127{
2128 if(!image)
2129 return InvalidParameter;
2130
2131 if (image->type == ImageTypeBitmap)
2132 {
2133 heap_free(((GpBitmap*)image)->bitmapbits);
2134 heap_free(((GpBitmap*)image)->own_bits);
2135 DeleteDC(((GpBitmap*)image)->hdc);
2137 if (((GpBitmap*)image)->metadata_reader)
2138 IWICMetadataReader_Release(((GpBitmap*)image)->metadata_reader);
2139 heap_free(((GpBitmap*)image)->prop_item);
2140 }
2141 else if (image->type == ImageTypeMetafile)
2143 else
2144 {
2145 WARN("invalid image: %p\n", image);
2146 return ObjectBusy;
2147 }
2148 if (image->decoder)
2149 IWICBitmapDecoder_Release(image->decoder);
2150 heap_free(image->palette);
2151
2152 return Ok;
2153}
2154
2156{
2158
2159 TRACE("%p\n", image);
2160
2162 if (status != Ok) return status;
2163 image->type = ~0;
2165
2166 return Ok;
2167}
2168
2170{
2171 static int calls;
2172
2173 TRACE("(%p,%p)\n", image, item);
2174
2175 if(!image || !item)
2176 return InvalidParameter;
2177
2178 if (!(calls++))
2179 FIXME("not implemented\n");
2180
2181 return NotImplemented;
2182}
2183
2185{
2186 static int calls;
2187
2188 TRACE("(%p,%p)\n", image, item);
2189
2190 if (!(calls++))
2191 FIXME("not implemented\n");
2192
2193 return NotImplemented;
2194}
2195
2197 GpUnit *srcUnit)
2198{
2199 TRACE("%p %p %p\n", image, srcRect, srcUnit);
2200
2201 if(!image || !srcRect || !srcUnit)
2202 return InvalidParameter;
2203 if(image->type == ImageTypeMetafile){
2204 *srcRect = ((GpMetafile*)image)->bounds;
2205 *srcUnit = ((GpMetafile*)image)->unit;
2206 }
2207 else if(image->type == ImageTypeBitmap){
2208 srcRect->X = srcRect->Y = 0.0;
2209 srcRect->Width = (REAL) ((GpBitmap*)image)->width;
2210 srcRect->Height = (REAL) ((GpBitmap*)image)->height;
2211 *srcUnit = UnitPixel;
2212 }
2213 else{
2214 WARN("GpImage with no image data\n");
2215 return InvalidParameter;
2216 }
2217
2218 TRACE("returning (%f, %f) (%f, %f) unit type %d\n", srcRect->X, srcRect->Y,
2219 srcRect->Width, srcRect->Height, *srcUnit);
2220
2221 return Ok;
2222}
2223
2225 REAL *height)
2226{
2227 TRACE("%p %p %p\n", image, width, height);
2228
2229 if(!image || !height || !width)
2230 return InvalidParameter;
2231
2232 if(image->type == ImageTypeMetafile){
2233 *height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit, image->yres);
2234 *width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit, image->xres);
2235 }
2236 else if(image->type == ImageTypeBitmap){
2237 *height = ((GpBitmap*)image)->height;
2238 *width = ((GpBitmap*)image)->width;
2239 }
2240 else{
2241 WARN("GpImage with no image data\n");
2242 return InvalidParameter;
2243 }
2244
2245 TRACE("returning (%f, %f)\n", *height, *width);
2246 return Ok;
2247}
2248
2250 GpGraphics **graphics)
2251{
2252 HDC hdc;
2253 GpStatus stat;
2254
2255 TRACE("%p %p\n", image, graphics);
2256
2257 if(!image || !graphics)
2258 return InvalidParameter;
2259
2260 if (image->type == ImageTypeBitmap && ((GpBitmap*)image)->hbitmap)
2261 {
2262 hdc = ((GpBitmap*)image)->hdc;
2263
2264 if(!hdc){
2267 ((GpBitmap*)image)->hdc = hdc;
2268 }
2269
2270 stat = GdipCreateFromHDC(hdc, graphics);
2271
2272 if (stat == Ok)
2273 {
2274 (*graphics)->image = image;
2275 (*graphics)->xres = image->xres;
2276 (*graphics)->yres = image->yres;
2277 }
2278 }
2279 else if (image->type == ImageTypeMetafile)
2281 else
2282 stat = graphics_from_image(image, graphics);
2283
2284 return stat;
2285}
2286
2288{
2289 TRACE("%p %p\n", image, height);
2290
2291 if(!image || !height)
2292 return InvalidParameter;
2293
2294 if(image->type == ImageTypeMetafile)
2295 *height = units_to_pixels(((GpMetafile*)image)->bounds.Height, ((GpMetafile*)image)->unit, image->yres);
2296 else if(image->type == ImageTypeBitmap)
2297 *height = ((GpBitmap*)image)->height;
2298 else
2299 {
2300 WARN("GpImage with no image data\n");
2301 return InvalidParameter;
2302 }
2303
2304 TRACE("returning %d\n", *height);
2305
2306 return Ok;
2307}
2308
2310{
2311 if(!image || !res)
2312 return InvalidParameter;
2313
2314 *res = image->xres;
2315
2316 TRACE("(%p) <-- %0.2f\n", image, *res);
2317
2318 return Ok;
2319}
2320
2322{
2323 TRACE("%p %p\n", image, size);
2324
2325 if(!image || !size)
2326 return InvalidParameter;
2327
2328 if (!image->palette || image->palette->Count == 0)
2329 *size = sizeof(ColorPalette);
2330 else
2331 *size = sizeof(UINT)*2 + sizeof(ARGB)*image->palette->Count;
2332
2333 TRACE("<-- %u\n", *size);
2334
2335 return Ok;
2336}
2337
2338/* FIXME: test this function for non-bitmap types */
2340{
2341 TRACE("%p %p\n", image, format);
2342
2343 if(!image || !format)
2344 return InvalidParameter;
2345
2346 if(image->type != ImageTypeBitmap)
2348 else
2349 *format = ((GpBitmap*) image)->format;
2350
2351 return Ok;
2352}
2353
2355{
2356 TRACE("(%p, %p)\n", image, format);
2357
2358 if(!image || !format)
2359 return InvalidParameter;
2360
2361 memcpy(format, &image->format, sizeof(GUID));
2362
2363 return Ok;
2364}
2365
2367{
2368 TRACE("%p %p\n", image, type);
2369
2370 if(!image || !type)
2371 return InvalidParameter;
2372
2373 *type = image->type;
2374
2375 return Ok;
2376}
2377
2379{
2380 if(!image || !res)
2381 return InvalidParameter;
2382
2383 *res = image->yres;
2384
2385 TRACE("(%p) <-- %0.2f\n", image, *res);
2386
2387 return Ok;
2388}
2389
2391{
2392 TRACE("%p %p\n", image, width);
2393
2394 if(!image || !width)
2395 return InvalidParameter;
2396
2397 if(image->type == ImageTypeMetafile)
2398 *width = units_to_pixels(((GpMetafile*)image)->bounds.Width, ((GpMetafile*)image)->unit, image->xres);
2399 else if(image->type == ImageTypeBitmap)
2400 *width = ((GpBitmap*)image)->width;
2401 else
2402 {
2403 WARN("GpImage with no image data\n");
2404 return InvalidParameter;
2405 }
2406
2407 TRACE("returning %d\n", *width);
2408
2409 return Ok;
2410}
2411
2413{
2414 TRACE("(%p, %p)\n", image, num);
2415
2416 if (!image || !num) return InvalidParameter;
2417
2418 *num = 0;
2419
2420 if (image->type == ImageTypeBitmap)
2421 {
2422 if (((GpBitmap *)image)->prop_item)
2423 {
2424 *num = ((GpBitmap *)image)->prop_count;
2425 return Ok;
2426 }
2427
2428 if (((GpBitmap *)image)->metadata_reader)
2429 IWICMetadataReader_GetCount(((GpBitmap *)image)->metadata_reader, num);
2430 }
2431
2432 return Ok;
2433}
2434
2436{
2437 HRESULT hr;
2439 IWICEnumMetadataItem *enumerator;
2440 UINT prop_count, i, items_returned;
2441
2442 TRACE("(%p, %u, %p)\n", image, num, list);
2443
2444 if (!image || !list) return InvalidParameter;
2445
2446 if (image->type != ImageTypeBitmap)
2447 {
2448 FIXME("Not implemented for type %d\n", image->type);
2449 return NotImplemented;
2450 }
2451
2452 if (((GpBitmap *)image)->prop_item)
2453 {
2454 if (num != ((GpBitmap *)image)->prop_count) return InvalidParameter;
2455
2456 for (i = 0; i < num; i++)
2457 {
2458 list[i] = ((GpBitmap *)image)->prop_item[i].id;
2459 }
2460
2461 return Ok;
2462 }
2463
2464 reader = ((GpBitmap *)image)->metadata_reader;
2465 if (!reader)
2466 {
2467 if (num != 0) return InvalidParameter;
2468 return Ok;
2469 }
2470
2471 hr = IWICMetadataReader_GetCount(reader, &prop_count);
2472 if (FAILED(hr)) return hresult_to_status(hr);
2473
2474 if (num != prop_count) return InvalidParameter;
2475
2476 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
2477 if (FAILED(hr)) return hresult_to_status(hr);
2478
2479 IWICEnumMetadataItem_Reset(enumerator);
2480
2481 for (i = 0; i < num; i++)
2482 {
2483 PROPVARIANT id;
2484
2485 hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, NULL, &items_returned);
2486 if (hr != S_OK) break;
2487
2488 if (id.vt != VT_UI2)
2489 {
2490 FIXME("not supported propvariant type for id: %u\n", id.vt);
2491 list[i] = 0;
2492 continue;
2493 }
2494 list[i] = id.u.uiVal;
2495 }
2496
2497 IWICEnumMetadataItem_Release(enumerator);
2498
2499 return hr == S_OK ? Ok : hresult_to_status(hr);
2500}
2501
2502static UINT propvariant_size(PROPVARIANT *value)
2503{
2504 switch (value->vt & ~VT_VECTOR)
2505 {
2506 case VT_EMPTY:
2507 return 0;
2508 case VT_I1:
2509 case VT_UI1:
2510 if (!(value->vt & VT_VECTOR)) return 1;
2511 return value->u.caub.cElems;
2512 case VT_I2:
2513 case VT_UI2:
2514 if (!(value->vt & VT_VECTOR)) return 2;
2515 return value->u.caui.cElems * 2;
2516 case VT_I4:
2517 case VT_UI4:
2518 case VT_R4:
2519 if (!(value->vt & VT_VECTOR)) return 4;
2520 return value->u.caul.cElems * 4;
2521 case VT_I8:
2522 case VT_UI8:
2523 case VT_R8:
2524 if (!(value->vt & VT_VECTOR)) return 8;
2525 return value->u.cauh.cElems * 8;
2526 case VT_LPSTR:
2527 return value->u.pszVal ? strlen(value->u.pszVal) + 1 : 0;
2528 case VT_BLOB:
2529 return value->u.blob.cbSize;
2530 default:
2531 FIXME("not supported variant type %d\n", value->vt);
2532 return 0;
2533 }
2534}
2535
2537{
2538 HRESULT hr;
2540 PROPVARIANT id, value;
2541
2542 TRACE("(%p,%#x,%p)\n", image, propid, size);
2543
2544 if (!size || !image) return InvalidParameter;
2545
2546 if (image->type != ImageTypeBitmap)
2547 {
2548 FIXME("Not implemented for type %d\n", image->type);
2549 return NotImplemented;
2550 }
2551
2552 if (((GpBitmap *)image)->prop_item)
2553 {
2554 UINT i;
2555
2556 for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
2557 {
2558 if (propid == ((GpBitmap *)image)->prop_item[i].id)
2559 {
2560 *size = sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length;
2561 return Ok;
2562 }
2563 }
2564
2565 return PropertyNotFound;
2566 }
2567
2568 reader = ((GpBitmap *)image)->metadata_reader;
2569 if (!reader) return PropertyNotFound;
2570
2571 id.vt = VT_UI2;
2572 id.u.uiVal = propid;
2573 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2574 if (FAILED(hr)) return PropertyNotFound;
2575
2577 if (*size) *size += sizeof(PropertyItem);
2579
2580 return Ok;
2581}
2582
2583#ifndef PropertyTagTypeSByte
2584#define PropertyTagTypeSByte 6
2585#define PropertyTagTypeSShort 8
2586#define PropertyTagTypeFloat 11
2587#define PropertyTagTypeDouble 12
2588#endif
2589
2591{
2592 static const struct
2593 {
2594 UINT vt, type;
2595 } vt2type[] =
2596 {
2609 };
2610 UINT i;
2611 for (i = 0; i < ARRAY_SIZE(vt2type); i++)
2612 {
2613 if (vt2type[i].vt == vt) return vt2type[i].type;
2614 }
2615 FIXME("not supported variant type %u\n", vt);
2616 return 0;
2617}
2618
2620 UINT size, PROPID id)
2621{
2622 UINT item_size, item_type;
2623
2624 item_size = propvariant_size(value);
2625 if (size != item_size + sizeof(PropertyItem)) return InvalidParameter;
2626
2627 item_type = vt_to_itemtype(value->vt & ~VT_VECTOR);
2628 if (!item_type) return InvalidParameter;
2629
2630 item->value = item + 1;
2631
2632 switch (value->vt & ~VT_VECTOR)
2633 {
2634 case VT_I1:
2635 case VT_UI1:
2636 if (!(value->vt & VT_VECTOR))
2637 *(BYTE *)item->value = value->u.bVal;
2638 else
2639 memcpy(item->value, value->u.caub.pElems, item_size);
2640 break;
2641 case VT_I2:
2642 case VT_UI2:
2643 if (!(value->vt & VT_VECTOR))
2644 *(USHORT *)item->value = value->u.uiVal;
2645 else
2646 memcpy(item->value, value->u.caui.pElems, item_size);
2647 break;
2648 case VT_I4:
2649 case VT_UI4:
2650 case VT_R4:
2651 if (!(value->vt & VT_VECTOR))
2652 *(ULONG *)item->value = value->u.ulVal;
2653 else
2654 memcpy(item->value, value->u.caul.pElems, item_size);
2655 break;
2656 case VT_I8:
2657 case VT_UI8:
2658 case VT_R8:
2659 if (!(value->vt & VT_VECTOR))
2660 *(ULONGLONG *)item->value = value->u.uhVal.QuadPart;
2661 else
2662 memcpy(item->value, value->u.cauh.pElems, item_size);
2663 break;
2664 case VT_LPSTR:
2665 memcpy(item->value, value->u.pszVal, item_size);
2666 break;
2667 case VT_BLOB:
2668 memcpy(item->value, value->u.blob.pBlobData, item_size);
2669 break;
2670 default:
2671 FIXME("not supported variant type %d\n", value->vt);
2672 return InvalidParameter;
2673 }
2674
2675 item->length = item_size;
2676 item->type = item_type;
2677 item->id = id;
2678
2679 return Ok;
2680}
2681
2684{
2685 GpStatus stat;
2686 HRESULT hr;
2688 PROPVARIANT id, value;
2689
2690 TRACE("(%p,%#x,%u,%p)\n", image, propid, size, buffer);
2691
2692 if (!image || !buffer) return InvalidParameter;
2693
2694 if (image->type != ImageTypeBitmap)
2695 {
2696 FIXME("Not implemented for type %d\n", image->type);
2697 return NotImplemented;
2698 }
2699
2700 if (((GpBitmap *)image)->prop_item)
2701 {
2702 UINT i;
2703
2704 for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
2705 {
2706 if (propid == ((GpBitmap *)image)->prop_item[i].id)
2707 {
2708 if (size != sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length)
2709 return InvalidParameter;
2710
2711 *buffer = ((GpBitmap *)image)->prop_item[i];
2712 buffer->value = buffer + 1;
2713 memcpy(buffer->value, ((GpBitmap *)image)->prop_item[i].value, buffer->length);
2714 return Ok;
2715 }
2716 }
2717
2718 return PropertyNotFound;
2719 }
2720
2721 reader = ((GpBitmap *)image)->metadata_reader;
2722 if (!reader) return PropertyNotFound;
2723
2724 id.vt = VT_UI2;
2725 id.u.uiVal = propid;
2726 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
2727 if (FAILED(hr)) return PropertyNotFound;
2728
2731
2732 return stat;
2733}
2734
2736{
2737 HRESULT hr;
2739 IWICEnumMetadataItem *enumerator;
2740 UINT prop_count, prop_size, i;
2741 PROPVARIANT id, value;
2742
2743 TRACE("(%p,%p,%p)\n", image, size, count);
2744
2745 if (!image || !size || !count) return InvalidParameter;
2746
2747 if (image->type != ImageTypeBitmap)
2748 {
2749 FIXME("Not implemented for type %d\n", image->type);
2750 return NotImplemented;
2751 }
2752
2753 if (((GpBitmap *)image)->prop_item)
2754 {
2755 *count = ((GpBitmap *)image)->prop_count;
2756 *size = 0;
2757
2758 for (i = 0; i < ((GpBitmap *)image)->prop_count; i++)
2759 {
2760 *size += sizeof(PropertyItem) + ((GpBitmap *)image)->prop_item[i].length;
2761 }
2762
2763 return Ok;
2764 }
2765
2766 reader = ((GpBitmap *)image)->metadata_reader;
2767 if (!reader) return PropertyNotFound;
2768
2769 hr = IWICMetadataReader_GetCount(reader, &prop_count);
2770 if (FAILED(hr)) return hresult_to_status(hr);
2771
2772 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
2773 if (FAILED(hr)) return hresult_to_status(hr);
2774
2775 IWICEnumMetadataItem_Reset(enumerator);
2776
2777 prop_size = 0;
2778
2779 PropVariantInit(&id);
2780 PropVariantInit(&value);
2781
2782 for (i = 0; i < prop_count; i++)
2783 {
2784 UINT items_returned, item_size;
2785
2786 hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, &value, &items_returned);
2787 if (hr != S_OK) break;
2788
2789 item_size = propvariant_size(&value);
2790 if (item_size) prop_size += sizeof(PropertyItem) + item_size;
2791
2792 PropVariantClear(&id);
2794 }
2795
2796 IWICEnumMetadataItem_Release(enumerator);
2797
2798 if (hr != S_OK) return PropertyNotFound;
2799
2800 *count = prop_count;
2801 *size = prop_size;
2802 return Ok;
2803}
2804
2807{
2809 HRESULT hr;
2811 IWICEnumMetadataItem *enumerator;
2812 UINT prop_count, prop_size, i;
2813 PROPVARIANT id, value;
2814 char *item_value;
2815
2816 TRACE("(%p,%u,%u,%p)\n", image, size, count, buf);
2817
2818 if (!image || !buf) return InvalidParameter;
2819
2820 if (image->type != ImageTypeBitmap)
2821 {
2822 FIXME("Not implemented for type %d\n", image->type);
2823 return NotImplemented;
2824 }
2825
2826 status = GdipGetPropertySize(image, &prop_size, &prop_count);
2827 if (status != Ok) return status;
2828
2829 if (prop_count != count || prop_size != size) return InvalidParameter;
2830
2831 if (((GpBitmap *)image)->prop_item)
2832 {
2833 memcpy(buf, ((GpBitmap *)image)->prop_item, prop_size);
2834
2835 item_value = (char *)(buf + prop_count);
2836
2837 for (i = 0; i < prop_count; i++)
2838 {
2839 buf[i].value = item_value;
2840 item_value += buf[i].length;
2841 }
2842
2843 return Ok;
2844 }
2845
2846 reader = ((GpBitmap *)image)->metadata_reader;
2847 if (!reader) return PropertyNotFound;
2848
2849 hr = IWICMetadataReader_GetEnumerator(reader, &enumerator);
2850 if (FAILED(hr)) return hresult_to_status(hr);
2851
2852 IWICEnumMetadataItem_Reset(enumerator);
2853
2854 item_value = (char *)(buf + prop_count);
2855
2856 PropVariantInit(&id);
2857 PropVariantInit(&value);
2858
2859 for (i = 0; i < prop_count; i++)
2860 {
2862 UINT items_returned, item_size;
2863
2864 hr = IWICEnumMetadataItem_Next(enumerator, 1, NULL, &id, &value, &items_returned);
2865 if (hr != S_OK) break;
2866
2867 if (id.vt != VT_UI2)
2868 {
2869 FIXME("not supported propvariant type for id: %u\n", id.vt);
2870 continue;
2871 }
2872
2873 item_size = propvariant_size(&value);
2874 if (item_size)
2875 {
2876 item = heap_alloc(item_size + sizeof(*item));
2877
2878 propvariant_to_item(&value, item, item_size + sizeof(*item), id.u.uiVal);
2879 buf[i].id = item->id;
2880 buf[i].type = item->type;
2881 buf[i].length = item_size;
2882 buf[i].value = item_value;
2883 memcpy(item_value, item->value, item_size);
2884 item_value += item_size;
2885
2886 heap_free(item);
2887 }
2888
2889 PropVariantClear(&id);
2891 }
2892
2893 IWICEnumMetadataItem_Release(enumerator);
2894
2895 if (hr != S_OK) return PropertyNotFound;
2896
2897 return Ok;
2898}
2899
2901{
2902 const GUID *format;
2904};
2905
2907{
2908 {&ImageFormatGIF, &FrameDimensionTime},
2909 {&ImageFormatIcon, &FrameDimensionResolution},
2910 {NULL}
2911};
2912
2914 GDIPCONST GUID* dimensionID, UINT* count)
2915{
2916 TRACE("(%p,%s,%p)\n", image, debugstr_guid(dimensionID), count);
2917
2918 if(!image || !count)
2919 return InvalidParameter;
2920
2921 if (!dimensionID ||
2922 IsEqualGUID(dimensionID, &image->format) ||
2923 IsEqualGUID(dimensionID, &FrameDimensionPage) ||
2924 IsEqualGUID(dimensionID, &FrameDimensionTime))
2925 {
2926 *count = image->frame_count;
2927 return Ok;
2928 }
2929
2930 return InvalidParameter;
2931}
2932
2934 UINT* count)
2935{
2936 TRACE("(%p, %p)\n", image, count);
2937
2938 /* Native gdiplus 1.1 does not yet support multiple frame dimensions. */
2939
2940 if(!image || !count)
2941 return InvalidParameter;
2942
2943 *count = 1;
2944
2945 return Ok;
2946}
2947
2949 GUID* dimensionIDs, UINT count)
2950{
2951 int i;
2952 const GUID *result=NULL;
2953
2954 TRACE("(%p,%p,%u)\n", image, dimensionIDs, count);
2955
2956 if(!image || !dimensionIDs || count != 1)
2957 return InvalidParameter;
2958
2959 for (i=0; image_format_dimensions[i].format; i++)
2960 {
2961 if (IsEqualGUID(&image->format, image_format_dimensions[i].format))
2962 {
2963 result = image_format_dimensions[i].dimension;
2964 break;
2965 }
2966 }
2967
2968 if (!result)
2969 result = &FrameDimensionPage;
2970
2971 memcpy(dimensionIDs, result, sizeof(GUID));
2972
2973 return Ok;
2974}
2975
2977 GpImage **image)
2978{
2979 GpStatus stat;
2980 IStream *stream;
2981
2982 TRACE("(%s) %p\n", debugstr_w(filename), image);
2983
2984 if (!filename || !image)
2985 return InvalidParameter;
2986
2987 *image = NULL;
2988
2990
2991 if (stat != Ok)
2992 return stat;
2993
2995
2996 IStream_Release(stream);
2997
2998 return stat;
2999}
3000
3001/* FIXME: no icm handling */
3003{
3004 TRACE("(%s) %p\n", debugstr_w(filename), image);
3005
3007}
3008
3010{
3011 UINT prop_size, prop_count;
3012 PropertyItem *prop_item;
3013
3014 if (bitmap->prop_item == NULL)
3015 {
3016 prop_size = prop_count = 0;
3017 prop_item = heap_alloc_zero(item->length + sizeof(PropertyItem));
3018 if (!prop_item) return;
3019 }
3020 else
3021 {
3022 UINT i;
3023 char *item_value;
3024
3025 GdipGetPropertySize(&bitmap->image, &prop_size, &prop_count);
3026
3027 prop_item = heap_alloc_zero(prop_size + item->length + sizeof(PropertyItem));
3028 if (!prop_item) return;
3029 memcpy(prop_item, bitmap->prop_item, sizeof(PropertyItem) * bitmap->prop_count);
3030 prop_size -= sizeof(PropertyItem) * bitmap->prop_count;
3031 memcpy(prop_item + prop_count + 1, bitmap->prop_item + prop_count, prop_size);
3032
3033 item_value = (char *)(prop_item + prop_count + 1);
3034
3035 for (i = 0; i < prop_count; i++)
3036 {
3037 prop_item[i].value = item_value;
3038 item_value += prop_item[i].length;
3039 }
3040 }
3041
3042 prop_item[prop_count].id = item->id;
3043 prop_item[prop_count].type = item->type;
3044 prop_item[prop_count].length = item->length;
3045 prop_item[prop_count].value = (char *)(prop_item + prop_count + 1) + prop_size;
3046 memcpy(prop_item[prop_count].value, item->value, item->length);
3047
3048 heap_free(bitmap->prop_item);
3049 bitmap->prop_item = prop_item;
3050 bitmap->prop_count++;
3051}
3052
3054{
3055 HRESULT hr;
3056 GUID format;
3057 PROPVARIANT id, value;
3058 BOOL ret = FALSE;
3059
3060 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
3061 if (FAILED(hr) || !IsEqualGUID(&format, guid)) return FALSE;
3062
3063 PropVariantInit(&id);
3064 PropVariantInit(&value);
3065
3066 id.vt = VT_LPWSTR;
3067 id.u.pwszVal = CoTaskMemAlloc((lstrlenW(prop_name) + 1) * sizeof(WCHAR));
3068 if (!id.u.pwszVal) return FALSE;
3069 lstrcpyW(id.u.pwszVal, prop_name);
3070 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
3071 if (hr == S_OK && value.vt == VT_BOOL)
3072 ret = value.u.boolVal;
3073
3074 PropVariantClear(&id);
3076
3077 return ret;
3078}
3079
3081{
3082 HRESULT hr;
3083 GUID format;
3084 PROPVARIANT id, value;
3086
3087 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
3088 if (FAILED(hr) || !IsEqualGUID(&format, guid)) return NULL;
3089
3090 PropVariantInit(&id);
3091 PropVariantInit(&value);
3092
3093 id.vt = VT_LPWSTR;
3094 id.u.pwszVal = CoTaskMemAlloc((lstrlenW(prop_name) + 1) * sizeof(WCHAR));
3095 if (!id.u.pwszVal) return NULL;
3096 lstrcpyW(id.u.pwszVal, prop_name);
3097 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
3098 if (hr == S_OK)
3099 {
3100 UINT item_size = propvariant_size(&value);
3101 if (item_size)
3102 {
3103 item_size += sizeof(*item);
3104 item = heap_alloc_zero(item_size);
3105 if (propvariant_to_item(&value, item, item_size, 0) != Ok)
3106 {
3107 heap_free(item);
3108 item = NULL;
3109 }
3110 }
3111 }
3112
3113 PropVariantClear(&id);
3115
3116 return item;
3117}
3118
3120{
3121 static const WCHAR textentryW[] = { 'T','e','x','t','E','n','t','r','y',0 };
3123
3124 comment = get_property(reader, &GUID_MetadataFormatGifComment, textentryW);
3125 if (comment)
3127
3128 return comment;
3129}
3130
3132{
3133 static const WCHAR applicationW[] = { 'A','p','p','l','i','c','a','t','i','o','n',0 };
3134 static const WCHAR dataW[] = { 'D','a','t','a',0 };
3135 PropertyItem *appext = NULL, *appdata = NULL, *loop = NULL;
3136
3137 appext = get_property(reader, &GUID_MetadataFormatAPE, applicationW);
3138 if (appext)
3139 {
3140 if (appext->type == PropertyTagTypeByte && appext->length == 11 &&
3141 (!memcmp(appext->value, "NETSCAPE2.0", 11) || !memcmp(appext->value, "ANIMEXTS1.0", 11)))
3142 {
3143 appdata = get_property(reader, &GUID_MetadataFormatAPE, dataW);
3144 if (appdata)
3145 {
3146 if (appdata->type == PropertyTagTypeByte && appdata->length == 4)
3147 {
3148 BYTE *data = appdata->value;
3149 if (data[0] == 3 && data[1] == 1)
3150 {
3151 loop = heap_alloc_zero(sizeof(*loop) + sizeof(SHORT));
3152 if (loop)
3153 {
3154 loop->type = PropertyTagTypeShort;
3155 loop->id = PropertyTagLoopCount;
3156 loop->length = sizeof(SHORT);
3157 loop->value = loop + 1;
3158 *(SHORT *)loop->value = data[2] | (data[3] << 8);
3159 }
3160 }
3161 }
3162 }
3163 }
3164 }
3165
3166 heap_free(appext);
3168
3169 return loop;
3170}
3171
3173{
3174 static const WCHAR backgroundW[] = { 'B','a','c','k','g','r','o','u','n','d','C','o','l','o','r','I','n','d','e','x',0 };
3175 PropertyItem *background;
3176
3177 background = get_property(reader, &GUID_MetadataFormatLSD, backgroundW);
3178 if (background)
3179 background->id = PropertyTagIndexBackground;
3180
3181 return background;
3182}
3183
3185{
3186 static const WCHAR global_flagW[] = { 'G','l','o','b','a','l','C','o','l','o','r','T','a','b','l','e','F','l','a','g',0 };
3187 HRESULT hr;
3190 UINT count = 0;
3191 WICColor colors[256];
3192
3193 if (!get_bool_property(reader, &GUID_MetadataFormatLSD, global_flagW))
3194 return NULL;
3195
3196 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
3197 if (hr != S_OK) return NULL;
3198
3199 hr = IWICImagingFactory_CreatePalette(factory, &palette);
3200 if (hr == S_OK)
3201 {
3202 hr = IWICBitmapDecoder_CopyPalette(decoder, palette);
3203 if (hr == S_OK)
3204 IWICPalette_GetColors(palette, 256, colors, &count);
3205
3206 IWICPalette_Release(palette);
3207 }
3208
3209 IWICImagingFactory_Release(factory);
3210
3211 if (count)
3212 {
3213 PropertyItem *pal;
3214 UINT i;
3215 BYTE *rgb;
3216
3217 pal = heap_alloc_zero(sizeof(*pal) + count * 3);
3218 if (!pal) return NULL;
3221 pal->value = pal + 1;
3222 pal->length = count * 3;
3223
3224 rgb = pal->value;
3225
3226 for (i = 0; i < count; i++)
3227 {
3228 rgb[i*3] = (colors[i] >> 16) & 0xff;
3229 rgb[i*3 + 1] = (colors[i] >> 8) & 0xff;
3230 rgb[i*3 + 2] = colors[i] & 0xff;
3231 }
3232
3233 return pal;
3234 }
3235
3236 return NULL;
3237}
3238
3240{
3241 static const WCHAR transparency_flagW[] = { 'T','r','a','n','s','p','a','r','e','n','c','y','F','l','a','g',0 };
3242 static const WCHAR colorW[] = { 'T','r','a','n','s','p','a','r','e','n','t','C','o','l','o','r','I','n','d','e','x',0 };
3244
3245 if (get_bool_property(reader, &GUID_MetadataFormatGCE, transparency_flagW))
3246 {
3247 index = get_property(reader, &GUID_MetadataFormatGCE, colorW);
3248 if (index)
3250 }
3251 return index;
3252}
3253
3255{
3256 HRESULT hr;
3257 IWICMetadataBlockReader *block_reader;
3259 UINT block_count, i;
3260 PropertyItem *prop;
3261 LONG value = 0;
3262
3263 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3264 if (hr == S_OK)
3265 {
3266 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3267 if (hr == S_OK)
3268 {
3269 for (i = 0; i < block_count; i++)
3270 {
3271 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3272 if (hr == S_OK)
3273 {
3275 if (prop)
3276 {
3277 if (prop->type == PropertyTagTypeByte && prop->length == 1)
3278 value = *(BYTE *)prop->value;
3279 else if (prop->type == PropertyTagTypeShort && prop->length == 2)
3280 value = *(SHORT *)prop->value;
3281
3282 heap_free(prop);
3283 }
3284 IWICMetadataReader_Release(reader);
3285 }
3286 }
3287 }
3288 IWICMetadataBlockReader_Release(block_reader);
3289 }
3290
3291 return value;
3292}
3293
3294static void gif_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT active_frame)
3295{
3296 static const WCHAR delayW[] = { 'D','e','l','a','y',0 };
3297 HRESULT hr;
3298 IWICBitmapFrameDecode *frame;
3299 IWICMetadataBlockReader *block_reader;
3301 UINT frame_count, block_count, i;
3302 PropertyItem *delay = NULL, *comment = NULL, *background = NULL;
3303 PropertyItem *transparent_idx = NULL, *loop = NULL, *palette = NULL;
3304
3305 IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
3306 if (frame_count > 1)
3307 {
3308 delay = heap_alloc_zero(sizeof(*delay) + frame_count * sizeof(LONG));
3309 if (delay)
3310 {
3311 LONG *value;
3312
3313 delay->type = PropertyTagTypeLong;
3314 delay->id = PropertyTagFrameDelay;
3315 delay->length = frame_count * sizeof(LONG);
3316 delay->value = delay + 1;
3317
3318 value = delay->value;
3319
3320 for (i = 0; i < frame_count; i++)
3321 {
3322 hr = IWICBitmapDecoder_GetFrame(decoder, i, &frame);
3323 if (hr == S_OK)
3324 {
3325 value[i] = get_gif_frame_property(frame, &GUID_MetadataFormatGCE, delayW);
3326 IWICBitmapFrameDecode_Release(frame);
3327 }
3328 else value[i] = 0;
3329 }
3330 }
3331 }
3332
3333 hr = IWICBitmapDecoder_QueryInterface(decoder, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3334 if (hr == S_OK)
3335 {
3336 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3337 if (hr == S_OK)
3338 {
3339 for (i = 0; i < block_count; i++)
3340 {
3341 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3342 if (hr == S_OK)
3343 {
3344 if (!comment)
3346
3347 if (frame_count > 1 && !loop)
3348 loop = get_gif_loopcount(reader);
3349
3350 if (!background)
3351 background = get_gif_background(reader);
3352
3353 if (!palette)
3354 palette = get_gif_palette(decoder, reader);
3355
3356 IWICMetadataReader_Release(reader);
3357 }
3358 }
3359 }
3360 IWICMetadataBlockReader_Release(block_reader);
3361 }
3362
3363 if (frame_count > 1 && !loop)
3364 {
3365 loop = heap_alloc_zero(sizeof(*loop) + sizeof(SHORT));
3366 if (loop)
3367 {
3368 loop->type = PropertyTagTypeShort;
3369 loop->id = PropertyTagLoopCount;
3370 loop->length = sizeof(SHORT);
3371 loop->value = loop + 1;
3372 *(SHORT *)loop->value = 1;
3373 }
3374 }
3375
3376 if (delay) add_property(bitmap, delay);
3378 if (loop) add_property(bitmap, loop);
3380 if (background) add_property(bitmap, background);
3381
3382 heap_free(delay);
3384 heap_free(loop);
3386 heap_free(background);
3387
3388 /* Win7 gdiplus always returns transparent color index from frame 0 */
3389 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
3390 if (hr != S_OK) return;
3391
3392 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3393 if (hr == S_OK)
3394 {
3395 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3396 if (hr == S_OK)
3397 {
3398 for (i = 0; i < block_count; i++)
3399 {
3400 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3401 if (hr == S_OK)
3402 {
3403 if (!transparent_idx)
3404 transparent_idx = get_gif_transparent_idx(reader);
3405
3406 IWICMetadataReader_Release(reader);
3407 }
3408 }
3409 }
3410 IWICMetadataBlockReader_Release(block_reader);
3411 }
3412
3413 if (transparent_idx) add_property(bitmap, transparent_idx);
3414 heap_free(transparent_idx);
3415
3416 IWICBitmapFrameDecode_Release(frame);
3417}
3418
3419static PropertyItem* create_prop(PROPID propid, PROPVARIANT* value)
3420{
3422 UINT item_size = propvariant_size(value);
3423
3424 if (item_size)
3425 {
3426 item_size += sizeof(*item);
3427 item = heap_alloc_zero(item_size);
3428 if (propvariant_to_item(value, item, item_size, propid) != Ok)
3429 {
3430 heap_free(item);
3431 item = NULL;
3432 }
3433 }
3434
3435 return item;
3436}
3437
3439{
3440 PROPVARIANT value;
3441 HRESULT hr;
3442 ULONG result=0;
3443
3444 hr = IWICMetadataReader_GetValueByIndex(reader, index, NULL, NULL, &value);
3445 if (SUCCEEDED(hr))
3446 {
3447 switch (value.vt)
3448 {
3449 case VT_UI4:
3450 result = value.u.ulVal;
3451 break;
3452 default:
3453 ERR("unhandled case %u\n", value.vt);
3454 break;
3455 }
3457 }
3458 return result;
3459}
3460
3461static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT active_frame)
3462{
3463 HRESULT hr;
3464 IWICBitmapFrameDecode *frame;
3465 IWICMetadataBlockReader *block_reader;
3467 UINT block_count, i, j;
3468 struct keyword_info {
3469 const char* name;
3470 PROPID propid;
3471 BOOL seen;
3472 } keywords[] = {
3473 { "Title", PropertyTagImageTitle },
3474 { "Author", PropertyTagArtist },
3475 { "Description", PropertyTagImageDescription },
3476 { "Copyright", PropertyTagCopyright },
3477 { "Software", PropertyTagSoftwareUsed },
3478 { "Source", PropertyTagEquipModel },
3479 { "Comment", PropertyTagExifUserComment },
3480 };
3481 BOOL seen_gamma=FALSE, seen_whitepoint=FALSE, seen_chrm=FALSE;
3482
3483 hr = IWICBitmapDecoder_GetFrame(decoder, active_frame, &frame);
3484 if (hr != S_OK) return;
3485
3486 hr = IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader);
3487 if (hr == S_OK)
3488 {
3489 hr = IWICMetadataBlockReader_GetCount(block_reader, &block_count);
3490 if (hr == S_OK)
3491 {
3492 for (i = 0; i < block_count; i++)
3493 {
3494 hr = IWICMetadataBlockReader_GetReaderByIndex(block_reader, i, &reader);
3495 if (hr == S_OK)
3496 {
3497 GUID format;
3498
3499 hr = IWICMetadataReader_GetMetadataFormat(reader, &format);
3500 if (SUCCEEDED(hr) && IsEqualGUID(&GUID_MetadataFormatChunktEXt, &format))
3501 {
3502 PROPVARIANT name, value;
3504
3505 hr = IWICMetadataReader_GetValueByIndex(reader, 0, NULL, &name, &value);
3506
3507 if (SUCCEEDED(hr))
3508 {
3509 if (name.vt == VT_LPSTR)
3510 {
3511 for (j = 0; j < ARRAY_SIZE(keywords); j++)
3512 if (!strcmp(keywords[j].name, name.u.pszVal))
3513 break;
3514 if (j < ARRAY_SIZE(keywords) && !keywords[j].seen)
3515 {
3516 keywords[j].seen = TRUE;
3517 item = create_prop(keywords[j].propid, &value);
3518 if (item)
3520 heap_free(item);
3521 }
3522 }
3523
3526 }
3527 }
3528 else if (SUCCEEDED(hr) && IsEqualGUID(&GUID_MetadataFormatChunkgAMA, &format))
3529 {
3531
3532 if (!seen_gamma)
3533 {
3534 item = heap_alloc_zero(sizeof(PropertyItem) + sizeof(ULONG) * 2);
3535 if (item)
3536 {
3537 ULONG *rational;
3538 item->length = sizeof(ULONG) * 2;
3540 item->id = PropertyTagGamma;
3541 rational = item->value = item + 1;
3542 rational[0] = 100000;
3543 rational[1] = get_ulong_by_index(reader, 0);
3545 seen_gamma = TRUE;
3546 heap_free(item);
3547 }
3548 }
3549 }
3550 else if (SUCCEEDED(hr) && IsEqualGUID(&GUID_MetadataFormatChunkcHRM, &format))
3551 {
3553
3554 if (!seen_whitepoint)
3555 {
3556 item = GdipAlloc(sizeof(PropertyItem) + sizeof(ULONG) * 4);
3557 if (item)
3558 {
3559 ULONG *rational;
3560 item->length = sizeof(ULONG) * 4;
3563 rational = item->value = item + 1;
3564 rational[0] = get_ulong_by_index(reader, 0);
3565 rational[1] = 100000;
3566 rational[2] = get_ulong_by_index(reader, 1);
3567 rational[3] = 100000;
3569 seen_whitepoint = TRUE;
3570 GdipFree(item);
3571 }
3572 }
3573 if (!seen_chrm)
3574 {
3575 item = GdipAlloc(sizeof(PropertyItem) + sizeof(ULONG) * 12);
3576 if (item)
3577 {
3578 ULONG *rational;
3579 item->length = sizeof(ULONG) * 12;
3582 rational = item->value = item + 1;
3583 rational[0] = get_ulong_by_index(reader, 2);
3584 rational[1] = 100000;
3585 rational[2] = get_ulong_by_index(reader, 3);
3586 rational[3] = 100000;
3587 rational[4] = get_ulong_by_index(reader, 4);
3588 rational[5] = 100000;
3589 rational[6] = get_ulong_by_index(reader, 5);
3590 rational[7] = 100000;
3591 rational[8] = get_ulong_by_index(reader, 6);
3592 rational[9] = 100000;
3593 rational[10] = get_ulong_by_index(reader, 7);
3594 rational[11] = 100000;
3596 seen_chrm = TRUE;
3597 GdipFree(item);
3598 }
3599 }
3600 }
3601
3602 IWICMetadataReader_Release(reader);
3603 }
3604 }
3605 }
3606 IWICMetadataBlockReader_Release(block_reader);
3607 }
3608
3609 IWICBitmapFrameDecode_Release(frame);
3610}
3611
3613{
3615 HRESULT hr;
3616
3617 TRACE("%p,%s\n", stream, wine_dbgstr_guid(container));
3618
3619 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
3620 if (FAILED(hr)) return hresult_to_status(hr);
3621 hr = IWICImagingFactory_CreateDecoder(factory, container, NULL, decoder);
3622 IWICImagingFactory_Release(factory);
3623 if (FAILED(hr)) return hresult_to_status(hr);
3624
3625 hr = IWICBitmapDecoder_Initialize(*decoder, stream, WICDecodeMetadataCacheOnLoad);
3626 if (FAILED(hr)) return hresult_to_status(hr);
3627 return Ok;
3628}
3629
3631
3632static GpStatus decode_frame_wic(IWICBitmapDecoder *decoder, BOOL force_conversion,
3633 UINT active_frame, metadata_reader_func metadata_reader, GpImage **image)
3634{
3637 HRESULT hr;
3638 IWICBitmapFrameDecode *frame;
3640 IWICMetadataBlockReader *block_reader;
3645 int i;
3646 UINT width, height, frame_count;
3647 BitmapData lockeddata;
3648 WICRect wrc;
3649
3650 TRACE("%p,%u,%p\n", decoder, active_frame, image);
3651
3652 IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
3653 hr = IWICBitmapDecoder_GetFrame(decoder, active_frame, &frame);
3654 if (SUCCEEDED(hr)) /* got frame */
3655 {
3656 hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &wic_format);
3657
3658 if (SUCCEEDED(hr))
3659 {
3660 if (!force_conversion)
3661 {
3662 for (i=0; pixel_formats[i].wic_format; i++)
3663 {
3665 {
3666 source = (IWICBitmapSource*)frame;
3667 IWICBitmapSource_AddRef(source);
3668 gdip_format = pixel_formats[i].gdip_format;
3669 palette_type = pixel_formats[i].palette_type;
3670 break;
3671 }
3672 }
3673 }
3674 if (!source)
3675 {
3676 /* unknown format; fall back on 32bppARGB */
3677 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source);
3679 }
3680 TRACE("%s => %#x\n", wine_dbgstr_guid(&wic_format), gdip_format);
3681 }
3682
3683 if (SUCCEEDED(hr)) /* got source */
3684 {
3685 hr = IWICBitmapSource_GetSize(source, &width, &height);
3686
3687 if (SUCCEEDED(hr))
3689 NULL, &bitmap);
3690
3691 if (SUCCEEDED(hr) && status == Ok) /* created bitmap */
3692 {
3694 gdip_format, &lockeddata);
3695 if (status == Ok) /* locked bitmap */
3696 {
3697 wrc.X = 0;
3698 wrc.Width = width;
3699 wrc.Height = 1;
3700 for (i=0; i<height; i++)
3701 {
3702 wrc.Y = i;
3703 hr = IWICBitmapSource_CopyPixels(source, &wrc, abs(lockeddata.Stride),
3704 abs(lockeddata.Stride), (BYTE*)lockeddata.Scan0+lockeddata.Stride*i);
3705 if (FAILED(hr)) break;
3706 }
3707
3708 GdipBitmapUnlockBits(bitmap, &lockeddata);
3709 }
3710
3711 if (SUCCEEDED(hr) && status == Ok)
3712 *image = &bitmap->image;
3713 else
3714 {
3715 *image = NULL;
3716 GdipDisposeImage(&bitmap->image);
3717 }
3718
3719 if (SUCCEEDED(hr) && status == Ok)
3720 {
3721 double dpix, dpiy;
3722 hr = IWICBitmapSource_GetResolution(source, &dpix, &dpiy);
3723 if (SUCCEEDED(hr))
3724 {
3725 bitmap->image.xres = dpix;
3726 bitmap->image.yres = dpiy;
3727 }
3728 hr = S_OK;
3729 }
3730 }
3731
3732 IWICBitmapSource_Release(source);
3733 }
3734
3735 if (SUCCEEDED(hr)) {
3736 bitmap->metadata_reader = NULL;
3737
3738 if (metadata_reader)
3739 metadata_reader(bitmap, decoder, active_frame);
3740 else if (IWICBitmapFrameDecode_QueryInterface(frame, &IID_IWICMetadataBlockReader, (void **)&block_reader) == S_OK)
3741 {
3742 UINT block_count = 0;
3743 if (IWICMetadataBlockReader_GetCount(block_reader, &block_count) == S_OK && block_count)
3744 IWICMetadataBlockReader_GetReaderByIndex(block_reader, 0, &bitmap->metadata_reader);
3745 IWICMetadataBlockReader_Release(block_reader);
3746 }
3747
3749 IWICBitmapFrameDecode_Release(frame);
3750 }
3751 }
3752
3753 if (FAILED(hr) && status == Ok) status = hresult_to_status(hr);
3754
3755 if (status == Ok)
3756 {
3757 /* Native GDI+ used to be smarter, but since Win7 it just sets these flags. */
3759 if (IsEqualGUID(&wic_format, &GUID_WICPixelFormat2bppGray) ||
3760 IsEqualGUID(&wic_format, &GUID_WICPixelFormat4bppGray) ||
3761 IsEqualGUID(&wic_format, &GUID_WICPixelFormat8bppGray) ||
3762 IsEqualGUID(&wic_format, &GUID_WICPixelFormat16bppGray))
3763 bitmap->image.flags |= ImageFlagsColorSpaceGRAY;
3764 else
3765 bitmap->image.flags |= ImageFlagsColorSpaceRGB;
3766 bitmap->image.frame_count = frame_count;
3767 bitmap->image.current_frame = active_frame;
3768 bitmap->image.decoder = decoder;
3769 IWICBitmapDecoder_AddRef(decoder);
3770 if (palette)
3771 {
3772 heap_free(bitmap->image.palette);
3773 bitmap->image.palette = palette;
3774 }
3775 else
3776 {
3777 if (IsEqualGUID(&wic_format, &GUID_WICPixelFormatBlackWhite))
3778 bitmap->image.palette->Flags = 0;
3779 }
3780 TRACE("=> %p\n", *image);
3781 }
3782
3783 return status;
3784}
3785
3787 metadata_reader_func metadata_reader, GpImage **image)
3788{
3789 IWICBitmapDecoder *decoder;
3791
3793 if(status != Ok)
3794 return status;
3795
3796 status = decode_frame_wic(decoder, FALSE, 0, metadata_reader, image);
3797 IWICBitmapDecoder_Release(decoder);
3798 return status;
3799}
3800
3802{
3803 GpImage *new_image;
3805
3806 status = decode_frame_wic(image->decoder, FALSE, active_frame, NULL, &new_image);
3807 if(status != Ok)
3808 return status;
3809
3810 new_image->busy = image->busy;
3811 memcpy(&new_image->format, &image->format, sizeof(GUID));
3813 if (image->type == ImageTypeBitmap)
3814 *(GpBitmap *)image = *(GpBitmap *)new_image;
3815 else if (image->type == ImageTypeMetafile)
3816 *(GpMetafile *)image = *(GpMetafile *)new_image;
3817 new_image->type = ~0;
3818 heap_free(new_image);
3819 return Ok;
3820}
3821
3824{
3825 static const WCHAR leftW[] = {'L','e','f','t',0};
3826 static const WCHAR topW[] = {'T','o','p',0};
3827
3828 *left = get_gif_frame_property(frame, &GUID_MetadataFormatIMD, leftW);
3829 *top = get_gif_frame_property(frame, &GUID_MetadataFormatIMD, topW);
3830
3831 return IWICBitmapFrameDecode_GetSize(frame, width, height);
3832}
3833
3835{
3836 UINT i, j, left, top, width, height;
3838 BYTE *new_bits;
3839 HRESULT hr;
3840
3841 hr = get_gif_frame_rect(frame, &left, &top, &width, &height);
3842 if(FAILED(hr))
3843 return hr;
3844
3845 hr = WICConvertBitmapSource(&GUID_WICPixelFormat32bppBGRA, (IWICBitmapSource*)frame, &source);
3846 if(FAILED(hr))
3847 return hr;
3848
3849 new_bits = heap_alloc_zero(width*height*4);
3850 if(!new_bits)
3851 return E_OUTOFMEMORY;
3852
3853 hr = IWICBitmapSource_CopyPixels(source, NULL, width*4, width*height*4, new_bits);
3854 IWICBitmapSource_Release(source);
3855 if(FAILED(hr)) {
3856 heap_free(new_bits);
3857 return hr;
3858 }
3859
3860 for(i=0; i<height && i+top<bitmap->height; i++) {
3861 for(j=0; j<width && j+left<bitmap->width; j++) {
3862 DWORD *src = (DWORD*)(new_bits+i*width*4+j*4);
3863 DWORD *dst = (DWORD*)(bitmap->bits+(i+top)*bitmap->stride+(j+left)*4);
3864
3865 if(first_frame || *src>>24 != 0)
3866 *dst = *src;
3867 }
3868 }
3869 heap_free(new_bits);
3870 return hr;
3871}
3872
3874{
3875 BYTE bgcolor_idx = 0;
3876 UINT i;
3877
3878 for(i=0; i<bitmap->prop_count; i++) {
3879 if(bitmap->prop_item[i].id == PropertyTagIndexBackground) {
3880 bgcolor_idx = *(BYTE*)bitmap->prop_item[i].value;
3881 break;
3882 }
3883 }
3884
3885 for(i=0; i<bitmap->prop_count; i++) {
3886 if(bitmap->prop_item[i].id == PropertyTagIndexTransparent) {
3887 BYTE transparent_idx;
3888 transparent_idx = *(BYTE*)bitmap->prop_item[i].value;
3889
3890 if(transparent_idx == bgcolor_idx)
3891 return 0;
3892 }
3893 }
3894
3895 for(i=0; i<bitmap->prop_count; i++) {
3896 if(bitmap->prop_item[i].id == PropertyTagGlobalPalette) {
3897 if(bitmap->prop_item[i].length/3 > bgcolor_idx) {
3898 BYTE *color = ((BYTE*)bitmap->prop_item[i].value)+bgcolor_idx*3;
3899 return color[2] + (color[1]<<8) + (color[0]<<16) + (0xffu<<24);
3900 }
3901 break;
3902 }
3903 }
3904
3905 FIXME("can't get gif background color\n");
3906 return 0xffffffff;
3907}
3908
3910{
3911 static const WCHAR disposalW[] = {'D','i','s','p','o','s','a','l',0};
3912
3914 IWICBitmapFrameDecode *frame;
3915 int cur_frame=0, disposal;
3916 BOOL bgcolor_set = FALSE;
3917 DWORD bgcolor = 0;
3918 HRESULT hr;
3919
3920 if(active_frame > image->current_frame) {
3921 hr = IWICBitmapDecoder_GetFrame(bitmap->image.decoder, image->current_frame, &frame);
3922 if(FAILED(hr))
3923 return hresult_to_status(hr);
3924 disposal = get_gif_frame_property(frame, &GUID_MetadataFormatGCE, disposalW);
3925 IWICBitmapFrameDecode_Release(frame);
3926
3927 if(disposal == GIF_DISPOSE_RESTORE_TO_BKGND)
3928 cur_frame = image->current_frame;
3929 else if(disposal != GIF_DISPOSE_RESTORE_TO_PREV)
3930 cur_frame = image->current_frame+1;
3931 }
3932
3933 while(cur_frame != active_frame) {
3934 hr = IWICBitmapDecoder_GetFrame(bitmap->image.decoder, cur_frame, &frame);
3935 if(FAILED(hr))
3936 return hresult_to_status(hr);
3937 disposal = get_gif_frame_property(frame, &GUID_MetadataFormatGCE, disposalW);
3938
3939 if(disposal==GIF_DISPOSE_UNSPECIFIED || disposal==GIF_DISPOSE_DO_NOT_DISPOSE) {
3940 hr = blit_gif_frame(bitmap, frame, cur_frame==0);
3941 if(FAILED(hr))
3942 return hresult_to_status(hr);
3943 }else if(disposal == GIF_DISPOSE_RESTORE_TO_BKGND) {
3944 UINT left, top, width, height, i, j;
3945
3946 if(!bgcolor_set) {
3948 bgcolor_set = TRUE;
3949 }
3950
3951 hr = get_gif_frame_rect(frame, &left, &top, &width, &height);
3952 if(FAILED(hr))
3953 return hresult_to_status(hr);
3954 for(i=top; i<top+height && i<bitmap->height; i++) {
3955 DWORD *bits = (DWORD*)(bitmap->bits+i*bitmap->stride);
3956 for(j=left; j<left+width && j<bitmap->width; j++)
3957 bits[j] = bgcolor;
3958 }
3959 }
3960
3961 IWICBitmapFrameDecode_Release(frame);
3962 cur_frame++;
3963 }
3964
3965 hr = IWICBitmapDecoder_GetFrame(bitmap->image.decoder, active_frame, &frame);
3966 if(FAILED(hr))
3967 return hresult_to_status(hr);
3968
3969 hr = blit_gif_frame(bitmap, frame, cur_frame==0);
3970 IWICBitmapFrameDecode_Release(frame);
3971 if(FAILED(hr))
3972 return hresult_to_status(hr);
3973
3974 image->current_frame = active_frame;
3975 return Ok;
3976}
3977
3979{
3980 return decode_image_wic(stream, &GUID_ContainerFormatIco, NULL, image);
3981}
3982
3984{
3987
3988 status = decode_image_wic(stream, &GUID_ContainerFormatBmp, NULL, image);
3989
3990 bitmap = (GpBitmap*)*image;
3991
3992 if (status == Ok && bitmap->format == PixelFormat32bppARGB)
3993 {
3994 /* WIC supports bmp files with alpha, but gdiplus does not */
3995 bitmap->format = PixelFormat32bppRGB;
3996 }
3997
3998 return status;
3999}
4000
4002{
4003 return decode_image_wic(stream, &GUID_ContainerFormatJpeg, NULL, image);
4004}
4005
4007{
4009 BOOL has_tRNS = FALSE;
4010 HRESULT hr;
4011 BYTE header[8];
4012
4013 seek.QuadPart = 8;
4014 do
4015 {
4016 ULARGE_INTEGER chunk_start;
4017 ULONG bytesread, chunk_size;
4018
4019 hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, &chunk_start);
4020 if (FAILED(hr)) break;
4021
4022 hr = IStream_Read(pIStream, header, 8, &bytesread);
4023 if (FAILED(hr) || bytesread < 8) break;
4024
4025 chunk_size = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
4026 if (!memcmp(&header[4], "tRNS", 4))
4027 {
4028 has_tRNS = TRUE;
4029 break;
4030 }
4031
4032 seek.QuadPart = chunk_start.QuadPart + chunk_size + 12; /* skip data and CRC */
4033 } while (memcmp(&header[4], "IDAT", 4) && memcmp(&header[4], "IEND", 4));
4034
4035 TRACE("has_tRNS = %d\n", has_tRNS);
4036 return has_tRNS;
4037}
4038
4040{
4041 IWICBitmapDecoder *decoder;
4042 IWICBitmapFrameDecode *frame;
4044 HRESULT hr;
4045 GUID format;
4046 BOOL force_conversion = FALSE;
4047
4048 status = initialize_decoder_wic(stream, &GUID_ContainerFormatPng, &decoder);
4049 if (status != Ok)
4050 return status;
4051
4052 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
4053 if (hr == S_OK)
4054 {
4055 hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
4056 if (hr == S_OK)
4057 {
4058 if (IsEqualGUID(&format, &GUID_WICPixelFormat8bppGray))
4059 force_conversion = TRUE;
4060 else if ((IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed) ||
4061 IsEqualGUID(&format, &GUID_WICPixelFormat4bppIndexed) ||
4062 IsEqualGUID(&format, &GUID_WICPixelFormat2bppIndexed) ||
4063 IsEqualGUID(&format, &GUID_WICPixelFormat1bppIndexed) ||
4064 IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR)) &&
4066 force_conversion = TRUE;
4067
4068 status = decode_frame_wic(decoder, force_conversion, 0, png_metadata_reader, image);
4069 }
4070 else
4072
4073 IWICBitmapFrameDecode_Release(frame);
4074 }
4075 else
4077
4078 IWICBitmapDecoder_Release(decoder);
4079 return status;
4080}
4081
4083{
4084 IWICBitmapDecoder *decoder;
4085 UINT frame_count;
4087 HRESULT hr;
4088
4089 status = initialize_decoder_wic(stream, &GUID_ContainerFormatGif, &decoder);
4090 if(status != Ok)
4091 return status;
4092
4093 hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
4094 if(FAILED(hr))
4095 return hresult_to_status(hr);
4096
4097 status = decode_frame_wic(decoder, frame_count > 1, 0, gif_metadata_reader, image);
4098 IWICBitmapDecoder_Release(decoder);
4099 if(status != Ok)
4100 return status;
4101
4102 if(frame_count > 1) {
4103 heap_free((*image)->palette);
4104 (*image)->palette = NULL;
4105 }
4106 return Ok;
4107}
4108
4110{
4111 return decode_image_wic(stream, &GUID_ContainerFormatTiff, NULL, image);
4112}
4113
4115{
4117 BOOL is_placeable = FALSE;
4120 METAHEADER mh;
4121 HMETAFILE hmf;
4122 HRESULT hr;
4123 UINT size;
4124 void *buf;
4125
4126 hr = IStream_Read(stream, &mh, sizeof(mh), &size);
4127 if (hr != S_OK || size != sizeof(mh))
4128 return GenericError;
4129
4131 {
4132 seek.QuadPart = 0;
4133 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4134 if (FAILED(hr)) return hresult_to_status(hr);
4135
4136 hr = IStream_Read(stream, &pfh, sizeof(pfh), &size);
4137 if (hr != S_OK || size != sizeof(pfh))
4138 return GenericError;
4139
4140 hr = IStream_Read(stream, &mh, sizeof(mh), &size);
4141 if (hr != S_OK || size != sizeof(mh))
4142 return GenericError;
4143
4144 is_placeable = TRUE;
4145 }
4146
4147 seek.QuadPart = is_placeable ? sizeof(pfh) : 0;
4148 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4149 if (FAILED(hr)) return hresult_to_status(hr);
4150
4151 buf = heap_alloc(mh.mtSize * 2);
4152 if (!buf) return OutOfMemory;
4153
4154 hr = IStream_Read(stream, buf, mh.mtSize * 2, &size);
4155 if (hr != S_OK || size != mh.mtSize * 2)
4156 {
4157 heap_free(buf);
4158 return GenericError;
4159 }
4160
4161 hmf = SetMetaFileBitsEx(mh.mtSize * 2, buf);
4162 heap_free(buf);
4163 if (!hmf)
4164 return GenericError;
4165
4166 status = GdipCreateMetafileFromWmf(hmf, TRUE, is_placeable ? &pfh : NULL, metafile);
4167 if (status != Ok)
4168 DeleteMetaFile(hmf);
4169 return status;
4170}
4171
4173{
4176
4177 TRACE("%p %p\n", stream, image);
4178
4179 if (!stream || !image)
4180 return InvalidParameter;
4181
4183 if (status != Ok)
4184 {
4185 TRACE("Could not load metafile\n");
4186 return status;
4187 }
4188
4189 *image = (GpImage *)metafile;
4190 TRACE("<-- %p\n", *image);
4191
4192 return Ok;
4193}
4194
4196{
4198 ENHMETAHEADER emh;
4199 HENHMETAFILE hemf;
4201 HRESULT hr;
4202 UINT size;
4203 void *buf;
4204
4205 hr = IStream_Read(stream, &emh, sizeof(emh), &size);
4206 if (hr != S_OK || size != sizeof(emh) || emh.dSignature != ENHMETA_SIGNATURE)
4207 return GenericError;
4208
4209 seek.QuadPart = 0;
4210 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4211 if (FAILED(hr)) return hresult_to_status(hr);
4212
4213 buf = heap_alloc(emh.nBytes);
4214 if (!buf) return OutOfMemory;
4215
4216 hr = IStream_Read(stream, buf, emh.nBytes, &size);
4217 if (hr != S_OK || size != emh.nBytes)
4218 {
4219 heap_free(buf);
4220 return GenericError;
4221 }
4222
4223 hemf = SetEnhMetaFileBits(emh.nBytes, buf);
4224 heap_free(buf);
4225 if (!hemf)
4226 return GenericError;
4227
4229 if (status != Ok)
4230 DeleteEnhMetaFile(hemf);
4231 return status;
4232}
4233
4235{
4238
4239 TRACE("%p %p\n", stream, image);
4240
4241 if (!stream || !image)
4242 return InvalidParameter;
4243
4245 if (status != Ok)
4246 {
4247 TRACE("Could not load metafile\n");
4248 return status;
4249 }
4250
4251 *image = (GpImage *)metafile;
4252 TRACE("<-- %p\n", *image);
4253
4254 return Ok;
4255}
4256
4259
4261
4262typedef GpStatus (*select_image_func)(GpImage *image, UINT active_frame);
4263
4264typedef struct image_codec {
4270
4271typedef enum {
4282
4283static const struct image_codec codecs[NUM_CODECS];
4284
4286{
4287 BYTE signature[8];
4288 const BYTE *pattern, *mask;
4290 HRESULT hr;
4291 UINT bytesread;
4292 int i;
4293 DWORD j, sig;
4294
4295 /* seek to the start of the stream */
4296 seek.QuadPart = 0;
4297 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4298 if (FAILED(hr)) return hresult_to_status(hr);
4299
4300 /* read the first 8 bytes */
4301 /* FIXME: This assumes all codecs have signatures <= 8 bytes in length */
4302 hr = IStream_Read(stream, signature, 8, &bytesread);
4303 if (FAILED(hr)) return hresult_to_status(hr);
4304 if (hr == S_FALSE || bytesread == 0) return GenericError;
4305
4306 for (i = 0; i < NUM_CODECS; i++) {
4307 if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) &&
4308 bytesread >= codecs[i].info.SigSize)
4309 {
4310 for (sig=0; sig<codecs[i].info.SigCount; sig++)
4311 {
4312 pattern = &codecs[i].info.SigPattern[codecs[i].info.SigSize*sig];
4313 mask = &codecs[i].info.SigMask[codecs[i].info.SigSize*sig];
4314 for (j=0; j<codecs[i].info.SigSize; j++)
4315 if ((signature[j] & mask[j]) != pattern[j])
4316 break;
4317 if (j == codecs[i].info.SigSize)
4318 {
4319 *result = &codecs[i];
4320 return Ok;
4321 }
4322 }
4323 }
4324 }
4325
4326 TRACE("no match for %i byte signature %x %x %x %x %x %x %x %x\n", bytesread,
4327 signature[0],signature[1],signature[2],signature[3],
4328 signature[4],signature[5],signature[6],signature[7]);
4329
4330 return GenericError;
4331}
4332
4334{
4335 int i;
4336
4337 for (i = 0; i < NUM_CODECS; i++) {
4338 if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) &&
4339 IsEqualIID(&codecs[i].info.FormatID, &image->format))
4340 {
4341 *result = &codecs[i];
4342 return Ok;
4343 }
4344 }
4345
4346 TRACE("no match for format: %s\n", wine_dbgstr_guid(&image->format));
4347 return GenericError;
4348}
4349
4351 UINT frame)
4352{
4353 GpStatus stat;
4354 const struct image_codec *codec = NULL;
4355 BOOL unlock;
4356
4357 TRACE("(%p,%s,%u)\n", image, debugstr_guid(dimensionID), frame);
4358
4359 if (!image || !dimensionID)
4360 return InvalidParameter;
4361 if(!image_lock(image, &unlock))
4362 return ObjectBusy;
4363
4364 if (frame >= image->frame_count)
4365 {
4366 WARN("requested frame %u, but image has only %u\n", frame, image->frame_count);
4367 image_unlock(image, unlock);
4368 return InvalidParameter;
4369 }
4370
4371 if (image->type != ImageTypeBitmap && image->type != ImageTypeMetafile)
4372 {
4373 WARN("invalid image type %d\n", image->type);
4374 image_unlock(image, unlock);
4375 return InvalidParameter;
4376 }
4377
4378 if (image->current_frame == frame)
4379 {
4380 image_unlock(image, unlock);
4381 return Ok;
4382 }
4383
4384 if (!image->decoder)
4385 {
4386 TRACE("image doesn't have an associated decoder\n");
4387 image_unlock(image, unlock);
4388 return Ok;
4389 }
4390
4391 /* choose an appropriate image decoder */
4393 if (stat != Ok)
4394 {
4395 WARN("can't find decoder info\n");
4396 image_unlock(image, unlock);
4397 return stat;
4398 }
4399
4400 stat = codec->select_func(image, frame);
4401 image_unlock(image, unlock);
4402 return stat;
4403}
4404
4406{
4407 GpStatus stat;
4409 HRESULT hr;
4410 const struct image_codec *codec=NULL;
4411
4412 TRACE("%p %p\n", stream, image);
4413
4414 if (!stream || !image)
4415 return InvalidParameter;
4416
4417 /* choose an appropriate image decoder */
4418 stat = get_decoder_info(stream, &codec);
4419 if (stat != Ok) return stat;
4420
4421 /* seek to the start of the stream */
4422 seek.QuadPart = 0;
4423 hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
4424 if (FAILED(hr)) return hresult_to_status(hr);
4425
4426 /* call on the image decoder to do the real work */
4427 stat = codec->decode_func(stream, image);
4428
4429 /* take note of the original data format */
4430 if (stat == Ok)
4431 {
4432 memcpy(&(*image)->format, &codec->info.FormatID, sizeof(GUID));
4433 return Ok;
4434 }
4435
4436 return stat;
4437}
4438
4439/* FIXME: no ICM */
4441{
4442 TRACE("%p %p\n", stream, image);
4443
4445}
4446
4448{
4449 static int calls;
4450
4451 TRACE("(%p,%u)\n", image, propId);
4452
4453 if(!image)
4454 return InvalidParameter;
4455
4456 if(!(calls++))
4457 FIXME("not implemented\n");
4458
4459 return NotImplemented;
4460}
4461
4463{
4464 static int calls;
4465
4466 if (!image || !item) return InvalidParameter;
4467
4468 TRACE("(%p,%p:%#x,%u,%u,%p)\n", image, item, item->id, item->type, item->length, item->value);
4469
4470 if(!(calls++))
4471 FIXME("not implemented\n");
4472
4473 return Ok;
4474}
4475
4477 GDIPCONST CLSID *clsidEncoder,
4478 GDIPCONST EncoderParameters *encoderParams)
4479{
4480 GpStatus stat;
4481 IStream *stream;
4482
4483 TRACE("%p (%s) %p %p\n", image, debugstr_w(filename), clsidEncoder, encoderParams);
4484
4485 if (!image || !filename|| !clsidEncoder)
4486 return InvalidParameter;
4487
4489 if (stat != Ok)
4490 return GenericError;
4491
4492 stat = GdipSaveImageToStream(image, stream, clsidEncoder, encoderParams);
4493
4494 IStream_Release(stream);
4495 return stat;
4496}
4497
4498/*************************************************************************
4499 * Encoding functions -
4500 * These functions encode an image in different image file formats.
4501 */
4502
4505{
4506 GpStatus stat;
4509 IWICBitmapEncoder *encoder;
4510 IWICBitmapFrameEncode *frameencode;
4511 IPropertyBag2 *encoderoptions;
4512 HRESULT hr;
4513 UINT width, height;
4514 PixelFormat gdipformat=0;
4515 const WICPixelFormatGUID *desired_wicformat;
4516 WICPixelFormatGUID wicformat;
4517 GpRect rc;
4518 BitmapData lockeddata;
4519 UINT i;
4520
4521 if (image->type != ImageTypeBitmap)
4522 return GenericError;
4523
4524 bitmap = (GpBitmap*)image;
4525
4528
4529 rc.X = 0;
4530 rc.Y = 0;
4531 rc.Width = width;
4532 rc.Height = height;
4533
4534 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
4535 if (FAILED(hr))
4536 return hresult_to_status(hr);
4537 hr = IWICImagingFactory_CreateEncoder(factory, container, NULL, &encoder);
4538 IWICImagingFactory_Release(factory);
4539 if (FAILED(hr))
4540 return hresult_to_status(hr);
4541
4542 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
4543
4544 if (SUCCEEDED(hr))
4545 {
4546 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &encoderoptions);
4547 }
4548
4549 if (SUCCEEDED(hr)) /* created frame */
4550 {
4551 hr = IWICBitmapFrameEncode_Initialize(frameencode, encoderoptions);
4552
4553 if (SUCCEEDED(hr))
4554 hr = IWICBitmapFrameEncode_SetSize(frameencode, width, height);
4555
4556 if (SUCCEEDED(hr))
4557 hr = IWICBitmapFrameEncode_SetResolution(frameencode, image->xres, image->yres);
4558
4559 if (SUCCEEDED(hr))
4560 {
4561 for (i=0; pixel_formats[i].wic_format; i++)
4562 {
4563 if (pixel_formats[i].gdip_format == bitmap->format)
4564 {
4565 desired_wicformat = pixel_formats[i].wic_format;
4566 gdipformat = bitmap->format;
4567 break;
4568 }
4569 }
4570 if (!gdipformat)
4571 {
4572 desired_wicformat = &GUID_WICPixelFormat32bppBGRA;
4573 gdipformat = PixelFormat32bppARGB;
4574 }
4575
4576 memcpy(&wicformat, desired_wicformat, sizeof(GUID));
4577 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &wicformat);
4578 }
4579
4580 if (SUCCEEDED(hr) && !IsEqualGUID(desired_wicformat, &wicformat))
4581 {
4582 /* Encoder doesn't support this bitmap's format. */
4583 gdipformat = 0;
4584 for (i=0; pixel_formats[i].wic_format; i++)
4585 {
4586 if (IsEqualGUID(&wicformat, pixel_formats[i].wic_format))
4587 {
4588 gdipformat = pixel_formats[i].gdip_format;
4589 break;
4590 }
4591 }
4592 if (!gdipformat)
4593 {
4594 ERR("Cannot support encoder format %s\n", debugstr_guid(&wicformat));
4595 hr = E_FAIL;
4596 }
4597 }
4598
4599 if (SUCCEEDED(hr))
4600 {
4601 stat = GdipBitmapLockBits(bitmap, &rc, ImageLockModeRead, gdipformat,
4602 &lockeddata);
4603
4604 if (stat == Ok)
4605 {
4606 UINT row_size = (lockeddata.Width * PIXELFORMATBPP(gdipformat) + 7)/8;
4607 BYTE *row;
4608
4609 /* write one row at a time in case stride is negative */
4610 row = lockeddata.Scan0;
4611 for (i=0; i<lockeddata.Height; i++)
4612 {
4613 hr = IWICBitmapFrameEncode_WritePixels(frameencode, 1, row_size, row_size, row);
4614 if (FAILED(hr)) break;
4615 row += lockeddata.Stride;
4616 }
4617
4618 GdipBitmapUnlockBits(bitmap, &lockeddata);
4619 }
4620 else
4621 hr = E_FAIL;
4622 }
4623
4624 if (SUCCEEDED(hr))
4625 hr = IWICBitmapFrameEncode_Commit(frameencode);
4626
4627 IWICBitmapFrameEncode_Release(frameencode);
4628 IPropertyBag2_Release(encoderoptions);
4629 }
4630
4631 if (SUCCEEDED(hr))
4632 hr = IWICBitmapEncoder_Commit(encoder);
4633
4634 IWICBitmapEncoder_Release(encoder);
4635 return hresult_to_status(hr);
4636}
4637
4640{
4641 return encode_image_wic(image, stream, &GUID_ContainerFormatBmp, params);
4642}
4643
4646{
4647 return encode_image_wic(image, stream, &GUID_ContainerFormatTiff, params);
4648}
4649
4652{
4653 return encode_image_wic(image, stream, &GUID_ContainerFormatPng, params);
4654}
4655
4658{
4659 return encode_image_wic(image, stream, &GUID_ContainerFormatJpeg, params);
4660}
4661
4664{
4665 return encode_image_wic(image, stream, &GUID_ContainerFormatGif, params);
4666}
4667
4668/*****************************************************************************
4669 * GdipSaveImageToStream [GDIPLUS.@]
4670 */
4673{
4674 GpStatus stat;
4675 encode_image_func encode_image;
4676 int i;
4677
4678 TRACE("%p, %p, %s, %p\n", image, stream, wine_dbgstr_guid(clsid), params);
4679
4680 if(!image || !stream)
4681 return InvalidParameter;
4682
4683 /* select correct encoder */
4684 encode_image = NULL;
4685 for (i = 0; i < NUM_CODECS; i++) {
4686 if ((codecs[i].info.Flags & ImageCodecFlagsEncoder) &&
4687 IsEqualCLSID(clsid, &codecs[i].info.Clsid))
4688 encode_image = codecs[i].encode_func;
4689 }
4690 if (encode_image == NULL)
4691 return UnknownImageFormat;
4692
4693 stat = encode_image(image, stream, params);
4694
4695 return stat;
4696}
4697
4698/*****************************************************************************
4699 * GdipSaveAdd [GDIPLUS.@]
4700 */
4702{
4703 FIXME("(%p,%p): stub\n", image, params);
4704 return Ok;
4705}
4706
4707/*****************************************************************************
4708 * GdipGetImagePalette [GDIPLUS.@]
4709 */
4711{
4712 INT count;
4713
4714 TRACE("(%p,%p,%i)\n", image, palette, size);
4715
4716 if (!image || !palette)
4717 return InvalidParameter;
4718
4719 count = image->palette ? image->palette->Count : 0;
4720
4721 if (size < (sizeof(UINT)*2+sizeof(ARGB)*count))
4722 {
4723 TRACE("<-- InsufficientBuffer\n");
4724 return InsufficientBuffer;
4725 }
4726
4727 if (image->palette)
4728 {
4729 palette->Flags = image->palette->Flags;
4730 palette->Count = image->palette->Count;
4731 memcpy(palette->Entries, image->palette->Entries, sizeof(ARGB)*image->palette->Count);
4732 }
4733 else
4734 {
4735 palette->Flags = 0;
4736 palette->Count = 0;
4737 }
4738 return Ok;
4739}
4740
4741/*****************************************************************************
4742 * GdipSetImagePalette [GDIPLUS.@]
4743 */
4746{
4747 ColorPalette *new_palette;
4748
4749 TRACE("(%p,%p)\n", image, palette);
4750
4751 if(!image || !palette || palette->Count > 256)
4752 return InvalidParameter;
4753
4754 new_palette = heap_alloc_zero(2 * sizeof(UINT) + palette->Count * sizeof(ARGB));
4755 if (!new_palette) return OutOfMemory;
4756
4757 heap_free(image->palette);
4758 image->palette = new_palette;
4759 image->palette->Flags = palette->Flags;
4760 image->palette->Count = palette->Count;
4761 memcpy(image->palette->Entries, palette->Entries, sizeof(ARGB)*palette->Count);
4762
4763 return Ok;
4764}
4765
4766/*************************************************************************
4767 * Encoders -
4768 * Structures that represent which formats we support for encoding.
4769 */
4770
4771/* ImageCodecInfo creation routines taken from libgdiplus */
4772static const WCHAR bmp_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'B', 'M', 'P', 0}; /* Built-in BMP */
4773static const WCHAR bmp_extension[] = {'*','.','B', 'M', 'P',';', '*','.', 'D','I', 'B',';', '*','.', 'R', 'L', 'E',0}; /* *.BMP;*.DIB;*.RLE */
4774static const WCHAR bmp_mimetype[] = {'i', 'm', 'a','g', 'e', '/', 'b', 'm', 'p', 0}; /* image/bmp */
4775static const WCHAR bmp_format[] = {'B', 'M', 'P', 0}; /* BMP */
4776static const BYTE bmp_sig_pattern[] = { 0x42, 0x4D };
4777static const BYTE bmp_sig_mask[] = { 0xFF, 0xFF };
4778
4779static const WCHAR jpeg_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'J','P','E','G', 0};
4780static const WCHAR jpeg_extension[] = {'*','.','J','P','G',';', '*','.','J','P','E','G',';', '*','.','J','P','E',';', '*','.','J','F','I','F',0};
4781static const WCHAR jpeg_mimetype[] = {'i','m','a','g','e','/','j','p','e','g', 0};
4782static const WCHAR jpeg_format[] = {'J','P','E','G',0};
4783static const BYTE jpeg_sig_pattern[] = { 0xFF, 0xD8 };
4784static const BYTE jpeg_sig_mask[] = { 0xFF, 0xFF };
4785
4786static const WCHAR gif_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'G','I','F', 0};
4787static const WCHAR gif_extension[] = {'*','.','G','I','F',0};
4788static const WCHAR gif_mimetype[] = {'i','m','a','g','e','/','g','i','f', 0};
4789static const WCHAR gif_format[] = {'G','I','F',0};
4790static const BYTE gif_sig_pattern[12] = "GIF87aGIF89a";
4791static const BYTE gif_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
4792
4793static const WCHAR tiff_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'T','I','F','F', 0};
4794static const WCHAR tiff_extension[] = {'*','.','T','I','F','F',';','*','.','T','I','F',0};
4795static const WCHAR tiff_mimetype[] = {'i','m','a','g','e','/','t','i','f','f', 0};
4796static const WCHAR tiff_format[] = {'T','I','F','F',0};
4797static const BYTE tiff_sig_pattern[] = {0x49,0x49,42,0,0x4d,0x4d,0,42};
4798static const BYTE tiff_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
4799
4800static const WCHAR emf_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'E','M','F', 0};
4801static const WCHAR emf_extension[] = {'*','.','E','M','F',0};
4802static const WCHAR emf_mimetype[] = {'i','m','a','g','e','/','x','-','e','m','f', 0};
4803static const WCHAR emf_format[] = {'E','M','F',0};
4804static const BYTE emf_sig_pattern[] = { 0x01, 0x00, 0x00, 0x00 };
4805static const BYTE emf_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF };
4806
4807static const WCHAR wmf_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'W','M','F', 0};
4808static const WCHAR wmf_extension[] = {'*','.','W','M','F',0};
4809static const WCHAR wmf_mimetype[] = {'i','m','a','g','e','/','x','-','w','m','f', 0};
4810static const WCHAR wmf_format[] = {'W','M','F',0};
4811static const BYTE wmf_sig_pattern[] = { 0xd7, 0xcd };
4812static const BYTE wmf_sig_mask[] = { 0xFF, 0xFF };
4813
4814static const WCHAR png_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'P','N','G', 0};
4815static const WCHAR png_extension[] = {'*','.','P','N','G',0};
4816static const WCHAR png_mimetype[] = {'i','m','a','g','e','/','p','n','g', 0};
4817static const WCHAR png_format[] = {'P','N','G',0};
4818static const BYTE png_sig_pattern[] = { 137, 80, 78, 71, 13, 10, 26, 10, };
4819static const BYTE png_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
4820
4821static const WCHAR ico_codecname[] = {'B', 'u', 'i','l', 't', '-','i', 'n', ' ', 'I','C','O', 0};
4822static const WCHAR ico_extension[] = {'*','.','I','C','O',0};
4823static const WCHAR ico_mimetype[] = {'i','m','a','g','e','/','x','-','i','c','o','n', 0};
4824static const WCHAR ico_format[] = {'I','C','O',0};
4825static const BYTE ico_sig_pattern[] = { 0x00, 0x00, 0x01, 0x00 };
4826static const BYTE ico_sig_mask[] = { 0xFF, 0xFF, 0xFF, 0xFF };
4827
4828static const struct image_codec codecs[NUM_CODECS] = {
4829 {
4830 { /* BMP */
4831 /* Clsid */ { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4832 /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4833 /* CodecName */ bmp_codecname,
4834 /* DllName */ NULL,
4835 /* FormatDescription */ bmp_format,
4836 /* FilenameExtension */ bmp_extension,
4837 /* MimeType */ bmp_mimetype,
4839 /* Version */ 1,
4840 /* SigCount */ 1,
4841 /* SigSize */ 2,
4842 /* SigPattern */ bmp_sig_pattern,
4843 /* SigMask */ bmp_sig_mask,
4844 },
4848 },
4849 {
4850 { /* JPEG */
4851 /* Clsid */ { 0x557cf401, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4852 /* FormatID */ { 0xb96b3caeU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4853 /* CodecName */ jpeg_codecname,
4854 /* DllName */ NULL,
4855 /* FormatDescription */ jpeg_format,
4856 /* FilenameExtension */ jpeg_extension,
4857 /* MimeType */ jpeg_mimetype,
4859 /* Version */ 1,
4860 /* SigCount */ 1,
4861 /* SigSize */ 2,
4862 /* SigPattern */ jpeg_sig_pattern,
4863 /* SigMask */ jpeg_sig_mask,
4864 },
4868 },
4869 {
4870 { /* GIF */
4871 /* Clsid */ { 0x557cf402, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4872 /* FormatID */ { 0xb96b3cb0U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4873 /* CodecName */ gif_codecname,
4874 /* DllName */ NULL,
4875 /* FormatDescription */ gif_format,
4876 /* FilenameExtension */ gif_extension,
4877 /* MimeType */ gif_mimetype,
4879 /* Version */ 1,
4880 /* SigCount */ 2,
4881 /* SigSize */ 6,
4882 /* SigPattern */ gif_sig_pattern,
4883 /* SigMask */ gif_sig_mask,
4884 },
4888 },
4889 {
4890 { /* TIFF */
4891 /* Clsid */ { 0x557cf405, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4892 /* FormatID */ { 0xb96b3cb1U, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4893 /* CodecName */ tiff_codecname,
4894 /* DllName */ NULL,
4895 /* FormatDescription */ tiff_format,
4896 /* FilenameExtension */ tiff_extension,
4897 /* MimeType */ tiff_mimetype,
4899 /* Version */ 1,
4900 /* SigCount */ 2,
4901 /* SigSize */ 4,
4902 /* SigPattern */ tiff_sig_pattern,
4903 /* SigMask */ tiff_sig_mask,
4904 },
4908 },
4909 {
4910 { /* EMF */
4911 /* Clsid */ { 0x557cf403, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4912 /* FormatID */ { 0xb96b3cacU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4913 /* CodecName */ emf_codecname,
4914 /* DllName */ NULL,
4915 /* FormatDescription */ emf_format,
4916 /* FilenameExtension */ emf_extension,
4917 /* MimeType */ emf_mimetype,
4919 /* Version */ 1,
4920 /* SigCount */ 1,
4921 /* SigSize */ 4,
4922 /* SigPattern */ emf_sig_pattern,
4923 /* SigMask */ emf_sig_mask,
4924 },
4925 NULL,
4927 NULL
4928 },
4929 {
4930 { /* WMF */
4931 /* Clsid */ { 0x557cf404, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4932 /* FormatID */ { 0xb96b3cadU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4933 /* CodecName */ wmf_codecname,
4934 /* DllName */ NULL,
4935 /* FormatDescription */ wmf_format,
4936 /* FilenameExtension */ wmf_extension,
4937 /* MimeType */ wmf_mimetype,
4939 /* Version */ 1,
4940 /* SigCount */ 1,
4941 /* SigSize */ 2,
4942 /* SigPattern */ wmf_sig_pattern,
4943 /* SigMask */ wmf_sig_mask,
4944 },
4945 NULL,
4947 NULL
4948 },
4949 {
4950 { /* PNG */
4951 /* Clsid */ { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4952 /* FormatID */ { 0xb96b3cafU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4953 /* CodecName */ png_codecname,
4954 /* DllName */ NULL,
4955 /* FormatDescription */ png_format,
4956 /* FilenameExtension */ png_extension,
4957 /* MimeType */ png_mimetype,
4959 /* Version */ 1,
4960 /* SigCount */ 1,
4961 /* SigSize */ 8,
4962 /* SigPattern */ png_sig_pattern,
4963 /* SigMask */ png_sig_mask,
4964 },
4968 },
4969 {
4970 { /* ICO */
4971 /* Clsid */ { 0x557cf407, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } },
4972 /* FormatID */ { 0xb96b3cabU, 0x0728U, 0x11d3U, {0x9d, 0x7b, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e} },
4973 /* CodecName */ ico_codecname,
4974 /* DllName */ NULL,
4975 /* FormatDescription */ ico_format,
4976 /* FilenameExtension */ ico_extension,
4977 /* MimeType */ ico_mimetype,
4979 /* Version */ 1,
4980 /* SigCount */ 1,
4981 /* SigSize */ 4,
4982 /* SigPattern */ ico_sig_pattern,
4983 /* SigMask */ ico_sig_mask,
4984 },
4985 NULL,
4988 },
4989};
4990
4991/*****************************************************************************
4992 * GdipGetImageDecodersSize [GDIPLUS.@]
4993 */
4995{
4996 int decoder_count=0;
4997 int i;
4998 TRACE("%p %p\n", numDecoders, size);
4999
5000 if (!numDecoders || !size)
5001 return InvalidParameter;
5002
5003 for (i=0; i<NUM_CODECS; i++)
5004 {
5005 if (codecs[i].info.Flags & ImageCodecFlagsDecoder)
5006 decoder_count++;
5007 }
5008
5009 *numDecoders = decoder_count;
5010 *size = decoder_count * sizeof(ImageCodecInfo);
5011
5012 return Ok;
5013}
5014
5015/*****************************************************************************
5016 * GdipGetImageDecoders [GDIPLUS.@]
5017 */
5019{
5020 int i, decoder_count=0;
5021 TRACE("%u %u %p\n", numDecoders, size, decoders);
5022
5023 if (!decoders ||
5024 size != numDecoders * sizeof(ImageCodecInfo))
5025 return GenericError;
5026
5027 for (i=0; i<NUM_CODECS; i++)
5028 {
5029 if (codecs[i].info.Flags & ImageCodecFlagsDecoder)
5030 {
5031 if (decoder_count == numDecoders) return GenericError;
5032 memcpy(&decoders[decoder_count], &codecs[i].info, sizeof(ImageCodecInfo));
5033 decoder_count++;
5034 }
5035 }
5036
5037 if (decoder_count < numDecoders) return GenericError;
5038
5039 return Ok;
5040}
5041
5042/*****************************************************************************
5043 * GdipGetImageEncodersSize [GDIPLUS.@]
5044 */
5046{
5047 int encoder_count=0;
5048 int i;
5049 TRACE("%p %p\n", numEncoders, size);
5050
5051 if (!numEncoders || !size)
5052 return InvalidParameter;
5053
5054 for (i=0; i<NUM_CODECS; i++)
5055 {
5056 if (codecs[i].info.Flags & ImageCodecFlagsEncoder)
5057 encoder_count++;
5058 }
5059
5060 *numEncoders = encoder_count;
5061 *size = encoder_count * sizeof(ImageCodecInfo);
5062
5063 return Ok;
5064}
5065
5066/*****************************************************************************
5067 * GdipGetImageEncoders [GDIPLUS.@]
5068 */
5070{
5071 int i, encoder_count=0;
5072 TRACE("%u %u %p\n", numEncoders, size, encoders);
5073
5074 if (!encoders ||
5075 size != numEncoders * sizeof(ImageCodecInfo))
5076 return GenericError;
5077
5078 for (i=0; i<NUM_CODECS; i++)
5079 {
5080 if (codecs[i].info.Flags & ImageCodecFlagsEncoder)
5081 {
5082 if (encoder_count == numEncoders) return GenericError;
5083 memcpy(&encoders[encoder_count], &codecs[i].info, sizeof(ImageCodecInfo));
5084 encoder_count++;
5085 }
5086 }
5087
5088 if (encoder_count < numEncoders) return GenericError;
5089
5090 return Ok;
5091}
5092
5094 GDIPCONST CLSID* clsidEncoder, UINT *size)
5095{
5096 static int calls;
5097
5098 TRACE("(%p,%s,%p)\n", image, debugstr_guid(clsidEncoder), size);
5099
5100 if(!(calls++))
5101 FIXME("not implemented\n");
5102
5103 *size = 0;
5104
5105 return NotImplemented;
5106}
5107
5109{
5110 BITMAPV4HEADER bmh;
5111 HDC hdc;
5113
5115
5116 memset(&bmh, 0, sizeof(bmh));
5117 bmh.bV4Size = sizeof(bmh);
5118 bmh.bV4Width = 1;
5119 bmh.bV4Height = 1;
5121 bmh.bV4BitCount = 16;
5122
5123 GetDIBits(hdc, hbm, 0, 0, NULL, (BITMAPINFO*)&bmh, DIB_RGB_COLORS);
5124
5125 if (bmh.bV4RedMask == 0x7c00 &&
5126 bmh.bV4GreenMask == 0x3e0 &&
5127 bmh.bV4BlueMask == 0x1f)
5128 {
5130 }
5131 else if (bmh.bV4RedMask == 0xf800 &&
5132 bmh.bV4GreenMask == 0x7e0 &&
5133 bmh.bV4BlueMask == 0x1f)
5134 {
5136 }
5137 else
5138 {
5139 FIXME("unrecognized bitfields %x,%x,%x\n", bmh.bV4RedMask,
5140 bmh.bV4GreenMask, bmh.bV4BlueMask);
5142 }
5143
5144 DeleteDC(hdc);
5145
5146 return result;
5147}
5148
5149/*****************************************************************************
5150 * GdipCreateBitmapFromHBITMAP [GDIPLUS.@]
5151 */
5153{
5154 BITMAP bm;
5155 GpStatus retval;
5157 BitmapData lockeddata;
5158
5159 TRACE("%p %p %p\n", hbm, hpal, bitmap);
5160
5161 if(!hbm || !bitmap)
5162 return InvalidParameter;
5163
5164 if (GetObjectA(hbm, sizeof(bm), &bm) != sizeof(bm))
5165 return InvalidParameter;
5166
5167 /* TODO: Figure out the correct format for 16, 32, 64 bpp */
5168 switch(bm.bmBitsPixel) {
5169 case 1:
5171 break;
5172 case 4:
5174 break;
5175 case 8:
5177 break;
5178 case 16:
5181 return InvalidParameter;
5182 break;
5183 case 24:
5185 break;
5186 case 32:
5188 break;
5189 case 48:
5191 break;
5192 default:
5193 FIXME("don't know how to handle %d bpp\n", bm.bmBitsPixel);
5194 return InvalidParameter;
5195 }
5196
5197 retval = GdipCreateBitmapFromScan0(bm.bmWidth, bm.bmHeight, 0,
5198 format, NULL, bitmap);
5199
5200 if (retval == Ok)
5201 {
5203 format, &lockeddata);
5204 if (retval == Ok)
5205 {
5206 HDC hdc;
5207 char bmibuf[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
5208 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
5209 INT src_height;
5210
5212
5215
5217
5218 src_height = abs(pbmi->bmiHeader.biHeight);
5219 pbmi->bmiHeader.biHeight = -src_height;
5220
5221 GetDIBits(hdc, hbm, 0, src_height, lockeddata.Scan0, pbmi, DIB_RGB_COLORS);
5222
5223 DeleteDC(hdc);
5224
5225 GdipBitmapUnlockBits(*bitmap, &lockeddata);
5226 }
5227
5228 if (retval == Ok && hpal)
5229 {
5230 PALETTEENTRY entry[256];
5232 int i, num_palette_entries;
5233
5234 num_palette_entries = GetPaletteEntries(hpal, 0, 256, entry);
5235 if (!num_palette_entries)
5236 retval = GenericError;
5237
5238 palette = heap_alloc_zero(sizeof(ColorPalette) + sizeof(ARGB) * (num_palette_entries-1));
5239 if (!palette)
5240 retval = OutOfMemory;
5241
5242 if (retval == Ok)
5243 {
5244 palette->Flags = 0;
5245 palette->Count = num_palette_entries;
5246
5247 for (i=0; i<num_palette_entries; i++)
5248 {
5249 palette->Entries[i] = 0xff000000 | entry[i].peRed << 16 |
5250 entry[i].peGreen << 8 | entry[i].peBlue;
5251 }
5252
5253 retval = GdipSetImagePalette(&(*bitmap)->image, palette);
5254 }
5255
5257 }
5258
5259 if (retval != Ok)
5260 {
5261 GdipDisposeImage(&(*bitmap)->image);
5262 *bitmap = NULL;
5263 }
5264 }
5265
5266 return retval;
5267}
5268
5269/*****************************************************************************
5270 * GdipCreateEffect [GDIPLUS.@]
5271 */
5273{
5274 FIXME("(%s, %p): stub\n", debugstr_guid(&guid), effect);
5275
5276 if(!effect)
5277 return InvalidParameter;
5278
5279 *effect = NULL;
5280
5281 return NotImplemented;
5282}
5283
5284/*****************************************************************************
5285 * GdipDeleteEffect [GDIPLUS.@]
5286 */
5288{
5289 FIXME("(%p): stub\n", effect);
5290 /* note: According to Jose Roca's GDI+ Docs, this is not implemented
5291 * in Windows's gdiplus */
5292 return NotImplemented;
5293}
5294
5295/*****************************************************************************
5296 * GdipSetEffectParameters [GDIPLUS.@]
5297 */
5299 const VOID *params, const UINT size)
5300{
5301 static int calls;
5302
5303 TRACE("(%p,%p,%u)\n", effect, params, size);
5304
5305 if(!(calls++))
5306 FIXME("not implemented\n");
5307
5308 return NotImplemented;
5309}
5310
5311/*****************************************************************************
5312 * GdipGetImageFlags [GDIPLUS.@]
5313 */
5315{
5316 TRACE("%p %p\n", image, flags);
5317
5318 if(!image || !flags)
5319 return InvalidParameter;
5320
5321 *flags = image->flags;
5322
5323 return Ok;
5324}
5325
5327{
5328 TRACE("(%d, %p)\n", control, param);
5329
5330 switch(control){
5332 if(param)
5333 FIXME("TestControlForceBilinear not handled\n");
5334 break;
5335 case TestControlNoICM:
5336 if(param)
5337 FIXME("TestControlNoICM not handled\n");
5338 break;
5340 *((DWORD*)param) = 3102;
5341 break;
5342 }
5343
5344 return Ok;
5345}
5346
5348{
5349 TRACE("%p\n", image);
5350
5351 return Ok;
5352}
5353
5354/*****************************************************************************
5355 * GdipGetImageThumbnail [GDIPLUS.@]
5356 */
5358 GpImage **ret_image, GetThumbnailImageAbort cb,
5359 VOID * cb_data)
5360{
5361 GpStatus stat;
5362 GpGraphics *graphics;
5363 UINT srcwidth, srcheight;
5364
5365 TRACE("(%p %u %u %p %p %p)\n",
5366 image, width, height, ret_image, cb, cb_data);
5367
5368 if (!image || !ret_image)
5369 return InvalidParameter;
5370
5371 if (!width) width = 120;
5372 if (!height) height = 120;
5373
5374 GdipGetImageWidth(image, &srcwidth);
5375 GdipGetImageHeight(image, &srcheight);
5376
5378 NULL, (GpBitmap**)ret_image);
5379
5380 if (stat == Ok)
5381 {
5382 stat = GdipGetImageGraphicsContext(*ret_image, &graphics);
5383
5384 if (stat == Ok)
5385 {
5386 stat = GdipDrawImageRectRectI(graphics, image,
5387 0, 0, width, height, 0, 0, srcwidth, srcheight, UnitPixel,
5388 NULL, NULL, NULL);
5389
5390 GdipDeleteGraphics(graphics);
5391 }
5392
5393 if (stat != Ok)
5394 {
5395 GdipDisposeImage(*ret_image);
5396 *ret_image = NULL;
5397 }
5398 }
5399
5400 return stat;
5401}
5402
5403/*****************************************************************************
5404 * GdipImageRotateFlip [GDIPLUS.@]
5405 */
5407{
5408 GpBitmap *new_bitmap;
5410 int bpp, bytesperpixel;
5411 BOOL rotate_90, flip_x, flip_y;
5412 int src_x_offset, src_y_offset;
5413 LPBYTE src_origin;
5414 UINT x, y, width, height;
5415 BitmapData src_lock, dst_lock;
5416 GpStatus stat;
5417 BOOL unlock;
5418
5419 TRACE("(%p, %u)\n", image, type);
5420
5421 if (!image)
5422 return InvalidParameter;
5423 if (!image_lock(image, &unlock))
5424 return ObjectBusy;
5425
5426 rotate_90 = type&1;
5427 flip_x = (type&6) == 2 || (type&6) == 4;
5428 flip_y = (type&3) == 1 || (type&3) == 2;
5429
5430 if (image->type != ImageTypeBitmap)
5431 {
5432 FIXME("Not implemented for type %i\n", image->type);
5433 image_unlock(image, unlock);
5434 return NotImplemented;
5435 }
5436
5437 bitmap = (GpBitmap*)image;
5438 bpp = PIXELFORMATBPP(bitmap->format);
5439
5440 if (bpp < 8)
5441 {
5442 FIXME("Not implemented for %i bit images\n", bpp);
5443 image_unlock(image, unlock);
5444 return NotImplemented;
5445 }
5446
5447 if (rotate_90)
5448 {
5449 width = bitmap->height;
5450 height = bitmap->width;
5451 }
5452 else
5453 {
5454 width = bitmap->width;
5455 height = bitmap->height;
5456 }
5457
5458 bytesperpixel = bpp/8;
5459
5460 stat = GdipCreateBitmapFromScan0(width, height, 0, bitmap->format, NULL, &new_bitmap);
5461
5462 if (stat != Ok)
5463 {
5464 image_unlock(image, unlock);
5465 return stat;
5466 }
5467
5468 stat = GdipBitmapLockBits(bitmap, NULL, ImageLockModeRead, bitmap->format, &src_lock);
5469
5470 if (stat == Ok)
5471 {
5472 stat = GdipBitmapLockBits(new_bitmap, NULL, ImageLockModeWrite, bitmap->format, &dst_lock);
5473
5474 if (stat == Ok)
5475 {
5476 LPBYTE src_row, src_pixel;
5477 LPBYTE dst_row, dst_pixel;
5478
5479 src_origin = src_lock.Scan0;
5480 if (flip_x) src_origin += bytesperpixel * (bitmap->width - 1);
5481 if (flip_y) src_origin += src_lock.Stride * (bitmap->height - 1);
5482
5483 if (rotate_90)
5484 {
5485 if (flip_y) src_x_offset = -src_lock.Stride;
5486 else src_x_offset = src_lock.Stride;
5487 if (flip_x) src_y_offset = -bytesperpixel;
5488 else src_y_offset = bytesperpixel;
5489 }
5490 else
5491 {
5492 if (flip_x) src_x_offset = -bytesperpixel;
5493 else src_x_offset = bytesperpixel;
5494 if (flip_y) src_y_offset = -src_lock.Stride;
5495 else src_y_offset = src_lock.Stride;
5496 }
5497
5498 src_row = src_origin;
5499 dst_row = dst_lock.Scan0;
5500 for (y=0; y<height; y++)
5501 {
5502 src_pixel = src_row;
5503 dst_pixel = dst_row;
5504 for (x=0; x<width; x++)
5505 {
5506 /* FIXME: This could probably be faster without memcpy. */
5507 memcpy(dst_pixel, src_pixel, bytesperpixel);
5508 dst_pixel += bytesperpixel;
5509 src_pixel += src_x_offset;
5510 }
5511 src_row += src_y_offset;
5512 dst_row += dst_lock.Stride;
5513 }
5514
5515 GdipBitmapUnlockBits(new_bitmap, &dst_lock);
5516 }
5517
5518 GdipBitmapUnlockBits(bitmap, &src_lock);
5519 }
5520
5521 if (stat == Ok)
5522 move_bitmap(bitmap, new_bitmap, FALSE);
5523 else
5524 GdipDisposeImage(&new_bitmap->image);
5525
5526 image_unlock(image, unlock);
5527 return stat;
5528}
5529
5530/*****************************************************************************
5531 * GdipImageSetAbort [GDIPLUS.@]
5532 */
5534{
5535 TRACE("(%p, %p)\n", image, pabort);
5536
5537 if (!image)
5538 return InvalidParameter;
5539
5540 if (pabort)
5541 FIXME("Abort callback is not supported.\n");
5542
5543 return Ok;
5544}
5545
5546/*****************************************************************************
5547 * GdipBitmapConvertFormat [GDIPLUS.@]
5548 */
5550 PaletteType palettetype, ColorPalette *palette, REAL alphathreshold)
5551{
5552 FIXME("(%p, 0x%08x, %d, %d, %p, %f): stub\n", bitmap, format, dithertype, palettetype, palette, alphathreshold);
5553 return NotImplemented;
5554}
5555
5556static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5557{
5558 ch0[ color >> 24 ]++;
5559 ch1[(color >> 16) & 0xff]++;
5560 ch2[(color >> 8) & 0xff]++;
5561 ch3[ color & 0xff]++;
5562}
5563
5564static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5565{
5566 BYTE alpha = color >> 24;
5567
5568 ch0[alpha]++;
5569 ch1[(((color >> 16) & 0xff) * alpha) / 0xff]++;
5570 ch2[(((color >> 8) & 0xff) * alpha) / 0xff]++;
5571 ch3[(( color & 0xff) * alpha) / 0xff]++;
5572}
5573
5574static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5575{
5576 ch0[(color >> 16) & 0xff]++;
5577 ch1[(color >> 8) & 0xff]++;
5578 ch2[ color & 0xff]++;
5579}
5580
5581static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5582{
5583 ch0[(76 * ((color >> 16) & 0xff) + 150 * ((color >> 8) & 0xff) + 29 * (color & 0xff)) / 0xff]++;
5584}
5585
5586static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5587{
5588 ch0[color & 0xff]++;
5589}
5590
5591static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5592{
5593 ch0[(color >> 8) & 0xff]++;
5594}
5595
5596static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5597{
5598 ch0[(color >> 16) & 0xff]++;
5599}
5600
5601static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5602{
5603 ch0[(color >> 24) & 0xff]++;
5604}
5605
5606/*****************************************************************************
5607 * GdipBitmapGetHistogram [GDIPLUS.@]
5608 */
5610 UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
5611{
5612 static void (* const set_histogram_point[])(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3) =
5613 {
5622 };
5623 UINT width, height, x, y;
5624
5625 TRACE("(%p, %d, %u, %p, %p, %p, %p)\n", bitmap, format, num_of_entries,
5626 ch0, ch1, ch2, ch3);
5627
5628 if (!bitmap || num_of_entries != 256)
5629 return InvalidParameter;
5630
5631 /* Make sure passed channel pointers match requested format */
5632 switch (format)
5633 {
5636 if (!ch0 || !ch1 || !ch2 || !ch3)
5637 return InvalidParameter;
5638 memset(ch0, 0, num_of_entries * sizeof(UINT));
5639 memset(ch1, 0, num_of_entries * sizeof(UINT));
5640 memset(ch2, 0, num_of_entries * sizeof(UINT));
5641 memset(ch3, 0, num_of_entries * sizeof(UINT));
5642 break;
5643 case HistogramFormatRGB:
5644 if (!ch0 || !ch1 || !ch2 || ch3)
5645 return InvalidParameter;
5646 memset(ch0, 0, num_of_entries * sizeof(UINT));
5647 memset(ch1, 0, num_of_entries * sizeof(UINT));
5648 memset(ch2, 0, num_of_entries * sizeof(UINT));
5649 break;
5651 case HistogramFormatB:
5652 case HistogramFormatG:
5653 case HistogramFormatR:
5654 case HistogramFormatA:
5655 if (!ch0 || ch1 || ch2 || ch3)
5656 return InvalidParameter;
5657 memset(ch0, 0, num_of_entries * sizeof(UINT));
5658 break;
5659 default:
5660 WARN("Invalid histogram format requested, %d\n", format);
5661 return InvalidParameter;
5662 }
5663
5664 GdipGetImageWidth(&bitmap->image, &width);
5665 GdipGetImageHeight(&bitmap->image, &height);
5666
5667 for (y = 0; y < height; y++)
5668 for (x = 0; x < width; x++)
5669 {
5670 ARGB color;
5671
5673 set_histogram_point[format](color, ch0, ch1, ch2, ch3);
5674 }
5675
5676 return Ok;
5677}
5678
5679/*****************************************************************************
5680 * GdipBitmapGetHistogramSize [GDIPLUS.@]
5681 */
5683{
5684 TRACE("(%d, %p)\n", format, num_of_entries);
5685
5686 if (!num_of_entries)
5687 return InvalidParameter;
5688
5689 *num_of_entries = 256;
5690 return Ok;
5691}
5692
5694 BOOL transparent, GpBitmap *bitmap)
5695{
5698 HRESULT hr;
5700 IWICPalette *wic_palette;
5701
5702 if (!bitmap) return InvalidParameter;
5703 if (palette->Count < desired) return GenericError;
5704
5706 if (status != Ok) return status;
5707
5708 hr = WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION, &factory);
5709 if (hr != S_OK)
5710 {
5712 return hresult_to_status(hr);
5713 }
5714
5715 hr = IWICImagingFactory_CreatePalette(factory, &wic_palette);
5716 if (hr == S_OK)
5717 {
5719
5720 /* PixelFormat24bppRGB actually stores the bitmap bits as BGR. */
5721 hr = IWICImagingFactory_CreateBitmapFromMemory(factory, data.Width, data.Height,
5722 &GUID_WICPixelFormat24bppBGR, data.Stride, data.Stride * data.Width, data.Scan0, &bitmap);
5723 if (hr == S_OK)
5724 {
5725 hr = IWICPalette_InitializeFromBitmap(wic_palette, (IWICBitmapSource *)bitmap, desired, transparent);
5726 if (hr == S_OK)
5727 {
5728 palette->Flags = 0;
5729 IWICPalette_GetColorCount(wic_palette, &palette->Count);
5730 IWICPalette_GetColors(wic_palette, palette->Count, palette->Entries, &palette->Count);
5731 }
5732
5733 IWICBitmap_Release(bitmap);
5734 }
5735
5736 IWICPalette_Release(wic_palette);
5737 }
5738
5739 IWICImagingFactory_Release(factory);
5741
5742 return hresult_to_status(hr);
5743}
5744
5745/*****************************************************************************
5746 * GdipInitializePalette [GDIPLUS.@]
5747 */
5749 PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap)
5750{
5751 TRACE("(%p,%d,%d,%d,%p)\n", palette, type, desired, transparent, bitmap);
5752
5753 if (!palette) return InvalidParameter;
5754
5755 switch (type)
5756 {
5757 case PaletteTypeCustom:
5758 return Ok;
5759
5760 case PaletteTypeOptimal:
5761 return create_optimal_palette(palette, desired, transparent, bitmap);
5762
5763 /* WIC palette type enumeration matches these gdiplus enums */
5764 case PaletteTypeFixedBW:
5772 {
5773 ColorPalette *wic_palette;
5774 GpStatus status = Ok;
5775
5776 wic_palette = get_palette(NULL, type);
5777 if (!wic_palette) return OutOfMemory;
5778
5779 if (palette->Count >= wic_palette->Count)
5780 {
5781 palette->Flags = wic_palette->Flags;
5782 palette->Count = wic_palette->Count;
5783 memcpy(palette->Entries, wic_palette->Entries, wic_palette->Count * sizeof(wic_palette->Entries[0]));
5784 }
5785 else
5787
5788 heap_free(wic_palette);
5789
5790 return status;
5791 }
5792
5793 default:
5794 FIXME("unknown palette type %d\n", type);
5795 break;
5796 }
5797
5798 return InvalidParameter;
5799}
static HBITMAP hbitmap
unsigned long long UINT64
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define stat
Definition: acwin.h:99
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#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:33
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
HINSTANCE hInstance
Definition: charmap.c:19
Definition: list.h:37
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#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
static const char b64[]
Definition: base64.c:67
#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:6621
GpStatus WINGDIPAPI GdipCreateFromHDC(HDC hdc, GpGraphics **graphics)
Definition: graphics.c:2395
GpStatus WINGDIPAPI GdipCreateStreamOnFile(GDIPCONST WCHAR *filename, UINT access, IStream **stream)
Definition: graphics.c:2558
GpStatus WINGDIPAPI GdipGetDpiY(GpGraphics *graphics, REAL *dpi)
Definition: graphics.c:6635
GpStatus WINGDIPAPI GdipDeleteGraphics(GpGraphics *graphics)
Definition: graphics.c:2581
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:3517
GpStatus WINGDIPAPI GdipDrawImage(GpGraphics *graphics, GpImage *image, REAL x, REAL y)
Definition: graphics.c:2969
static const WCHAR emf_codecname[]
Definition: image.c:4800
static GpStatus load_wmf(IStream *stream, GpMetafile **metafile)
Definition: image.c:4114
GpStatus WINGDIPAPI GdipCreateBitmapFromFile(GDIPCONST WCHAR *filename, GpBitmap **bitmap)
Definition: image.c:1360
static PropertyItem * create_prop(PROPID propid, PROPVARIANT *value)
Definition: image.c:3419
static PropertyItem * get_gif_comment(IWICMetadataReader *reader)
Definition: image.c:3119
static const BYTE bmp_sig_mask[]
Definition: image.c:4777
GpStatus WINGDIPAPI GdipGetPropertySize(GpImage *image, UINT *size, UINT *count)
Definition: image.c:2735
static void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:430
static const BYTE wmf_sig_pattern[]
Definition: image.c:4811
GpStatus encode_image_png(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4650
static const BYTE tiff_sig_mask[]
Definition: image.c:4798
GpStatus WINGDIPAPI GdipDeleteEffect(CGpEffect *effect)
Definition: image.c:5287
GpStatus WINGDIPAPI GdipGetImageVerticalResolution(GpImage *image, REAL *res)
Definition: image.c:2378
static GpStatus decode_image_wmf(IStream *stream, GpImage **image)
Definition: image.c:4172
static void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:468
GpStatus WINGDIPAPI GdipGetImageRawFormat(GpImage *image, GUID *format)
Definition: image.c:2354
GpStatus WINGDIPAPI GdipGetImagePalette(GpImage *image, ColorPalette *palette, INT size)
Definition: image.c:4710
GpStatus WINGDIPAPI GdipGetImageEncodersSize(UINT *numEncoders, UINT *size)
Definition: image.c:5045
static const struct @416 pixel_formats[]
static void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:459
static const WCHAR tiff_format[]
Definition: image.c:4796
GpStatus WINGDIPAPI GdipGetImageFlags(GpImage *image, UINT *flags)
Definition: image.c:5314
GpStatus WINGDIPAPI GdipBitmapConvertFormat(GpBitmap *bitmap, PixelFormat format, DitherType dithertype, PaletteType palettetype, ColorPalette *palette, REAL alphathreshold)
Definition: image.c:5549
GpStatus WINGDIPAPI GdipSaveImageToStream(GpImage *image, IStream *stream, GDIPCONST CLSID *clsid, GDIPCONST EncoderParameters *params)
Definition: image.c:4671
#define PIXELFORMATBPP(x)
Definition: image.c:45
static GpStatus decode_image_icon(IStream *stream, GpImage **image)
Definition: image.c:3978
static void set_histogram_point_g(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5591
static DWORD blend_argb_no_bkgnd_alpha(DWORD src, DWORD bkgnd)
Definition: image.c:1467
GpStatus WINGDIPAPI GdipBitmapGetHistogramSize(HistogramFormat format, UINT *num_of_entries)
Definition: image.c:5682
GpStatus WINGDIPAPI GdipCloneBitmapAreaI(INT x, INT y, INT width, INT height, PixelFormat format, GpBitmap *srcBitmap, GpBitmap **dstBitmap)
Definition: image.c:1300
GpStatus WINGDIPAPI GdipGetAllPropertyItems(GpImage *image, UINT size, UINT count, PropertyItem *buf)
Definition: image.c:2805
static const WCHAR bmp_extension[]
Definition: image.c:4773
GpStatus WINGDIPAPI GdipGetImageWidth(GpImage *image, UINT *width)
Definition: image.c:2390
static const WCHAR wmf_mimetype[]
Definition: image.c:4809
GpStatus WINGDIPAPI GdipGetImageItemData(GpImage *image, ImageItemData *item)
Definition: image.c:2184
ImageFormat
Definition: image.c:4271
@ EMF
Definition: image.c:4276
@ WMF
Definition: image.c:4277
@ NUM_CODECS
Definition: image.c:4280
@ BMP
Definition: image.c:4272
@ TIFF
Definition: image.c:4275
@ ICO
Definition: image.c:4279
@ PNG
Definition: image.c:4278
@ GIF
Definition: image.c:4274
@ JPEG
Definition: image.c:4273
static void set_histogram_point_rgb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5574
static void set_histogram_point_argb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5556
static GpStatus decode_image_jpeg(IStream *stream, GpImage **image)
Definition: image.c:4001
static GpStatus decode_image_png(IStream *stream, GpImage **image)
Definition: image.c:4039
GpStatus WINGDIPAPI GdipGetImageHeight(GpImage *image, UINT *height)
Definition: image.c:2287
GpStatus WINGDIPAPI GdipGetImageDimension(GpImage *image, REAL *width, REAL *height)
Definition: image.c:2224
GpStatus(* decode_image_func)(IStream *stream, GpImage **image)
Definition: image.c:4260
GpStatus WINGDIPAPI GdipCreateBitmapFromScan0(INT width, INT height, INT stride, PixelFormat format, BYTE *scan0, GpBitmap **bitmap)
Definition: image.c:1760
static void getpixel_16bppARGB1555(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:202
GpStatus WINGDIPAPI GdipGetImageDecodersSize(UINT *numDecoders, UINT *size)
Definition: image.c:4994
static GpStatus decode_image_emf(IStream *stream, GpImage **image)
Definition: image.c:4234
static void getpixel_64bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:274
#define PropertyTagTypeSShort
Definition: image.c:2585
static void generate_halftone_palette(ARGB *entries, UINT count)
Definition: image.c:1708
static void getpixel_16bppRGB565(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:192
static const WCHAR png_mimetype[]
Definition: image.c:4816
static GpStatus load_emf(IStream *stream, GpMetafile **metafile)
Definition: image.c:4195
static void getpixel_4bppIndexed(BYTE *index, const BYTE *row, UINT x)
Definition: image.c:162
GpStatus WINGDIPAPI GdipSetImagePalette(GpImage *image, GDIPCONST ColorPalette *palette)
Definition: image.c:4744
static const WCHAR jpeg_mimetype[]
Definition: image.c:4781
GpStatus WINGDIPAPI GdipCreateBitmapFromResource(HINSTANCE hInstance, GDIPCONST WCHAR *lpBitmapName, GpBitmap **bitmap)
Definition: image.c:1444
static HRESULT get_gif_frame_rect(IWICBitmapFrameDecode *frame, UINT *left, UINT *top, UINT *width, UINT *height)
Definition: image.c:3822
GpStatus WINGDIPAPI GdipImageGetFrameCount(GpImage *image, GDIPCONST GUID *dimensionID, UINT *count)
Definition: image.c:2913
static void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:414
static const WCHAR bmp_format[]
Definition: image.c:4775
#define PropertyTagTypeFloat
Definition: image.c:2586
static DWORD get_gif_background_color(GpBitmap *bitmap)
Definition: image.c:3873
static const BYTE ico_sig_pattern[]
Definition: image.c:4825
GpStatus WINGDIPAPI GdipCreateCachedBitmap(GpBitmap *bitmap, GpGraphics *graphics, GpCachedBitmap **cachedbmp)
Definition: image.c:1978
GpStatus WINGDIPAPI GdipSetPropertyItem(GpImage *image, GDIPCONST PropertyItem *item)
Definition: image.c:4462
GpStatus WINGDIPAPI GdipRemovePropertyItem(GpImage *image, PROPID propId)
Definition: image.c:4447
static void add_property(GpBitmap *bitmap, PropertyItem *item)
Definition: image.c:3009
static void set_histogram_point_pargb(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5564
GpStatus WINGDIPAPI GdipGetImageGraphicsContext(GpImage *image, GpGraphics **graphics)
Definition: image.c:2249
static void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:483
static GpStatus encode_image_tiff(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4644
void(* metadata_reader_func)(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT frame)
Definition: image.c:3630
static void set_histogram_point_a(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5601
static const WCHAR wmf_format[]
Definition: image.c:4810
#define convert_rgb_to_indexed(getpixel_function, setpixel_function)
#define PropertyTagTypeDouble
Definition: image.c:2587
GpStatus WINGDIPAPI GdipSaveImageToFile(GpImage *image, GDIPCONST WCHAR *filename, GDIPCONST CLSID *clsidEncoder, GDIPCONST EncoderParameters *encoderParams)
Definition: image.c:4476
GpStatus convert_pixels(INT width, INT height, INT dst_stride, BYTE *dst_bits, PixelFormat dst_format, INT src_stride, const BYTE *src_bits, PixelFormat src_format, ColorPalette *palette)
Definition: image.c:562
static void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:447
GpStatus WINGDIPAPI GdipBitmapGetHistogram(GpBitmap *bitmap, HistogramFormat format, UINT num_of_entries, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5609
GpStatus WINGDIPAPI GdipImageGetFrameDimensionsCount(GpImage *image, UINT *count)
Definition: image.c:2933
static GpStatus encode_image_gif(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4662
static void getpixel_1bppIndexed(BYTE *index, const BYTE *row, UINT x)
Definition: image.c:157
GpStatus WINGDIPAPI GdipCreateBitmapFromGraphics(INT width, INT height, GpGraphics *target, GpBitmap **bitmap)
Definition: image.c:1542
GpStatus WINGDIPAPI GdipBitmapSetResolution(GpBitmap *bitmap, REAL xdpi, REAL ydpi)
Definition: image.c:1163
static const WCHAR bmp_mimetype[]
Definition: image.c:4774
GpStatus WINGDIPAPI GdipCreateBitmapFromGdiDib(GDIPCONST BITMAPINFO *info, VOID *bits, GpBitmap **bitmap)
Definition: image.c:1385
static const WCHAR tiff_mimetype[]
Definition: image.c:4795
static GpStatus get_decoder_info(IStream *stream, const struct image_codec **result)
Definition: image.c:4285
static GpStatus free_image_data(GpImage *image)
Definition: image.c:2126
static void getpixel_32bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:224
static const BYTE emf_sig_pattern[]
Definition: image.c:4804
GpStatus WINGDIPAPI GdipBitmapLockBits(GpBitmap *bitmap, GDIPCONST GpRect *rect, UINT flags, PixelFormat format, BitmapData *lockeddata)
Definition: image.c:1030
static const BYTE jpeg_sig_mask[]
Definition: image.c:4784
static void getpixel_8bppIndexed(BYTE *index, const BYTE *row, UINT x)
Definition: image.c:170
GpStatus WINGDIPAPI GdipDeleteCachedBitmap(GpCachedBitmap *cachedbmp)
Definition: image.c:2055
GpStatus WINGDIPAPI GdipGetPropertyCount(GpImage *image, UINT *num)
Definition: image.c:2412
GpStatus WINGDIPAPI GdipBitmapApplyEffect(GpBitmap *bitmap, CGpEffect *effect, RECT *roi, BOOL useAuxData, VOID **auxData, INT *auxDataSize)
Definition: image.c:134
GpStatus WINGDIPAPI GdipGetEncoderParameterListSize(GpImage *image, GDIPCONST CLSID *clsidEncoder, UINT *size)
Definition: image.c:5093
static const BYTE png_sig_pattern[]
Definition: image.c:4818
static const WCHAR jpeg_format[]
Definition: image.c:4782
GpStatus WINGDIPAPI GdipDisposeImage(GpImage *image)
Definition: image.c:2155
#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:265
GpStatus WINGDIPAPI GdipGetImagePixelFormat(GpImage *image, PixelFormat *format)
Definition: image.c:2339
static const WCHAR gif_format[]
Definition: image.c:4789
static GpStatus encode_image_BMP(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4638
GpStatus WINGDIPAPI GdipLoadImageFromFile(GDIPCONST WCHAR *filename, GpImage **image)
Definition: image.c:2976
static void getpixel_48bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:256
static const BYTE gif_sig_mask[]
Definition: image.c:4791
static GpStatus decode_image_bmp(IStream *stream, GpImage **image)
Definition: image.c:3983
static void setpixel_16bppGrayScale(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:408
GpStatus WINGDIPAPI GdipGetImageThumbnail(GpImage *image, UINT width, UINT height, GpImage **ret_image, GetThumbnailImageAbort cb, VOID *cb_data)
Definition: image.c:5357
GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap *bitmap, INT x, INT y, ARGB *color)
Definition: image.c:288
static void move_bitmap(GpBitmap *dst, GpBitmap *src, BOOL clobber_palette)
Definition: image.c:2081
static const WCHAR emf_mimetype[]
Definition: image.c:4802
const WICPixelFormatGUID * wic_format
Definition: image.c:50
GpStatus(* encode_image_func)(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4257
GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap *bitmap, INT x, INT y, ARGB color)
Definition: image.c:494
#define PropertyTagTypeSByte
Definition: image.c:2584
static GpStatus decode_image_gif(IStream *stream, GpImage **image)
Definition: image.c:4082
GpStatus WINGDIPAPI GdipCreateHICONFromBitmap(GpBitmap *bitmap, HICON *hicon)
Definition: image.c:2001
GpStatus WINGDIPAPI GdipSetEffectParameters(CGpEffect *effect, const VOID *params, const UINT size)
Definition: image.c:5298
GpStatus WINGDIPAPI GdipDrawCachedBitmap(GpGraphics *graphics, GpCachedBitmap *cachedbmp, INT x, INT y)
Definition: image.c:2068
static void getpixel_16bppGrayScale(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:175
static void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:476
GpStatus WINGDIPAPI GdipImageSetAbort(GpImage *image, GdiplusAbort *pabort)
Definition: image.c:5533
static UINT propvariant_size(PROPVARIANT *value)
Definition: image.c:2502
static const WCHAR gif_extension[]
Definition: image.c:4787
GpStatus(* select_image_func)(GpImage *image, UINT active_frame)
Definition: image.c:4262
WICBitmapPaletteType palette_type
Definition: image.c:53
static const BYTE png_sig_mask[]
Definition: image.c:4819
static void getpixel_24bppRGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:215
static GpStatus select_frame_gif(GpImage *image, UINT active_frame)
Definition: image.c:3909
static PropertyItem * get_gif_transparent_idx(IWICMetadataReader *reader)
Definition: image.c:3239
static void png_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT active_frame)
Definition: image.c:3461
static const WCHAR ico_format[]
Definition: image.c:4824
static PropertyItem * get_gif_background(IWICMetadataReader *reader)
Definition: image.c:3172
PixelFormat gdip_format
Definition: image.c:51
static GpStatus create_optimal_palette(ColorPalette *palette, INT desired, BOOL transparent, GpBitmap *bitmap)
Definition: image.c:5693
GpStatus WINGDIPAPI GdipGetImagePaletteSize(GpImage *image, INT *size)
Definition: image.c:2321
static void setpixel_4bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x, ColorPalette *palette)
Definition: image.c:399
static const WCHAR ico_extension[]
Definition: image.c:4822
GpStatus WINGDIPAPI GdipImageSelectActiveFrame(GpImage *image, GDIPCONST GUID *dimensionID, UINT frame)
Definition: image.c:4350
static BOOL has_png_transparency_chunk(IStream *pIStream)
Definition: image.c:4006
GpStatus WINGDIPAPI GdipGetPropertyIdList(GpImage *image, UINT num, PROPID *list)
Definition: image.c:2435
static const WCHAR tiff_extension[]
Definition: image.c:4794
static GpStatus encode_image_jpeg(GpImage *image, IStream *stream, GDIPCONST EncoderParameters *params)
Definition: image.c:4656
#define convert_rgb_to_rgb(getpixel_function, setpixel_function)
static PixelFormat get_16bpp_format(HBITMAP hbm)
Definition: image.c:5108
static const WCHAR png_codecname[]
Definition: image.c:4814
static const WCHAR jpeg_codecname[]
Definition: image.c:4779
static void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:453
GpStatus WINGDIPAPI GdipGetImageType(GpImage *image, ImageType *type)
Definition: image.c:2366
static const struct image_format_dimension image_format_dimensions[]
Definition: image.c:2906
GpStatus WINGDIPAPI GdipFindFirstImageItem(GpImage *image, ImageItemData *item)
Definition: image.c:2169
GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream *stream, GpImage **image)
Definition: image.c:4405
static const WCHAR emf_extension[]
Definition: image.c:4801
static const WCHAR wmf_extension[]
Definition: image.c:4808
static ColorPalette * get_palette(IWICBitmapFrameDecode *frame, WICBitmapPaletteType palette_type)
Definition: image.c:74
GpStatus WINGDIPAPI GdipCreateBitmapFromStream(IStream *stream, GpBitmap **bitmap)
Definition: image.c:1935
GpStatus WINGDIPAPI GdipInitializePalette(ColorPalette *palette, PaletteType type, INT desired, BOOL transparent, GpBitmap *bitmap)
Definition: image.c:5748
static GpStatus initialize_decoder_wic(IStream *stream, REFGUID container, IWICBitmapDecoder **decoder)
Definition: image.c:3612
static void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:422
static const WCHAR bmp_codecname[]
Definition: image.c:4772
static const WCHAR tiff_codecname[]
Definition: image.c:4793
static GpStatus get_screen_resolution(REAL *xres, REAL *yres)
Definition: image.c:1746
static void getpixel_16bppRGB555(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:182
static BOOL get_bool_property(IWICMetadataReader *reader, const GUID *guid, const WCHAR *prop_name)
Definition: image.c:3053
static void setpixel_1bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x, ColorPalette *palette)
Definition: image.c:393
GpStatus WINGDIPAPI GdipImageRotateFlip(GpImage *image, RotateFlipType type)
Definition: image.c:5406
GpStatus WINGDIPAPI GdipCloneBitmapArea(REAL x, REAL y, REAL width, REAL height, PixelFormat format, GpBitmap *srcBitmap, GpBitmap **dstBitmap)
Definition: image.c:1237
GpStatus WINGDIPAPI GdipGetImageEncoders(UINT numEncoders, UINT size, ImageCodecInfo *encoders)
Definition: image.c:5069
GpStatus WINGDIPAPI GdipGetPropertyItem(GpImage *image, PROPID propid, UINT size, PropertyItem *buffer)
Definition: image.c:2682
static ULONG get_ulong_by_index(IWICMetadataReader *reader, ULONG index)
Definition: image.c:3438
GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR *filename, GpImage **image)
Definition: image.c:3002
GpStatus WINGDIPAPI GdipGetImageDecoders(UINT numDecoders, UINT size, ImageCodecInfo *decoders)
Definition: image.c:5018
GpStatus WINGDIPAPI GdipCreateHBITMAPFromBitmap(GpBitmap *bitmap, HBITMAP *hbmReturn, ARGB background)
Definition: image.c:1479
GpStatus WINGDIPAPI GdipTestControl(GpTestControlEnum control, void *param)
Definition: image.c:5326
static const WCHAR png_format[]
Definition: image.c:4817
static GpStatus select_frame_wic(GpImage *image, UINT active_frame)
Definition: image.c:3801
static void getpixel_32bppARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:233
GpStatus WINGDIPAPI GdipGetImageBounds(GpImage *image, GpRectF *srcRect, GpUnit *srcUnit)
Definition: image.c:2196
static const struct image_codec codecs[NUM_CODECS]
Definition: image.c:4283
static const BYTE wmf_sig_mask[]
Definition: image.c:4812
static void set_histogram_point_r(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5596
GpStatus WINGDIPAPI GdipCreateBitmapFromFileICM(GDIPCONST WCHAR *filename, GpBitmap **bitmap)
Definition: image.c:1436
static const BYTE jpeg_sig_pattern[]
Definition: image.c:4783
static PropertyItem * get_gif_loopcount(IWICMetadataReader *reader)
Definition: image.c:3131
GpStatus WINGDIPAPI GdipCreateBitmapFromHICON(HICON hicon, GpBitmap **bitmap)
Definition: image.c:1564
static void set_histogram_point_gray(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5581
static const WCHAR png_extension[]
Definition: image.c:4815
GpStatus WINGDIPAPI GdipImageForceValidation(GpImage *image)
Definition: image.c:5347
HRESULT WINAPI WICCreateImagingFactory_Proxy(UINT, IWICImagingFactory **)
Definition: proxy.c:651
static const BYTE bmp_sig_pattern[]
Definition: image.c:4776
static void setpixel_8bppIndexed(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x, ColorPalette *palette)
Definition: image.c:386
static const BYTE tiff_sig_pattern[]
Definition: image.c:4797
static const BYTE ico_sig_mask[]
Definition: image.c:4826
GpStatus WINGDIPAPI GdipCreateEffect(const GUID guid, CGpEffect **effect)
Definition: image.c:5272
GpStatus WINGDIPAPI GdipGetImageHorizontalResolution(GpImage *image, REAL *res)
Definition: image.c:2309
GpStatus WINGDIPAPI GdipCloneImage(GpImage *image, GpImage **cloneImage)
Definition: image.c:1308
GpStatus WINGDIPAPI GdipGetPropertyItemSize(GpImage *image, PROPID propid, UINT *size)
Definition: image.c:2536
static void set_histogram_point_b(ARGB color, UINT *ch0, UINT *ch1, UINT *ch2, UINT *ch3)
Definition: image.c:5586
GpStatus WINGDIPAPI GdipCreateBitmapFromStreamICM(IStream *stream, GpBitmap **bitmap)
Definition: image.c:1970
static GpStatus decode_image_tiff(IStream *stream, GpImage **image)
Definition: image.c:4109
static PropertyItem * get_gif_palette(IWICBitmapDecoder *decoder, IWICMetadataReader *reader)
Definition: image.c:3184
static GpStatus decode_image_wic(IStream *stream, REFGUID container, metadata_reader_func metadata_reader, GpImage **image)
Definition: image.c:3786
static GpStatus get_decoder_info_from_image(GpImage *image, const struct image_codec **result)
Definition: image.c:4333
static UINT vt_to_itemtype(UINT vt)
Definition: image.c:2590
GpStatus WINGDIPAPI GdipImageGetFrameDimensionsList(GpImage *image, GUID *dimensionIDs, UINT count)
Definition: image.c:2948
static const WCHAR gif_mimetype[]
Definition: image.c:4788
GpStatus WINGDIPAPI GdipBitmapUnlockBits(GpBitmap *bitmap, BitmapData *lockeddata)
Definition: image.c:1176
#define WMF_PLACEABLE_KEY
Definition: image.c:46
static GpStatus decode_frame_wic(IWICBitmapDecoder *decoder, BOOL force_conversion, UINT active_frame, metadata_reader_func metadata_reader, GpImage **image)
Definition: image.c:3632
static const WCHAR ico_mimetype[]
Definition: image.c:4823
static const BYTE gif_sig_pattern[12]
Definition: image.c:4790
GpStatus WINGDIPAPI GdipCreateBitmapFromHBITMAP(HBITMAP hbm, HPALETTE hpal, GpBitmap **bitmap)
Definition: image.c:5152
GpStatus WINGDIPAPI GdipLoadImageFromStreamICM(IStream *stream, GpImage **image)
Definition: image.c:4440
GpStatus WINGDIPAPI GdipSaveAdd(GpImage *image, GDIPCONST EncoderParameters *params)
Definition: image.c:4701
static const WCHAR jpeg_extension[]
Definition: image.c:4780
static GpStatus encode_image_wic(GpImage *image, IStream *stream, REFGUID container, GDIPCONST EncoderParameters *params)
Definition: image.c:4503
static LONG get_gif_frame_property(IWICBitmapFrameDecode *frame, const GUID *format, const WCHAR *property)
Definition: image.c:3254
static void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a, BYTE *row, UINT x)
Definition: image.c:439
static UINT get_palette_index(BYTE r, BYTE g, BYTE b, BYTE a, ColorPalette *palette)
Definition: image.c:358
static const WCHAR wmf_codecname[]
Definition: image.c:4807
GpStatus WINGDIPAPI GdipBitmapCreateApplyEffect(GpBitmap **inputBitmaps, INT numInputs, CGpEffect *effect, RECT *roi, RECT *outputRect, GpBitmap **outputBitmap, BOOL useAuxData, VOID **auxData, INT *auxDataSize)
Definition: image.c:145
static void gif_metadata_reader(GpBitmap *bitmap, IWICBitmapDecoder *decoder, UINT active_frame)
Definition: image.c:3294
static const WCHAR ico_codecname[]
Definition: image.c:4821
static HRESULT blit_gif_frame(GpBitmap *bitmap, IWICBitmapFrameDecode *frame, BOOL first_frame)
Definition: image.c:3834
static GpStatus propvariant_to_item(PROPVARIANT *value, PropertyItem *item, UINT size, PROPID id)
Definition: image.c:2619
static PropertyItem * get_property(IWICMetadataReader *reader, const GUID *guid, const WCHAR *prop_name)
Definition: image.c:3080
static const WCHAR emf_format[]
Definition: image.c:4803
static void getpixel_32bppPARGB(BYTE *r, BYTE *g, BYTE *b, BYTE *a, const BYTE *row, UINT x)
Definition: image.c:242
static const WCHAR gif_codecname[]
Definition: image.c:4786
static const BYTE emf_sig_mask[]
Definition: image.c:4805
GpStatus WINGDIPAPI GdipCreateMetafileFromWmf(HMETAFILE hwmf, BOOL delete, GDIPCONST WmfPlaceableFileHeader *placeable, GpMetafile **metafile)
Definition: metafile.c:3845
GpStatus WINGDIPAPI GdipCreateMetafileFromEmf(HENHMETAFILE hemf, BOOL delete, GpMetafile **metafile)
Definition: metafile.c:3804
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:86
HRESULT WINAPI PropVariantClear(PROPVARIANT *pvar)
Definition: ole2.c:2968
HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst)
Definition: info.c:2474
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
#define assert(x)
Definition: debug.h:53
#define BI_RGB
Definition: precomp.h:47
ULONG RGBQUAD
Definition: precomp.h:50
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
pKey DeleteObject()
void WINGDIPAPI GdipFree(void *ptr)
Definition: gdiplus.c:150
GpStatus hresult_to_status(HRESULT res)
Definition: gdiplus.c:312
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:435
void *WINGDIPAPI GdipAlloc(SIZE_T size)
Definition: gdiplus.c:142
REAL units_to_pixels(REAL units, GpUnit unit, REAL dpi)
Definition: gdiplus.c:327
#define GIF_DISPOSE_RESTORE_TO_PREV
#define GIF_DISPOSE_DO_NOT_DISPOSE
static INT gdip_round(REAL x)
static void image_unlock(GpImage *image, BOOL unlock)
GpStatus graphics_from_image(GpImage *image, GpGraphics **graphics) DECLSPEC_HIDDEN
Definition: graphics.c:2484
#define GIF_DISPOSE_UNSPECIFIED
static BOOL image_lock(GpImage *image, BOOL *unlock)
GpStatus METAFILE_GetGraphicsContext(GpMetafile *metafile, GpGraphics **result) DECLSPEC_HIDDEN
Definition: metafile.c:908
#define GIF_DISPOSE_RESTORE_TO_BKGND
void METAFILE_Free(GpMetafile *metafile) DECLSPEC_HIDDEN
Definition: metafile.c:590
HistogramFormat
@ HistogramFormatRGB
@ HistogramFormatPARGB
@ HistogramFormatB
@ HistogramFormatA
@ HistogramFormatARGB
@ HistogramFormatR
@ HistogramFormatGray
@ HistogramFormatG
ImageType
Definition: gdiplusenums.h:193
@ ImageTypeBitmap
Definition: gdiplusenums.h:195
@ ImageTypeMetafile
Definition: gdiplusenums.h:196
@ ImageFlagsHasRealDPI
Definition: gdiplusenums.h:343
@ ImageFlagsNone
Definition: gdiplusenums.h:333
@ ImageFlagsHasAlpha
Definition: gdiplusenums.h:335
@ ImageFlagsHasRealPixelSize
Definition: gdiplusenums.h:344
@ ImageFlagsReadOnly
Definition: gdiplusenums.h:345
@ ImageFlagsColorSpaceRGB
Definition: gdiplusenums.h:338
@ ImageFlagsColorSpaceGRAY
Definition: gdiplusenums.h:340
@ ImageCodecFlagsBuiltin
Definition: gdiplusenums.h:326
@ ImageCodecFlagsSupportBitmap
Definition: gdiplusenums.h:322
@ ImageCodecFlagsEncoder
Definition: gdiplusenums.h:320
@ ImageCodecFlagsDecoder
Definition: gdiplusenums.h:321
@ ImageCodecFlagsSupportVector
Definition: gdiplusenums.h:323
GpTestControlEnum
Definition: gdiplusenums.h:373
@ TestControlNoICM
Definition: gdiplusenums.h:375
@ TestControlForceBilinear
Definition: gdiplusenums.h:374
@ TestControlGetBuildNumber
Definition: gdiplusenums.h:376
Unit
Definition: gdiplusenums.h:26
@ UnitPixel
Definition: gdiplusenums.h:29
#define GDIPCONST
Definition: gdiplusflat.h:24
#define WINGDIPAPI
Definition: gdiplusflat.h:22
struct CGpEffect CGpEffect
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 PropertyTagTypeSLONG
#define PropertyTagTypeRational
#define PropertyTagTypeByte
#define PropertyTagEquipModel
#define PropertyTagGamma
#define PropertyTagTypeSRational
RotateFlipType
#define PropertyTagArtist
#define PropertyTagLoopCount
#define PropertyTagSoftwareUsed
#define PropertyTagTypeASCII
#define PropertyTagExifUserComment
DWORD ARGB
#define PixelFormat32bppPARGB
#define PixelFormat64bppARGB
#define PixelFormat32bppRGB
#define PixelFormatDontCare
#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 PixelFormat32bppCMYK
#define PixelFormatPAlpha
#define PixelFormat24bppRGB
#define PixelFormat16bppRGB565
#define PixelFormat1bppIndexed
#define PixelFormat32bppARGB
#define PixelFormatUndefined
#define PixelFormatGDI
#define PixelFormatAlpha
#define PixelFormat48bppRGB
struct GdiplusAbort GdiplusAbort
Definition: gdiplustypes.h:58
ImageAbort GetThumbnailImageAbort
Definition: gdiplustypes.h:57
Status
Definition: gdiplustypes.h:25
@ Ok
Definition: gdiplustypes.h:26
@ WrongState
Definition: gdiplustypes.h:34
@ ObjectBusy
Definition: gdiplustypes.h:30
@ InvalidParameter
Definition: gdiplustypes.h:28
@ OutOfMemory
Definition: gdiplustypes.h:29
@ PropertyNotFound
Definition: gdiplustypes.h:45
@ InsufficientBuffer
Definition: gdiplustypes.h:31
@ NotImplemented
Definition: gdiplustypes.h:32
@ GenericError
Definition: gdiplustypes.h:27
@ UnknownImageFormat
Definition: gdiplustypes.h:39
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
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
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
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
GLsizeiptr size
Definition: glext.h:5919
GLsizei stride
Definition: glext.h:5848
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
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 GLuint num
Definition: glext.h:9618
GLfloat param
Definition: glext.h:5796
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLenum target
Definition: glext.h:7315
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 * u
Definition: glfuncs.h:240
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
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
#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
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
int desired
Definition: jpeglib.h:1119
static const struct @445 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
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define BI_BITFIELDS
Definition: mmreg.h:507
#define for
Definition: utility.h:88
static PVOID ptr
Definition: dispmode.c:27
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static HICON
Definition: imagelist.c:84
#define comment(fmt, arg1)
Definition: rebar.c:820
static const char * dst_format
Definition: dib.c:1133
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static const unsigned char metafile[]
Definition: olepicture.c:138
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:1345
static ATOM item
Definition: dde.c:856
REFCLSID clsid
Definition: msctf.c:82
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
_In_ HBITMAP _In_ UINT _In_ UINT _Inout_ LPBITMAPINFO pbmi
Definition: ntgdi.h:2780
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
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
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
int seek(void *fd, ulong off, int mode)
Definition: pe.c:51
#define memset(x, y, z)
Definition: compat.h:39
static const WCHAR applicationW[]
Definition: actctx.c:699
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
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:1504
DWORD bV4V4Compression
Definition: wingdi.h:1497
LONG bV4Height
Definition: wingdi.h:1494
DWORD bV4RedMask
Definition: wingdi.h:1503
LONG bV4Width
Definition: wingdi.h:1493
WORD bV4BitCount
Definition: wingdi.h:1496
DWORD bV4BlueMask
Definition: wingdi.h:1505
DWORD bV4Size
Definition: wingdi.h:1492
UINT_PTR Reserved
PixelFormat PixelFormat
GpImage image
PixelFormat format
ColorPalette * palette
ImageType type
REAL Height
Definition: gdiplustypes.h:664
REAL X
Definition: gdiplustypes.h:661
REAL Width
Definition: gdiplustypes.h:663
REAL Y
Definition: gdiplustypes.h:662
INT Width
Definition: gdiplustypes.h:671
INT Height
Definition: gdiplustypes.h:672
INT X
Definition: gdiplustypes.h:669
INT Y
Definition: gdiplustypes.h:670
INT Height
Definition: wincodec.idl:301
INT Width
Definition: wincodec.idl:300
Definition: bl.h:1331
Definition: scsiwmi.h:51
HBITMAP hbmColor
Definition: winuser.h:3127
HBITMAP hbmMask
Definition: winuser.h:3126
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
Definition: uimain.c:89
uint32 width
Definition: uimain.c:91
uint32 height
Definition: uimain.c:92
char * value
Definition: compiler.c:67
Definition: main.c:439
select_image_func select_func
Definition: image.c:4268
decode_image_func decode_func
Definition: image.c:4267
encode_image_func encode_func
Definition: image.c:4266
ImageCodecInfo info
Definition: image.c:4265
const GUID * format
Definition: image.c:2902
const GUID * dimension
Definition: image.c:2903
Definition: name.c:39
Definition: reader.h:84
Definition: stat.h:55
Definition: ps.c:97
Definition: parse.h:23
ULONG biClrImportant
Definition: precomp.h:43
USHORT biBitCount
Definition: precomp.h:37
LONG biYPelsPerMeter
Definition: precomp.h:41
ULONG biCompression
Definition: precomp.h:38
LONG biXPelsPerMeter
Definition: precomp.h:40
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1476
DWORD dSignature
Definition: wingdi.h:2324
DWORD mtSize
Definition: wingdi.h:2313
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
Definition: pdh_main.c:94
int ret
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
UINT WINAPI GetPaletteEntries(HPALETTE hpal, UINT iStartIndex, UINT cEntries, LPPALETTEENTRY ppe)
Definition: palette.c:64
#define ZeroMemory
Definition: winbase.h:1712
@ WICBitmapEncoderNoCache
Definition: wincodec.idl:72
@ WICDecodeMetadataCacheOnLoad
Definition: wincodec.idl:29
WICBitmapPaletteType
Definition: wincodec.idl:90
@ WICBitmapPaletteTypeFixedHalftone256
Definition: wincodec.idl:101
@ WICBitmapPaletteTypeFixedGray256
Definition: wincodec.idl:104
@ WICBitmapPaletteTypeFixedBW
Definition: wincodec.idl:93
@ WICBitmapPaletteTypeFixedHalftone64
Definition: wincodec.idl:96
@ WICBitmapPaletteTypeFixedGray16
Definition: wincodec.idl:103
@ WICBitmapPaletteTypeFixedGray4
Definition: wincodec.idl:102
@ WICBitmapPaletteTypeFixedHalftone216
Definition: wincodec.idl:98
@ WICBitmapPaletteTypeFixedHalftone27
Definition: wincodec.idl:95
@ WICBitmapPaletteTypeFixedHalftone125
Definition: wincodec.idl:97
@ WICBitmapPaletteTypeFixedHalftone8
Definition: wincodec.idl:94
@ WICBitmapPaletteTypeFixedHalftone252
Definition: wincodec.idl:100
UINT32 WICColor
Definition: wincodec.idl:312
_In_ ULONG _In_ ULONG rgb
Definition: winddi.h:3521
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define WINCODEC_ERR_PALETTEUNAVAILABLE
Definition: winerror.h:3292
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
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
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)
UINT WINAPI GetEnhMetaFileHeader(_In_ HENHMETAFILE hemf, _In_ UINT nSize, _Out_writes_bytes_opt_(nSize) LPENHMETAHEADER lpEnhMetaHeader)
BOOL WINAPI DeleteDC(_In_ HDC)
BOOL WINAPI PlayEnhMetaFile(_In_ HDC, _In_ HENHMETAFILE, _In_ LPCRECT)
#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:2395
BOOL WINAPI GetIconInfo(_In_ HICON, _Out_ PICONINFO)
Definition: cursoricon.c:2045
#define LR_CREATEDIBSECTION
Definition: winuser.h:1098
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:2203
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
__wchar_t WCHAR
Definition: xmlstorage.h:180
unsigned char BYTE
Definition: xxhash.c:193