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