8682f8706192204b8091ac69f66c1e716d8e41c3
[reactos.git] / modules / rostests / winetests / windowscodecs / converter.c
1 /*
2 * Copyright 2009 Vincent Povirk
3 * Copyright 2016 Dmitry Timoshkov
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <math.h>
23
24 #define COBJMACROS
25 #define CONST_VTABLE
26
27 #include "windef.h"
28 #include "objbase.h"
29 #include "wincodec.h"
30 #include "wincodecsdk.h"
31 #include "wine/test.h"
32
33 static IWICImagingFactory *factory;
34
35 typedef struct bitmap_data {
36 const WICPixelFormatGUID *format;
37 UINT bpp;
38 const BYTE *bits;
39 UINT width;
40 UINT height;
41 double xres;
42 double yres;
43 const struct bitmap_data *alt_data;
44 } bitmap_data;
45
46 typedef struct BitmapTestSrc {
47 IWICBitmapSource IWICBitmapSource_iface;
48 LONG ref;
49 const bitmap_data *data;
50 } BitmapTestSrc;
51
52 extern HRESULT STDMETHODCALLTYPE IWICBitmapFrameEncode_WriteSource_Proxy(IWICBitmapFrameEncode* This,
53 IWICBitmapSource *pIBitmapSource, WICRect *prc);
54
55 static BOOL near_equal(float a, float b)
56 {
57 return fabsf(a - b) < 0.001;
58 }
59
60 static inline BitmapTestSrc *impl_from_IWICBitmapSource(IWICBitmapSource *iface)
61 {
62 return CONTAINING_RECORD(iface, BitmapTestSrc, IWICBitmapSource_iface);
63 }
64
65 static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid,
66 void **ppv)
67 {
68 if (!ppv) return E_INVALIDARG;
69
70 if (IsEqualIID(&IID_IUnknown, iid) ||
71 IsEqualIID(&IID_IWICBitmapSource, iid))
72 *ppv = iface;
73 else
74 return E_NOINTERFACE;
75
76 IUnknown_AddRef((IUnknown*)*ppv);
77 return S_OK;
78 }
79
80 static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface)
81 {
82 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
83 ULONG ref = InterlockedIncrement(&This->ref);
84 return ref;
85 }
86
87 static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface)
88 {
89 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
90 ULONG ref = InterlockedDecrement(&This->ref);
91 return ref;
92 }
93
94 static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface,
95 UINT *puiWidth, UINT *puiHeight)
96 {
97 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
98 *puiWidth = This->data->width;
99 *puiHeight = This->data->height;
100 return S_OK;
101 }
102
103 static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface,
104 WICPixelFormatGUID *pPixelFormat)
105 {
106 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
107 memcpy(pPixelFormat, This->data->format, sizeof(GUID));
108 return S_OK;
109 }
110
111 static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface,
112 double *pDpiX, double *pDpiY)
113 {
114 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
115 *pDpiX = This->data->xres;
116 *pDpiY = This->data->yres;
117 return S_OK;
118 }
119
120 static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface,
121 IWICPalette *palette)
122 {
123 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
124
125 if (IsEqualGUID(This->data->format, &GUID_WICPixelFormat1bppIndexed) ||
126 IsEqualGUID(This->data->format, &GUID_WICPixelFormat2bppIndexed) ||
127 IsEqualGUID(This->data->format, &GUID_WICPixelFormat4bppIndexed) ||
128 IsEqualGUID(This->data->format, &GUID_WICPixelFormat8bppIndexed))
129 {
130 WICColor colors[8];
131
132 colors[0] = 0xff0000ff;
133 colors[1] = 0xff00ff00;
134 colors[2] = 0xffff0000;
135 colors[3] = 0xff000000;
136 colors[4] = 0xffffff00;
137 colors[5] = 0xffff00ff;
138 colors[6] = 0xff00ffff;
139 colors[7] = 0xffffffff;
140 return IWICPalette_InitializeCustom(palette, colors, 8);
141 }
142
143 /* unique error marker */
144 return 0xdeadbeef;
145 }
146
147 static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface,
148 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
149 {
150 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
151 UINT bytesperrow;
152 UINT srcstride;
153 UINT row_offset;
154 WICRect rc;
155
156 if (!prc)
157 {
158 rc.X = 0;
159 rc.Y = 0;
160 rc.Width = This->data->width;
161 rc.Height = This->data->height;
162 prc = &rc;
163 }
164 else
165 {
166 if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->data->width || prc->Y+prc->Height > This->data->height)
167 return E_INVALIDARG;
168 }
169
170 bytesperrow = ((This->data->bpp * prc->Width)+7)/8;
171 srcstride = ((This->data->bpp * This->data->width)+7)/8;
172
173 if (cbStride < bytesperrow)
174 return E_INVALIDARG;
175
176 if ((cbStride * prc->Height) > cbBufferSize)
177 return E_INVALIDARG;
178
179 row_offset = prc->X * This->data->bpp;
180
181 if (row_offset % 8 == 0)
182 {
183 UINT row;
184 const BYTE *src;
185 BYTE *dst;
186
187 src = This->data->bits + (row_offset / 8) + prc->Y * srcstride;
188 dst = pbBuffer;
189 for (row=0; row < prc->Height; row++)
190 {
191 memcpy(dst, src, bytesperrow);
192 src += srcstride;
193 dst += cbStride;
194 }
195 return S_OK;
196 }
197 else
198 {
199 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface);
200 return E_FAIL;
201 }
202 }
203
204 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl = {
205 BitmapTestSrc_QueryInterface,
206 BitmapTestSrc_AddRef,
207 BitmapTestSrc_Release,
208 BitmapTestSrc_GetSize,
209 BitmapTestSrc_GetPixelFormat,
210 BitmapTestSrc_GetResolution,
211 BitmapTestSrc_CopyPalette,
212 BitmapTestSrc_CopyPixels
213 };
214
215 static void CreateTestBitmap(const bitmap_data *data, BitmapTestSrc **This)
216 {
217 *This = HeapAlloc(GetProcessHeap(), 0, sizeof(**This));
218
219 if (*This)
220 {
221 (*This)->IWICBitmapSource_iface.lpVtbl = &BitmapTestSrc_Vtbl;
222 (*This)->ref = 1;
223 (*This)->data = data;
224 }
225 }
226
227 static void DeleteTestBitmap(BitmapTestSrc *This)
228 {
229 ok(This->IWICBitmapSource_iface.lpVtbl == &BitmapTestSrc_Vtbl, "test bitmap %p deleted with incorrect vtable\n", This);
230 ok(This->ref == 1, "test bitmap %p deleted with %i references instead of 1\n", This, This->ref);
231 HeapFree(GetProcessHeap(), 0, This);
232 }
233
234 static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, const BYTE *converted_bits)
235 {
236 BOOL equal;
237
238 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
239 {
240 /* ignore the padding byte when comparing data */
241 UINT i;
242 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits;
243 equal=TRUE;
244 for (i=0; i<(buffersize/4); i++)
245 if ((a[i]&0xffffff) != (b[i]&0xffffff))
246 {
247 equal = FALSE;
248 break;
249 }
250 }
251 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppGrayFloat))
252 {
253 UINT i;
254 const float *a=(const float*)expect->bits, *b=(const float*)converted_bits;
255 equal=TRUE;
256 for (i=0; i<(buffersize/4); i++)
257 if (!near_equal(a[i], b[i]))
258 {
259 equal = FALSE;
260 break;
261 }
262 }
263 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormatBlackWhite) ||
264 IsEqualGUID(expect->format, &GUID_WICPixelFormat1bppIndexed))
265 {
266 UINT i;
267 const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits;
268 equal=TRUE;
269 for (i=0; i<buffersize; i++)
270 if (a[i] != b[i] && b[i] != 0xff /* BMP encoder B&W */)
271 {
272 equal = FALSE;
273 break;
274 }
275 }
276 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat2bppIndexed) ||
277 IsEqualGUID(expect->format, &GUID_WICPixelFormat4bppIndexed) ||
278 IsEqualGUID(expect->format, &GUID_WICPixelFormat8bppIndexed))
279 {
280 UINT i;
281 const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits;
282 equal=TRUE;
283
284 for (i=0; i<buffersize; i++)
285 if (a[i] != b[i])
286 {
287 equal = FALSE;
288 break;
289 }
290 }
291 else
292 equal = (memcmp(expect->bits, converted_bits, buffersize) == 0);
293
294 if (!equal && expect->alt_data)
295 equal = compare_bits(expect->alt_data, buffersize, converted_bits);
296
297 if (!equal && winetest_debug > 1)
298 {
299 UINT i, bps;
300 bps = expect->bpp / 8;
301 if (!bps) bps = buffersize;
302 printf("converted_bits (%u bytes):\n ", buffersize);
303 for (i = 0; i < buffersize; i++)
304 {
305 printf("%u,", converted_bits[i]);
306 if (!((i + 1) % 32)) printf("\n ");
307 else if (!((i+1) % bps)) printf(" ");
308 }
309 printf("\n");
310 }
311
312 return equal;
313 }
314
315 static BOOL is_indexed_format(const GUID *format)
316 {
317 if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed) ||
318 IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed) ||
319 IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed) ||
320 IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
321 return TRUE;
322
323 return FALSE;
324 }
325
326 static void compare_bitmap_data(const struct bitmap_data *src, const struct bitmap_data *expect,
327 IWICBitmapSource *source, const char *name)
328 {
329 BYTE *converted_bits;
330 UINT width, height;
331 double xres, yres;
332 WICRect prc;
333 UINT stride, buffersize;
334 GUID dst_pixelformat;
335 HRESULT hr;
336
337 hr = IWICBitmapSource_GetSize(source, &width, &height);
338 ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr);
339 ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name);
340 ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name);
341
342 hr = IWICBitmapSource_GetResolution(source, &xres, &yres);
343 ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr);
344 ok(fabs(xres - expect->xres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name);
345 ok(fabs(yres - expect->yres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name);
346
347 hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat);
348 ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr);
349 ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format %s (%s)\n", wine_dbgstr_guid(&dst_pixelformat), name);
350
351 prc.X = 0;
352 prc.Y = 0;
353 prc.Width = expect->width;
354 prc.Height = expect->height;
355
356 stride = (expect->bpp * expect->width + 7) / 8;
357 buffersize = stride * expect->height;
358
359 converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
360 memset(converted_bits, 0xaa, buffersize);
361 hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits);
362 ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr);
363
364 /* The result of conversion of color to indexed formats depends on
365 * optimized palette generation implementation. We either need to
366 * assign our own palette, or just skip the comparison.
367 */
368 if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format)))
369 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name);
370
371 /* Test with NULL rectangle - should copy the whole bitmap */
372 memset(converted_bits, 0xaa, buffersize);
373 hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits);
374 ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr);
375 /* see comment above */
376 if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format)))
377 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name);
378
379 HeapFree(GetProcessHeap(), 0, converted_bits);
380 }
381
382 /* some encoders (like BMP) require data to be 4-bytes aligned */
383 static const BYTE bits_1bpp[] = {
384 0x55,0x55,0x55,0x55, /*01010101*/
385 0xaa,0xaa,0xaa,0xaa}; /*10101010*/
386 static const struct bitmap_data testdata_BlackWhite = {
387 &GUID_WICPixelFormatBlackWhite, 1, bits_1bpp, 32, 2, 96.0, 96.0};
388 static const struct bitmap_data testdata_1bppIndexed = {
389 &GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0};
390
391 /* some encoders (like BMP) require data to be 4-bytes aligned */
392 static const BYTE bits_2bpp[] = {
393 0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,
394 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24};
395 static const struct bitmap_data testdata_2bppIndexed = {
396 &GUID_WICPixelFormat2bppIndexed, 2, bits_2bpp, 32, 2, 96.0, 96.0};
397
398 /* some encoders (like BMP) require data to be 4-bytes aligned */
399 static const BYTE bits_4bpp[] = {
400 0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,
401 0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67};
402
403 static const struct bitmap_data testdata_4bppIndexed = {
404 &GUID_WICPixelFormat4bppIndexed, 4, bits_4bpp, 32, 2, 96.0, 96.0};
405
406 static const BYTE bits_8bpp_BW[] = {
407 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,
408 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0};
409 static const struct bitmap_data testdata_8bppIndexed_BW = {
410 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_BW, 32, 2, 96.0, 96.0};
411
412 static const BYTE bits_8bpp_4colors[] = {
413 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,
414 3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3};
415 static const struct bitmap_data testdata_8bppIndexed_4colors = {
416 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_4colors, 32, 2, 96.0, 96.0};
417
418 static const BYTE bits_8bpp[] = {
419 0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,
420 4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7};
421 static const struct bitmap_data testdata_8bppIndexed = {
422 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 32, 2, 96.0, 96.0};
423
424 static const BYTE bits_24bppBGR[] = {
425 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
426 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
427 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
428 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
429 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255,
430 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255,
431 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255,
432 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255};
433 static const struct bitmap_data testdata_24bppBGR = {
434 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 32, 2, 96.0, 96.0};
435
436 static const BYTE bits_24bppRGB[] = {
437 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
438 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
439 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
440 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
441 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255,
442 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255,
443 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255,
444 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255 };
445 static const struct bitmap_data testdata_24bppRGB = {
446 &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 32, 2, 96.0, 96.0};
447
448 static const BYTE bits_32bppBGR[] = {
449 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
450 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
451 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
452 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
453 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80,
454 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80,
455 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80,
456 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
457 static const struct bitmap_data testdata_32bppBGR = {
458 &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 32, 2, 96.0, 96.0};
459 static const struct bitmap_data testdata_32bppBGRA80 = {
460 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGR, 32, 2, 96.0, 96.0};
461 static const struct bitmap_data testdata_32bppRGBA80 = {
462 &GUID_WICPixelFormat32bppRGBA, 32, bits_32bppBGR, 32, 2, 96.0, 96.0};
463
464 static const BYTE bits_32bppBGRA[] = {
465 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
466 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
467 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
468 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
469 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255,
470 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255,
471 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255,
472 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
473 static const struct bitmap_data testdata_32bppBGRA = {
474 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0};
475 static const struct bitmap_data testdata_32bppRGBA = {
476 &GUID_WICPixelFormat32bppRGBA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0};
477 static const struct bitmap_data testdata_32bppRGB = {
478 &GUID_WICPixelFormat32bppRGB, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0};
479
480 static const BYTE bits_32bppPBGRA[] = {
481 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80,
482 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80,
483 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80,
484 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80,
485 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80,
486 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80,
487 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80,
488 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80};
489 static const struct bitmap_data testdata_32bppPBGRA = {
490 &GUID_WICPixelFormat32bppPBGRA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0};
491 static const struct bitmap_data testdata_32bppPRGBA = {
492 &GUID_WICPixelFormat32bppPRGBA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0};
493
494 /* XP and 2003 use linear color conversion, later versions use sRGB gamma */
495 static const float bits_32bppGrayFloat_xp[] = {
496 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
497 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
498 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
499 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
500 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f,
501 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f,
502 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f,
503 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f};
504 static const struct bitmap_data testdata_32bppGrayFloat_xp = {
505 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat_xp, 32, 2, 96.0, 96.0};
506
507 static const float bits_32bppGrayFloat[] = {
508 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
509 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
510 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
511 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
512 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f,
513 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f,
514 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f,
515 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f};
516 static const struct bitmap_data testdata_32bppGrayFloat = {
517 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 32, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp};
518
519 static const BYTE bits_8bppGray_xp[] = {
520 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0,
521 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0,
522 226,105,179,255,226,105,179,255,226,105,179,255,226,105,179,255,
523 226,105,179,255,226,105,179,255,226,105,179,255,226,105,179,255};
524 static const struct bitmap_data testdata_8bppGray_xp = {
525 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray_xp, 32, 2, 96.0, 96.0};
526
527 static const BYTE bits_8bppGray[] = {
528 76,220,127,0,76,220,127,0,76,220,127,0,76,220,127,0,
529 76,220,127,0,76,220,127,0,76,220,127,0,76,220,127,0,
530 247,145,230,255,247,145,230,255,247,145,230,255,247,145,230,255,
531 247,145,230,255,247,145,230,255,247,145,230,255,247,145,230,255};
532 static const struct bitmap_data testdata_8bppGray = {
533 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray, 32, 2, 96.0, 96.0, &testdata_8bppGray_xp};
534
535 static const BYTE bits_24bppBGR_gray[] = {
536 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
537 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
538 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
539 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
540 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255,
541 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255,
542 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255,
543 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255};
544 static const struct bitmap_data testdata_24bppBGR_gray = {
545 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_gray, 32, 2, 96.0, 96.0};
546
547 static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo)
548 {
549 BitmapTestSrc *src_obj;
550 IWICBitmapSource *dst_bitmap;
551 HRESULT hr;
552
553 CreateTestBitmap(src, &src_obj);
554
555 hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
556 todo_wine_if (todo)
557 ok(hr == S_OK ||
558 broken(hr == E_INVALIDARG || hr == WINCODEC_ERR_COMPONENTNOTFOUND) /* XP */, "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
559
560 if (hr == S_OK)
561 {
562 compare_bitmap_data(src, dst, dst_bitmap, name);
563
564 IWICBitmapSource_Release(dst_bitmap);
565 }
566
567 DeleteTestBitmap(src_obj);
568 }
569
570 static void test_invalid_conversion(void)
571 {
572 BitmapTestSrc *src_obj;
573 IWICBitmapSource *dst_bitmap;
574 HRESULT hr;
575
576 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
577
578 /* convert to a non-pixel-format GUID */
579 hr = WICConvertBitmapSource(&GUID_VendorMicrosoft, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
580 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "WICConvertBitmapSource returned %x\n", hr);
581
582 DeleteTestBitmap(src_obj);
583 }
584
585 static void test_default_converter(void)
586 {
587 BitmapTestSrc *src_obj;
588 IWICFormatConverter *converter;
589 BOOL can_convert = TRUE;
590 HRESULT hr;
591
592 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
593
594 hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER,
595 &IID_IWICFormatConverter, (void**)&converter);
596 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
597 if (SUCCEEDED(hr))
598 {
599 hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA,
600 &GUID_WICPixelFormat32bppBGR, &can_convert);
601 ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr);
602 ok(can_convert, "expected TRUE, got %i\n", can_convert);
603
604 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
605 &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.0,
606 WICBitmapPaletteTypeCustom);
607 ok(SUCCEEDED(hr), "Initialize returned %x\n", hr);
608
609 if (SUCCEEDED(hr))
610 compare_bitmap_data(&testdata_32bppBGRA, &testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter");
611
612 IWICFormatConverter_Release(converter);
613 }
614
615 DeleteTestBitmap(src_obj);
616 }
617
618 typedef struct property_opt_test_data
619 {
620 LPCOLESTR name;
621 VARTYPE var_type;
622 VARTYPE initial_var_type;
623 int i_init_val;
624 float f_init_val;
625 BOOL skippable;
626 } property_opt_test_data;
627
628 static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0};
629 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
630 static const WCHAR wszInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
631 static const WCHAR wszFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
632 static const WCHAR wszImageQuality[] = {'I','m','a','g','e','Q','u','a','l','i','t','y',0};
633 static const WCHAR wszBitmapTransform[] = {'B','i','t','m','a','p','T','r','a','n','s','f','o','r','m',0};
634 static const WCHAR wszLuminance[] = {'L','u','m','i','n','a','n','c','e',0};
635 static const WCHAR wszChrominance[] = {'C','h','r','o','m','i','n','a','n','c','e',0};
636 static const WCHAR wszJpegYCrCbSubsampling[] = {'J','p','e','g','Y','C','r','C','b','S','u','b','s','a','m','p','l','i','n','g',0};
637 static const WCHAR wszSuppressApp0[] = {'S','u','p','p','r','e','s','s','A','p','p','0',0};
638 static const WCHAR wszEnableV5Header32bppBGRA[] = {'E','n','a','b','l','e','V','5','H','e','a','d','e','r','3','2','b','p','p','B','G','R','A',0};
639
640 static const struct property_opt_test_data testdata_tiff_props[] = {
641 { wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare },
642 { wszCompressionQuality, VT_R4, VT_EMPTY },
643 { NULL }
644 };
645
646 static const struct property_opt_test_data testdata_png_props[] = {
647 { wszInterlaceOption, VT_BOOL, VT_BOOL, 0 },
648 { wszFilterOption, VT_UI1, VT_UI1, WICPngFilterUnspecified, 0.0f, TRUE /* not supported on XP/2k3 */},
649 { NULL }
650 };
651
652 static const struct property_opt_test_data testdata_jpeg_props[] = {
653 { wszImageQuality, VT_R4, VT_EMPTY },
654 { wszBitmapTransform, VT_UI1, VT_UI1, WICBitmapTransformRotate0 },
655 { wszLuminance, VT_I4|VT_ARRAY, VT_EMPTY },
656 { wszChrominance, VT_I4|VT_ARRAY, VT_EMPTY },
657 { wszJpegYCrCbSubsampling, VT_UI1, VT_UI1, WICJpegYCrCbSubsamplingDefault, 0.0f, TRUE }, /* not supported on XP/2k3 */
658 { wszSuppressApp0, VT_BOOL, VT_BOOL, FALSE },
659 { NULL }
660 };
661
662 static const struct property_opt_test_data testdata_bmp_props[] = {
663 { wszEnableV5Header32bppBGRA, VT_BOOL, VT_BOOL, VARIANT_FALSE, 0.0f, TRUE }, /* Supported since Win7 */
664 { NULL }
665 };
666
667 static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt)
668 {
669 int i;
670 for (i=0; i < all_prop_cnt; i++)
671 {
672 if (lstrcmpW(name, all_props[i].pstrName) == 0)
673 return i;
674 }
675 return -1;
676 }
677
678 static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt)
679 {
680 HRESULT hr;
681 int i = 0;
682 VARIANT pvarValue;
683 HRESULT phrError = S_OK;
684
685 while (data[i].name)
686 {
687 int idx = find_property_index(data[i].name, all_props, all_prop_cnt);
688 PROPBAG2 pb = {0};
689 pb.pstrName = (LPOLESTR)data[i].name;
690
691 hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError);
692
693 if (data[i].skippable && idx == -1)
694 {
695 win_skip("Property %s is not supported on this machine.\n", wine_dbgstr_w(data[i].name));
696 i++;
697 continue;
698 }
699
700 ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n",
701 wine_dbgstr_w(data[i].name));
702 if (idx >= 0)
703 {
704 ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n",
705 wine_dbgstr_w(data[i].name), all_props[idx].vt);
706 ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n",
707 wine_dbgstr_w(data[i].name), all_props[idx].dwType);
708 ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n",
709 wine_dbgstr_w(data[i].name), all_props[idx].cfType);
710 }
711
712 ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n",
713 wine_dbgstr_w(data[i].name), hr);
714
715 if (SUCCEEDED(hr))
716 {
717 /* On XP the initial type is always VT_EMPTY */
718 ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY,
719 "Property %s has unexpected initial type, V_VT=%i\n",
720 wine_dbgstr_w(data[i].name), V_VT(&pvarValue));
721
722 if(V_VT(&pvarValue) == data[i].initial_var_type)
723 {
724 switch (data[i].initial_var_type)
725 {
726 case VT_BOOL:
727 case VT_UI1:
728 ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n",
729 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal));
730 break;
731 case VT_R4:
732 ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n",
733 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal));
734 break;
735 default:
736 break;
737 }
738 }
739
740 VariantClear(&pvarValue);
741 }
742
743 i++;
744 }
745 }
746
747 static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *options)
748 {
749 HRESULT hr;
750 ULONG cProperties = 0;
751 ULONG cProperties2 = 0;
752 PROPBAG2 all_props[64] = {{0}}; /* Should be enough for every encoder out there */
753 int i;
754
755 /* CountProperties */
756 {
757 hr = IPropertyBag2_CountProperties(options, &cProperties);
758 ok(SUCCEEDED(hr), "Reading property count, hr=%x\n", hr);
759 }
760
761 /* GetPropertyInfo */
762 {
763 hr = IPropertyBag2_GetPropertyInfo(options, cProperties, 1, all_props, &cProperties2);
764 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - iProperty out of bounce handled wrong, hr=%x\n", hr);
765
766 hr = IPropertyBag2_GetPropertyInfo(options, 0, cProperties+1, all_props, &cProperties2);
767 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - cProperty out of bounce handled wrong, hr=%x\n", hr);
768
769 if (cProperties == 0) /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */
770 {
771 cProperties2 = cProperties;
772 hr = S_OK;
773 }
774 else
775 {
776 hr = IPropertyBag2_GetPropertyInfo(options, 0, min(64, cProperties), all_props, &cProperties2);
777 ok(SUCCEEDED(hr), "Reading infos from property bag failed, hr=%x\n", hr);
778 }
779
780 if (FAILED(hr))
781 return;
782
783 ok(cProperties == cProperties2, "Mismatch of property count (IPropertyBag2::CountProperties=%i, IPropertyBag2::GetPropertyInfo=%i)\n",
784 (int)cProperties, (int)cProperties2);
785 }
786
787 if (IsEqualCLSID(clsid_encoder, &CLSID_WICTiffEncoder))
788 test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2);
789 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICPngEncoder))
790 test_specific_encoder_properties(options, testdata_png_props, all_props, cProperties2);
791 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICJpegEncoder))
792 test_specific_encoder_properties(options, testdata_jpeg_props, all_props, cProperties2);
793 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICBmpEncoder))
794 test_specific_encoder_properties(options, testdata_bmp_props, all_props, cProperties2);
795
796 for (i=0; i < cProperties2; i++)
797 {
798 ok(all_props[i].pstrName != NULL, "Unset property name in output of IPropertyBag2::GetPropertyInfo\n");
799 CoTaskMemFree(all_props[i].pstrName);
800 }
801 }
802
803 static void load_stream(IUnknown *reader, IStream *stream)
804 {
805 HRESULT hr;
806 IWICPersistStream *persist;
807 #ifdef WORDS_BIGENDIAN
808 DWORD persist_options = WICPersistOptionBigEndian;
809 #else
810 DWORD persist_options = WICPersistOptionLittleEndian;
811 #endif
812
813 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
814 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
815
816 hr = IWICPersistStream_LoadEx(persist, stream, NULL, persist_options);
817 ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
818
819 IWICPersistStream_Release(persist);
820 }
821
822 static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
823 {
824 HRESULT hr;
825 IWICMetadataReader *reader;
826 PROPVARIANT id, value;
827 struct
828 {
829 USHORT byte_order;
830 USHORT version;
831 ULONG dir_offset;
832 } tiff;
833 LARGE_INTEGER pos;
834 UINT count, i;
835 int width, height, bps, photo, samples, colormap;
836 struct
837 {
838 int id, *value;
839 } tag[] =
840 {
841 { 0x100, &width }, { 0x101, &height }, { 0x102, &bps },
842 { 0x106, &photo }, { 0x115, &samples }, { 0x140, &colormap }
843 };
844
845 memset(&tiff, 0, sizeof(tiff));
846 hr = IStream_Read(stream, &tiff, sizeof(tiff), NULL);
847 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
848 ok(tiff.byte_order == MAKEWORD('I','I') || tiff.byte_order == MAKEWORD('M','M'),
849 "wrong TIFF byte order mark %02x\n", tiff.byte_order);
850 ok(tiff.version == 42, "wrong TIFF version %u\n", tiff.version);
851
852 pos.QuadPart = tiff.dir_offset;
853 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
854 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
855
856 hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
857 &IID_IWICMetadataReader, (void **)&reader);
858 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
859
860 load_stream((IUnknown *)reader, stream);
861
862 hr = IWICMetadataReader_GetCount(reader, &count);
863 ok(hr == S_OK, "GetCount error %#x\n", hr);
864 ok(count != 0, "wrong count %u\n", count);
865
866 for (i = 0; i < sizeof(tag)/sizeof(tag[0]); i++)
867 {
868 PropVariantInit(&id);
869 PropVariantInit(&value);
870
871 id.vt = VT_UI2;
872 U(id).uiVal = tag[i].id;
873 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
874 ok(hr == S_OK || (tag[i].id == 0x140 && hr == WINCODEC_ERR_PROPERTYNOTFOUND),
875 "GetValue(%04x) error %#x\n", tag[i].id, hr);
876 if (hr == S_OK)
877 {
878 ok(value.vt == VT_UI2 || value.vt == VT_UI4 || value.vt == (VT_UI2 | VT_VECTOR), "wrong vt: %d\n", value.vt);
879 tag[i].value[0] = U(value).uiVal;
880 }
881 else
882 tag[i].value[0] = -1;
883 }
884
885 IWICMetadataReader_Release(reader);
886
887 if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
888 {
889 ok(width == 32, "wrong width %u\n", width);
890 ok(height == 2, "wrong height %u\n", height);
891
892 ok(bps == 1, "wrong bps %d\n", bps);
893 ok(photo == 1, "wrong photometric %d\n", photo);
894 ok(samples == 1, "wrong samples %d\n", samples);
895 ok(colormap == -1, "wrong colormap %d\n", colormap);
896 }
897 else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
898 {
899 ok(width == 32, "wrong width %u\n", width);
900 ok(height == 2, "wrong height %u\n", height);
901
902 ok(bps == 1, "wrong bps %d\n", bps);
903 ok(photo == 3, "wrong photometric %d\n", photo);
904 ok(samples == 1, "wrong samples %d\n", samples);
905 ok(colormap == 6, "wrong colormap %d\n", colormap);
906 }
907 else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
908 {
909 ok(width == 32, "wrong width %u\n", width);
910 ok(height == 2, "wrong height %u\n", height);
911
912 ok(bps == 4, "wrong bps %d\n", bps);
913 ok(photo == 3, "wrong photometric %d\n", photo);
914 ok(samples == 1, "wrong samples %d\n", samples);
915 ok(colormap == 48, "wrong colormap %d\n", colormap);
916 }
917 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
918 {
919 ok(width == 32, "wrong width %u\n", width);
920 ok(height == 2, "wrong height %u\n", height);
921
922 ok(bps == 8, "wrong bps %d\n", bps);
923 ok(photo == 3, "wrong photometric %d\n", photo);
924 ok(samples == 1, "wrong samples %d\n", samples);
925 ok(colormap == 768, "wrong colormap %d\n", colormap);
926 }
927 else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
928 {
929 ok(width == 32, "wrong width %u\n", width);
930 ok(height == 2, "wrong height %u\n", height);
931
932 ok(bps == 3, "wrong bps %d\n", bps);
933 ok(photo == 2, "wrong photometric %d\n", photo);
934 ok(samples == 3, "wrong samples %d\n", samples);
935 ok(colormap == -1, "wrong colormap %d\n", colormap);
936 }
937 else
938 ok(0, "unknown TIFF pixel format %s\n", wine_dbgstr_guid(format));
939 }
940
941 static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
942 {
943 HRESULT hr;
944 BITMAPFILEHEADER bfh;
945 BITMAPV5HEADER bih;
946
947 hr = IStream_Read(stream, &bfh, sizeof(bfh), NULL);
948 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
949
950 ok(bfh.bfType == 0x4d42, "wrong BMP signature %02x\n", bfh.bfType);
951 ok(bfh.bfReserved1 == 0, "wrong bfReserved1 %02x\n", bfh.bfReserved1);
952 ok(bfh.bfReserved2 == 0, "wrong bfReserved2 %02x\n", bfh.bfReserved2);
953
954 hr = IStream_Read(stream, &bih, sizeof(bih), NULL);
955 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
956
957 if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
958 {
959 ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
960
961 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
962 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
963
964 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
965 ok(bih.bV5BitCount == 1, "wrong BitCount %d\n", bih.bV5BitCount);
966 ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
967 ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
968 }
969 else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
970 {
971 ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
972
973 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
974 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
975
976 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
977 ok(bih.bV5BitCount == 4, "wrong BitCount %d\n", bih.bV5BitCount);
978 ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
979 ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
980 }
981 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
982 {
983 ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
984
985 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
986 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
987
988 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
989 ok(bih.bV5BitCount == 8, "wrong BitCount %d\n", bih.bV5BitCount);
990 ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
991 ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
992 }
993 else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
994 {
995 ok(bfh.bfOffBits == 0x0036, "wrong bfOffBits %08x\n", bfh.bfOffBits);
996
997 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
998 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
999
1000 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
1001 ok(bih.bV5BitCount == 32, "wrong BitCount %d\n", bih.bV5BitCount);
1002 ok(bih.bV5ClrUsed == 0, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
1003 ok(bih.bV5ClrImportant == 0, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
1004 }
1005 else
1006 ok(0, "unknown BMP pixel format %s\n", wine_dbgstr_guid(format));
1007 }
1008
1009 static unsigned be_uint(unsigned val)
1010 {
1011 union
1012 {
1013 unsigned val;
1014 char c[4];
1015 } u;
1016
1017 u.val = val;
1018 return (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3];
1019 }
1020
1021 static void check_png_format(IStream *stream, const WICPixelFormatGUID *format)
1022 {
1023 static const char png_sig[8] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
1024 static const char png_IHDR[8] = {0,0,0,0x0d,'I','H','D','R'};
1025 HRESULT hr;
1026 struct
1027 {
1028 char png_sig[8];
1029 char ihdr_sig[8];
1030 unsigned width, height;
1031 char bit_depth, color_type, compression, filter, interlace;
1032 } png;
1033
1034 memset(&png, 0, sizeof(png));
1035 hr = IStream_Read(stream, &png, sizeof(png), NULL);
1036 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
1037
1038 ok(!memcmp(png.png_sig, png_sig, sizeof(png_sig)), "expected PNG signature\n");
1039 ok(!memcmp(png.ihdr_sig, png_IHDR, sizeof(png_IHDR)), "expected PNG IHDR\n");
1040
1041 if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
1042 {
1043 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1044 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1045
1046 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
1047 ok(png.color_type == 0, "wrong color_type %d\n", png.color_type);
1048 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1049 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1050 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1051 }
1052 else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
1053 {
1054 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1055 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1056
1057 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
1058 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1059 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1060 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1061 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1062 }
1063 else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
1064 {
1065 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1066 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1067
1068 ok(png.bit_depth == 2, "wrong bit_depth %d\n", png.bit_depth);
1069 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1070 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1071 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1072 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1073 }
1074 else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
1075 {
1076 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1077 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1078
1079 ok(png.bit_depth == 4, "wrong bit_depth %d\n", png.bit_depth);
1080 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1081 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1082 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1083 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1084 }
1085 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
1086 {
1087 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1088 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1089
1090 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
1091 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1092 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1093 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1094 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1095 }
1096 else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
1097 {
1098 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1099 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1100
1101 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
1102 ok(png.color_type == 2, "wrong color_type %d\n", png.color_type);
1103 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1104 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1105 ok(png.interlace == 0 || png.interlace == 1, "wrong interlace %d\n", png.interlace);
1106 }
1107 else
1108 ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format));
1109 }
1110
1111 static void check_gif_format(IStream *stream, const WICPixelFormatGUID *format)
1112 {
1113 #include "pshpack1.h"
1114 struct logical_screen_descriptor
1115 {
1116 char signature[6];
1117 USHORT width;
1118 USHORT height;
1119 BYTE packed;
1120 /* global_color_table_flag : 1;
1121 * color_resolution : 3;
1122 * sort_flag : 1;
1123 * global_color_table_size : 3;
1124 */
1125 BYTE background_color_index;
1126 BYTE pixel_aspect_ratio;
1127 } lsd;
1128 #include "poppack.h"
1129 UINT color_resolution;
1130 HRESULT hr;
1131
1132 memset(&lsd, 0, sizeof(lsd));
1133 hr = IStream_Read(stream, &lsd, sizeof(lsd), NULL);
1134 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
1135
1136 ok(!memcmp(lsd.signature, "GIF89a", 6), "wrong GIF signature %.6s\n", lsd.signature);
1137
1138 ok(lsd.width == 32, "wrong width %u\n", lsd.width);
1139 ok(lsd.height == 2, "wrong height %u\n", lsd.height);
1140 color_resolution = 1 << (((lsd.packed >> 4) & 0x07) + 1);
1141 ok(color_resolution == 256, "wrong color resolution %u\n", color_resolution);
1142 ok(lsd.pixel_aspect_ratio == 0, "wrong pixel_aspect_ratio %u\n", lsd.pixel_aspect_ratio);
1143 }
1144
1145 static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format)
1146 {
1147 HRESULT hr;
1148 LARGE_INTEGER pos;
1149
1150 pos.QuadPart = 0;
1151 hr = IStream_Seek(stream, pos, SEEK_SET, (ULARGE_INTEGER *)&pos);
1152 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1153
1154 if (IsEqualGUID(encoder, &CLSID_WICPngEncoder))
1155 check_png_format(stream, format);
1156 else if (IsEqualGUID(encoder, &CLSID_WICBmpEncoder))
1157 check_bmp_format(stream, format);
1158 else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder))
1159 check_tiff_format(stream, format);
1160 else if (IsEqualGUID(encoder, &CLSID_WICGifEncoder))
1161 check_gif_format(stream, format);
1162 else
1163 ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder));
1164
1165 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
1166 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1167 }
1168
1169 struct setting {
1170 const WCHAR *name;
1171 PROPBAG2_TYPE type;
1172 VARTYPE vt;
1173 void *value;
1174 };
1175
1176 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
1177 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
1178 {
1179 ULONG rc;
1180 IUnknown_AddRef(obj);
1181 rc = IUnknown_Release(obj);
1182 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
1183 }
1184
1185 static void test_set_frame_palette(IWICBitmapFrameEncode *frameencode)
1186 {
1187 IWICComponentFactory *factory;
1188 IWICPalette *palette;
1189 HRESULT hr;
1190
1191 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1192 &IID_IWICComponentFactory, (void **)&factory);
1193 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
1194
1195 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
1196 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
1197
1198 hr = IWICComponentFactory_CreatePalette(factory, &palette);
1199 ok(hr == S_OK, "CreatePalette failed, hr=%x\n", hr);
1200
1201 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1202 todo_wine
1203 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr=%x\n", hr);
1204
1205 hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedHalftone256, FALSE);
1206 ok(hr == S_OK, "InitializePredefined failed, hr=%x\n", hr);
1207
1208 EXPECT_REF(palette, 1);
1209 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1210 ok(hr == S_OK, "SetPalette failed, hr=%x\n", hr);
1211 EXPECT_REF(palette, 1);
1212
1213 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
1214 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
1215
1216 IWICPalette_Release(palette);
1217 IWICComponentFactory_Release(factory);
1218 }
1219
1220 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
1221 const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc,
1222 const struct setting *settings, const char *name, IWICPalette *palette)
1223 {
1224 const GUID *container_format = NULL;
1225 HRESULT hr;
1226 IWICBitmapEncoder *encoder;
1227 BitmapTestSrc *src_obj;
1228 HGLOBAL hglobal;
1229 IStream *stream;
1230 IWICBitmapFrameEncode *frameencode;
1231 IPropertyBag2 *options=NULL;
1232 IWICBitmapDecoder *decoder;
1233 IWICBitmapFrameDecode *framedecode;
1234 WICPixelFormatGUID pixelformat;
1235 GUID guid;
1236 int i;
1237
1238 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
1239 &IID_IWICBitmapEncoder, (void **)&encoder);
1240 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1241
1242 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1243 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
1244
1245 hr = IWICBitmapEncoder_GetContainerFormat(encoder, NULL);
1246 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1247
1248 if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
1249 container_format = &GUID_ContainerFormatPng;
1250 else if (IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder))
1251 container_format = &GUID_ContainerFormatBmp;
1252 else if (IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder))
1253 container_format = &GUID_ContainerFormatTiff;
1254 else if (IsEqualGUID(clsid_encoder, &CLSID_WICJpegEncoder))
1255 container_format = &GUID_ContainerFormatJpeg;
1256 else
1257 ok(0, "Unknown encoder %s.\n", wine_dbgstr_guid(clsid_encoder));
1258
1259 if (container_format)
1260 {
1261 memset(&guid, 0, sizeof(guid));
1262 hr = IWICBitmapEncoder_GetContainerFormat(encoder, &guid);
1263 ok(SUCCEEDED(hr), "Failed to get container format, hr %#x.\n", hr);
1264 ok(IsEqualGUID(container_format, &guid), "Unexpected container format %s.\n", wine_dbgstr_guid(&guid));
1265 }
1266
1267 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
1268 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1269
1270 /* Encoder options are optional. */
1271 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, NULL);
1272 ok(SUCCEEDED(hr), "Failed to create encode frame, hr %#x.\n", hr);
1273
1274 IStream_Release(stream);
1275 IWICBitmapEncoder_Release(encoder);
1276 IWICBitmapFrameEncode_Release(frameencode);
1277
1278 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
1279 &IID_IWICBitmapEncoder, (void**)&encoder);
1280 ok(SUCCEEDED(hr), "CoCreateInstance(%s) failed, hr=%x\n", wine_dbgstr_guid(clsid_encoder), hr);
1281 if (SUCCEEDED(hr))
1282 {
1283 hglobal = GlobalAlloc(GMEM_MOVEABLE, 0);
1284 ok(hglobal != NULL, "GlobalAlloc failed\n");
1285 if (hglobal)
1286 {
1287 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
1288 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
1289 }
1290
1291 if (hglobal && SUCCEEDED(hr))
1292 {
1293 IWICBitmapEncoderInfo *info = NULL;
1294
1295 if (palette)
1296 {
1297 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
1298 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x (%s)\n", hr, name);
1299 }
1300
1301 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
1302 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1303
1304 if (palette)
1305 {
1306 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
1307 if (IsEqualGUID(clsid_encoder, &CLSID_WICGifEncoder))
1308 ok(hr == S_OK, "SetPalette failed, hr=%#x\n", hr);
1309 else
1310 ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr);
1311 hr = S_OK;
1312 }
1313
1314 hr = IWICBitmapEncoder_GetEncoderInfo(encoder, &info);
1315 ok(hr == S_OK || hr == WINCODEC_ERR_COMPONENTNOTFOUND, "wrong error %#x\n", hr);
1316 if (SUCCEEDED(hr))
1317 {
1318 CLSID clsid;
1319
1320 hr = IWICBitmapEncoderInfo_GetCLSID(info, &clsid);
1321 ok(hr == S_OK, "wrong error %#x\n", hr);
1322 ok(!IsEqualGUID(&clsid_encoder, &clsid), "wrong CLSID %s (%s)\n",
1323 wine_dbgstr_guid(clsid_encoder), wine_dbgstr_guid(&clsid));
1324
1325 IWICBitmapEncoderInfo_Release(info);
1326 }
1327
1328 i=0;
1329 while (SUCCEEDED(hr) && srcs[i])
1330 {
1331 CreateTestBitmap(srcs[i], &src_obj);
1332
1333 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options);
1334 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr);
1335 if (SUCCEEDED(hr))
1336 {
1337 ok(options != NULL, "Encoder initialization has not created an property bag\n");
1338 if(options)
1339 test_encoder_properties(clsid_encoder, options);
1340
1341 if (settings)
1342 {
1343 int j;
1344 for (j=0; settings[j].name; j++)
1345 {
1346 PROPBAG2 propbag;
1347 VARIANT var;
1348
1349 memset(&propbag, 0, sizeof(propbag));
1350 memset(&var, 0, sizeof(var));
1351 propbag.pstrName = (LPOLESTR)settings[j].name;
1352 propbag.dwType = settings[j].type;
1353 V_VT(&var) = settings[j].vt;
1354 V_UNKNOWN(&var) = settings[j].value;
1355
1356 hr = IPropertyBag2_Write(options, 1, &propbag, &var);
1357 ok(SUCCEEDED(hr), "Writing property %s failed, hr=%x\n", wine_dbgstr_w(settings[j].name), hr);
1358 }
1359 }
1360
1361 if (palette)
1362 {
1363 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1364 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x\n", hr);
1365 }
1366
1367 hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
1368 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1369
1370 memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
1371 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
1372 ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
1373 ok(IsEqualGUID(&pixelformat, dsts[i]->format) ||
1374 (IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) ||
1375 (IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
1376 "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
1377
1378 hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
1379 ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
1380
1381 if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
1382 test_set_frame_palette(frameencode);
1383
1384 if (palette)
1385 {
1386 WICColor colors[256];
1387
1388 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1389 ok(SUCCEEDED(hr), "SetPalette failed, hr=%x (%s)\n", hr, name);
1390
1391 /* trash the assigned palette */
1392 memset(colors, 0, sizeof(colors));
1393 hr = IWICPalette_InitializeCustom(palette, colors, 256);
1394 ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1395 }
1396
1397 hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, rc);
1398 if (rc && (rc->Width <= 0 || rc->Height <= 0))
1399 {
1400 /* WriteSource fails but WriteSource_Proxy succeeds. */
1401 ok(hr == E_INVALIDARG, "WriteSource should fail, hr=%x (%s)\n", hr, name);
1402 hr = IWICBitmapFrameEncode_WriteSource_Proxy(frameencode, &src_obj->IWICBitmapSource_iface, rc);
1403 ok(SUCCEEDED(hr), "WriteSource_Proxy failed, %dx%d, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
1404 }
1405 else
1406 {
1407 if (rc)
1408 ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
1409 else
1410 ok(hr == S_OK ||
1411 (hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) ||
1412 (hr == E_NOTIMPL && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) ||
1413 broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
1414 "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
1415 }
1416
1417 if (SUCCEEDED(hr))
1418 {
1419 hr = IWICBitmapFrameEncode_Commit(frameencode);
1420 ok(SUCCEEDED(hr), "Commit failed, hr=%x (%s)\n", hr, name);
1421 }
1422
1423 IWICBitmapFrameEncode_Release(frameencode);
1424 IPropertyBag2_Release(options);
1425 }
1426
1427 DeleteTestBitmap(src_obj);
1428
1429 i++;
1430 }
1431
1432 if (clsid_decoder == NULL)
1433 {
1434 IStream_Release(stream);
1435 IWICBitmapEncoder_Release(encoder);
1436 return;
1437 }
1438
1439 if (SUCCEEDED(hr))
1440 {
1441 hr = IWICBitmapEncoder_Commit(encoder);
1442 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
1443
1444 if (IsEqualGUID(&pixelformat, dsts[0]->format))
1445 check_bitmap_format(stream, clsid_encoder, dsts[0]->format);
1446 }
1447
1448 if (SUCCEEDED(hr))
1449 {
1450 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER,
1451 &IID_IWICBitmapDecoder, (void**)&decoder);
1452 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1453 }
1454
1455 if (SUCCEEDED(hr))
1456 {
1457 IWICPalette *frame_palette;
1458
1459 hr = IWICImagingFactory_CreatePalette(factory, &frame_palette);
1460 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1461
1462 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
1463 if (IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder))
1464 ok(hr == WINCODEC_ERR_WRONGSTATE, "wrong error %#x\n", hr);
1465 else
1466 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1467
1468 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
1469 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1470
1471 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
1472 if (IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder))
1473 ok(hr == S_OK || broken(hr == WINCODEC_ERR_FRAMEMISSING) /* XP */, "CopyPalette failed, hr=%#x\n", hr);
1474 else
1475 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1476
1477 hr = S_OK;
1478 i=0;
1479 while (SUCCEEDED(hr) && dsts[i])
1480 {
1481 hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
1482 ok(SUCCEEDED(hr), "GetFrame failed, hr=%x (%s)\n", hr, name);
1483
1484 if (SUCCEEDED(hr))
1485 {
1486 hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &pixelformat);
1487 ok(hr == S_OK, "GetPixelFormat) failed, hr=%x (%s)\n", hr, name);
1488 if (IsEqualGUID(&pixelformat, dsts[i]->format))
1489 compare_bitmap_data(srcs[i], dsts[i], (IWICBitmapSource*)framedecode, name);
1490
1491 hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette);
1492 if (winetest_debug > 1)
1493 trace("%s, bpp %d, %s, hr %#x\n", name, dsts[i]->bpp, wine_dbgstr_guid(dsts[i]->format), hr);
1494 if (dsts[i]->bpp > 8 || IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite))
1495 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1496 else
1497 {
1498 UINT count, ret;
1499 WICColor colors[256];
1500
1501 ok(hr == S_OK, "CopyPalette error %#x (%s)\n", hr, name);
1502
1503 count = 0;
1504 hr = IWICPalette_GetColorCount(frame_palette, &count);
1505 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1506
1507 memset(colors, 0, sizeof(colors));
1508 ret = 0;
1509 hr = IWICPalette_GetColors(frame_palette, count, colors, &ret);
1510 ok(hr == S_OK, "GetColors error %#x\n", hr);
1511 ok(ret == count, "expected %u, got %u\n", count, ret);
1512 if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder))
1513 {
1514 /* Newer libpng versions don't accept larger palettes than the declared
1515 * bit depth, so we need to generate the palette of the correct length.
1516 */
1517 ok(count == 256 || (dsts[i]->bpp == 1 && count == 2) ||
1518 (dsts[i]->bpp == 2 && count == 4) || (dsts[i]->bpp == 4 && count == 16),
1519 "expected 256, got %u (%s)\n", count, name);
1520
1521 ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name);
1522 ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name);
1523 if (count > 2)
1524 {
1525 ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name);
1526 ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name);
1527 if (count > 4)
1528 {
1529 ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
1530 ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
1531 }
1532 }
1533 }
1534 else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) ||
1535 IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder) ||
1536 IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder))
1537 {
1538 if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormatBlackWhite) ||
1539 IsEqualGUID(&pixelformat, &GUID_WICPixelFormat8bppIndexed))
1540 {
1541 ok(count == 256, "expected 256, got %u (%s)\n", count, name);
1542
1543 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1544 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1545 ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1546 ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1547 ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1548 ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1549 }
1550 else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed))
1551 {
1552 ok(count == 16, "expected 16, got %u (%s)\n", count, name);
1553
1554 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1555 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1556 ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1557 ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1558 ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1559 ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1560 }
1561 else
1562 {
1563 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1564
1565 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1566 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1567 }
1568 }
1569 else
1570 {
1571 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1572
1573 ok(colors[0] == 0xff111111, "got %08x\n", colors[0]);
1574 ok(colors[1] == 0xff222222, "got %08x\n", colors[1]);
1575 }
1576 }
1577
1578 IWICBitmapFrameDecode_Release(framedecode);
1579 }
1580
1581 i++;
1582 }
1583
1584 IWICPalette_Release(frame_palette);
1585 IWICBitmapDecoder_Release(decoder);
1586 }
1587
1588 IStream_Release(stream);
1589 }
1590
1591 IWICBitmapEncoder_Release(encoder);
1592 }
1593 }
1594
1595 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder,
1596 const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name)
1597 {
1598 const struct bitmap_data *srcs[2];
1599 const struct bitmap_data *dsts[2];
1600 WICColor colors[256];
1601 IWICPalette *palette;
1602 HRESULT hr;
1603
1604 hr = IWICImagingFactory_CreatePalette(factory, &palette);
1605 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1606
1607 memset(colors, 0, sizeof(colors));
1608 colors[0] = 0x11111111;
1609 colors[1] = 0x22222222;
1610 colors[2] = 0x33333333;
1611 colors[3] = 0x44444444;
1612 colors[4] = 0x55555555;
1613 /* TIFF decoder fails to decode a 8bpp frame if palette has less than 256 colors */
1614 hr = IWICPalette_InitializeCustom(palette, colors, 256);
1615 ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1616
1617 srcs[0] = src;
1618 srcs[1] = NULL;
1619 dsts[0] = dst;
1620 dsts[1] = NULL;
1621
1622 test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name, palette);
1623
1624 IWICPalette_Release(palette);
1625 }
1626
1627 static void test_encoder_rects(void)
1628 {
1629 const struct bitmap_data *srcs[2];
1630 const struct bitmap_data *dsts[2];
1631 WICRect rc;
1632
1633 srcs[0] = &testdata_24bppBGR;
1634 srcs[1] = NULL;
1635 dsts[0] = &testdata_24bppBGR;
1636 dsts[1] = NULL;
1637
1638 rc.X = 0;
1639 rc.Y = 0;
1640 rc.Width = 32;
1641 rc.Height = 2;
1642
1643 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL);
1644
1645 rc.Width = 0;
1646 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0", NULL);
1647
1648 rc.Width = -1;
1649 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL);
1650
1651 rc.Width = 32;
1652 rc.Height = 0;
1653 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL);
1654
1655 rc.Height = -1;
1656 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1", NULL);
1657 }
1658
1659 static const struct bitmap_data *multiple_frames[3] = {
1660 &testdata_24bppBGR,
1661 &testdata_24bppBGR,
1662 NULL};
1663
1664 static const struct bitmap_data *single_frame[2] = {
1665 &testdata_24bppBGR,
1666 NULL};
1667
1668 static const struct setting png_interlace_settings[] = {
1669 {wszInterlaceOption, PROPBAG2_TYPE_DATA, VT_BOOL, (void*)VARIANT_TRUE},
1670 {NULL}
1671 };
1672
1673 static void test_converter_8bppIndexed(void)
1674 {
1675 HRESULT hr;
1676 BitmapTestSrc *src_obj;
1677 IWICFormatConverter *converter;
1678 IWICPalette *palette;
1679 UINT count, i;
1680 BYTE buf[32 * 2 * 3]; /* enough to hold 32x2 24bppBGR data */
1681
1682 CreateTestBitmap(&testdata_24bppBGR, &src_obj);
1683
1684 hr = IWICImagingFactory_CreatePalette(factory, &palette);
1685 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1686 count = 0xdeadbeef;
1687 hr = IWICPalette_GetColorCount(palette, &count);
1688 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1689 ok(count == 0, "expected 0, got %u\n", count);
1690
1691 /* NULL palette + Custom type*/
1692 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1693 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1694 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1695 &GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone,
1696 NULL, 0.0, WICBitmapPaletteTypeCustom);
1697 ok(hr == S_OK, "Initialize error %#x\n", hr);
1698 hr = IWICFormatConverter_CopyPalette(converter, palette);
1699 ok(hr == 0xdeadbeef, "unexpected error %#x\n", hr);
1700 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32 * 3, sizeof(buf), buf);
1701 ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1702 IWICFormatConverter_Release(converter);
1703
1704 /* NULL palette + Custom type*/
1705 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1706 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1707 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1708 &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1709 NULL, 0.0, WICBitmapPaletteTypeCustom);
1710 ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr);
1711 hr = IWICFormatConverter_CopyPalette(converter, palette);
1712 ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr);
1713 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1714 ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr);
1715 IWICFormatConverter_Release(converter);
1716
1717 /* empty palette + Custom type*/
1718 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1719 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1720 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1721 &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1722 palette, 0.0, WICBitmapPaletteTypeCustom);
1723 ok(hr == S_OK, "Initialize error %#x\n", hr);
1724 hr = IWICFormatConverter_CopyPalette(converter, palette);
1725 ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1726 count = 0xdeadbeef;
1727 hr = IWICPalette_GetColorCount(palette, &count);
1728 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1729 ok(count == 0, "expected 0, got %u\n", count);
1730 memset(buf, 0xaa, sizeof(buf));
1731 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1732 ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1733 count = 0;
1734 for (i = 0; i < 32 * 2; i++)
1735 if (buf[i] != 0) count++;
1736 ok(count == 0, "expected 0\n");
1737 IWICFormatConverter_Release(converter);
1738
1739 /* NULL palette + Predefined type*/
1740 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1741 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1742 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1743 &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1744 NULL, 0.0, WICBitmapPaletteTypeFixedGray16);
1745 ok(hr == S_OK, "Initialize error %#x\n", hr);
1746 hr = IWICFormatConverter_CopyPalette(converter, palette);
1747 ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1748 count = 0xdeadbeef;
1749 hr = IWICPalette_GetColorCount(palette, &count);
1750 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1751 ok(count == 16, "expected 16, got %u\n", count);
1752 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1753 ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1754 count = 0;
1755 for (i = 0; i < 32 * 2; i++)
1756 if (buf[i] != 0) count++;
1757 ok(count != 0, "expected != 0\n");
1758 IWICFormatConverter_Release(converter);
1759
1760 /* not empty palette + Predefined type*/
1761 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1762 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1763 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1764 &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1765 palette, 0.0, WICBitmapPaletteTypeFixedHalftone64);
1766 ok(hr == S_OK, "Initialize error %#x\n", hr);
1767 hr = IWICFormatConverter_CopyPalette(converter, palette);
1768 ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1769 count = 0xdeadbeef;
1770 hr = IWICPalette_GetColorCount(palette, &count);
1771 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1772 ok(count == 16, "expected 16, got %u\n", count);
1773 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1774 ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1775 count = 0;
1776 for (i = 0; i < 32 * 2; i++)
1777 if (buf[i] != 0) count++;
1778 ok(count != 0, "expected != 0\n");
1779 IWICFormatConverter_Release(converter);
1780
1781 /* not empty palette + MedianCut type*/
1782 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1783 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1784 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1785 &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1786 palette, 0.0, WICBitmapPaletteTypeMedianCut);
1787 ok(hr == S_OK, "Initialize error %#x\n", hr);
1788 hr = IWICFormatConverter_CopyPalette(converter, palette);
1789 ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1790 count = 0xdeadbeef;
1791 hr = IWICPalette_GetColorCount(palette, &count);
1792 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1793 ok(count == 16, "expected 16, got %u\n", count);
1794 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1795 ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1796 count = 0;
1797 for (i = 0; i < 32 * 2; i++)
1798 if (buf[i] != 0) count++;
1799 ok(count != 0, "expected != 0\n");
1800 IWICFormatConverter_Release(converter);
1801
1802 /* NULL palette + MedianCut type*/
1803 hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1804 ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1805 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1806 &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1807 NULL, 0.0, WICBitmapPaletteTypeMedianCut);
1808 ok(hr == S_OK || broken(hr == E_INVALIDARG) /* XP */, "Initialize error %#x\n", hr);
1809 if (hr == S_OK)
1810 {
1811 hr = IWICFormatConverter_CopyPalette(converter, palette);
1812 ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1813 count = 0xdeadbeef;
1814 hr = IWICPalette_GetColorCount(palette, &count);
1815 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1816 ok(count == 8, "expected 8, got %u\n", count);
1817 hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1818 ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1819 count = 0;
1820 for (i = 0; i < 32 * 2; i++)
1821 if (buf[i] != 0) count++;
1822 ok(count != 0, "expected != 0\n");
1823 }
1824 IWICFormatConverter_Release(converter);
1825
1826 IWICPalette_Release(palette);
1827 DeleteTestBitmap(src_obj);
1828 }
1829
1830 START_TEST(converter)
1831 {
1832 HRESULT hr;
1833
1834 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1835
1836 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1837 &IID_IWICImagingFactory, (void **)&factory);
1838 ok(hr == S_OK, "failed to create factory: %#x\n", hr);
1839
1840 test_conversion(&testdata_24bppRGB, &testdata_1bppIndexed, "24bppRGB -> 1bppIndexed", TRUE);
1841 test_conversion(&testdata_24bppRGB, &testdata_2bppIndexed, "24bppRGB -> 2bppIndexed", TRUE);
1842 test_conversion(&testdata_24bppRGB, &testdata_4bppIndexed, "24bppRGB -> 4bppIndexed", TRUE);
1843 test_conversion(&testdata_24bppRGB, &testdata_8bppIndexed, "24bppRGB -> 8bppIndexed", FALSE);
1844
1845 test_conversion(&testdata_BlackWhite, &testdata_8bppIndexed_BW, "BlackWhite -> 8bppIndexed", TRUE);
1846 test_conversion(&testdata_1bppIndexed, &testdata_8bppIndexed_BW, "1bppIndexed -> 8bppIndexed", TRUE);
1847 test_conversion(&testdata_2bppIndexed, &testdata_8bppIndexed_4colors, "2bppIndexed -> 8bppIndexed", TRUE);
1848 test_conversion(&testdata_4bppIndexed, &testdata_8bppIndexed, "4bppIndexed -> 8bppIndexed", TRUE);
1849
1850 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE);
1851 test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE);
1852 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE);
1853 test_conversion(&testdata_32bppBGRA80, &testdata_32bppPBGRA, "BGRA -> PBGRA", FALSE);
1854
1855 test_conversion(&testdata_32bppRGBA, &testdata_32bppRGB, "RGBA -> RGB", FALSE);
1856 test_conversion(&testdata_32bppRGB, &testdata_32bppRGBA, "RGB -> RGBA", FALSE);
1857 test_conversion(&testdata_32bppRGBA, &testdata_32bppRGBA, "RGBA -> RGBA", FALSE);
1858 test_conversion(&testdata_32bppRGBA80, &testdata_32bppPRGBA, "RGBA -> PRGBA", FALSE);
1859
1860 test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE);
1861 test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE);
1862
1863 test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", FALSE);
1864 test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", FALSE);
1865
1866 test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", FALSE);
1867 test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", FALSE);
1868 test_conversion(&testdata_32bppBGRA, &testdata_24bppRGB, "32bppBGRA -> 24bppRGB", FALSE);
1869
1870 test_conversion(&testdata_24bppRGB, &testdata_32bppGrayFloat, "24bppRGB -> 32bppGrayFloat", FALSE);
1871 test_conversion(&testdata_32bppBGR, &testdata_32bppGrayFloat, "32bppBGR -> 32bppGrayFloat", FALSE);
1872
1873 test_conversion(&testdata_24bppBGR, &testdata_8bppGray, "24bppBGR -> 8bppGray", FALSE);
1874 test_conversion(&testdata_32bppBGR, &testdata_8bppGray, "32bppBGR -> 8bppGray", FALSE);
1875 test_conversion(&testdata_32bppGrayFloat, &testdata_24bppBGR_gray, "32bppGrayFloat -> 24bppBGR gray", FALSE);
1876 test_conversion(&testdata_32bppGrayFloat, &testdata_8bppGray, "32bppGrayFloat -> 8bppGray", FALSE);
1877
1878 test_invalid_conversion();
1879 test_default_converter();
1880 test_converter_8bppIndexed();
1881
1882 test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder,
1883 &testdata_8bppIndexed, &CLSID_WICGifDecoder, "GIF encoder 8bppIndexed");
1884
1885 test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder,
1886 &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite");
1887 test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder,
1888 &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed");
1889 test_encoder(&testdata_2bppIndexed, &CLSID_WICPngEncoder,
1890 &testdata_2bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 2bppIndexed");
1891 test_encoder(&testdata_4bppIndexed, &CLSID_WICPngEncoder,
1892 &testdata_4bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 4bppIndexed");
1893 test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder,
1894 &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed");
1895 test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
1896 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
1897 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
1898 {
1899 test_encoder(&testdata_32bppBGR, &CLSID_WICPngEncoder,
1900 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 32bppBGR");
1901 }
1902
1903 test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
1904 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
1905 test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
1906 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
1907 test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder,
1908 &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
1909 test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder,
1910 &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
1911 test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
1912 &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
1913 test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
1914 &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
1915
1916 test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder,
1917 &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite");
1918 test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
1919 &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
1920 test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder,
1921 &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
1922 test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder,
1923 &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed");
1924 test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
1925 &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
1926 test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
1927 &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
1928
1929 test_encoder(&testdata_24bppBGR, &CLSID_WICJpegEncoder,
1930 &testdata_24bppBGR, NULL, "JPEG encoder 24bppBGR");
1931
1932 test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
1933 multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame", NULL);
1934
1935 test_encoder_rects();
1936
1937 test_multi_encoder(single_frame, &CLSID_WICPngEncoder,
1938 single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced", NULL);
1939
1940 IWICImagingFactory_Release(factory);
1941
1942 CoUninitialize();
1943 }