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 #include "wincodecs_private.h"
21 struct FormatConverter
;
46 typedef HRESULT (*copyfunc
)(struct FormatConverter
*This
, const WICRect
*prc
,
47 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
);
49 struct pixelformatinfo
{
50 enum pixelformat format
;
51 const WICPixelFormatGUID
*guid
;
52 copyfunc copy_function
;
55 typedef struct FormatConverter
{
56 IWICFormatConverter IWICFormatConverter_iface
;
58 IWICBitmapSource
*source
;
59 const struct pixelformatinfo
*dst_format
, *src_format
;
60 WICBitmapDitherType dither
;
61 double alpha_threshold
;
62 WICBitmapPaletteType palette_type
;
63 CRITICAL_SECTION lock
; /* must be held when initialized */
66 static inline FormatConverter
*impl_from_IWICFormatConverter(IWICFormatConverter
*iface
)
68 return CONTAINING_RECORD(iface
, FormatConverter
, IWICFormatConverter_iface
);
71 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
72 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
74 switch (source_format
)
76 case format_1bppIndexed
:
77 case format_BlackWhite
:
83 UINT srcstride
, srcdatasize
;
92 res
= PaletteImpl_Create(&palette
);
93 if (FAILED(res
)) return res
;
95 if (source_format
== format_1bppIndexed
)
96 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
98 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedBW
, FALSE
);
101 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
103 IWICPalette_Release(palette
);
104 if (FAILED(res
)) return res
;
106 srcstride
= (prc
->Width
+7)/8;
107 srcdatasize
= srcstride
* prc
->Height
;
109 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
110 if (!srcdata
) return E_OUTOFMEMORY
;
112 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
118 for (y
=0; y
<prc
->Height
; y
++) {
120 dstpixel
=(DWORD
*)dstrow
;
121 for (x
=0; x
<prc
->Width
; x
+=8) {
124 *dstpixel
++ = colors
[srcval
>>7&1];
125 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
126 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
127 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
128 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
129 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
130 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
131 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
138 HeapFree(GetProcessHeap(), 0, srcdata
);
143 case format_2bppIndexed
:
144 case format_2bppGray
:
150 UINT srcstride
, srcdatasize
;
156 IWICPalette
*palette
;
159 res
= PaletteImpl_Create(&palette
);
160 if (FAILED(res
)) return res
;
162 if (source_format
== format_2bppIndexed
)
163 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
165 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray4
, FALSE
);
168 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
170 IWICPalette_Release(palette
);
171 if (FAILED(res
)) return res
;
173 srcstride
= (prc
->Width
+3)/4;
174 srcdatasize
= srcstride
* prc
->Height
;
176 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
177 if (!srcdata
) return E_OUTOFMEMORY
;
179 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
185 for (y
=0; y
<prc
->Height
; y
++) {
187 dstpixel
=(DWORD
*)dstrow
;
188 for (x
=0; x
<prc
->Width
; x
+=4) {
191 *dstpixel
++ = colors
[srcval
>>6];
192 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
193 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
194 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
201 HeapFree(GetProcessHeap(), 0, srcdata
);
206 case format_4bppIndexed
:
207 case format_4bppGray
:
213 UINT srcstride
, srcdatasize
;
219 IWICPalette
*palette
;
222 res
= PaletteImpl_Create(&palette
);
223 if (FAILED(res
)) return res
;
225 if (source_format
== format_4bppIndexed
)
226 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
228 res
= IWICPalette_InitializePredefined(palette
, WICBitmapPaletteTypeFixedGray16
, FALSE
);
231 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
233 IWICPalette_Release(palette
);
234 if (FAILED(res
)) return res
;
236 srcstride
= (prc
->Width
+1)/2;
237 srcdatasize
= srcstride
* prc
->Height
;
239 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
240 if (!srcdata
) return E_OUTOFMEMORY
;
242 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
248 for (y
=0; y
<prc
->Height
; y
++) {
250 dstpixel
=(DWORD
*)dstrow
;
251 for (x
=0; x
<prc
->Width
; x
+=2) {
254 *dstpixel
++ = colors
[srcval
>>4];
255 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
262 HeapFree(GetProcessHeap(), 0, srcdata
);
267 case format_8bppGray
:
273 UINT srcstride
, srcdatasize
;
279 srcstride
= prc
->Width
;
280 srcdatasize
= srcstride
* prc
->Height
;
282 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
283 if (!srcdata
) return E_OUTOFMEMORY
;
285 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
291 for (y
=0; y
<prc
->Height
; y
++) {
293 dstpixel
=(DWORD
*)dstrow
;
294 for (x
=0; x
<prc
->Width
; x
++)
296 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
304 HeapFree(GetProcessHeap(), 0, srcdata
);
309 case format_8bppIndexed
:
315 UINT srcstride
, srcdatasize
;
320 WICColor colors
[256];
321 IWICPalette
*palette
;
324 res
= PaletteImpl_Create(&palette
);
325 if (FAILED(res
)) return res
;
327 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
329 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
331 IWICPalette_Release(palette
);
333 if (FAILED(res
)) return res
;
335 srcstride
= prc
->Width
;
336 srcdatasize
= srcstride
* prc
->Height
;
338 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
339 if (!srcdata
) return E_OUTOFMEMORY
;
341 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
347 for (y
=0; y
<prc
->Height
; y
++) {
349 dstpixel
=(DWORD
*)dstrow
;
350 for (x
=0; x
<prc
->Width
; x
++)
351 *dstpixel
++ = colors
[*srcbyte
++];
357 HeapFree(GetProcessHeap(), 0, srcdata
);
362 case format_16bppGray
:
368 UINT srcstride
, srcdatasize
;
374 srcstride
= prc
->Width
* 2;
375 srcdatasize
= srcstride
* prc
->Height
;
377 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
378 if (!srcdata
) return E_OUTOFMEMORY
;
380 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
386 for (y
=0; y
<prc
->Height
; y
++) {
388 dstpixel
=(DWORD
*)dstrow
;
389 for (x
=0; x
<prc
->Width
; x
++)
391 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
399 HeapFree(GetProcessHeap(), 0, srcdata
);
404 case format_16bppBGR555
:
410 UINT srcstride
, srcdatasize
;
412 const WORD
*srcpixel
;
416 srcstride
= 2 * prc
->Width
;
417 srcdatasize
= srcstride
* prc
->Height
;
419 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
420 if (!srcdata
) return E_OUTOFMEMORY
;
422 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
428 for (y
=0; y
<prc
->Height
; y
++) {
429 srcpixel
=(const WORD
*)srcrow
;
430 dstpixel
=(DWORD
*)dstrow
;
431 for (x
=0; x
<prc
->Width
; x
++) {
434 *dstpixel
++=0xff000000 | /* constant 255 alpha */
435 ((srcval
<< 9) & 0xf80000) | /* r */
436 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
437 ((srcval
<< 6) & 0x00f800) | /* g */
438 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
439 ((srcval
<< 3) & 0x0000f8) | /* b */
440 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
447 HeapFree(GetProcessHeap(), 0, srcdata
);
452 case format_16bppBGR565
:
458 UINT srcstride
, srcdatasize
;
460 const WORD
*srcpixel
;
464 srcstride
= 2 * prc
->Width
;
465 srcdatasize
= srcstride
* prc
->Height
;
467 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
468 if (!srcdata
) return E_OUTOFMEMORY
;
470 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
476 for (y
=0; y
<prc
->Height
; y
++) {
477 srcpixel
=(const WORD
*)srcrow
;
478 dstpixel
=(DWORD
*)dstrow
;
479 for (x
=0; x
<prc
->Width
; x
++) {
482 *dstpixel
++=0xff000000 | /* constant 255 alpha */
483 ((srcval
<< 8) & 0xf80000) | /* r */
484 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
485 ((srcval
<< 5) & 0x00fc00) | /* g */
486 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
487 ((srcval
<< 3) & 0x0000f8) | /* b */
488 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
495 HeapFree(GetProcessHeap(), 0, srcdata
);
500 case format_16bppBGRA5551
:
506 UINT srcstride
, srcdatasize
;
508 const WORD
*srcpixel
;
512 srcstride
= 2 * prc
->Width
;
513 srcdatasize
= srcstride
* prc
->Height
;
515 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
516 if (!srcdata
) return E_OUTOFMEMORY
;
518 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
524 for (y
=0; y
<prc
->Height
; y
++) {
525 srcpixel
=(const WORD
*)srcrow
;
526 dstpixel
=(DWORD
*)dstrow
;
527 for (x
=0; x
<prc
->Width
; x
++) {
530 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
531 ((srcval
<< 9) & 0xf80000) | /* r */
532 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
533 ((srcval
<< 6) & 0x00f800) | /* g */
534 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
535 ((srcval
<< 3) & 0x0000f8) | /* b */
536 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
543 HeapFree(GetProcessHeap(), 0, srcdata
);
548 case format_24bppBGR
:
554 UINT srcstride
, srcdatasize
;
556 const BYTE
*srcpixel
;
560 srcstride
= 3 * prc
->Width
;
561 srcdatasize
= srcstride
* prc
->Height
;
563 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
564 if (!srcdata
) return E_OUTOFMEMORY
;
566 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
572 for (y
=0; y
<prc
->Height
; y
++) {
575 for (x
=0; x
<prc
->Width
; x
++) {
576 *dstpixel
++=*srcpixel
++; /* blue */
577 *dstpixel
++=*srcpixel
++; /* green */
578 *dstpixel
++=*srcpixel
++; /* red */
579 *dstpixel
++=255; /* alpha */
586 HeapFree(GetProcessHeap(), 0, srcdata
);
591 case format_24bppRGB
:
597 UINT srcstride
, srcdatasize
;
599 const BYTE
*srcpixel
;
604 srcstride
= 3 * prc
->Width
;
605 srcdatasize
= srcstride
* prc
->Height
;
607 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
608 if (!srcdata
) return E_OUTOFMEMORY
;
610 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
616 for (y
=0; y
<prc
->Height
; y
++) {
619 for (x
=0; x
<prc
->Width
; x
++) {
620 tmppixel
[0]=*srcpixel
++; /* red */
621 tmppixel
[1]=*srcpixel
++; /* green */
622 tmppixel
[2]=*srcpixel
++; /* blue */
624 *dstpixel
++=tmppixel
[2]; /* blue */
625 *dstpixel
++=tmppixel
[1]; /* green */
626 *dstpixel
++=tmppixel
[0]; /* red */
627 *dstpixel
++=255; /* alpha */
634 HeapFree(GetProcessHeap(), 0, srcdata
);
639 case format_32bppBGR
:
645 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
646 if (FAILED(res
)) return res
;
648 /* set all alpha values to 255 */
649 for (y
=0; y
<prc
->Height
; y
++)
650 for (x
=0; x
<prc
->Width
; x
++)
651 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
654 case format_32bppBGRA
:
656 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
658 case format_32bppPBGRA
:
664 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
665 if (FAILED(res
)) return res
;
667 for (y
=0; y
<prc
->Height
; y
++)
668 for (x
=0; x
<prc
->Width
; x
++)
670 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
671 if (alpha
!= 0 && alpha
!= 255)
673 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
674 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
675 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
680 case format_48bppRGB
:
686 UINT srcstride
, srcdatasize
;
688 const BYTE
*srcpixel
;
692 srcstride
= 6 * prc
->Width
;
693 srcdatasize
= srcstride
* prc
->Height
;
695 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
696 if (!srcdata
) return E_OUTOFMEMORY
;
698 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
704 for (y
=0; y
<prc
->Height
; y
++) {
706 dstpixel
=(DWORD
*)dstrow
;
707 for (x
=0; x
<prc
->Width
; x
++) {
708 BYTE red
, green
, blue
;
709 red
= *srcpixel
++; srcpixel
++;
710 green
= *srcpixel
++; srcpixel
++;
711 blue
= *srcpixel
++; srcpixel
++;
712 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
719 HeapFree(GetProcessHeap(), 0, srcdata
);
724 case format_64bppRGBA
:
730 UINT srcstride
, srcdatasize
;
732 const BYTE
*srcpixel
;
736 srcstride
= 8 * prc
->Width
;
737 srcdatasize
= srcstride
* prc
->Height
;
739 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
740 if (!srcdata
) return E_OUTOFMEMORY
;
742 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
748 for (y
=0; y
<prc
->Height
; y
++) {
750 dstpixel
=(DWORD
*)dstrow
;
751 for (x
=0; x
<prc
->Width
; x
++) {
752 BYTE red
, green
, blue
, alpha
;
753 red
= *srcpixel
++; srcpixel
++;
754 green
= *srcpixel
++; srcpixel
++;
755 blue
= *srcpixel
++; srcpixel
++;
756 alpha
= *srcpixel
++; srcpixel
++;
757 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
764 HeapFree(GetProcessHeap(), 0, srcdata
);
769 case format_32bppCMYK
:
775 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
776 if (FAILED(res
)) return res
;
778 for (y
=0; y
<prc
->Height
; y
++)
779 for (x
=0; x
<prc
->Width
; x
++)
781 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
782 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
783 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
784 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
785 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
786 pixel
[3] = 255; /* alpha */
791 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
795 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
796 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
798 switch (source_format
)
800 case format_32bppBGR
:
801 case format_32bppBGRA
:
802 case format_32bppPBGRA
:
804 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
807 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
811 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
812 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
816 switch (source_format
)
818 case format_32bppPBGRA
:
820 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
823 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
824 if (SUCCEEDED(hr
) && prc
)
828 for (y
=0; y
<prc
->Height
; y
++)
829 for (x
=0; x
<prc
->Width
; x
++)
831 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
834 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
835 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
836 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
844 static HRESULT
copypixels_to_24bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
845 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
849 switch (source_format
)
851 case format_24bppBGR
:
852 case format_24bppRGB
:
855 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
856 if (SUCCEEDED(hr
) && source_format
== format_24bppRGB
)
857 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
861 case format_32bppBGR
:
862 case format_32bppBGRA
:
863 case format_32bppPBGRA
:
869 UINT srcstride
, srcdatasize
;
871 const BYTE
*srcpixel
;
875 srcstride
= 4 * prc
->Width
;
876 srcdatasize
= srcstride
* prc
->Height
;
878 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
879 if (!srcdata
) return E_OUTOFMEMORY
;
881 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
887 for (y
=0; y
<prc
->Height
; y
++) {
890 for (x
=0; x
<prc
->Width
; x
++) {
891 *dstpixel
++=*srcpixel
++; /* blue */
892 *dstpixel
++=*srcpixel
++; /* green */
893 *dstpixel
++=*srcpixel
++; /* red */
894 srcpixel
++; /* alpha */
901 HeapFree(GetProcessHeap(), 0, srcdata
);
907 FIXME("Unimplemented conversion path!\n");
908 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
912 static HRESULT
copypixels_to_24bppRGB(struct FormatConverter
*This
, const WICRect
*prc
,
913 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
917 switch (source_format
)
919 case format_24bppBGR
:
920 case format_24bppRGB
:
923 hr
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
924 if (SUCCEEDED(hr
) && source_format
== format_24bppBGR
)
925 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
929 case format_32bppBGR
:
930 case format_32bppBGRA
:
931 case format_32bppPBGRA
:
937 UINT srcstride
, srcdatasize
;
939 const BYTE
*srcpixel
;
943 srcstride
= 4 * prc
->Width
;
944 srcdatasize
= srcstride
* prc
->Height
;
946 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
947 if (!srcdata
) return E_OUTOFMEMORY
;
949 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
955 for (y
=0; y
<prc
->Height
; y
++) {
958 for (x
=0; x
<prc
->Width
; x
++) {
959 *dstpixel
++=*srcpixel
++; /* blue */
960 *dstpixel
++=*srcpixel
++; /* green */
961 *dstpixel
++=*srcpixel
++; /* red */
962 srcpixel
++; /* alpha */
968 reverse_bgr8(3, pbBuffer
, prc
->Width
, prc
->Height
, cbStride
);
971 HeapFree(GetProcessHeap(), 0, srcdata
);
977 FIXME("Unimplemented conversion path!\n");
978 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
982 static const struct pixelformatinfo supported_formats
[] = {
983 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
984 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
985 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
986 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
987 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
988 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
989 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
990 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
991 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
992 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
993 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
994 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
995 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, copypixels_to_24bppBGR
},
996 {format_24bppRGB
, &GUID_WICPixelFormat24bppRGB
, copypixels_to_24bppRGB
},
997 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
998 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
999 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
1000 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
1001 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
1002 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
1006 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
1010 for (i
=0; supported_formats
[i
].guid
; i
++)
1011 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
1016 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
1019 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1020 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1022 if (!ppv
) return E_INVALIDARG
;
1024 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1025 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
1026 IsEqualIID(&IID_IWICFormatConverter
, iid
))
1028 *ppv
= &This
->IWICFormatConverter_iface
;
1033 return E_NOINTERFACE
;
1036 IUnknown_AddRef((IUnknown
*)*ppv
);
1040 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
1042 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1043 ULONG ref
= InterlockedIncrement(&This
->ref
);
1045 TRACE("(%p) refcount=%u\n", iface
, ref
);
1050 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
1052 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1053 ULONG ref
= InterlockedDecrement(&This
->ref
);
1055 TRACE("(%p) refcount=%u\n", iface
, ref
);
1059 This
->lock
.DebugInfo
->Spare
[0] = 0;
1060 DeleteCriticalSection(&This
->lock
);
1061 if (This
->source
) IWICBitmapSource_Release(This
->source
);
1062 HeapFree(GetProcessHeap(), 0, This
);
1068 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
1069 UINT
*puiWidth
, UINT
*puiHeight
)
1071 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1073 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
1076 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
1078 return WINCODEC_ERR_NOTINITIALIZED
;
1081 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
1082 WICPixelFormatGUID
*pPixelFormat
)
1084 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1086 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
1089 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
1091 return WINCODEC_ERR_NOTINITIALIZED
;
1096 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
1097 double *pDpiX
, double *pDpiY
)
1099 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1101 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
1104 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
1106 return WINCODEC_ERR_NOTINITIALIZED
;
1109 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
1110 IWICPalette
*pIPalette
)
1112 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
1116 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
1117 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
1119 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1122 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
1129 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
1130 if (FAILED(hr
)) return hr
;
1138 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
1139 pbBuffer
, This
->src_format
->format
);
1142 return WINCODEC_ERR_NOTINITIALIZED
;
1145 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
1146 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
1147 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
1149 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1150 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1155 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
1156 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
1158 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
1160 EnterCriticalSection(&This
->lock
);
1164 res
= WINCODEC_ERR_WRONGSTATE
;
1168 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
1169 if (FAILED(res
)) goto end
;
1171 srcinfo
= get_formatinfo(&srcFormat
);
1174 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1175 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1179 dstinfo
= get_formatinfo(dstFormat
);
1182 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1183 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1187 if (dstinfo
->copy_function
)
1189 IWICBitmapSource_AddRef(pISource
);
1190 This
->src_format
= srcinfo
;
1191 This
->dst_format
= dstinfo
;
1192 This
->dither
= dither
;
1193 This
->alpha_threshold
= alphaThresholdPercent
;
1194 This
->palette_type
= paletteTranslate
;
1195 This
->source
= pISource
;
1199 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1200 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1205 LeaveCriticalSection(&This
->lock
);
1210 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1211 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1214 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1215 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1217 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1218 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1220 srcinfo
= get_formatinfo(srcPixelFormat
);
1223 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1224 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1227 dstinfo
= get_formatinfo(dstPixelFormat
);
1230 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1231 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1234 if (dstinfo
->copy_function
&&
1235 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1236 *pfCanConvert
= TRUE
;
1239 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1240 *pfCanConvert
= FALSE
;
1246 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1247 FormatConverter_QueryInterface
,
1248 FormatConverter_AddRef
,
1249 FormatConverter_Release
,
1250 FormatConverter_GetSize
,
1251 FormatConverter_GetPixelFormat
,
1252 FormatConverter_GetResolution
,
1253 FormatConverter_CopyPalette
,
1254 FormatConverter_CopyPixels
,
1255 FormatConverter_Initialize
,
1256 FormatConverter_CanConvert
1259 HRESULT
FormatConverter_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1261 FormatConverter
*This
;
1264 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1268 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1270 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1271 if (!This
) return E_OUTOFMEMORY
;
1273 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1275 This
->source
= NULL
;
1276 InitializeCriticalSection(&This
->lock
);
1277 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1279 ret
= IWICFormatConverter_QueryInterface(&This
->IWICFormatConverter_iface
, iid
, ppv
);
1280 IWICFormatConverter_Release(&This
->IWICFormatConverter_iface
);