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
;
57 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
58 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
60 struct pixelformatinfo
{
61 enum pixelformat format
;
62 const WICPixelFormatGUID
*guid
;
63 copyfunc copy_function
;
66 typedef struct FormatConverter
{
67 const IWICFormatConverterVtbl
*lpVtbl
;
69 IWICBitmapSource
*source
;
70 const struct pixelformatinfo
*dst_format
, *src_format
;
71 WICBitmapDitherType dither
;
72 double alpha_threshold
;
73 WICBitmapPaletteType palette_type
;
74 CRITICAL_SECTION lock
; /* must be held when initialized */
77 static void make_grayscale_palette(WICColor
*colors
, UINT num_colors
)
80 for (i
=0; i
<num_colors
; i
++)
82 v
= i
* 255 / (num_colors
-1);
83 colors
[i
] = 0xff000000 | v
<<16 | v
<<8 | v
;
87 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
88 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
90 switch (source_format
)
92 case format_1bppIndexed
:
93 case format_BlackWhite
:
99 UINT srcstride
, srcdatasize
;
105 IWICPalette
*palette
;
108 if (source_format
== format_1bppIndexed
)
110 res
= PaletteImpl_Create(&palette
);
111 if (FAILED(res
)) return res
;
113 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
115 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
117 IWICPalette_Release(palette
);
119 if (FAILED(res
)) return res
;
123 colors
[0] = 0xff000000;
124 colors
[1] = 0xffffffff;
127 srcstride
= (prc
->Width
+7)/8;
128 srcdatasize
= srcstride
* prc
->Height
;
130 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
131 if (!srcdata
) return E_OUTOFMEMORY
;
133 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
139 for (y
=0; y
<prc
->Height
; y
++) {
140 srcbyte
=(const BYTE
*)srcrow
;
141 dstpixel
=(DWORD
*)dstrow
;
142 for (x
=0; x
<prc
->Width
; x
+=8) {
145 *dstpixel
++ = colors
[srcval
>>7&1];
146 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
147 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
148 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
149 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
150 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
151 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
152 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
159 HeapFree(GetProcessHeap(), 0, srcdata
);
164 case format_2bppIndexed
:
165 case format_2bppGray
:
171 UINT srcstride
, srcdatasize
;
177 IWICPalette
*palette
;
180 if (source_format
== format_2bppIndexed
)
182 res
= PaletteImpl_Create(&palette
);
183 if (FAILED(res
)) return res
;
185 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
187 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
189 IWICPalette_Release(palette
);
191 if (FAILED(res
)) return res
;
194 make_grayscale_palette(colors
, 4);
196 srcstride
= (prc
->Width
+3)/4;
197 srcdatasize
= srcstride
* prc
->Height
;
199 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
200 if (!srcdata
) return E_OUTOFMEMORY
;
202 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
208 for (y
=0; y
<prc
->Height
; y
++) {
209 srcbyte
=(const BYTE
*)srcrow
;
210 dstpixel
=(DWORD
*)dstrow
;
211 for (x
=0; x
<prc
->Width
; x
+=4) {
214 *dstpixel
++ = colors
[srcval
>>6];
215 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
216 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
217 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
224 HeapFree(GetProcessHeap(), 0, srcdata
);
229 case format_4bppIndexed
:
230 case format_4bppGray
:
236 UINT srcstride
, srcdatasize
;
242 IWICPalette
*palette
;
245 if (source_format
== format_4bppIndexed
)
247 res
= PaletteImpl_Create(&palette
);
248 if (FAILED(res
)) return res
;
250 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
252 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
254 IWICPalette_Release(palette
);
256 if (FAILED(res
)) return res
;
259 make_grayscale_palette(colors
, 16);
261 srcstride
= (prc
->Width
+1)/2;
262 srcdatasize
= srcstride
* prc
->Height
;
264 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
265 if (!srcdata
) return E_OUTOFMEMORY
;
267 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
273 for (y
=0; y
<prc
->Height
; y
++) {
274 srcbyte
=(const BYTE
*)srcrow
;
275 dstpixel
=(DWORD
*)dstrow
;
276 for (x
=0; x
<prc
->Width
; x
+=2) {
279 *dstpixel
++ = colors
[srcval
>>4];
280 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
287 HeapFree(GetProcessHeap(), 0, srcdata
);
292 case format_8bppGray
:
298 UINT srcstride
, srcdatasize
;
304 srcstride
= prc
->Width
;
305 srcdatasize
= srcstride
* prc
->Height
;
307 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
308 if (!srcdata
) return E_OUTOFMEMORY
;
310 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
316 for (y
=0; y
<prc
->Height
; y
++) {
317 srcbyte
=(const BYTE
*)srcrow
;
318 dstpixel
=(DWORD
*)dstrow
;
319 for (x
=0; x
<prc
->Width
; x
++)
321 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
329 HeapFree(GetProcessHeap(), 0, srcdata
);
334 case format_8bppIndexed
:
340 UINT srcstride
, srcdatasize
;
345 WICColor colors
[256];
346 IWICPalette
*palette
;
349 res
= PaletteImpl_Create(&palette
);
350 if (FAILED(res
)) return res
;
352 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
354 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
356 IWICPalette_Release(palette
);
358 if (FAILED(res
)) return res
;
360 srcstride
= prc
->Width
;
361 srcdatasize
= srcstride
* prc
->Height
;
363 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
364 if (!srcdata
) return E_OUTOFMEMORY
;
366 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
372 for (y
=0; y
<prc
->Height
; y
++) {
373 srcbyte
=(const BYTE
*)srcrow
;
374 dstpixel
=(DWORD
*)dstrow
;
375 for (x
=0; x
<prc
->Width
; x
++)
376 *dstpixel
++ = colors
[*srcbyte
++];
382 HeapFree(GetProcessHeap(), 0, srcdata
);
387 case format_16bppGray
:
393 UINT srcstride
, srcdatasize
;
399 srcstride
= prc
->Width
* 2;
400 srcdatasize
= srcstride
* prc
->Height
;
402 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
403 if (!srcdata
) return E_OUTOFMEMORY
;
405 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
411 for (y
=0; y
<prc
->Height
; y
++) {
412 srcbyte
=(const BYTE
*)srcrow
;
413 dstpixel
=(DWORD
*)dstrow
;
414 for (x
=0; x
<prc
->Width
; x
++)
416 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
424 HeapFree(GetProcessHeap(), 0, srcdata
);
429 case format_16bppBGR555
:
435 UINT srcstride
, srcdatasize
;
437 const WORD
*srcpixel
;
441 srcstride
= 2 * prc
->Width
;
442 srcdatasize
= srcstride
* prc
->Height
;
444 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
445 if (!srcdata
) return E_OUTOFMEMORY
;
447 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
453 for (y
=0; y
<prc
->Height
; y
++) {
454 srcpixel
=(const WORD
*)srcrow
;
455 dstpixel
=(DWORD
*)dstrow
;
456 for (x
=0; x
<prc
->Width
; x
++) {
459 *dstpixel
++=0xff000000 | /* constant 255 alpha */
460 ((srcval
<< 9) & 0xf80000) | /* r */
461 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
462 ((srcval
<< 6) & 0x00f800) | /* g */
463 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
464 ((srcval
<< 3) & 0x0000f8) | /* b */
465 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
472 HeapFree(GetProcessHeap(), 0, srcdata
);
477 case format_16bppBGR565
:
483 UINT srcstride
, srcdatasize
;
485 const WORD
*srcpixel
;
489 srcstride
= 2 * prc
->Width
;
490 srcdatasize
= srcstride
* prc
->Height
;
492 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
493 if (!srcdata
) return E_OUTOFMEMORY
;
495 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
501 for (y
=0; y
<prc
->Height
; y
++) {
502 srcpixel
=(const WORD
*)srcrow
;
503 dstpixel
=(DWORD
*)dstrow
;
504 for (x
=0; x
<prc
->Width
; x
++) {
507 *dstpixel
++=0xff000000 | /* constant 255 alpha */
508 ((srcval
<< 8) & 0xf80000) | /* r */
509 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
510 ((srcval
<< 5) & 0x00fc00) | /* g */
511 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
512 ((srcval
<< 3) & 0x0000f8) | /* b */
513 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
520 HeapFree(GetProcessHeap(), 0, srcdata
);
525 case format_24bppBGR
:
531 UINT srcstride
, srcdatasize
;
533 const BYTE
*srcpixel
;
537 srcstride
= 3 * prc
->Width
;
538 srcdatasize
= srcstride
* prc
->Height
;
540 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
541 if (!srcdata
) return E_OUTOFMEMORY
;
543 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
549 for (y
=0; y
<prc
->Height
; y
++) {
552 for (x
=0; x
<prc
->Width
; x
++) {
553 *dstpixel
++=*srcpixel
++; /* blue */
554 *dstpixel
++=*srcpixel
++; /* green */
555 *dstpixel
++=*srcpixel
++; /* red */
556 *dstpixel
++=255; /* alpha */
563 HeapFree(GetProcessHeap(), 0, srcdata
);
568 case format_32bppBGR
:
574 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
575 if (FAILED(res
)) return res
;
577 /* set all alpha values to 255 */
578 for (y
=0; y
<prc
->Height
; y
++)
579 for (x
=0; x
<prc
->Width
; x
++)
580 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
583 case format_32bppBGRA
:
585 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
587 case format_48bppRGB
:
593 UINT srcstride
, srcdatasize
;
595 const BYTE
*srcpixel
;
599 srcstride
= 6 * prc
->Width
;
600 srcdatasize
= srcstride
* prc
->Height
;
602 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
603 if (!srcdata
) return E_OUTOFMEMORY
;
605 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
611 for (y
=0; y
<prc
->Height
; y
++) {
613 dstpixel
=(DWORD
*)dstrow
;
614 for (x
=0; x
<prc
->Width
; x
++) {
615 BYTE red
, green
, blue
;
616 red
= *srcpixel
++; srcpixel
++;
617 green
= *srcpixel
++; srcpixel
++;
618 blue
= *srcpixel
++; srcpixel
++;
619 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
626 HeapFree(GetProcessHeap(), 0, srcdata
);
631 case format_64bppRGBA
:
637 UINT srcstride
, srcdatasize
;
639 const BYTE
*srcpixel
;
643 srcstride
= 8 * prc
->Width
;
644 srcdatasize
= srcstride
* prc
->Height
;
646 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
647 if (!srcdata
) return E_OUTOFMEMORY
;
649 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
655 for (y
=0; y
<prc
->Height
; y
++) {
657 dstpixel
=(DWORD
*)dstrow
;
658 for (x
=0; x
<prc
->Width
; x
++) {
659 BYTE red
, green
, blue
, alpha
;
660 red
= *srcpixel
++; srcpixel
++;
661 green
= *srcpixel
++; srcpixel
++;
662 blue
= *srcpixel
++; srcpixel
++;
663 alpha
= *srcpixel
++; srcpixel
++;
664 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
671 HeapFree(GetProcessHeap(), 0, srcdata
);
677 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
681 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
682 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
684 switch (source_format
)
686 case format_32bppBGR
:
687 case format_32bppBGRA
:
689 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
692 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
696 static const struct pixelformatinfo supported_formats
[] = {
697 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
698 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
699 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
700 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
701 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
702 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
703 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
704 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
705 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
706 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
707 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
708 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, NULL
},
709 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
710 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
711 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
712 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
716 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
720 for (i
=0; supported_formats
[i
].guid
; i
++)
721 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
726 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
729 FormatConverter
*This
= (FormatConverter
*)iface
;
730 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
732 if (!ppv
) return E_INVALIDARG
;
734 if (IsEqualIID(&IID_IUnknown
, iid
) ||
735 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
736 IsEqualIID(&IID_IWICFormatConverter
, iid
))
743 return E_NOINTERFACE
;
746 IUnknown_AddRef((IUnknown
*)*ppv
);
750 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
752 FormatConverter
*This
= (FormatConverter
*)iface
;
753 ULONG ref
= InterlockedIncrement(&This
->ref
);
755 TRACE("(%p) refcount=%u\n", iface
, ref
);
760 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
762 FormatConverter
*This
= (FormatConverter
*)iface
;
763 ULONG ref
= InterlockedDecrement(&This
->ref
);
765 TRACE("(%p) refcount=%u\n", iface
, ref
);
769 This
->lock
.DebugInfo
->Spare
[0] = 0;
770 DeleteCriticalSection(&This
->lock
);
771 if (This
->source
) IWICBitmapSource_Release(This
->source
);
772 HeapFree(GetProcessHeap(), 0, This
);
778 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
779 UINT
*puiWidth
, UINT
*puiHeight
)
781 FormatConverter
*This
= (FormatConverter
*)iface
;
783 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
786 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
788 return WINCODEC_ERR_NOTINITIALIZED
;
791 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
792 WICPixelFormatGUID
*pPixelFormat
)
794 FormatConverter
*This
= (FormatConverter
*)iface
;
796 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
799 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
801 return WINCODEC_ERR_NOTINITIALIZED
;
806 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
807 double *pDpiX
, double *pDpiY
)
809 FormatConverter
*This
= (FormatConverter
*)iface
;
811 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
814 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
816 return WINCODEC_ERR_NOTINITIALIZED
;
819 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
820 IWICPalette
*pIPalette
)
822 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
826 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
827 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
829 FormatConverter
*This
= (FormatConverter
*)iface
;
830 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
833 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
834 pbBuffer
, This
->src_format
->format
);
836 return WINCODEC_ERR_NOTINITIALIZED
;
839 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
840 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
841 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
843 FormatConverter
*This
= (FormatConverter
*)iface
;
844 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
849 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
850 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
852 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
854 EnterCriticalSection(&This
->lock
);
858 res
= WINCODEC_ERR_WRONGSTATE
;
862 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
863 if (FAILED(res
)) goto end
;
865 srcinfo
= get_formatinfo(&srcFormat
);
868 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
872 dstinfo
= get_formatinfo(dstFormat
);
875 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
879 if (dstinfo
->copy_function
)
881 IWICBitmapSource_AddRef(pISource
);
882 This
->src_format
= srcinfo
;
883 This
->dst_format
= dstinfo
;
884 This
->dither
= dither
;
885 This
->alpha_threshold
= alphaThresholdPercent
;
886 This
->palette_type
= paletteTranslate
;
887 This
->source
= pISource
;
890 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
894 LeaveCriticalSection(&This
->lock
);
899 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
900 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
903 FormatConverter
*This
= (FormatConverter
*)iface
;
904 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
906 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
907 debugstr_guid(dstPixelFormat
), pfCanConvert
);
909 srcinfo
= get_formatinfo(srcPixelFormat
);
910 if (!srcinfo
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
912 dstinfo
= get_formatinfo(dstPixelFormat
);
913 if (!dstinfo
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
915 if (dstinfo
->copy_function
&&
916 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
917 *pfCanConvert
= TRUE
;
919 *pfCanConvert
= FALSE
;
924 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
925 FormatConverter_QueryInterface
,
926 FormatConverter_AddRef
,
927 FormatConverter_Release
,
928 FormatConverter_GetSize
,
929 FormatConverter_GetPixelFormat
,
930 FormatConverter_GetResolution
,
931 FormatConverter_CopyPalette
,
932 FormatConverter_CopyPixels
,
933 FormatConverter_Initialize
,
934 FormatConverter_CanConvert
937 HRESULT
FormatConverter_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
939 FormatConverter
*This
;
942 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
946 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
948 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
949 if (!This
) return E_OUTOFMEMORY
;
951 This
->lpVtbl
= &FormatConverter_Vtbl
;
954 InitializeCriticalSection(&This
->lock
);
955 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
957 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
958 IUnknown_Release((IUnknown
*)This
);