xref: /reactos/dll/win32/windowscodecs/converter.c (revision cfaeaaa9)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2009 Vincent Povirk
3c2c66affSColin Finck  * Copyright 2016 Dmitry Timoshkov
4c2c66affSColin Finck  *
5c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck  * License as published by the Free Software Foundation; either
8c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck  *
10c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13c2c66affSColin Finck  * Lesser General Public License for more details.
14c2c66affSColin Finck  *
15c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck  */
19c2c66affSColin Finck 
20ae80686dSAmine Khaldi #include "config.h"
21ae80686dSAmine Khaldi 
22ae80686dSAmine Khaldi #include <stdarg.h>
23ae80686dSAmine Khaldi #include <math.h>
24ae80686dSAmine Khaldi 
25ae80686dSAmine Khaldi #define COBJMACROS
26ae80686dSAmine Khaldi 
27ae80686dSAmine Khaldi #include "windef.h"
28ae80686dSAmine Khaldi #include "winbase.h"
29ae80686dSAmine Khaldi #include "objbase.h"
30ae80686dSAmine Khaldi 
31c2c66affSColin Finck #include "wincodecs_private.h"
32c2c66affSColin Finck 
33324214f9SAmine Khaldi #include "wine/heap.h"
34ae80686dSAmine Khaldi #include "wine/debug.h"
35ae80686dSAmine Khaldi 
36ae80686dSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
37c2c66affSColin Finck 
38c2c66affSColin Finck struct FormatConverter;
39c2c66affSColin Finck 
40c2c66affSColin Finck enum pixelformat {
41c2c66affSColin Finck     format_1bppIndexed,
42c2c66affSColin Finck     format_2bppIndexed,
43c2c66affSColin Finck     format_4bppIndexed,
44c2c66affSColin Finck     format_8bppIndexed,
45c2c66affSColin Finck     format_BlackWhite,
46c2c66affSColin Finck     format_2bppGray,
47c2c66affSColin Finck     format_4bppGray,
48c2c66affSColin Finck     format_8bppGray,
49c2c66affSColin Finck     format_16bppGray,
50c2c66affSColin Finck     format_16bppBGR555,
51c2c66affSColin Finck     format_16bppBGR565,
52c2c66affSColin Finck     format_16bppBGRA5551,
53c2c66affSColin Finck     format_24bppBGR,
54c2c66affSColin Finck     format_24bppRGB,
55c2c66affSColin Finck     format_32bppGrayFloat,
56c2c66affSColin Finck     format_32bppBGR,
57ae80686dSAmine Khaldi     format_32bppRGB,
58c2c66affSColin Finck     format_32bppBGRA,
59ae80686dSAmine Khaldi     format_32bppRGBA,
60c2c66affSColin Finck     format_32bppPBGRA,
61ae80686dSAmine Khaldi     format_32bppPRGBA,
62c2c66affSColin Finck     format_48bppRGB,
63c2c66affSColin Finck     format_64bppRGBA,
64c2c66affSColin Finck     format_32bppCMYK,
65c2c66affSColin Finck };
66c2c66affSColin Finck 
67c2c66affSColin Finck typedef HRESULT (*copyfunc)(struct FormatConverter *This, const WICRect *prc,
68c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format);
69c2c66affSColin Finck 
70c2c66affSColin Finck struct pixelformatinfo {
71c2c66affSColin Finck     enum pixelformat format;
72c2c66affSColin Finck     const WICPixelFormatGUID *guid;
73c2c66affSColin Finck     copyfunc copy_function;
74c2c66affSColin Finck };
75c2c66affSColin Finck 
76c2c66affSColin Finck typedef struct FormatConverter {
77c2c66affSColin Finck     IWICFormatConverter IWICFormatConverter_iface;
78c2c66affSColin Finck     LONG ref;
79c2c66affSColin Finck     IWICBitmapSource *source;
80c2c66affSColin Finck     const struct pixelformatinfo *dst_format, *src_format;
81c2c66affSColin Finck     WICBitmapDitherType dither;
82c2c66affSColin Finck     double alpha_threshold;
83ae80686dSAmine Khaldi     IWICPalette *palette;
84c2c66affSColin Finck     CRITICAL_SECTION lock; /* must be held when initialized */
85c2c66affSColin Finck } FormatConverter;
86c2c66affSColin Finck 
87c2c66affSColin Finck /* https://www.w3.org/Graphics/Color/srgb */
to_sRGB_component(float f)88c2c66affSColin Finck static inline float to_sRGB_component(float f)
89c2c66affSColin Finck {
90c2c66affSColin Finck     if (f <= 0.0031308f) return 12.92f * f;
91c2c66affSColin Finck     return 1.055f * powf(f, 1.0f/2.4f) - 0.055f;
92c2c66affSColin Finck }
93c2c66affSColin Finck 
94c2c66affSColin Finck #if 0 /* FIXME: enable once needed */
95f6a1733dSAmine Khaldi static inline float from_sRGB_component(float f)
96f6a1733dSAmine Khaldi {
97f6a1733dSAmine Khaldi     if (f <= 0.04045f) return f / 12.92f;
98f6a1733dSAmine Khaldi     return powf((f + 0.055f) / 1.055f, 2.4f);
99f6a1733dSAmine Khaldi }
100f6a1733dSAmine Khaldi 
101c2c66affSColin Finck static void from_sRGB(BYTE *bgr)
102c2c66affSColin Finck {
103c2c66affSColin Finck     float r, g, b;
104c2c66affSColin Finck 
105c2c66affSColin Finck     r = bgr[2] / 255.0f;
106c2c66affSColin Finck     g = bgr[1] / 255.0f;
107c2c66affSColin Finck     b = bgr[0] / 255.0f;
108c2c66affSColin Finck 
109c2c66affSColin Finck     r = from_sRGB_component(r);
110c2c66affSColin Finck     g = from_sRGB_component(g);
111c2c66affSColin Finck     b = from_sRGB_component(b);
112c2c66affSColin Finck 
113c2c66affSColin Finck     bgr[2] = (BYTE)(r * 255.0f);
114c2c66affSColin Finck     bgr[1] = (BYTE)(g * 255.0f);
115c2c66affSColin Finck     bgr[0] = (BYTE)(b * 255.0f);
116c2c66affSColin Finck }
117c2c66affSColin Finck 
118c2c66affSColin Finck static void to_sRGB(BYTE *bgr)
119c2c66affSColin Finck {
120c2c66affSColin Finck     float r, g, b;
121c2c66affSColin Finck 
122c2c66affSColin Finck     r = bgr[2] / 255.0f;
123c2c66affSColin Finck     g = bgr[1] / 255.0f;
124c2c66affSColin Finck     b = bgr[0] / 255.0f;
125c2c66affSColin Finck 
126c2c66affSColin Finck     r = to_sRGB_component(r);
127c2c66affSColin Finck     g = to_sRGB_component(g);
128c2c66affSColin Finck     b = to_sRGB_component(b);
129c2c66affSColin Finck 
130c2c66affSColin Finck     bgr[2] = (BYTE)(r * 255.0f);
131c2c66affSColin Finck     bgr[1] = (BYTE)(g * 255.0f);
132c2c66affSColin Finck     bgr[0] = (BYTE)(b * 255.0f);
133c2c66affSColin Finck }
134c2c66affSColin Finck #endif
135c2c66affSColin Finck 
impl_from_IWICFormatConverter(IWICFormatConverter * iface)136c2c66affSColin Finck static inline FormatConverter *impl_from_IWICFormatConverter(IWICFormatConverter *iface)
137c2c66affSColin Finck {
138c2c66affSColin Finck     return CONTAINING_RECORD(iface, FormatConverter, IWICFormatConverter_iface);
139c2c66affSColin Finck }
140c2c66affSColin Finck 
copypixels_to_32bppBGRA(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)141c2c66affSColin Finck static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRect *prc,
142c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
143c2c66affSColin Finck {
144c2c66affSColin Finck     switch (source_format)
145c2c66affSColin Finck     {
146c2c66affSColin Finck     case format_1bppIndexed:
147c2c66affSColin Finck     case format_BlackWhite:
148c2c66affSColin Finck         if (prc)
149c2c66affSColin Finck         {
150c2c66affSColin Finck             HRESULT res;
151c2c66affSColin Finck             INT x, y;
152c2c66affSColin Finck             BYTE *srcdata;
153c2c66affSColin Finck             UINT srcstride, srcdatasize;
154c2c66affSColin Finck             const BYTE *srcrow;
155c2c66affSColin Finck             const BYTE *srcbyte;
156c2c66affSColin Finck             BYTE *dstrow;
157c2c66affSColin Finck             DWORD *dstpixel;
158c2c66affSColin Finck             WICColor colors[2];
159c2c66affSColin Finck             IWICPalette *palette;
160c2c66affSColin Finck             UINT actualcolors;
161c2c66affSColin Finck 
162c2c66affSColin Finck             res = PaletteImpl_Create(&palette);
163c2c66affSColin Finck             if (FAILED(res)) return res;
164c2c66affSColin Finck 
165c2c66affSColin Finck             if (source_format == format_1bppIndexed)
166c2c66affSColin Finck                 res = IWICBitmapSource_CopyPalette(This->source, palette);
167c2c66affSColin Finck             else
168c2c66affSColin Finck                 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedBW, FALSE);
169c2c66affSColin Finck 
170c2c66affSColin Finck             if (SUCCEEDED(res))
171c2c66affSColin Finck                 res = IWICPalette_GetColors(palette, 2, colors, &actualcolors);
172c2c66affSColin Finck 
173c2c66affSColin Finck             IWICPalette_Release(palette);
174c2c66affSColin Finck             if (FAILED(res)) return res;
175c2c66affSColin Finck 
176c2c66affSColin Finck             srcstride = (prc->Width+7)/8;
177c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
178c2c66affSColin Finck 
179c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
180c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
181c2c66affSColin Finck 
182c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
183c2c66affSColin Finck 
184c2c66affSColin Finck             if (SUCCEEDED(res))
185c2c66affSColin Finck             {
186c2c66affSColin Finck                 srcrow = srcdata;
187c2c66affSColin Finck                 dstrow = pbBuffer;
188c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
189c2c66affSColin Finck                     srcbyte = srcrow;
190c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
191c2c66affSColin Finck                     for (x=0; x<prc->Width; x+=8) {
192c2c66affSColin Finck                         BYTE srcval;
193c2c66affSColin Finck                         srcval=*srcbyte++;
194c2c66affSColin Finck                         *dstpixel++ = colors[srcval>>7&1];
195c2c66affSColin Finck                         if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>6&1];
196c2c66affSColin Finck                         if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>5&1];
197c2c66affSColin Finck                         if (x+3 < prc->Width) *dstpixel++ = colors[srcval>>4&1];
198c2c66affSColin Finck                         if (x+4 < prc->Width) *dstpixel++ = colors[srcval>>3&1];
199c2c66affSColin Finck                         if (x+5 < prc->Width) *dstpixel++ = colors[srcval>>2&1];
200c2c66affSColin Finck                         if (x+6 < prc->Width) *dstpixel++ = colors[srcval>>1&1];
201c2c66affSColin Finck                         if (x+7 < prc->Width) *dstpixel++ = colors[srcval&1];
202c2c66affSColin Finck                     }
203c2c66affSColin Finck                     srcrow += srcstride;
204c2c66affSColin Finck                     dstrow += cbStride;
205c2c66affSColin Finck                 }
206c2c66affSColin Finck             }
207c2c66affSColin Finck 
208c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
209c2c66affSColin Finck 
210c2c66affSColin Finck             return res;
211c2c66affSColin Finck         }
212c2c66affSColin Finck         return S_OK;
213c2c66affSColin Finck     case format_2bppIndexed:
214c2c66affSColin Finck     case format_2bppGray:
215c2c66affSColin Finck         if (prc)
216c2c66affSColin Finck         {
217c2c66affSColin Finck             HRESULT res;
218c2c66affSColin Finck             INT x, y;
219c2c66affSColin Finck             BYTE *srcdata;
220c2c66affSColin Finck             UINT srcstride, srcdatasize;
221c2c66affSColin Finck             const BYTE *srcrow;
222c2c66affSColin Finck             const BYTE *srcbyte;
223c2c66affSColin Finck             BYTE *dstrow;
224c2c66affSColin Finck             DWORD *dstpixel;
225c2c66affSColin Finck             WICColor colors[4];
226c2c66affSColin Finck             IWICPalette *palette;
227c2c66affSColin Finck             UINT actualcolors;
228c2c66affSColin Finck 
229c2c66affSColin Finck             res = PaletteImpl_Create(&palette);
230c2c66affSColin Finck             if (FAILED(res)) return res;
231c2c66affSColin Finck 
232c2c66affSColin Finck             if (source_format == format_2bppIndexed)
233c2c66affSColin Finck                 res = IWICBitmapSource_CopyPalette(This->source, palette);
234c2c66affSColin Finck             else
235c2c66affSColin Finck                 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray4, FALSE);
236c2c66affSColin Finck 
237c2c66affSColin Finck             if (SUCCEEDED(res))
238c2c66affSColin Finck                 res = IWICPalette_GetColors(palette, 4, colors, &actualcolors);
239c2c66affSColin Finck 
240c2c66affSColin Finck             IWICPalette_Release(palette);
241c2c66affSColin Finck             if (FAILED(res)) return res;
242c2c66affSColin Finck 
243c2c66affSColin Finck             srcstride = (prc->Width+3)/4;
244c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
245c2c66affSColin Finck 
246c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
247c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
248c2c66affSColin Finck 
249c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
250c2c66affSColin Finck 
251c2c66affSColin Finck             if (SUCCEEDED(res))
252c2c66affSColin Finck             {
253c2c66affSColin Finck                 srcrow = srcdata;
254c2c66affSColin Finck                 dstrow = pbBuffer;
255c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
256c2c66affSColin Finck                     srcbyte = srcrow;
257c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
258c2c66affSColin Finck                     for (x=0; x<prc->Width; x+=4) {
259c2c66affSColin Finck                         BYTE srcval;
260c2c66affSColin Finck                         srcval=*srcbyte++;
261c2c66affSColin Finck                         *dstpixel++ = colors[srcval>>6];
262c2c66affSColin Finck                         if (x+1 < prc->Width) *dstpixel++ = colors[srcval>>4&0x3];
263c2c66affSColin Finck                         if (x+2 < prc->Width) *dstpixel++ = colors[srcval>>2&0x3];
264c2c66affSColin Finck                         if (x+3 < prc->Width) *dstpixel++ = colors[srcval&0x3];
265c2c66affSColin Finck                     }
266c2c66affSColin Finck                     srcrow += srcstride;
267c2c66affSColin Finck                     dstrow += cbStride;
268c2c66affSColin Finck                 }
269c2c66affSColin Finck             }
270c2c66affSColin Finck 
271c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
272c2c66affSColin Finck 
273c2c66affSColin Finck             return res;
274c2c66affSColin Finck         }
275c2c66affSColin Finck         return S_OK;
276c2c66affSColin Finck     case format_4bppIndexed:
277c2c66affSColin Finck     case format_4bppGray:
278c2c66affSColin Finck         if (prc)
279c2c66affSColin Finck         {
280c2c66affSColin Finck             HRESULT res;
281c2c66affSColin Finck             INT x, y;
282c2c66affSColin Finck             BYTE *srcdata;
283c2c66affSColin Finck             UINT srcstride, srcdatasize;
284c2c66affSColin Finck             const BYTE *srcrow;
285c2c66affSColin Finck             const BYTE *srcbyte;
286c2c66affSColin Finck             BYTE *dstrow;
287c2c66affSColin Finck             DWORD *dstpixel;
288c2c66affSColin Finck             WICColor colors[16];
289c2c66affSColin Finck             IWICPalette *palette;
290c2c66affSColin Finck             UINT actualcolors;
291c2c66affSColin Finck 
292c2c66affSColin Finck             res = PaletteImpl_Create(&palette);
293c2c66affSColin Finck             if (FAILED(res)) return res;
294c2c66affSColin Finck 
295c2c66affSColin Finck             if (source_format == format_4bppIndexed)
296c2c66affSColin Finck                 res = IWICBitmapSource_CopyPalette(This->source, palette);
297c2c66affSColin Finck             else
298c2c66affSColin Finck                 res = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedGray16, FALSE);
299c2c66affSColin Finck 
300c2c66affSColin Finck             if (SUCCEEDED(res))
301c2c66affSColin Finck                 res = IWICPalette_GetColors(palette, 16, colors, &actualcolors);
302c2c66affSColin Finck 
303c2c66affSColin Finck             IWICPalette_Release(palette);
304c2c66affSColin Finck             if (FAILED(res)) return res;
305c2c66affSColin Finck 
306c2c66affSColin Finck             srcstride = (prc->Width+1)/2;
307c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
308c2c66affSColin Finck 
309c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
310c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
311c2c66affSColin Finck 
312c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
313c2c66affSColin Finck 
314c2c66affSColin Finck             if (SUCCEEDED(res))
315c2c66affSColin Finck             {
316c2c66affSColin Finck                 srcrow = srcdata;
317c2c66affSColin Finck                 dstrow = pbBuffer;
318c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
319c2c66affSColin Finck                     srcbyte = srcrow;
320c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
321c2c66affSColin Finck                     for (x=0; x<prc->Width; x+=2) {
322c2c66affSColin Finck                         BYTE srcval;
323c2c66affSColin Finck                         srcval=*srcbyte++;
324c2c66affSColin Finck                         *dstpixel++ = colors[srcval>>4];
325c2c66affSColin Finck                         if (x+1 < prc->Width) *dstpixel++ = colors[srcval&0xf];
326c2c66affSColin Finck                     }
327c2c66affSColin Finck                     srcrow += srcstride;
328c2c66affSColin Finck                     dstrow += cbStride;
329c2c66affSColin Finck                 }
330c2c66affSColin Finck             }
331c2c66affSColin Finck 
332c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
333c2c66affSColin Finck 
334c2c66affSColin Finck             return res;
335c2c66affSColin Finck         }
336c2c66affSColin Finck         return S_OK;
337c2c66affSColin Finck     case format_8bppGray:
338c2c66affSColin Finck         if (prc)
339c2c66affSColin Finck         {
340c2c66affSColin Finck             HRESULT res;
341c2c66affSColin Finck             INT x, y;
342c2c66affSColin Finck             BYTE *srcdata;
343c2c66affSColin Finck             UINT srcstride, srcdatasize;
344c2c66affSColin Finck             const BYTE *srcrow;
345c2c66affSColin Finck             const BYTE *srcbyte;
346c2c66affSColin Finck             BYTE *dstrow;
347c2c66affSColin Finck             DWORD *dstpixel;
348c2c66affSColin Finck 
349c2c66affSColin Finck             srcstride = prc->Width;
350c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
351c2c66affSColin Finck 
352c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
353c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
354c2c66affSColin Finck 
355c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
356c2c66affSColin Finck 
357c2c66affSColin Finck             if (SUCCEEDED(res))
358c2c66affSColin Finck             {
359c2c66affSColin Finck                 srcrow = srcdata;
360c2c66affSColin Finck                 dstrow = pbBuffer;
361c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
362c2c66affSColin Finck                     srcbyte = srcrow;
363c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
364c2c66affSColin Finck                     for (x=0; x<prc->Width; x++)
365c2c66affSColin Finck                     {
366c2c66affSColin Finck                         *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
367c2c66affSColin Finck                         srcbyte++;
368c2c66affSColin Finck                     }
369c2c66affSColin Finck                     srcrow += srcstride;
370c2c66affSColin Finck                     dstrow += cbStride;
371c2c66affSColin Finck                 }
372c2c66affSColin Finck             }
373c2c66affSColin Finck 
374c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
375c2c66affSColin Finck 
376c2c66affSColin Finck             return res;
377c2c66affSColin Finck         }
378c2c66affSColin Finck         return S_OK;
379c2c66affSColin Finck     case format_8bppIndexed:
380c2c66affSColin Finck         if (prc)
381c2c66affSColin Finck         {
382c2c66affSColin Finck             HRESULT res;
383c2c66affSColin Finck             INT x, y;
384c2c66affSColin Finck             BYTE *srcdata;
385c2c66affSColin Finck             UINT srcstride, srcdatasize;
386c2c66affSColin Finck             const BYTE *srcrow;
387c2c66affSColin Finck             const BYTE *srcbyte;
388c2c66affSColin Finck             BYTE *dstrow;
389c2c66affSColin Finck             DWORD *dstpixel;
390c2c66affSColin Finck             WICColor colors[256];
391c2c66affSColin Finck             IWICPalette *palette;
392c2c66affSColin Finck             UINT actualcolors;
393c2c66affSColin Finck 
394c2c66affSColin Finck             res = PaletteImpl_Create(&palette);
395c2c66affSColin Finck             if (FAILED(res)) return res;
396c2c66affSColin Finck 
397c2c66affSColin Finck             res = IWICBitmapSource_CopyPalette(This->source, palette);
398c2c66affSColin Finck             if (SUCCEEDED(res))
399c2c66affSColin Finck                 res = IWICPalette_GetColors(palette, 256, colors, &actualcolors);
400c2c66affSColin Finck 
401c2c66affSColin Finck             IWICPalette_Release(palette);
402c2c66affSColin Finck 
403c2c66affSColin Finck             if (FAILED(res)) return res;
404c2c66affSColin Finck 
405c2c66affSColin Finck             srcstride = prc->Width;
406c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
407c2c66affSColin Finck 
408c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
409c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
410c2c66affSColin Finck 
411c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
412c2c66affSColin Finck 
413c2c66affSColin Finck             if (SUCCEEDED(res))
414c2c66affSColin Finck             {
415c2c66affSColin Finck                 srcrow = srcdata;
416c2c66affSColin Finck                 dstrow = pbBuffer;
417c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
418c2c66affSColin Finck                     srcbyte = srcrow;
419c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
420c2c66affSColin Finck                     for (x=0; x<prc->Width; x++)
421c2c66affSColin Finck                         *dstpixel++ = colors[*srcbyte++];
422c2c66affSColin Finck                     srcrow += srcstride;
423c2c66affSColin Finck                     dstrow += cbStride;
424c2c66affSColin Finck                 }
425c2c66affSColin Finck             }
426c2c66affSColin Finck 
427c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
428c2c66affSColin Finck 
429c2c66affSColin Finck             return res;
430c2c66affSColin Finck         }
431c2c66affSColin Finck         return S_OK;
432c2c66affSColin Finck     case format_16bppGray:
433c2c66affSColin Finck         if (prc)
434c2c66affSColin Finck         {
435c2c66affSColin Finck             HRESULT res;
436c2c66affSColin Finck             INT x, y;
437c2c66affSColin Finck             BYTE *srcdata;
438c2c66affSColin Finck             UINT srcstride, srcdatasize;
439c2c66affSColin Finck             const BYTE *srcrow;
440c2c66affSColin Finck             const BYTE *srcbyte;
441c2c66affSColin Finck             BYTE *dstrow;
442c2c66affSColin Finck             DWORD *dstpixel;
443c2c66affSColin Finck 
444c2c66affSColin Finck             srcstride = prc->Width * 2;
445c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
446c2c66affSColin Finck 
447c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
448c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
449c2c66affSColin Finck 
450c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
451c2c66affSColin Finck 
452c2c66affSColin Finck             if (SUCCEEDED(res))
453c2c66affSColin Finck             {
454c2c66affSColin Finck                 srcrow = srcdata;
455c2c66affSColin Finck                 dstrow = pbBuffer;
456c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
457c2c66affSColin Finck                     srcbyte = srcrow;
458c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
459c2c66affSColin Finck                     for (x=0; x<prc->Width; x++)
460c2c66affSColin Finck                     {
461f6a1733dSAmine Khaldi                         srcbyte++;
462c2c66affSColin Finck                         *dstpixel++ = 0xff000000|(*srcbyte<<16)|(*srcbyte<<8)|*srcbyte;
463f6a1733dSAmine Khaldi                         srcbyte++;
464c2c66affSColin Finck                     }
465c2c66affSColin Finck                     srcrow += srcstride;
466c2c66affSColin Finck                     dstrow += cbStride;
467c2c66affSColin Finck                 }
468c2c66affSColin Finck             }
469c2c66affSColin Finck 
470c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
471c2c66affSColin Finck 
472c2c66affSColin Finck             return res;
473c2c66affSColin Finck         }
474c2c66affSColin Finck         return S_OK;
475c2c66affSColin Finck     case format_16bppBGR555:
476c2c66affSColin Finck         if (prc)
477c2c66affSColin Finck         {
478c2c66affSColin Finck             HRESULT res;
479c2c66affSColin Finck             INT x, y;
480c2c66affSColin Finck             BYTE *srcdata;
481c2c66affSColin Finck             UINT srcstride, srcdatasize;
482c2c66affSColin Finck             const BYTE *srcrow;
483c2c66affSColin Finck             const WORD *srcpixel;
484c2c66affSColin Finck             BYTE *dstrow;
485c2c66affSColin Finck             DWORD *dstpixel;
486c2c66affSColin Finck 
487c2c66affSColin Finck             srcstride = 2 * prc->Width;
488c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
489c2c66affSColin Finck 
490c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
491c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
492c2c66affSColin Finck 
493c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
494c2c66affSColin Finck 
495c2c66affSColin Finck             if (SUCCEEDED(res))
496c2c66affSColin Finck             {
497c2c66affSColin Finck                 srcrow = srcdata;
498c2c66affSColin Finck                 dstrow = pbBuffer;
499c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
500c2c66affSColin Finck                     srcpixel=(const WORD*)srcrow;
501c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
502c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
503c2c66affSColin Finck                         WORD srcval;
504c2c66affSColin Finck                         srcval=*srcpixel++;
505c2c66affSColin Finck                         *dstpixel++=0xff000000 | /* constant 255 alpha */
506c2c66affSColin Finck                                     ((srcval << 9) & 0xf80000) | /* r */
507c2c66affSColin Finck                                     ((srcval << 4) & 0x070000) | /* r - 3 bits */
508c2c66affSColin Finck                                     ((srcval << 6) & 0x00f800) | /* g */
509c2c66affSColin Finck                                     ((srcval << 1) & 0x000700) | /* g - 3 bits */
510c2c66affSColin Finck                                     ((srcval << 3) & 0x0000f8) | /* b */
511c2c66affSColin Finck                                     ((srcval >> 2) & 0x000007);  /* b - 3 bits */
512c2c66affSColin Finck                     }
513c2c66affSColin Finck                     srcrow += srcstride;
514c2c66affSColin Finck                     dstrow += cbStride;
515c2c66affSColin Finck                 }
516c2c66affSColin Finck             }
517c2c66affSColin Finck 
518c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
519c2c66affSColin Finck 
520c2c66affSColin Finck             return res;
521c2c66affSColin Finck         }
522c2c66affSColin Finck         return S_OK;
523c2c66affSColin Finck     case format_16bppBGR565:
524c2c66affSColin Finck         if (prc)
525c2c66affSColin Finck         {
526c2c66affSColin Finck             HRESULT res;
527c2c66affSColin Finck             INT x, y;
528c2c66affSColin Finck             BYTE *srcdata;
529c2c66affSColin Finck             UINT srcstride, srcdatasize;
530c2c66affSColin Finck             const BYTE *srcrow;
531c2c66affSColin Finck             const WORD *srcpixel;
532c2c66affSColin Finck             BYTE *dstrow;
533c2c66affSColin Finck             DWORD *dstpixel;
534c2c66affSColin Finck 
535c2c66affSColin Finck             srcstride = 2 * prc->Width;
536c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
537c2c66affSColin Finck 
538c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
539c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
540c2c66affSColin Finck 
541c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
542c2c66affSColin Finck 
543c2c66affSColin Finck             if (SUCCEEDED(res))
544c2c66affSColin Finck             {
545c2c66affSColin Finck                 srcrow = srcdata;
546c2c66affSColin Finck                 dstrow = pbBuffer;
547c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
548c2c66affSColin Finck                     srcpixel=(const WORD*)srcrow;
549c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
550c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
551c2c66affSColin Finck                         WORD srcval;
552c2c66affSColin Finck                         srcval=*srcpixel++;
553c2c66affSColin Finck                         *dstpixel++=0xff000000 | /* constant 255 alpha */
554c2c66affSColin Finck                                     ((srcval << 8) & 0xf80000) | /* r */
555c2c66affSColin Finck                                     ((srcval << 3) & 0x070000) | /* r - 3 bits */
556c2c66affSColin Finck                                     ((srcval << 5) & 0x00fc00) | /* g */
557c2c66affSColin Finck                                     ((srcval >> 1) & 0x000300) | /* g - 2 bits */
558c2c66affSColin Finck                                     ((srcval << 3) & 0x0000f8) | /* b */
559c2c66affSColin Finck                                     ((srcval >> 2) & 0x000007);  /* b - 3 bits */
560c2c66affSColin Finck                     }
561c2c66affSColin Finck                     srcrow += srcstride;
562c2c66affSColin Finck                     dstrow += cbStride;
563c2c66affSColin Finck                 }
564c2c66affSColin Finck             }
565c2c66affSColin Finck 
566c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
567c2c66affSColin Finck 
568c2c66affSColin Finck             return res;
569c2c66affSColin Finck         }
570c2c66affSColin Finck         return S_OK;
571c2c66affSColin Finck     case format_16bppBGRA5551:
572c2c66affSColin Finck         if (prc)
573c2c66affSColin Finck         {
574c2c66affSColin Finck             HRESULT res;
575c2c66affSColin Finck             INT x, y;
576c2c66affSColin Finck             BYTE *srcdata;
577c2c66affSColin Finck             UINT srcstride, srcdatasize;
578c2c66affSColin Finck             const BYTE *srcrow;
579c2c66affSColin Finck             const WORD *srcpixel;
580c2c66affSColin Finck             BYTE *dstrow;
581c2c66affSColin Finck             DWORD *dstpixel;
582c2c66affSColin Finck 
583c2c66affSColin Finck             srcstride = 2 * prc->Width;
584c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
585c2c66affSColin Finck 
586c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
587c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
588c2c66affSColin Finck 
589c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
590c2c66affSColin Finck 
591c2c66affSColin Finck             if (SUCCEEDED(res))
592c2c66affSColin Finck             {
593c2c66affSColin Finck                 srcrow = srcdata;
594c2c66affSColin Finck                 dstrow = pbBuffer;
595c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
596c2c66affSColin Finck                     srcpixel=(const WORD*)srcrow;
597c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
598c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
599c2c66affSColin Finck                         WORD srcval;
600c2c66affSColin Finck                         srcval=*srcpixel++;
601c2c66affSColin Finck                         *dstpixel++=((srcval & 0x8000) ? 0xff000000 : 0) | /* alpha */
602c2c66affSColin Finck                                     ((srcval << 9) & 0xf80000) | /* r */
603c2c66affSColin Finck                                     ((srcval << 4) & 0x070000) | /* r - 3 bits */
604c2c66affSColin Finck                                     ((srcval << 6) & 0x00f800) | /* g */
605c2c66affSColin Finck                                     ((srcval << 1) & 0x000700) | /* g - 3 bits */
606c2c66affSColin Finck                                     ((srcval << 3) & 0x0000f8) | /* b */
607c2c66affSColin Finck                                     ((srcval >> 2) & 0x000007);  /* b - 3 bits */
608c2c66affSColin Finck                     }
609c2c66affSColin Finck                     srcrow += srcstride;
610c2c66affSColin Finck                     dstrow += cbStride;
611c2c66affSColin Finck                 }
612c2c66affSColin Finck             }
613c2c66affSColin Finck 
614c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
615c2c66affSColin Finck 
616c2c66affSColin Finck             return res;
617c2c66affSColin Finck         }
618c2c66affSColin Finck         return S_OK;
619c2c66affSColin Finck     case format_24bppBGR:
620c2c66affSColin Finck         if (prc)
621c2c66affSColin Finck         {
622c2c66affSColin Finck             HRESULT res;
623c2c66affSColin Finck             INT x, y;
624c2c66affSColin Finck             BYTE *srcdata;
625c2c66affSColin Finck             UINT srcstride, srcdatasize;
626c2c66affSColin Finck             const BYTE *srcrow;
627c2c66affSColin Finck             const BYTE *srcpixel;
628c2c66affSColin Finck             BYTE *dstrow;
629c2c66affSColin Finck             BYTE *dstpixel;
630c2c66affSColin Finck 
631c2c66affSColin Finck             srcstride = 3 * prc->Width;
632c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
633c2c66affSColin Finck 
634c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
635c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
636c2c66affSColin Finck 
637c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
638c2c66affSColin Finck 
639c2c66affSColin Finck             if (SUCCEEDED(res))
640c2c66affSColin Finck             {
641c2c66affSColin Finck                 srcrow = srcdata;
642c2c66affSColin Finck                 dstrow = pbBuffer;
643c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
644c2c66affSColin Finck                     srcpixel=srcrow;
645c2c66affSColin Finck                     dstpixel=dstrow;
646c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
647c2c66affSColin Finck                         *dstpixel++=*srcpixel++; /* blue */
648c2c66affSColin Finck                         *dstpixel++=*srcpixel++; /* green */
649c2c66affSColin Finck                         *dstpixel++=*srcpixel++; /* red */
650c2c66affSColin Finck                         *dstpixel++=255; /* alpha */
651c2c66affSColin Finck                     }
652c2c66affSColin Finck                     srcrow += srcstride;
653c2c66affSColin Finck                     dstrow += cbStride;
654c2c66affSColin Finck                 }
655c2c66affSColin Finck             }
656c2c66affSColin Finck 
657c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
658c2c66affSColin Finck 
659c2c66affSColin Finck             return res;
660c2c66affSColin Finck         }
661c2c66affSColin Finck         return S_OK;
662c2c66affSColin Finck     case format_24bppRGB:
663c2c66affSColin Finck         if (prc)
664c2c66affSColin Finck         {
665c2c66affSColin Finck             HRESULT res;
666c2c66affSColin Finck             INT x, y;
667c2c66affSColin Finck             BYTE *srcdata;
668c2c66affSColin Finck             UINT srcstride, srcdatasize;
669c2c66affSColin Finck             const BYTE *srcrow;
670c2c66affSColin Finck             const BYTE *srcpixel;
671c2c66affSColin Finck             BYTE *dstrow;
672c2c66affSColin Finck             BYTE *dstpixel;
673c2c66affSColin Finck             BYTE tmppixel[3];
674c2c66affSColin Finck 
675c2c66affSColin Finck             srcstride = 3 * prc->Width;
676c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
677c2c66affSColin Finck 
678c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
679c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
680c2c66affSColin Finck 
681c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
682c2c66affSColin Finck 
683c2c66affSColin Finck             if (SUCCEEDED(res))
684c2c66affSColin Finck             {
685c2c66affSColin Finck                 srcrow = srcdata;
686c2c66affSColin Finck                 dstrow = pbBuffer;
687c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
688c2c66affSColin Finck                     srcpixel=srcrow;
689c2c66affSColin Finck                     dstpixel=dstrow;
690c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
691c2c66affSColin Finck                         tmppixel[0]=*srcpixel++; /* red */
692c2c66affSColin Finck                         tmppixel[1]=*srcpixel++; /* green */
693c2c66affSColin Finck                         tmppixel[2]=*srcpixel++; /* blue */
694c2c66affSColin Finck 
695c2c66affSColin Finck                         *dstpixel++=tmppixel[2]; /* blue */
696c2c66affSColin Finck                         *dstpixel++=tmppixel[1]; /* green */
697c2c66affSColin Finck                         *dstpixel++=tmppixel[0]; /* red */
698c2c66affSColin Finck                         *dstpixel++=255; /* alpha */
699c2c66affSColin Finck                     }
700c2c66affSColin Finck                     srcrow += srcstride;
701c2c66affSColin Finck                     dstrow += cbStride;
702c2c66affSColin Finck                 }
703c2c66affSColin Finck             }
704c2c66affSColin Finck 
705c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
706c2c66affSColin Finck 
707c2c66affSColin Finck             return res;
708c2c66affSColin Finck         }
709c2c66affSColin Finck         return S_OK;
710c2c66affSColin Finck     case format_32bppBGR:
711c2c66affSColin Finck         if (prc)
712c2c66affSColin Finck         {
713c2c66affSColin Finck             HRESULT res;
714c2c66affSColin Finck             INT x, y;
715c2c66affSColin Finck 
716c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
717c2c66affSColin Finck             if (FAILED(res)) return res;
718c2c66affSColin Finck 
719c2c66affSColin Finck             /* set all alpha values to 255 */
720c2c66affSColin Finck             for (y=0; y<prc->Height; y++)
721c2c66affSColin Finck                 for (x=0; x<prc->Width; x++)
722c2c66affSColin Finck                     pbBuffer[cbStride*y+4*x+3] = 0xff;
723c2c66affSColin Finck         }
724c2c66affSColin Finck         return S_OK;
725*cfaeaaa9SThomas Csovcsity     case format_32bppRGBA:
726*cfaeaaa9SThomas Csovcsity         if (prc)
727*cfaeaaa9SThomas Csovcsity         {
728*cfaeaaa9SThomas Csovcsity             HRESULT res;
729*cfaeaaa9SThomas Csovcsity             res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
730*cfaeaaa9SThomas Csovcsity             if (FAILED(res)) return res;
731*cfaeaaa9SThomas Csovcsity             convert_rgba_to_bgra(4, pbBuffer, prc->Width, prc->Height, cbStride);
732*cfaeaaa9SThomas Csovcsity         }
733*cfaeaaa9SThomas Csovcsity         return S_OK;
734c2c66affSColin Finck     case format_32bppBGRA:
735c2c66affSColin Finck         if (prc)
736c2c66affSColin Finck             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
737c2c66affSColin Finck         return S_OK;
738c2c66affSColin Finck     case format_32bppPBGRA:
739c2c66affSColin Finck         if (prc)
740c2c66affSColin Finck         {
741c2c66affSColin Finck             HRESULT res;
742c2c66affSColin Finck             INT x, y;
743c2c66affSColin Finck 
744c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
745c2c66affSColin Finck             if (FAILED(res)) return res;
746c2c66affSColin Finck 
747c2c66affSColin Finck             for (y=0; y<prc->Height; y++)
748c2c66affSColin Finck                 for (x=0; x<prc->Width; x++)
749c2c66affSColin Finck                 {
750c2c66affSColin Finck                     BYTE alpha = pbBuffer[cbStride*y+4*x+3];
751c2c66affSColin Finck                     if (alpha != 0 && alpha != 255)
752c2c66affSColin Finck                     {
753c2c66affSColin Finck                         pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha;
754c2c66affSColin Finck                         pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha;
755c2c66affSColin Finck                         pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha;
756c2c66affSColin Finck                     }
757c2c66affSColin Finck                 }
758c2c66affSColin Finck         }
759c2c66affSColin Finck         return S_OK;
760c2c66affSColin Finck     case format_48bppRGB:
761c2c66affSColin Finck         if (prc)
762c2c66affSColin Finck         {
763c2c66affSColin Finck             HRESULT res;
764c2c66affSColin Finck             INT x, y;
765c2c66affSColin Finck             BYTE *srcdata;
766c2c66affSColin Finck             UINT srcstride, srcdatasize;
767c2c66affSColin Finck             const BYTE *srcrow;
768c2c66affSColin Finck             const BYTE *srcpixel;
769c2c66affSColin Finck             BYTE *dstrow;
770c2c66affSColin Finck             DWORD *dstpixel;
771c2c66affSColin Finck 
772c2c66affSColin Finck             srcstride = 6 * prc->Width;
773c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
774c2c66affSColin Finck 
775c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
776c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
777c2c66affSColin Finck 
778c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
779c2c66affSColin Finck 
780c2c66affSColin Finck             if (SUCCEEDED(res))
781c2c66affSColin Finck             {
782c2c66affSColin Finck                 srcrow = srcdata;
783c2c66affSColin Finck                 dstrow = pbBuffer;
784c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
785c2c66affSColin Finck                     srcpixel=srcrow;
786c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
787c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
788c2c66affSColin Finck                         BYTE red, green, blue;
789f6a1733dSAmine Khaldi                         srcpixel++; red = *srcpixel++;
790f6a1733dSAmine Khaldi                         srcpixel++; green = *srcpixel++;
791f6a1733dSAmine Khaldi                         srcpixel++; blue = *srcpixel++;
792c2c66affSColin Finck                         *dstpixel++=0xff000000|red<<16|green<<8|blue;
793c2c66affSColin Finck                     }
794c2c66affSColin Finck                     srcrow += srcstride;
795c2c66affSColin Finck                     dstrow += cbStride;
796c2c66affSColin Finck                 }
797c2c66affSColin Finck             }
798c2c66affSColin Finck 
799c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
800c2c66affSColin Finck 
801c2c66affSColin Finck             return res;
802c2c66affSColin Finck         }
803c2c66affSColin Finck         return S_OK;
804c2c66affSColin Finck     case format_64bppRGBA:
805c2c66affSColin Finck         if (prc)
806c2c66affSColin Finck         {
807c2c66affSColin Finck             HRESULT res;
808c2c66affSColin Finck             INT x, y;
809c2c66affSColin Finck             BYTE *srcdata;
810c2c66affSColin Finck             UINT srcstride, srcdatasize;
811c2c66affSColin Finck             const BYTE *srcrow;
812c2c66affSColin Finck             const BYTE *srcpixel;
813c2c66affSColin Finck             BYTE *dstrow;
814c2c66affSColin Finck             DWORD *dstpixel;
815c2c66affSColin Finck 
816c2c66affSColin Finck             srcstride = 8 * prc->Width;
817c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
818c2c66affSColin Finck 
819c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
820c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
821c2c66affSColin Finck 
822c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
823c2c66affSColin Finck 
824c2c66affSColin Finck             if (SUCCEEDED(res))
825c2c66affSColin Finck             {
826c2c66affSColin Finck                 srcrow = srcdata;
827c2c66affSColin Finck                 dstrow = pbBuffer;
828c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
829c2c66affSColin Finck                     srcpixel=srcrow;
830c2c66affSColin Finck                     dstpixel=(DWORD*)dstrow;
831c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
832c2c66affSColin Finck                         BYTE red, green, blue, alpha;
833f6a1733dSAmine Khaldi                         srcpixel++; red = *srcpixel++;
834f6a1733dSAmine Khaldi                         srcpixel++; green = *srcpixel++;
835f6a1733dSAmine Khaldi                         srcpixel++; blue = *srcpixel++;
836f6a1733dSAmine Khaldi                         srcpixel++; alpha = *srcpixel++;
837c2c66affSColin Finck                         *dstpixel++=alpha<<24|red<<16|green<<8|blue;
838c2c66affSColin Finck                     }
839c2c66affSColin Finck                     srcrow += srcstride;
840c2c66affSColin Finck                     dstrow += cbStride;
841c2c66affSColin Finck                 }
842c2c66affSColin Finck             }
843c2c66affSColin Finck 
844c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
845c2c66affSColin Finck 
846c2c66affSColin Finck             return res;
847c2c66affSColin Finck         }
848c2c66affSColin Finck         return S_OK;
849c2c66affSColin Finck     case format_32bppCMYK:
850c2c66affSColin Finck         if (prc)
851c2c66affSColin Finck         {
852c2c66affSColin Finck             HRESULT res;
853c2c66affSColin Finck             UINT x, y;
854c2c66affSColin Finck 
855c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
856c2c66affSColin Finck             if (FAILED(res)) return res;
857c2c66affSColin Finck 
858c2c66affSColin Finck             for (y=0; y<prc->Height; y++)
859c2c66affSColin Finck                 for (x=0; x<prc->Width; x++)
860c2c66affSColin Finck                 {
861c2c66affSColin Finck                     BYTE *pixel = pbBuffer+cbStride*y+4*x;
862c2c66affSColin Finck                     BYTE c=pixel[0], m=pixel[1], y=pixel[2], k=pixel[3];
863c2c66affSColin Finck                     pixel[0] = (255-y)*(255-k)/255; /* blue */
864c2c66affSColin Finck                     pixel[1] = (255-m)*(255-k)/255; /* green */
865c2c66affSColin Finck                     pixel[2] = (255-c)*(255-k)/255; /* red */
866c2c66affSColin Finck                     pixel[3] = 255; /* alpha */
867c2c66affSColin Finck                 }
868c2c66affSColin Finck         }
869c2c66affSColin Finck         return S_OK;
870c2c66affSColin Finck     default:
871*cfaeaaa9SThomas Csovcsity         FIXME("Unimplemented conversion path!\n");
872c2c66affSColin Finck         return WINCODEC_ERR_UNSUPPORTEDOPERATION;
873c2c66affSColin Finck     }
874c2c66affSColin Finck }
875c2c66affSColin Finck 
copypixels_to_32bppRGBA(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)876ae80686dSAmine Khaldi static HRESULT copypixels_to_32bppRGBA(struct FormatConverter *This, const WICRect *prc,
877ae80686dSAmine Khaldi     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
878ae80686dSAmine Khaldi {
879ae80686dSAmine Khaldi     HRESULT hr;
880ae80686dSAmine Khaldi 
881ae80686dSAmine Khaldi     switch (source_format)
882ae80686dSAmine Khaldi     {
883ae80686dSAmine Khaldi     case format_32bppRGB:
884f6a1733dSAmine Khaldi         if (prc)
885f6a1733dSAmine Khaldi         {
886f6a1733dSAmine Khaldi             INT x, y;
887f6a1733dSAmine Khaldi 
888f6a1733dSAmine Khaldi             hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
889f6a1733dSAmine Khaldi             if (FAILED(hr)) return hr;
890f6a1733dSAmine Khaldi 
891f6a1733dSAmine Khaldi             /* set all alpha values to 255 */
892f6a1733dSAmine Khaldi             for (y=0; y<prc->Height; y++)
893f6a1733dSAmine Khaldi                 for (x=0; x<prc->Width; x++)
894f6a1733dSAmine Khaldi                     pbBuffer[cbStride*y+4*x+3] = 0xff;
895f6a1733dSAmine Khaldi         }
896f6a1733dSAmine Khaldi         return S_OK;
897f6a1733dSAmine Khaldi 
898ae80686dSAmine Khaldi     case format_32bppRGBA:
899ae80686dSAmine Khaldi         if (prc)
900ae80686dSAmine Khaldi             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
901ae80686dSAmine Khaldi         return S_OK;
902f6a1733dSAmine Khaldi 
903f6a1733dSAmine Khaldi     case format_32bppPRGBA:
904f6a1733dSAmine Khaldi         if (prc)
905f6a1733dSAmine Khaldi         {
906f6a1733dSAmine Khaldi             INT x, y;
907f6a1733dSAmine Khaldi 
908f6a1733dSAmine Khaldi             hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
909f6a1733dSAmine Khaldi             if (FAILED(hr)) return hr;
910f6a1733dSAmine Khaldi 
911f6a1733dSAmine Khaldi             for (y=0; y<prc->Height; y++)
912f6a1733dSAmine Khaldi                 for (x=0; x<prc->Width; x++)
913f6a1733dSAmine Khaldi                 {
914f6a1733dSAmine Khaldi                     BYTE alpha = pbBuffer[cbStride*y+4*x+3];
915f6a1733dSAmine Khaldi                     if (alpha != 0 && alpha != 255)
916f6a1733dSAmine Khaldi                     {
917f6a1733dSAmine Khaldi                         pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * 255 / alpha;
918f6a1733dSAmine Khaldi                         pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * 255 / alpha;
919f6a1733dSAmine Khaldi                         pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * 255 / alpha;
920f6a1733dSAmine Khaldi                     }
921f6a1733dSAmine Khaldi                 }
922f6a1733dSAmine Khaldi         }
923f6a1733dSAmine Khaldi         return S_OK;
924f6a1733dSAmine Khaldi 
925ae80686dSAmine Khaldi     default:
926ae80686dSAmine Khaldi         hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
927ae80686dSAmine Khaldi         if (SUCCEEDED(hr) && prc)
928ae80686dSAmine Khaldi               reverse_bgr8(4, pbBuffer, prc->Width, prc->Height, cbStride);
929ae80686dSAmine Khaldi         return hr;
930ae80686dSAmine Khaldi     }
931ae80686dSAmine Khaldi }
932ae80686dSAmine Khaldi 
copypixels_to_32bppBGR(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)933c2c66affSColin Finck static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc,
934c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
935c2c66affSColin Finck {
936c2c66affSColin Finck     switch (source_format)
937c2c66affSColin Finck     {
938c2c66affSColin Finck     case format_32bppBGR:
939c2c66affSColin Finck     case format_32bppBGRA:
940c2c66affSColin Finck     case format_32bppPBGRA:
941c2c66affSColin Finck         if (prc)
942c2c66affSColin Finck             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
943c2c66affSColin Finck         return S_OK;
944c2c66affSColin Finck     default:
945c2c66affSColin Finck         return copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
946c2c66affSColin Finck     }
947c2c66affSColin Finck }
948c2c66affSColin Finck 
copypixels_to_32bppRGB(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)949ae80686dSAmine Khaldi static HRESULT copypixels_to_32bppRGB(struct FormatConverter *This, const WICRect *prc,
950ae80686dSAmine Khaldi     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
951ae80686dSAmine Khaldi {
952ae80686dSAmine Khaldi     switch (source_format)
953ae80686dSAmine Khaldi     {
954ae80686dSAmine Khaldi     case format_32bppRGB:
955ae80686dSAmine Khaldi     case format_32bppRGBA:
956ae80686dSAmine Khaldi     case format_32bppPRGBA:
957ae80686dSAmine Khaldi         if (prc)
958ae80686dSAmine Khaldi             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
959ae80686dSAmine Khaldi         return S_OK;
960ae80686dSAmine Khaldi     default:
961ae80686dSAmine Khaldi         return copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
962ae80686dSAmine Khaldi     }
963ae80686dSAmine Khaldi }
964ae80686dSAmine Khaldi 
copypixels_to_32bppPBGRA(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)965c2c66affSColin Finck static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc,
966c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
967c2c66affSColin Finck {
968c2c66affSColin Finck     HRESULT hr;
969c2c66affSColin Finck 
970c2c66affSColin Finck     switch (source_format)
971c2c66affSColin Finck     {
972c2c66affSColin Finck     case format_32bppPBGRA:
973c2c66affSColin Finck         if (prc)
974c2c66affSColin Finck             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
975c2c66affSColin Finck         return S_OK;
976c2c66affSColin Finck     default:
977c2c66affSColin Finck         hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
978c2c66affSColin Finck         if (SUCCEEDED(hr) && prc)
979c2c66affSColin Finck         {
980c2c66affSColin Finck             INT x, y;
981c2c66affSColin Finck 
982c2c66affSColin Finck             for (y=0; y<prc->Height; y++)
983c2c66affSColin Finck                 for (x=0; x<prc->Width; x++)
984c2c66affSColin Finck                 {
985c2c66affSColin Finck                     BYTE alpha = pbBuffer[cbStride*y+4*x+3];
986c2c66affSColin Finck                     if (alpha != 255)
987c2c66affSColin Finck                     {
988c2c66affSColin Finck                         pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255;
989c2c66affSColin Finck                         pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255;
990c2c66affSColin Finck                         pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255;
991c2c66affSColin Finck                     }
992c2c66affSColin Finck                 }
993c2c66affSColin Finck         }
994c2c66affSColin Finck         return hr;
995c2c66affSColin Finck     }
996c2c66affSColin Finck }
997c2c66affSColin Finck 
copypixels_to_32bppPRGBA(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)998ae80686dSAmine Khaldi static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter *This, const WICRect *prc,
999ae80686dSAmine Khaldi     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1000ae80686dSAmine Khaldi {
1001ae80686dSAmine Khaldi     HRESULT hr;
1002ae80686dSAmine Khaldi 
1003ae80686dSAmine Khaldi     switch (source_format)
1004ae80686dSAmine Khaldi     {
1005ae80686dSAmine Khaldi     case format_32bppPRGBA:
1006ae80686dSAmine Khaldi         if (prc)
1007ae80686dSAmine Khaldi             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1008ae80686dSAmine Khaldi         return S_OK;
1009ae80686dSAmine Khaldi     default:
1010ae80686dSAmine Khaldi         hr = copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
1011ae80686dSAmine Khaldi         if (SUCCEEDED(hr) && prc)
1012ae80686dSAmine Khaldi         {
1013ae80686dSAmine Khaldi             INT x, y;
1014ae80686dSAmine Khaldi 
1015ae80686dSAmine Khaldi             for (y=0; y<prc->Height; y++)
1016ae80686dSAmine Khaldi                 for (x=0; x<prc->Width; x++)
1017ae80686dSAmine Khaldi                 {
1018ae80686dSAmine Khaldi                     BYTE alpha = pbBuffer[cbStride*y+4*x+3];
1019ae80686dSAmine Khaldi                     if (alpha != 255)
1020ae80686dSAmine Khaldi                     {
1021ae80686dSAmine Khaldi                         pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255;
1022ae80686dSAmine Khaldi                         pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255;
1023ae80686dSAmine Khaldi                         pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255;
1024ae80686dSAmine Khaldi                     }
1025ae80686dSAmine Khaldi                 }
1026ae80686dSAmine Khaldi         }
1027ae80686dSAmine Khaldi         return hr;
1028ae80686dSAmine Khaldi     }
1029ae80686dSAmine Khaldi }
1030ae80686dSAmine Khaldi 
copypixels_to_24bppBGR(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)1031c2c66affSColin Finck static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRect *prc,
1032c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1033c2c66affSColin Finck {
1034c2c66affSColin Finck     HRESULT hr;
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     switch (source_format)
1037c2c66affSColin Finck     {
1038c2c66affSColin Finck     case format_24bppBGR:
1039c2c66affSColin Finck     case format_24bppRGB:
1040c2c66affSColin Finck         if (prc)
1041c2c66affSColin Finck         {
1042c2c66affSColin Finck             hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1043c2c66affSColin Finck             if (SUCCEEDED(hr) && source_format == format_24bppRGB)
1044c2c66affSColin Finck               reverse_bgr8(3, pbBuffer, prc->Width, prc->Height, cbStride);
1045c2c66affSColin Finck             return hr;
1046c2c66affSColin Finck         }
1047c2c66affSColin Finck         return S_OK;
1048c2c66affSColin Finck     case format_32bppBGR:
1049c2c66affSColin Finck     case format_32bppBGRA:
1050c2c66affSColin Finck     case format_32bppPBGRA:
1051*cfaeaaa9SThomas Csovcsity     case format_32bppRGBA:
1052c2c66affSColin Finck         if (prc)
1053c2c66affSColin Finck         {
1054c2c66affSColin Finck             HRESULT res;
1055c2c66affSColin Finck             INT x, y;
1056c2c66affSColin Finck             BYTE *srcdata;
1057c2c66affSColin Finck             UINT srcstride, srcdatasize;
1058c2c66affSColin Finck             const BYTE *srcrow;
1059c2c66affSColin Finck             const BYTE *srcpixel;
1060c2c66affSColin Finck             BYTE *dstrow;
1061c2c66affSColin Finck             BYTE *dstpixel;
1062c2c66affSColin Finck 
1063c2c66affSColin Finck             srcstride = 4 * prc->Width;
1064c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
1065c2c66affSColin Finck 
1066c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1067c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
1068c2c66affSColin Finck 
1069c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
1070c2c66affSColin Finck 
1071c2c66affSColin Finck             if (SUCCEEDED(res))
1072c2c66affSColin Finck             {
1073c2c66affSColin Finck                 srcrow = srcdata;
1074c2c66affSColin Finck                 dstrow = pbBuffer;
1075*cfaeaaa9SThomas Csovcsity 
1076*cfaeaaa9SThomas Csovcsity                 if (source_format == format_32bppRGBA)
1077*cfaeaaa9SThomas Csovcsity                 {
1078*cfaeaaa9SThomas Csovcsity                     for (y = 0; y < prc->Height; y++)
1079*cfaeaaa9SThomas Csovcsity                     {
1080*cfaeaaa9SThomas Csovcsity                         srcpixel = srcrow;
1081*cfaeaaa9SThomas Csovcsity                         dstpixel = dstrow;
1082*cfaeaaa9SThomas Csovcsity                         for (x = 0; x < prc->Width; x++) {
1083*cfaeaaa9SThomas Csovcsity                             *dstpixel++ = srcpixel[2]; /* blue */
1084*cfaeaaa9SThomas Csovcsity                             *dstpixel++ = srcpixel[1]; /* green */
1085*cfaeaaa9SThomas Csovcsity                             *dstpixel++ = srcpixel[0]; /* red */
1086*cfaeaaa9SThomas Csovcsity                             srcpixel += 4;
1087*cfaeaaa9SThomas Csovcsity                         }
1088*cfaeaaa9SThomas Csovcsity                         srcrow += srcstride;
1089*cfaeaaa9SThomas Csovcsity                         dstrow += cbStride;
1090*cfaeaaa9SThomas Csovcsity                     }
1091*cfaeaaa9SThomas Csovcsity                 }
1092*cfaeaaa9SThomas Csovcsity                 else
1093*cfaeaaa9SThomas Csovcsity                 {
1094*cfaeaaa9SThomas Csovcsity                     for (y = 0; y < prc->Height; y++)
1095*cfaeaaa9SThomas Csovcsity                     {
1096c2c66affSColin Finck                         srcpixel = srcrow;
1097c2c66affSColin Finck                         dstpixel = dstrow;
1098c2c66affSColin Finck                         for (x = 0; x < prc->Width; x++) {
1099c2c66affSColin Finck                             *dstpixel++ = *srcpixel++; /* blue */
1100c2c66affSColin Finck                             *dstpixel++ = *srcpixel++; /* green */
1101c2c66affSColin Finck                             *dstpixel++ = *srcpixel++; /* red */
1102c2c66affSColin Finck                             srcpixel++; /* alpha */
1103c2c66affSColin Finck                         }
1104c2c66affSColin Finck                         srcrow += srcstride;
1105c2c66affSColin Finck                         dstrow += cbStride;
1106c2c66affSColin Finck                     }
1107c2c66affSColin Finck                 }
1108*cfaeaaa9SThomas Csovcsity             }
1109c2c66affSColin Finck 
1110c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
1111c2c66affSColin Finck 
1112c2c66affSColin Finck             return res;
1113c2c66affSColin Finck         }
1114c2c66affSColin Finck         return S_OK;
1115c2c66affSColin Finck 
1116c2c66affSColin Finck     case format_32bppGrayFloat:
1117c2c66affSColin Finck         if (prc)
1118c2c66affSColin Finck         {
1119c2c66affSColin Finck             BYTE *srcdata;
1120c2c66affSColin Finck             UINT srcstride, srcdatasize;
1121c2c66affSColin Finck 
1122c2c66affSColin Finck             srcstride = 4 * prc->Width;
1123c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
1124c2c66affSColin Finck 
1125c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1126c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
1127c2c66affSColin Finck 
1128c2c66affSColin Finck             hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
1129c2c66affSColin Finck 
1130c2c66affSColin Finck             if (SUCCEEDED(hr))
1131c2c66affSColin Finck             {
1132c2c66affSColin Finck                 INT x, y;
1133c2c66affSColin Finck                 BYTE *src = srcdata, *dst = pbBuffer;
1134c2c66affSColin Finck 
1135c2c66affSColin Finck                 for (y = 0; y < prc->Height; y++)
1136c2c66affSColin Finck                 {
1137c2c66affSColin Finck                     float *gray_float = (float *)src;
1138c2c66affSColin Finck                     BYTE *bgr = dst;
1139c2c66affSColin Finck 
1140c2c66affSColin Finck                     for (x = 0; x < prc->Width; x++)
1141c2c66affSColin Finck                     {
1142c2c66affSColin Finck                         BYTE gray = (BYTE)floorf(to_sRGB_component(gray_float[x]) * 255.0f + 0.51f);
1143c2c66affSColin Finck                         *bgr++ = gray;
1144c2c66affSColin Finck                         *bgr++ = gray;
1145c2c66affSColin Finck                         *bgr++ = gray;
1146c2c66affSColin Finck                     }
1147c2c66affSColin Finck                     src += srcstride;
1148c2c66affSColin Finck                     dst += cbStride;
1149c2c66affSColin Finck                 }
1150c2c66affSColin Finck             }
1151c2c66affSColin Finck 
1152c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
1153c2c66affSColin Finck 
1154c2c66affSColin Finck             return hr;
1155c2c66affSColin Finck         }
1156c2c66affSColin Finck         return S_OK;
1157c2c66affSColin Finck 
1158324214f9SAmine Khaldi     case format_32bppCMYK:
1159324214f9SAmine Khaldi         if (prc)
1160324214f9SAmine Khaldi         {
1161324214f9SAmine Khaldi             BYTE *srcdata;
1162324214f9SAmine Khaldi             UINT srcstride, srcdatasize;
1163324214f9SAmine Khaldi 
1164324214f9SAmine Khaldi             srcstride = 4 * prc->Width;
1165324214f9SAmine Khaldi             srcdatasize = srcstride * prc->Height;
1166324214f9SAmine Khaldi 
1167324214f9SAmine Khaldi             srcdata = heap_alloc(srcdatasize);
1168324214f9SAmine Khaldi             if (!srcdata) return E_OUTOFMEMORY;
1169324214f9SAmine Khaldi 
1170324214f9SAmine Khaldi             hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
1171324214f9SAmine Khaldi             if (SUCCEEDED(hr))
1172324214f9SAmine Khaldi             {
1173324214f9SAmine Khaldi                 INT x, y;
1174324214f9SAmine Khaldi                 BYTE *src = srcdata, *dst = pbBuffer;
1175324214f9SAmine Khaldi 
1176324214f9SAmine Khaldi                 for (y = 0; y < prc->Height; y++)
1177324214f9SAmine Khaldi                 {
1178324214f9SAmine Khaldi                     BYTE *cmyk = src;
1179324214f9SAmine Khaldi                     BYTE *bgr = dst;
1180324214f9SAmine Khaldi 
1181324214f9SAmine Khaldi                     for (x = 0; x < prc->Width; x++)
1182324214f9SAmine Khaldi                     {
1183324214f9SAmine Khaldi                         BYTE c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
1184324214f9SAmine Khaldi                         bgr[0] = (255 - y) * (255 - k) / 255; /* B */
1185324214f9SAmine Khaldi                         bgr[1] = (255 - m) * (255 - k) / 255; /* G */
1186324214f9SAmine Khaldi                         bgr[2] = (255 - c) * (255 - k) / 255; /* R */
1187324214f9SAmine Khaldi                         cmyk += 4;
1188324214f9SAmine Khaldi                         bgr += 3;
1189324214f9SAmine Khaldi                     }
1190324214f9SAmine Khaldi                     src += srcstride;
1191324214f9SAmine Khaldi                     dst += cbStride;
1192324214f9SAmine Khaldi                 }
1193324214f9SAmine Khaldi             }
1194324214f9SAmine Khaldi 
1195324214f9SAmine Khaldi             heap_free(srcdata);
1196324214f9SAmine Khaldi             return hr;
1197324214f9SAmine Khaldi         }
1198324214f9SAmine Khaldi         return S_OK;
1199324214f9SAmine Khaldi 
1200c2c66affSColin Finck     default:
1201c2c66affSColin Finck         FIXME("Unimplemented conversion path!\n");
1202c2c66affSColin Finck         return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1203c2c66affSColin Finck     }
1204c2c66affSColin Finck }
1205c2c66affSColin Finck 
copypixels_to_24bppRGB(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)1206c2c66affSColin Finck static HRESULT copypixels_to_24bppRGB(struct FormatConverter *This, const WICRect *prc,
1207c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1208c2c66affSColin Finck {
1209c2c66affSColin Finck     HRESULT hr;
1210c2c66affSColin Finck 
1211c2c66affSColin Finck     switch (source_format)
1212c2c66affSColin Finck     {
1213c2c66affSColin Finck     case format_24bppBGR:
1214c2c66affSColin Finck     case format_24bppRGB:
1215c2c66affSColin Finck         if (prc)
1216c2c66affSColin Finck         {
1217c2c66affSColin Finck             hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1218c2c66affSColin Finck             if (SUCCEEDED(hr) && source_format == format_24bppBGR)
1219c2c66affSColin Finck               reverse_bgr8(3, pbBuffer, prc->Width, prc->Height, cbStride);
1220c2c66affSColin Finck             return hr;
1221c2c66affSColin Finck         }
1222c2c66affSColin Finck         return S_OK;
1223c2c66affSColin Finck     case format_32bppBGR:
1224c2c66affSColin Finck     case format_32bppBGRA:
1225c2c66affSColin Finck     case format_32bppPBGRA:
1226c2c66affSColin Finck         if (prc)
1227c2c66affSColin Finck         {
1228c2c66affSColin Finck             HRESULT res;
1229c2c66affSColin Finck             INT x, y;
1230c2c66affSColin Finck             BYTE *srcdata;
1231c2c66affSColin Finck             UINT srcstride, srcdatasize;
1232c2c66affSColin Finck             const BYTE *srcrow;
1233c2c66affSColin Finck             const BYTE *srcpixel;
1234c2c66affSColin Finck             BYTE *dstrow;
1235c2c66affSColin Finck             BYTE *dstpixel;
1236c2c66affSColin Finck             BYTE tmppixel[3];
1237c2c66affSColin Finck 
1238c2c66affSColin Finck             srcstride = 4 * prc->Width;
1239c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
1240c2c66affSColin Finck 
1241c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1242c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
1243c2c66affSColin Finck 
1244c2c66affSColin Finck             res = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
1245c2c66affSColin Finck 
1246c2c66affSColin Finck             if (SUCCEEDED(res))
1247c2c66affSColin Finck             {
1248c2c66affSColin Finck                 srcrow = srcdata;
1249c2c66affSColin Finck                 dstrow = pbBuffer;
1250c2c66affSColin Finck                 for (y=0; y<prc->Height; y++) {
1251c2c66affSColin Finck                     srcpixel=srcrow;
1252c2c66affSColin Finck                     dstpixel=dstrow;
1253c2c66affSColin Finck                     for (x=0; x<prc->Width; x++) {
1254c2c66affSColin Finck                         tmppixel[0]=*srcpixel++; /* blue */
1255c2c66affSColin Finck                         tmppixel[1]=*srcpixel++; /* green */
1256c2c66affSColin Finck                         tmppixel[2]=*srcpixel++; /* red */
1257c2c66affSColin Finck                         srcpixel++; /* alpha */
1258c2c66affSColin Finck 
1259c2c66affSColin Finck                         *dstpixel++=tmppixel[2]; /* red */
1260c2c66affSColin Finck                         *dstpixel++=tmppixel[1]; /* green */
1261c2c66affSColin Finck                         *dstpixel++=tmppixel[0]; /* blue */
1262c2c66affSColin Finck                     }
1263c2c66affSColin Finck                     srcrow += srcstride;
1264c2c66affSColin Finck                     dstrow += cbStride;
1265c2c66affSColin Finck                 }
1266c2c66affSColin Finck             }
1267c2c66affSColin Finck 
1268c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
1269c2c66affSColin Finck 
1270c2c66affSColin Finck             return res;
1271c2c66affSColin Finck         }
1272c2c66affSColin Finck         return S_OK;
1273c2c66affSColin Finck     default:
1274c2c66affSColin Finck         FIXME("Unimplemented conversion path!\n");
1275c2c66affSColin Finck         return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1276c2c66affSColin Finck     }
1277c2c66affSColin Finck }
1278c2c66affSColin Finck 
copypixels_to_32bppGrayFloat(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)1279c2c66affSColin Finck static HRESULT copypixels_to_32bppGrayFloat(struct FormatConverter *This, const WICRect *prc,
1280c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1281c2c66affSColin Finck {
1282c2c66affSColin Finck     HRESULT hr;
1283c2c66affSColin Finck 
1284c2c66affSColin Finck     switch (source_format)
1285c2c66affSColin Finck     {
1286c2c66affSColin Finck     case format_32bppBGR:
1287c2c66affSColin Finck     case format_32bppBGRA:
1288c2c66affSColin Finck     case format_32bppPBGRA:
1289c2c66affSColin Finck     case format_32bppGrayFloat:
1290c2c66affSColin Finck         if (prc)
1291c2c66affSColin Finck         {
1292c2c66affSColin Finck             hr = IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1293c2c66affSColin Finck             break;
1294c2c66affSColin Finck         }
1295c2c66affSColin Finck         return S_OK;
1296c2c66affSColin Finck 
1297c2c66affSColin Finck     default:
1298c2c66affSColin Finck         hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format);
1299c2c66affSColin Finck         break;
1300c2c66affSColin Finck     }
1301c2c66affSColin Finck 
1302c2c66affSColin Finck     if (SUCCEEDED(hr) && prc && source_format != format_32bppGrayFloat)
1303c2c66affSColin Finck     {
1304c2c66affSColin Finck         INT x, y;
1305c2c66affSColin Finck         BYTE *p = pbBuffer;
1306c2c66affSColin Finck 
1307c2c66affSColin Finck         for (y = 0; y < prc->Height; y++)
1308c2c66affSColin Finck         {
1309c2c66affSColin Finck             BYTE *bgr = p;
1310c2c66affSColin Finck             for (x = 0; x < prc->Width; x++)
1311c2c66affSColin Finck             {
1312c2c66affSColin Finck                 float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f;
1313c2c66affSColin Finck                 *(float *)bgr = gray;
1314c2c66affSColin Finck                 bgr += 4;
1315c2c66affSColin Finck             }
1316c2c66affSColin Finck             p += cbStride;
1317c2c66affSColin Finck         }
1318c2c66affSColin Finck     }
1319c2c66affSColin Finck     return hr;
1320c2c66affSColin Finck }
1321c2c66affSColin Finck 
copypixels_to_8bppGray(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)1322c2c66affSColin Finck static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRect *prc,
1323c2c66affSColin Finck     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1324c2c66affSColin Finck {
1325c2c66affSColin Finck     HRESULT hr;
1326c2c66affSColin Finck     BYTE *srcdata;
1327c2c66affSColin Finck     UINT srcstride, srcdatasize;
1328c2c66affSColin Finck 
1329c2c66affSColin Finck     if (source_format == format_8bppGray)
1330c2c66affSColin Finck     {
1331c2c66affSColin Finck         if (prc)
1332c2c66affSColin Finck             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1333c2c66affSColin Finck 
1334c2c66affSColin Finck         return S_OK;
1335c2c66affSColin Finck     }
1336c2c66affSColin Finck 
1337c2c66affSColin Finck     if (source_format == format_32bppGrayFloat)
1338c2c66affSColin Finck     {
1339c2c66affSColin Finck         hr = S_OK;
1340c2c66affSColin Finck 
1341c2c66affSColin Finck         if (prc)
1342c2c66affSColin Finck         {
1343c2c66affSColin Finck             srcstride = 4 * prc->Width;
1344c2c66affSColin Finck             srcdatasize = srcstride * prc->Height;
1345c2c66affSColin Finck 
1346c2c66affSColin Finck             srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1347c2c66affSColin Finck             if (!srcdata) return E_OUTOFMEMORY;
1348c2c66affSColin Finck 
1349c2c66affSColin Finck             hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata);
1350c2c66affSColin Finck             if (SUCCEEDED(hr))
1351c2c66affSColin Finck             {
1352c2c66affSColin Finck                 INT x, y;
1353c2c66affSColin Finck                 BYTE *src = srcdata, *dst = pbBuffer;
1354c2c66affSColin Finck 
1355c2c66affSColin Finck                 for (y=0; y < prc->Height; y++)
1356c2c66affSColin Finck                 {
1357c2c66affSColin Finck                     float *srcpixel = (float*)src;
1358c2c66affSColin Finck                     BYTE *dstpixel = dst;
1359c2c66affSColin Finck 
1360c2c66affSColin Finck                     for (x=0; x < prc->Width; x++)
1361c2c66affSColin Finck                         *dstpixel++ = (BYTE)floorf(to_sRGB_component(*srcpixel++) * 255.0f + 0.51f);
1362c2c66affSColin Finck 
1363c2c66affSColin Finck                     src += srcstride;
1364c2c66affSColin Finck                     dst += cbStride;
1365c2c66affSColin Finck                 }
1366c2c66affSColin Finck             }
1367c2c66affSColin Finck 
1368c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, srcdata);
1369c2c66affSColin Finck         }
1370c2c66affSColin Finck 
1371c2c66affSColin Finck         return hr;
1372c2c66affSColin Finck     }
1373c2c66affSColin Finck 
1374f6a1733dSAmine Khaldi     if (!prc)
1375f6a1733dSAmine Khaldi         return copypixels_to_24bppBGR(This, NULL, cbStride, cbBufferSize, pbBuffer, source_format);
1376f6a1733dSAmine Khaldi 
1377c2c66affSColin Finck     srcstride = 3 * prc->Width;
1378c2c66affSColin Finck     srcdatasize = srcstride * prc->Height;
1379c2c66affSColin Finck 
1380c2c66affSColin Finck     srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1381c2c66affSColin Finck     if (!srcdata) return E_OUTOFMEMORY;
1382c2c66affSColin Finck 
1383c2c66affSColin Finck     hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format);
1384f6a1733dSAmine Khaldi     if (SUCCEEDED(hr))
1385c2c66affSColin Finck     {
1386c2c66affSColin Finck         INT x, y;
1387c2c66affSColin Finck         BYTE *src = srcdata, *dst = pbBuffer;
1388c2c66affSColin Finck 
1389c2c66affSColin Finck         for (y = 0; y < prc->Height; y++)
1390c2c66affSColin Finck         {
1391c2c66affSColin Finck             BYTE *bgr = src;
1392c2c66affSColin Finck 
1393c2c66affSColin Finck             for (x = 0; x < prc->Width; x++)
1394c2c66affSColin Finck             {
1395c2c66affSColin Finck                 float gray = (bgr[2] * 0.2126f + bgr[1] * 0.7152f + bgr[0] * 0.0722f) / 255.0f;
1396c2c66affSColin Finck 
1397c2c66affSColin Finck                 gray = to_sRGB_component(gray) * 255.0f;
1398c2c66affSColin Finck                 dst[x] = (BYTE)floorf(gray + 0.51f);
1399c2c66affSColin Finck                 bgr += 3;
1400c2c66affSColin Finck             }
1401c2c66affSColin Finck             src += srcstride;
1402c2c66affSColin Finck             dst += cbStride;
1403c2c66affSColin Finck         }
1404c2c66affSColin Finck     }
1405c2c66affSColin Finck 
1406c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, srcdata);
1407c2c66affSColin Finck     return hr;
1408c2c66affSColin Finck }
1409c2c66affSColin Finck 
rgb_to_palette_index(BYTE bgr[3],WICColor * colors,UINT count)1410f6a1733dSAmine Khaldi static UINT rgb_to_palette_index(BYTE bgr[3], WICColor *colors, UINT count)
1411ae80686dSAmine Khaldi {
1412ae80686dSAmine Khaldi     UINT best_diff, best_index, i;
1413ae80686dSAmine Khaldi 
1414ae80686dSAmine Khaldi     best_diff = ~0;
1415ae80686dSAmine Khaldi     best_index = 0;
1416ae80686dSAmine Khaldi 
1417ae80686dSAmine Khaldi     for (i = 0; i < count; i++)
1418ae80686dSAmine Khaldi     {
1419ae80686dSAmine Khaldi         BYTE pal_r, pal_g, pal_b;
1420f6a1733dSAmine Khaldi         UINT diff_r, diff_g, diff_b, diff;
1421ae80686dSAmine Khaldi 
1422ae80686dSAmine Khaldi         pal_r = colors[i] >> 16;
1423ae80686dSAmine Khaldi         pal_g = colors[i] >> 8;
1424ae80686dSAmine Khaldi         pal_b = colors[i];
1425ae80686dSAmine Khaldi 
1426f6a1733dSAmine Khaldi         diff_r = bgr[2] - pal_r;
1427f6a1733dSAmine Khaldi         diff_g = bgr[1] - pal_g;
1428f6a1733dSAmine Khaldi         diff_b = bgr[0] - pal_b;
1429ae80686dSAmine Khaldi 
1430ae80686dSAmine Khaldi         diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b;
1431ae80686dSAmine Khaldi         if (diff == 0) return i;
1432ae80686dSAmine Khaldi 
1433ae80686dSAmine Khaldi         if (diff < best_diff)
1434ae80686dSAmine Khaldi         {
1435ae80686dSAmine Khaldi             best_diff = diff;
1436ae80686dSAmine Khaldi             best_index = i;
1437ae80686dSAmine Khaldi         }
1438ae80686dSAmine Khaldi     }
1439ae80686dSAmine Khaldi 
1440ae80686dSAmine Khaldi     return best_index;
1441ae80686dSAmine Khaldi }
1442ae80686dSAmine Khaldi 
copypixels_to_8bppIndexed(struct FormatConverter * This,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer,enum pixelformat source_format)1443ae80686dSAmine Khaldi static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WICRect *prc,
1444ae80686dSAmine Khaldi     UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format)
1445ae80686dSAmine Khaldi {
1446ae80686dSAmine Khaldi     HRESULT hr;
1447ae80686dSAmine Khaldi     BYTE *srcdata;
1448ae80686dSAmine Khaldi     WICColor colors[256];
1449ae80686dSAmine Khaldi     UINT srcstride, srcdatasize, count;
1450ae80686dSAmine Khaldi 
1451ae80686dSAmine Khaldi     if (source_format == format_8bppIndexed)
1452ae80686dSAmine Khaldi     {
1453ae80686dSAmine Khaldi         if (prc)
1454ae80686dSAmine Khaldi             return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer);
1455ae80686dSAmine Khaldi 
1456ae80686dSAmine Khaldi         return S_OK;
1457ae80686dSAmine Khaldi     }
1458ae80686dSAmine Khaldi 
1459f6a1733dSAmine Khaldi     if (!prc)
1460f6a1733dSAmine Khaldi         return copypixels_to_24bppBGR(This, NULL, cbStride, cbBufferSize, pbBuffer, source_format);
1461f6a1733dSAmine Khaldi 
1462ae80686dSAmine Khaldi     if (!This->palette) return WINCODEC_ERR_WRONGSTATE;
1463ae80686dSAmine Khaldi 
1464ae80686dSAmine Khaldi     hr = IWICPalette_GetColors(This->palette, 256, colors, &count);
1465ae80686dSAmine Khaldi     if (hr != S_OK) return hr;
1466ae80686dSAmine Khaldi 
1467ae80686dSAmine Khaldi     srcstride = 3 * prc->Width;
1468ae80686dSAmine Khaldi     srcdatasize = srcstride * prc->Height;
1469ae80686dSAmine Khaldi 
1470ae80686dSAmine Khaldi     srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize);
1471ae80686dSAmine Khaldi     if (!srcdata) return E_OUTOFMEMORY;
1472ae80686dSAmine Khaldi 
1473ae80686dSAmine Khaldi     hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format);
1474f6a1733dSAmine Khaldi     if (SUCCEEDED(hr))
1475ae80686dSAmine Khaldi     {
1476ae80686dSAmine Khaldi         INT x, y;
1477ae80686dSAmine Khaldi         BYTE *src = srcdata, *dst = pbBuffer;
1478ae80686dSAmine Khaldi 
1479ae80686dSAmine Khaldi         for (y = 0; y < prc->Height; y++)
1480ae80686dSAmine Khaldi         {
1481ae80686dSAmine Khaldi             BYTE *bgr = src;
1482ae80686dSAmine Khaldi 
1483ae80686dSAmine Khaldi             for (x = 0; x < prc->Width; x++)
1484ae80686dSAmine Khaldi             {
1485f6a1733dSAmine Khaldi                 dst[x] = rgb_to_palette_index(bgr, colors, count);
1486ae80686dSAmine Khaldi                 bgr += 3;
1487ae80686dSAmine Khaldi             }
1488ae80686dSAmine Khaldi             src += srcstride;
1489ae80686dSAmine Khaldi             dst += cbStride;
1490ae80686dSAmine Khaldi         }
1491ae80686dSAmine Khaldi     }
1492ae80686dSAmine Khaldi 
1493ae80686dSAmine Khaldi     HeapFree(GetProcessHeap(), 0, srcdata);
1494ae80686dSAmine Khaldi     return hr;
1495ae80686dSAmine Khaldi }
1496ae80686dSAmine Khaldi 
1497c2c66affSColin Finck static const struct pixelformatinfo supported_formats[] = {
1498c2c66affSColin Finck     {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL},
1499c2c66affSColin Finck     {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL},
1500c2c66affSColin Finck     {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL},
1501ae80686dSAmine Khaldi     {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed},
1502c2c66affSColin Finck     {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL},
1503c2c66affSColin Finck     {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL},
1504c2c66affSColin Finck     {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL},
1505c2c66affSColin Finck     {format_8bppGray, &GUID_WICPixelFormat8bppGray, copypixels_to_8bppGray},
1506c2c66affSColin Finck     {format_16bppGray, &GUID_WICPixelFormat16bppGray, NULL},
1507c2c66affSColin Finck     {format_16bppBGR555, &GUID_WICPixelFormat16bppBGR555, NULL},
1508c2c66affSColin Finck     {format_16bppBGR565, &GUID_WICPixelFormat16bppBGR565, NULL},
1509c2c66affSColin Finck     {format_16bppBGRA5551, &GUID_WICPixelFormat16bppBGRA5551, NULL},
1510c2c66affSColin Finck     {format_24bppBGR, &GUID_WICPixelFormat24bppBGR, copypixels_to_24bppBGR},
1511c2c66affSColin Finck     {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB},
1512c2c66affSColin Finck     {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat},
1513c2c66affSColin Finck     {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR},
1514ae80686dSAmine Khaldi     {format_32bppRGB, &GUID_WICPixelFormat32bppRGB, copypixels_to_32bppRGB},
1515c2c66affSColin Finck     {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA},
1516ae80686dSAmine Khaldi     {format_32bppRGBA, &GUID_WICPixelFormat32bppRGBA, copypixels_to_32bppRGBA},
1517c2c66affSColin Finck     {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA},
1518ae80686dSAmine Khaldi     {format_32bppPRGBA, &GUID_WICPixelFormat32bppPRGBA, copypixels_to_32bppPRGBA},
1519c2c66affSColin Finck     {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL},
1520c2c66affSColin Finck     {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL},
1521c2c66affSColin Finck     {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL},
1522c2c66affSColin Finck     {0}
1523c2c66affSColin Finck };
1524c2c66affSColin Finck 
get_formatinfo(const WICPixelFormatGUID * format)1525c2c66affSColin Finck static const struct pixelformatinfo *get_formatinfo(const WICPixelFormatGUID *format)
1526c2c66affSColin Finck {
1527c2c66affSColin Finck     UINT i;
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     for (i=0; supported_formats[i].guid; i++)
1530c2c66affSColin Finck         if (IsEqualGUID(supported_formats[i].guid, format)) return &supported_formats[i];
1531c2c66affSColin Finck 
1532c2c66affSColin Finck     return NULL;
1533c2c66affSColin Finck }
1534c2c66affSColin Finck 
FormatConverter_QueryInterface(IWICFormatConverter * iface,REFIID iid,void ** ppv)1535c2c66affSColin Finck static HRESULT WINAPI FormatConverter_QueryInterface(IWICFormatConverter *iface, REFIID iid,
1536c2c66affSColin Finck     void **ppv)
1537c2c66affSColin Finck {
1538c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1539c2c66affSColin Finck     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1540c2c66affSColin Finck 
1541c2c66affSColin Finck     if (!ppv) return E_INVALIDARG;
1542c2c66affSColin Finck 
1543c2c66affSColin Finck     if (IsEqualIID(&IID_IUnknown, iid) ||
1544c2c66affSColin Finck         IsEqualIID(&IID_IWICBitmapSource, iid) ||
1545c2c66affSColin Finck         IsEqualIID(&IID_IWICFormatConverter, iid))
1546c2c66affSColin Finck     {
1547c2c66affSColin Finck         *ppv = &This->IWICFormatConverter_iface;
1548c2c66affSColin Finck     }
1549c2c66affSColin Finck     else
1550c2c66affSColin Finck     {
1551c2c66affSColin Finck         *ppv = NULL;
1552c2c66affSColin Finck         return E_NOINTERFACE;
1553c2c66affSColin Finck     }
1554c2c66affSColin Finck 
1555c2c66affSColin Finck     IUnknown_AddRef((IUnknown*)*ppv);
1556c2c66affSColin Finck     return S_OK;
1557c2c66affSColin Finck }
1558c2c66affSColin Finck 
FormatConverter_AddRef(IWICFormatConverter * iface)1559c2c66affSColin Finck static ULONG WINAPI FormatConverter_AddRef(IWICFormatConverter *iface)
1560c2c66affSColin Finck {
1561c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1562c2c66affSColin Finck     ULONG ref = InterlockedIncrement(&This->ref);
1563c2c66affSColin Finck 
1564c2c66affSColin Finck     TRACE("(%p) refcount=%u\n", iface, ref);
1565c2c66affSColin Finck 
1566c2c66affSColin Finck     return ref;
1567c2c66affSColin Finck }
1568c2c66affSColin Finck 
FormatConverter_Release(IWICFormatConverter * iface)1569c2c66affSColin Finck static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface)
1570c2c66affSColin Finck {
1571c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1572c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&This->ref);
1573c2c66affSColin Finck 
1574c2c66affSColin Finck     TRACE("(%p) refcount=%u\n", iface, ref);
1575c2c66affSColin Finck 
1576c2c66affSColin Finck     if (ref == 0)
1577c2c66affSColin Finck     {
1578c2c66affSColin Finck         This->lock.DebugInfo->Spare[0] = 0;
1579c2c66affSColin Finck         DeleteCriticalSection(&This->lock);
1580c2c66affSColin Finck         if (This->source) IWICBitmapSource_Release(This->source);
1581ae80686dSAmine Khaldi         if (This->palette) IWICPalette_Release(This->palette);
1582c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, This);
1583c2c66affSColin Finck     }
1584c2c66affSColin Finck 
1585c2c66affSColin Finck     return ref;
1586c2c66affSColin Finck }
1587c2c66affSColin Finck 
FormatConverter_GetSize(IWICFormatConverter * iface,UINT * puiWidth,UINT * puiHeight)1588c2c66affSColin Finck static HRESULT WINAPI FormatConverter_GetSize(IWICFormatConverter *iface,
1589c2c66affSColin Finck     UINT *puiWidth, UINT *puiHeight)
1590c2c66affSColin Finck {
1591c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1592c2c66affSColin Finck 
1593c2c66affSColin Finck     TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);
1594c2c66affSColin Finck 
1595c2c66affSColin Finck     if (This->source)
1596c2c66affSColin Finck         return IWICBitmapSource_GetSize(This->source, puiWidth, puiHeight);
1597c2c66affSColin Finck     else
1598c2c66affSColin Finck         return WINCODEC_ERR_NOTINITIALIZED;
1599c2c66affSColin Finck }
1600c2c66affSColin Finck 
FormatConverter_GetPixelFormat(IWICFormatConverter * iface,WICPixelFormatGUID * pPixelFormat)1601c2c66affSColin Finck static HRESULT WINAPI FormatConverter_GetPixelFormat(IWICFormatConverter *iface,
1602c2c66affSColin Finck     WICPixelFormatGUID *pPixelFormat)
1603c2c66affSColin Finck {
1604c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1605c2c66affSColin Finck 
1606c2c66affSColin Finck     TRACE("(%p,%p)\n", iface, pPixelFormat);
1607c2c66affSColin Finck 
1608c2c66affSColin Finck     if (This->source)
1609c2c66affSColin Finck         memcpy(pPixelFormat, This->dst_format->guid, sizeof(GUID));
1610c2c66affSColin Finck     else
1611c2c66affSColin Finck         return WINCODEC_ERR_NOTINITIALIZED;
1612c2c66affSColin Finck 
1613c2c66affSColin Finck     return S_OK;
1614c2c66affSColin Finck }
1615c2c66affSColin Finck 
FormatConverter_GetResolution(IWICFormatConverter * iface,double * pDpiX,double * pDpiY)1616c2c66affSColin Finck static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface,
1617c2c66affSColin Finck     double *pDpiX, double *pDpiY)
1618c2c66affSColin Finck {
1619c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1620c2c66affSColin Finck 
1621c2c66affSColin Finck     TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
1622c2c66affSColin Finck 
1623c2c66affSColin Finck     if (This->source)
1624c2c66affSColin Finck         return IWICBitmapSource_GetResolution(This->source, pDpiX, pDpiY);
1625c2c66affSColin Finck     else
1626c2c66affSColin Finck         return WINCODEC_ERR_NOTINITIALIZED;
1627c2c66affSColin Finck }
1628c2c66affSColin Finck 
FormatConverter_CopyPalette(IWICFormatConverter * iface,IWICPalette * palette)1629c2c66affSColin Finck static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface,
1630ae80686dSAmine Khaldi     IWICPalette *palette)
1631c2c66affSColin Finck {
1632ae80686dSAmine Khaldi     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1633ae80686dSAmine Khaldi 
1634ae80686dSAmine Khaldi     TRACE("(%p,%p)\n", iface, palette);
1635ae80686dSAmine Khaldi 
1636ae80686dSAmine Khaldi     if (!palette) return E_INVALIDARG;
1637ae80686dSAmine Khaldi     if (!This->source) return WINCODEC_ERR_WRONGSTATE;
1638ae80686dSAmine Khaldi 
1639ae80686dSAmine Khaldi     if (!This->palette)
1640ae80686dSAmine Khaldi     {
1641ae80686dSAmine Khaldi         HRESULT hr;
1642ae80686dSAmine Khaldi         UINT bpp;
1643ae80686dSAmine Khaldi 
1644ae80686dSAmine Khaldi         hr = get_pixelformat_bpp(This->dst_format->guid, &bpp);
1645ae80686dSAmine Khaldi         if (hr != S_OK) return hr;
1646ae80686dSAmine Khaldi         if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE;
1647ae80686dSAmine Khaldi         return IWICBitmapSource_CopyPalette(This->source, palette);
1648ae80686dSAmine Khaldi     }
1649ae80686dSAmine Khaldi 
1650ae80686dSAmine Khaldi     return IWICPalette_InitializeFromPalette(palette, This->palette);
1651c2c66affSColin Finck }
1652c2c66affSColin Finck 
FormatConverter_CopyPixels(IWICFormatConverter * iface,const WICRect * prc,UINT cbStride,UINT cbBufferSize,BYTE * pbBuffer)1653c2c66affSColin Finck static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface,
1654c2c66affSColin Finck     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
1655c2c66affSColin Finck {
1656c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1657c2c66affSColin Finck     WICRect rc;
1658c2c66affSColin Finck     HRESULT hr;
1659e98ef499SAmine Khaldi     TRACE("(%p,%s,%u,%u,%p)\n", iface, debug_wic_rect(prc), cbStride, cbBufferSize, pbBuffer);
1660c2c66affSColin Finck 
1661c2c66affSColin Finck     if (This->source)
1662c2c66affSColin Finck     {
1663c2c66affSColin Finck         if (!prc)
1664c2c66affSColin Finck         {
1665c2c66affSColin Finck             UINT width, height;
1666c2c66affSColin Finck             hr = IWICBitmapSource_GetSize(This->source, &width, &height);
1667c2c66affSColin Finck             if (FAILED(hr)) return hr;
1668c2c66affSColin Finck             rc.X = 0;
1669c2c66affSColin Finck             rc.Y = 0;
1670c2c66affSColin Finck             rc.Width = width;
1671c2c66affSColin Finck             rc.Height = height;
1672c2c66affSColin Finck             prc = &rc;
1673c2c66affSColin Finck         }
1674c2c66affSColin Finck 
1675c2c66affSColin Finck         return This->dst_format->copy_function(This, prc, cbStride, cbBufferSize,
1676c2c66affSColin Finck             pbBuffer, This->src_format->format);
1677c2c66affSColin Finck     }
1678c2c66affSColin Finck     else
1679ae80686dSAmine Khaldi         return WINCODEC_ERR_WRONGSTATE;
1680c2c66affSColin Finck }
1681c2c66affSColin Finck 
FormatConverter_Initialize(IWICFormatConverter * iface,IWICBitmapSource * source,REFWICPixelFormatGUID dstFormat,WICBitmapDitherType dither,IWICPalette * palette,double alpha_threshold,WICBitmapPaletteType palette_type)1682c2c66affSColin Finck static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface,
1683ae80686dSAmine Khaldi     IWICBitmapSource *source, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither,
1684ae80686dSAmine Khaldi     IWICPalette *palette, double alpha_threshold, WICBitmapPaletteType palette_type)
1685c2c66affSColin Finck {
1686c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1687c2c66affSColin Finck     const struct pixelformatinfo *srcinfo, *dstinfo;
1688c2c66affSColin Finck     GUID srcFormat;
1689ae80686dSAmine Khaldi     HRESULT res;
1690c2c66affSColin Finck 
1691ae80686dSAmine Khaldi     TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat),
1692ae80686dSAmine Khaldi         dither, palette, alpha_threshold, palette_type);
1693c2c66affSColin Finck 
1694ae80686dSAmine Khaldi     if (!palette)
1695ae80686dSAmine Khaldi     {
1696ae80686dSAmine Khaldi         UINT bpp;
1697ae80686dSAmine Khaldi         res = get_pixelformat_bpp(dstFormat, &bpp);
1698ae80686dSAmine Khaldi         if (res != S_OK) return res;
1699ae80686dSAmine Khaldi 
1700ae80686dSAmine Khaldi         res = PaletteImpl_Create(&palette);
1701ae80686dSAmine Khaldi         if (res != S_OK) return res;
1702ae80686dSAmine Khaldi 
1703ae80686dSAmine Khaldi         switch (palette_type)
1704ae80686dSAmine Khaldi         {
1705ae80686dSAmine Khaldi         case WICBitmapPaletteTypeCustom:
1706ae80686dSAmine Khaldi             IWICPalette_Release(palette);
1707ae80686dSAmine Khaldi             palette = NULL;
1708ae80686dSAmine Khaldi             if (bpp <= 8) return E_INVALIDARG;
1709ae80686dSAmine Khaldi             break;
1710ae80686dSAmine Khaldi 
1711ae80686dSAmine Khaldi         case WICBitmapPaletteTypeMedianCut:
1712ae80686dSAmine Khaldi         {
1713ae80686dSAmine Khaldi             if (bpp <= 8)
1714ae80686dSAmine Khaldi                 res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE);
1715ae80686dSAmine Khaldi             break;
1716ae80686dSAmine Khaldi         }
1717ae80686dSAmine Khaldi 
1718ae80686dSAmine Khaldi         default:
1719ae80686dSAmine Khaldi             if (bpp <= 8)
1720ae80686dSAmine Khaldi                 res = IWICPalette_InitializePredefined(palette, palette_type, FALSE);
1721ae80686dSAmine Khaldi             break;
1722ae80686dSAmine Khaldi         }
1723ae80686dSAmine Khaldi 
1724ae80686dSAmine Khaldi         if (res != S_OK)
1725ae80686dSAmine Khaldi         {
1726ae80686dSAmine Khaldi             IWICPalette_Release(palette);
1727ae80686dSAmine Khaldi             return res;
1728ae80686dSAmine Khaldi         }
1729ae80686dSAmine Khaldi     }
1730ae80686dSAmine Khaldi     else
1731ae80686dSAmine Khaldi         IWICPalette_AddRef(palette);
1732c2c66affSColin Finck 
1733c2c66affSColin Finck     EnterCriticalSection(&This->lock);
1734c2c66affSColin Finck 
1735c2c66affSColin Finck     if (This->source)
1736c2c66affSColin Finck     {
1737c2c66affSColin Finck         res = WINCODEC_ERR_WRONGSTATE;
1738c2c66affSColin Finck         goto end;
1739c2c66affSColin Finck     }
1740c2c66affSColin Finck 
1741ae80686dSAmine Khaldi     res = IWICBitmapSource_GetPixelFormat(source, &srcFormat);
1742c2c66affSColin Finck     if (FAILED(res)) goto end;
1743c2c66affSColin Finck 
1744c2c66affSColin Finck     srcinfo = get_formatinfo(&srcFormat);
1745c2c66affSColin Finck     if (!srcinfo)
1746c2c66affSColin Finck     {
1747c2c66affSColin Finck         res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1748c2c66affSColin Finck         FIXME("Unsupported source format %s\n", debugstr_guid(&srcFormat));
1749c2c66affSColin Finck         goto end;
1750c2c66affSColin Finck     }
1751c2c66affSColin Finck 
1752c2c66affSColin Finck     dstinfo = get_formatinfo(dstFormat);
1753c2c66affSColin Finck     if (!dstinfo)
1754c2c66affSColin Finck     {
1755c2c66affSColin Finck         res = WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1756c2c66affSColin Finck         FIXME("Unsupported destination format %s\n", debugstr_guid(dstFormat));
1757c2c66affSColin Finck         goto end;
1758c2c66affSColin Finck     }
1759c2c66affSColin Finck 
1760c2c66affSColin Finck     if (dstinfo->copy_function)
1761c2c66affSColin Finck     {
1762ae80686dSAmine Khaldi         IWICBitmapSource_AddRef(source);
1763c2c66affSColin Finck         This->src_format = srcinfo;
1764c2c66affSColin Finck         This->dst_format = dstinfo;
1765c2c66affSColin Finck         This->dither = dither;
1766ae80686dSAmine Khaldi         This->alpha_threshold = alpha_threshold;
1767ae80686dSAmine Khaldi         This->palette = palette;
1768ae80686dSAmine Khaldi         This->source = source;
1769c2c66affSColin Finck     }
1770c2c66affSColin Finck     else
1771c2c66affSColin Finck     {
1772c2c66affSColin Finck         FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(&srcFormat), debugstr_guid(dstFormat));
1773c2c66affSColin Finck         res = WINCODEC_ERR_UNSUPPORTEDOPERATION;
1774c2c66affSColin Finck     }
1775c2c66affSColin Finck 
1776c2c66affSColin Finck end:
1777c2c66affSColin Finck 
1778c2c66affSColin Finck     LeaveCriticalSection(&This->lock);
1779c2c66affSColin Finck 
1780ae80686dSAmine Khaldi     if (res != S_OK && palette)
1781ae80686dSAmine Khaldi         IWICPalette_Release(palette);
1782ae80686dSAmine Khaldi 
1783c2c66affSColin Finck     return res;
1784c2c66affSColin Finck }
1785c2c66affSColin Finck 
FormatConverter_CanConvert(IWICFormatConverter * iface,REFWICPixelFormatGUID srcPixelFormat,REFWICPixelFormatGUID dstPixelFormat,BOOL * pfCanConvert)1786c2c66affSColin Finck static HRESULT WINAPI FormatConverter_CanConvert(IWICFormatConverter *iface,
1787c2c66affSColin Finck     REFWICPixelFormatGUID srcPixelFormat, REFWICPixelFormatGUID dstPixelFormat,
1788c2c66affSColin Finck     BOOL *pfCanConvert)
1789c2c66affSColin Finck {
1790c2c66affSColin Finck     FormatConverter *This = impl_from_IWICFormatConverter(iface);
1791c2c66affSColin Finck     const struct pixelformatinfo *srcinfo, *dstinfo;
1792c2c66affSColin Finck 
1793c2c66affSColin Finck     TRACE("(%p,%s,%s,%p)\n", iface, debugstr_guid(srcPixelFormat),
1794c2c66affSColin Finck         debugstr_guid(dstPixelFormat), pfCanConvert);
1795c2c66affSColin Finck 
1796c2c66affSColin Finck     srcinfo = get_formatinfo(srcPixelFormat);
1797c2c66affSColin Finck     if (!srcinfo)
1798c2c66affSColin Finck     {
1799c2c66affSColin Finck         FIXME("Unsupported source format %s\n", debugstr_guid(srcPixelFormat));
1800c2c66affSColin Finck         return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1801c2c66affSColin Finck     }
1802c2c66affSColin Finck 
1803c2c66affSColin Finck     dstinfo = get_formatinfo(dstPixelFormat);
1804c2c66affSColin Finck     if (!dstinfo)
1805c2c66affSColin Finck     {
1806c2c66affSColin Finck         FIXME("Unsupported destination format %s\n", debugstr_guid(dstPixelFormat));
1807c2c66affSColin Finck         return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
1808c2c66affSColin Finck     }
1809c2c66affSColin Finck 
1810c2c66affSColin Finck     if (dstinfo->copy_function &&
1811c2c66affSColin Finck         SUCCEEDED(dstinfo->copy_function(This, NULL, 0, 0, NULL, dstinfo->format)))
1812c2c66affSColin Finck         *pfCanConvert = TRUE;
1813c2c66affSColin Finck     else
1814c2c66affSColin Finck     {
1815c2c66affSColin Finck         FIXME("Unsupported conversion %s -> %s\n", debugstr_guid(srcPixelFormat), debugstr_guid(dstPixelFormat));
1816c2c66affSColin Finck         *pfCanConvert = FALSE;
1817c2c66affSColin Finck     }
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     return S_OK;
1820c2c66affSColin Finck }
1821c2c66affSColin Finck 
1822c2c66affSColin Finck static const IWICFormatConverterVtbl FormatConverter_Vtbl = {
1823c2c66affSColin Finck     FormatConverter_QueryInterface,
1824c2c66affSColin Finck     FormatConverter_AddRef,
1825c2c66affSColin Finck     FormatConverter_Release,
1826c2c66affSColin Finck     FormatConverter_GetSize,
1827c2c66affSColin Finck     FormatConverter_GetPixelFormat,
1828c2c66affSColin Finck     FormatConverter_GetResolution,
1829c2c66affSColin Finck     FormatConverter_CopyPalette,
1830c2c66affSColin Finck     FormatConverter_CopyPixels,
1831c2c66affSColin Finck     FormatConverter_Initialize,
1832c2c66affSColin Finck     FormatConverter_CanConvert
1833c2c66affSColin Finck };
1834c2c66affSColin Finck 
FormatConverter_CreateInstance(REFIID iid,void ** ppv)1835c2c66affSColin Finck HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv)
1836c2c66affSColin Finck {
1837c2c66affSColin Finck     FormatConverter *This;
1838c2c66affSColin Finck     HRESULT ret;
1839c2c66affSColin Finck 
1840c2c66affSColin Finck     TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1841c2c66affSColin Finck 
1842c2c66affSColin Finck     *ppv = NULL;
1843c2c66affSColin Finck 
1844c2c66affSColin Finck     This = HeapAlloc(GetProcessHeap(), 0, sizeof(FormatConverter));
1845c2c66affSColin Finck     if (!This) return E_OUTOFMEMORY;
1846c2c66affSColin Finck 
1847c2c66affSColin Finck     This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl;
1848c2c66affSColin Finck     This->ref = 1;
1849c2c66affSColin Finck     This->source = NULL;
1850ae80686dSAmine Khaldi     This->palette = NULL;
1851c2c66affSColin Finck     InitializeCriticalSection(&This->lock);
1852c2c66affSColin Finck     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock");
1853c2c66affSColin Finck 
1854c2c66affSColin Finck     ret = IWICFormatConverter_QueryInterface(&This->IWICFormatConverter_iface, iid, ppv);
1855c2c66affSColin Finck     IWICFormatConverter_Release(&This->IWICFormatConverter_iface);
1856c2c66affSColin Finck 
1857c2c66affSColin Finck     return ret;
1858c2c66affSColin Finck }
1859