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 */
88 static inline float to_sRGB_component(float f
)
90 if (f
<= 0.0031308f
) return 12.92f
* f
;
91 return 1.055f
* powf(f
, 1.0f
/2.4f
) - 0.055f
;
94 #if 0 /* FIXME: enable once needed */
95 static inline float from_sRGB_component(float f
)
97 if (f
<= 0.04045f
) return f
/ 12.92f
;
98 return powf((f
+ 0.055f
) / 1.055f
, 2.4f
);
101 static void from_sRGB(BYTE
*bgr
)
109 r
= from_sRGB_component(r
);
110 g
= from_sRGB_component(g
);
111 b
= from_sRGB_component(b
);
113 bgr
[2] = (BYTE
)(r
* 255.0f
);
114 bgr
[1] = (BYTE
)(g
* 255.0f
);
115 bgr
[0] = (BYTE
)(b
* 255.0f
);
118 static void to_sRGB(BYTE
*bgr
)
126 r
= to_sRGB_component(r
);
127 g
= to_sRGB_component(g
);
128 b
= to_sRGB_component(b
);
130 bgr
[2] = (BYTE
)(r
* 255.0f
);
131 bgr
[1] = (BYTE
)(g
* 255.0f
);
132 bgr
[0] = (BYTE
)(b
* 255.0f
);
136 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
138 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
141 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
142 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
144 switch (source_format
)
146 case format_1bppIndexed
:
147 case format_BlackWhite
:
153 UINT srcstride
, srcdatasize
;
159 IWICPalette
*palette
;
162 res
= PaletteImpl_Create(&palette
);
163 if (FAILED(res
)) return res
;
165 if (source_format
== format_1bppIndexed
)
166 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
168 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
171 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
173 IWICPalette_Release(palette
);
174 if (FAILED(res
)) return res
;
176 srcstride
= (prc
->Width
+7)/8;
177 srcdatasize
= srcstride
* prc
->Height
;
179 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
180 if (!srcdata
) return E_OUTOFMEMORY
;
182 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
188 for (y
=0; y
<prc
->Height
; y
++) {
190 dstpixel
=(DWORD
*)dstrow
;
191 for (x
=0; x
<prc
->Width
; x
+=8) {
194 *dstpixel
++ = colors
[srcval
>>7&1];
195 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
196 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
197 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
198 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
199 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
200 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
201 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
208 HeapFree(GetProcessHeap(), 0, srcdata
);
213 case format_2bppIndexed
:
214 case format_2bppGray
:
220 UINT srcstride
, srcdatasize
;
226 IWICPalette
*palette
;
229 res
= PaletteImpl_Create(&palette
);
230 if (FAILED(res
)) return res
;
232 if (source_format
== format_2bppIndexed
)
233 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
235 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
238 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
240 IWICPalette_Release(palette
);
241 if (FAILED(res
)) return res
;
243 srcstride
= (prc
->Width
+3)/4;
244 srcdatasize
= srcstride
* prc
->Height
;
246 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
247 if (!srcdata
) return E_OUTOFMEMORY
;
249 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
255 for (y
=0; y
<prc
->Height
; y
++) {
257 dstpixel
=(DWORD
*)dstrow
;
258 for (x
=0; x
<prc
->Width
; x
+=4) {
261 *dstpixel
++ = colors
[srcval
>>6];
262 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
263 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
264 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
271 HeapFree(GetProcessHeap(), 0, srcdata
);
276 case format_4bppIndexed
:
277 case format_4bppGray
:
283 UINT srcstride
, srcdatasize
;
289 IWICPalette
*palette
;
292 res
= PaletteImpl_Create(&palette
);
293 if (FAILED(res
)) return res
;
295 if (source_format
== format_4bppIndexed
)
296 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
298 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
301 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
303 IWICPalette_Release(palette
);
304 if (FAILED(res
)) return res
;
306 srcstride
= (prc
->Width
+1)/2;
307 srcdatasize
= srcstride
* prc
->Height
;
309 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
310 if (!srcdata
) return E_OUTOFMEMORY
;
312 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
318 for (y
=0; y
<prc
->Height
; y
++) {
320 dstpixel
=(DWORD
*)dstrow
;
321 for (x
=0; x
<prc
->Width
; x
+=2) {
324 *dstpixel
++ = colors
[srcval
>>4];
325 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
332 HeapFree(GetProcessHeap(), 0, srcdata
);
337 case format_8bppGray
:
343 UINT srcstride
, srcdatasize
;
349 srcstride
= prc
->Width
;
350 srcdatasize
= srcstride
* prc
->Height
;
352 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
353 if (!srcdata
) return E_OUTOFMEMORY
;
355 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
361 for (y
=0; y
<prc
->Height
; y
++) {
363 dstpixel
=(DWORD
*)dstrow
;
364 for (x
=0; x
<prc
->Width
; x
++)
366 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
374 HeapFree(GetProcessHeap(), 0, srcdata
);
379 case format_8bppIndexed
:
385 UINT srcstride
, srcdatasize
;
390 WICColor colors
[256];
391 IWICPalette
*palette
;
394 res
= PaletteImpl_Create(&palette
);
395 if (FAILED(res
)) return res
;
397 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
399 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
401 IWICPalette_Release(palette
);
403 if (FAILED(res
)) return res
;
405 srcstride
= prc
->Width
;
406 srcdatasize
= srcstride
* prc
->Height
;
408 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
409 if (!srcdata
) return E_OUTOFMEMORY
;
411 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
417 for (y
=0; y
<prc
->Height
; y
++) {
419 dstpixel
=(DWORD
*)dstrow
;
420 for (x
=0; x
<prc
->Width
; x
++)
421 *dstpixel
++ = colors
[*srcbyte
++];
427 HeapFree(GetProcessHeap(), 0, srcdata
);
432 case format_16bppGray
:
438 UINT srcstride
, srcdatasize
;
444 srcstride
= prc
->Width
* 2;
445 srcdatasize
= srcstride
* prc
->Height
;
447 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
448 if (!srcdata
) return E_OUTOFMEMORY
;
450 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
456 for (y
=0; y
<prc
->Height
; y
++) {
458 dstpixel
=(DWORD
*)dstrow
;
459 for (x
=0; x
<prc
->Width
; x
++)
462 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
470 HeapFree(GetProcessHeap(), 0, srcdata
);
475 case format_16bppBGR555
:
481 UINT srcstride
, srcdatasize
;
483 const WORD
*srcpixel
;
487 srcstride
= 2 * prc
->Width
;
488 srcdatasize
= srcstride
* prc
->Height
;
490 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
491 if (!srcdata
) return E_OUTOFMEMORY
;
493 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
499 for (y
=0; y
<prc
->Height
; y
++) {
500 srcpixel
=(const WORD
*)srcrow
;
501 dstpixel
=(DWORD
*)dstrow
;
502 for (x
=0; x
<prc
->Width
; x
++) {
505 *dstpixel
++=0xff000000 | /* constant 255 alpha */
506 ((srcval
<< 9) & 0xf80000) | /* r */
507 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
508 ((srcval
<< 6) & 0x00f800) | /* g */
509 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
510 ((srcval
<< 3) & 0x0000f8) | /* b */
511 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
518 HeapFree(GetProcessHeap(), 0, srcdata
);
523 case format_16bppBGR565
:
529 UINT srcstride
, srcdatasize
;
531 const WORD
*srcpixel
;
535 srcstride
= 2 * prc
->Width
;
536 srcdatasize
= srcstride
* prc
->Height
;
538 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
539 if (!srcdata
) return E_OUTOFMEMORY
;
541 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
547 for (y
=0; y
<prc
->Height
; y
++) {
548 srcpixel
=(const WORD
*)srcrow
;
549 dstpixel
=(DWORD
*)dstrow
;
550 for (x
=0; x
<prc
->Width
; x
++) {
553 *dstpixel
++=0xff000000 | /* constant 255 alpha */
554 ((srcval
<< 8) & 0xf80000) | /* r */
555 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
556 ((srcval
<< 5) & 0x00fc00) | /* g */
557 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
558 ((srcval
<< 3) & 0x0000f8) | /* b */
559 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
566 HeapFree(GetProcessHeap(), 0, srcdata
);
571 case format_16bppBGRA5551
:
577 UINT srcstride
, srcdatasize
;
579 const WORD
*srcpixel
;
583 srcstride
= 2 * prc
->Width
;
584 srcdatasize
= srcstride
* prc
->Height
;
586 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
587 if (!srcdata
) return E_OUTOFMEMORY
;
589 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
595 for (y
=0; y
<prc
->Height
; y
++) {
596 srcpixel
=(const WORD
*)srcrow
;
597 dstpixel
=(DWORD
*)dstrow
;
598 for (x
=0; x
<prc
->Width
; x
++) {
601 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
602 ((srcval
<< 9) & 0xf80000) | /* r */
603 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
604 ((srcval
<< 6) & 0x00f800) | /* g */
605 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
606 ((srcval
<< 3) & 0x0000f8) | /* b */
607 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
614 HeapFree(GetProcessHeap(), 0, srcdata
);
619 case format_24bppBGR
:
625 UINT srcstride
, srcdatasize
;
627 const BYTE
*srcpixel
;
631 srcstride
= 3 * prc
->Width
;
632 srcdatasize
= srcstride
* prc
->Height
;
634 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
635 if (!srcdata
) return E_OUTOFMEMORY
;
637 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
643 for (y
=0; y
<prc
->Height
; y
++) {
646 for (x
=0; x
<prc
->Width
; x
++) {
647 *dstpixel
++=*srcpixel
++; /* blue */
648 *dstpixel
++=*srcpixel
++; /* green */
649 *dstpixel
++=*srcpixel
++; /* red */
650 *dstpixel
++=255; /* alpha */
657 HeapFree(GetProcessHeap(), 0, srcdata
);
662 case format_24bppRGB
:
668 UINT srcstride
, srcdatasize
;
670 const BYTE
*srcpixel
;
675 srcstride
= 3 * prc
->Width
;
676 srcdatasize
= srcstride
* prc
->Height
;
678 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
679 if (!srcdata
) return E_OUTOFMEMORY
;
681 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
687 for (y
=0; y
<prc
->Height
; y
++) {
690 for (x
=0; x
<prc
->Width
; x
++) {
691 tmppixel
[0]=*srcpixel
++; /* red */
692 tmppixel
[1]=*srcpixel
++; /* green */
693 tmppixel
[2]=*srcpixel
++; /* blue */
695 *dstpixel
++=tmppixel
[2]; /* blue */
696 *dstpixel
++=tmppixel
[1]; /* green */
697 *dstpixel
++=tmppixel
[0]; /* red */
698 *dstpixel
++=255; /* alpha */
705 HeapFree(GetProcessHeap(), 0, srcdata
);
710 case format_32bppBGR
:
716 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
717 if (FAILED(res
)) return res
;
719 /* set all alpha values to 255 */
720 for (y
=0; y
<prc
->Height
; y
++)
721 for (x
=0; x
<prc
->Width
; x
++)
722 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
725 case format_32bppRGBA
:
729 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
730 if (FAILED(res
)) return res
;
731 reverse_bgr8(4, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
734 case format_32bppBGRA
:
736 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
738 case format_32bppPBGRA
:
744 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
745 if (FAILED(res
)) return res
;
747 for (y
=0; y
<prc
->Height
; y
++)
748 for (x
=0; x
<prc
->Width
; x
++)
750 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
751 if (alpha
!= 0 && alpha
!= 255)
753 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
754 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
755 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
760 case format_48bppRGB
:
766 UINT srcstride
, srcdatasize
;
768 const BYTE
*srcpixel
;
772 srcstride
= 6 * prc
->Width
;
773 srcdatasize
= srcstride
* prc
->Height
;
775 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
776 if (!srcdata
) return E_OUTOFMEMORY
;
778 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
784 for (y
=0; y
<prc
->Height
; y
++) {
786 dstpixel
=(DWORD
*)dstrow
;
787 for (x
=0; x
<prc
->Width
; x
++) {
788 BYTE red
, green
, blue
;
789 srcpixel
++; red
= *srcpixel
++;
790 srcpixel
++; green
= *srcpixel
++;
791 srcpixel
++; blue
= *srcpixel
++;
792 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
799 HeapFree(GetProcessHeap(), 0, srcdata
);
804 case format_64bppRGBA
:
810 UINT srcstride
, srcdatasize
;
812 const BYTE
*srcpixel
;
816 srcstride
= 8 * prc
->Width
;
817 srcdatasize
= srcstride
* prc
->Height
;
819 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
820 if (!srcdata
) return E_OUTOFMEMORY
;
822 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
828 for (y
=0; y
<prc
->Height
; y
++) {
830 dstpixel
=(DWORD
*)dstrow
;
831 for (x
=0; x
<prc
->Width
; x
++) {
832 BYTE red
, green
, blue
, alpha
;
833 srcpixel
++; red
= *srcpixel
++;
834 srcpixel
++; green
= *srcpixel
++;
835 srcpixel
++; blue
= *srcpixel
++;
836 srcpixel
++; alpha
= *srcpixel
++;
837 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
844 HeapFree(GetProcessHeap(), 0, srcdata
);
849 case format_32bppCMYK
:
855 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
856 if (FAILED(res
)) return res
;
858 for (y
=0; y
<prc
->Height
; y
++)
859 for (x
=0; x
<prc
->Width
; x
++)
861 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
862 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
863 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
864 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
865 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
866 pixel
[3] = 255; /* alpha */
871 FIXME("Unimplemented conversion path!\n");
872 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
876 static HRESULT
copypixels_to_32bppRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
877 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
881 switch (source_format
)
883 case format_32bppRGB
:
888 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
889 if (FAILED(hr
)) return hr
;
891 /* set all alpha values to 255 */
892 for (y
=0; y
<prc
->Height
; y
++)
893 for (x
=0; x
<prc
->Width
; x
++)
894 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
898 case format_32bppRGBA
:
900 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
903 case format_32bppPRGBA
:
908 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
909 if (FAILED(hr
)) return hr
;
911 for (y
=0; y
<prc
->Height
; y
++)
912 for (x
=0; x
<prc
->Width
; x
++)
914 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
915 if (alpha
!= 0 && alpha
!= 255)
917 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
918 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
919 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
926 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
927 if (SUCCEEDED(hr
) && prc
)
928 reverse_bgr8(4, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
933 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
934 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
936 switch (source_format
)
938 case format_32bppBGR
:
939 case format_32bppBGRA
:
940 case format_32bppPBGRA
:
942 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
945 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
949 static HRESULT
copypixels_to_32bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
950 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
952 switch (source_format
)
954 case format_32bppRGB
:
955 case format_32bppRGBA
:
956 case format_32bppPRGBA
:
958 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
961 return copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
965 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
966 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
970 switch (source_format
)
972 case format_32bppPBGRA
:
974 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
977 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
978 if (SUCCEEDED(hr
) && prc
)
982 for (y
=0; y
<prc
->Height
; y
++)
983 for (x
=0; x
<prc
->Width
; x
++)
985 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
988 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
989 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
990 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
998 static HRESULT
copypixels_to_32bppPRGBA(struct FormatConverter
*This
, const WICRect
*prc
,
999 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1003 switch (source_format
)
1005 case format_32bppPRGBA
:
1007 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1010 hr
= copypixels_to_32bppRGBA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1011 if (SUCCEEDED(hr
) && prc
)
1015 for (y
=0; y
<prc
->Height
; y
++)
1016 for (x
=0; x
<prc
->Width
; x
++)
1018 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
1021 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
1022 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
1023 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
1031 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
1032 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1036 switch (source_format
)
1038 case format_24bppBGR
:
1039 case format_24bppRGB
:
1042 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1043 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
1044 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1048 case format_32bppBGR
:
1049 case format_32bppBGRA
:
1050 case format_32bppPBGRA
:
1051 case format_32bppRGBA
:
1057 UINT srcstride
, srcdatasize
;
1059 const BYTE
*srcpixel
;
1063 srcstride
= 4 * prc
->Width
;
1064 srcdatasize
= srcstride
* prc
->Height
;
1066 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1067 if (!srcdata
) return E_OUTOFMEMORY
;
1069 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1076 if (source_format
== format_32bppRGBA
)
1078 for (y
= 0; y
< prc
->Height
; y
++)
1082 for (x
= 0; x
< prc
->Width
; x
++) {
1083 *dstpixel
++ = srcpixel
[2]; /* blue */
1084 *dstpixel
++ = srcpixel
[1]; /* green */
1085 *dstpixel
++ = srcpixel
[0]; /* red */
1088 srcrow
+= srcstride
;
1094 for (y
= 0; y
< prc
->Height
; y
++)
1098 for (x
= 0; x
< prc
->Width
; x
++) {
1099 *dstpixel
++ = *srcpixel
++; /* blue */
1100 *dstpixel
++ = *srcpixel
++; /* green */
1101 *dstpixel
++ = *srcpixel
++; /* red */
1102 srcpixel
++; /* alpha */
1104 srcrow
+= srcstride
;
1110 HeapFree(GetProcessHeap(), 0, srcdata
);
1116 case format_32bppGrayFloat
:
1120 UINT srcstride
, srcdatasize
;
1122 srcstride
= 4 * prc
->Width
;
1123 srcdatasize
= srcstride
* prc
->Height
;
1125 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1126 if (!srcdata
) return E_OUTOFMEMORY
;
1128 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1133 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1135 for (y
= 0; y
< prc
->Height
; y
++)
1137 float *gray_float
= (float *)src
;
1140 for (x
= 0; x
< prc
->Width
; x
++)
1142 BYTE gray
= (BYTE
)floorf(to_sRGB_component(gray_float
[x
]) * 255.0f
+ 0.51f
);
1152 HeapFree(GetProcessHeap(), 0, srcdata
);
1158 case format_32bppCMYK
:
1162 UINT srcstride
, srcdatasize
;
1164 srcstride
= 4 * prc
->Width
;
1165 srcdatasize
= srcstride
* prc
->Height
;
1167 srcdata
= heap_alloc(srcdatasize
);
1168 if (!srcdata
) return E_OUTOFMEMORY
;
1170 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1174 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1176 for (y
= 0; y
< prc
->Height
; y
++)
1181 for (x
= 0; x
< prc
->Width
; x
++)
1183 BYTE c
= cmyk
[0], m
= cmyk
[1], y
= cmyk
[2], k
= cmyk
[3];
1184 bgr
[0] = (255 - y
) * (255 - k
) / 255; /* B */
1185 bgr
[1] = (255 - m
) * (255 - k
) / 255; /* G */
1186 bgr
[2] = (255 - c
) * (255 - k
) / 255; /* R */
1201 FIXME("Unimplemented conversion path!\n");
1202 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1206 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
1207 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1211 switch (source_format
)
1213 case format_24bppBGR
:
1214 case format_24bppRGB
:
1217 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1218 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
1219 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
1223 case format_32bppBGR
:
1224 case format_32bppBGRA
:
1225 case format_32bppPBGRA
:
1231 UINT srcstride
, srcdatasize
;
1233 const BYTE
*srcpixel
;
1238 srcstride
= 4 * prc
->Width
;
1239 srcdatasize
= srcstride
* prc
->Height
;
1241 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1242 if (!srcdata
) return E_OUTOFMEMORY
;
1244 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1250 for (y
=0; y
<prc
->Height
; y
++) {
1253 for (x
=0; x
<prc
->Width
; x
++) {
1254 tmppixel
[0]=*srcpixel
++; /* blue */
1255 tmppixel
[1]=*srcpixel
++; /* green */
1256 tmppixel
[2]=*srcpixel
++; /* red */
1257 srcpixel
++; /* alpha */
1259 *dstpixel
++=tmppixel
[2]; /* red */
1260 *dstpixel
++=tmppixel
[1]; /* green */
1261 *dstpixel
++=tmppixel
[0]; /* blue */
1263 srcrow
+= srcstride
;
1268 HeapFree(GetProcessHeap(), 0, srcdata
);
1274 FIXME("Unimplemented conversion path!\n");
1275 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1279 static HRESULT
copypixels_to_32bppGrayFloat(struct FormatConverter
*This
, const WICRect
*prc
,
1280 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1284 switch (source_format
)
1286 case format_32bppBGR
:
1287 case format_32bppBGRA
:
1288 case format_32bppPBGRA
:
1289 case format_32bppGrayFloat
:
1292 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1298 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1302 if (SUCCEEDED(hr
) && prc
&& source_format
!= format_32bppGrayFloat
)
1307 for (y
= 0; y
< prc
->Height
; y
++)
1310 for (x
= 0; x
< prc
->Width
; x
++)
1312 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1313 *(float *)bgr
= gray
;
1322 static HRESULT
copypixels_to_8bppGray(struct FormatConverter
*This
, const WICRect
*prc
,
1323 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1327 UINT srcstride
, srcdatasize
;
1329 if (source_format
== format_8bppGray
)
1332 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1337 if (source_format
== format_32bppGrayFloat
)
1343 srcstride
= 4 * prc
->Width
;
1344 srcdatasize
= srcstride
* prc
->Height
;
1346 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1347 if (!srcdata
) return E_OUTOFMEMORY
;
1349 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
1353 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1355 for (y
=0; y
< prc
->Height
; y
++)
1357 float *srcpixel
= (float*)src
;
1358 BYTE
*dstpixel
= dst
;
1360 for (x
=0; x
< prc
->Width
; x
++)
1361 *dstpixel
++ = (BYTE
)floorf(to_sRGB_component(*srcpixel
++) * 255.0f
+ 0.51f
);
1368 HeapFree(GetProcessHeap(), 0, srcdata
);
1375 return copypixels_to_24bppBGR(This
, NULL
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1377 srcstride
= 3 * prc
->Width
;
1378 srcdatasize
= srcstride
* prc
->Height
;
1380 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1381 if (!srcdata
) return E_OUTOFMEMORY
;
1383 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1387 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1389 for (y
= 0; y
< prc
->Height
; y
++)
1393 for (x
= 0; x
< prc
->Width
; x
++)
1395 float gray
= (bgr
[2] * 0.2126f
+ bgr
[1] * 0.7152f
+ bgr
[0] * 0.0722f
) / 255.0f
;
1397 gray
= to_sRGB_component(gray
) * 255.0f
;
1398 dst
[x
] = (BYTE
)floorf(gray
+ 0.51f
);
1406 HeapFree(GetProcessHeap(), 0, srcdata
);
1410 static UINT
rgb_to_palette_index(BYTE bgr
[3], WICColor
*colors
, UINT count
)
1412 UINT best_diff
, best_index
, i
;
1417 for (i
= 0; i
< count
; i
++)
1419 BYTE pal_r
, pal_g
, pal_b
;
1420 UINT diff_r
, diff_g
, diff_b
, diff
;
1422 pal_r
= colors
[i
] >> 16;
1423 pal_g
= colors
[i
] >> 8;
1426 diff_r
= bgr
[2] - pal_r
;
1427 diff_g
= bgr
[1] - pal_g
;
1428 diff_b
= bgr
[0] - pal_b
;
1430 diff
= diff_r
* diff_r
+ diff_g
* diff_g
+ diff_b
* diff_b
;
1431 if (diff
== 0) return i
;
1433 if (diff
< best_diff
)
1443 static HRESULT
copypixels_to_8bppIndexed(struct FormatConverter
*This
, const WICRect
*prc
,
1444 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
1448 WICColor colors
[256];
1449 UINT srcstride
, srcdatasize
, count
;
1451 if (source_format
== format_8bppIndexed
)
1454 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1460 return copypixels_to_24bppBGR(This
, NULL
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
1462 if (!This
->palette
) return WINCODEC_ERR_WRONGSTATE
;
1464 hr
= IWICPalette_GetColors(This
->palette
, 256, colors
, &count
);
1465 if (hr
!= S_OK
) return hr
;
1467 srcstride
= 3 * prc
->Width
;
1468 srcdatasize
= srcstride
* prc
->Height
;
1470 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
1471 if (!srcdata
) return E_OUTOFMEMORY
;
1473 hr
= copypixels_to_24bppBGR(This
, prc
, srcstride
, srcdatasize
, srcdata
, source_format
);
1477 BYTE
*src
= srcdata
, *dst
= pbBuffer
;
1479 for (y
= 0; y
< prc
->Height
; y
++)
1483 for (x
= 0; x
< prc
->Width
; x
++)
1485 dst
[x
] = rgb_to_palette_index(bgr
, colors
, count
);
1493 HeapFree(GetProcessHeap(), 0, srcdata
);
1497 static const struct pixelformatinfo supported_formats
[] = {
1498 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
1499 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
1500 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1501 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, copypixels_to_8bppIndexed
},
1502 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1503 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1504 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1505 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, copypixels_to_8bppGray
},
1506 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1507 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1508 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1509 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1510 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1511 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1512 {format_32bppGrayFloat
, &GUID_WICPixelFormat32bppGrayFloat
, copypixels_to_32bppGrayFloat
},
1513 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1514 {format_32bppRGB
, &GUID_WICPixelFormat32bppRGB
, copypixels_to_32bppRGB
},
1515 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1516 {format_32bppRGBA
, &GUID_WICPixelFormat32bppRGBA
, copypixels_to_32bppRGBA
},
1517 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1518 {format_32bppPRGBA
, &GUID_WICPixelFormat32bppPRGBA
, copypixels_to_32bppPRGBA
},
1519 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1520 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1521 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1525 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1529 for (i
=0; supported_formats
[i
].guid
; i
++)
1530 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1535 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1538 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1539 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1541 if (!ppv
) return E_INVALIDARG
;
1543 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1544 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1545 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1547 *ppv
= &This
->IWICFormatConverter_iface
;
1552 return E_NOINTERFACE
;
1555 IUnknown_AddRef((IUnknown
*)*ppv
);
1559 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1561 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1562 ULONG ref
= InterlockedIncrement(&This
->ref
);
1564 TRACE("(%p) refcount=%u\n", iface
, ref
);
1569 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1571 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1572 ULONG ref
= InterlockedDecrement(&This
->ref
);
1574 TRACE("(%p) refcount=%u\n", iface
, ref
);
1578 This
->lock
.DebugInfo
->Spare
[0] = 0;
1579 DeleteCriticalSection(&This
->lock
);
1580 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1581 if (This
->palette
) IWICPalette_Release(This
->palette
);
1582 HeapFree(GetProcessHeap(), 0, This
);
1588 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1589 UINT
*puiWidth
, UINT
*puiHeight
)
1591 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1593 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1596 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1598 return WINCODEC_ERR_NOTINITIALIZED
;
1601 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1602 WICPixelFormatGUID
*pPixelFormat
)
1604 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1606 TRACE("(%p,%p)\n", iface
, pPixelFormat
);
1609 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1611 return WINCODEC_ERR_NOTINITIALIZED
;
1616 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1617 double *pDpiX
, double *pDpiY
)
1619 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1621 TRACE("(%p,%p,%p)\n", iface
, pDpiX
, pDpiY
);
1624 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1626 return WINCODEC_ERR_NOTINITIALIZED
;
1629 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1630 IWICPalette
*palette
)
1632 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1634 TRACE("(%p,%p)\n", iface
, palette
);
1636 if (!palette
) return E_INVALIDARG
;
1637 if (!This
->source
) return WINCODEC_ERR_WRONGSTATE
;
1644 hr
= get_pixelformat_bpp(This
->dst_format
->guid
, &bpp
);
1645 if (hr
!= S_OK
) return hr
;
1646 if (bpp
<= 8) return WINCODEC_ERR_WRONGSTATE
;
1647 return IWICBitmapSource_CopyPalette(This
->source
, palette
);
1650 return IWICPalette_InitializeFromPalette(palette
, This
->palette
);
1653 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1654 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1656 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1659 TRACE("(%p,%s,%u,%u,%p)\n", iface
, debug_wic_rect(prc
), cbStride
, cbBufferSize
, pbBuffer
);
1666 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1667 if (FAILED(hr
)) return hr
;
1675 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1676 pbBuffer
, This
->src_format
->format
);
1679 return WINCODEC_ERR_WRONGSTATE
;
1682 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1683 IWICBitmapSource
*source
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1684 IWICPalette
*palette
, double alpha_threshold
, WICBitmapPaletteType palette_type
)
1686 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1687 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1691 TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface
, source
, debugstr_guid(dstFormat
),
1692 dither
, palette
, alpha_threshold
, palette_type
);
1697 res
= get_pixelformat_bpp(dstFormat
, &bpp
);
1698 if (res
!= S_OK
) return res
;
1700 res
= PaletteImpl_Create(&palette
);
1701 if (res
!= S_OK
) return res
;
1703 switch (palette_type
)
1705 case WICBitmapPaletteTypeCustom
:
1706 IWICPalette_Release(palette
);
1708 if (bpp
<= 8) return E_INVALIDARG
;
1711 case WICBitmapPaletteTypeMedianCut
:
1714 res
= IWICPalette_InitializeFromBitmap(palette
, source
, 1 << bpp
, FALSE
);
1720 res
= IWICPalette_InitializePredefined(palette
, palette_type
, FALSE
);
1726 IWICPalette_Release(palette
);
1731 IWICPalette_AddRef(palette
);
1733 EnterCriticalSection(&This
->lock
);
1737 res
= WINCODEC_ERR_WRONGSTATE
;
1741 res
= IWICBitmapSource_GetPixelFormat(source
, &srcFormat
);
1742 if (FAILED(res
)) goto end
;
1744 srcinfo
= get_formatinfo(&srcFormat
);
1747 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1748 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1752 dstinfo
= get_formatinfo(dstFormat
);
1755 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1756 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1760 if (dstinfo
->copy_function
)
1762 IWICBitmapSource_AddRef(source
);
1763 This
->src_format
= srcinfo
;
1764 This
->dst_format
= dstinfo
;
1765 This
->dither
= dither
;
1766 This
->alpha_threshold
= alpha_threshold
;
1767 This
->palette
= palette
;
1768 This
->source
= source
;
1772 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1773 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1778 LeaveCriticalSection(&This
->lock
);
1780 if (res
!= S_OK
&& palette
)
1781 IWICPalette_Release(palette
);
1786 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1787 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1790 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1791 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1793 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1794 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1796 srcinfo
= get_formatinfo(srcPixelFormat
);
1799 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1800 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1803 dstinfo
= get_formatinfo(dstPixelFormat
);
1806 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1807 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1810 if (dstinfo
->copy_function
&&
1811 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1812 *pfCanConvert
= TRUE
;
1815 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1816 *pfCanConvert
= FALSE
;
1822 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1823 FormatConverter_QueryInterface
,
1824 FormatConverter_AddRef
,
1825 FormatConverter_Release
,
1826 FormatConverter_GetSize
,
1827 FormatConverter_GetPixelFormat
,
1828 FormatConverter_GetResolution
,
1829 FormatConverter_CopyPalette
,
1830 FormatConverter_CopyPixels
,
1831 FormatConverter_Initialize
,
1832 FormatConverter_CanConvert
1835 HRESULT
FormatConverter_CreateInstance(REFIID iid
, void** ppv
)
1837 FormatConverter
*This
;
1840 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1844 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1845 if (!This
) return E_OUTOFMEMORY
;
1847 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1849 This
->source
= NULL
;
1850 This
->palette
= NULL
;
1851 InitializeCriticalSection(&This
->lock
);
1852 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1854 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1855 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);