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
29 #include "wincodecs_private.h"
31 #include "wine/heap.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
36 struct FormatConverter
;
53 format_32bppGrayFloat
,
65 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
66 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
68 struct pixelformatinfo
{
69 enum pixelformat format
;
70 const WICPixelFormatGUID
*guid
;
71 copyfunc copy_function
;
74 typedef struct FormatConverter
{
75 IWICFormatConverter IWICFormatConverter_iface
;
77 IWICBitmapSource
*source
;
78 const struct pixelformatinfo
*dst_format
, *src_format
;
79 WICBitmapDitherType dither
;
80 double alpha_threshold
;
82 CRITICAL_SECTION lock
; /* must be held when initialized */
85 /* https://www.w3.org/Graphics/Color/srgb */
86 static inline float to_sRGB_component(float f
)
88 if (f
<= 0.0031308f
) return 12.92f
* f
;
89 return 1.055f
* powf(f
, 1.0f
/2.4f
) - 0.055f
;
92 #if 0 /* FIXME: enable once needed */
93 static inline float from_sRGB_component(float f
)
95 if (f
<= 0.04045f
) return f
/ 12.92f
;
96 return powf((f
+ 0.055f
) / 1.055f
, 2.4f
);
99 static void from_sRGB(BYTE
*bgr
)
107 r
= from_sRGB_component(r
);
108 g
= from_sRGB_component(g
);
109 b
= from_sRGB_component(b
);
111 bgr
[2] = (BYTE
)(r
* 255.0f
);
112 bgr
[1] = (BYTE
)(g
* 255.0f
);
113 bgr
[0] = (BYTE
)(b
* 255.0f
);
116 static void to_sRGB(BYTE
*bgr
)
124 r
= to_sRGB_component(r
);
125 g
= to_sRGB_component(g
);
126 b
= to_sRGB_component(b
);
128 bgr
[2] = (BYTE
)(r
* 255.0f
);
129 bgr
[1] = (BYTE
)(g
* 255.0f
);
130 bgr
[0] = (BYTE
)(b
* 255.0f
);
134 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
136 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
139 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
140 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
142 switch (source_format
)
144 case format_1bppIndexed
:
145 case format_BlackWhite
:
151 UINT srcstride
, srcdatasize
;
157 IWICPalette
*palette
;
160 res
= PaletteImpl_Create(&palette
);
161 if (FAILED(res
)) return res
;
163 if (source_format
== format_1bppIndexed
)
164 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
166 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
169 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
171 IWICPalette_Release(palette
);
172 if (FAILED(res
)) return res
;
174 srcstride
= (prc
->Width
+7)/8;
175 srcdatasize
= srcstride
* prc
->Height
;
177 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
178 if (!srcdata
) return E_OUTOFMEMORY
;
180 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
186 for (y
=0; y
<prc
->Height
; y
++) {
188 dstpixel
=(DWORD
*)dstrow
;
189 for (x
=0; x
<prc
->Width
; x
+=8) {
192 *dstpixel
++ = colors
[srcval
>>7&1];
193 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
194 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
195 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
196 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
197 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
198 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
199 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
206 HeapFree(GetProcessHeap(), 0, srcdata
);
211 case format_2bppIndexed
:
212 case format_2bppGray
:
218 UINT srcstride
, srcdatasize
;
224 IWICPalette
*palette
;
227 res
= PaletteImpl_Create(&palette
);
228 if (FAILED(res
)) return res
;
230 if (source_format
== format_2bppIndexed
)
231 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
233 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
236 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
238 IWICPalette_Release(palette
);
239 if (FAILED(res
)) return res
;
241 srcstride
= (prc
->Width
+3)/4;
242 srcdatasize
= srcstride
* prc
->Height
;
244 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
245 if (!srcdata
) return E_OUTOFMEMORY
;
247 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
253 for (y
=0; y
<prc
->Height
; y
++) {
255 dstpixel
=(DWORD
*)dstrow
;
256 for (x
=0; x
<prc
->Width
; x
+=4) {
259 *dstpixel
++ = colors
[srcval
>>6];
260 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
261 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
262 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
269 HeapFree(GetProcessHeap(), 0, srcdata
);
274 case format_4bppIndexed
:
275 case format_4bppGray
:
281 UINT srcstride
, srcdatasize
;
287 IWICPalette
*palette
;
290 res
= PaletteImpl_Create(&palette
);
291 if (FAILED(res
)) return res
;
293 if (source_format
== format_4bppIndexed
)
294 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
296 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
299 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
301 IWICPalette_Release(palette
);
302 if (FAILED(res
)) return res
;
304 srcstride
= (prc
->Width
+1)/2;
305 srcdatasize
= srcstride
* prc
->Height
;
307 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
308 if (!srcdata
) return E_OUTOFMEMORY
;
310 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
316 for (y
=0; y
<prc
->Height
; y
++) {
318 dstpixel
=(DWORD
*)dstrow
;
319 for (x
=0; x
<prc
->Width
; x
+=2) {
322 *dstpixel
++ = colors
[srcval
>>4];
323 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
330 HeapFree(GetProcessHeap(), 0, srcdata
);
335 case format_8bppGray
:
341 UINT srcstride
, srcdatasize
;
347 srcstride
= prc
->Width
;
348 srcdatasize
= srcstride
* prc
->Height
;
350 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
351 if (!srcdata
) return E_OUTOFMEMORY
;
353 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
359 for (y
=0; y
<prc
->Height
; y
++) {
361 dstpixel
=(DWORD
*)dstrow
;
362 for (x
=0; x
<prc
->Width
; x
++)
364 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
372 HeapFree(GetProcessHeap(), 0, srcdata
);
377 case format_8bppIndexed
:
383 UINT srcstride
, srcdatasize
;
388 WICColor colors
[256];
389 IWICPalette
*palette
;
392 res
= PaletteImpl_Create(&palette
);
393 if (FAILED(res
)) return res
;
395 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
397 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
399 IWICPalette_Release(palette
);
401 if (FAILED(res
)) return res
;
403 srcstride
= prc
->Width
;
404 srcdatasize
= srcstride
* prc
->Height
;
406 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
407 if (!srcdata
) return E_OUTOFMEMORY
;
409 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
415 for (y
=0; y
<prc
->Height
; y
++) {
417 dstpixel
=(DWORD
*)dstrow
;
418 for (x
=0; x
<prc
->Width
; x
++)
419 *dstpixel
++ = colors
[*srcbyte
++];
425 HeapFree(GetProcessHeap(), 0, srcdata
);
430 case format_16bppGray
:
436 UINT srcstride
, srcdatasize
;
442 srcstride
= prc
->Width
* 2;
443 srcdatasize
= srcstride
* prc
->Height
;
445 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
446 if (!srcdata
) return E_OUTOFMEMORY
;
448 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
454 for (y
=0; y
<prc
->Height
; y
++) {
456 dstpixel
=(DWORD
*)dstrow
;
457 for (x
=0; x
<prc
->Width
; x
++)
460 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
468 HeapFree(GetProcessHeap(), 0, srcdata
);
473 case format_16bppBGR555
:
479 UINT srcstride
, srcdatasize
;
481 const WORD
*srcpixel
;
485 srcstride
= 2 * prc
->Width
;
486 srcdatasize
= srcstride
* prc
->Height
;
488 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
489 if (!srcdata
) return E_OUTOFMEMORY
;
491 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
497 for (y
=0; y
<prc
->Height
; y
++) {
498 srcpixel
=(const WORD
*)srcrow
;
499 dstpixel
=(DWORD
*)dstrow
;
500 for (x
=0; x
<prc
->Width
; x
++) {
503 *dstpixel
++=0xff000000 | /* constant 255 alpha */
504 ((srcval
<< 9) & 0xf80000) | /* r */
505 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
506 ((srcval
<< 6) & 0x00f800) | /* g */
507 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
508 ((srcval
<< 3) & 0x0000f8) | /* b */
509 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
516 HeapFree(GetProcessHeap(), 0, srcdata
);
521 case format_16bppBGR565
:
527 UINT srcstride
, srcdatasize
;
529 const WORD
*srcpixel
;
533 srcstride
= 2 * prc
->Width
;
534 srcdatasize
= srcstride
* prc
->Height
;
536 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
537 if (!srcdata
) return E_OUTOFMEMORY
;
539 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
545 for (y
=0; y
<prc
->Height
; y
++) {
546 srcpixel
=(const WORD
*)srcrow
;
547 dstpixel
=(DWORD
*)dstrow
;
548 for (x
=0; x
<prc
->Width
; x
++) {
551 *dstpixel
++=0xff000000 | /* constant 255 alpha */
552 ((srcval
<< 8) & 0xf80000) | /* r */
553 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
554 ((srcval
<< 5) & 0x00fc00) | /* g */
555 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
556 ((srcval
<< 3) & 0x0000f8) | /* b */
557 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
564 HeapFree(GetProcessHeap(), 0, srcdata
);
569 case format_16bppBGRA5551
:
575 UINT srcstride
, srcdatasize
;
577 const WORD
*srcpixel
;
581 srcstride
= 2 * prc
->Width
;
582 srcdatasize
= srcstride
* prc
->Height
;
584 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
585 if (!srcdata
) return E_OUTOFMEMORY
;
587 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
593 for (y
=0; y
<prc
->Height
; y
++) {
594 srcpixel
=(const WORD
*)srcrow
;
595 dstpixel
=(DWORD
*)dstrow
;
596 for (x
=0; x
<prc
->Width
; x
++) {
599 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
600 ((srcval
<< 9) & 0xf80000) | /* r */
601 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
602 ((srcval
<< 6) & 0x00f800) | /* g */
603 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
604 ((srcval
<< 3) & 0x0000f8) | /* b */
605 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
612 HeapFree(GetProcessHeap(), 0, srcdata
);
617 case format_24bppBGR
:
623 UINT srcstride
, srcdatasize
;
625 const BYTE
*srcpixel
;
629 srcstride
= 3 * prc
->Width
;
630 srcdatasize
= srcstride
* prc
->Height
;
632 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
633 if (!srcdata
) return E_OUTOFMEMORY
;
635 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
641 for (y
=0; y
<prc
->Height
; y
++) {
644 for (x
=0; x
<prc
->Width
; x
++) {
645 *dstpixel
++=*srcpixel
++; /* blue */
646 *dstpixel
++=*srcpixel
++; /* green */
647 *dstpixel
++=*srcpixel
++; /* red */
648 *dstpixel
++=255; /* alpha */
655 HeapFree(GetProcessHeap(), 0, srcdata
);
660 case format_24bppRGB
:
666 UINT srcstride
, srcdatasize
;
668 const BYTE
*srcpixel
;
673 srcstride
= 3 * prc
->Width
;
674 srcdatasize
= srcstride
* prc
->Height
;
676 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
677 if (!srcdata
) return E_OUTOFMEMORY
;
679 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
685 for (y
=0; y
<prc
->Height
; y
++) {
688 for (x
=0; x
<prc
->Width
; x
++) {
689 tmppixel
[0]=*srcpixel
++; /* red */
690 tmppixel
[1]=*srcpixel
++; /* green */
691 tmppixel
[2]=*srcpixel
++; /* blue */
693 *dstpixel
++=tmppixel
[2]; /* blue */
694 *dstpixel
++=tmppixel
[1]; /* green */
695 *dstpixel
++=tmppixel
[0]; /* red */
696 *dstpixel
++=255; /* alpha */
703 HeapFree(GetProcessHeap(), 0, srcdata
);
708 case format_32bppBGR
:
714 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
715 if (FAILED(res
)) return res
;
717 /* set all alpha values to 255 */
718 for (y
=0; y
<prc
->Height
; y
++)
719 for (x
=0; x
<prc
->Width
; x
++)
720 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
723 case format_32bppRGBA
:
727 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
728 if (FAILED(res
)) return res
;
729 reverse_bgr8(4, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
732 case format_32bppBGRA
:
734 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
736 case format_32bppPBGRA
:
742 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
743 if (FAILED(res
)) return res
;
745 for (y
=0; y
<prc
->Height
; y
++)
746 for (x
=0; x
<prc
->Width
; x
++)
748 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
749 if (alpha
!= 0 && alpha
!= 255)
751 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
752 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
753 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
758 case format_48bppRGB
:
764 UINT srcstride
, srcdatasize
;
766 const BYTE
*srcpixel
;
770 srcstride
= 6 * prc
->Width
;
771 srcdatasize
= srcstride
* prc
->Height
;
773 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
774 if (!srcdata
) return E_OUTOFMEMORY
;
776 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
782 for (y
=0; y
<prc
->Height
; y
++) {
784 dstpixel
=(DWORD
*)dstrow
;
785 for (x
=0; x
<prc
->Width
; x
++) {
786 BYTE red
, green
, blue
;
787 srcpixel
++; red
= *srcpixel
++;
788 srcpixel
++; green
= *srcpixel
++;
789 srcpixel
++; blue
= *srcpixel
++;
790 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
797 HeapFree(GetProcessHeap(), 0, srcdata
);
802 case format_64bppRGBA
:
808 UINT srcstride
, srcdatasize
;
810 const BYTE
*srcpixel
;
814 srcstride
= 8 * prc
->Width
;
815 srcdatasize
= srcstride
* prc
->Height
;
817 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
818 if (!srcdata
) return E_OUTOFMEMORY
;
820 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
826 for (y
=0; y
<prc
->Height
; y
++) {
828 dstpixel
=(DWORD
*)dstrow
;
829 for (x
=0; x
<prc
->Width
; x
++) {
830 BYTE red
, green
, blue
, alpha
;
831 srcpixel
++; red
= *srcpixel
++;
832 srcpixel
++; green
= *srcpixel
++;
833 srcpixel
++; blue
= *srcpixel
++;
834 srcpixel
++; alpha
= *srcpixel
++;
835 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
842 HeapFree(GetProcessHeap(), 0, srcdata
);
847 case format_32bppCMYK
:
853 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
854 if (FAILED(res
)) return res
;
856 for (y
=0; y
<prc
->Height
; y
++)
857 for (x
=0; x
<prc
->Width
; x
++)
859 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
860 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
861 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
862 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
863 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
864 pixel
[3] = 255; /* alpha */
869 FIXME("Unimplemented conversion path!\n");
870 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
874 static HRESULT
copypixels_to_32bppRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
875 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
879 switch (source_format
)
881 case format_32bppRGB
:
886 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
887 if (FAILED(hr
)) return hr
;
889 /* set all alpha values to 255 */
890 for (y
=0; y
<prc
->Height
; y
++)
891 for (x
=0; x
<prc
->Width
; x
++)
892 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
896 case format_32bppRGBA
:
898 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
901 case format_32bppPRGBA
:
906 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
907 if (FAILED(hr
)) return hr
;
909 for (y
=0; y
<prc
->Height
; y
++)
910 for (x
=0; x
<prc
->Width
; x
++)
912 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
913 if (alpha
!= 0 && alpha
!= 255)
915 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
916 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
917 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
924 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
925 if (SUCCEEDED(hr
) && prc
)
926 reverse_bgr8(4, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
931 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
932 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
934 switch (source_format
)
936 case format_32bppBGR
:
937 case format_32bppBGRA
:
938 case format_32bppPBGRA
:
940 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
943 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
947 static HRESULT
copypixels_to_32bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
948 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
950 switch (source_format
)
952 case format_32bppRGB
:
953 case format_32bppRGBA
:
954 case format_32bppPRGBA
:
956 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
959 return copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
963 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
964 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
968 switch (source_format
)
970 case format_32bppPBGRA
:
972 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
975 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
976 if (SUCCEEDED(hr
) && prc
)
980 for (y
=0; y
<prc
->Height
; y
++)
981 for (x
=0; x
<prc
->Width
; x
++)
983 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
986 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
987 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
988 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
996 static HRESULT
copypixels_to_32bppPRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
997 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1001 switch (source_format
)
1003 case format_32bppPRGBA
:
1005 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1008 hr
= copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1009 if (SUCCEEDED(hr
) && prc
)
1013 for (y
=0; y
<prc
->Height
; y
++)
1014 for (x
=0; x
<prc
->Width
; x
++)
1016 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
1019 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
1020 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
1021 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
1029 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
1030 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1034 switch (source_format
)
1036 case format_24bppBGR
:
1037 case format_24bppRGB
:
1040 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1041 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
1042 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1046 case format_32bppBGR
:
1047 case format_32bppBGRA
:
1048 case format_32bppPBGRA
:
1049 case format_32bppRGBA
:
1055 UINT srcstride
, srcdatasize
;
1057 const BYTE
*srcpixel
;
1061 srcstride
= 4 * prc
->Width
;
1062 srcdatasize
= srcstride
* prc
->Height
;
1064 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1065 if (!srcdata
) return E_OUTOFMEMORY
;
1067 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1074 if (source_format
== format_32bppRGBA
)
1076 for (y
= 0; y
< prc
->Height
; y
++)
1080 for (x
= 0; x
< prc
->Width
; x
++) {
1081 *dstpixel
++ = srcpixel
[2]; /* blue */
1082 *dstpixel
++ = srcpixel
[1]; /* green */
1083 *dstpixel
++ = srcpixel
[0]; /* red */
1086 srcrow
+= srcstride
;
1092 for (y
= 0; y
< prc
->Height
; y
++)
1096 for (x
= 0; x
< prc
->Width
; x
++) {
1097 *dstpixel
++ = *srcpixel
++; /* blue */
1098 *dstpixel
++ = *srcpixel
++; /* green */
1099 *dstpixel
++ = *srcpixel
++; /* red */
1100 srcpixel
++; /* alpha */
1102 srcrow
+= srcstride
;
1108 HeapFree(GetProcessHeap(), 0, srcdata
);
1114 case format_32bppGrayFloat
:
1118 UINT srcstride
, srcdatasize
;
1120 srcstride
= 4 * prc
->Width
;
1121 srcdatasize
= srcstride
* prc
->Height
;
1123 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1124 if (!srcdata
) return E_OUTOFMEMORY
;
1126 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1131 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1133 for (y
= 0; y
< prc
->Height
; y
++)
1135 float *gray_float
= (float *)src
;
1138 for (x
= 0; x
< prc
->Width
; x
++)
1140 BYTE gray
= (BYTE
)floorf(to_sRGB_component(gray_float
[x
]) * 255.0f
+ 0.51f
);
1150 HeapFree(GetProcessHeap(), 0, srcdata
);
1156 case format_32bppCMYK
:
1160 UINT srcstride
, srcdatasize
;
1162 srcstride
= 4 * prc
->Width
;
1163 srcdatasize
= srcstride
* prc
->Height
;
1165 srcdata
= heap_alloc(srcdatasize
);
1166 if (!srcdata
) return E_OUTOFMEMORY
;
1168 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1172 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1174 for (y
= 0; y
< prc
->Height
; y
++)
1179 for (x
= 0; x
< prc
->Width
; x
++)
1181 BYTE c
= cmyk
[0], m
= cmyk
[1], y
= cmyk
[2], k
= cmyk
[3];
1182 bgr
[0] = (255 - y
) * (255 - k
) / 255; /* B */
1183 bgr
[1] = (255 - m
) * (255 - k
) / 255; /* G */
1184 bgr
[2] = (255 - c
) * (255 - k
) / 255; /* R */
1199 FIXME("Unimplemented conversion path!\n");
1200 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1204 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
1205 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1209 switch (source_format
)
1211 case format_24bppBGR
:
1212 case format_24bppRGB
:
1215 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1216 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
1217 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1221 case format_32bppBGR
:
1222 case format_32bppBGRA
:
1223 case format_32bppPBGRA
:
1229 UINT srcstride
, srcdatasize
;
1231 const BYTE
*srcpixel
;
1236 srcstride
= 4 * prc
->Width
;
1237 srcdatasize
= srcstride
* prc
->Height
;
1239 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1240 if (!srcdata
) return E_OUTOFMEMORY
;
1242 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1248 for (y
=0; y
<prc
->Height
; y
++) {
1251 for (x
=0; x
<prc
->Width
; x
++) {
1252 tmppixel
[0]=*srcpixel
++; /* blue */
1253 tmppixel
[1]=*srcpixel
++; /* green */
1254 tmppixel
[2]=*srcpixel
++; /* red */
1255 srcpixel
++; /* alpha */
1257 *dstpixel
++=tmppixel
[2]; /* red */
1258 *dstpixel
++=tmppixel
[1]; /* green */
1259 *dstpixel
++=tmppixel
[0]; /* blue */
1261 srcrow
+= srcstride
;
1266 HeapFree(GetProcessHeap(), 0, srcdata
);
1272 FIXME("Unimplemented conversion path!\n");
1273 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1277 static HRESULT
copypixels_to_32bppGrayFloat(struct FormatConverter
*This
, const WICRect
*prc
,
1278 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1282 switch (source_format
)
1284 case format_32bppBGR
:
1285 case format_32bppBGRA
:
1286 case format_32bppPBGRA
:
1287 case format_32bppGrayFloat
:
1290 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1296 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1300 if (SUCCEEDED(hr
) && prc
&& source_format
!= format_32bppGrayFloat
)
1305 for (y
= 0; y
< prc
->Height
; y
++)
1308 for (x
= 0; x
< prc
->Width
; x
++)
1310 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1311 *(float *)bgr
= gray
;
1320 static HRESULT
copypixels_to_8bppGray(struct FormatConverter
*This
, const WICRect
*prc
,
1321 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1325 UINT srcstride
, srcdatasize
;
1327 if (source_format
== format_8bppGray
)
1330 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1335 if (source_format
== format_32bppGrayFloat
)
1341 srcstride
= 4 * prc
->Width
;
1342 srcdatasize
= srcstride
* prc
->Height
;
1344 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1345 if (!srcdata
) return E_OUTOFMEMORY
;
1347 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1351 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1353 for (y
=0; y
< prc
->Height
; y
++)
1355 float *srcpixel
= (float*)src
;
1356 BYTE
*dstpixel
= dst
;
1358 for (x
=0; x
< prc
->Width
; x
++)
1359 *dstpixel
++ = (BYTE
)floorf(to_sRGB_component(*srcpixel
++) * 255.0f
+ 0.51f
);
1366 HeapFree(GetProcessHeap(), 0, srcdata
);
1373 return copypixels_to_24bppBGR(This
, NULL
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1375 srcstride
= 3 * prc
->Width
;
1376 srcdatasize
= srcstride
* prc
->Height
;
1378 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1379 if (!srcdata
) return E_OUTOFMEMORY
;
1381 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1385 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1387 for (y
= 0; y
< prc
->Height
; y
++)
1391 for (x
= 0; x
< prc
->Width
; x
++)
1393 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1395 gray
= to_sRGB_component(gray
) * 255.0f
;
1396 dst
[x
] = (BYTE
)floorf(gray
+ 0.51f
);
1404 HeapFree(GetProcessHeap(), 0, srcdata
);
1408 static UINT
rgb_to_palette_index(BYTE bgr
[3], WICColor
*colors
, UINT count
)
1410 UINT best_diff
, best_index
, i
;
1415 for (i
= 0; i
< count
; i
++)
1417 BYTE pal_r
, pal_g
, pal_b
;
1418 UINT diff_r
, diff_g
, diff_b
, diff
;
1420 pal_r
= colors
[i
] >> 16;
1421 pal_g
= colors
[i
] >> 8;
1424 diff_r
= bgr
[2] - pal_r
;
1425 diff_g
= bgr
[1] - pal_g
;
1426 diff_b
= bgr
[0] - pal_b
;
1428 diff
= diff_r
* diff_r
+ diff_g
* diff_g
+ diff_b
* diff_b
;
1429 if (diff
== 0) return i
;
1431 if (diff
< best_diff
)
1441 static HRESULT
copypixels_to_8bppIndexed(struct FormatConverter
*This
, const WICRect
*prc
,
1442 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1446 WICColor colors
[256];
1447 UINT srcstride
, srcdatasize
, count
;
1449 if (source_format
== format_8bppIndexed
)
1452 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1458 return copypixels_to_24bppBGR(This
, NULL
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1460 if (!This
->palette
) return WINCODEC_ERR_WRONGSTATE
;
1462 hr
= IWICPalette_GetColors(This
->palette
, 256, colors
, &count
);
1463 if (hr
!= S_OK
) return hr
;
1465 srcstride
= 3 * prc
->Width
;
1466 srcdatasize
= srcstride
* prc
->Height
;
1468 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1469 if (!srcdata
) return E_OUTOFMEMORY
;
1471 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1475 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1477 for (y
= 0; y
< prc
->Height
; y
++)
1481 for (x
= 0; x
< prc
->Width
; x
++)
1483 dst
[x
] = rgb_to_palette_index(bgr
, colors
, count
);
1491 HeapFree(GetProcessHeap(), 0, srcdata
);
1495 static const struct pixelformatinfo supported_formats
[] = {
1496 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
1497 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
1498 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1499 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, copypixels_to_8bppIndexed
},
1500 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1501 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1502 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1503 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, copypixels_to_8bppGray
},
1504 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1505 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1506 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1507 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1508 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1509 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1510 {format_32bppGrayFloat
, &GUID_WICPixelFormat32bppGrayFloat
, copypixels_to_32bppGrayFloat
},
1511 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1512 {format_32bppRGB
, &GUID_WICPixelFormat32bppRGB
, copypixels_to_32bppRGB
},
1513 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1514 {format_32bppRGBA
, &GUID_WICPixelFormat32bppRGBA
, copypixels_to_32bppRGBA
},
1515 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1516 {format_32bppPRGBA
, &GUID_WICPixelFormat32bppPRGBA
, copypixels_to_32bppPRGBA
},
1517 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1518 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1519 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1523 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1527 for (i
=0; supported_formats
[i
].guid
; i
++)
1528 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1533 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1536 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1537 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1539 if (!ppv
) return E_INVALIDARG
;
1541 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1542 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1543 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1545 *ppv
= &This
->IWICFormatConverter_iface
;
1550 return E_NOINTERFACE
;
1553 IUnknown_AddRef((IUnknown
*)*ppv
);
1557 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1559 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1560 ULONG ref
= InterlockedIncrement(&This
->ref
);
1562 TRACE("(%p) refcount=%u\n", iface
, ref
);
1567 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1569 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1570 ULONG ref
= InterlockedDecrement(&This
->ref
);
1572 TRACE("(%p) refcount=%u\n", iface
, ref
);
1576 This
->lock
.DebugInfo
->Spare
[0] = 0;
1577 DeleteCriticalSection(&This
->lock
);
1578 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1579 if (This
->palette
) IWICPalette_Release(This
->palette
);
1580 HeapFree(GetProcessHeap(), 0, This
);
1586 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1587 UINT
*puiWidth
, UINT
*puiHeight
)
1589 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1591 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1594 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1596 return WINCODEC_ERR_NOTINITIALIZED
;
1599 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1600 WICPixelFormatGUID
*pPixelFormat
)
1602 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1604 TRACE("(%p,%p)\n", iface
, pPixelFormat
);
1607 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1609 return WINCODEC_ERR_NOTINITIALIZED
;
1614 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1615 double *pDpiX
, double *pDpiY
)
1617 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1619 TRACE("(%p,%p,%p)\n", iface
, pDpiX
, pDpiY
);
1622 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1624 return WINCODEC_ERR_NOTINITIALIZED
;
1627 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1628 IWICPalette
*palette
)
1630 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1632 TRACE("(%p,%p)\n", iface
, palette
);
1634 if (!palette
) return E_INVALIDARG
;
1635 if (!This
->source
) return WINCODEC_ERR_WRONGSTATE
;
1642 hr
= get_pixelformat_bpp(This
->dst_format
->guid
, &bpp
);
1643 if (hr
!= S_OK
) return hr
;
1644 if (bpp
<= 8) return WINCODEC_ERR_WRONGSTATE
;
1645 return IWICBitmapSource_CopyPalette(This
->source
, palette
);
1648 return IWICPalette_InitializeFromPalette(palette
, This
->palette
);
1651 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1652 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1654 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1657 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
1664 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1665 if (FAILED(hr
)) return hr
;
1673 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1674 pbBuffer
, This
->src_format
->format
);
1677 return WINCODEC_ERR_WRONGSTATE
;
1680 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1681 IWICBitmapSource
*source
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1682 IWICPalette
*palette
, double alpha_threshold
, WICBitmapPaletteType palette_type
)
1684 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1685 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1689 TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface
, source
, debugstr_guid(dstFormat
),
1690 dither
, palette
, alpha_threshold
, palette_type
);
1695 res
= get_pixelformat_bpp(dstFormat
, &bpp
);
1696 if (res
!= S_OK
) return res
;
1698 res
= PaletteImpl_Create(&palette
);
1699 if (res
!= S_OK
) return res
;
1701 switch (palette_type
)
1703 case WICBitmapPaletteTypeCustom
:
1704 IWICPalette_Release(palette
);
1706 if (bpp
<= 8) return E_INVALIDARG
;
1709 case WICBitmapPaletteTypeMedianCut
:
1712 res
= IWICPalette_InitializeFromBitmap(palette
, source
, 1 << bpp
, FALSE
);
1718 res
= IWICPalette_InitializePredefined(palette
, palette_type
, FALSE
);
1724 IWICPalette_Release(palette
);
1729 IWICPalette_AddRef(palette
);
1731 EnterCriticalSection(&This
->lock
);
1735 res
= WINCODEC_ERR_WRONGSTATE
;
1739 res
= IWICBitmapSource_GetPixelFormat(source
, &srcFormat
);
1740 if (FAILED(res
)) goto end
;
1742 srcinfo
= get_formatinfo(&srcFormat
);
1745 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1746 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1750 dstinfo
= get_formatinfo(dstFormat
);
1753 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1754 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1758 if (dstinfo
->copy_function
)
1760 IWICBitmapSource_AddRef(source
);
1761 This
->src_format
= srcinfo
;
1762 This
->dst_format
= dstinfo
;
1763 This
->dither
= dither
;
1764 This
->alpha_threshold
= alpha_threshold
;
1765 This
->palette
= palette
;
1766 This
->source
= source
;
1770 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1771 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1776 LeaveCriticalSection(&This
->lock
);
1778 if (res
!= S_OK
&& palette
)
1779 IWICPalette_Release(palette
);
1784 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1785 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1788 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1789 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1791 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1792 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1794 srcinfo
= get_formatinfo(srcPixelFormat
);
1797 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1798 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1801 dstinfo
= get_formatinfo(dstPixelFormat
);
1804 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1805 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1808 if (dstinfo
->copy_function
&&
1809 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1810 *pfCanConvert
= TRUE
;
1813 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1814 *pfCanConvert
= FALSE
;
1820 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1821 FormatConverter_QueryInterface
,
1822 FormatConverter_AddRef
,
1823 FormatConverter_Release
,
1824 FormatConverter_GetSize
,
1825 FormatConverter_GetPixelFormat
,
1826 FormatConverter_GetResolution
,
1827 FormatConverter_CopyPalette
,
1828 FormatConverter_CopyPixels
,
1829 FormatConverter_Initialize
,
1830 FormatConverter_CanConvert
1833 HRESULT
FormatConverter_CreateInstance(REFIID iid
, void** ppv
)
1835 FormatConverter
*This
;
1838 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1842 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1843 if (!This
) return E_OUTOFMEMORY
;
1845 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1847 This
->source
= NULL
;
1848 This
->palette
= NULL
;
1849 InitializeCriticalSection(&This
->lock
);
1850 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1852 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1853 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);