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
19 #define WIN32_NO_STATUS
21 #define COM_NO_WINDOWS_H
34 #include "wincodecs_private.h"
36 #include <wine/debug.h>
38 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
40 struct FormatConverter
;
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
;
81 WICBitmapPaletteType palette_type
;
82 CRITICAL_SECTION lock
; /* must be held when initialized */
85 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
87 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
90 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
91 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
93 switch (source_format
)
95 case format_1bppIndexed
:
96 case format_BlackWhite
:
102 UINT srcstride
, srcdatasize
;
108 IWICPalette
*palette
;
111 res
= PaletteImpl_Create(&palette
);
112 if (FAILED(res
)) return res
;
114 if (source_format
== format_1bppIndexed
)
115 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
117 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
120 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
122 IWICPalette_Release(palette
);
123 if (FAILED(res
)) return res
;
125 srcstride
= (prc
->Width
+7)/8;
126 srcdatasize
= srcstride
* prc
->Height
;
128 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
129 if (!srcdata
) return E_OUTOFMEMORY
;
131 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
137 for (y
=0; y
<prc
->Height
; y
++) {
139 dstpixel
=(DWORD
*)dstrow
;
140 for (x
=0; x
<prc
->Width
; x
+=8) {
143 *dstpixel
++ = colors
[srcval
>>7&1];
144 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
145 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
146 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
147 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
148 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
149 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
150 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
157 HeapFree(GetProcessHeap(), 0, srcdata
);
162 case format_2bppIndexed
:
163 case format_2bppGray
:
169 UINT srcstride
, srcdatasize
;
175 IWICPalette
*palette
;
178 res
= PaletteImpl_Create(&palette
);
179 if (FAILED(res
)) return res
;
181 if (source_format
== format_2bppIndexed
)
182 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
184 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
187 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
189 IWICPalette_Release(palette
);
190 if (FAILED(res
)) return res
;
192 srcstride
= (prc
->Width
+3)/4;
193 srcdatasize
= srcstride
* prc
->Height
;
195 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
196 if (!srcdata
) return E_OUTOFMEMORY
;
198 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
204 for (y
=0; y
<prc
->Height
; y
++) {
206 dstpixel
=(DWORD
*)dstrow
;
207 for (x
=0; x
<prc
->Width
; x
+=4) {
210 *dstpixel
++ = colors
[srcval
>>6];
211 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
212 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
213 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
220 HeapFree(GetProcessHeap(), 0, srcdata
);
225 case format_4bppIndexed
:
226 case format_4bppGray
:
232 UINT srcstride
, srcdatasize
;
238 IWICPalette
*palette
;
241 res
= PaletteImpl_Create(&palette
);
242 if (FAILED(res
)) return res
;
244 if (source_format
== format_4bppIndexed
)
245 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
247 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
250 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
252 IWICPalette_Release(palette
);
253 if (FAILED(res
)) return res
;
255 srcstride
= (prc
->Width
+1)/2;
256 srcdatasize
= srcstride
* prc
->Height
;
258 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
259 if (!srcdata
) return E_OUTOFMEMORY
;
261 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
267 for (y
=0; y
<prc
->Height
; y
++) {
269 dstpixel
=(DWORD
*)dstrow
;
270 for (x
=0; x
<prc
->Width
; x
+=2) {
273 *dstpixel
++ = colors
[srcval
>>4];
274 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
281 HeapFree(GetProcessHeap(), 0, srcdata
);
286 case format_8bppGray
:
292 UINT srcstride
, srcdatasize
;
298 srcstride
= prc
->Width
;
299 srcdatasize
= srcstride
* prc
->Height
;
301 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
302 if (!srcdata
) return E_OUTOFMEMORY
;
304 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
310 for (y
=0; y
<prc
->Height
; y
++) {
312 dstpixel
=(DWORD
*)dstrow
;
313 for (x
=0; x
<prc
->Width
; x
++)
315 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
323 HeapFree(GetProcessHeap(), 0, srcdata
);
328 case format_8bppIndexed
:
334 UINT srcstride
, srcdatasize
;
339 WICColor colors
[256];
340 IWICPalette
*palette
;
343 res
= PaletteImpl_Create(&palette
);
344 if (FAILED(res
)) return res
;
346 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
348 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
350 IWICPalette_Release(palette
);
352 if (FAILED(res
)) return res
;
354 srcstride
= prc
->Width
;
355 srcdatasize
= srcstride
* prc
->Height
;
357 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
358 if (!srcdata
) return E_OUTOFMEMORY
;
360 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
366 for (y
=0; y
<prc
->Height
; y
++) {
368 dstpixel
=(DWORD
*)dstrow
;
369 for (x
=0; x
<prc
->Width
; x
++)
370 *dstpixel
++ = colors
[*srcbyte
++];
376 HeapFree(GetProcessHeap(), 0, srcdata
);
381 case format_16bppGray
:
387 UINT srcstride
, srcdatasize
;
393 srcstride
= prc
->Width
* 2;
394 srcdatasize
= srcstride
* prc
->Height
;
396 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
397 if (!srcdata
) return E_OUTOFMEMORY
;
399 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
405 for (y
=0; y
<prc
->Height
; y
++) {
407 dstpixel
=(DWORD
*)dstrow
;
408 for (x
=0; x
<prc
->Width
; x
++)
410 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
418 HeapFree(GetProcessHeap(), 0, srcdata
);
423 case format_16bppBGR555
:
429 UINT srcstride
, srcdatasize
;
431 const WORD
*srcpixel
;
435 srcstride
= 2 * prc
->Width
;
436 srcdatasize
= srcstride
* prc
->Height
;
438 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
439 if (!srcdata
) return E_OUTOFMEMORY
;
441 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
447 for (y
=0; y
<prc
->Height
; y
++) {
448 srcpixel
=(const WORD
*)srcrow
;
449 dstpixel
=(DWORD
*)dstrow
;
450 for (x
=0; x
<prc
->Width
; x
++) {
453 *dstpixel
++=0xff000000 | /* constant 255 alpha */
454 ((srcval
<< 9) & 0xf80000) | /* r */
455 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
456 ((srcval
<< 6) & 0x00f800) | /* g */
457 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
458 ((srcval
<< 3) & 0x0000f8) | /* b */
459 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
466 HeapFree(GetProcessHeap(), 0, srcdata
);
471 case format_16bppBGR565
:
477 UINT srcstride
, srcdatasize
;
479 const WORD
*srcpixel
;
483 srcstride
= 2 * prc
->Width
;
484 srcdatasize
= srcstride
* prc
->Height
;
486 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
487 if (!srcdata
) return E_OUTOFMEMORY
;
489 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
495 for (y
=0; y
<prc
->Height
; y
++) {
496 srcpixel
=(const WORD
*)srcrow
;
497 dstpixel
=(DWORD
*)dstrow
;
498 for (x
=0; x
<prc
->Width
; x
++) {
501 *dstpixel
++=0xff000000 | /* constant 255 alpha */
502 ((srcval
<< 8) & 0xf80000) | /* r */
503 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
504 ((srcval
<< 5) & 0x00fc00) | /* g */
505 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
506 ((srcval
<< 3) & 0x0000f8) | /* b */
507 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
514 HeapFree(GetProcessHeap(), 0, srcdata
);
519 case format_16bppBGRA5551
:
525 UINT srcstride
, srcdatasize
;
527 const WORD
*srcpixel
;
531 srcstride
= 2 * prc
->Width
;
532 srcdatasize
= srcstride
* prc
->Height
;
534 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
535 if (!srcdata
) return E_OUTOFMEMORY
;
537 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
543 for (y
=0; y
<prc
->Height
; y
++) {
544 srcpixel
=(const WORD
*)srcrow
;
545 dstpixel
=(DWORD
*)dstrow
;
546 for (x
=0; x
<prc
->Width
; x
++) {
549 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
550 ((srcval
<< 9) & 0xf80000) | /* r */
551 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
552 ((srcval
<< 6) & 0x00f800) | /* g */
553 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
554 ((srcval
<< 3) & 0x0000f8) | /* b */
555 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
562 HeapFree(GetProcessHeap(), 0, srcdata
);
567 case format_24bppBGR
:
573 UINT srcstride
, srcdatasize
;
575 const BYTE
*srcpixel
;
579 srcstride
= 3 * prc
->Width
;
580 srcdatasize
= srcstride
* prc
->Height
;
582 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
583 if (!srcdata
) return E_OUTOFMEMORY
;
585 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
591 for (y
=0; y
<prc
->Height
; y
++) {
594 for (x
=0; x
<prc
->Width
; x
++) {
595 *dstpixel
++=*srcpixel
++; /* blue */
596 *dstpixel
++=*srcpixel
++; /* green */
597 *dstpixel
++=*srcpixel
++; /* red */
598 *dstpixel
++=255; /* alpha */
605 HeapFree(GetProcessHeap(), 0, srcdata
);
610 case format_24bppRGB
:
616 UINT srcstride
, srcdatasize
;
618 const BYTE
*srcpixel
;
623 srcstride
= 3 * prc
->Width
;
624 srcdatasize
= srcstride
* prc
->Height
;
626 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
627 if (!srcdata
) return E_OUTOFMEMORY
;
629 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
635 for (y
=0; y
<prc
->Height
; y
++) {
638 for (x
=0; x
<prc
->Width
; x
++) {
639 tmppixel
[0]=*srcpixel
++; /* red */
640 tmppixel
[1]=*srcpixel
++; /* green */
641 tmppixel
[2]=*srcpixel
++; /* blue */
643 *dstpixel
++=tmppixel
[2]; /* blue */
644 *dstpixel
++=tmppixel
[1]; /* green */
645 *dstpixel
++=tmppixel
[0]; /* red */
646 *dstpixel
++=255; /* alpha */
653 HeapFree(GetProcessHeap(), 0, srcdata
);
658 case format_32bppBGR
:
664 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
665 if (FAILED(res
)) return res
;
667 /* set all alpha values to 255 */
668 for (y
=0; y
<prc
->Height
; y
++)
669 for (x
=0; x
<prc
->Width
; x
++)
670 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
673 case format_32bppBGRA
:
675 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
677 case format_32bppPBGRA
:
683 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
684 if (FAILED(res
)) return res
;
686 for (y
=0; y
<prc
->Height
; y
++)
687 for (x
=0; x
<prc
->Width
; x
++)
689 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
690 if (alpha
!= 0 && alpha
!= 255)
692 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
693 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
694 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
699 case format_48bppRGB
:
705 UINT srcstride
, srcdatasize
;
707 const BYTE
*srcpixel
;
711 srcstride
= 6 * prc
->Width
;
712 srcdatasize
= srcstride
* prc
->Height
;
714 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
715 if (!srcdata
) return E_OUTOFMEMORY
;
717 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
723 for (y
=0; y
<prc
->Height
; y
++) {
725 dstpixel
=(DWORD
*)dstrow
;
726 for (x
=0; x
<prc
->Width
; x
++) {
727 BYTE red
, green
, blue
;
728 red
= *srcpixel
++; srcpixel
++;
729 green
= *srcpixel
++; srcpixel
++;
730 blue
= *srcpixel
++; srcpixel
++;
731 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
738 HeapFree(GetProcessHeap(), 0, srcdata
);
743 case format_64bppRGBA
:
749 UINT srcstride
, srcdatasize
;
751 const BYTE
*srcpixel
;
755 srcstride
= 8 * prc
->Width
;
756 srcdatasize
= srcstride
* prc
->Height
;
758 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
759 if (!srcdata
) return E_OUTOFMEMORY
;
761 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
767 for (y
=0; y
<prc
->Height
; y
++) {
769 dstpixel
=(DWORD
*)dstrow
;
770 for (x
=0; x
<prc
->Width
; x
++) {
771 BYTE red
, green
, blue
, alpha
;
772 red
= *srcpixel
++; srcpixel
++;
773 green
= *srcpixel
++; srcpixel
++;
774 blue
= *srcpixel
++; srcpixel
++;
775 alpha
= *srcpixel
++; srcpixel
++;
776 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
783 HeapFree(GetProcessHeap(), 0, srcdata
);
788 case format_32bppCMYK
:
794 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
795 if (FAILED(res
)) return res
;
797 for (y
=0; y
<prc
->Height
; y
++)
798 for (x
=0; x
<prc
->Width
; x
++)
800 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
801 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
802 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
803 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
804 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
805 pixel
[3] = 255; /* alpha */
810 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
814 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
815 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
817 switch (source_format
)
819 case format_32bppBGR
:
820 case format_32bppBGRA
:
821 case format_32bppPBGRA
:
823 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
826 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
830 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
831 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
835 switch (source_format
)
837 case format_32bppPBGRA
:
839 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
842 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
843 if (SUCCEEDED(hr
) && prc
)
847 for (y
=0; y
<prc
->Height
; y
++)
848 for (x
=0; x
<prc
->Width
; x
++)
850 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
853 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
854 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
855 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
863 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
864 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
868 switch (source_format
)
870 case format_24bppBGR
:
871 case format_24bppRGB
:
874 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
875 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
876 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
880 case format_32bppBGR
:
881 case format_32bppBGRA
:
882 case format_32bppPBGRA
:
888 UINT srcstride
, srcdatasize
;
890 const BYTE
*srcpixel
;
894 srcstride
= 4 * prc
->Width
;
895 srcdatasize
= srcstride
* prc
->Height
;
897 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
898 if (!srcdata
) return E_OUTOFMEMORY
;
900 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
906 for (y
=0; y
<prc
->Height
; y
++) {
909 for (x
=0; x
<prc
->Width
; x
++) {
910 *dstpixel
++=*srcpixel
++; /* blue */
911 *dstpixel
++=*srcpixel
++; /* green */
912 *dstpixel
++=*srcpixel
++; /* red */
913 srcpixel
++; /* alpha */
920 HeapFree(GetProcessHeap(), 0, srcdata
);
926 FIXME("Unimplemented conversion path!\n");
927 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
931 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
932 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
936 switch (source_format
)
938 case format_24bppBGR
:
939 case format_24bppRGB
:
942 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
943 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
944 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
948 case format_32bppBGR
:
949 case format_32bppBGRA
:
950 case format_32bppPBGRA
:
956 UINT srcstride
, srcdatasize
;
958 const BYTE
*srcpixel
;
962 srcstride
= 4 * prc
->Width
;
963 srcdatasize
= srcstride
* prc
->Height
;
965 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
966 if (!srcdata
) return E_OUTOFMEMORY
;
968 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
974 for (y
=0; y
<prc
->Height
; y
++) {
977 for (x
=0; x
<prc
->Width
; x
++) {
978 *dstpixel
++=*srcpixel
++; /* blue */
979 *dstpixel
++=*srcpixel
++; /* green */
980 *dstpixel
++=*srcpixel
++; /* red */
981 srcpixel
++; /* alpha */
987 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
990 HeapFree(GetProcessHeap(), 0, srcdata
);
996 FIXME("Unimplemented conversion path!\n");
997 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1001 static const struct pixelformatinfo supported_formats
[] = {
1002 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
1003 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
1004 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1005 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
1006 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1007 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1008 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1009 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
1010 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1011 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1012 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1013 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1014 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1015 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1016 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1017 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1018 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1019 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1020 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1021 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1025 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1029 for (i
=0; supported_formats
[i
].guid
; i
++)
1030 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1035 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1038 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1039 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1041 if (!ppv
) return E_INVALIDARG
;
1043 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1044 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1045 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1047 *ppv
= &This
->IWICFormatConverter_iface
;
1052 return E_NOINTERFACE
;
1055 IUnknown_AddRef((IUnknown
*)*ppv
);
1059 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1061 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1062 ULONG ref
= InterlockedIncrement(&This
->ref
);
1064 TRACE("(%p) refcount=%u\n", iface
, ref
);
1069 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1071 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1072 ULONG ref
= InterlockedDecrement(&This
->ref
);
1074 TRACE("(%p) refcount=%u\n", iface
, ref
);
1078 This
->lock
.DebugInfo
->Spare
[0] = 0;
1079 DeleteCriticalSection(&This
->lock
);
1080 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1081 HeapFree(GetProcessHeap(), 0, This
);
1087 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1088 UINT
*puiWidth
, UINT
*puiHeight
)
1090 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1092 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1095 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1097 return WINCODEC_ERR_NOTINITIALIZED
;
1100 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1101 WICPixelFormatGUID
*pPixelFormat
)
1103 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1105 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
1108 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1110 return WINCODEC_ERR_NOTINITIALIZED
;
1115 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1116 double *pDpiX
, double *pDpiY
)
1118 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1120 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
1123 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1125 return WINCODEC_ERR_NOTINITIALIZED
;
1128 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1129 IWICPalette
*pIPalette
)
1131 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
1135 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1136 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1138 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1141 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1148 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1149 if (FAILED(hr
)) return hr
;
1157 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1158 pbBuffer
, This
->src_format
->format
);
1161 return WINCODEC_ERR_NOTINITIALIZED
;
1164 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1165 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1166 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
1168 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1169 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1174 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
1175 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
1177 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
1179 EnterCriticalSection(&This
->lock
);
1183 res
= WINCODEC_ERR_WRONGSTATE
;
1187 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
1188 if (FAILED(res
)) goto end
;
1190 srcinfo
= get_formatinfo(&srcFormat
);
1193 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1194 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1198 dstinfo
= get_formatinfo(dstFormat
);
1201 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1202 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1206 if (dstinfo
->copy_function
)
1208 IWICBitmapSource_AddRef(pISource
);
1209 This
->src_format
= srcinfo
;
1210 This
->dst_format
= dstinfo
;
1211 This
->dither
= dither
;
1212 This
->alpha_threshold
= alphaThresholdPercent
;
1213 This
->palette_type
= paletteTranslate
;
1214 This
->source
= pISource
;
1218 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1219 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1224 LeaveCriticalSection(&This
->lock
);
1229 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1230 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1233 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1234 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1236 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1237 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1239 srcinfo
= get_formatinfo(srcPixelFormat
);
1242 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1243 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1246 dstinfo
= get_formatinfo(dstPixelFormat
);
1249 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1250 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1253 if (dstinfo
->copy_function
&&
1254 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1255 *pfCanConvert
= TRUE
;
1258 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1259 *pfCanConvert
= FALSE
;
1265 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1266 FormatConverter_QueryInterface
,
1267 FormatConverter_AddRef
,
1268 FormatConverter_Release
,
1269 FormatConverter_GetSize
,
1270 FormatConverter_GetPixelFormat
,
1271 FormatConverter_GetResolution
,
1272 FormatConverter_CopyPalette
,
1273 FormatConverter_CopyPixels
,
1274 FormatConverter_Initialize
,
1275 FormatConverter_CanConvert
1278 HRESULT
FormatConverter_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1280 FormatConverter
*This
;
1283 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1287 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1289 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1290 if (!This
) return E_OUTOFMEMORY
;
1292 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1294 This
->source
= NULL
;
1295 InitializeCriticalSection(&This
->lock
);
1296 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1298 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1299 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);