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
31 #include "wincodecs_private.h"
33 #include "wine/heap.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
38 struct FormatConverter
;
55 format_32bppGrayFloat
,
67 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
68 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
70 struct pixelformatinfo
{
71 enum pixelformat format
;
72 const WICPixelFormatGUID
*guid
;
73 copyfunc copy_function
;
76 typedef struct FormatConverter
{
77 IWICFormatConverter IWICFormatConverter_iface
;
79 IWICBitmapSource
*source
;
80 const struct pixelformatinfo
*dst_format
, *src_format
;
81 WICBitmapDitherType dither
;
82 double alpha_threshold
;
84 CRITICAL_SECTION lock
; /* must be held when initialized */
87 /* https://www.w3.org/Graphics/Color/srgb */
89 static inline float from_sRGB_component(float f
)
91 if (f
<= 0.04045f
) return f
/ 12.92f
;
92 return powf((f
+ 0.055f
) / 1.055f
, 2.4f
);
96 static inline float to_sRGB_component(float f
)
98 if (f
<= 0.0031308f
) return 12.92f
* f
;
99 return 1.055f
* powf(f
, 1.0f
/2.4f
) - 0.055f
;
102 #if 0 /* FIXME: enable once needed */
103 static void from_sRGB(BYTE
*bgr
)
111 r
= from_sRGB_component(r
);
112 g
= from_sRGB_component(g
);
113 b
= from_sRGB_component(b
);
115 bgr
[2] = (BYTE
)(r
* 255.0f
);
116 bgr
[1] = (BYTE
)(g
* 255.0f
);
117 bgr
[0] = (BYTE
)(b
* 255.0f
);
120 static void to_sRGB(BYTE
*bgr
)
128 r
= to_sRGB_component(r
);
129 g
= to_sRGB_component(g
);
130 b
= to_sRGB_component(b
);
132 bgr
[2] = (BYTE
)(r
* 255.0f
);
133 bgr
[1] = (BYTE
)(g
* 255.0f
);
134 bgr
[0] = (BYTE
)(b
* 255.0f
);
138 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
140 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
143 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
144 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
146 switch (source_format
)
148 case format_1bppIndexed
:
149 case format_BlackWhite
:
155 UINT srcstride
, srcdatasize
;
161 IWICPalette
*palette
;
164 res
= PaletteImpl_Create(&palette
);
165 if (FAILED(res
)) return res
;
167 if (source_format
== format_1bppIndexed
)
168 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
170 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
173 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
175 IWICPalette_Release(palette
);
176 if (FAILED(res
)) return res
;
178 srcstride
= (prc
->Width
+7)/8;
179 srcdatasize
= srcstride
* prc
->Height
;
181 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
182 if (!srcdata
) return E_OUTOFMEMORY
;
184 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
190 for (y
=0; y
<prc
->Height
; y
++) {
192 dstpixel
=(DWORD
*)dstrow
;
193 for (x
=0; x
<prc
->Width
; x
+=8) {
196 *dstpixel
++ = colors
[srcval
>>7&1];
197 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
198 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
199 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
200 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
201 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
202 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
203 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
210 HeapFree(GetProcessHeap(), 0, srcdata
);
215 case format_2bppIndexed
:
216 case format_2bppGray
:
222 UINT srcstride
, srcdatasize
;
228 IWICPalette
*palette
;
231 res
= PaletteImpl_Create(&palette
);
232 if (FAILED(res
)) return res
;
234 if (source_format
== format_2bppIndexed
)
235 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
237 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
240 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
242 IWICPalette_Release(palette
);
243 if (FAILED(res
)) return res
;
245 srcstride
= (prc
->Width
+3)/4;
246 srcdatasize
= srcstride
* prc
->Height
;
248 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
249 if (!srcdata
) return E_OUTOFMEMORY
;
251 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
257 for (y
=0; y
<prc
->Height
; y
++) {
259 dstpixel
=(DWORD
*)dstrow
;
260 for (x
=0; x
<prc
->Width
; x
+=4) {
263 *dstpixel
++ = colors
[srcval
>>6];
264 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
265 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
266 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
273 HeapFree(GetProcessHeap(), 0, srcdata
);
278 case format_4bppIndexed
:
279 case format_4bppGray
:
285 UINT srcstride
, srcdatasize
;
291 IWICPalette
*palette
;
294 res
= PaletteImpl_Create(&palette
);
295 if (FAILED(res
)) return res
;
297 if (source_format
== format_4bppIndexed
)
298 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
300 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
303 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
305 IWICPalette_Release(palette
);
306 if (FAILED(res
)) return res
;
308 srcstride
= (prc
->Width
+1)/2;
309 srcdatasize
= srcstride
* prc
->Height
;
311 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
312 if (!srcdata
) return E_OUTOFMEMORY
;
314 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
320 for (y
=0; y
<prc
->Height
; y
++) {
322 dstpixel
=(DWORD
*)dstrow
;
323 for (x
=0; x
<prc
->Width
; x
+=2) {
326 *dstpixel
++ = colors
[srcval
>>4];
327 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
334 HeapFree(GetProcessHeap(), 0, srcdata
);
339 case format_8bppGray
:
345 UINT srcstride
, srcdatasize
;
351 srcstride
= prc
->Width
;
352 srcdatasize
= srcstride
* prc
->Height
;
354 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
355 if (!srcdata
) return E_OUTOFMEMORY
;
357 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
363 for (y
=0; y
<prc
->Height
; y
++) {
365 dstpixel
=(DWORD
*)dstrow
;
366 for (x
=0; x
<prc
->Width
; x
++)
368 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
376 HeapFree(GetProcessHeap(), 0, srcdata
);
381 case format_8bppIndexed
:
387 UINT srcstride
, srcdatasize
;
392 WICColor colors
[256];
393 IWICPalette
*palette
;
396 res
= PaletteImpl_Create(&palette
);
397 if (FAILED(res
)) return res
;
399 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
401 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
403 IWICPalette_Release(palette
);
405 if (FAILED(res
)) return res
;
407 srcstride
= prc
->Width
;
408 srcdatasize
= srcstride
* prc
->Height
;
410 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
411 if (!srcdata
) return E_OUTOFMEMORY
;
413 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
419 for (y
=0; y
<prc
->Height
; y
++) {
421 dstpixel
=(DWORD
*)dstrow
;
422 for (x
=0; x
<prc
->Width
; x
++)
423 *dstpixel
++ = colors
[*srcbyte
++];
429 HeapFree(GetProcessHeap(), 0, srcdata
);
434 case format_16bppGray
:
440 UINT srcstride
, srcdatasize
;
446 srcstride
= prc
->Width
* 2;
447 srcdatasize
= srcstride
* prc
->Height
;
449 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
450 if (!srcdata
) return E_OUTOFMEMORY
;
452 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
458 for (y
=0; y
<prc
->Height
; y
++) {
460 dstpixel
=(DWORD
*)dstrow
;
461 for (x
=0; x
<prc
->Width
; x
++)
463 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
471 HeapFree(GetProcessHeap(), 0, srcdata
);
476 case format_16bppBGR555
:
482 UINT srcstride
, srcdatasize
;
484 const WORD
*srcpixel
;
488 srcstride
= 2 * prc
->Width
;
489 srcdatasize
= srcstride
* prc
->Height
;
491 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
492 if (!srcdata
) return E_OUTOFMEMORY
;
494 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
500 for (y
=0; y
<prc
->Height
; y
++) {
501 srcpixel
=(const WORD
*)srcrow
;
502 dstpixel
=(DWORD
*)dstrow
;
503 for (x
=0; x
<prc
->Width
; x
++) {
506 *dstpixel
++=0xff000000 | /* constant 255 alpha */
507 ((srcval
<< 9) & 0xf80000) | /* r */
508 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
509 ((srcval
<< 6) & 0x00f800) | /* g */
510 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
511 ((srcval
<< 3) & 0x0000f8) | /* b */
512 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
519 HeapFree(GetProcessHeap(), 0, srcdata
);
524 case format_16bppBGR565
:
530 UINT srcstride
, srcdatasize
;
532 const WORD
*srcpixel
;
536 srcstride
= 2 * prc
->Width
;
537 srcdatasize
= srcstride
* prc
->Height
;
539 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
540 if (!srcdata
) return E_OUTOFMEMORY
;
542 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
548 for (y
=0; y
<prc
->Height
; y
++) {
549 srcpixel
=(const WORD
*)srcrow
;
550 dstpixel
=(DWORD
*)dstrow
;
551 for (x
=0; x
<prc
->Width
; x
++) {
554 *dstpixel
++=0xff000000 | /* constant 255 alpha */
555 ((srcval
<< 8) & 0xf80000) | /* r */
556 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
557 ((srcval
<< 5) & 0x00fc00) | /* g */
558 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
559 ((srcval
<< 3) & 0x0000f8) | /* b */
560 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
567 HeapFree(GetProcessHeap(), 0, srcdata
);
572 case format_16bppBGRA5551
:
578 UINT srcstride
, srcdatasize
;
580 const WORD
*srcpixel
;
584 srcstride
= 2 * prc
->Width
;
585 srcdatasize
= srcstride
* prc
->Height
;
587 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
588 if (!srcdata
) return E_OUTOFMEMORY
;
590 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
596 for (y
=0; y
<prc
->Height
; y
++) {
597 srcpixel
=(const WORD
*)srcrow
;
598 dstpixel
=(DWORD
*)dstrow
;
599 for (x
=0; x
<prc
->Width
; x
++) {
602 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
603 ((srcval
<< 9) & 0xf80000) | /* r */
604 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
605 ((srcval
<< 6) & 0x00f800) | /* g */
606 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
607 ((srcval
<< 3) & 0x0000f8) | /* b */
608 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
615 HeapFree(GetProcessHeap(), 0, srcdata
);
620 case format_24bppBGR
:
626 UINT srcstride
, srcdatasize
;
628 const BYTE
*srcpixel
;
632 srcstride
= 3 * prc
->Width
;
633 srcdatasize
= srcstride
* prc
->Height
;
635 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
636 if (!srcdata
) return E_OUTOFMEMORY
;
638 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
644 for (y
=0; y
<prc
->Height
; y
++) {
647 for (x
=0; x
<prc
->Width
; x
++) {
648 *dstpixel
++=*srcpixel
++; /* blue */
649 *dstpixel
++=*srcpixel
++; /* green */
650 *dstpixel
++=*srcpixel
++; /* red */
651 *dstpixel
++=255; /* alpha */
658 HeapFree(GetProcessHeap(), 0, srcdata
);
663 case format_24bppRGB
:
669 UINT srcstride
, srcdatasize
;
671 const BYTE
*srcpixel
;
676 srcstride
= 3 * prc
->Width
;
677 srcdatasize
= srcstride
* prc
->Height
;
679 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
680 if (!srcdata
) return E_OUTOFMEMORY
;
682 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
688 for (y
=0; y
<prc
->Height
; y
++) {
691 for (x
=0; x
<prc
->Width
; x
++) {
692 tmppixel
[0]=*srcpixel
++; /* red */
693 tmppixel
[1]=*srcpixel
++; /* green */
694 tmppixel
[2]=*srcpixel
++; /* blue */
696 *dstpixel
++=tmppixel
[2]; /* blue */
697 *dstpixel
++=tmppixel
[1]; /* green */
698 *dstpixel
++=tmppixel
[0]; /* red */
699 *dstpixel
++=255; /* alpha */
706 HeapFree(GetProcessHeap(), 0, srcdata
);
711 case format_32bppBGR
:
717 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
718 if (FAILED(res
)) return res
;
720 /* set all alpha values to 255 */
721 for (y
=0; y
<prc
->Height
; y
++)
722 for (x
=0; x
<prc
->Width
; x
++)
723 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
726 case format_32bppBGRA
:
728 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
730 case format_32bppPBGRA
:
736 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
737 if (FAILED(res
)) return res
;
739 for (y
=0; y
<prc
->Height
; y
++)
740 for (x
=0; x
<prc
->Width
; x
++)
742 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
743 if (alpha
!= 0 && alpha
!= 255)
745 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
746 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
747 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
752 case format_48bppRGB
:
758 UINT srcstride
, srcdatasize
;
760 const BYTE
*srcpixel
;
764 srcstride
= 6 * prc
->Width
;
765 srcdatasize
= srcstride
* prc
->Height
;
767 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
768 if (!srcdata
) return E_OUTOFMEMORY
;
770 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
776 for (y
=0; y
<prc
->Height
; y
++) {
778 dstpixel
=(DWORD
*)dstrow
;
779 for (x
=0; x
<prc
->Width
; x
++) {
780 BYTE red
, green
, blue
;
781 red
= *srcpixel
++; srcpixel
++;
782 green
= *srcpixel
++; srcpixel
++;
783 blue
= *srcpixel
++; srcpixel
++;
784 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
791 HeapFree(GetProcessHeap(), 0, srcdata
);
796 case format_64bppRGBA
:
802 UINT srcstride
, srcdatasize
;
804 const BYTE
*srcpixel
;
808 srcstride
= 8 * prc
->Width
;
809 srcdatasize
= srcstride
* prc
->Height
;
811 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
812 if (!srcdata
) return E_OUTOFMEMORY
;
814 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
820 for (y
=0; y
<prc
->Height
; y
++) {
822 dstpixel
=(DWORD
*)dstrow
;
823 for (x
=0; x
<prc
->Width
; x
++) {
824 BYTE red
, green
, blue
, alpha
;
825 red
= *srcpixel
++; srcpixel
++;
826 green
= *srcpixel
++; srcpixel
++;
827 blue
= *srcpixel
++; srcpixel
++;
828 alpha
= *srcpixel
++; srcpixel
++;
829 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
836 HeapFree(GetProcessHeap(), 0, srcdata
);
841 case format_32bppCMYK
:
847 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
848 if (FAILED(res
)) return res
;
850 for (y
=0; y
<prc
->Height
; y
++)
851 for (x
=0; x
<prc
->Width
; x
++)
853 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
854 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
855 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
856 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
857 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
858 pixel
[3] = 255; /* alpha */
863 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
867 static HRESULT
copypixels_to_32bppRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
868 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
872 switch (source_format
)
874 case format_32bppRGB
:
875 case format_32bppRGBA
:
876 case format_32bppPRGBA
:
878 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
881 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
882 if (SUCCEEDED(hr
) && prc
)
883 reverse_bgr8(4, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
888 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
889 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
891 switch (source_format
)
893 case format_32bppBGR
:
894 case format_32bppBGRA
:
895 case format_32bppPBGRA
:
897 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
900 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
904 static HRESULT
copypixels_to_32bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
905 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
907 switch (source_format
)
909 case format_32bppRGB
:
910 case format_32bppRGBA
:
911 case format_32bppPRGBA
:
913 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
916 return copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
920 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
921 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
925 switch (source_format
)
927 case format_32bppPBGRA
:
929 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
932 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
933 if (SUCCEEDED(hr
) && prc
)
937 for (y
=0; y
<prc
->Height
; y
++)
938 for (x
=0; x
<prc
->Width
; x
++)
940 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
943 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
944 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
945 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
953 static HRESULT
copypixels_to_32bppPRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
954 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
958 switch (source_format
)
960 case format_32bppPRGBA
:
962 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
965 hr
= copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
966 if (SUCCEEDED(hr
) && prc
)
970 for (y
=0; y
<prc
->Height
; y
++)
971 for (x
=0; x
<prc
->Width
; x
++)
973 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
976 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
977 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
978 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
986 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
987 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
991 switch (source_format
)
993 case format_24bppBGR
:
994 case format_24bppRGB
:
997 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
998 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
999 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1003 case format_32bppBGR
:
1004 case format_32bppBGRA
:
1005 case format_32bppPBGRA
:
1011 UINT srcstride
, srcdatasize
;
1013 const BYTE
*srcpixel
;
1017 srcstride
= 4 * prc
->Width
;
1018 srcdatasize
= srcstride
* prc
->Height
;
1020 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1021 if (!srcdata
) return E_OUTOFMEMORY
;
1023 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1029 for (y
=0; y
<prc
->Height
; y
++) {
1032 for (x
=0; x
<prc
->Width
; x
++) {
1033 *dstpixel
++=*srcpixel
++; /* blue */
1034 *dstpixel
++=*srcpixel
++; /* green */
1035 *dstpixel
++=*srcpixel
++; /* red */
1036 srcpixel
++; /* alpha */
1038 srcrow
+= srcstride
;
1043 HeapFree(GetProcessHeap(), 0, srcdata
);
1049 case format_32bppGrayFloat
:
1053 UINT srcstride
, srcdatasize
;
1055 srcstride
= 4 * prc
->Width
;
1056 srcdatasize
= srcstride
* prc
->Height
;
1058 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1059 if (!srcdata
) return E_OUTOFMEMORY
;
1061 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1066 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1068 for (y
= 0; y
< prc
->Height
; y
++)
1070 float *gray_float
= (float *)src
;
1073 for (x
= 0; x
< prc
->Width
; x
++)
1075 BYTE gray
= (BYTE
)floorf(to_sRGB_component(gray_float
[x
]) * 255.0f
+ 0.51f
);
1085 HeapFree(GetProcessHeap(), 0, srcdata
);
1091 case format_32bppCMYK
:
1095 UINT srcstride
, srcdatasize
;
1097 srcstride
= 4 * prc
->Width
;
1098 srcdatasize
= srcstride
* prc
->Height
;
1100 srcdata
= heap_alloc(srcdatasize
);
1101 if (!srcdata
) return E_OUTOFMEMORY
;
1103 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1107 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1109 for (y
= 0; y
< prc
->Height
; y
++)
1114 for (x
= 0; x
< prc
->Width
; x
++)
1116 BYTE c
= cmyk
[0], m
= cmyk
[1], y
= cmyk
[2], k
= cmyk
[3];
1117 bgr
[0] = (255 - y
) * (255 - k
) / 255; /* B */
1118 bgr
[1] = (255 - m
) * (255 - k
) / 255; /* G */
1119 bgr
[2] = (255 - c
) * (255 - k
) / 255; /* R */
1134 FIXME("Unimplemented conversion path!\n");
1135 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1139 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
1140 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1144 switch (source_format
)
1146 case format_24bppBGR
:
1147 case format_24bppRGB
:
1150 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1151 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
1152 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1156 case format_32bppBGR
:
1157 case format_32bppBGRA
:
1158 case format_32bppPBGRA
:
1164 UINT srcstride
, srcdatasize
;
1166 const BYTE
*srcpixel
;
1171 srcstride
= 4 * prc
->Width
;
1172 srcdatasize
= srcstride
* prc
->Height
;
1174 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1175 if (!srcdata
) return E_OUTOFMEMORY
;
1177 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1183 for (y
=0; y
<prc
->Height
; y
++) {
1186 for (x
=0; x
<prc
->Width
; x
++) {
1187 tmppixel
[0]=*srcpixel
++; /* blue */
1188 tmppixel
[1]=*srcpixel
++; /* green */
1189 tmppixel
[2]=*srcpixel
++; /* red */
1190 srcpixel
++; /* alpha */
1192 *dstpixel
++=tmppixel
[2]; /* red */
1193 *dstpixel
++=tmppixel
[1]; /* green */
1194 *dstpixel
++=tmppixel
[0]; /* blue */
1196 srcrow
+= srcstride
;
1201 HeapFree(GetProcessHeap(), 0, srcdata
);
1207 FIXME("Unimplemented conversion path!\n");
1208 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1212 static HRESULT
copypixels_to_32bppGrayFloat(struct FormatConverter
*This
, const WICRect
*prc
,
1213 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1217 switch (source_format
)
1219 case format_32bppBGR
:
1220 case format_32bppBGRA
:
1221 case format_32bppPBGRA
:
1222 case format_32bppGrayFloat
:
1225 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1231 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1235 if (SUCCEEDED(hr
) && prc
&& source_format
!= format_32bppGrayFloat
)
1240 for (y
= 0; y
< prc
->Height
; y
++)
1243 for (x
= 0; x
< prc
->Width
; x
++)
1245 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1246 *(float *)bgr
= gray
;
1255 static HRESULT
copypixels_to_8bppGray(struct FormatConverter
*This
, const WICRect
*prc
,
1256 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1260 UINT srcstride
, srcdatasize
;
1262 if (source_format
== format_8bppGray
)
1265 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1270 if (source_format
== format_32bppGrayFloat
)
1276 srcstride
= 4 * prc
->Width
;
1277 srcdatasize
= srcstride
* prc
->Height
;
1279 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1280 if (!srcdata
) return E_OUTOFMEMORY
;
1282 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1286 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1288 for (y
=0; y
< prc
->Height
; y
++)
1290 float *srcpixel
= (float*)src
;
1291 BYTE
*dstpixel
= dst
;
1293 for (x
=0; x
< prc
->Width
; x
++)
1294 *dstpixel
++ = (BYTE
)floorf(to_sRGB_component(*srcpixel
++) * 255.0f
+ 0.51f
);
1301 HeapFree(GetProcessHeap(), 0, srcdata
);
1307 srcstride
= 3 * prc
->Width
;
1308 srcdatasize
= srcstride
* prc
->Height
;
1310 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1311 if (!srcdata
) return E_OUTOFMEMORY
;
1313 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1314 if (SUCCEEDED(hr
) && prc
)
1317 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1319 for (y
= 0; y
< prc
->Height
; y
++)
1323 for (x
= 0; x
< prc
->Width
; x
++)
1325 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1327 gray
= to_sRGB_component(gray
) * 255.0f
;
1328 dst
[x
] = (BYTE
)floorf(gray
+ 0.51f
);
1336 HeapFree(GetProcessHeap(), 0, srcdata
);
1340 static UINT
rgb_to_palette_index(BYTE r
, BYTE g
, BYTE b
, WICColor
*colors
, UINT count
)
1342 UINT best_diff
, best_index
, i
;
1347 for (i
= 0; i
< count
; i
++)
1349 BYTE pal_r
, pal_g
, pal_b
;
1350 DWORD diff_r
, diff_g
, diff_b
, diff
;
1352 pal_r
= colors
[i
] >> 16;
1353 pal_g
= colors
[i
] >> 8;
1360 diff
= diff_r
* diff_r
+ diff_g
* diff_g
+ diff_b
* diff_b
;
1361 if (diff
== 0) return i
;
1363 if (diff
< best_diff
)
1373 static HRESULT
copypixels_to_8bppIndexed(struct FormatConverter
*This
, const WICRect
*prc
,
1374 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1378 WICColor colors
[256];
1379 UINT srcstride
, srcdatasize
, count
;
1381 if (source_format
== format_8bppIndexed
)
1384 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1389 if (!This
->palette
) return WINCODEC_ERR_WRONGSTATE
;
1391 hr
= IWICPalette_GetColors(This
->palette
, 256, colors
, &count
);
1392 if (hr
!= S_OK
) return hr
;
1394 srcstride
= 3 * prc
->Width
;
1395 srcdatasize
= srcstride
* prc
->Height
;
1397 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1398 if (!srcdata
) return E_OUTOFMEMORY
;
1400 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1401 if (SUCCEEDED(hr
) && prc
)
1404 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1406 for (y
= 0; y
< prc
->Height
; y
++)
1410 for (x
= 0; x
< prc
->Width
; x
++)
1412 dst
[x
] = rgb_to_palette_index(bgr
[2], bgr
[1], bgr
[0], colors
, count
);
1420 HeapFree(GetProcessHeap(), 0, srcdata
);
1424 static const struct pixelformatinfo supported_formats
[] = {
1425 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
1426 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
1427 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1428 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, copypixels_to_8bppIndexed
},
1429 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1430 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1431 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1432 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, copypixels_to_8bppGray
},
1433 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1434 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1435 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1436 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1437 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1438 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1439 {format_32bppGrayFloat
, &GUID_WICPixelFormat32bppGrayFloat
, copypixels_to_32bppGrayFloat
},
1440 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1441 {format_32bppRGB
, &GUID_WICPixelFormat32bppRGB
, copypixels_to_32bppRGB
},
1442 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1443 {format_32bppRGBA
, &GUID_WICPixelFormat32bppRGBA
, copypixels_to_32bppRGBA
},
1444 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1445 {format_32bppPRGBA
, &GUID_WICPixelFormat32bppPRGBA
, copypixels_to_32bppPRGBA
},
1446 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1447 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1448 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1452 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1456 for (i
=0; supported_formats
[i
].guid
; i
++)
1457 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1462 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1465 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1466 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1468 if (!ppv
) return E_INVALIDARG
;
1470 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1471 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1472 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1474 *ppv
= &This
->IWICFormatConverter_iface
;
1479 return E_NOINTERFACE
;
1482 IUnknown_AddRef((IUnknown
*)*ppv
);
1486 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1488 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1489 ULONG ref
= InterlockedIncrement(&This
->ref
);
1491 TRACE("(%p) refcount=%u\n", iface
, ref
);
1496 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1498 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1499 ULONG ref
= InterlockedDecrement(&This
->ref
);
1501 TRACE("(%p) refcount=%u\n", iface
, ref
);
1505 This
->lock
.DebugInfo
->Spare
[0] = 0;
1506 DeleteCriticalSection(&This
->lock
);
1507 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1508 if (This
->palette
) IWICPalette_Release(This
->palette
);
1509 HeapFree(GetProcessHeap(), 0, This
);
1515 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1516 UINT
*puiWidth
, UINT
*puiHeight
)
1518 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1520 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1523 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1525 return WINCODEC_ERR_NOTINITIALIZED
;
1528 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1529 WICPixelFormatGUID
*pPixelFormat
)
1531 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1533 TRACE("(%p,%p)\n", iface
, pPixelFormat
);
1536 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1538 return WINCODEC_ERR_NOTINITIALIZED
;
1543 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1544 double *pDpiX
, double *pDpiY
)
1546 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1548 TRACE("(%p,%p,%p)\n", iface
, pDpiX
, pDpiY
);
1551 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1553 return WINCODEC_ERR_NOTINITIALIZED
;
1556 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1557 IWICPalette
*palette
)
1559 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1561 TRACE("(%p,%p)\n", iface
, palette
);
1563 if (!palette
) return E_INVALIDARG
;
1564 if (!This
->source
) return WINCODEC_ERR_WRONGSTATE
;
1571 hr
= get_pixelformat_bpp(This
->dst_format
->guid
, &bpp
);
1572 if (hr
!= S_OK
) return hr
;
1573 if (bpp
<= 8) return WINCODEC_ERR_WRONGSTATE
;
1574 return IWICBitmapSource_CopyPalette(This
->source
, palette
);
1577 return IWICPalette_InitializeFromPalette(palette
, This
->palette
);
1580 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1581 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1583 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1586 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
1593 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1594 if (FAILED(hr
)) return hr
;
1602 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1603 pbBuffer
, This
->src_format
->format
);
1606 return WINCODEC_ERR_WRONGSTATE
;
1609 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1610 IWICBitmapSource
*source
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1611 IWICPalette
*palette
, double alpha_threshold
, WICBitmapPaletteType palette_type
)
1613 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1614 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1618 TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface
, source
, debugstr_guid(dstFormat
),
1619 dither
, palette
, alpha_threshold
, palette_type
);
1624 res
= get_pixelformat_bpp(dstFormat
, &bpp
);
1625 if (res
!= S_OK
) return res
;
1627 res
= PaletteImpl_Create(&palette
);
1628 if (res
!= S_OK
) return res
;
1630 switch (palette_type
)
1632 case WICBitmapPaletteTypeCustom
:
1633 IWICPalette_Release(palette
);
1635 if (bpp
<= 8) return E_INVALIDARG
;
1638 case WICBitmapPaletteTypeMedianCut
:
1641 res
= IWICPalette_InitializeFromBitmap(palette
, source
, 1 << bpp
, FALSE
);
1647 res
= IWICPalette_InitializePredefined(palette
, palette_type
, FALSE
);
1653 IWICPalette_Release(palette
);
1658 IWICPalette_AddRef(palette
);
1660 EnterCriticalSection(&This
->lock
);
1664 res
= WINCODEC_ERR_WRONGSTATE
;
1668 res
= IWICBitmapSource_GetPixelFormat(source
, &srcFormat
);
1669 if (FAILED(res
)) goto end
;
1671 srcinfo
= get_formatinfo(&srcFormat
);
1674 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1675 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1679 dstinfo
= get_formatinfo(dstFormat
);
1682 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1683 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1687 if (dstinfo
->copy_function
)
1689 IWICBitmapSource_AddRef(source
);
1690 This
->src_format
= srcinfo
;
1691 This
->dst_format
= dstinfo
;
1692 This
->dither
= dither
;
1693 This
->alpha_threshold
= alpha_threshold
;
1694 This
->palette
= palette
;
1695 This
->source
= source
;
1699 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1700 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1705 LeaveCriticalSection(&This
->lock
);
1707 if (res
!= S_OK
&& palette
)
1708 IWICPalette_Release(palette
);
1713 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1714 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1717 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1718 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1720 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1721 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1723 srcinfo
= get_formatinfo(srcPixelFormat
);
1726 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1727 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1730 dstinfo
= get_formatinfo(dstPixelFormat
);
1733 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1734 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1737 if (dstinfo
->copy_function
&&
1738 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1739 *pfCanConvert
= TRUE
;
1742 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1743 *pfCanConvert
= FALSE
;
1749 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1750 FormatConverter_QueryInterface
,
1751 FormatConverter_AddRef
,
1752 FormatConverter_Release
,
1753 FormatConverter_GetSize
,
1754 FormatConverter_GetPixelFormat
,
1755 FormatConverter_GetResolution
,
1756 FormatConverter_CopyPalette
,
1757 FormatConverter_CopyPixels
,
1758 FormatConverter_Initialize
,
1759 FormatConverter_CanConvert
1762 HRESULT
FormatConverter_CreateInstance(REFIID iid
, void** ppv
)
1764 FormatConverter
*This
;
1767 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1771 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1772 if (!This
) return E_OUTOFMEMORY
;
1774 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1776 This
->source
= NULL
;
1777 This
->palette
= NULL
;
1778 InitializeCriticalSection(&This
->lock
);
1779 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1781 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1782 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);