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
30 #include "wincodecs_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
36 struct FormatConverter
;
61 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
62 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
64 struct pixelformatinfo
{
65 enum pixelformat format
;
66 const WICPixelFormatGUID
*guid
;
67 copyfunc copy_function
;
70 typedef struct FormatConverter
{
71 IWICFormatConverter IWICFormatConverter_iface
;
73 IWICBitmapSource
*source
;
74 const struct pixelformatinfo
*dst_format
, *src_format
;
75 WICBitmapDitherType dither
;
76 double alpha_threshold
;
77 WICBitmapPaletteType palette_type
;
78 CRITICAL_SECTION lock
; /* must be held when initialized */
81 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
83 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
86 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
87 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
89 switch (source_format
)
91 case format_1bppIndexed
:
92 case format_BlackWhite
:
98 UINT srcstride
, srcdatasize
;
104 IWICPalette
*palette
;
107 res
= PaletteImpl_Create(&palette
);
108 if (FAILED(res
)) return res
;
110 if (source_format
== format_1bppIndexed
)
111 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
113 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
116 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
118 IWICPalette_Release(palette
);
119 if (FAILED(res
)) return res
;
121 srcstride
= (prc
->Width
+7)/8;
122 srcdatasize
= srcstride
* prc
->Height
;
124 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
125 if (!srcdata
) return E_OUTOFMEMORY
;
127 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
133 for (y
=0; y
<prc
->Height
; y
++) {
135 dstpixel
=(DWORD
*)dstrow
;
136 for (x
=0; x
<prc
->Width
; x
+=8) {
139 *dstpixel
++ = colors
[srcval
>>7&1];
140 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
141 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
142 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
143 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
144 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
145 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
146 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
153 HeapFree(GetProcessHeap(), 0, srcdata
);
158 case format_2bppIndexed
:
159 case format_2bppGray
:
165 UINT srcstride
, srcdatasize
;
171 IWICPalette
*palette
;
174 res
= PaletteImpl_Create(&palette
);
175 if (FAILED(res
)) return res
;
177 if (source_format
== format_2bppIndexed
)
178 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
180 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
183 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
185 IWICPalette_Release(palette
);
186 if (FAILED(res
)) return res
;
188 srcstride
= (prc
->Width
+3)/4;
189 srcdatasize
= srcstride
* prc
->Height
;
191 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
192 if (!srcdata
) return E_OUTOFMEMORY
;
194 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
200 for (y
=0; y
<prc
->Height
; y
++) {
202 dstpixel
=(DWORD
*)dstrow
;
203 for (x
=0; x
<prc
->Width
; x
+=4) {
206 *dstpixel
++ = colors
[srcval
>>6];
207 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
208 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
209 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
216 HeapFree(GetProcessHeap(), 0, srcdata
);
221 case format_4bppIndexed
:
222 case format_4bppGray
:
228 UINT srcstride
, srcdatasize
;
234 IWICPalette
*palette
;
237 res
= PaletteImpl_Create(&palette
);
238 if (FAILED(res
)) return res
;
240 if (source_format
== format_4bppIndexed
)
241 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
243 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
246 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
248 IWICPalette_Release(palette
);
249 if (FAILED(res
)) return res
;
251 srcstride
= (prc
->Width
+1)/2;
252 srcdatasize
= srcstride
* prc
->Height
;
254 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
255 if (!srcdata
) return E_OUTOFMEMORY
;
257 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
263 for (y
=0; y
<prc
->Height
; y
++) {
265 dstpixel
=(DWORD
*)dstrow
;
266 for (x
=0; x
<prc
->Width
; x
+=2) {
269 *dstpixel
++ = colors
[srcval
>>4];
270 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
277 HeapFree(GetProcessHeap(), 0, srcdata
);
282 case format_8bppGray
:
288 UINT srcstride
, srcdatasize
;
294 srcstride
= prc
->Width
;
295 srcdatasize
= srcstride
* prc
->Height
;
297 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
298 if (!srcdata
) return E_OUTOFMEMORY
;
300 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
306 for (y
=0; y
<prc
->Height
; y
++) {
308 dstpixel
=(DWORD
*)dstrow
;
309 for (x
=0; x
<prc
->Width
; x
++)
311 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
319 HeapFree(GetProcessHeap(), 0, srcdata
);
324 case format_8bppIndexed
:
330 UINT srcstride
, srcdatasize
;
335 WICColor colors
[256];
336 IWICPalette
*palette
;
339 res
= PaletteImpl_Create(&palette
);
340 if (FAILED(res
)) return res
;
342 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
344 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
346 IWICPalette_Release(palette
);
348 if (FAILED(res
)) return res
;
350 srcstride
= prc
->Width
;
351 srcdatasize
= srcstride
* prc
->Height
;
353 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
354 if (!srcdata
) return E_OUTOFMEMORY
;
356 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
362 for (y
=0; y
<prc
->Height
; y
++) {
364 dstpixel
=(DWORD
*)dstrow
;
365 for (x
=0; x
<prc
->Width
; x
++)
366 *dstpixel
++ = colors
[*srcbyte
++];
372 HeapFree(GetProcessHeap(), 0, srcdata
);
377 case format_16bppGray
:
383 UINT srcstride
, srcdatasize
;
389 srcstride
= prc
->Width
* 2;
390 srcdatasize
= srcstride
* prc
->Height
;
392 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
393 if (!srcdata
) return E_OUTOFMEMORY
;
395 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
401 for (y
=0; y
<prc
->Height
; y
++) {
403 dstpixel
=(DWORD
*)dstrow
;
404 for (x
=0; x
<prc
->Width
; x
++)
406 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
414 HeapFree(GetProcessHeap(), 0, srcdata
);
419 case format_16bppBGR555
:
425 UINT srcstride
, srcdatasize
;
427 const WORD
*srcpixel
;
431 srcstride
= 2 * prc
->Width
;
432 srcdatasize
= srcstride
* prc
->Height
;
434 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
435 if (!srcdata
) return E_OUTOFMEMORY
;
437 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
443 for (y
=0; y
<prc
->Height
; y
++) {
444 srcpixel
=(const WORD
*)srcrow
;
445 dstpixel
=(DWORD
*)dstrow
;
446 for (x
=0; x
<prc
->Width
; x
++) {
449 *dstpixel
++=0xff000000 | /* constant 255 alpha */
450 ((srcval
<< 9) & 0xf80000) | /* r */
451 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
452 ((srcval
<< 6) & 0x00f800) | /* g */
453 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
454 ((srcval
<< 3) & 0x0000f8) | /* b */
455 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
462 HeapFree(GetProcessHeap(), 0, srcdata
);
467 case format_16bppBGR565
:
473 UINT srcstride
, srcdatasize
;
475 const WORD
*srcpixel
;
479 srcstride
= 2 * prc
->Width
;
480 srcdatasize
= srcstride
* prc
->Height
;
482 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
483 if (!srcdata
) return E_OUTOFMEMORY
;
485 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
491 for (y
=0; y
<prc
->Height
; y
++) {
492 srcpixel
=(const WORD
*)srcrow
;
493 dstpixel
=(DWORD
*)dstrow
;
494 for (x
=0; x
<prc
->Width
; x
++) {
497 *dstpixel
++=0xff000000 | /* constant 255 alpha */
498 ((srcval
<< 8) & 0xf80000) | /* r */
499 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
500 ((srcval
<< 5) & 0x00fc00) | /* g */
501 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
502 ((srcval
<< 3) & 0x0000f8) | /* b */
503 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
510 HeapFree(GetProcessHeap(), 0, srcdata
);
515 case format_16bppBGRA5551
:
521 UINT srcstride
, srcdatasize
;
523 const WORD
*srcpixel
;
527 srcstride
= 2 * prc
->Width
;
528 srcdatasize
= srcstride
* prc
->Height
;
530 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
531 if (!srcdata
) return E_OUTOFMEMORY
;
533 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
539 for (y
=0; y
<prc
->Height
; y
++) {
540 srcpixel
=(const WORD
*)srcrow
;
541 dstpixel
=(DWORD
*)dstrow
;
542 for (x
=0; x
<prc
->Width
; x
++) {
545 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
546 ((srcval
<< 9) & 0xf80000) | /* r */
547 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
548 ((srcval
<< 6) & 0x00f800) | /* g */
549 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
550 ((srcval
<< 3) & 0x0000f8) | /* b */
551 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
558 HeapFree(GetProcessHeap(), 0, srcdata
);
563 case format_24bppBGR
:
569 UINT srcstride
, srcdatasize
;
571 const BYTE
*srcpixel
;
575 srcstride
= 3 * prc
->Width
;
576 srcdatasize
= srcstride
* prc
->Height
;
578 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
579 if (!srcdata
) return E_OUTOFMEMORY
;
581 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
587 for (y
=0; y
<prc
->Height
; y
++) {
590 for (x
=0; x
<prc
->Width
; x
++) {
591 *dstpixel
++=*srcpixel
++; /* blue */
592 *dstpixel
++=*srcpixel
++; /* green */
593 *dstpixel
++=*srcpixel
++; /* red */
594 *dstpixel
++=255; /* alpha */
601 HeapFree(GetProcessHeap(), 0, srcdata
);
606 case format_24bppRGB
:
612 UINT srcstride
, srcdatasize
;
614 const BYTE
*srcpixel
;
619 srcstride
= 3 * prc
->Width
;
620 srcdatasize
= srcstride
* prc
->Height
;
622 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
623 if (!srcdata
) return E_OUTOFMEMORY
;
625 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
631 for (y
=0; y
<prc
->Height
; y
++) {
634 for (x
=0; x
<prc
->Width
; x
++) {
635 tmppixel
[0]=*srcpixel
++; /* red */
636 tmppixel
[1]=*srcpixel
++; /* green */
637 tmppixel
[2]=*srcpixel
++; /* blue */
639 *dstpixel
++=tmppixel
[2]; /* blue */
640 *dstpixel
++=tmppixel
[1]; /* green */
641 *dstpixel
++=tmppixel
[0]; /* red */
642 *dstpixel
++=255; /* alpha */
649 HeapFree(GetProcessHeap(), 0, srcdata
);
654 case format_32bppBGR
:
660 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
661 if (FAILED(res
)) return res
;
663 /* set all alpha values to 255 */
664 for (y
=0; y
<prc
->Height
; y
++)
665 for (x
=0; x
<prc
->Width
; x
++)
666 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
669 case format_32bppBGRA
:
671 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
673 case format_32bppPBGRA
:
679 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
680 if (FAILED(res
)) return res
;
682 for (y
=0; y
<prc
->Height
; y
++)
683 for (x
=0; x
<prc
->Width
; x
++)
685 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
686 if (alpha
!= 0 && alpha
!= 255)
688 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
689 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
690 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
695 case format_48bppRGB
:
701 UINT srcstride
, srcdatasize
;
703 const BYTE
*srcpixel
;
707 srcstride
= 6 * prc
->Width
;
708 srcdatasize
= srcstride
* prc
->Height
;
710 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
711 if (!srcdata
) return E_OUTOFMEMORY
;
713 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
719 for (y
=0; y
<prc
->Height
; y
++) {
721 dstpixel
=(DWORD
*)dstrow
;
722 for (x
=0; x
<prc
->Width
; x
++) {
723 BYTE red
, green
, blue
;
724 red
= *srcpixel
++; srcpixel
++;
725 green
= *srcpixel
++; srcpixel
++;
726 blue
= *srcpixel
++; srcpixel
++;
727 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
734 HeapFree(GetProcessHeap(), 0, srcdata
);
739 case format_64bppRGBA
:
745 UINT srcstride
, srcdatasize
;
747 const BYTE
*srcpixel
;
751 srcstride
= 8 * prc
->Width
;
752 srcdatasize
= srcstride
* prc
->Height
;
754 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
755 if (!srcdata
) return E_OUTOFMEMORY
;
757 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
763 for (y
=0; y
<prc
->Height
; y
++) {
765 dstpixel
=(DWORD
*)dstrow
;
766 for (x
=0; x
<prc
->Width
; x
++) {
767 BYTE red
, green
, blue
, alpha
;
768 red
= *srcpixel
++; srcpixel
++;
769 green
= *srcpixel
++; srcpixel
++;
770 blue
= *srcpixel
++; srcpixel
++;
771 alpha
= *srcpixel
++; srcpixel
++;
772 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
779 HeapFree(GetProcessHeap(), 0, srcdata
);
784 case format_32bppCMYK
:
790 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
791 if (FAILED(res
)) return res
;
793 for (y
=0; y
<prc
->Height
; y
++)
794 for (x
=0; x
<prc
->Width
; x
++)
796 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
797 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
798 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
799 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
800 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
801 pixel
[3] = 255; /* alpha */
806 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
810 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
811 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
813 switch (source_format
)
815 case format_32bppBGR
:
816 case format_32bppBGRA
:
817 case format_32bppPBGRA
:
819 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
822 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
826 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
827 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
831 switch (source_format
)
833 case format_32bppPBGRA
:
835 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
838 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
839 if (SUCCEEDED(hr
) && prc
)
843 for (y
=0; y
<prc
->Height
; y
++)
844 for (x
=0; x
<prc
->Width
; x
++)
846 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
849 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
850 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
851 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
859 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
860 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
864 switch (source_format
)
866 case format_24bppBGR
:
867 case format_24bppRGB
:
870 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
871 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
872 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
876 case format_32bppBGR
:
877 case format_32bppBGRA
:
878 case format_32bppPBGRA
:
884 UINT srcstride
, srcdatasize
;
886 const BYTE
*srcpixel
;
890 srcstride
= 4 * prc
->Width
;
891 srcdatasize
= srcstride
* prc
->Height
;
893 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
894 if (!srcdata
) return E_OUTOFMEMORY
;
896 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
902 for (y
=0; y
<prc
->Height
; y
++) {
905 for (x
=0; x
<prc
->Width
; x
++) {
906 *dstpixel
++=*srcpixel
++; /* blue */
907 *dstpixel
++=*srcpixel
++; /* green */
908 *dstpixel
++=*srcpixel
++; /* red */
909 srcpixel
++; /* alpha */
916 HeapFree(GetProcessHeap(), 0, srcdata
);
922 FIXME("Unimplemented conversion path!\n");
923 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
927 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
928 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
932 switch (source_format
)
934 case format_24bppBGR
:
935 case format_24bppRGB
:
938 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
939 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
940 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
944 case format_32bppBGR
:
945 case format_32bppBGRA
:
946 case format_32bppPBGRA
:
952 UINT srcstride
, srcdatasize
;
954 const BYTE
*srcpixel
;
958 srcstride
= 4 * prc
->Width
;
959 srcdatasize
= srcstride
* prc
->Height
;
961 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
962 if (!srcdata
) return E_OUTOFMEMORY
;
964 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
970 for (y
=0; y
<prc
->Height
; y
++) {
973 for (x
=0; x
<prc
->Width
; x
++) {
974 *dstpixel
++=*srcpixel
++; /* blue */
975 *dstpixel
++=*srcpixel
++; /* green */
976 *dstpixel
++=*srcpixel
++; /* red */
977 srcpixel
++; /* alpha */
983 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
986 HeapFree(GetProcessHeap(), 0, srcdata
);
992 FIXME("Unimplemented conversion path!\n");
993 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
997 static const struct pixelformatinfo supported_formats
[] = {
998 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
999 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
1000 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
1001 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
1002 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
1003 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
1004 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
1005 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
1006 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
1007 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
1008 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
1009 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
1010 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
1011 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
1012 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
1013 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
1014 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1015 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1016 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1017 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1021 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1025 for (i
=0; supported_formats
[i
].guid
; i
++)
1026 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1031 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1034 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1035 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1037 if (!ppv
) return E_INVALIDARG
;
1039 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1040 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1041 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1043 *ppv
= &This
->IWICFormatConverter_iface
;
1048 return E_NOINTERFACE
;
1051 IUnknown_AddRef((IUnknown
*)*ppv
);
1055 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1057 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1058 ULONG ref
= InterlockedIncrement(&This
->ref
);
1060 TRACE("(%p) refcount=%u\n", iface
, ref
);
1065 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1067 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1068 ULONG ref
= InterlockedDecrement(&This
->ref
);
1070 TRACE("(%p) refcount=%u\n", iface
, ref
);
1074 This
->lock
.DebugInfo
->Spare
[0] = 0;
1075 DeleteCriticalSection(&This
->lock
);
1076 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1077 HeapFree(GetProcessHeap(), 0, This
);
1083 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1084 UINT
*puiWidth
, UINT
*puiHeight
)
1086 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1088 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1091 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1093 return WINCODEC_ERR_NOTINITIALIZED
;
1096 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1097 WICPixelFormatGUID
*pPixelFormat
)
1099 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1101 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
1104 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1106 return WINCODEC_ERR_NOTINITIALIZED
;
1111 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1112 double *pDpiX
, double *pDpiY
)
1114 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1116 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
1119 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1121 return WINCODEC_ERR_NOTINITIALIZED
;
1124 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1125 IWICPalette
*pIPalette
)
1127 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
1131 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1132 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1134 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1137 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1144 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1145 if (FAILED(hr
)) return hr
;
1153 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1154 pbBuffer
, This
->src_format
->format
);
1157 return WINCODEC_ERR_NOTINITIALIZED
;
1160 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1161 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1162 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
1164 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1165 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1170 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
1171 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
1173 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
1175 EnterCriticalSection(&This
->lock
);
1179 res
= WINCODEC_ERR_WRONGSTATE
;
1183 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
1184 if (FAILED(res
)) goto end
;
1186 srcinfo
= get_formatinfo(&srcFormat
);
1189 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1190 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1194 dstinfo
= get_formatinfo(dstFormat
);
1197 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1198 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1202 if (dstinfo
->copy_function
)
1204 IWICBitmapSource_AddRef(pISource
);
1205 This
->src_format
= srcinfo
;
1206 This
->dst_format
= dstinfo
;
1207 This
->dither
= dither
;
1208 This
->alpha_threshold
= alphaThresholdPercent
;
1209 This
->palette_type
= paletteTranslate
;
1210 This
->source
= pISource
;
1214 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1215 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1220 LeaveCriticalSection(&This
->lock
);
1225 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1226 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1229 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1230 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1232 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1233 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1235 srcinfo
= get_formatinfo(srcPixelFormat
);
1238 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1239 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1242 dstinfo
= get_formatinfo(dstPixelFormat
);
1245 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1246 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1249 if (dstinfo
->copy_function
&&
1250 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1251 *pfCanConvert
= TRUE
;
1254 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1255 *pfCanConvert
= FALSE
;
1261 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1262 FormatConverter_QueryInterface
,
1263 FormatConverter_AddRef
,
1264 FormatConverter_Release
,
1265 FormatConverter_GetSize
,
1266 FormatConverter_GetPixelFormat
,
1267 FormatConverter_GetResolution
,
1268 FormatConverter_CopyPalette
,
1269 FormatConverter_CopyPixels
,
1270 FormatConverter_Initialize
,
1271 FormatConverter_CanConvert
1274 HRESULT
FormatConverter_CreateInstance(REFIID iid
, void** ppv
)
1276 FormatConverter
*This
;
1279 TRACE("(%s,%p)\n", debugstr_guid(iid
), ppv
);
1283 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1284 if (!This
) return E_OUTOFMEMORY
;
1286 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1288 This
->source
= NULL
;
1289 InitializeCriticalSection(&This
->lock
);
1290 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1292 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1293 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);