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 HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc,
86 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
88 switch (source_format)
90 case format_1bppIndexed:
91 case format_BlackWhite:
97 UINT srcstride, srcdatasize;
103 IWICPalette *palette;
106 res = PaletteImpl_Create(&palette);
107 if (FAILED(res)) return res;
109 if (source_format == format_1bppIndexed)
110 res = IWICBitmapSource_CopyPalette(This->source, palette);
112 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedBW, FALSE);
115 res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
117 IWICPalette_Release(palette);
118 if (FAILED(res)) return res;
120 srcstride = (prc->Width+7)/8;
121 srcdatasize = srcstride * prc->Height;
123 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
124 if (!srcdata) return E_OUTOFMEMORY;
126 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
132 for (y=0; y<prc->Height; y++) {
134 dstpixel=(DWORD*)dstrow;
135 for (x=0; x<prc->Width; x+=8) {
138 *dstpixel++ = colors[srcval>>7&1];
139 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>6&1];
140 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>5&1];
141 if (x+3 < prc->Width) *dstpixel++ = colors[srcval>>4&1];
142 if (x+4 < prc->Width) *dstpixel++ = colors[srcval>>3&1];
143 if (x+5 < prc->Width) *dstpixel++ = colors[srcval>>2&1];
144 if (x+6 < prc->Width) *dstpixel++ = colors[srcval>>1&1];
145 if (x+7 < prc->Width) *dstpixel++ = colors[srcval&1];
152 HeapFree(GetProcessHeap(), 0, srcdata);
157 case format_2bppIndexed:
158 case format_2bppGray:
164 UINT srcstride, srcdatasize;
170 IWICPalette *palette;
173 res = PaletteImpl_Create(&palette);
174 if (FAILED(res)) return res;
176 if (source_format == format_2bppIndexed)
177 res = IWICBitmapSource_CopyPalette(This->source, palette);
179 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray4, FALSE);
182 res = IWICPalette_GetColors(palette, 4, colors, &actualcolors);
184 IWICPalette_Release(palette);
185 if (FAILED(res)) return res;
187 srcstride = (prc->Width+3)/4;
188 srcdatasize = srcstride * prc->Height;
190 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
191 if (!srcdata) return E_OUTOFMEMORY;
193 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
199 for (y=0; y<prc->Height; y++) {
201 dstpixel=(DWORD*)dstrow;
202 for (x=0; x<prc->Width; x+=4) {
205 *dstpixel++ = colors[srcval>>6];
206 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>4&0x3];
207 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>2&0x3];
208 if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0x3];
215 HeapFree(GetProcessHeap(), 0, srcdata);
220 case format_4bppIndexed:
221 case format_4bppGray:
227 UINT srcstride, srcdatasize;
233 IWICPalette *palette;
236 res = PaletteImpl_Create(&palette);
237 if (FAILED(res)) return res;
239 if (source_format == format_4bppIndexed)
240 res = IWICBitmapSource_CopyPalette(This->source, palette);
242 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray16, FALSE);
245 res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
247 IWICPalette_Release(palette);
248 if (FAILED(res)) return res;
250 srcstride = (prc->Width+1)/2;
251 srcdatasize = srcstride * prc->Height;
253 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
254 if (!srcdata) return E_OUTOFMEMORY;
256 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
262 for (y=0; y<prc->Height; y++) {
264 dstpixel=(DWORD*)dstrow;
265 for (x=0; x<prc->Width; x+=2) {
268 *dstpixel++ = colors[srcval>>4];
269 if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0xf];
276 HeapFree(GetProcessHeap(), 0, srcdata);
281 case format_8bppGray:
287 UINT srcstride, srcdatasize;
293 srcstride = prc->Width;
294 srcdatasize = srcstride * prc->Height;
296 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
297 if (!srcdata) return E_OUTOFMEMORY;
299 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
305 for (y=0; y<prc->Height; y++) {
307 dstpixel=(DWORD*)dstrow;
308 for (x=0; x<prc->Width; x++)
310 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
318 HeapFree(GetProcessHeap(), 0, srcdata);
323 case format_8bppIndexed:
329 UINT srcstride, srcdatasize;
334 WICColor colors[256];
335 IWICPalette *palette;
338 res = PaletteImpl_Create(&palette);
339 if (FAILED(res)) return res;
341 res = IWICBitmapSource_CopyPalette(This->source, palette);
343 res = IWICPalette_GetColors(palette, 256, colors, &actualcolors);
345 IWICPalette_Release(palette);
347 if (FAILED(res)) return res;
349 srcstride = prc->Width;
350 srcdatasize = srcstride * prc->Height;
352 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
353 if (!srcdata) return E_OUTOFMEMORY;
355 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
361 for (y=0; y<prc->Height; y++) {
363 dstpixel=(DWORD*)dstrow;
364 for (x=0; x<prc->Width; x++)
365 *dstpixel++ = colors[*srcbyte++];
371 HeapFree(GetProcessHeap(), 0, srcdata);
376 case format_16bppGray:
382 UINT srcstride, srcdatasize;
388 srcstride = prc->Width * 2;
389 srcdatasize = srcstride * prc->Height;
391 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
392 if (!srcdata) return E_OUTOFMEMORY;
394 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
400 for (y=0; y<prc->Height; y++) {
402 dstpixel=(DWORD*)dstrow;
403 for (x=0; x<prc->Width; x++)
405 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
413 HeapFree(GetProcessHeap(), 0, srcdata);
418 case format_16bppBGR555:
424 UINT srcstride, srcdatasize;
426 const WORD *srcpixel;
430 srcstride = 2 * prc->Width;
431 srcdatasize = srcstride * prc->Height;
433 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
434 if (!srcdata) return E_OUTOFMEMORY;
436 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
442 for (y=0; y<prc->Height; y++) {
443 srcpixel=(const WORD*)srcrow;
444 dstpixel=(DWORD*)dstrow;
445 for (x=0; x<prc->Width; x++) {
448 *dstpixel++=0xff000000 | /* constant 255 alpha */
449 ((srcval << 9) & 0xf80000) | /* r */
450 ((srcval << 4) & 0x070000) | /* r - 3 bits */
451 ((srcval << 6) & 0x00f800) | /* g */
452 ((srcval << 1) & 0x000700) | /* g - 3 bits */
453 ((srcval << 3) & 0x0000f8) | /* b */
454 ((srcval >> 2) & 0x000007); /* b - 3 bits */
461 HeapFree(GetProcessHeap(), 0, srcdata);
466 case format_16bppBGR565:
472 UINT srcstride, srcdatasize;
474 const WORD *srcpixel;
478 srcstride = 2 * prc->Width;
479 srcdatasize = srcstride * prc->Height;
481 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
482 if (!srcdata) return E_OUTOFMEMORY;
484 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
490 for (y=0; y<prc->Height; y++) {
491 srcpixel=(const WORD*)srcrow;
492 dstpixel=(DWORD*)dstrow;
493 for (x=0; x<prc->Width; x++) {
496 *dstpixel++=0xff000000 | /* constant 255 alpha */
497 ((srcval << 8) & 0xf80000) | /* r */
498 ((srcval << 3) & 0x070000) | /* r - 3 bits */
499 ((srcval << 5) & 0x00fc00) | /* g */
500 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
501 ((srcval << 3) & 0x0000f8) | /* b */
502 ((srcval >> 2) & 0x000007); /* b - 3 bits */
509 HeapFree(GetProcessHeap(), 0, srcdata);
514 case format_16bppBGRA5551:
520 UINT srcstride, srcdatasize;
522 const WORD *srcpixel;
526 srcstride = 2 * prc->Width;
527 srcdatasize = srcstride * prc->Height;
529 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
530 if (!srcdata) return E_OUTOFMEMORY;
532 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
538 for (y=0; y<prc->Height; y++) {
539 srcpixel=(const WORD*)srcrow;
540 dstpixel=(DWORD*)dstrow;
541 for (x=0; x<prc->Width; x++) {
544 *dstpixel++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
545 ((srcval << 9) & 0xf80000) | /* r */
546 ((srcval << 4) & 0x070000) | /* r - 3 bits */
547 ((srcval << 6) & 0x00f800) | /* g */
548 ((srcval << 1) & 0x000700) | /* g - 3 bits */
549 ((srcval << 3) & 0x0000f8) | /* b */
550 ((srcval >> 2) & 0x000007); /* b - 3 bits */
557 HeapFree(GetProcessHeap(), 0, srcdata);
562 case format_24bppBGR:
568 UINT srcstride, srcdatasize;
570 const BYTE *srcpixel;
574 srcstride = 3 * prc->Width;
575 srcdatasize = srcstride * prc->Height;
577 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
578 if (!srcdata) return E_OUTOFMEMORY;
580 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
586 for (y=0; y<prc->Height; y++) {
589 for (x=0; x<prc->Width; x++) {
590 *dstpixel++=*srcpixel++; /* blue */
591 *dstpixel++=*srcpixel++; /* green */
592 *dstpixel++=*srcpixel++; /* red */
593 *dstpixel++=255; /* alpha */
600 HeapFree(GetProcessHeap(), 0, srcdata);
605 case format_32bppBGR:
611 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
612 if (FAILED(res)) return res;
614 /* set all alpha values to 255 */
615 for (y=0; y<prc->Height; y++)
616 for (x=0; x<prc->Width; x++)
617 pbBuffer[cbStride*y+4*x+3] = 0xff;
620 case format_32bppBGRA:
622 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
624 case format_32bppPBGRA:
630 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
631 if (FAILED(res)) return res;
633 for (y=0; y<prc->Height; y++)
634 for (x=0; x<prc->Width; x++)
636 BYTE alpha = pbBuffer[cbStride*y+4*x+3];
637 if (alpha != 0 && alpha != 255)
639 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha;
640 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha;
641 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha;
646 case format_48bppRGB:
652 UINT srcstride, srcdatasize;
654 const BYTE *srcpixel;
658 srcstride = 6 * prc->Width;
659 srcdatasize = srcstride * prc->Height;
661 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
662 if (!srcdata) return E_OUTOFMEMORY;
664 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
670 for (y=0; y<prc->Height; y++) {
672 dstpixel=(DWORD*)dstrow;
673 for (x=0; x<prc->Width; x++) {
674 BYTE red, green, blue;
675 red = *srcpixel++; srcpixel++;
676 green = *srcpixel++; srcpixel++;
677 blue = *srcpixel++; srcpixel++;
678 *dstpixel++=0xff000000|red<<16|green<<8|blue;
685 HeapFree(GetProcessHeap(), 0, srcdata);
690 case format_64bppRGBA:
696 UINT srcstride, srcdatasize;
698 const BYTE *srcpixel;
702 srcstride = 8 * prc->Width;
703 srcdatasize = srcstride * prc->Height;
705 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
706 if (!srcdata) return E_OUTOFMEMORY;
708 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
714 for (y=0; y<prc->Height; y++) {
716 dstpixel=(DWORD*)dstrow;
717 for (x=0; x<prc->Width; x++) {
718 BYTE red, green, blue, alpha;
719 red = *srcpixel++; srcpixel++;
720 green = *srcpixel++; srcpixel++;
721 blue = *srcpixel++; srcpixel++;
722 alpha = *srcpixel++; srcpixel++;
723 *dstpixel++=alpha<<24|red<<16|green<<8|blue;
730 HeapFree(GetProcessHeap(), 0, srcdata);
735 case format_32bppCMYK:
741 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
742 if (FAILED(res)) return res;
744 for (y=0; y<prc->Height; y++)
745 for (x=0; x<prc->Width; x++)
747 BYTE *pixel = pbBuffer+cbStride*y+4*x;
748 BYTE c=pixel[0], m=pixel[1], y=pixel[2], k=pixel[3];
749 pixel[0] = (255-y)*(255-k)/255; /* blue */
750 pixel[1] = (255-m)*(255-k)/255; /* green */
751 pixel[2] = (255-c)*(255-k)/255; /* red */
752 pixel[3] = 255; /* alpha */
757 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
761 static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc,
762 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
764 switch (source_format)
766 case format_32bppBGR:
767 case format_32bppBGRA:
768 case format_32bppPBGRA:
770 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
773 return copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
777 static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc,
778 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
782 switch (source_format)
784 case format_32bppPBGRA:
786 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
789 hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
790 if (SUCCEEDED(hr) && prc)
794 for (y=0; y<prc->Height; y++)
795 for (x=0; x<prc->Width; x++)
797 BYTE alpha = pbBuffer[cbStride*y+4*x+3];
800 pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255;
801 pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255;
802 pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255;
810 static const struct pixelformatinfo supported_formats[] = {
811 {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
812 {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
813 {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
814 {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL},
815 {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
816 {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
817 {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
818 {format_8bppGray, &GUID_WICPixelFormat8bppGray, NULL},
819 {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL},
820 {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
821 {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
822 {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL},
823 {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, NULL},
824 {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR},
825 {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA},
826 {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA},
827 {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL},
828 {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL},
829 {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL},
833 static const struct pixelformatinfo *get_formatinfo(const WICPixelFormatGUID *format)
837 for (i=0; supported_formats[i].guid; i++)
838 if (IsEqualGUID(supported_formats[i].guid, format)) return &supported_formats[i];
843 static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid,
846 FormatConverter *This = impl_from_IWICFormatConverter(iface);
847 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
849 if (!ppv) return E_INVALIDARG;
851 if (IsEqualIID(&IID_IUnknown, iid) ||
852 IsEqualIID(&IID_IWICBitmapSource, iid) ||
853 IsEqualIID(&IID_IWICFormatConverter, iid))
855 *ppv = &This->IWICFormatConverter_iface;
860 return E_NOINTERFACE;
863 IUnknown_AddRef((IUnknown*)*ppv);
867 static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface)
869 FormatConverter *This = impl_from_IWICFormatConverter(iface);
870 ULONG ref = InterlockedIncrement(&This->ref);
872 TRACE("(%p) refcount=%u\n", iface, ref);
877 static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
879 FormatConverter *This = impl_from_IWICFormatConverter(iface);
880 ULONG ref = InterlockedDecrement(&This->ref);
882 TRACE("(%p) refcount=%u\n", iface, ref);
886 This->lock.DebugInfo->Spare[0] = 0;
887 DeleteCriticalSection(&This->lock);
888 if (This->source) IWICBitmapSource_Release(This->source);
889 HeapFree(GetProcessHeap(), 0, This);
895 static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface,
896 UINT *puiWidth, UINT *puiHeight)
898 FormatConverter *This = impl_from_IWICFormatConverter(iface);
900 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
903 return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight);
905 return WINCODEC_ERR_NOTINITIALIZED;
908 static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface,
909 WICPixelFormatGUID *pPixelFormat)
911 FormatConverter *This = impl_from_IWICFormatConverter(iface);
913 TRACE("(%p,%p): stub\n", iface, pPixelFormat);
916 memcpy(pPixelFormat, This->dst_format->guid, sizeof(GUID));
918 return WINCODEC_ERR_NOTINITIALIZED;
923 static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
924 double *pDpiX, double *pDpiY)
926 FormatConverter *This = impl_from_IWICFormatConverter(iface);
928 TRACE("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
931 return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY);
933 return WINCODEC_ERR_NOTINITIALIZED;
936 static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
937 IWICPalette *pIPalette)
939 FIXME("(%p,%p): stub\n", iface, pIPalette);
943 static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
944 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
946 FormatConverter *This = impl_from_IWICFormatConverter(iface);
949 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
956 hr = IWICBitmapSource_GetSize(This->source, &width, &height);
957 if (FAILED(hr)) return hr;
965 return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize,
966 pbBuffer, This->src_format->format);
969 return WINCODEC_ERR_NOTINITIALIZED;
972 static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
973 IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
974 IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
976 FormatConverter *This = impl_from_IWICFormatConverter(iface);
977 const struct pixelformatinfo *srcinfo, *dstinfo;
982 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
983 dither, pIPalette, alphaThresholdPercent, paletteTranslate);
985 if (pIPalette && !fixme++) FIXME("ignoring palette\n");
987 EnterCriticalSection(&This->lock);
991 res = WINCODEC_ERR_WRONGSTATE;
995 res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
996 if (FAILED(res)) goto end;
998 srcinfo = get_formatinfo(&srcFormat);
1001 res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1002 FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat));
1006 dstinfo = get_formatinfo(dstFormat);
1009 res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1010 FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat));
1014 if (dstinfo->copy_function)
1016 IWICBitmapSource_AddRef(pISource);
1017 This->src_format = srcinfo;
1018 This->dst_format = dstinfo;
1019 This->dither = dither;
1020 This->alpha_threshold = alphaThresholdPercent;
1021 This->palette_type = paletteTranslate;
1022 This->source = pISource;
1026 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1027 res = WINCODEC_ERR_UNSUPPORTEDOPERATION;
1032 LeaveCriticalSection(&This->lock);
1037 static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface,
1038 REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat,
1041 FormatConverter *This = impl_from_IWICFormatConverter(iface);
1042 const struct pixelformatinfo *srcinfo, *dstinfo;
1044 TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat),
1045 debugstr_guid(dstPixelFormat), pfCanConvert);
1047 srcinfo = get_formatinfo(srcPixelFormat);
1050 FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat));
1051 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1054 dstinfo = get_formatinfo(dstPixelFormat);
1057 FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat));
1058 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1061 if (dstinfo->copy_function &&
1062 SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format)))
1063 *pfCanConvert = TRUE;
1066 FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat));
1067 *pfCanConvert = FALSE;
1073 static const IWICFormatConverterVtbl FormatConverter_Vtbl = {
1074 FormatConverter_QueryInterface,
1075 FormatConverter_AddRef,
1076 FormatConverter_Release,
1077 FormatConverter_GetSize,
1078 FormatConverter_GetPixelFormat,
1079 FormatConverter_GetResolution,
1080 FormatConverter_CopyPalette,
1081 FormatConverter_CopyPixels,
1082 FormatConverter_Initialize,
1083 FormatConverter_CanConvert
1086 HRESULT FormatConverter_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
1088 FormatConverter *This;
1091 TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
1095 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
1097 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
1098 if (!This) return E_OUTOFMEMORY;
1100 This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
1102 This->source = NULL;
1103 InitializeCriticalSection(&This->lock);
1104 This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
1106 ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface, iid, ppv);
1107 IWICFormatConverter_Release(&This->IWICFormatConverter_iface);