2 * Copyright 2009 Vincent Povirk
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wincodecs_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
35 struct FormatConverter
;
60 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
61 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
63 struct pixelformatinfo
{
64 enum pixelformat format
;
65 const WICPixelFormatGUID
*guid
;
66 copyfunc copy_function
;
69 typedef struct FormatConverter
{
70 IWICFormatConverter IWICFormatConverter_iface
;
72 IWICBitmapSource
*source
;
73 const struct pixelformatinfo
*dst_format
, *src_format
;
74 WICBitmapDitherType dither
;
75 double alpha_threshold
;
76 WICBitmapPaletteType palette_type
;
77 CRITICAL_SECTION lock
; /* must be held when initialized */
80 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
82 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
85 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
86 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
88 switch (source_format
)
90 case format_1bppIndexed
:
91 case format_BlackWhite
:
97 UINT srcstride
, srcdatasize
;
103 IWICPalette
*palette
;
106 res
= PaletteImpl_Create(&palette
);
107 if (FAILED(res
)) return res
;
109 if (source_format
== format_1bppIndexed
)
110 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
112 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
115 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
117 IWICPalette_Release(palette
);
118 if (FAILED(res
)) return res
;
120 srcstride
= (prc
->Width
+7)/8;
121 srcdatasize
= srcstride
* prc
->Height
;
123 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
124 if (!srcdata
) return E_OUTOFMEMORY
;
126 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
132 for (y
=0; y
<prc
->Height
; y
++) {
134 dstpixel
=(DWORD
*)dstrow
;
135 for (x
=0; x
<prc
->Width
; x
+=8) {
138 *dstpixel
++ = colors
[srcval
>>7&1];
139 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
140 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
141 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
142 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
143 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
144 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
145 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
152 HeapFree(GetProcessHeap(), 0, srcdata
);
157 case format_2bppIndexed
:
158 case format_2bppGray
:
164 UINT srcstride
, srcdatasize
;
170 IWICPalette
*palette
;
173 res
= PaletteImpl_Create(&palette
);
174 if (FAILED(res
)) return res
;
176 if (source_format
== format_2bppIndexed
)
177 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
179 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
182 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
184 IWICPalette_Release(palette
);
185 if (FAILED(res
)) return res
;
187 srcstride
= (prc
->Width
+3)/4;
188 srcdatasize
= srcstride
* prc
->Height
;
190 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
191 if (!srcdata
) return E_OUTOFMEMORY
;
193 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
199 for (y
=0; y
<prc
->Height
; y
++) {
201 dstpixel
=(DWORD
*)dstrow
;
202 for (x
=0; x
<prc
->Width
; x
+=4) {
205 *dstpixel
++ = colors
[srcval
>>6];
206 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
207 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
208 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
215 HeapFree(GetProcessHeap(), 0, srcdata
);
220 case format_4bppIndexed
:
221 case format_4bppGray
:
227 UINT srcstride
, srcdatasize
;
233 IWICPalette
*palette
;
236 res
= PaletteImpl_Create(&palette
);
237 if (FAILED(res
)) return res
;
239 if (source_format
== format_4bppIndexed
)
240 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
242 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
245 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
247 IWICPalette_Release(palette
);
248 if (FAILED(res
)) return res
;
250 srcstride
= (prc
->Width
+1)/2;
251 srcdatasize
= srcstride
* prc
->Height
;
253 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
254 if (!srcdata
) return E_OUTOFMEMORY
;
256 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
262 for (y
=0; y
<prc
->Height
; y
++) {
264 dstpixel
=(DWORD
*)dstrow
;
265 for (x
=0; x
<prc
->Width
; x
+=2) {
268 *dstpixel
++ = colors
[srcval
>>4];
269 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
276 HeapFree(GetProcessHeap(), 0, srcdata
);
281 case format_8bppGray
:
287 UINT srcstride
, srcdatasize
;
293 srcstride
= prc
->Width
;
294 srcdatasize
= srcstride
* prc
->Height
;
296 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
297 if (!srcdata
) return E_OUTOFMEMORY
;
299 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
305 for (y
=0; y
<prc
->Height
; y
++) {
307 dstpixel
=(DWORD
*)dstrow
;
308 for (x
=0; x
<prc
->Width
; x
++)
310 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
318 HeapFree(GetProcessHeap(), 0, srcdata
);
323 case format_8bppIndexed
:
329 UINT srcstride
, srcdatasize
;
334 WICColor colors
[256];
335 IWICPalette
*palette
;
338 res
= PaletteImpl_Create(&palette
);
339 if (FAILED(res
)) return res
;
341 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
343 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
345 IWICPalette_Release(palette
);
347 if (FAILED(res
)) return res
;
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
++)
365 *dstpixel
++ = colors
[*srcbyte
++];
371 HeapFree(GetProcessHeap(), 0, srcdata
);
376 case format_16bppGray
:
382 UINT srcstride
, srcdatasize
;
388 srcstride
= prc
->Width
* 2;
389 srcdatasize
= srcstride
* prc
->Height
;
391 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
392 if (!srcdata
) return E_OUTOFMEMORY
;
394 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
400 for (y
=0; y
<prc
->Height
; y
++) {
402 dstpixel
=(DWORD
*)dstrow
;
403 for (x
=0; x
<prc
->Width
; x
++)
405 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
413 HeapFree(GetProcessHeap(), 0, srcdata
);
418 case format_16bppBGR555
:
424 UINT srcstride
, srcdatasize
;
426 const WORD
*srcpixel
;
430 srcstride
= 2 * prc
->Width
;
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
++) {
443 srcpixel
=(const WORD
*)srcrow
;
444 dstpixel
=(DWORD
*)dstrow
;
445 for (x
=0; x
<prc
->Width
; x
++) {
448 *dstpixel
++=0xff000000 | /* constant 255 alpha */
449 ((srcval
<< 9) & 0xf80000) | /* r */
450 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
451 ((srcval
<< 6) & 0x00f800) | /* g */
452 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
453 ((srcval
<< 3) & 0x0000f8) | /* b */
454 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
461 HeapFree(GetProcessHeap(), 0, srcdata
);
466 case format_16bppBGR565
:
472 UINT srcstride
, srcdatasize
;
474 const WORD
*srcpixel
;
478 srcstride
= 2 * prc
->Width
;
479 srcdatasize
= srcstride
* prc
->Height
;
481 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
482 if (!srcdata
) return E_OUTOFMEMORY
;
484 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
490 for (y
=0; y
<prc
->Height
; y
++) {
491 srcpixel
=(const WORD
*)srcrow
;
492 dstpixel
=(DWORD
*)dstrow
;
493 for (x
=0; x
<prc
->Width
; x
++) {
496 *dstpixel
++=0xff000000 | /* constant 255 alpha */
497 ((srcval
<< 8) & 0xf80000) | /* r */
498 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
499 ((srcval
<< 5) & 0x00fc00) | /* g */
500 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
501 ((srcval
<< 3) & 0x0000f8) | /* b */
502 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
509 HeapFree(GetProcessHeap(), 0, srcdata
);
514 case format_16bppBGRA5551
:
520 UINT srcstride
, srcdatasize
;
522 const WORD
*srcpixel
;
526 srcstride
= 2 * prc
->Width
;
527 srcdatasize
= srcstride
* prc
->Height
;
529 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
530 if (!srcdata
) return E_OUTOFMEMORY
;
532 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
538 for (y
=0; y
<prc
->Height
; y
++) {
539 srcpixel
=(const WORD
*)srcrow
;
540 dstpixel
=(DWORD
*)dstrow
;
541 for (x
=0; x
<prc
->Width
; x
++) {
544 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
545 ((srcval
<< 9) & 0xf80000) | /* r */
546 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
547 ((srcval
<< 6) & 0x00f800) | /* g */
548 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
549 ((srcval
<< 3) & 0x0000f8) | /* b */
550 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
557 HeapFree(GetProcessHeap(), 0, srcdata
);
562 case format_24bppBGR
:
568 UINT srcstride
, srcdatasize
;
570 const BYTE
*srcpixel
;
574 srcstride
= 3 * prc
->Width
;
575 srcdatasize
= srcstride
* prc
->Height
;
577 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
578 if (!srcdata
) return E_OUTOFMEMORY
;
580 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
586 for (y
=0; y
<prc
->Height
; y
++) {
589 for (x
=0; x
<prc
->Width
; x
++) {
590 *dstpixel
++=*srcpixel
++; /* blue */
591 *dstpixel
++=*srcpixel
++; /* green */
592 *dstpixel
++=*srcpixel
++; /* red */
593 *dstpixel
++=255; /* alpha */
600 HeapFree(GetProcessHeap(), 0, srcdata
);
605 case format_24bppRGB
:
611 UINT srcstride
, srcdatasize
;
613 const BYTE
*srcpixel
;
618 srcstride
= 3 * prc
->Width
;
619 srcdatasize
= srcstride
* prc
->Height
;
621 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
622 if (!srcdata
) return E_OUTOFMEMORY
;
624 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
630 for (y
=0; y
<prc
->Height
; y
++) {
633 for (x
=0; x
<prc
->Width
; x
++) {
634 tmppixel
[0]=*srcpixel
++; /* red */
635 tmppixel
[1]=*srcpixel
++; /* green */
636 tmppixel
[2]=*srcpixel
++; /* blue */
638 *dstpixel
++=tmppixel
[2]; /* blue */
639 *dstpixel
++=tmppixel
[1]; /* green */
640 *dstpixel
++=tmppixel
[0]; /* red */
641 *dstpixel
++=255; /* alpha */
648 HeapFree(GetProcessHeap(), 0, srcdata
);
653 case format_32bppBGR
:
659 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
660 if (FAILED(res
)) return res
;
662 /* set all alpha values to 255 */
663 for (y
=0; y
<prc
->Height
; y
++)
664 for (x
=0; x
<prc
->Width
; x
++)
665 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
668 case format_32bppBGRA
:
670 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
672 case format_32bppPBGRA
:
678 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
679 if (FAILED(res
)) return res
;
681 for (y
=0; y
<prc
->Height
; y
++)
682 for (x
=0; x
<prc
->Width
; x
++)
684 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
685 if (alpha
!= 0 && alpha
!= 255)
687 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
688 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
689 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
694 case format_48bppRGB
:
700 UINT srcstride
, srcdatasize
;
702 const BYTE
*srcpixel
;
706 srcstride
= 6 * prc
->Width
;
707 srcdatasize
= srcstride
* prc
->Height
;
709 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
710 if (!srcdata
) return E_OUTOFMEMORY
;
712 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
718 for (y
=0; y
<prc
->Height
; y
++) {
720 dstpixel
=(DWORD
*)dstrow
;
721 for (x
=0; x
<prc
->Width
; x
++) {
722 BYTE red
, green
, blue
;
723 red
= *srcpixel
++; srcpixel
++;
724 green
= *srcpixel
++; srcpixel
++;
725 blue
= *srcpixel
++; srcpixel
++;
726 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
733 HeapFree(GetProcessHeap(), 0, srcdata
);
738 case format_64bppRGBA
:
744 UINT srcstride
, srcdatasize
;
746 const BYTE
*srcpixel
;
750 srcstride
= 8 * prc
->Width
;
751 srcdatasize
= srcstride
* prc
->Height
;
753 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
754 if (!srcdata
) return E_OUTOFMEMORY
;
756 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
762 for (y
=0; y
<prc
->Height
; y
++) {
764 dstpixel
=(DWORD
*)dstrow
;
765 for (x
=0; x
<prc
->Width
; x
++) {
766 BYTE red
, green
, blue
, alpha
;
767 red
= *srcpixel
++; srcpixel
++;
768 green
= *srcpixel
++; srcpixel
++;
769 blue
= *srcpixel
++; srcpixel
++;
770 alpha
= *srcpixel
++; srcpixel
++;
771 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
778 HeapFree(GetProcessHeap(), 0, srcdata
);
783 case format_32bppCMYK
:
789 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
790 if (FAILED(res
)) return res
;
792 for (y
=0; y
<prc
->Height
; y
++)
793 for (x
=0; x
<prc
->Width
; x
++)
795 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
796 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
797 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
798 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
799 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
800 pixel
[3] = 255; /* alpha */
805 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
809 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
810 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
812 switch (source_format
)
814 case format_32bppBGR
:
815 case format_32bppBGRA
:
816 case format_32bppPBGRA
:
818 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
821 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
825 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
826 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
830 switch (source_format
)
832 case format_32bppPBGRA
:
834 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
837 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
838 if (SUCCEEDED(hr
) && prc
)
842 for (y
=0; y
<prc
->Height
; y
++)
843 for (x
=0; x
<prc
->Width
; x
++)
845 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
848 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
849 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
850 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
858 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
859 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
863 switch (source_format
)
865 case format_24bppBGR
:
866 case format_24bppRGB
:
869 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
870 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
871 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
875 case format_32bppBGR
:
876 case format_32bppBGRA
:
877 case format_32bppPBGRA
:
883 UINT srcstride
, srcdatasize
;
885 const BYTE
*srcpixel
;
889 srcstride
= 4 * prc
->Width
;
890 srcdatasize
= srcstride
* prc
->Height
;
892 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
893 if (!srcdata
) return E_OUTOFMEMORY
;
895 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
901 for (y
=0; y
<prc
->Height
; y
++) {
904 for (x
=0; x
<prc
->Width
; x
++) {
905 *dstpixel
++=*srcpixel
++; /* blue */
906 *dstpixel
++=*srcpixel
++; /* green */
907 *dstpixel
++=*srcpixel
++; /* red */
908 srcpixel
++; /* alpha */
915 HeapFree(GetProcessHeap(), 0, srcdata
);
921 FIXME("Unimplemented conversion path!\n");
922 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
926 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
927 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
931 switch (source_format
)
933 case format_24bppBGR
:
934 case format_24bppRGB
:
937 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
938 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
939 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
943 case format_32bppBGR
:
944 case format_32bppBGRA
:
945 case format_32bppPBGRA
:
951 UINT srcstride
, srcdatasize
;
953 const BYTE
*srcpixel
;
957 srcstride
= 4 * prc
->Width
;
958 srcdatasize
= srcstride
* prc
->Height
;
960 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
961 if (!srcdata
) return E_OUTOFMEMORY
;
963 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
969 for (y
=0; y
<prc
->Height
; y
++) {
972 for (x
=0; x
<prc
->Width
; x
++) {
973 *dstpixel
++=*srcpixel
++; /* blue */
974 *dstpixel
++=*srcpixel
++; /* green */
975 *dstpixel
++=*srcpixel
++; /* red */
976 srcpixel
++; /* alpha */
982 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
985 HeapFree(GetProcessHeap(), 0, srcdata
);
991 FIXME("Unimplemented conversion path!\n");
992 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
996 static const struct pixelformatinfo supported_formats
[] = {
997 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
998 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
999 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1000 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
1001 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1002 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1003 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1004 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
1005 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1006 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1007 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1008 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1009 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1010 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1011 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1012 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1013 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1014 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1015 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1016 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1020 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1024 for (i
=0; supported_formats
[i
].guid
; i
++)
1025 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1030 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1033 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1034 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1036 if (!ppv
) return E_INVALIDARG
;
1038 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1039 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1040 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1042 *ppv
= &This
->IWICFormatConverter_iface
;
1047 return E_NOINTERFACE
;
1050 IUnknown_AddRef((IUnknown
*)*ppv
);
1054 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1056 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1057 ULONG ref
= InterlockedIncrement(&This
->ref
);
1059 TRACE("(%p) refcount=%u\n", iface
, ref
);
1064 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1066 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1067 ULONG ref
= InterlockedDecrement(&This
->ref
);
1069 TRACE("(%p) refcount=%u\n", iface
, ref
);
1073 This
->lock
.DebugInfo
->Spare
[0] = 0;
1074 DeleteCriticalSection(&This
->lock
);
1075 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1076 HeapFree(GetProcessHeap(), 0, This
);
1082 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1083 UINT
*puiWidth
, UINT
*puiHeight
)
1085 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1087 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1090 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1092 return WINCODEC_ERR_NOTINITIALIZED
;
1095 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1096 WICPixelFormatGUID
*pPixelFormat
)
1098 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1100 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
1103 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1105 return WINCODEC_ERR_NOTINITIALIZED
;
1110 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1111 double *pDpiX
, double *pDpiY
)
1113 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1115 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
1118 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1120 return WINCODEC_ERR_NOTINITIALIZED
;
1123 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1124 IWICPalette
*pIPalette
)
1126 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
1130 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1131 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1133 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1136 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1143 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1144 if (FAILED(hr
)) return hr
;
1152 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1153 pbBuffer
, This
->src_format
->format
);
1156 return WINCODEC_ERR_NOTINITIALIZED
;
1159 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1160 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1161 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
1163 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1164 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1169 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
1170 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
1172 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
1174 EnterCriticalSection(&This
->lock
);
1178 res
= WINCODEC_ERR_WRONGSTATE
;
1182 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
1183 if (FAILED(res
)) goto end
;
1185 srcinfo
= get_formatinfo(&srcFormat
);
1188 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1189 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1193 dstinfo
= get_formatinfo(dstFormat
);
1196 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1197 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1201 if (dstinfo
->copy_function
)
1203 IWICBitmapSource_AddRef(pISource
);
1204 This
->src_format
= srcinfo
;
1205 This
->dst_format
= dstinfo
;
1206 This
->dither
= dither
;
1207 This
->alpha_threshold
= alphaThresholdPercent
;
1208 This
->palette_type
= paletteTranslate
;
1209 This
->source
= pISource
;
1213 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1214 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1219 LeaveCriticalSection(&This
->lock
);
1224 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1225 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1228 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1229 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1231 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1232 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1234 srcinfo
= get_formatinfo(srcPixelFormat
);
1237 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1238 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1241 dstinfo
= get_formatinfo(dstPixelFormat
);
1244 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1245 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1248 if (dstinfo
->copy_function
&&
1249 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1250 *pfCanConvert
= TRUE
;
1253 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1254 *pfCanConvert
= FALSE
;
1260 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1261 FormatConverter_QueryInterface
,
1262 FormatConverter_AddRef
,
1263 FormatConverter_Release
,
1264 FormatConverter_GetSize
,
1265 FormatConverter_GetPixelFormat
,
1266 FormatConverter_GetResolution
,
1267 FormatConverter_CopyPalette
,
1268 FormatConverter_CopyPixels
,
1269 FormatConverter_Initialize
,
1270 FormatConverter_CanConvert
1273 HRESULT
FormatConverter_CreateInstance(REFIID iid
, void** ppv
)
1275 FormatConverter
*This
;
1278 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1282 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1283 if (!This
) return E_OUTOFMEMORY
;
1285 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1287 This
->source
= NULL
;
1288 InitializeCriticalSection(&This
->lock
);
1289 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1291 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1292 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);