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
;
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 void make_grayscale_palette(WICColor
*colors
, UINT num_colors
)
88 for (i
=0; i
<num_colors
; i
++)
90 v
= i
* 255 / (num_colors
-1);
91 colors
[i
] = 0xff000000 | v
<<16 | v
<<8 | v
;
95 static HRESULT
copypixels_to_32bppBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
96 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
98 switch (source_format
)
100 case format_1bppIndexed
:
101 case format_BlackWhite
:
107 UINT srcstride
, srcdatasize
;
113 IWICPalette
*palette
;
116 if (source_format
== format_1bppIndexed
)
118 res
= PaletteImpl_Create(&palette
);
119 if (FAILED(res
)) return res
;
121 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
123 res
= IWICPalette_GetColors(palette
, 2, colors
, &actualcolors
);
125 IWICPalette_Release(palette
);
127 if (FAILED(res
)) return res
;
131 colors
[0] = 0xff000000;
132 colors
[1] = 0xffffffff;
135 srcstride
= (prc
->Width
+7)/8;
136 srcdatasize
= srcstride
* prc
->Height
;
138 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
139 if (!srcdata
) return E_OUTOFMEMORY
;
141 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
147 for (y
=0; y
<prc
->Height
; y
++) {
148 srcbyte
=(const BYTE
*)srcrow
;
149 dstpixel
=(DWORD
*)dstrow
;
150 for (x
=0; x
<prc
->Width
; x
+=8) {
153 *dstpixel
++ = colors
[srcval
>>7&1];
154 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>6&1];
155 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>5&1];
156 if (x
+3 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&1];
157 if (x
+4 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>3&1];
158 if (x
+5 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&1];
159 if (x
+6 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>1&1];
160 if (x
+7 < prc
->Width
) *dstpixel
++ = colors
[srcval
&1];
167 HeapFree(GetProcessHeap(), 0, srcdata
);
172 case format_2bppIndexed
:
173 case format_2bppGray
:
179 UINT srcstride
, srcdatasize
;
185 IWICPalette
*palette
;
188 if (source_format
== format_2bppIndexed
)
190 res
= PaletteImpl_Create(&palette
);
191 if (FAILED(res
)) return res
;
193 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
195 res
= IWICPalette_GetColors(palette
, 4, colors
, &actualcolors
);
197 IWICPalette_Release(palette
);
199 if (FAILED(res
)) return res
;
202 make_grayscale_palette(colors
, 4);
204 srcstride
= (prc
->Width
+3)/4;
205 srcdatasize
= srcstride
* prc
->Height
;
207 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
208 if (!srcdata
) return E_OUTOFMEMORY
;
210 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
216 for (y
=0; y
<prc
->Height
; y
++) {
217 srcbyte
=(const BYTE
*)srcrow
;
218 dstpixel
=(DWORD
*)dstrow
;
219 for (x
=0; x
<prc
->Width
; x
+=4) {
222 *dstpixel
++ = colors
[srcval
>>6];
223 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>4&0x3];
224 if (x
+2 < prc
->Width
) *dstpixel
++ = colors
[srcval
>>2&0x3];
225 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0x3];
232 HeapFree(GetProcessHeap(), 0, srcdata
);
237 case format_4bppIndexed
:
238 case format_4bppGray
:
244 UINT srcstride
, srcdatasize
;
250 IWICPalette
*palette
;
253 if (source_format
== format_4bppIndexed
)
255 res
= PaletteImpl_Create(&palette
);
256 if (FAILED(res
)) return res
;
258 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
260 res
= IWICPalette_GetColors(palette
, 16, colors
, &actualcolors
);
262 IWICPalette_Release(palette
);
264 if (FAILED(res
)) return res
;
267 make_grayscale_palette(colors
, 16);
269 srcstride
= (prc
->Width
+1)/2;
270 srcdatasize
= srcstride
* prc
->Height
;
272 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
273 if (!srcdata
) return E_OUTOFMEMORY
;
275 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
281 for (y
=0; y
<prc
->Height
; y
++) {
282 srcbyte
=(const BYTE
*)srcrow
;
283 dstpixel
=(DWORD
*)dstrow
;
284 for (x
=0; x
<prc
->Width
; x
+=2) {
287 *dstpixel
++ = colors
[srcval
>>4];
288 if (x
+1 < prc
->Width
) *dstpixel
++ = colors
[srcval
&0xf];
295 HeapFree(GetProcessHeap(), 0, srcdata
);
300 case format_8bppGray
:
306 UINT srcstride
, srcdatasize
;
312 srcstride
= prc
->Width
;
313 srcdatasize
= srcstride
* prc
->Height
;
315 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
316 if (!srcdata
) return E_OUTOFMEMORY
;
318 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
324 for (y
=0; y
<prc
->Height
; y
++) {
325 srcbyte
=(const BYTE
*)srcrow
;
326 dstpixel
=(DWORD
*)dstrow
;
327 for (x
=0; x
<prc
->Width
; x
++)
329 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
337 HeapFree(GetProcessHeap(), 0, srcdata
);
342 case format_8bppIndexed
:
348 UINT srcstride
, srcdatasize
;
353 WICColor colors
[256];
354 IWICPalette
*palette
;
357 res
= PaletteImpl_Create(&palette
);
358 if (FAILED(res
)) return res
;
360 res
= IWICBitmapSource_CopyPalette(This
->source
, palette
);
362 res
= IWICPalette_GetColors(palette
, 256, colors
, &actualcolors
);
364 IWICPalette_Release(palette
);
366 if (FAILED(res
)) return res
;
368 srcstride
= prc
->Width
;
369 srcdatasize
= srcstride
* prc
->Height
;
371 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
372 if (!srcdata
) return E_OUTOFMEMORY
;
374 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
380 for (y
=0; y
<prc
->Height
; y
++) {
381 srcbyte
=(const BYTE
*)srcrow
;
382 dstpixel
=(DWORD
*)dstrow
;
383 for (x
=0; x
<prc
->Width
; x
++)
384 *dstpixel
++ = colors
[*srcbyte
++];
390 HeapFree(GetProcessHeap(), 0, srcdata
);
395 case format_16bppGray
:
401 UINT srcstride
, srcdatasize
;
407 srcstride
= prc
->Width
* 2;
408 srcdatasize
= srcstride
* prc
->Height
;
410 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
411 if (!srcdata
) return E_OUTOFMEMORY
;
413 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
419 for (y
=0; y
<prc
->Height
; y
++) {
420 srcbyte
=(const BYTE
*)srcrow
;
421 dstpixel
=(DWORD
*)dstrow
;
422 for (x
=0; x
<prc
->Width
; x
++)
424 *dstpixel
++ = 0xff000000|(*srcbyte
<<16)|(*srcbyte
<<8)|*srcbyte
;
432 HeapFree(GetProcessHeap(), 0, srcdata
);
437 case format_16bppBGR555
:
443 UINT srcstride
, srcdatasize
;
445 const WORD
*srcpixel
;
449 srcstride
= 2 * prc
->Width
;
450 srcdatasize
= srcstride
* prc
->Height
;
452 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
453 if (!srcdata
) return E_OUTOFMEMORY
;
455 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
461 for (y
=0; y
<prc
->Height
; y
++) {
462 srcpixel
=(const WORD
*)srcrow
;
463 dstpixel
=(DWORD
*)dstrow
;
464 for (x
=0; x
<prc
->Width
; x
++) {
467 *dstpixel
++=0xff000000 | /* constant 255 alpha */
468 ((srcval
<< 9) & 0xf80000) | /* r */
469 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
470 ((srcval
<< 6) & 0x00f800) | /* g */
471 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
472 ((srcval
<< 3) & 0x0000f8) | /* b */
473 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
480 HeapFree(GetProcessHeap(), 0, srcdata
);
485 case format_16bppBGR565
:
491 UINT srcstride
, srcdatasize
;
493 const WORD
*srcpixel
;
497 srcstride
= 2 * prc
->Width
;
498 srcdatasize
= srcstride
* prc
->Height
;
500 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
501 if (!srcdata
) return E_OUTOFMEMORY
;
503 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
509 for (y
=0; y
<prc
->Height
; y
++) {
510 srcpixel
=(const WORD
*)srcrow
;
511 dstpixel
=(DWORD
*)dstrow
;
512 for (x
=0; x
<prc
->Width
; x
++) {
515 *dstpixel
++=0xff000000 | /* constant 255 alpha */
516 ((srcval
<< 8) & 0xf80000) | /* r */
517 ((srcval
<< 3) & 0x070000) | /* r - 3 bits */
518 ((srcval
<< 5) & 0x00fc00) | /* g */
519 ((srcval
>> 1) & 0x000300) | /* g - 2 bits */
520 ((srcval
<< 3) & 0x0000f8) | /* b */
521 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
528 HeapFree(GetProcessHeap(), 0, srcdata
);
533 case format_16bppBGRA5551
:
539 UINT srcstride
, srcdatasize
;
541 const WORD
*srcpixel
;
545 srcstride
= 2 * prc
->Width
;
546 srcdatasize
= srcstride
* prc
->Height
;
548 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
549 if (!srcdata
) return E_OUTOFMEMORY
;
551 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
557 for (y
=0; y
<prc
->Height
; y
++) {
558 srcpixel
=(const WORD
*)srcrow
;
559 dstpixel
=(DWORD
*)dstrow
;
560 for (x
=0; x
<prc
->Width
; x
++) {
563 *dstpixel
++=((srcval
& 0x8000) ? 0xff000000 : 0) | /* alpha */
564 ((srcval
<< 9) & 0xf80000) | /* r */
565 ((srcval
<< 4) & 0x070000) | /* r - 3 bits */
566 ((srcval
<< 6) & 0x00f800) | /* g */
567 ((srcval
<< 1) & 0x000700) | /* g - 3 bits */
568 ((srcval
<< 3) & 0x0000f8) | /* b */
569 ((srcval
>> 2) & 0x000007); /* b - 3 bits */
576 HeapFree(GetProcessHeap(), 0, srcdata
);
581 case format_24bppBGR
:
587 UINT srcstride
, srcdatasize
;
589 const BYTE
*srcpixel
;
593 srcstride
= 3 * prc
->Width
;
594 srcdatasize
= srcstride
* prc
->Height
;
596 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
597 if (!srcdata
) return E_OUTOFMEMORY
;
599 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
605 for (y
=0; y
<prc
->Height
; y
++) {
608 for (x
=0; x
<prc
->Width
; x
++) {
609 *dstpixel
++=*srcpixel
++; /* blue */
610 *dstpixel
++=*srcpixel
++; /* green */
611 *dstpixel
++=*srcpixel
++; /* red */
612 *dstpixel
++=255; /* alpha */
619 HeapFree(GetProcessHeap(), 0, srcdata
);
624 case format_32bppBGR
:
630 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
631 if (FAILED(res
)) return res
;
633 /* set all alpha values to 255 */
634 for (y
=0; y
<prc
->Height
; y
++)
635 for (x
=0; x
<prc
->Width
; x
++)
636 pbBuffer
[cbStride
*y
+4*x
+3] = 0xff;
639 case format_32bppBGRA
:
641 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
643 case format_32bppPBGRA
:
649 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
650 if (FAILED(res
)) return res
;
652 for (y
=0; y
<prc
->Height
; y
++)
653 for (x
=0; x
<prc
->Width
; x
++)
655 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
656 if (alpha
!= 0 && alpha
!= 255)
658 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * 255 / alpha
;
659 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * 255 / alpha
;
660 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * 255 / alpha
;
665 case format_48bppRGB
:
671 UINT srcstride
, srcdatasize
;
673 const BYTE
*srcpixel
;
677 srcstride
= 6 * prc
->Width
;
678 srcdatasize
= srcstride
* prc
->Height
;
680 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
681 if (!srcdata
) return E_OUTOFMEMORY
;
683 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
689 for (y
=0; y
<prc
->Height
; y
++) {
691 dstpixel
=(DWORD
*)dstrow
;
692 for (x
=0; x
<prc
->Width
; x
++) {
693 BYTE red
, green
, blue
;
694 red
= *srcpixel
++; srcpixel
++;
695 green
= *srcpixel
++; srcpixel
++;
696 blue
= *srcpixel
++; srcpixel
++;
697 *dstpixel
++=0xff000000|red
<<16|green
<<8|blue
;
704 HeapFree(GetProcessHeap(), 0, srcdata
);
709 case format_64bppRGBA
:
715 UINT srcstride
, srcdatasize
;
717 const BYTE
*srcpixel
;
721 srcstride
= 8 * prc
->Width
;
722 srcdatasize
= srcstride
* prc
->Height
;
724 srcdata
= HeapAlloc(GetProcessHeap(), 0, srcdatasize
);
725 if (!srcdata
) return E_OUTOFMEMORY
;
727 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, srcstride
, srcdatasize
, srcdata
);
733 for (y
=0; y
<prc
->Height
; y
++) {
735 dstpixel
=(DWORD
*)dstrow
;
736 for (x
=0; x
<prc
->Width
; x
++) {
737 BYTE red
, green
, blue
, alpha
;
738 red
= *srcpixel
++; srcpixel
++;
739 green
= *srcpixel
++; srcpixel
++;
740 blue
= *srcpixel
++; srcpixel
++;
741 alpha
= *srcpixel
++; srcpixel
++;
742 *dstpixel
++=alpha
<<24|red
<<16|green
<<8|blue
;
749 HeapFree(GetProcessHeap(), 0, srcdata
);
754 case format_32bppCMYK
:
760 res
= IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
761 if (FAILED(res
)) return res
;
763 for (y
=0; y
<prc
->Height
; y
++)
764 for (x
=0; x
<prc
->Width
; x
++)
766 BYTE
*pixel
= pbBuffer
+cbStride
*y
+4*x
;
767 BYTE c
=pixel
[0], m
=pixel
[1], y
=pixel
[2], k
=pixel
[3];
768 pixel
[0] = (255-y
)*(255-k
)/255; /* blue */
769 pixel
[1] = (255-m
)*(255-k
)/255; /* green */
770 pixel
[2] = (255-c
)*(255-k
)/255; /* red */
771 pixel
[3] = 255; /* alpha */
776 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
780 static HRESULT
copypixels_to_32bppBGR(struct FormatConverter
*This
, const WICRect
*prc
,
781 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
783 switch (source_format
)
785 case format_32bppBGR
:
786 case format_32bppBGRA
:
787 case format_32bppPBGRA
:
789 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
792 return copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
796 static HRESULT
copypixels_to_32bppPBGRA(struct FormatConverter
*This
, const WICRect
*prc
,
797 UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
, enum pixelformat source_format
)
801 switch (source_format
)
803 case format_32bppPBGRA
:
805 return IWICBitmapSource_CopyPixels(This
->source
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
808 hr
= copypixels_to_32bppBGRA(This
, prc
, cbStride
, cbBufferSize
, pbBuffer
, source_format
);
809 if (SUCCEEDED(hr
) && prc
)
813 for (y
=0; y
<prc
->Height
; y
++)
814 for (x
=0; x
<prc
->Width
; x
++)
816 BYTE alpha
= pbBuffer
[cbStride
*y
+4*x
+3];
819 pbBuffer
[cbStride
*y
+4*x
] = pbBuffer
[cbStride
*y
+4*x
] * alpha
/ 255;
820 pbBuffer
[cbStride
*y
+4*x
+1] = pbBuffer
[cbStride
*y
+4*x
+1] * alpha
/ 255;
821 pbBuffer
[cbStride
*y
+4*x
+2] = pbBuffer
[cbStride
*y
+4*x
+2] * alpha
/ 255;
829 static const struct pixelformatinfo supported_formats
[] = {
830 {format_1bppIndexed
, &GUID_WICPixelFormat1bppIndexed
, NULL
},
831 {format_2bppIndexed
, &GUID_WICPixelFormat2bppIndexed
, NULL
},
832 {format_4bppIndexed
, &GUID_WICPixelFormat4bppIndexed
, NULL
},
833 {format_8bppIndexed
, &GUID_WICPixelFormat8bppIndexed
, NULL
},
834 {format_BlackWhite
, &GUID_WICPixelFormatBlackWhite
, NULL
},
835 {format_2bppGray
, &GUID_WICPixelFormat2bppGray
, NULL
},
836 {format_4bppGray
, &GUID_WICPixelFormat4bppGray
, NULL
},
837 {format_8bppGray
, &GUID_WICPixelFormat8bppGray
, NULL
},
838 {format_16bppGray
, &GUID_WICPixelFormat16bppGray
, NULL
},
839 {format_16bppBGR555
, &GUID_WICPixelFormat16bppBGR555
, NULL
},
840 {format_16bppBGR565
, &GUID_WICPixelFormat16bppBGR565
, NULL
},
841 {format_16bppBGRA5551
, &GUID_WICPixelFormat16bppBGRA5551
, NULL
},
842 {format_24bppBGR
, &GUID_WICPixelFormat24bppBGR
, NULL
},
843 {format_32bppBGR
, &GUID_WICPixelFormat32bppBGR
, copypixels_to_32bppBGR
},
844 {format_32bppBGRA
, &GUID_WICPixelFormat32bppBGRA
, copypixels_to_32bppBGRA
},
845 {format_32bppPBGRA
, &GUID_WICPixelFormat32bppPBGRA
, copypixels_to_32bppPBGRA
},
846 {format_48bppRGB
, &GUID_WICPixelFormat48bppRGB
, NULL
},
847 {format_64bppRGBA
, &GUID_WICPixelFormat64bppRGBA
, NULL
},
848 {format_32bppCMYK
, &GUID_WICPixelFormat32bppCMYK
, NULL
},
852 static const struct pixelformatinfo
*get_formatinfo(const WICPixelFormatGUID
*format
)
856 for (i
=0; supported_formats
[i
].guid
; i
++)
857 if (IsEqualGUID(supported_formats
[i
].guid
, format
)) return &supported_formats
[i
];
862 static HRESULT WINAPI
FormatConverter_QueryInterface(IWICFormatConverter
*iface
, REFIID iid
,
865 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
866 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
868 if (!ppv
) return E_INVALIDARG
;
870 if (IsEqualIID(&IID_IUnknown
, iid
) ||
871 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
872 IsEqualIID(&IID_IWICFormatConverter
, iid
))
879 return E_NOINTERFACE
;
882 IUnknown_AddRef((IUnknown
*)*ppv
);
886 static ULONG WINAPI
FormatConverter_AddRef(IWICFormatConverter
*iface
)
888 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
889 ULONG ref
= InterlockedIncrement(&This
->ref
);
891 TRACE("(%p) refcount=%u\n", iface
, ref
);
896 static ULONG WINAPI
FormatConverter_Release(IWICFormatConverter
*iface
)
898 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
899 ULONG ref
= InterlockedDecrement(&This
->ref
);
901 TRACE("(%p) refcount=%u\n", iface
, ref
);
905 This
->lock
.DebugInfo
->Spare
[0] = 0;
906 DeleteCriticalSection(&This
->lock
);
907 if (This
->source
) IWICBitmapSource_Release(This
->source
);
908 HeapFree(GetProcessHeap(), 0, This
);
914 static HRESULT WINAPI
FormatConverter_GetSize(IWICFormatConverter
*iface
,
915 UINT
*puiWidth
, UINT
*puiHeight
)
917 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
919 TRACE("(%p,%p,%p)\n", iface
, puiWidth
, puiHeight
);
922 return IWICBitmapSource_GetSize(This
->source
, puiWidth
, puiHeight
);
924 return WINCODEC_ERR_NOTINITIALIZED
;
927 static HRESULT WINAPI
FormatConverter_GetPixelFormat(IWICFormatConverter
*iface
,
928 WICPixelFormatGUID
*pPixelFormat
)
930 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
932 TRACE("(%p,%p): stub\n", iface
, pPixelFormat
);
935 memcpy(pPixelFormat
, This
->dst_format
->guid
, sizeof(GUID
));
937 return WINCODEC_ERR_NOTINITIALIZED
;
942 static HRESULT WINAPI
FormatConverter_GetResolution(IWICFormatConverter
*iface
,
943 double *pDpiX
, double *pDpiY
)
945 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
947 TRACE("(%p,%p,%p): stub\n", iface
, pDpiX
, pDpiY
);
950 return IWICBitmapSource_GetResolution(This
->source
, pDpiX
, pDpiY
);
952 return WINCODEC_ERR_NOTINITIALIZED
;
955 static HRESULT WINAPI
FormatConverter_CopyPalette(IWICFormatConverter
*iface
,
956 IWICPalette
*pIPalette
)
958 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
962 static HRESULT WINAPI
FormatConverter_CopyPixels(IWICFormatConverter
*iface
,
963 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
965 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
968 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
975 hr
= IWICBitmapSource_GetSize(This
->source
, &width
, &height
);
976 if (FAILED(hr
)) return hr
;
984 return This
->dst_format
->copy_function(This
, prc
, cbStride
, cbBufferSize
,
985 pbBuffer
, This
->src_format
->format
);
988 return WINCODEC_ERR_NOTINITIALIZED
;
991 static HRESULT WINAPI
FormatConverter_Initialize(IWICFormatConverter
*iface
,
992 IWICBitmapSource
*pISource
, REFWICPixelFormatGUID dstFormat
, WICBitmapDitherType dither
,
993 IWICPalette
*pIPalette
, double alphaThresholdPercent
, WICBitmapPaletteType paletteTranslate
)
995 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
996 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1001 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface
, pISource
, debugstr_guid(dstFormat
),
1002 dither
, pIPalette
, alphaThresholdPercent
, paletteTranslate
);
1004 if (pIPalette
&& !fixme
++) FIXME("ignoring palette\n");
1006 EnterCriticalSection(&This
->lock
);
1010 res
= WINCODEC_ERR_WRONGSTATE
;
1014 res
= IWICBitmapSource_GetPixelFormat(pISource
, &srcFormat
);
1015 if (FAILED(res
)) goto end
;
1017 srcinfo
= get_formatinfo(&srcFormat
);
1020 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1021 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat
));
1025 dstinfo
= get_formatinfo(dstFormat
);
1028 res
= WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1029 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat
));
1033 if (dstinfo
->copy_function
)
1035 IWICBitmapSource_AddRef(pISource
);
1036 This
->src_format
= srcinfo
;
1037 This
->dst_format
= dstinfo
;
1038 This
->dither
= dither
;
1039 This
->alpha_threshold
= alphaThresholdPercent
;
1040 This
->palette_type
= paletteTranslate
;
1041 This
->source
= pISource
;
1045 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat
), debugstr_guid(dstFormat
));
1046 res
= WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1051 LeaveCriticalSection(&This
->lock
);
1056 static HRESULT WINAPI
FormatConverter_CanConvert(IWICFormatConverter
*iface
,
1057 REFWICPixelFormatGUID srcPixelFormat
, REFWICPixelFormatGUID dstPixelFormat
,
1060 FormatConverter
*This
= impl_from_IWICFormatConverter(iface
);
1061 const struct pixelformatinfo
*srcinfo
, *dstinfo
;
1063 TRACE("(%p,%s,%s,%p)\n", iface
, debugstr_guid(srcPixelFormat
),
1064 debugstr_guid(dstPixelFormat
), pfCanConvert
);
1066 srcinfo
= get_formatinfo(srcPixelFormat
);
1069 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat
));
1070 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1073 dstinfo
= get_formatinfo(dstPixelFormat
);
1076 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat
));
1077 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
1080 if (dstinfo
->copy_function
&&
1081 SUCCEEDED(dstinfo
->copy_function(This
, NULL
, 0, 0, NULL
, dstinfo
->format
)))
1082 *pfCanConvert
= TRUE
;
1085 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat
), debugstr_guid(dstPixelFormat
));
1086 *pfCanConvert
= FALSE
;
1092 static const IWICFormatConverterVtbl FormatConverter_Vtbl
= {
1093 FormatConverter_QueryInterface
,
1094 FormatConverter_AddRef
,
1095 FormatConverter_Release
,
1096 FormatConverter_GetSize
,
1097 FormatConverter_GetPixelFormat
,
1098 FormatConverter_GetResolution
,
1099 FormatConverter_CopyPalette
,
1100 FormatConverter_CopyPixels
,
1101 FormatConverter_Initialize
,
1102 FormatConverter_CanConvert
1105 HRESULT
FormatConverter_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1107 FormatConverter
*This
;
1110 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1114 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1116 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter
));
1117 if (!This
) return E_OUTOFMEMORY
;
1119 This
->IWICFormatConverter_iface
.lpVtbl
= &FormatConverter_Vtbl
;
1121 This
->source
= NULL
;
1122 InitializeCriticalSection(&This
->lock
);
1123 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FormatConverter.lock");
1125 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
1126 IUnknown_Release((IUnknown
*)This
);