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);