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
;
59 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
60 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
62 struct pixelformatinfo
{
63 enum pixelformat format
;
64 const WICPixelFormatGUID
*guid
;
65 copyfunc copy_function
;
68 typedef struct FormatConverter
{
69 const IWICFormatConverterVtbl
*lpVtbl
;
71 IWICBitmapSource
*source
;
72 const struct pixelformatinfo
*dst_format
, *src_format
;
73 WICBitmapDitherType dither
;
74 double alpha_threshold
;
75 WICBitmapPaletteType palette_type
;
76 CRITICAL_SECTION lock
; /* must be held when initialized */
79 static void make_grayscale_palette(WICColor
*colors
, UINT num_colors
)
82 for (i
=0; i
<num_colors
; i
++)
84 v
= i
* 255 / (num_colors
-1);
85 colors
[i
] = 0xff000000 | v
<<16 | v
<<8 | v
;
89 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
90 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
92 switch (source_format
)
94 case format_1bppIndexed
:
95 case format_BlackWhite
:
101 UINT srcstride
, srcdatasize
;
107 IWICPalette
*palette
;
110 if (source_format
== format_1bppIndexed
)
112 res
= PaletteImpl_Create(&palette
);
113 if (FAILED(res
)) return res
;
115 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
117 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
119 IWICPalette_Release(palette
);
121 if (FAILED(res
)) return res
;
125 colors
[0] = 0xff000000;
126 colors
[1] = 0xffffffff;
129 srcstride
= (prc
->Width
+7)/8;
130 srcdatasize
= srcstride
* prc
->Height
;
132 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
133 if (!srcdata
) return E_OUTOFMEMORY
;
135 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
141 for (y
=0; y
<prc
->Height
; y
++) {
142 srcbyte
=(const BYTE
*)srcrow
;
143 dstpixel
=(DWORD
*)dstrow
;
144 for (x
=0; x
<prc
->Width
; x
+=8) {
147 *dstpixel
++ = colors
[srcval
>>7&1];
148 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
149 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
150 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
151 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
152 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
153 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
154 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
161 HeapFree(GetProcessHeap(), 0, srcdata
);
166 case format_2bppIndexed
:
167 case format_2bppGray
:
173 UINT srcstride
, srcdatasize
;
179 IWICPalette
*palette
;
182 if (source_format
== format_2bppIndexed
)
184 res
= PaletteImpl_Create(&palette
);
185 if (FAILED(res
)) return res
;
187 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
189 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
191 IWICPalette_Release(palette
);
193 if (FAILED(res
)) return res
;
196 make_grayscale_palette(colors
, 4);
198 srcstride
= (prc
->Width
+3)/4;
199 srcdatasize
= srcstride
* prc
->Height
;
201 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
202 if (!srcdata
) return E_OUTOFMEMORY
;
204 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
210 for (y
=0; y
<prc
->Height
; y
++) {
211 srcbyte
=(const BYTE
*)srcrow
;
212 dstpixel
=(DWORD
*)dstrow
;
213 for (x
=0; x
<prc
->Width
; x
+=4) {
216 *dstpixel
++ = colors
[srcval
>>6];
217 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
218 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
219 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
226 HeapFree(GetProcessHeap(), 0, srcdata
);
231 case format_4bppIndexed
:
232 case format_4bppGray
:
238 UINT srcstride
, srcdatasize
;
244 IWICPalette
*palette
;
247 if (source_format
== format_4bppIndexed
)
249 res
= PaletteImpl_Create(&palette
);
250 if (FAILED(res
)) return res
;
252 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
254 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
256 IWICPalette_Release(palette
);
258 if (FAILED(res
)) return res
;
261 make_grayscale_palette(colors
, 16);
263 srcstride
= (prc
->Width
+1)/2;
264 srcdatasize
= srcstride
* prc
->Height
;
266 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
267 if (!srcdata
) return E_OUTOFMEMORY
;
269 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
275 for (y
=0; y
<prc
->Height
; y
++) {
276 srcbyte
=(const BYTE
*)srcrow
;
277 dstpixel
=(DWORD
*)dstrow
;
278 for (x
=0; x
<prc
->Width
; x
+=2) {
281 *dstpixel
++ = colors
[srcval
>>4];
282 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
289 HeapFree(GetProcessHeap(), 0, srcdata
);
294 case format_8bppGray
:
300 UINT srcstride
, srcdatasize
;
306 srcstride
= prc
->Width
;
307 srcdatasize
= srcstride
* prc
->Height
;
309 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
310 if (!srcdata
) return E_OUTOFMEMORY
;
312 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
318 for (y
=0; y
<prc
->Height
; y
++) {
319 srcbyte
=(const BYTE
*)srcrow
;
320 dstpixel
=(DWORD
*)dstrow
;
321 for (x
=0; x
<prc
->Width
; x
++)
323 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
331 HeapFree(GetProcessHeap(), 0, srcdata
);
336 case format_8bppIndexed
:
342 UINT srcstride
, srcdatasize
;
347 WICColor colors
[256];
348 IWICPalette
*palette
;
351 res
= PaletteImpl_Create(&palette
);
352 if (FAILED(res
)) return res
;
354 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
356 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
358 IWICPalette_Release(palette
);
360 if (FAILED(res
)) return res
;
362 srcstride
= prc
->Width
;
363 srcdatasize
= srcstride
* prc
->Height
;
365 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
366 if (!srcdata
) return E_OUTOFMEMORY
;
368 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
374 for (y
=0; y
<prc
->Height
; y
++) {
375 srcbyte
=(const BYTE
*)srcrow
;
376 dstpixel
=(DWORD
*)dstrow
;
377 for (x
=0; x
<prc
->Width
; x
++)
378 *dstpixel
++ = colors
[*srcbyte
++];
384 HeapFree(GetProcessHeap(), 0, srcdata
);
389 case format_16bppGray
:
395 UINT srcstride
, srcdatasize
;
401 srcstride
= prc
->Width
* 2;
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
);
413 for (y
=0; y
<prc
->Height
; y
++) {
414 srcbyte
=(const BYTE
*)srcrow
;
415 dstpixel
=(DWORD
*)dstrow
;
416 for (x
=0; x
<prc
->Width
; x
++)
418 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
426 HeapFree(GetProcessHeap(), 0, srcdata
);
431 case format_16bppBGR555
:
437 UINT srcstride
, srcdatasize
;
439 const WORD
*srcpixel
;
443 srcstride
= 2 * prc
->Width
;
444 srcdatasize
= srcstride
* prc
->Height
;
446 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
447 if (!srcdata
) return E_OUTOFMEMORY
;
449 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
455 for (y
=0; y
<prc
->Height
; y
++) {
456 srcpixel
=(const WORD
*)srcrow
;
457 dstpixel
=(DWORD
*)dstrow
;
458 for (x
=0; x
<prc
->Width
; x
++) {
461 *dstpixel
++=0xff000000 | /* constant 255 alpha */
462 ((srcval
<< 9) & 0xf80000) | /* r */
463 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
464 ((srcval
<< 6) & 0x00f800) | /* g */
465 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
466 ((srcval
<< 3) & 0x0000f8) | /* b */
467 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
474 HeapFree(GetProcessHeap(), 0, srcdata
);
479 case format_16bppBGR565
:
485 UINT srcstride
, srcdatasize
;
487 const WORD
*srcpixel
;
491 srcstride
= 2 * prc
->Width
;
492 srcdatasize
= srcstride
* prc
->Height
;
494 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
495 if (!srcdata
) return E_OUTOFMEMORY
;
497 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
503 for (y
=0; y
<prc
->Height
; y
++) {
504 srcpixel
=(const WORD
*)srcrow
;
505 dstpixel
=(DWORD
*)dstrow
;
506 for (x
=0; x
<prc
->Width
; x
++) {
509 *dstpixel
++=0xff000000 | /* constant 255 alpha */
510 ((srcval
<< 8) & 0xf80000) | /* r */
511 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
512 ((srcval
<< 5) & 0x00fc00) | /* g */
513 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
514 ((srcval
<< 3) & 0x0000f8) | /* b */
515 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
522 HeapFree(GetProcessHeap(), 0, srcdata
);
527 case format_16bppBGRA5551
:
533 UINT srcstride
, srcdatasize
;
535 const WORD
*srcpixel
;
539 srcstride
= 2 * prc
->Width
;
540 srcdatasize
= srcstride
* prc
->Height
;
542 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
543 if (!srcdata
) return E_OUTOFMEMORY
;
545 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
551 for (y
=0; y
<prc
->Height
; y
++) {
552 srcpixel
=(const WORD
*)srcrow
;
553 dstpixel
=(DWORD
*)dstrow
;
554 for (x
=0; x
<prc
->Width
; x
++) {
557 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
558 ((srcval
<< 9) & 0xf80000) | /* r */
559 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
560 ((srcval
<< 6) & 0x00f800) | /* g */
561 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
562 ((srcval
<< 3) & 0x0000f8) | /* b */
563 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
570 HeapFree(GetProcessHeap(), 0, srcdata
);
575 case format_24bppBGR
:
581 UINT srcstride
, srcdatasize
;
583 const BYTE
*srcpixel
;
587 srcstride
= 3 * prc
->Width
;
588 srcdatasize
= srcstride
* prc
->Height
;
590 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
591 if (!srcdata
) return E_OUTOFMEMORY
;
593 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
599 for (y
=0; y
<prc
->Height
; y
++) {
602 for (x
=0; x
<prc
->Width
; x
++) {
603 *dstpixel
++=*srcpixel
++; /* blue */
604 *dstpixel
++=*srcpixel
++; /* green */
605 *dstpixel
++=*srcpixel
++; /* red */
606 *dstpixel
++=255; /* alpha */
613 HeapFree(GetProcessHeap(), 0, srcdata
);
618 case format_32bppBGR
:
624 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
625 if (FAILED(res
)) return res
;
627 /* set all alpha values to 255 */
628 for (y
=0; y
<prc
->Height
; y
++)
629 for (x
=0; x
<prc
->Width
; x
++)
630 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
633 case format_32bppBGRA
:
635 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
637 case format_48bppRGB
:
643 UINT srcstride
, srcdatasize
;
645 const BYTE
*srcpixel
;
649 srcstride
= 6 * prc
->Width
;
650 srcdatasize
= srcstride
* prc
->Height
;
652 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
653 if (!srcdata
) return E_OUTOFMEMORY
;
655 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
661 for (y
=0; y
<prc
->Height
; y
++) {
663 dstpixel
=(DWORD
*)dstrow
;
664 for (x
=0; x
<prc
->Width
; x
++) {
665 BYTE red
, green
, blue
;
666 red
= *srcpixel
++; srcpixel
++;
667 green
= *srcpixel
++; srcpixel
++;
668 blue
= *srcpixel
++; srcpixel
++;
669 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
676 HeapFree(GetProcessHeap(), 0, srcdata
);
681 case format_64bppRGBA
:
687 UINT srcstride
, srcdatasize
;
689 const BYTE
*srcpixel
;
693 srcstride
= 8 * prc
->Width
;
694 srcdatasize
= srcstride
* prc
->Height
;
696 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
697 if (!srcdata
) return E_OUTOFMEMORY
;
699 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
705 for (y
=0; y
<prc
->Height
; y
++) {
707 dstpixel
=(DWORD
*)dstrow
;
708 for (x
=0; x
<prc
->Width
; x
++) {
709 BYTE red
, green
, blue
, alpha
;
710 red
= *srcpixel
++; srcpixel
++;
711 green
= *srcpixel
++; srcpixel
++;
712 blue
= *srcpixel
++; srcpixel
++;
713 alpha
= *srcpixel
++; srcpixel
++;
714 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
721 HeapFree(GetProcessHeap(), 0, srcdata
);
726 case format_32bppCMYK
:
732 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
733 if (FAILED(res
)) return res
;
735 for (y
=0; y
<prc
->Height
; y
++)
736 for (x
=0; x
<prc
->Width
; x
++)
738 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
739 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
740 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
741 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
742 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
743 pixel
[3] = 255; /* alpha */
748 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
752 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
753 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
755 switch (source_format
)
757 case format_32bppBGR
:
758 case format_32bppBGRA
:
760 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
763 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
767 static const struct pixelformatinfo supported_formats
[] = {
768 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
769 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
770 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
771 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
772 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
773 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
774 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
775 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
776 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
777 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
778 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
779 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
780 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, NULL
},
781 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
782 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
783 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
784 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
785 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
789 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
793 for (i
=0; supported_formats
[i
].guid
; i
++)
794 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
799 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
802 FormatConverter
*This
= (FormatConverter
*)iface
;
803 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
805 if (!ppv
) return E_INVALIDARG
;
807 if (IsEqualIID(&IID_IUnknown
, iid
) ||
808 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
809 IsEqualIID(&IID_IWICFormatConverter
, iid
))
816 return E_NOINTERFACE
;
819 IUnknown_AddRef((IUnknown
*)*ppv
);
823 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
825 FormatConverter
*This
= (FormatConverter
*)iface
;
826 ULONG ref
= InterlockedIncrement(&This
->ref
);
828 TRACE("(%p) refcount=%u\n", iface
, ref
);
833 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
835 FormatConverter
*This
= (FormatConverter
*)iface
;
836 ULONG ref
= InterlockedDecrement(&This
->ref
);
838 TRACE("(%p) refcount=%u\n", iface
, ref
);
842 This
->lock
.DebugInfo
->Spare
[0] = 0;
843 DeleteCriticalSection(&This
->lock
);
844 if (This
->source
) IWICBitmapSource_Release(This
->source
);
845 HeapFree(GetProcessHeap(), 0, This
);
851 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
852 UINT
*puiWidth
, UINT
*puiHeight
)
854 FormatConverter
*This
= (FormatConverter
*)iface
;
856 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
859 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
861 return WINCODEC_ERR_NOTINITIALIZED
;
864 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
865 WICPixelFormatGUID
*pPixelFormat
)
867 FormatConverter
*This
= (FormatConverter
*)iface
;
869 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
872 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
874 return WINCODEC_ERR_NOTINITIALIZED
;
879 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
880 double *pDpiX
, double *pDpiY
)
882 FormatConverter
*This
= (FormatConverter
*)iface
;
884 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
887 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
889 return WINCODEC_ERR_NOTINITIALIZED
;
892 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
893 IWICPalette
*pIPalette
)
895 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
899 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
900 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
902 FormatConverter
*This
= (FormatConverter
*)iface
;
905 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
912 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
913 if (FAILED(hr
)) return hr
;
921 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
922 pbBuffer
, This
->src_format
->format
);
925 return WINCODEC_ERR_NOTINITIALIZED
;
928 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
929 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
930 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
932 FormatConverter
*This
= (FormatConverter
*)iface
;
933 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
938 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
939 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
941 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
943 EnterCriticalSection(&This
->lock
);
947 res
= WINCODEC_ERR_WRONGSTATE
;
951 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
952 if (FAILED(res
)) goto end
;
954 srcinfo
= get_formatinfo(&srcFormat
);
957 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
961 dstinfo
= get_formatinfo(dstFormat
);
964 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
968 if (dstinfo
->copy_function
)
970 IWICBitmapSource_AddRef(pISource
);
971 This
->src_format
= srcinfo
;
972 This
->dst_format
= dstinfo
;
973 This
->dither
= dither
;
974 This
->alpha_threshold
= alphaThresholdPercent
;
975 This
->palette_type
= paletteTranslate
;
976 This
->source
= pISource
;
979 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
983 LeaveCriticalSection(&This
->lock
);
988 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
989 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
992 FormatConverter
*This
= (FormatConverter
*)iface
;
993 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
995 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
996 debugstr_guid(dstPixelFormat
), pfCanConvert
);
998 srcinfo
= get_formatinfo(srcPixelFormat
);
999 if (!srcinfo
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1001 dstinfo
= get_formatinfo(dstPixelFormat
);
1002 if (!dstinfo
) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1004 if (dstinfo
->copy_function
&&
1005 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1006 *pfCanConvert
= TRUE
;
1008 *pfCanConvert
= FALSE
;
1013 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1014 FormatConverter_QueryInterface
,
1015 FormatConverter_AddRef
,
1016 FormatConverter_Release
,
1017 FormatConverter_GetSize
,
1018 FormatConverter_GetPixelFormat
,
1019 FormatConverter_GetResolution
,
1020 FormatConverter_CopyPalette
,
1021 FormatConverter_CopyPixels
,
1022 FormatConverter_Initialize
,
1023 FormatConverter_CanConvert
1026 HRESULT
FormatConverter_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1028 FormatConverter
*This
;
1031 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1035 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1037 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1038 if (!This
) return E_OUTOFMEMORY
;
1040 This
->lpVtbl
= &FormatConverter_Vtbl
;
1042 This
->source
= NULL
;
1043 InitializeCriticalSection(&This
->lock
);
1044 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1046 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
1047 IUnknown_Release((IUnknown
*)This
);