2 * Copyright 2009 Vincent Povirk
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wincodecs_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
36 struct FormatConverter
;
58 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
59 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
61 struct pixelformatinfo
{
62 enum pixelformat format
;
63 const WICPixelFormatGUID
*guid
;
64 copyfunc copy_function
;
67 typedef struct FormatConverter
{
68 const IWICFormatConverterVtbl
*lpVtbl
;
70 IWICBitmapSource
*source
;
71 const struct pixelformatinfo
*dst_format
, *src_format
;
72 WICBitmapDitherType dither
;
73 double alpha_threshold
;
74 WICBitmapPaletteType palette_type
;
75 CRITICAL_SECTION lock
; /* must be held when initialized */
78 static void make_grayscale_palette(WICColor
*colors
, UINT num_colors
)
81 for (i
=0; i
<num_colors
; i
++)
83 v
= i
* 255 / (num_colors
-1);
84 colors
[i
] = 0xff000000 | v
<<16 | v
<<8 | v
;
88 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
89 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
91 switch (source_format
)
93 case format_1bppIndexed
:
94 case format_BlackWhite
:
100 UINT srcstride
, srcdatasize
;
106 IWICPalette
*palette
;
109 if (source_format
== format_1bppIndexed
)
111 res
= PaletteImpl_Create(&palette
);
112 if (FAILED(res
)) return res
;
114 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
116 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
118 IWICPalette_Release(palette
);
120 if (FAILED(res
)) return res
;
124 colors
[0] = 0xff000000;
125 colors
[1] = 0xffffffff;
128 srcstride
= (prc
->Width
+7)/8;
129 srcdatasize
= srcstride
* prc
->Height
;
131 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
132 if (!srcdata
) return E_OUTOFMEMORY
;
134 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
140 for (y
=0; y
<prc
->Height
; y
++) {
141 srcbyte
=(const BYTE
*)srcrow
;
142 dstpixel
=(DWORD
*)dstrow
;
143 for (x
=0; x
<prc
->Width
; x
+=8) {
146 *dstpixel
++ = colors
[srcval
>>7&1];
147 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
148 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
149 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
150 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
151 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
152 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
153 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
160 HeapFree(GetProcessHeap(), 0, srcdata
);
165 case format_2bppIndexed
:
166 case format_2bppGray
:
172 UINT srcstride
, srcdatasize
;
178 IWICPalette
*palette
;
181 if (source_format
== format_2bppIndexed
)
183 res
= PaletteImpl_Create(&palette
);
184 if (FAILED(res
)) return res
;
186 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
188 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
190 IWICPalette_Release(palette
);
192 if (FAILED(res
)) return res
;
195 make_grayscale_palette(colors
, 4);
197 srcstride
= (prc
->Width
+3)/4;
198 srcdatasize
= srcstride
* prc
->Height
;
200 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
201 if (!srcdata
) return E_OUTOFMEMORY
;
203 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
209 for (y
=0; y
<prc
->Height
; y
++) {
210 srcbyte
=(const BYTE
*)srcrow
;
211 dstpixel
=(DWORD
*)dstrow
;
212 for (x
=0; x
<prc
->Width
; x
+=4) {
215 *dstpixel
++ = colors
[srcval
>>6];
216 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
217 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
218 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
225 HeapFree(GetProcessHeap(), 0, srcdata
);
230 case format_4bppIndexed
:
231 case format_4bppGray
:
237 UINT srcstride
, srcdatasize
;
243 IWICPalette
*palette
;
246 if (source_format
== format_4bppIndexed
)
248 res
= PaletteImpl_Create(&palette
);
249 if (FAILED(res
)) return res
;
251 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
253 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
255 IWICPalette_Release(palette
);
257 if (FAILED(res
)) return res
;
260 make_grayscale_palette(colors
, 16);
262 srcstride
= (prc
->Width
+1)/2;
263 srcdatasize
= srcstride
* prc
->Height
;
265 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
266 if (!srcdata
) return E_OUTOFMEMORY
;
268 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
274 for (y
=0; y
<prc
->Height
; y
++) {
275 srcbyte
=(const BYTE
*)srcrow
;
276 dstpixel
=(DWORD
*)dstrow
;
277 for (x
=0; x
<prc
->Width
; x
+=2) {
280 *dstpixel
++ = colors
[srcval
>>4];
281 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
288 HeapFree(GetProcessHeap(), 0, srcdata
);
293 case format_8bppGray
:
299 UINT srcstride
, srcdatasize
;
305 srcstride
= prc
->Width
;
306 srcdatasize
= srcstride
* prc
->Height
;
308 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
309 if (!srcdata
) return E_OUTOFMEMORY
;
311 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
317 for (y
=0; y
<prc
->Height
; y
++) {
318 srcbyte
=(const BYTE
*)srcrow
;
319 dstpixel
=(DWORD
*)dstrow
;
320 for (x
=0; x
<prc
->Width
; x
++)
322 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
330 HeapFree(GetProcessHeap(), 0, srcdata
);
335 case format_8bppIndexed
:
341 UINT srcstride
, srcdatasize
;
346 WICColor colors
[256];
347 IWICPalette
*palette
;
350 res
= PaletteImpl_Create(&palette
);
351 if (FAILED(res
)) return res
;
353 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
355 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
357 IWICPalette_Release(palette
);
359 if (FAILED(res
)) return res
;
361 srcstride
= prc
->Width
;
362 srcdatasize
= srcstride
* prc
->Height
;
364 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
365 if (!srcdata
) return E_OUTOFMEMORY
;
367 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
373 for (y
=0; y
<prc
->Height
; y
++) {
374 srcbyte
=(const BYTE
*)srcrow
;
375 dstpixel
=(DWORD
*)dstrow
;
376 for (x
=0; x
<prc
->Width
; x
++)
377 *dstpixel
++ = colors
[*srcbyte
++];
383 HeapFree(GetProcessHeap(), 0, srcdata
);
388 case format_16bppGray
:
394 UINT srcstride
, srcdatasize
;
400 srcstride
= prc
->Width
* 2;
401 srcdatasize
= srcstride
* prc
->Height
;
403 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
404 if (!srcdata
) return E_OUTOFMEMORY
;
406 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
412 for (y
=0; y
<prc
->Height
; y
++) {
413 srcbyte
=(const BYTE
*)srcrow
;
414 dstpixel
=(DWORD
*)dstrow
;
415 for (x
=0; x
<prc
->Width
; x
++)
417 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
425 HeapFree(GetProcessHeap(), 0, srcdata
);
430 case format_16bppBGR555
:
436 UINT srcstride
, srcdatasize
;
438 const WORD
*srcpixel
;
442 srcstride
= 2 * prc
->Width
;
443 srcdatasize
= srcstride
* prc
->Height
;
445 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
446 if (!srcdata
) return E_OUTOFMEMORY
;
448 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
454 for (y
=0; y
<prc
->Height
; y
++) {
455 srcpixel
=(const WORD
*)srcrow
;
456 dstpixel
=(DWORD
*)dstrow
;
457 for (x
=0; x
<prc
->Width
; x
++) {
460 *dstpixel
++=0xff000000 | /* constant 255 alpha */
461 ((srcval
<< 9) & 0xf80000) | /* r */
462 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
463 ((srcval
<< 6) & 0x00f800) | /* g */
464 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
465 ((srcval
<< 3) & 0x0000f8) | /* b */
466 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
473 HeapFree(GetProcessHeap(), 0, srcdata
);
478 case format_16bppBGR565
:
484 UINT srcstride
, srcdatasize
;
486 const WORD
*srcpixel
;
490 srcstride
= 2 * prc
->Width
;
491 srcdatasize
= srcstride
* prc
->Height
;
493 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
494 if (!srcdata
) return E_OUTOFMEMORY
;
496 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
502 for (y
=0; y
<prc
->Height
; y
++) {
503 srcpixel
=(const WORD
*)srcrow
;
504 dstpixel
=(DWORD
*)dstrow
;
505 for (x
=0; x
<prc
->Width
; x
++) {
508 *dstpixel
++=0xff000000 | /* constant 255 alpha */
509 ((srcval
<< 8) & 0xf80000) | /* r */
510 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
511 ((srcval
<< 5) & 0x00fc00) | /* g */
512 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
513 ((srcval
<< 3) & 0x0000f8) | /* b */
514 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
521 HeapFree(GetProcessHeap(), 0, srcdata
);
526 case format_24bppBGR
:
532 UINT srcstride
, srcdatasize
;
534 const BYTE
*srcpixel
;
538 srcstride
= 3 * prc
->Width
;
539 srcdatasize
= srcstride
* prc
->Height
;
541 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
542 if (!srcdata
) return E_OUTOFMEMORY
;
544 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
550 for (y
=0; y
<prc
->Height
; y
++) {
553 for (x
=0; x
<prc
->Width
; x
++) {
554 *dstpixel
++=*srcpixel
++; /* blue */
555 *dstpixel
++=*srcpixel
++; /* green */
556 *dstpixel
++=*srcpixel
++; /* red */
557 *dstpixel
++=255; /* alpha */
564 HeapFree(GetProcessHeap(), 0, srcdata
);
569 case format_32bppBGR
:
575 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
576 if (FAILED(res
)) return res
;
578 /* set all alpha values to 255 */
579 for (y
=0; y
<prc
->Height
; y
++)
580 for (x
=0; x
<prc
->Width
; x
++)
581 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
584 case format_32bppBGRA
:
586 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
588 case format_48bppRGB
:
594 UINT srcstride
, srcdatasize
;
596 const BYTE
*srcpixel
;
600 srcstride
= 6 * prc
->Width
;
601 srcdatasize
= srcstride
* prc
->Height
;
603 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
604 if (!srcdata
) return E_OUTOFMEMORY
;
606 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
612 for (y
=0; y
<prc
->Height
; y
++) {
614 dstpixel
=(DWORD
*)dstrow
;
615 for (x
=0; x
<prc
->Width
; x
++) {
616 BYTE red
, green
, blue
;
617 red
= *srcpixel
++; srcpixel
++;
618 green
= *srcpixel
++; srcpixel
++;
619 blue
= *srcpixel
++; srcpixel
++;
620 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
627 HeapFree(GetProcessHeap(), 0, srcdata
);
632 case format_64bppRGBA
:
638 UINT srcstride
, srcdatasize
;
640 const BYTE
*srcpixel
;
644 srcstride
= 8 * prc
->Width
;
645 srcdatasize
= srcstride
* prc
->Height
;
647 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
648 if (!srcdata
) return E_OUTOFMEMORY
;
650 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
656 for (y
=0; y
<prc
->Height
; y
++) {
658 dstpixel
=(DWORD
*)dstrow
;
659 for (x
=0; x
<prc
->Width
; x
++) {
660 BYTE red
, green
, blue
, alpha
;
661 red
= *srcpixel
++; srcpixel
++;
662 green
= *srcpixel
++; srcpixel
++;
663 blue
= *srcpixel
++; srcpixel
++;
664 alpha
= *srcpixel
++; srcpixel
++;
665 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
672 HeapFree(GetProcessHeap(), 0, srcdata
);
677 case format_32bppCMYK
:
683 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
684 if (FAILED(res
)) return res
;
686 for (y
=0; y
<prc
->Height
; y
++)
687 for (x
=0; x
<prc
->Width
; x
++)
689 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
690 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
691 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
692 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
693 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
694 pixel
[3] = 255; /* alpha */
699 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
703 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
704 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
706 switch (source_format
)
708 case format_32bppBGR
:
709 case format_32bppBGRA
:
711 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
714 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
718 static const struct pixelformatinfo supported_formats
[] = {
719 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
720 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
721 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
722 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
723 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
724 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
725 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
726 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
727 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
728 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
729 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
730 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, NULL
},
731 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
732 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
733 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
734 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
735 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
739 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
743 for (i
=0; supported_formats
[i
].guid
; i
++)
744 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
749 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
752 FormatConverter
*This
= (FormatConverter
*)iface
;
753 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
755 if (!ppv
) return E_INVALIDARG
;
757 if (IsEqualIID(&IID_IUnknown
, iid
) ||
758 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
759 IsEqualIID(&IID_IWICFormatConverter
, iid
))
766 return E_NOINTERFACE
;
769 IUnknown_AddRef((IUnknown
*)*ppv
);
773 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
775 FormatConverter
*This
= (FormatConverter
*)iface
;
776 ULONG ref
= InterlockedIncrement(&This
->ref
);
778 TRACE("(%p) refcount=%u\n", iface
, ref
);
783 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
785 FormatConverter
*This
= (FormatConverter
*)iface
;
786 ULONG ref
= InterlockedDecrement(&This
->ref
);
788 TRACE("(%p) refcount=%u\n", iface
, ref
);
792 This
->lock
.DebugInfo
->Spare
[0] = 0;
793 DeleteCriticalSection(&This
->lock
);
794 if (This
->source
) IWICBitmapSource_Release(This
->source
);
795 HeapFree(GetProcessHeap(), 0, This
);
801 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
802 UINT
*puiWidth
, UINT
*puiHeight
)
804 FormatConverter
*This
= (FormatConverter
*)iface
;
806 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
809 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
811 return WINCODEC_ERR_NOTINITIALIZED
;
814 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
815 WICPixelFormatGUID
*pPixelFormat
)
817 FormatConverter
*This
= (FormatConverter
*)iface
;
819 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
822 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
824 return WINCODEC_ERR_NOTINITIALIZED
;
829 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
830 double *pDpiX
, double *pDpiY
)
832 FormatConverter
*This
= (FormatConverter
*)iface
;
834 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
837 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
839 return WINCODEC_ERR_NOTINITIALIZED
;
842 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
843 IWICPalette
*pIPalette
)
845 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
849 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
850 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
852 FormatConverter
*This
= (FormatConverter
*)iface
;
853 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
856 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
857 pbBuffer
, This
->src_format
->format
);
859 return WINCODEC_ERR_NOTINITIALIZED
;
862 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
863 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
864 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
866 FormatConverter
*This
= (FormatConverter
*)iface
;
867 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
872 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
873 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
875 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
877 EnterCriticalSection(&This
->lock
);
881 res
= WINCODEC_ERR_WRONGSTATE
;
885 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
886 if (FAILED(res
)) goto end
;
888 srcinfo
= get_formatinfo(&srcFormat
);
891 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
895 dstinfo
= get_formatinfo(dstFormat
);
898 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
902 if (dstinfo
->copy_function
)
904 IWICBitmapSource_AddRef(pISource
);
905 This
->src_format
= srcinfo
;
906 This
->dst_format
= dstinfo
;
907 This
->dither
= dither
;
908 This
->alpha_threshold
= alphaThresholdPercent
;
909 This
->palette_type
= paletteTranslate
;
910 This
->source
= pISource
;
913 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
917 LeaveCriticalSection(&This
->lock
);
922 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
923 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
926 FormatConverter
*This
= (FormatConverter
*)iface
;
927 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
929 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
930 debugstr_guid(dstPixelFormat
), pfCanConvert
);
932 srcinfo
= get_formatinfo(srcPixelFormat
);
933 if (!srcinfo
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
935 dstinfo
= get_formatinfo(dstPixelFormat
);
936 if (!dstinfo
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
938 if (dstinfo
->copy_function
&&
939 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
940 *pfCanConvert
= TRUE
;
942 *pfCanConvert
= FALSE
;
947 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
948 FormatConverter_QueryInterface
,
949 FormatConverter_AddRef
,
950 FormatConverter_Release
,
951 FormatConverter_GetSize
,
952 FormatConverter_GetPixelFormat
,
953 FormatConverter_GetResolution
,
954 FormatConverter_CopyPalette
,
955 FormatConverter_CopyPixels
,
956 FormatConverter_Initialize
,
957 FormatConverter_CanConvert
960 HRESULT
FormatConverter_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
962 FormatConverter
*This
;
965 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
969 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
971 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
972 if (!This
) return E_OUTOFMEMORY
;
974 This
->lpVtbl
= &FormatConverter_Vtbl
;
977 InitializeCriticalSection(&This
->lock
);
978 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
980 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
981 IUnknown_Release((IUnknown
*)This
);