msvcp140: Add _ContextCallback implementation.
[wine.git] / dlls / windowscodecs / converter.c
blobe5d61e1991379d9afcc4291e6e1e6645d4009fd1
1 /*
2 * Copyright 2009 Vincent Povirk
3 * Copyright 2016 Dmitry Timoshkov
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.
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.
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
20 #include "config.h"
22 #include <stdarg.h>
23 #include <math.h>
25 #define COBJMACROS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "objbase.h"
31 #include "wincodecs_private.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
37 struct FormatConverter;
39 enum pixelformat {
40 format_1bppIndexed,
41 format_2bppIndexed,
42 format_4bppIndexed,
43 format_8bppIndexed,
44 format_BlackWhite,
45 format_2bppGray,
46 format_4bppGray,
47 format_8bppGray,
48 format_16bppGray,
49 format_16bppBGR555,
50 format_16bppBGR565,
51 format_16bppBGRA5551,
52 format_24bppBGR,
53 format_24bppRGB,
54 format_32bppGrayFloat,
55 format_32bppBGR,
56 format_32bppBGRA,
57 format_32bppPBGRA,
58 format_48bppRGB,
59 format_64bppRGBA,
60 format_32bppCMYK,
63 typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc,
64 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format);
66 struct pixelformatinfo {
67 enum pixelformat format;
68 const WICPixelFormatGUID *guid;
69 copyfunc copy_function;
72 typedef struct FormatConverter {
73 IWICFormatConverter IWICFormatConverter_iface;
74 LONG ref;
75 IWICBitmapSource *source;
76 const struct pixelformatinfo *dst_format, *src_format;
77 WICBitmapDitherType dither;
78 double alpha_threshold;
79 WICBitmapPaletteType palette_type;
80 CRITICAL_SECTION lock; /* must be held when initialized */
81 } FormatConverter;
83 /* https://www.w3.org/Graphics/Color/srgb */
84 static inline float from_sRGB_component(float f)
86 if (f <= 0.04045f) return f / 12.92f;
87 return powf((f + 0.055f) / 1.055f, 2.4f);
90 static inline float to_sRGB_component(float f)
92 if (f <= 0.0031308f) return 12.92f * f;
93 return 1.055f * powf(f, 1.0f/2.4f) - 0.055f;
96 #if 0 /* FIXME: enable once needed */
97 static void from_sRGB(BYTE *bgr)
99 float r, g, b;
101 r = bgr[2] / 255.0f;
102 g = bgr[1] / 255.0f;
103 b = bgr[0] / 255.0f;
105 r = from_sRGB_component(r);
106 g = from_sRGB_component(g);
107 b = from_sRGB_component(b);
109 bgr[2] = (BYTE)(r * 255.0f);
110 bgr[1] = (BYTE)(g * 255.0f);
111 bgr[0] = (BYTE)(b * 255.0f);
114 static void to_sRGB(BYTE *bgr)
116 float r, g, b;
118 r = bgr[2] / 255.0f;
119 g = bgr[1] / 255.0f;
120 b = bgr[0] / 255.0f;
122 r = to_sRGB_component(r);
123 g = to_sRGB_component(g);
124 b = to_sRGB_component(b);
126 bgr[2] = (BYTE)(r * 255.0f);
127 bgr[1] = (BYTE)(g * 255.0f);
128 bgr[0] = (BYTE)(b * 255.0f);
130 #endif
132 static inline FormatConverter *impl_from_IWICFormatConverter(IWICFormatConverter *iface)
134 return CONTAINING_RECORD(iface, FormatConverter, IWICFormatConverter_iface);
137 static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc,
138 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
140 switch (source_format)
142 case format_1bppIndexed:
143 case format_BlackWhite:
144 if (prc)
146 HRESULT res;
147 INT x, y;
148 BYTE *srcdata;
149 UINT srcstride, srcdatasize;
150 const BYTE *srcrow;
151 const BYTE *srcbyte;
152 BYTE *dstrow;
153 DWORD *dstpixel;
154 WICColor colors[2];
155 IWICPalette *palette;
156 UINT actualcolors;
158 res = PaletteImpl_Create(&palette);
159 if (FAILED(res)) return res;
161 if (source_format == format_1bppIndexed)
162 res = IWICBitmapSource_CopyPalette(This->source, palette);
163 else
164 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedBW, FALSE);
166 if (SUCCEEDED(res))
167 res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
169 IWICPalette_Release(palette);
170 if (FAILED(res)) return res;
172 srcstride = (prc->Width+7)/8;
173 srcdatasize = srcstride * prc->Height;
175 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
176 if (!srcdata) return E_OUTOFMEMORY;
178 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
180 if (SUCCEEDED(res))
182 srcrow = srcdata;
183 dstrow = pbBuffer;
184 for (y=0; y<prc->Height; y++) {
185 srcbyte = srcrow;
186 dstpixel=(DWORD*)dstrow;
187 for (x=0; x<prc->Width; x+=8) {
188 BYTE srcval;
189 srcval=*srcbyte++;
190 *dstpixel++ = colors[srcval>>7&1];
191 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>6&1];
192 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>5&1];
193 if (x+3 < prc->Width) *dstpixel++ = colors[srcval>>4&1];
194 if (x+4 < prc->Width) *dstpixel++ = colors[srcval>>3&1];
195 if (x+5 < prc->Width) *dstpixel++ = colors[srcval>>2&1];
196 if (x+6 < prc->Width) *dstpixel++ = colors[srcval>>1&1];
197 if (x+7 < prc->Width) *dstpixel++ = colors[srcval&1];
199 srcrow += srcstride;
200 dstrow += cbStride;
204 HeapFree(GetProcessHeap(), 0, srcdata);
206 return res;
208 return S_OK;
209 case format_2bppIndexed:
210 case format_2bppGray:
211 if (prc)
213 HRESULT res;
214 INT x, y;
215 BYTE *srcdata;
216 UINT srcstride, srcdatasize;
217 const BYTE *srcrow;
218 const BYTE *srcbyte;
219 BYTE *dstrow;
220 DWORD *dstpixel;
221 WICColor colors[4];
222 IWICPalette *palette;
223 UINT actualcolors;
225 res = PaletteImpl_Create(&palette);
226 if (FAILED(res)) return res;
228 if (source_format == format_2bppIndexed)
229 res = IWICBitmapSource_CopyPalette(This->source, palette);
230 else
231 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray4, FALSE);
233 if (SUCCEEDED(res))
234 res = IWICPalette_GetColors(palette, 4, colors, &actualcolors);
236 IWICPalette_Release(palette);
237 if (FAILED(res)) return res;
239 srcstride = (prc->Width+3)/4;
240 srcdatasize = srcstride * prc->Height;
242 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
243 if (!srcdata) return E_OUTOFMEMORY;
245 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
247 if (SUCCEEDED(res))
249 srcrow = srcdata;
250 dstrow = pbBuffer;
251 for (y=0; y<prc->Height; y++) {
252 srcbyte = srcrow;
253 dstpixel=(DWORD*)dstrow;
254 for (x=0; x<prc->Width; x+=4) {
255 BYTE srcval;
256 srcval=*srcbyte++;
257 *dstpixel++ = colors[srcval>>6];
258 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>4&0x3];
259 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>2&0x3];
260 if (x+3 < prc->Width) *dstpixel++ = colors[srcval&0x3];
262 srcrow += srcstride;
263 dstrow += cbStride;
267 HeapFree(GetProcessHeap(), 0, srcdata);
269 return res;
271 return S_OK;
272 case format_4bppIndexed:
273 case format_4bppGray:
274 if (prc)
276 HRESULT res;
277 INT x, y;
278 BYTE *srcdata;
279 UINT srcstride, srcdatasize;
280 const BYTE *srcrow;
281 const BYTE *srcbyte;
282 BYTE *dstrow;
283 DWORD *dstpixel;
284 WICColor colors[16];
285 IWICPalette *palette;
286 UINT actualcolors;
288 res = PaletteImpl_Create(&palette);
289 if (FAILED(res)) return res;
291 if (source_format == format_4bppIndexed)
292 res = IWICBitmapSource_CopyPalette(This->source, palette);
293 else
294 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray16, FALSE);
296 if (SUCCEEDED(res))
297 res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
299 IWICPalette_Release(palette);
300 if (FAILED(res)) return res;
302 srcstride = (prc->Width+1)/2;
303 srcdatasize = srcstride * prc->Height;
305 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
306 if (!srcdata) return E_OUTOFMEMORY;
308 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
310 if (SUCCEEDED(res))
312 srcrow = srcdata;
313 dstrow = pbBuffer;
314 for (y=0; y<prc->Height; y++) {
315 srcbyte = srcrow;
316 dstpixel=(DWORD*)dstrow;
317 for (x=0; x<prc->Width; x+=2) {
318 BYTE srcval;
319 srcval=*srcbyte++;
320 *dstpixel++ = colors[srcval>>4];
321 if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0xf];
323 srcrow += srcstride;
324 dstrow += cbStride;
328 HeapFree(GetProcessHeap(), 0, srcdata);
330 return res;
332 return S_OK;
333 case format_8bppGray:
334 if (prc)
336 HRESULT res;
337 INT x, y;
338 BYTE *srcdata;
339 UINT srcstride, srcdatasize;
340 const BYTE *srcrow;
341 const BYTE *srcbyte;
342 BYTE *dstrow;
343 DWORD *dstpixel;
345 srcstride = prc->Width;
346 srcdatasize = srcstride * prc->Height;
348 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
349 if (!srcdata) return E_OUTOFMEMORY;
351 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
353 if (SUCCEEDED(res))
355 srcrow = srcdata;
356 dstrow = pbBuffer;
357 for (y=0; y<prc->Height; y++) {
358 srcbyte = srcrow;
359 dstpixel=(DWORD*)dstrow;
360 for (x=0; x<prc->Width; x++)
362 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
363 srcbyte++;
365 srcrow += srcstride;
366 dstrow += cbStride;
370 HeapFree(GetProcessHeap(), 0, srcdata);
372 return res;
374 return S_OK;
375 case format_8bppIndexed:
376 if (prc)
378 HRESULT res;
379 INT x, y;
380 BYTE *srcdata;
381 UINT srcstride, srcdatasize;
382 const BYTE *srcrow;
383 const BYTE *srcbyte;
384 BYTE *dstrow;
385 DWORD *dstpixel;
386 WICColor colors[256];
387 IWICPalette *palette;
388 UINT actualcolors;
390 res = PaletteImpl_Create(&palette);
391 if (FAILED(res)) return res;
393 res = IWICBitmapSource_CopyPalette(This->source, palette);
394 if (SUCCEEDED(res))
395 res = IWICPalette_GetColors(palette, 256, colors, &actualcolors);
397 IWICPalette_Release(palette);
399 if (FAILED(res)) return res;
401 srcstride = prc->Width;
402 srcdatasize = srcstride * prc->Height;
404 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
405 if (!srcdata) return E_OUTOFMEMORY;
407 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
409 if (SUCCEEDED(res))
411 srcrow = srcdata;
412 dstrow = pbBuffer;
413 for (y=0; y<prc->Height; y++) {
414 srcbyte = srcrow;
415 dstpixel=(DWORD*)dstrow;
416 for (x=0; x<prc->Width; x++)
417 *dstpixel++ = colors[*srcbyte++];
418 srcrow += srcstride;
419 dstrow += cbStride;
423 HeapFree(GetProcessHeap(), 0, srcdata);
425 return res;
427 return S_OK;
428 case format_16bppGray:
429 if (prc)
431 HRESULT res;
432 INT x, y;
433 BYTE *srcdata;
434 UINT srcstride, srcdatasize;
435 const BYTE *srcrow;
436 const BYTE *srcbyte;
437 BYTE *dstrow;
438 DWORD *dstpixel;
440 srcstride = prc->Width * 2;
441 srcdatasize = srcstride * prc->Height;
443 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
444 if (!srcdata) return E_OUTOFMEMORY;
446 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
448 if (SUCCEEDED(res))
450 srcrow = srcdata;
451 dstrow = pbBuffer;
452 for (y=0; y<prc->Height; y++) {
453 srcbyte = srcrow;
454 dstpixel=(DWORD*)dstrow;
455 for (x=0; x<prc->Width; x++)
457 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
458 srcbyte+=2;
460 srcrow += srcstride;
461 dstrow += cbStride;
465 HeapFree(GetProcessHeap(), 0, srcdata);
467 return res;
469 return S_OK;
470 case format_16bppBGR555:
471 if (prc)
473 HRESULT res;
474 INT x, y;
475 BYTE *srcdata;
476 UINT srcstride, srcdatasize;
477 const BYTE *srcrow;
478 const WORD *srcpixel;
479 BYTE *dstrow;
480 DWORD *dstpixel;
482 srcstride = 2 * prc->Width;
483 srcdatasize = srcstride * prc->Height;
485 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
486 if (!srcdata) return E_OUTOFMEMORY;
488 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
490 if (SUCCEEDED(res))
492 srcrow = srcdata;
493 dstrow = pbBuffer;
494 for (y=0; y<prc->Height; y++) {
495 srcpixel=(const WORD*)srcrow;
496 dstpixel=(DWORD*)dstrow;
497 for (x=0; x<prc->Width; x++) {
498 WORD srcval;
499 srcval=*srcpixel++;
500 *dstpixel++=0xff000000 | /* constant 255 alpha */
501 ((srcval << 9) & 0xf80000) | /* r */
502 ((srcval << 4) & 0x070000) | /* r - 3 bits */
503 ((srcval << 6) & 0x00f800) | /* g */
504 ((srcval << 1) & 0x000700) | /* g - 3 bits */
505 ((srcval << 3) & 0x0000f8) | /* b */
506 ((srcval >> 2) & 0x000007); /* b - 3 bits */
508 srcrow += srcstride;
509 dstrow += cbStride;
513 HeapFree(GetProcessHeap(), 0, srcdata);
515 return res;
517 return S_OK;
518 case format_16bppBGR565:
519 if (prc)
521 HRESULT res;
522 INT x, y;
523 BYTE *srcdata;
524 UINT srcstride, srcdatasize;
525 const BYTE *srcrow;
526 const WORD *srcpixel;
527 BYTE *dstrow;
528 DWORD *dstpixel;
530 srcstride = 2 * prc->Width;
531 srcdatasize = srcstride * prc->Height;
533 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
534 if (!srcdata) return E_OUTOFMEMORY;
536 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
538 if (SUCCEEDED(res))
540 srcrow = srcdata;
541 dstrow = pbBuffer;
542 for (y=0; y<prc->Height; y++) {
543 srcpixel=(const WORD*)srcrow;
544 dstpixel=(DWORD*)dstrow;
545 for (x=0; x<prc->Width; x++) {
546 WORD srcval;
547 srcval=*srcpixel++;
548 *dstpixel++=0xff000000 | /* constant 255 alpha */
549 ((srcval << 8) & 0xf80000) | /* r */
550 ((srcval << 3) & 0x070000) | /* r - 3 bits */
551 ((srcval << 5) & 0x00fc00) | /* g */
552 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
553 ((srcval << 3) & 0x0000f8) | /* b */
554 ((srcval >> 2) & 0x000007); /* b - 3 bits */
556 srcrow += srcstride;
557 dstrow += cbStride;
561 HeapFree(GetProcessHeap(), 0, srcdata);
563 return res;
565 return S_OK;
566 case format_16bppBGRA5551:
567 if (prc)
569 HRESULT res;
570 INT x, y;
571 BYTE *srcdata;
572 UINT srcstride, srcdatasize;
573 const BYTE *srcrow;
574 const WORD *srcpixel;
575 BYTE *dstrow;
576 DWORD *dstpixel;
578 srcstride = 2 * prc->Width;
579 srcdatasize = srcstride * prc->Height;
581 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
582 if (!srcdata) return E_OUTOFMEMORY;
584 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
586 if (SUCCEEDED(res))
588 srcrow = srcdata;
589 dstrow = pbBuffer;
590 for (y=0; y<prc->Height; y++) {
591 srcpixel=(const WORD*)srcrow;
592 dstpixel=(DWORD*)dstrow;
593 for (x=0; x<prc->Width; x++) {
594 WORD srcval;
595 srcval=*srcpixel++;
596 *dstpixel++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
597 ((srcval << 9) & 0xf80000) | /* r */
598 ((srcval << 4) & 0x070000) | /* r - 3 bits */
599 ((srcval << 6) & 0x00f800) | /* g */
600 ((srcval << 1) & 0x000700) | /* g - 3 bits */
601 ((srcval << 3) & 0x0000f8) | /* b */
602 ((srcval >> 2) & 0x000007); /* b - 3 bits */
604 srcrow += srcstride;
605 dstrow += cbStride;
609 HeapFree(GetProcessHeap(), 0, srcdata);
611 return res;
613 return S_OK;
614 case format_24bppBGR:
615 if (prc)
617 HRESULT res;
618 INT x, y;
619 BYTE *srcdata;
620 UINT srcstride, srcdatasize;
621 const BYTE *srcrow;
622 const BYTE *srcpixel;
623 BYTE *dstrow;
624 BYTE *dstpixel;
626 srcstride = 3 * prc->Width;
627 srcdatasize = srcstride * prc->Height;
629 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
630 if (!srcdata) return E_OUTOFMEMORY;
632 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
634 if (SUCCEEDED(res))
636 srcrow = srcdata;
637 dstrow = pbBuffer;
638 for (y=0; y<prc->Height; y++) {
639 srcpixel=srcrow;
640 dstpixel=dstrow;
641 for (x=0; x<prc->Width; x++) {
642 *dstpixel++=*srcpixel++; /* blue */
643 *dstpixel++=*srcpixel++; /* green */
644 *dstpixel++=*srcpixel++; /* red */
645 *dstpixel++=255; /* alpha */
647 srcrow += srcstride;
648 dstrow += cbStride;
652 HeapFree(GetProcessHeap(), 0, srcdata);
654 return res;
656 return S_OK;
657 case format_24bppRGB:
658 if (prc)
660 HRESULT res;
661 INT x, y;
662 BYTE *srcdata;
663 UINT srcstride, srcdatasize;
664 const BYTE *srcrow;
665 const BYTE *srcpixel;
666 BYTE *dstrow;
667 BYTE *dstpixel;
668 BYTE tmppixel[3];
670 srcstride = 3 * prc->Width;
671 srcdatasize = srcstride * prc->Height;
673 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
674 if (!srcdata) return E_OUTOFMEMORY;
676 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
678 if (SUCCEEDED(res))
680 srcrow = srcdata;
681 dstrow = pbBuffer;
682 for (y=0; y<prc->Height; y++) {
683 srcpixel=srcrow;
684 dstpixel=dstrow;
685 for (x=0; x<prc->Width; x++) {
686 tmppixel[0]=*srcpixel++; /* red */
687 tmppixel[1]=*srcpixel++; /* green */
688 tmppixel[2]=*srcpixel++; /* blue */
690 *dstpixel++=tmppixel[2]; /* blue */
691 *dstpixel++=tmppixel[1]; /* green */
692 *dstpixel++=tmppixel[0]; /* red */
693 *dstpixel++=255; /* alpha */
695 srcrow += srcstride;
696 dstrow += cbStride;
700 HeapFree(GetProcessHeap(), 0, srcdata);
702 return res;
704 return S_OK;
705 case format_32bppBGR:
706 if (prc)
708 HRESULT res;
709 INT x, y;
711 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
712 if (FAILED(res)) return res;
714 /* set all alpha values to 255 */
715 for (y=0; y<prc->Height; y++)
716 for (x=0; x<prc->Width; x++)
717 pbBuffer[cbStride*y+4*x+3] = 0xff;
719 return S_OK;
720 case format_32bppBGRA:
721 if (prc)
722 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
723 return S_OK;
724 case format_32bppPBGRA:
725 if (prc)
727 HRESULT res;
728 INT x, y;
730 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
731 if (FAILED(res)) return res;
733 for (y=0; y<prc->Height; y++)
734 for (x=0; x<prc->Width; x++)
736 BYTE alpha = pbBuffer[cbStride*y+4*x+3];
737 if (alpha != 0 && alpha != 255)
739 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha;
740 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha;
741 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha;
745 return S_OK;
746 case format_48bppRGB:
747 if (prc)
749 HRESULT res;
750 INT x, y;
751 BYTE *srcdata;
752 UINT srcstride, srcdatasize;
753 const BYTE *srcrow;
754 const BYTE *srcpixel;
755 BYTE *dstrow;
756 DWORD *dstpixel;
758 srcstride = 6 * prc->Width;
759 srcdatasize = srcstride * prc->Height;
761 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
762 if (!srcdata) return E_OUTOFMEMORY;
764 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
766 if (SUCCEEDED(res))
768 srcrow = srcdata;
769 dstrow = pbBuffer;
770 for (y=0; y<prc->Height; y++) {
771 srcpixel=srcrow;
772 dstpixel=(DWORD*)dstrow;
773 for (x=0; x<prc->Width; x++) {
774 BYTE red, green, blue;
775 red = *srcpixel++; srcpixel++;
776 green = *srcpixel++; srcpixel++;
777 blue = *srcpixel++; srcpixel++;
778 *dstpixel++=0xff000000|red<<16|green<<8|blue;
780 srcrow += srcstride;
781 dstrow += cbStride;
785 HeapFree(GetProcessHeap(), 0, srcdata);
787 return res;
789 return S_OK;
790 case format_64bppRGBA:
791 if (prc)
793 HRESULT res;
794 INT x, y;
795 BYTE *srcdata;
796 UINT srcstride, srcdatasize;
797 const BYTE *srcrow;
798 const BYTE *srcpixel;
799 BYTE *dstrow;
800 DWORD *dstpixel;
802 srcstride = 8 * prc->Width;
803 srcdatasize = srcstride * prc->Height;
805 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
806 if (!srcdata) return E_OUTOFMEMORY;
808 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
810 if (SUCCEEDED(res))
812 srcrow = srcdata;
813 dstrow = pbBuffer;
814 for (y=0; y<prc->Height; y++) {
815 srcpixel=srcrow;
816 dstpixel=(DWORD*)dstrow;
817 for (x=0; x<prc->Width; x++) {
818 BYTE red, green, blue, alpha;
819 red = *srcpixel++; srcpixel++;
820 green = *srcpixel++; srcpixel++;
821 blue = *srcpixel++; srcpixel++;
822 alpha = *srcpixel++; srcpixel++;
823 *dstpixel++=alpha<<24|red<<16|green<<8|blue;
825 srcrow += srcstride;
826 dstrow += cbStride;
830 HeapFree(GetProcessHeap(), 0, srcdata);
832 return res;
834 return S_OK;
835 case format_32bppCMYK:
836 if (prc)
838 HRESULT res;
839 UINT x, y;
841 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
842 if (FAILED(res)) return res;
844 for (y=0; y<prc->Height; y++)
845 for (x=0; x<prc->Width; x++)
847 BYTE *pixel = pbBuffer+cbStride*y+4*x;
848 BYTE c=pixel[0], m=pixel[1], y=pixel[2], k=pixel[3];
849 pixel[0] = (255-y)*(255-k)/255; /* blue */
850 pixel[1] = (255-m)*(255-k)/255; /* green */
851 pixel[2] = (255-c)*(255-k)/255; /* red */
852 pixel[3] = 255; /* alpha */
855 return S_OK;
856 default:
857 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
861 static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc,
862 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
864 switch (source_format)
866 case format_32bppBGR:
867 case format_32bppBGRA:
868 case format_32bppPBGRA:
869 if (prc)
870 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
871 return S_OK;
872 default:
873 return copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
877 static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc,
878 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
880 HRESULT hr;
882 switch (source_format)
884 case format_32bppPBGRA:
885 if (prc)
886 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
887 return S_OK;
888 default:
889 hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
890 if (SUCCEEDED(hr) && prc)
892 INT x, y;
894 for (y=0; y<prc->Height; y++)
895 for (x=0; x<prc->Width; x++)
897 BYTE alpha = pbBuffer[cbStride*y+4*x+3];
898 if (alpha != 255)
900 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255;
901 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255;
902 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255;
906 return hr;
910 static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRect *prc,
911 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
913 HRESULT hr;
915 switch (source_format)
917 case format_24bppBGR:
918 case format_24bppRGB:
919 if (prc)
921 hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
922 if (SUCCEEDED(hr) && source_format == format_24bppRGB)
923 reverse_bgr8(3, pbBuffer, prc->Width, prc->Height, cbStride);
924 return hr;
926 return S_OK;
927 case format_32bppBGR:
928 case format_32bppBGRA:
929 case format_32bppPBGRA:
930 if (prc)
932 HRESULT res;
933 INT x, y;
934 BYTE *srcdata;
935 UINT srcstride, srcdatasize;
936 const BYTE *srcrow;
937 const BYTE *srcpixel;
938 BYTE *dstrow;
939 BYTE *dstpixel;
941 srcstride = 4 * prc->Width;
942 srcdatasize = srcstride * prc->Height;
944 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
945 if (!srcdata) return E_OUTOFMEMORY;
947 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
949 if (SUCCEEDED(res))
951 srcrow = srcdata;
952 dstrow = pbBuffer;
953 for (y=0; y<prc->Height; y++) {
954 srcpixel=srcrow;
955 dstpixel=dstrow;
956 for (x=0; x<prc->Width; x++) {
957 *dstpixel++=*srcpixel++; /* blue */
958 *dstpixel++=*srcpixel++; /* green */
959 *dstpixel++=*srcpixel++; /* red */
960 srcpixel++; /* alpha */
962 srcrow += srcstride;
963 dstrow += cbStride;
967 HeapFree(GetProcessHeap(), 0, srcdata);
969 return res;
971 return S_OK;
973 case format_32bppGrayFloat:
974 if (prc)
976 BYTE *srcdata;
977 UINT srcstride, srcdatasize;
979 srcstride = 4 * prc->Width;
980 srcdatasize = srcstride * prc->Height;
982 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
983 if (!srcdata) return E_OUTOFMEMORY;
985 hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
987 if (SUCCEEDED(hr))
989 INT x, y;
990 BYTE *src = srcdata, *dst = pbBuffer;
992 for (y = 0; y < prc->Height; y++)
994 float *gray_float = (float *)src;
995 BYTE *bgr = dst;
997 for (x = 0; x < prc->Width; x++)
999 BYTE gray = (BYTE)floorf(to_sRGB_component(gray_float[x]) * 255.0f + 0.51f);
1000 *bgr++ = gray;
1001 *bgr++ = gray;
1002 *bgr++ = gray;
1004 src += srcstride;
1005 dst += cbStride;
1009 HeapFree(GetProcessHeap(), 0, srcdata);
1011 return hr;
1013 return S_OK;
1015 default:
1016 FIXME("Unimplemented conversion path!\n");
1017 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1021 static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRect *prc,
1022 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1024 HRESULT hr;
1026 switch (source_format)
1028 case format_24bppBGR:
1029 case format_24bppRGB:
1030 if (prc)
1032 hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1033 if (SUCCEEDED(hr) && source_format == format_24bppBGR)
1034 reverse_bgr8(3, pbBuffer, prc->Width, prc->Height, cbStride);
1035 return hr;
1037 return S_OK;
1038 case format_32bppBGR:
1039 case format_32bppBGRA:
1040 case format_32bppPBGRA:
1041 if (prc)
1043 HRESULT res;
1044 INT x, y;
1045 BYTE *srcdata;
1046 UINT srcstride, srcdatasize;
1047 const BYTE *srcrow;
1048 const BYTE *srcpixel;
1049 BYTE *dstrow;
1050 BYTE *dstpixel;
1051 BYTE tmppixel[3];
1053 srcstride = 4 * prc->Width;
1054 srcdatasize = srcstride * prc->Height;
1056 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1057 if (!srcdata) return E_OUTOFMEMORY;
1059 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
1061 if (SUCCEEDED(res))
1063 srcrow = srcdata;
1064 dstrow = pbBuffer;
1065 for (y=0; y<prc->Height; y++) {
1066 srcpixel=srcrow;
1067 dstpixel=dstrow;
1068 for (x=0; x<prc->Width; x++) {
1069 tmppixel[0]=*srcpixel++; /* blue */
1070 tmppixel[1]=*srcpixel++; /* green */
1071 tmppixel[2]=*srcpixel++; /* red */
1072 srcpixel++; /* alpha */
1074 *dstpixel++=tmppixel[2]; /* red */
1075 *dstpixel++=tmppixel[1]; /* green */
1076 *dstpixel++=tmppixel[0]; /* blue */
1078 srcrow += srcstride;
1079 dstrow += cbStride;
1083 HeapFree(GetProcessHeap(), 0, srcdata);
1085 return res;
1087 return S_OK;
1088 default:
1089 FIXME("Unimplemented conversion path!\n");
1090 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1094 static HRESULT copypixels_to_32bppGrayFloat(struct FormatConverter *This, const WICRect *prc,
1095 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1097 HRESULT hr;
1099 switch (source_format)
1101 case format_32bppBGR:
1102 case format_32bppBGRA:
1103 case format_32bppPBGRA:
1104 case format_32bppGrayFloat:
1105 if (prc)
1107 hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1108 break;
1110 return S_OK;
1112 default:
1113 hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
1114 break;
1117 if (SUCCEEDED(hr) && prc && source_format != format_32bppGrayFloat)
1119 INT x, y;
1120 BYTE *p = pbBuffer;
1122 for (y = 0; y < prc->Height; y++)
1124 BYTE *bgr = p;
1125 for (x = 0; x < prc->Width; x++)
1127 float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f;
1128 *(float *)bgr = gray;
1129 bgr += 4;
1131 p += cbStride;
1134 return hr;
1137 static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRect *prc,
1138 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1140 HRESULT hr;
1141 BYTE *srcdata;
1142 UINT srcstride, srcdatasize;
1144 if (source_format == format_8bppGray)
1146 if (prc)
1147 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1149 return S_OK;
1152 srcstride = 3 * prc->Width;
1153 srcdatasize = srcstride * prc->Height;
1155 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1156 if (!srcdata) return E_OUTOFMEMORY;
1158 hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format);
1159 if (SUCCEEDED(hr) && prc)
1161 INT x, y;
1162 BYTE *src = srcdata, *dst = pbBuffer;
1164 for (y = 0; y < prc->Height; y++)
1166 BYTE *bgr = src;
1168 for (x = 0; x < prc->Width; x++)
1170 float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f;
1172 gray = to_sRGB_component(gray) * 255.0f;
1173 dst[x] = (BYTE)floorf(gray + 0.51f);
1174 bgr += 3;
1176 src += srcstride;
1177 dst += cbStride;
1181 HeapFree(GetProcessHeap(), 0, srcdata);
1182 return hr;
1185 static const struct pixelformatinfo supported_formats[] = {
1186 {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
1187 {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
1188 {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
1189 {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL},
1190 {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
1191 {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
1192 {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
1193 {format_8bppGray, &GUID_WICPixelFormat8bppGray, copypixels_to_8bppGray},
1194 {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL},
1195 {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
1196 {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
1197 {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL},
1198 {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, copypixels_to_24bppBGR},
1199 {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB},
1200 {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat},
1201 {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR},
1202 {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA},
1203 {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA},
1204 {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL},
1205 {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL},
1206 {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL},
1210 static const struct pixelformatinfo *get_formatinfo(const WICPixelFormatGUID *format)
1212 UINT i;
1214 for (i=0; supported_formats[i].guid; i++)
1215 if (IsEqualGUID(supported_formats[i].guid, format)) return &supported_formats[i];
1217 return NULL;
1220 static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid,
1221 void **ppv)
1223 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1224 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1226 if (!ppv) return E_INVALIDARG;
1228 if (IsEqualIID(&IID_IUnknown, iid) ||
1229 IsEqualIID(&IID_IWICBitmapSource, iid) ||
1230 IsEqualIID(&IID_IWICFormatConverter, iid))
1232 *ppv = &This->IWICFormatConverter_iface;
1234 else
1236 *ppv = NULL;
1237 return E_NOINTERFACE;
1240 IUnknown_AddRef((IUnknown*)*ppv);
1241 return S_OK;
1244 static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface)
1246 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1247 ULONG ref = InterlockedIncrement(&This->ref);
1249 TRACE("(%p) refcount=%u\n", iface, ref);
1251 return ref;
1254 static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
1256 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1257 ULONG ref = InterlockedDecrement(&This->ref);
1259 TRACE("(%p) refcount=%u\n", iface, ref);
1261 if (ref == 0)
1263 This->lock.DebugInfo->Spare[0] = 0;
1264 DeleteCriticalSection(&This->lock);
1265 if (This->source) IWICBitmapSource_Release(This->source);
1266 HeapFree(GetProcessHeap(), 0, This);
1269 return ref;
1272 static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface,
1273 UINT *puiWidth, UINT *puiHeight)
1275 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1277 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
1279 if (This->source)
1280 return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight);
1281 else
1282 return WINCODEC_ERR_NOTINITIALIZED;
1285 static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface,
1286 WICPixelFormatGUID *pPixelFormat)
1288 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1290 TRACE("(%p,%p)\n", iface, pPixelFormat);
1292 if (This->source)
1293 memcpy(pPixelFormat, This->dst_format->guid, sizeof(GUID));
1294 else
1295 return WINCODEC_ERR_NOTINITIALIZED;
1297 return S_OK;
1300 static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
1301 double *pDpiX, double *pDpiY)
1303 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1305 TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
1307 if (This->source)
1308 return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY);
1309 else
1310 return WINCODEC_ERR_NOTINITIALIZED;
1313 static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
1314 IWICPalette *pIPalette)
1316 FIXME("(%p,%p): stub\n", iface, pIPalette);
1317 return E_NOTIMPL;
1320 static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
1321 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
1323 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1324 WICRect rc;
1325 HRESULT hr;
1326 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
1328 if (This->source)
1330 if (!prc)
1332 UINT width, height;
1333 hr = IWICBitmapSource_GetSize(This->source, &width, &height);
1334 if (FAILED(hr)) return hr;
1335 rc.X = 0;
1336 rc.Y = 0;
1337 rc.Width = width;
1338 rc.Height = height;
1339 prc = &rc;
1342 return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize,
1343 pbBuffer, This->src_format->format);
1345 else
1346 return WINCODEC_ERR_NOTINITIALIZED;
1349 static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
1350 IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
1351 IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
1353 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1354 const struct pixelformatinfo *srcinfo, *dstinfo;
1355 static INT fixme=0;
1356 GUID srcFormat;
1357 HRESULT res=S_OK;
1359 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
1360 dither, pIPalette, alphaThresholdPercent, paletteTranslate);
1362 if (pIPalette && !fixme++) FIXME("ignoring palette\n");
1364 EnterCriticalSection(&This->lock);
1366 if (This->source)
1368 res = WINCODEC_ERR_WRONGSTATE;
1369 goto end;
1372 res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
1373 if (FAILED(res)) goto end;
1375 srcinfo = get_formatinfo(&srcFormat);
1376 if (!srcinfo)
1378 res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1379 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat));
1380 goto end;
1383 dstinfo = get_formatinfo(dstFormat);
1384 if (!dstinfo)
1386 res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1387 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat));
1388 goto end;
1391 if (dstinfo->copy_function)
1393 IWICBitmapSource_AddRef(pISource);
1394 This->src_format = srcinfo;
1395 This->dst_format = dstinfo;
1396 This->dither = dither;
1397 This->alpha_threshold = alphaThresholdPercent;
1398 This->palette_type = paletteTranslate;
1399 This->source = pISource;
1401 else
1403 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1404 res = WINCODEC_ERR_UNSUPPORTEDOPERATION;
1407 end:
1409 LeaveCriticalSection(&This->lock);
1411 return res;
1414 static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface,
1415 REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat,
1416 BOOL *pfCanConvert)
1418 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1419 const struct pixelformatinfo *srcinfo, *dstinfo;
1421 TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat),
1422 debugstr_guid(dstPixelFormat), pfCanConvert);
1424 srcinfo = get_formatinfo(srcPixelFormat);
1425 if (!srcinfo)
1427 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat));
1428 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1431 dstinfo = get_formatinfo(dstPixelFormat);
1432 if (!dstinfo)
1434 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat));
1435 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1438 if (dstinfo->copy_function &&
1439 SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format)))
1440 *pfCanConvert = TRUE;
1441 else
1443 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat));
1444 *pfCanConvert = FALSE;
1447 return S_OK;
1450 static const IWICFormatConverterVtbl FormatConverter_Vtbl = {
1451 FormatConverter_QueryInterface,
1452 FormatConverter_AddRef,
1453 FormatConverter_Release,
1454 FormatConverter_GetSize,
1455 FormatConverter_GetPixelFormat,
1456 FormatConverter_GetResolution,
1457 FormatConverter_CopyPalette,
1458 FormatConverter_CopyPixels,
1459 FormatConverter_Initialize,
1460 FormatConverter_CanConvert
1463 HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv)
1465 FormatConverter *This;
1466 HRESULT ret;
1468 TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1470 *ppv = NULL;
1472 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
1473 if (!This) return E_OUTOFMEMORY;
1475 This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
1476 This->ref = 1;
1477 This->source = NULL;
1478 InitializeCriticalSection(&This->lock);
1479 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
1481 ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface, iid, ppv);
1482 IWICFormatConverter_Release(&This->IWICFormatConverter_iface);
1484 return ret;