makefiles: Generate the config.status dependency as part of the makefile dependencies.
[wine/multimedia.git] / dlls / windowscodecs / converter.c
blob15c7b0f380aab39219b92983d34151cefac74c64
1 /*
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 "config.h"
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
28 #include "wincodec.h"
30 #include "wincodecs_private.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
36 struct FormatConverter;
38 enum pixelformat {
39 format_1bppIndexed,
40 format_2bppIndexed,
41 format_4bppIndexed,
42 format_8bppIndexed,
43 format_BlackWhite,
44 format_2bppGray,
45 format_4bppGray,
46 format_8bppGray,
47 format_16bppGray,
48 format_16bppBGR555,
49 format_16bppBGR565,
50 format_24bppBGR,
51 format_32bppBGR,
52 format_32bppBGRA,
53 format_48bppRGB,
54 format_64bppRGBA,
57 typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc,
58 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format);
60 struct pixelformatinfo {
61 enum pixelformat format;
62 const WICPixelFormatGUID *guid;
63 copyfunc copy_function;
66 typedef struct FormatConverter {
67 const IWICFormatConverterVtbl *lpVtbl;
68 LONG ref;
69 IWICBitmapSource *source;
70 const struct pixelformatinfo *dst_format, *src_format;
71 WICBitmapDitherType dither;
72 double alpha_threshold;
73 WICBitmapPaletteType palette_type;
74 } FormatConverter;
76 static void make_grayscale_palette(WICColor *colors, UINT num_colors)
78 int i, v;
79 for (i=0; i<num_colors; i++)
81 v = i * 255 / (num_colors-1);
82 colors[i] = 0xff000000 | v<<16 | v<<8 | v;
86 static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc,
87 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
89 switch (source_format)
91 case format_1bppIndexed:
92 case format_BlackWhite:
93 if (prc)
95 HRESULT res;
96 UINT x, y;
97 BYTE *srcdata;
98 UINT srcstride, srcdatasize;
99 const BYTE *srcrow;
100 const BYTE *srcbyte;
101 BYTE *dstrow;
102 DWORD *dstpixel;
103 WICColor colors[2];
104 IWICPalette *palette;
105 UINT actualcolors;
107 if (source_format == format_1bppIndexed)
109 res = PaletteImpl_Create(&palette);
110 if (FAILED(res)) return res;
112 res = IWICBitmapSource_CopyPalette(This->source, palette);
113 if (SUCCEEDED(res))
114 res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
116 IWICPalette_Release(palette);
118 if (FAILED(res)) return res;
120 else
122 colors[0] = 0xff000000;
123 colors[1] = 0xffffffff;
126 srcstride = (prc->Width+7)/8;
127 srcdatasize = srcstride * prc->Height;
129 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
130 if (!srcdata) return E_OUTOFMEMORY;
132 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
134 if (SUCCEEDED(res))
136 srcrow = srcdata;
137 dstrow = pbBuffer;
138 for (y=0; y<prc->Height; y++) {
139 srcbyte=(const BYTE*)srcrow;
140 dstpixel=(DWORD*)dstrow;
141 for (x=0; x<prc->Width; x+=8) {
142 BYTE srcval;
143 srcval=*srcbyte++;
144 *dstpixel++ = colors[srcval>>7&1];
145 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>6&1];
146 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>5&1];
147 if (x+3 < prc->Width) *dstpixel++ = colors[srcval>>4&1];
148 if (x+4 < prc->Width) *dstpixel++ = colors[srcval>>3&1];
149 if (x+5 < prc->Width) *dstpixel++ = colors[srcval>>2&1];
150 if (x+6 < prc->Width) *dstpixel++ = colors[srcval>>1&1];
151 if (x+7 < prc->Width) *dstpixel++ = colors[srcval&1];
153 srcrow += srcstride;
154 dstrow += cbStride;
158 HeapFree(GetProcessHeap(), 0, srcdata);
160 return res;
162 return S_OK;
163 case format_2bppIndexed:
164 case format_2bppGray:
165 if (prc)
167 HRESULT res;
168 UINT x, y;
169 BYTE *srcdata;
170 UINT srcstride, srcdatasize;
171 const BYTE *srcrow;
172 const BYTE *srcbyte;
173 BYTE *dstrow;
174 DWORD *dstpixel;
175 WICColor colors[4];
176 IWICPalette *palette;
177 UINT actualcolors;
179 if (source_format == format_2bppIndexed)
181 res = PaletteImpl_Create(&palette);
182 if (FAILED(res)) return res;
184 res = IWICBitmapSource_CopyPalette(This->source, palette);
185 if (SUCCEEDED(res))
186 res = IWICPalette_GetColors(palette, 4, colors, &actualcolors);
188 IWICPalette_Release(palette);
190 if (FAILED(res)) return res;
192 else
193 make_grayscale_palette(colors, 4);
195 srcstride = (prc->Width+3)/4;
196 srcdatasize = srcstride * prc->Height;
198 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
199 if (!srcdata) return E_OUTOFMEMORY;
201 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
203 if (SUCCEEDED(res))
205 srcrow = srcdata;
206 dstrow = pbBuffer;
207 for (y=0; y<prc->Height; y++) {
208 srcbyte=(const BYTE*)srcrow;
209 dstpixel=(DWORD*)dstrow;
210 for (x=0; x<prc->Width; x+=4) {
211 BYTE srcval;
212 srcval=*srcbyte++;
213 *dstpixel++ = colors[srcval>>6];
214 if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>4&0x3];
215 if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>2&0x3];
216 if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0x3];
218 srcrow += srcstride;
219 dstrow += cbStride;
223 HeapFree(GetProcessHeap(), 0, srcdata);
225 return res;
227 return S_OK;
228 case format_4bppIndexed:
229 case format_4bppGray:
230 if (prc)
232 HRESULT res;
233 UINT x, y;
234 BYTE *srcdata;
235 UINT srcstride, srcdatasize;
236 const BYTE *srcrow;
237 const BYTE *srcbyte;
238 BYTE *dstrow;
239 DWORD *dstpixel;
240 WICColor colors[16];
241 IWICPalette *palette;
242 UINT actualcolors;
244 if (source_format == format_4bppIndexed)
246 res = PaletteImpl_Create(&palette);
247 if (FAILED(res)) return res;
249 res = IWICBitmapSource_CopyPalette(This->source, palette);
250 if (SUCCEEDED(res))
251 res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
253 IWICPalette_Release(palette);
255 if (FAILED(res)) return res;
257 else
258 make_grayscale_palette(colors, 16);
260 srcstride = (prc->Width+1)/2;
261 srcdatasize = srcstride * prc->Height;
263 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
264 if (!srcdata) return E_OUTOFMEMORY;
266 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
268 if (SUCCEEDED(res))
270 srcrow = srcdata;
271 dstrow = pbBuffer;
272 for (y=0; y<prc->Height; y++) {
273 srcbyte=(const BYTE*)srcrow;
274 dstpixel=(DWORD*)dstrow;
275 for (x=0; x<prc->Width; x+=2) {
276 BYTE srcval;
277 srcval=*srcbyte++;
278 *dstpixel++ = colors[srcval>>4];
279 if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0xf];
281 srcrow += srcstride;
282 dstrow += cbStride;
286 HeapFree(GetProcessHeap(), 0, srcdata);
288 return res;
290 return S_OK;
291 case format_8bppGray:
292 if (prc)
294 HRESULT res;
295 UINT x, y;
296 BYTE *srcdata;
297 UINT srcstride, srcdatasize;
298 const BYTE *srcrow;
299 const BYTE *srcbyte;
300 BYTE *dstrow;
301 DWORD *dstpixel;
303 srcstride = prc->Width;
304 srcdatasize = srcstride * prc->Height;
306 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
307 if (!srcdata) return E_OUTOFMEMORY;
309 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
311 if (SUCCEEDED(res))
313 srcrow = srcdata;
314 dstrow = pbBuffer;
315 for (y=0; y<prc->Height; y++) {
316 srcbyte=(const BYTE*)srcrow;
317 dstpixel=(DWORD*)dstrow;
318 for (x=0; x<prc->Width; x++)
320 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
321 srcbyte++;
323 srcrow += srcstride;
324 dstrow += cbStride;
328 HeapFree(GetProcessHeap(), 0, srcdata);
330 return res;
332 return S_OK;
333 case format_8bppIndexed:
334 if (prc)
336 HRESULT res;
337 UINT x, y;
338 BYTE *srcdata;
339 UINT srcstride, srcdatasize;
340 const BYTE *srcrow;
341 const BYTE *srcbyte;
342 BYTE *dstrow;
343 DWORD *dstpixel;
344 WICColor colors[256];
345 IWICPalette *palette;
346 UINT actualcolors;
348 res = PaletteImpl_Create(&palette);
349 if (FAILED(res)) return res;
351 res = IWICBitmapSource_CopyPalette(This->source, palette);
352 if (SUCCEEDED(res))
353 res = IWICPalette_GetColors(palette, 256, colors, &actualcolors);
355 IWICPalette_Release(palette);
357 if (FAILED(res)) return res;
359 srcstride = prc->Width;
360 srcdatasize = srcstride * prc->Height;
362 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
363 if (!srcdata) return E_OUTOFMEMORY;
365 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
367 if (SUCCEEDED(res))
369 srcrow = srcdata;
370 dstrow = pbBuffer;
371 for (y=0; y<prc->Height; y++) {
372 srcbyte=(const BYTE*)srcrow;
373 dstpixel=(DWORD*)dstrow;
374 for (x=0; x<prc->Width; x++)
375 *dstpixel++ = colors[*srcbyte++];
376 srcrow += srcstride;
377 dstrow += cbStride;
381 HeapFree(GetProcessHeap(), 0, srcdata);
383 return res;
385 return S_OK;
386 case format_16bppGray:
387 if (prc)
389 HRESULT res;
390 UINT x, y;
391 BYTE *srcdata;
392 UINT srcstride, srcdatasize;
393 const BYTE *srcrow;
394 const BYTE *srcbyte;
395 BYTE *dstrow;
396 DWORD *dstpixel;
398 srcstride = prc->Width * 2;
399 srcdatasize = srcstride * prc->Height;
401 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
402 if (!srcdata) return E_OUTOFMEMORY;
404 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
406 if (SUCCEEDED(res))
408 srcrow = srcdata;
409 dstrow = pbBuffer;
410 for (y=0; y<prc->Height; y++) {
411 srcbyte=(const BYTE*)srcrow;
412 dstpixel=(DWORD*)dstrow;
413 for (x=0; x<prc->Width; x++)
415 *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
416 srcbyte+=2;
418 srcrow += srcstride;
419 dstrow += cbStride;
423 HeapFree(GetProcessHeap(), 0, srcdata);
425 return res;
427 return S_OK;
428 case format_16bppBGR555:
429 if (prc)
431 HRESULT res;
432 UINT x, y;
433 BYTE *srcdata;
434 UINT srcstride, srcdatasize;
435 const BYTE *srcrow;
436 const WORD *srcpixel;
437 BYTE *dstrow;
438 DWORD *dstpixel;
440 srcstride = 2 * prc->Width;
441 srcdatasize = srcstride * prc->Height;
443 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
444 if (!srcdata) return E_OUTOFMEMORY;
446 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
448 if (SUCCEEDED(res))
450 srcrow = srcdata;
451 dstrow = pbBuffer;
452 for (y=0; y<prc->Height; y++) {
453 srcpixel=(const WORD*)srcrow;
454 dstpixel=(DWORD*)dstrow;
455 for (x=0; x<prc->Width; x++) {
456 WORD srcval;
457 srcval=*srcpixel++;
458 *dstpixel++=0xff000000 | /* constant 255 alpha */
459 ((srcval << 9) & 0xf80000) | /* r */
460 ((srcval << 4) & 0x070000) | /* r - 3 bits */
461 ((srcval << 6) & 0x00f800) | /* g */
462 ((srcval << 1) & 0x000700) | /* g - 3 bits */
463 ((srcval << 3) & 0x0000f8) | /* b */
464 ((srcval >> 2) & 0x000007); /* b - 3 bits */
466 srcrow += srcstride;
467 dstrow += cbStride;
471 HeapFree(GetProcessHeap(), 0, srcdata);
473 return res;
475 return S_OK;
476 case format_16bppBGR565:
477 if (prc)
479 HRESULT res;
480 UINT x, y;
481 BYTE *srcdata;
482 UINT srcstride, srcdatasize;
483 const BYTE *srcrow;
484 const WORD *srcpixel;
485 BYTE *dstrow;
486 DWORD *dstpixel;
488 srcstride = 2 * prc->Width;
489 srcdatasize = srcstride * prc->Height;
491 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
492 if (!srcdata) return E_OUTOFMEMORY;
494 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
496 if (SUCCEEDED(res))
498 srcrow = srcdata;
499 dstrow = pbBuffer;
500 for (y=0; y<prc->Height; y++) {
501 srcpixel=(const WORD*)srcrow;
502 dstpixel=(DWORD*)dstrow;
503 for (x=0; x<prc->Width; x++) {
504 WORD srcval;
505 srcval=*srcpixel++;
506 *dstpixel++=0xff000000 | /* constant 255 alpha */
507 ((srcval << 8) & 0xf80000) | /* r */
508 ((srcval << 3) & 0x070000) | /* r - 3 bits */
509 ((srcval << 5) & 0x00fc00) | /* g */
510 ((srcval >> 1) & 0x000300) | /* g - 2 bits */
511 ((srcval << 3) & 0x0000f8) | /* b */
512 ((srcval >> 2) & 0x000007); /* b - 3 bits */
514 srcrow += srcstride;
515 dstrow += cbStride;
519 HeapFree(GetProcessHeap(), 0, srcdata);
521 return res;
523 return S_OK;
524 case format_24bppBGR:
525 if (prc)
527 HRESULT res;
528 UINT x, y;
529 BYTE *srcdata;
530 UINT srcstride, srcdatasize;
531 const BYTE *srcrow;
532 const BYTE *srcpixel;
533 BYTE *dstrow;
534 BYTE *dstpixel;
536 srcstride = 3 * prc->Width;
537 srcdatasize = srcstride * prc->Height;
539 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
540 if (!srcdata) return E_OUTOFMEMORY;
542 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
544 if (SUCCEEDED(res))
546 srcrow = srcdata;
547 dstrow = pbBuffer;
548 for (y=0; y<prc->Height; y++) {
549 srcpixel=srcrow;
550 dstpixel=dstrow;
551 for (x=0; x<prc->Width; x++) {
552 *dstpixel++=*srcpixel++; /* blue */
553 *dstpixel++=*srcpixel++; /* green */
554 *dstpixel++=*srcpixel++; /* red */
555 *dstpixel++=255; /* alpha */
557 srcrow += srcstride;
558 dstrow += cbStride;
562 HeapFree(GetProcessHeap(), 0, srcdata);
564 return res;
566 return S_OK;
567 case format_32bppBGR:
568 if (prc)
570 HRESULT res;
571 UINT x, y;
573 res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
574 if (FAILED(res)) return res;
576 /* set all alpha values to 255 */
577 for (y=0; y<prc->Height; y++)
578 for (x=0; x<prc->Width; x++)
579 pbBuffer[cbStride*y+4*x+3] = 0xff;
581 return S_OK;
582 case format_32bppBGRA:
583 if (prc)
584 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
585 return S_OK;
586 case format_48bppRGB:
587 if (prc)
589 HRESULT res;
590 UINT x, y;
591 BYTE *srcdata;
592 UINT srcstride, srcdatasize;
593 const BYTE *srcrow;
594 const BYTE *srcpixel;
595 BYTE *dstrow;
596 DWORD *dstpixel;
598 srcstride = 6 * prc->Width;
599 srcdatasize = srcstride * prc->Height;
601 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
602 if (!srcdata) return E_OUTOFMEMORY;
604 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
606 if (SUCCEEDED(res))
608 srcrow = srcdata;
609 dstrow = pbBuffer;
610 for (y=0; y<prc->Height; y++) {
611 srcpixel=srcrow;
612 dstpixel=(DWORD*)dstrow;
613 for (x=0; x<prc->Width; x++) {
614 BYTE red, green, blue;
615 red = *srcpixel++; srcpixel++;
616 green = *srcpixel++; srcpixel++;
617 blue = *srcpixel++; srcpixel++;
618 *dstpixel++=0xff000000|red<<16|green<<8|blue;
620 srcrow += srcstride;
621 dstrow += cbStride;
625 HeapFree(GetProcessHeap(), 0, srcdata);
627 return res;
629 return S_OK;
630 case format_64bppRGBA:
631 if (prc)
633 HRESULT res;
634 UINT x, y;
635 BYTE *srcdata;
636 UINT srcstride, srcdatasize;
637 const BYTE *srcrow;
638 const BYTE *srcpixel;
639 BYTE *dstrow;
640 DWORD *dstpixel;
642 srcstride = 8 * prc->Width;
643 srcdatasize = srcstride * prc->Height;
645 srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
646 if (!srcdata) return E_OUTOFMEMORY;
648 res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
650 if (SUCCEEDED(res))
652 srcrow = srcdata;
653 dstrow = pbBuffer;
654 for (y=0; y<prc->Height; y++) {
655 srcpixel=srcrow;
656 dstpixel=(DWORD*)dstrow;
657 for (x=0; x<prc->Width; x++) {
658 BYTE red, green, blue, alpha;
659 red = *srcpixel++; srcpixel++;
660 green = *srcpixel++; srcpixel++;
661 blue = *srcpixel++; srcpixel++;
662 alpha = *srcpixel++; srcpixel++;
663 *dstpixel++=alpha<<24|red<<16|green<<8|blue;
665 srcrow += srcstride;
666 dstrow += cbStride;
670 HeapFree(GetProcessHeap(), 0, srcdata);
672 return res;
674 return S_OK;
675 default:
676 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
680 static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc,
681 UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
683 switch (source_format)
685 case format_32bppBGR:
686 case format_32bppBGRA:
687 if (prc)
688 return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
689 return S_OK;
690 default:
691 return copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
695 static const struct pixelformatinfo supported_formats[] = {
696 {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
697 {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
698 {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
699 {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL},
700 {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
701 {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
702 {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
703 {format_8bppGray, &GUID_WICPixelFormat8bppGray, NULL},
704 {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL},
705 {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
706 {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
707 {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, NULL},
708 {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR},
709 {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA},
710 {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL},
711 {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL},
715 static const struct pixelformatinfo *get_formatinfo(const WICPixelFormatGUID *format)
717 UINT i;
719 for (i=0; supported_formats[i].guid; i++)
720 if (IsEqualGUID(supported_formats[i].guid, format)) return &supported_formats[i];
722 return NULL;
725 static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid,
726 void **ppv)
728 FormatConverter *This = (FormatConverter*)iface;
729 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
731 if (!ppv) return E_INVALIDARG;
733 if (IsEqualIID(&IID_IUnknown, iid) ||
734 IsEqualIID(&IID_IWICBitmapSource, iid) ||
735 IsEqualIID(&IID_IWICFormatConverter, iid))
737 *ppv = This;
739 else
741 *ppv = NULL;
742 return E_NOINTERFACE;
745 IUnknown_AddRef((IUnknown*)*ppv);
746 return S_OK;
749 static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface)
751 FormatConverter *This = (FormatConverter*)iface;
752 ULONG ref = InterlockedIncrement(&This->ref);
754 TRACE("(%p) refcount=%u\n", iface, ref);
756 return ref;
759 static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
761 FormatConverter *This = (FormatConverter*)iface;
762 ULONG ref = InterlockedDecrement(&This->ref);
764 TRACE("(%p) refcount=%u\n", iface, ref);
766 if (ref == 0)
768 if (This->source) IWICBitmapSource_Release(This->source);
769 HeapFree(GetProcessHeap(), 0, This);
772 return ref;
775 static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface,
776 UINT *puiWidth, UINT *puiHeight)
778 FormatConverter *This = (FormatConverter*)iface;
780 TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
782 if (This->source)
783 return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight);
784 else
785 return WINCODEC_ERR_NOTINITIALIZED;
788 static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface,
789 WICPixelFormatGUID *pPixelFormat)
791 FormatConverter *This = (FormatConverter*)iface;
793 TRACE("(%p,%p): stub\n", iface, pPixelFormat);
795 if (This->source)
796 memcpy(pPixelFormat, This->dst_format->guid, sizeof(GUID));
797 else
798 return WINCODEC_ERR_NOTINITIALIZED;
800 return S_OK;
803 static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
804 double *pDpiX, double *pDpiY)
806 FormatConverter *This = (FormatConverter*)iface;
808 TRACE("(%p,%p,%p): stub\n", iface, pDpiX, pDpiY);
810 if (This->source)
811 return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY);
812 else
813 return WINCODEC_ERR_NOTINITIALIZED;
816 static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
817 IWICPalette *pIPalette)
819 FIXME("(%p,%p): stub\n", iface, pIPalette);
820 return E_NOTIMPL;
823 static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
824 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
826 FormatConverter *This = (FormatConverter*)iface;
827 TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
829 if (This->source)
830 return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize,
831 pbBuffer, This->src_format->format);
832 else
833 return WINCODEC_ERR_NOTINITIALIZED;
836 static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
837 IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
838 IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate)
840 FormatConverter *This = (FormatConverter*)iface;
841 const struct pixelformatinfo *srcinfo, *dstinfo;
842 static INT fixme=0;
843 GUID srcFormat;
844 HRESULT res;
846 TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat),
847 dither, pIPalette, alphaThresholdPercent, paletteTranslate);
849 if (pIPalette && !fixme++) FIXME("ignoring palette\n");
851 if (This->source) return WINCODEC_ERR_WRONGSTATE;
853 res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat);
854 if (FAILED(res)) return res;
856 srcinfo = get_formatinfo(&srcFormat);
857 if (!srcinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
859 dstinfo = get_formatinfo(dstFormat);
860 if (!dstinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
862 if (dstinfo->copy_function)
864 IWICBitmapSource_AddRef(pISource);
865 This->source = pISource;
866 This->src_format = srcinfo;
867 This->dst_format = dstinfo;
868 This->dither = dither;
869 This->alpha_threshold = alphaThresholdPercent;
870 This->palette_type = paletteTranslate;
872 else
873 return WINCODEC_ERR_UNSUPPORTEDOPERATION;
875 return S_OK;
878 static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface,
879 REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat,
880 BOOL *pfCanConvert)
882 FormatConverter *This = (FormatConverter*)iface;
883 const struct pixelformatinfo *srcinfo, *dstinfo;
885 TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat),
886 debugstr_guid(dstPixelFormat), pfCanConvert);
888 srcinfo = get_formatinfo(srcPixelFormat);
889 if (!srcinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
891 dstinfo = get_formatinfo(dstPixelFormat);
892 if (!dstinfo) return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
894 if (dstinfo->copy_function &&
895 SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format)))
896 *pfCanConvert = TRUE;
897 else
898 *pfCanConvert = FALSE;
900 return S_OK;
903 static const IWICFormatConverterVtbl FormatConverter_Vtbl = {
904 FormatConverter_QueryInterface,
905 FormatConverter_AddRef,
906 FormatConverter_Release,
907 FormatConverter_GetSize,
908 FormatConverter_GetPixelFormat,
909 FormatConverter_GetResolution,
910 FormatConverter_CopyPalette,
911 FormatConverter_CopyPixels,
912 FormatConverter_Initialize,
913 FormatConverter_CanConvert
916 HRESULT FormatConverter_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
918 FormatConverter *This;
919 HRESULT ret;
921 TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
923 *ppv = NULL;
925 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
927 This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
928 if (!This) return E_OUTOFMEMORY;
930 This->lpVtbl = &FormatConverter_Vtbl;
931 This->ref = 1;
932 This->source = NULL;
934 ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
935 IUnknown_Release((IUnknown*)This);
937 return ret;