2 * Copyright 2009 Vincent Povirk
3 * Copyright 2016 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "wincodecs_private.h"
24 struct FormatConverter
;
41 format_32bppGrayFloat
,
53 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
54 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
56 struct pixelformatinfo
{
57 enum pixelformat format
;
58 const WICPixelFormatGUID
*guid
;
59 copyfunc copy_function
;
62 typedef struct FormatConverter
{
63 IWICFormatConverter IWICFormatConverter_iface
;
65 IWICBitmapSource
*source
;
66 const struct pixelformatinfo
*dst_format
, *src_format
;
67 WICBitmapDitherType dither
;
68 double alpha_threshold
;
70 CRITICAL_SECTION lock
; /* must be held when initialized */
73 /* https://www.w3.org/Graphics/Color/srgb */
74 static inline float from_sRGB_component(float f
)
76 if (f
<= 0.04045f
) return f
/ 12.92f
;
77 return powf((f
+ 0.055f
) / 1.055f
, 2.4f
);
80 static inline float to_sRGB_component(float f
)
82 if (f
<= 0.0031308f
) return 12.92f
* f
;
83 return 1.055f
* powf(f
, 1.0f
/2.4f
) - 0.055f
;
86 #if 0 /* FIXME: enable once needed */
87 static void from_sRGB(BYTE
*bgr
)
95 r
= from_sRGB_component(r
);
96 g
= from_sRGB_component(g
);
97 b
= from_sRGB_component(b
);
99 bgr
[2] = (BYTE
)(r
* 255.0f
);
100 bgr
[1] = (BYTE
)(g
* 255.0f
);
101 bgr
[0] = (BYTE
)(b
* 255.0f
);
104 static void to_sRGB(BYTE
*bgr
)
112 r
= to_sRGB_component(r
);
113 g
= to_sRGB_component(g
);
114 b
= to_sRGB_component(b
);
116 bgr
[2] = (BYTE
)(r
* 255.0f
);
117 bgr
[1] = (BYTE
)(g
* 255.0f
);
118 bgr
[0] = (BYTE
)(b
* 255.0f
);
122 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
124 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
127 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
128 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
130 switch (source_format
)
132 case format_1bppIndexed
:
133 case format_BlackWhite
:
139 UINT srcstride
, srcdatasize
;
145 IWICPalette
*palette
;
148 res
= PaletteImpl_Create(&palette
);
149 if (FAILED(res
)) return res
;
151 if (source_format
== format_1bppIndexed
)
152 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
154 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
157 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
159 IWICPalette_Release(palette
);
160 if (FAILED(res
)) return res
;
162 srcstride
= (prc
->Width
+7)/8;
163 srcdatasize
= srcstride
* prc
->Height
;
165 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
166 if (!srcdata
) return E_OUTOFMEMORY
;
168 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
174 for (y
=0; y
<prc
->Height
; y
++) {
176 dstpixel
=(DWORD
*)dstrow
;
177 for (x
=0; x
<prc
->Width
; x
+=8) {
180 *dstpixel
++ = colors
[srcval
>>7&1];
181 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
182 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
183 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
184 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
185 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
186 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
187 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
194 HeapFree(GetProcessHeap(), 0, srcdata
);
199 case format_2bppIndexed
:
200 case format_2bppGray
:
206 UINT srcstride
, srcdatasize
;
212 IWICPalette
*palette
;
215 res
= PaletteImpl_Create(&palette
);
216 if (FAILED(res
)) return res
;
218 if (source_format
== format_2bppIndexed
)
219 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
221 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
224 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
226 IWICPalette_Release(palette
);
227 if (FAILED(res
)) return res
;
229 srcstride
= (prc
->Width
+3)/4;
230 srcdatasize
= srcstride
* prc
->Height
;
232 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
233 if (!srcdata
) return E_OUTOFMEMORY
;
235 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
241 for (y
=0; y
<prc
->Height
; y
++) {
243 dstpixel
=(DWORD
*)dstrow
;
244 for (x
=0; x
<prc
->Width
; x
+=4) {
247 *dstpixel
++ = colors
[srcval
>>6];
248 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
249 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
250 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
257 HeapFree(GetProcessHeap(), 0, srcdata
);
262 case format_4bppIndexed
:
263 case format_4bppGray
:
269 UINT srcstride
, srcdatasize
;
275 IWICPalette
*palette
;
278 res
= PaletteImpl_Create(&palette
);
279 if (FAILED(res
)) return res
;
281 if (source_format
== format_4bppIndexed
)
282 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
284 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
287 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
289 IWICPalette_Release(palette
);
290 if (FAILED(res
)) return res
;
292 srcstride
= (prc
->Width
+1)/2;
293 srcdatasize
= srcstride
* prc
->Height
;
295 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
296 if (!srcdata
) return E_OUTOFMEMORY
;
298 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
304 for (y
=0; y
<prc
->Height
; y
++) {
306 dstpixel
=(DWORD
*)dstrow
;
307 for (x
=0; x
<prc
->Width
; x
+=2) {
310 *dstpixel
++ = colors
[srcval
>>4];
311 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
318 HeapFree(GetProcessHeap(), 0, srcdata
);
323 case format_8bppGray
:
329 UINT srcstride
, srcdatasize
;
335 srcstride
= prc
->Width
;
336 srcdatasize
= srcstride
* prc
->Height
;
338 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
339 if (!srcdata
) return E_OUTOFMEMORY
;
341 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
347 for (y
=0; y
<prc
->Height
; y
++) {
349 dstpixel
=(DWORD
*)dstrow
;
350 for (x
=0; x
<prc
->Width
; x
++)
352 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
360 HeapFree(GetProcessHeap(), 0, srcdata
);
365 case format_8bppIndexed
:
371 UINT srcstride
, srcdatasize
;
376 WICColor colors
[256];
377 IWICPalette
*palette
;
380 res
= PaletteImpl_Create(&palette
);
381 if (FAILED(res
)) return res
;
383 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
385 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
387 IWICPalette_Release(palette
);
389 if (FAILED(res
)) return res
;
391 srcstride
= prc
->Width
;
392 srcdatasize
= srcstride
* prc
->Height
;
394 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
395 if (!srcdata
) return E_OUTOFMEMORY
;
397 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
403 for (y
=0; y
<prc
->Height
; y
++) {
405 dstpixel
=(DWORD
*)dstrow
;
406 for (x
=0; x
<prc
->Width
; x
++)
407 *dstpixel
++ = colors
[*srcbyte
++];
413 HeapFree(GetProcessHeap(), 0, srcdata
);
418 case format_16bppGray
:
424 UINT srcstride
, srcdatasize
;
430 srcstride
= prc
->Width
* 2;
431 srcdatasize
= srcstride
* prc
->Height
;
433 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
434 if (!srcdata
) return E_OUTOFMEMORY
;
436 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
442 for (y
=0; y
<prc
->Height
; y
++) {
444 dstpixel
=(DWORD
*)dstrow
;
445 for (x
=0; x
<prc
->Width
; x
++)
447 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
455 HeapFree(GetProcessHeap(), 0, srcdata
);
460 case format_16bppBGR555
:
466 UINT srcstride
, srcdatasize
;
468 const WORD
*srcpixel
;
472 srcstride
= 2 * prc
->Width
;
473 srcdatasize
= srcstride
* prc
->Height
;
475 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
476 if (!srcdata
) return E_OUTOFMEMORY
;
478 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
484 for (y
=0; y
<prc
->Height
; y
++) {
485 srcpixel
=(const WORD
*)srcrow
;
486 dstpixel
=(DWORD
*)dstrow
;
487 for (x
=0; x
<prc
->Width
; x
++) {
490 *dstpixel
++=0xff000000 | /* constant 255 alpha */
491 ((srcval
<< 9) & 0xf80000) | /* r */
492 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
493 ((srcval
<< 6) & 0x00f800) | /* g */
494 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
495 ((srcval
<< 3) & 0x0000f8) | /* b */
496 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
503 HeapFree(GetProcessHeap(), 0, srcdata
);
508 case format_16bppBGR565
:
514 UINT srcstride
, srcdatasize
;
516 const WORD
*srcpixel
;
520 srcstride
= 2 * prc
->Width
;
521 srcdatasize
= srcstride
* prc
->Height
;
523 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
524 if (!srcdata
) return E_OUTOFMEMORY
;
526 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
532 for (y
=0; y
<prc
->Height
; y
++) {
533 srcpixel
=(const WORD
*)srcrow
;
534 dstpixel
=(DWORD
*)dstrow
;
535 for (x
=0; x
<prc
->Width
; x
++) {
538 *dstpixel
++=0xff000000 | /* constant 255 alpha */
539 ((srcval
<< 8) & 0xf80000) | /* r */
540 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
541 ((srcval
<< 5) & 0x00fc00) | /* g */
542 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
543 ((srcval
<< 3) & 0x0000f8) | /* b */
544 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
551 HeapFree(GetProcessHeap(), 0, srcdata
);
556 case format_16bppBGRA5551
:
562 UINT srcstride
, srcdatasize
;
564 const WORD
*srcpixel
;
568 srcstride
= 2 * prc
->Width
;
569 srcdatasize
= srcstride
* prc
->Height
;
571 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
572 if (!srcdata
) return E_OUTOFMEMORY
;
574 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
580 for (y
=0; y
<prc
->Height
; y
++) {
581 srcpixel
=(const WORD
*)srcrow
;
582 dstpixel
=(DWORD
*)dstrow
;
583 for (x
=0; x
<prc
->Width
; x
++) {
586 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
587 ((srcval
<< 9) & 0xf80000) | /* r */
588 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
589 ((srcval
<< 6) & 0x00f800) | /* g */
590 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
591 ((srcval
<< 3) & 0x0000f8) | /* b */
592 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
599 HeapFree(GetProcessHeap(), 0, srcdata
);
604 case format_24bppBGR
:
610 UINT srcstride
, srcdatasize
;
612 const BYTE
*srcpixel
;
616 srcstride
= 3 * prc
->Width
;
617 srcdatasize
= srcstride
* prc
->Height
;
619 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
620 if (!srcdata
) return E_OUTOFMEMORY
;
622 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
628 for (y
=0; y
<prc
->Height
; y
++) {
631 for (x
=0; x
<prc
->Width
; x
++) {
632 *dstpixel
++=*srcpixel
++; /* blue */
633 *dstpixel
++=*srcpixel
++; /* green */
634 *dstpixel
++=*srcpixel
++; /* red */
635 *dstpixel
++=255; /* alpha */
642 HeapFree(GetProcessHeap(), 0, srcdata
);
647 case format_24bppRGB
:
653 UINT srcstride
, srcdatasize
;
655 const BYTE
*srcpixel
;
660 srcstride
= 3 * prc
->Width
;
661 srcdatasize
= srcstride
* prc
->Height
;
663 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
664 if (!srcdata
) return E_OUTOFMEMORY
;
666 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
672 for (y
=0; y
<prc
->Height
; y
++) {
675 for (x
=0; x
<prc
->Width
; x
++) {
676 tmppixel
[0]=*srcpixel
++; /* red */
677 tmppixel
[1]=*srcpixel
++; /* green */
678 tmppixel
[2]=*srcpixel
++; /* blue */
680 *dstpixel
++=tmppixel
[2]; /* blue */
681 *dstpixel
++=tmppixel
[1]; /* green */
682 *dstpixel
++=tmppixel
[0]; /* red */
683 *dstpixel
++=255; /* alpha */
690 HeapFree(GetProcessHeap(), 0, srcdata
);
695 case format_32bppBGR
:
701 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
702 if (FAILED(res
)) return res
;
704 /* set all alpha values to 255 */
705 for (y
=0; y
<prc
->Height
; y
++)
706 for (x
=0; x
<prc
->Width
; x
++)
707 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
710 case format_32bppBGRA
:
712 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
714 case format_32bppPBGRA
:
720 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
721 if (FAILED(res
)) return res
;
723 for (y
=0; y
<prc
->Height
; y
++)
724 for (x
=0; x
<prc
->Width
; x
++)
726 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
727 if (alpha
!= 0 && alpha
!= 255)
729 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
730 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
731 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
736 case format_48bppRGB
:
742 UINT srcstride
, srcdatasize
;
744 const BYTE
*srcpixel
;
748 srcstride
= 6 * prc
->Width
;
749 srcdatasize
= srcstride
* prc
->Height
;
751 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
752 if (!srcdata
) return E_OUTOFMEMORY
;
754 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
760 for (y
=0; y
<prc
->Height
; y
++) {
762 dstpixel
=(DWORD
*)dstrow
;
763 for (x
=0; x
<prc
->Width
; x
++) {
764 BYTE red
, green
, blue
;
765 red
= *srcpixel
++; srcpixel
++;
766 green
= *srcpixel
++; srcpixel
++;
767 blue
= *srcpixel
++; srcpixel
++;
768 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
775 HeapFree(GetProcessHeap(), 0, srcdata
);
780 case format_64bppRGBA
:
786 UINT srcstride
, srcdatasize
;
788 const BYTE
*srcpixel
;
792 srcstride
= 8 * prc
->Width
;
793 srcdatasize
= srcstride
* prc
->Height
;
795 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
796 if (!srcdata
) return E_OUTOFMEMORY
;
798 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
804 for (y
=0; y
<prc
->Height
; y
++) {
806 dstpixel
=(DWORD
*)dstrow
;
807 for (x
=0; x
<prc
->Width
; x
++) {
808 BYTE red
, green
, blue
, alpha
;
809 red
= *srcpixel
++; srcpixel
++;
810 green
= *srcpixel
++; srcpixel
++;
811 blue
= *srcpixel
++; srcpixel
++;
812 alpha
= *srcpixel
++; srcpixel
++;
813 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
820 HeapFree(GetProcessHeap(), 0, srcdata
);
825 case format_32bppCMYK
:
831 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
832 if (FAILED(res
)) return res
;
834 for (y
=0; y
<prc
->Height
; y
++)
835 for (x
=0; x
<prc
->Width
; x
++)
837 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
838 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
839 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
840 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
841 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
842 pixel
[3] = 255; /* alpha */
847 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
851 static HRESULT
copypixels_to_32bppRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
852 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
856 switch (source_format
)
858 case format_32bppRGB
:
859 case format_32bppRGBA
:
860 case format_32bppPRGBA
:
862 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
865 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
866 if (SUCCEEDED(hr
) && prc
)
867 reverse_bgr8(4, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
872 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
873 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
875 switch (source_format
)
877 case format_32bppBGR
:
878 case format_32bppBGRA
:
879 case format_32bppPBGRA
:
881 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
884 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
888 static HRESULT
copypixels_to_32bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
889 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
891 switch (source_format
)
893 case format_32bppRGB
:
894 case format_32bppRGBA
:
895 case format_32bppPRGBA
:
897 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
900 return copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
904 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
905 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
909 switch (source_format
)
911 case format_32bppPBGRA
:
913 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
916 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
917 if (SUCCEEDED(hr
) && prc
)
921 for (y
=0; y
<prc
->Height
; y
++)
922 for (x
=0; x
<prc
->Width
; x
++)
924 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
927 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
928 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
929 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
937 static HRESULT
copypixels_to_32bppPRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
938 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
942 switch (source_format
)
944 case format_32bppPRGBA
:
946 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
949 hr
= copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
950 if (SUCCEEDED(hr
) && prc
)
954 for (y
=0; y
<prc
->Height
; y
++)
955 for (x
=0; x
<prc
->Width
; x
++)
957 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
960 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
961 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
962 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
970 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
971 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
975 switch (source_format
)
977 case format_24bppBGR
:
978 case format_24bppRGB
:
981 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
982 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
983 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
987 case format_32bppBGR
:
988 case format_32bppBGRA
:
989 case format_32bppPBGRA
:
995 UINT srcstride
, srcdatasize
;
997 const BYTE
*srcpixel
;
1001 srcstride
= 4 * prc
->Width
;
1002 srcdatasize
= srcstride
* prc
->Height
;
1004 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1005 if (!srcdata
) return E_OUTOFMEMORY
;
1007 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1013 for (y
=0; y
<prc
->Height
; y
++) {
1016 for (x
=0; x
<prc
->Width
; x
++) {
1017 *dstpixel
++=*srcpixel
++; /* blue */
1018 *dstpixel
++=*srcpixel
++; /* green */
1019 *dstpixel
++=*srcpixel
++; /* red */
1020 srcpixel
++; /* alpha */
1022 srcrow
+= srcstride
;
1027 HeapFree(GetProcessHeap(), 0, srcdata
);
1033 case format_32bppGrayFloat
:
1037 UINT srcstride
, srcdatasize
;
1039 srcstride
= 4 * prc
->Width
;
1040 srcdatasize
= srcstride
* prc
->Height
;
1042 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1043 if (!srcdata
) return E_OUTOFMEMORY
;
1045 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1050 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1052 for (y
= 0; y
< prc
->Height
; y
++)
1054 float *gray_float
= (float *)src
;
1057 for (x
= 0; x
< prc
->Width
; x
++)
1059 BYTE gray
= (BYTE
)floorf(to_sRGB_component(gray_float
[x
]) * 255.0f
+ 0.51f
);
1069 HeapFree(GetProcessHeap(), 0, srcdata
);
1075 case format_32bppCMYK
:
1079 UINT srcstride
, srcdatasize
;
1081 srcstride
= 4 * prc
->Width
;
1082 srcdatasize
= srcstride
* prc
->Height
;
1084 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1085 if (!srcdata
) return E_OUTOFMEMORY
;
1087 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1091 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1093 for (y
= 0; y
< prc
->Height
; y
++)
1098 for (x
= 0; x
< prc
->Width
; x
++)
1100 BYTE c
= cmyk
[0], m
= cmyk
[1], y
= cmyk
[2], k
= cmyk
[3];
1101 bgr
[0] = (255 - y
) * (255 - k
) / 255; /* B */
1102 bgr
[1] = (255 - m
) * (255 - k
) / 255; /* G */
1103 bgr
[2] = (255 - c
) * (255 - k
) / 255; /* R */
1112 HeapFree(GetProcessHeap(), 0, srcdata
);
1118 FIXME("Unimplemented conversion path!\n");
1119 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1123 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
1124 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1128 switch (source_format
)
1130 case format_24bppBGR
:
1131 case format_24bppRGB
:
1134 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1135 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
1136 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1140 case format_32bppBGR
:
1141 case format_32bppBGRA
:
1142 case format_32bppPBGRA
:
1148 UINT srcstride
, srcdatasize
;
1150 const BYTE
*srcpixel
;
1155 srcstride
= 4 * prc
->Width
;
1156 srcdatasize
= srcstride
* prc
->Height
;
1158 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1159 if (!srcdata
) return E_OUTOFMEMORY
;
1161 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1167 for (y
=0; y
<prc
->Height
; y
++) {
1170 for (x
=0; x
<prc
->Width
; x
++) {
1171 tmppixel
[0]=*srcpixel
++; /* blue */
1172 tmppixel
[1]=*srcpixel
++; /* green */
1173 tmppixel
[2]=*srcpixel
++; /* red */
1174 srcpixel
++; /* alpha */
1176 *dstpixel
++=tmppixel
[2]; /* red */
1177 *dstpixel
++=tmppixel
[1]; /* green */
1178 *dstpixel
++=tmppixel
[0]; /* blue */
1180 srcrow
+= srcstride
;
1185 HeapFree(GetProcessHeap(), 0, srcdata
);
1191 FIXME("Unimplemented conversion path!\n");
1192 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1196 static HRESULT
copypixels_to_32bppGrayFloat(struct FormatConverter
*This
, const WICRect
*prc
,
1197 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1201 switch (source_format
)
1203 case format_32bppBGR
:
1204 case format_32bppBGRA
:
1205 case format_32bppPBGRA
:
1206 case format_32bppGrayFloat
:
1209 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1215 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1219 if (SUCCEEDED(hr
) && prc
&& source_format
!= format_32bppGrayFloat
)
1224 for (y
= 0; y
< prc
->Height
; y
++)
1227 for (x
= 0; x
< prc
->Width
; x
++)
1229 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1230 *(float *)bgr
= gray
;
1239 static HRESULT
copypixels_to_8bppGray(struct FormatConverter
*This
, const WICRect
*prc
,
1240 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1244 UINT srcstride
, srcdatasize
;
1246 if (source_format
== format_8bppGray
)
1249 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1254 if (source_format
== format_32bppGrayFloat
)
1260 srcstride
= 4 * prc
->Width
;
1261 srcdatasize
= srcstride
* prc
->Height
;
1263 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1264 if (!srcdata
) return E_OUTOFMEMORY
;
1266 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1270 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1272 for (y
=0; y
< prc
->Height
; y
++)
1274 float *srcpixel
= (float*)src
;
1275 BYTE
*dstpixel
= dst
;
1277 for (x
=0; x
< prc
->Width
; x
++)
1278 *dstpixel
++ = (BYTE
)floorf(to_sRGB_component(*srcpixel
++) * 255.0f
+ 0.51f
);
1285 HeapFree(GetProcessHeap(), 0, srcdata
);
1291 srcstride
= 3 * prc
->Width
;
1292 srcdatasize
= srcstride
* prc
->Height
;
1294 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1295 if (!srcdata
) return E_OUTOFMEMORY
;
1297 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1298 if (SUCCEEDED(hr
) && prc
)
1301 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1303 for (y
= 0; y
< prc
->Height
; y
++)
1307 for (x
= 0; x
< prc
->Width
; x
++)
1309 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1311 gray
= to_sRGB_component(gray
) * 255.0f
;
1312 dst
[x
] = (BYTE
)floorf(gray
+ 0.51f
);
1320 HeapFree(GetProcessHeap(), 0, srcdata
);
1324 static UINT
rgb_to_palette_index(BYTE r
, BYTE g
, BYTE b
, WICColor
*colors
, UINT count
)
1326 UINT best_diff
, best_index
, i
;
1331 for (i
= 0; i
< count
; i
++)
1333 BYTE pal_r
, pal_g
, pal_b
;
1334 DWORD diff_r
, diff_g
, diff_b
, diff
;
1336 pal_r
= colors
[i
] >> 16;
1337 pal_g
= colors
[i
] >> 8;
1344 diff
= diff_r
* diff_r
+ diff_g
* diff_g
+ diff_b
* diff_b
;
1345 if (diff
== 0) return i
;
1347 if (diff
< best_diff
)
1357 static HRESULT
copypixels_to_8bppIndexed(struct FormatConverter
*This
, const WICRect
*prc
,
1358 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1362 WICColor colors
[256];
1363 UINT srcstride
, srcdatasize
, count
;
1365 if (source_format
== format_8bppIndexed
)
1368 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1373 if (!This
->palette
) return WINCODEC_ERR_WRONGSTATE
;
1375 hr
= IWICPalette_GetColors(This
->palette
, 256, colors
, &count
);
1376 if (hr
!= S_OK
) return hr
;
1378 srcstride
= 3 * prc
->Width
;
1379 srcdatasize
= srcstride
* prc
->Height
;
1381 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1382 if (!srcdata
) return E_OUTOFMEMORY
;
1384 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1385 if (SUCCEEDED(hr
) && prc
)
1388 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1390 for (y
= 0; y
< prc
->Height
; y
++)
1394 for (x
= 0; x
< prc
->Width
; x
++)
1396 dst
[x
] = rgb_to_palette_index(bgr
[2], bgr
[1], bgr
[0], colors
, count
);
1404 HeapFree(GetProcessHeap(), 0, srcdata
);
1408 static const struct pixelformatinfo supported_formats
[] = {
1409 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
1410 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
1411 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1412 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, copypixels_to_8bppIndexed
},
1413 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1414 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1415 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1416 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, copypixels_to_8bppGray
},
1417 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1418 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1419 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1420 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1421 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1422 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1423 {format_32bppGrayFloat
, &GUID_WICPixelFormat32bppGrayFloat
, copypixels_to_32bppGrayFloat
},
1424 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1425 {format_32bppRGB
, &GUID_WICPixelFormat32bppRGB
, copypixels_to_32bppRGB
},
1426 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1427 {format_32bppRGBA
, &GUID_WICPixelFormat32bppRGBA
, copypixels_to_32bppRGBA
},
1428 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1429 {format_32bppPRGBA
, &GUID_WICPixelFormat32bppPRGBA
, copypixels_to_32bppPRGBA
},
1430 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1431 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1432 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1436 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1440 for (i
=0; supported_formats
[i
].guid
; i
++)
1441 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1446 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1449 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1450 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1452 if (!ppv
) return E_INVALIDARG
;
1454 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1455 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1456 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1458 *ppv
= &This
->IWICFormatConverter_iface
;
1463 return E_NOINTERFACE
;
1466 IUnknown_AddRef((IUnknown
*)*ppv
);
1470 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1472 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1473 ULONG ref
= InterlockedIncrement(&This
->ref
);
1475 TRACE("(%p) refcount=%u\n", iface
, ref
);
1480 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1482 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1483 ULONG ref
= InterlockedDecrement(&This
->ref
);
1485 TRACE("(%p) refcount=%u\n", iface
, ref
);
1489 This
->lock
.DebugInfo
->Spare
[0] = 0;
1490 DeleteCriticalSection(&This
->lock
);
1491 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1492 if (This
->palette
) IWICPalette_Release(This
->palette
);
1493 HeapFree(GetProcessHeap(), 0, This
);
1499 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1500 UINT
*puiWidth
, UINT
*puiHeight
)
1502 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1504 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1507 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1509 return WINCODEC_ERR_NOTINITIALIZED
;
1512 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1513 WICPixelFormatGUID
*pPixelFormat
)
1515 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1517 TRACE("(%p,%p)\n", iface
, pPixelFormat
);
1520 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1522 return WINCODEC_ERR_NOTINITIALIZED
;
1527 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1528 double *pDpiX
, double *pDpiY
)
1530 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1532 TRACE("(%p,%p,%p)\n", iface
, pDpiX
, pDpiY
);
1535 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1537 return WINCODEC_ERR_NOTINITIALIZED
;
1540 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1541 IWICPalette
*palette
)
1543 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1545 TRACE("(%p,%p)\n", iface
, palette
);
1547 if (!palette
) return E_INVALIDARG
;
1548 if (!This
->source
) return WINCODEC_ERR_WRONGSTATE
;
1555 hr
= get_pixelformat_bpp(This
->dst_format
->guid
, &bpp
);
1556 if (hr
!= S_OK
) return hr
;
1557 if (bpp
<= 8) return WINCODEC_ERR_WRONGSTATE
;
1558 return IWICBitmapSource_CopyPalette(This
->source
, palette
);
1561 return IWICPalette_InitializeFromPalette(palette
, This
->palette
);
1564 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1565 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1567 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1570 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1577 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1578 if (FAILED(hr
)) return hr
;
1586 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1587 pbBuffer
, This
->src_format
->format
);
1590 return WINCODEC_ERR_WRONGSTATE
;
1593 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1594 IWICBitmapSource
*source
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1595 IWICPalette
*palette
, double alpha_threshold
, WICBitmapPaletteType palette_type
)
1597 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1598 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1602 TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface
, source
, debugstr_guid(dstFormat
),
1603 dither
, palette
, alpha_threshold
, palette_type
);
1608 res
= get_pixelformat_bpp(dstFormat
, &bpp
);
1609 if (res
!= S_OK
) return res
;
1611 res
= PaletteImpl_Create(&palette
);
1612 if (res
!= S_OK
) return res
;
1614 switch (palette_type
)
1616 case WICBitmapPaletteTypeCustom
:
1617 IWICPalette_Release(palette
);
1619 if (bpp
<= 8) return E_INVALIDARG
;
1622 case WICBitmapPaletteTypeMedianCut
:
1625 res
= IWICPalette_InitializeFromBitmap(palette
, source
, 1 << bpp
, FALSE
);
1631 res
= IWICPalette_InitializePredefined(palette
, palette_type
, FALSE
);
1637 IWICPalette_Release(palette
);
1642 IWICPalette_AddRef(palette
);
1644 EnterCriticalSection(&This
->lock
);
1648 res
= WINCODEC_ERR_WRONGSTATE
;
1652 res
= IWICBitmapSource_GetPixelFormat(source
, &srcFormat
);
1653 if (FAILED(res
)) goto end
;
1655 srcinfo
= get_formatinfo(&srcFormat
);
1658 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1659 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1663 dstinfo
= get_formatinfo(dstFormat
);
1666 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1667 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1671 if (dstinfo
->copy_function
)
1673 IWICBitmapSource_AddRef(source
);
1674 This
->src_format
= srcinfo
;
1675 This
->dst_format
= dstinfo
;
1676 This
->dither
= dither
;
1677 This
->alpha_threshold
= alpha_threshold
;
1678 This
->palette
= palette
;
1679 This
->source
= source
;
1683 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1684 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1689 LeaveCriticalSection(&This
->lock
);
1691 if (res
!= S_OK
&& palette
)
1692 IWICPalette_Release(palette
);
1697 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1698 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1701 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1702 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1704 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1705 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1707 srcinfo
= get_formatinfo(srcPixelFormat
);
1710 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1711 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1714 dstinfo
= get_formatinfo(dstPixelFormat
);
1717 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1718 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1721 if (dstinfo
->copy_function
&&
1722 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1723 *pfCanConvert
= TRUE
;
1726 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1727 *pfCanConvert
= FALSE
;
1733 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1734 FormatConverter_QueryInterface
,
1735 FormatConverter_AddRef
,
1736 FormatConverter_Release
,
1737 FormatConverter_GetSize
,
1738 FormatConverter_GetPixelFormat
,
1739 FormatConverter_GetResolution
,
1740 FormatConverter_CopyPalette
,
1741 FormatConverter_CopyPixels
,
1742 FormatConverter_Initialize
,
1743 FormatConverter_CanConvert
1746 HRESULT
FormatConverter_CreateInstance(REFIID iid
, void** ppv
)
1748 FormatConverter
*This
;
1751 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1755 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1756 if (!This
) return E_OUTOFMEMORY
;
1758 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1760 This
->source
= NULL
;
1761 This
->palette
= NULL
;
1762 InitializeCriticalSection(&This
->lock
);
1763 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1765 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1766 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);