2a44ef50b0744d7b1641f4ca67331052994c51d0
[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 "precomp.h"
21
22 static IWICImagingFactory *factory;
23
24 typedef struct bitmap_data {
25 const WICPixelFormatGUID *format;
26 UINT bpp;
27 const BYTE *bits;
28 UINT width;
29 UINT height;
30 double xres;
31 double yres;
32 const struct bitmap_data *alt_data;
33 } bitmap_data;
34
35 typedef struct BitmapTestSrc {
36 IWICBitmapSource IWICBitmapSource_iface;
37 LONG ref;
38 const bitmap_data *data;
39 } BitmapTestSrc;
40
41 extern HRESULT STDMETHODCALLTYPE IWICBitmapFrameEncode_WriteSource_Proxy(IWICBitmapFrameEncode* This,
42 IWICBitmapSource *pIBitmapSource, WICRect *prc);
43
44 static BOOL near_equal(float a, float b)
45 {
46 return fabsf(a - b) < 0.001;
47 }
48
49 static inline BitmapTestSrc *impl_from_IWICBitmapSource(IWICBitmapSource *iface)
50 {
51 return CONTAINING_RECORD(iface, BitmapTestSrc, IWICBitmapSource_iface);
52 }
53
54 static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid,
55 void **ppv)
56 {
57 if (!ppv) return E_INVALIDARG;
58
59 if (IsEqualIID(&IID_IUnknown, iid) ||
60 IsEqualIID(&IID_IWICBitmapSource, iid))
61 *ppv = iface;
62 else
63 return E_NOINTERFACE;
64
65 IUnknown_AddRef((IUnknown*)*ppv);
66 return S_OK;
67 }
68
69 static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface)
70 {
71 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
72 ULONG ref = InterlockedIncrement(&This->ref);
73 return ref;
74 }
75
76 static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface)
77 {
78 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
79 ULONG ref = InterlockedDecrement(&This->ref);
80 return ref;
81 }
82
83 static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface,
84 UINT *puiWidth, UINT *puiHeight)
85 {
86 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
87 *puiWidth = This->data->width;
88 *puiHeight = This->data->height;
89 return S_OK;
90 }
91
92 static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface,
93 WICPixelFormatGUID *pPixelFormat)
94 {
95 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
96 memcpy(pPixelFormat, This->data->format, sizeof(GUID));
97 return S_OK;
98 }
99
100 static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface,
101 double *pDpiX, double *pDpiY)
102 {
103 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
104 *pDpiX = This->data->xres;
105 *pDpiY = This->data->yres;
106 return S_OK;
107 }
108
109 static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface,
110 IWICPalette *pIPalette)
111 {
112 return E_NOTIMPL;
113 }
114
115 static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface,
116 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
117 {
118 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
119 UINT bytesperrow;
120 UINT srcstride;
121 UINT row_offset;
122 WICRect rc;
123
124 if (!prc)
125 {
126 rc.X = 0;
127 rc.Y = 0;
128 rc.Width = This->data->width;
129 rc.Height = This->data->height;
130 prc = &rc;
131 }
132 else
133 {
134 if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->data->width || prc->Y+prc->Height > This->data->height)
135 return E_INVALIDARG;
136 }
137
138 bytesperrow = ((This->data->bpp * prc->Width)+7)/8;
139 srcstride = ((This->data->bpp * This->data->width)+7)/8;
140
141 if (cbStride < bytesperrow)
142 return E_INVALIDARG;
143
144 if ((cbStride * prc->Height) > cbBufferSize)
145 return E_INVALIDARG;
146
147 row_offset = prc->X * This->data->bpp;
148
149 if (row_offset % 8 == 0)
150 {
151 UINT row;
152 const BYTE *src;
153 BYTE *dst;
154
155 src = This->data->bits + (row_offset / 8) + prc->Y * srcstride;
156 dst = pbBuffer;
157 for (row=0; row < prc->Height; row++)
158 {
159 memcpy(dst, src, bytesperrow);
160 src += srcstride;
161 dst += cbStride;
162 }
163 return S_OK;
164 }
165 else
166 {
167 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface);
168 return E_FAIL;
169 }
170 }
171
172 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl = {
173 BitmapTestSrc_QueryInterface,
174 BitmapTestSrc_AddRef,
175 BitmapTestSrc_Release,
176 BitmapTestSrc_GetSize,
177 BitmapTestSrc_GetPixelFormat,
178 BitmapTestSrc_GetResolution,
179 BitmapTestSrc_CopyPalette,
180 BitmapTestSrc_CopyPixels
181 };
182
183 static void CreateTestBitmap(const bitmap_data *data, BitmapTestSrc **This)
184 {
185 *This = HeapAlloc(GetProcessHeap(), 0, sizeof(**This));
186
187 if (*This)
188 {
189 (*This)->IWICBitmapSource_iface.lpVtbl = &BitmapTestSrc_Vtbl;
190 (*This)->ref = 1;
191 (*This)->data = data;
192 }
193 }
194
195 static void DeleteTestBitmap(BitmapTestSrc *This)
196 {
197 ok(This->IWICBitmapSource_iface.lpVtbl == &BitmapTestSrc_Vtbl, "test bitmap %p deleted with incorrect vtable\n", This);
198 ok(This->ref == 1, "test bitmap %p deleted with %i references instead of 1\n", This, This->ref);
199 HeapFree(GetProcessHeap(), 0, This);
200 }
201
202 static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, const BYTE *converted_bits)
203 {
204 BOOL equal;
205
206 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
207 {
208 /* ignore the padding byte when comparing data */
209 UINT i;
210 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits;
211 equal=TRUE;
212 for (i=0; i<(buffersize/4); i++)
213 if ((a[i]&0xffffff) != (b[i]&0xffffff))
214 {
215 equal = FALSE;
216 break;
217 }
218 }
219 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppGrayFloat))
220 {
221 UINT i;
222 const float *a=(const float*)expect->bits, *b=(const float*)converted_bits;
223 equal=TRUE;
224 for (i=0; i<(buffersize/4); i++)
225 if (!near_equal(a[i], b[i]))
226 {
227 equal = FALSE;
228 break;
229 }
230 }
231 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormatBlackWhite) ||
232 IsEqualGUID(expect->format, &GUID_WICPixelFormat1bppIndexed))
233 {
234 UINT i;
235 const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits;
236 equal=TRUE;
237 for (i=0; i<buffersize; i++)
238 if (a[i] != b[i] && b[i] != 0xff /* BMP encoder B&W */)
239 {
240 equal = FALSE;
241 break;
242 }
243 }
244 else
245 equal = (memcmp(expect->bits, converted_bits, buffersize) == 0);
246
247 if (!equal && expect->alt_data)
248 equal = compare_bits(expect->alt_data, buffersize, converted_bits);
249
250 return equal;
251 }
252
253 static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name)
254 {
255 BYTE *converted_bits;
256 UINT width, height;
257 double xres, yres;
258 WICRect prc;
259 UINT stride, buffersize;
260 GUID dst_pixelformat;
261 HRESULT hr;
262
263 hr = IWICBitmapSource_GetSize(source, &width, &height);
264 ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr);
265 ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name);
266 ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name);
267
268 hr = IWICBitmapSource_GetResolution(source, &xres, &yres);
269 ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr);
270 ok(fabs(xres - expect->xres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name);
271 ok(fabs(yres - expect->yres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name);
272
273 hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat);
274 ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr);
275 ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format %s (%s)\n", wine_dbgstr_guid(&dst_pixelformat), name);
276
277 prc.X = 0;
278 prc.Y = 0;
279 prc.Width = expect->width;
280 prc.Height = expect->height;
281
282 stride = (expect->bpp * expect->width + 7) / 8;
283 buffersize = stride * expect->height;
284
285 converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
286 hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits);
287 ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr);
288 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name);
289
290 /* Test with NULL rectangle - should copy the whole bitmap */
291 memset(converted_bits, 0xaa, buffersize);
292 hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits);
293 ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr);
294 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name);
295
296 HeapFree(GetProcessHeap(), 0, converted_bits);
297 }
298
299 /* some encoders (like BMP) require data to be 4-bytes aligned */
300 static const BYTE bits_1bpp[] = {
301 0x55,0x55,0x55,0x55, /*01010101*/
302 0xaa,0xaa,0xaa,0xaa}; /*10101010*/
303 static const struct bitmap_data testdata_BlackWhite = {
304 &GUID_WICPixelFormatBlackWhite, 1, bits_1bpp, 32, 2, 96.0, 96.0};
305 static const struct bitmap_data testdata_1bppIndexed = {
306 &GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0};
307
308 static const BYTE bits_8bpp[] = {
309 0,1,2,3,
310 4,5,6,7};
311 static const struct bitmap_data testdata_8bppIndexed = {
312 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 4, 2, 96.0, 96.0};
313
314 static const BYTE bits_24bppBGR[] = {
315 255,0,0, 0,255,0, 0,0,255, 0,0,0,
316 0,255,255, 255,0,255, 255,255,0, 255,255,255};
317 static const struct bitmap_data testdata_24bppBGR = {
318 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 4, 2, 96.0, 96.0};
319
320 static const BYTE bits_24bppRGB[] = {
321 0,0,255, 0,255,0, 255,0,0, 0,0,0,
322 255,255,0, 255,0,255, 0,255,255, 255,255,255};
323 static const struct bitmap_data testdata_24bppRGB = {
324 &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 4, 2, 96.0, 96.0};
325
326 static const BYTE bits_32bppBGR[] = {
327 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
328 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
329 static const struct bitmap_data testdata_32bppBGR = {
330 &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 4, 2, 96.0, 96.0};
331
332 static const BYTE bits_32bppBGRA[] = {
333 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
334 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
335 static const struct bitmap_data testdata_32bppBGRA = {
336 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 4, 2, 96.0, 96.0};
337
338 /* XP and 2003 use linear color conversion, later versions use sRGB gamma */
339 static const float bits_32bppGrayFloat_xp[] = {
340 0.114000f,0.587000f,0.299000f,0.000000f,
341 0.886000f,0.413000f,0.701000f,1.000000f};
342 static const struct bitmap_data testdata_32bppGrayFloat_xp = {
343 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat_xp, 4, 2, 96.0, 96.0};
344
345 static const float bits_32bppGrayFloat[] = {
346 0.072200f,0.715200f,0.212600f,0.000000f,
347 0.927800f,0.284800f,0.787400f,1.000000f};
348 static const struct bitmap_data testdata_32bppGrayFloat = {
349 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 4, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp};
350
351 static const BYTE bits_8bppGray_xp[] = {
352 29,150,76,0,
353 226,105,179,255};
354 static const struct bitmap_data testdata_8bppGray_xp = {
355 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray_xp, 4, 2, 96.0, 96.0};
356
357 static const BYTE bits_8bppGray[] = {
358 76,220,127,0,
359 247,145,230,255};
360 static const struct bitmap_data testdata_8bppGray = {
361 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray, 4, 2, 96.0, 96.0, &testdata_8bppGray_xp};
362
363 static const BYTE bits_24bppBGR_gray[] = {
364 76,76,76, 220,220,220, 127,127,127, 0,0,0,
365 247,247,247, 145,145,145, 230,230,230, 255,255,255};
366 static const struct bitmap_data testdata_24bppBGR_gray = {
367 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_gray, 4, 2, 96.0, 96.0};
368
369 static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo)
370 {
371 BitmapTestSrc *src_obj;
372 IWICBitmapSource *dst_bitmap;
373 HRESULT hr;
374
375 CreateTestBitmap(src, &src_obj);
376
377 hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
378 todo_wine_if (todo)
379 ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
380
381 if (SUCCEEDED(hr))
382 {
383 compare_bitmap_data(dst, dst_bitmap, name);
384
385 IWICBitmapSource_Release(dst_bitmap);
386 }
387
388 DeleteTestBitmap(src_obj);
389 }
390
391 static void test_invalid_conversion(void)
392 {
393 BitmapTestSrc *src_obj;
394 IWICBitmapSource *dst_bitmap;
395 HRESULT hr;
396
397 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
398
399 /* convert to a non-pixel-format GUID */
400 hr = WICConvertBitmapSource(&GUID_VendorMicrosoft, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
401 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "WICConvertBitmapSource returned %x\n", hr);
402
403 DeleteTestBitmap(src_obj);
404 }
405
406 static void test_default_converter(void)
407 {
408 BitmapTestSrc *src_obj;
409 IWICFormatConverter *converter;
410 BOOL can_convert = TRUE;
411 HRESULT hr;
412
413 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
414
415 hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER,
416 &IID_IWICFormatConverter, (void**)&converter);
417 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
418 if (SUCCEEDED(hr))
419 {
420 hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA,
421 &GUID_WICPixelFormat32bppBGR, &can_convert);
422 ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr);
423 ok(can_convert, "expected TRUE, got %i\n", can_convert);
424
425 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
426 &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.0,
427 WICBitmapPaletteTypeCustom);
428 ok(SUCCEEDED(hr), "Initialize returned %x\n", hr);
429
430 if (SUCCEEDED(hr))
431 compare_bitmap_data(&testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter");
432
433 IWICFormatConverter_Release(converter);
434 }
435
436 DeleteTestBitmap(src_obj);
437 }
438
439 typedef struct property_opt_test_data
440 {
441 LPCOLESTR name;
442 VARTYPE var_type;
443 VARTYPE initial_var_type;
444 int i_init_val;
445 float f_init_val;
446 BOOL skippable;
447 } property_opt_test_data;
448
449 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};
450 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
451 static const WCHAR wszInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
452 static const WCHAR wszFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
453 static const WCHAR wszImageQuality[] = {'I','m','a','g','e','Q','u','a','l','i','t','y',0};
454 static const WCHAR wszBitmapTransform[] = {'B','i','t','m','a','p','T','r','a','n','s','f','o','r','m',0};
455 static const WCHAR wszLuminance[] = {'L','u','m','i','n','a','n','c','e',0};
456 static const WCHAR wszChrominance[] = {'C','h','r','o','m','i','n','a','n','c','e',0};
457 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};
458 static const WCHAR wszSuppressApp0[] = {'S','u','p','p','r','e','s','s','A','p','p','0',0};
459
460 static const struct property_opt_test_data testdata_tiff_props[] = {
461 { wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare },
462 { wszCompressionQuality, VT_R4, VT_EMPTY },
463 { NULL }
464 };
465
466 static const struct property_opt_test_data testdata_png_props[] = {
467 { wszInterlaceOption, VT_BOOL, VT_BOOL, 0 },
468 { wszFilterOption, VT_UI1, VT_UI1, WICPngFilterUnspecified, 0.0f, TRUE /* not supported on XP/2k3 */},
469 { NULL }
470 };
471
472 static const struct property_opt_test_data testdata_jpeg_props[] = {
473 { wszImageQuality, VT_R4, VT_EMPTY },
474 { wszBitmapTransform, VT_UI1, VT_UI1, WICBitmapTransformRotate0 },
475 { wszLuminance, VT_I4|VT_ARRAY, VT_EMPTY },
476 { wszChrominance, VT_I4|VT_ARRAY, VT_EMPTY },
477 { wszJpegYCrCbSubsampling, VT_UI1, VT_UI1, WICJpegYCrCbSubsamplingDefault, 0.0f, TRUE }, /* not supported on XP/2k3 */
478 { wszSuppressApp0, VT_BOOL, VT_BOOL, FALSE },
479 { NULL }
480 };
481
482 static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt)
483 {
484 int i;
485 for (i=0; i < all_prop_cnt; i++)
486 {
487 if (lstrcmpW(name, all_props[i].pstrName) == 0)
488 return i;
489 }
490 return -1;
491 }
492
493 static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt)
494 {
495 HRESULT hr;
496 int i = 0;
497 VARIANT pvarValue;
498 HRESULT phrError = S_OK;
499
500 while (data[i].name)
501 {
502 int idx = find_property_index(data[i].name, all_props, all_prop_cnt);
503 PROPBAG2 pb = {0};
504 pb.pstrName = (LPOLESTR)data[i].name;
505
506 hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError);
507
508 if (data[i].skippable && idx == -1)
509 {
510 win_skip("Property %s is not supported on this machine.\n", wine_dbgstr_w(data[i].name));
511 i++;
512 continue;
513 }
514
515 ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n",
516 wine_dbgstr_w(data[i].name));
517 if (idx >= 0)
518 {
519 ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n",
520 wine_dbgstr_w(data[i].name), all_props[idx].vt);
521 ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n",
522 wine_dbgstr_w(data[i].name), all_props[idx].dwType);
523 ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n",
524 wine_dbgstr_w(data[i].name), all_props[idx].cfType);
525 }
526
527 ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n",
528 wine_dbgstr_w(data[i].name), hr);
529
530 if (SUCCEEDED(hr))
531 {
532 /* On XP the initial type is always VT_EMPTY */
533 ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY,
534 "Property %s has unexpected initial type, V_VT=%i\n",
535 wine_dbgstr_w(data[i].name), V_VT(&pvarValue));
536
537 if(V_VT(&pvarValue) == data[i].initial_var_type)
538 {
539 switch (data[i].initial_var_type)
540 {
541 case VT_BOOL:
542 case VT_UI1:
543 ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n",
544 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal));
545 break;
546 case VT_R4:
547 ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n",
548 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal));
549 break;
550 default:
551 break;
552 }
553 }
554
555 VariantClear(&pvarValue);
556 }
557
558 i++;
559 }
560 }
561
562 static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *options)
563 {
564 HRESULT hr;
565 ULONG cProperties = 0;
566 ULONG cProperties2 = 0;
567 PROPBAG2 all_props[64] = {{0}}; /* Should be enough for every encoder out there */
568 int i;
569
570 /* CountProperties */
571 {
572 hr = IPropertyBag2_CountProperties(options, &cProperties);
573 ok(SUCCEEDED(hr), "Reading property count, hr=%x\n", hr);
574 }
575
576 /* GetPropertyInfo */
577 {
578 hr = IPropertyBag2_GetPropertyInfo(options, cProperties, 1, all_props, &cProperties2);
579 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - iProperty out of bounce handled wrong, hr=%x\n", hr);
580
581 hr = IPropertyBag2_GetPropertyInfo(options, 0, cProperties+1, all_props, &cProperties2);
582 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - cProperty out of bounce handled wrong, hr=%x\n", hr);
583
584 if (cProperties == 0) /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */
585 {
586 cProperties2 = cProperties;
587 hr = S_OK;
588 }
589 else
590 {
591 hr = IPropertyBag2_GetPropertyInfo(options, 0, min(64, cProperties), all_props, &cProperties2);
592 ok(SUCCEEDED(hr), "Reading infos from property bag failed, hr=%x\n", hr);
593 }
594
595 if (FAILED(hr))
596 return;
597
598 ok(cProperties == cProperties2, "Mismatch of property count (IPropertyBag2::CountProperties=%i, IPropertyBag2::GetPropertyInfo=%i)\n",
599 (int)cProperties, (int)cProperties2);
600 }
601
602 if (IsEqualCLSID(clsid_encoder, &CLSID_WICTiffEncoder))
603 test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2);
604 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICPngEncoder))
605 test_specific_encoder_properties(options, testdata_png_props, all_props, cProperties2);
606 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICJpegEncoder))
607 test_specific_encoder_properties(options, testdata_jpeg_props, all_props, cProperties2);
608
609 for (i=0; i < cProperties2; i++)
610 {
611 ok(all_props[i].pstrName != NULL, "Unset property name in output of IPropertyBag2::GetPropertyInfo\n");
612 CoTaskMemFree(all_props[i].pstrName);
613 }
614 }
615
616 static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
617 {
618 /* FIXME */
619 }
620
621 static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
622 {
623 /* FIXME */
624 }
625
626 static unsigned be_uint(unsigned val)
627 {
628 union
629 {
630 unsigned val;
631 char c[4];
632 } u;
633
634 u.val = val;
635 return (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3];
636 }
637
638 static void check_png_format(IStream *stream, const WICPixelFormatGUID *format)
639 {
640 static const char png_sig[8] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
641 static const char png_IHDR[8] = {0,0,0,0x0d,'I','H','D','R'};
642 HRESULT hr;
643 struct
644 {
645 char png_sig[8];
646 char ihdr_sig[8];
647 unsigned width, height;
648 char bit_depth, color_type, compression, filter, interlace;
649 } png;
650
651 memset(&png, 0, sizeof(png));
652 hr = IStream_Read(stream, &png, sizeof(png), NULL);
653 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
654
655 ok(!memcmp(png.png_sig, png_sig, sizeof(png_sig)), "expected PNG signature\n");
656 ok(!memcmp(png.ihdr_sig, png_IHDR, sizeof(png_IHDR)), "expected PNG IHDR\n");
657
658 if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
659 {
660 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
661 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
662
663 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
664 ok(png.color_type == 0, "wrong color_type %d\n", png.color_type);
665 ok(png.compression == 0, "wrong compression %d\n", png.compression);
666 ok(png.filter == 0, "wrong filter %d\n", png.filter);
667 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
668 }
669 else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
670 {
671 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
672 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
673
674 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
675 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
676 ok(png.compression == 0, "wrong compression %d\n", png.compression);
677 ok(png.filter == 0, "wrong filter %d\n", png.filter);
678 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
679 }
680 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
681 {
682 ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width));
683 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
684
685 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
686 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
687 ok(png.compression == 0, "wrong compression %d\n", png.compression);
688 ok(png.filter == 0, "wrong filter %d\n", png.filter);
689 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
690 }
691 else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
692 {
693 ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width));
694 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
695
696 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
697 ok(png.color_type == 2, "wrong color_type %d\n", png.color_type);
698 ok(png.compression == 0, "wrong compression %d\n", png.compression);
699 ok(png.filter == 0, "wrong filter %d\n", png.filter);
700 ok(png.interlace == 0 || png.interlace == 1, "wrong interlace %d\n", png.interlace);
701 }
702 else
703 ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format));
704 }
705
706 static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format)
707 {
708 HRESULT hr;
709 LARGE_INTEGER pos;
710
711 pos.QuadPart = 0;
712 hr = IStream_Seek(stream, pos, SEEK_SET, (ULARGE_INTEGER *)&pos);
713 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
714
715 if (IsEqualGUID(encoder, &CLSID_WICPngEncoder))
716 check_png_format(stream, format);
717 else if (IsEqualGUID(encoder, &CLSID_WICBmpEncoder))
718 check_bmp_format(stream, format);
719 else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder))
720 check_tiff_format(stream, format);
721 else
722 ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder));
723
724 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
725 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
726 }
727
728 struct setting {
729 const WCHAR *name;
730 PROPBAG2_TYPE type;
731 VARTYPE vt;
732 void *value;
733 };
734
735 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
736 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
737 {
738 ULONG rc;
739 IUnknown_AddRef(obj);
740 rc = IUnknown_Release(obj);
741 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
742 }
743
744 static void test_set_frame_palette(IWICBitmapFrameEncode *frameencode)
745 {
746 IWICComponentFactory *factory;
747 IWICPalette *palette;
748 HRESULT hr;
749
750 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
751 &IID_IWICComponentFactory, (void **)&factory);
752 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
753
754 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
755 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
756
757 hr = IWICComponentFactory_CreatePalette(factory, &palette);
758 ok(hr == S_OK, "CreatePalette failed, hr=%x\n", hr);
759
760 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
761 todo_wine
762 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr=%x\n", hr);
763
764 hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedHalftone256, FALSE);
765 ok(hr == S_OK, "InitializePredefined failed, hr=%x\n", hr);
766
767 EXPECT_REF(palette, 1);
768 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
769 ok(hr == S_OK, "SetPalette failed, hr=%x\n", hr);
770 EXPECT_REF(palette, 1);
771
772 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
773 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
774
775 IWICPalette_Release(palette);
776 IWICComponentFactory_Release(factory);
777 }
778
779 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
780 const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc,
781 const struct setting *settings, const char *name, IWICPalette *palette)
782 {
783 HRESULT hr;
784 IWICBitmapEncoder *encoder;
785 BitmapTestSrc *src_obj;
786 HGLOBAL hglobal;
787 IStream *stream;
788 IWICBitmapFrameEncode *frameencode;
789 IPropertyBag2 *options=NULL;
790 IWICBitmapDecoder *decoder;
791 IWICBitmapFrameDecode *framedecode;
792 WICPixelFormatGUID pixelformat;
793 int i;
794
795 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
796 &IID_IWICBitmapEncoder, (void**)&encoder);
797 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
798 if (SUCCEEDED(hr))
799 {
800 hglobal = GlobalAlloc(GMEM_MOVEABLE, 0);
801 ok(hglobal != NULL, "GlobalAlloc failed\n");
802 if (hglobal)
803 {
804 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
805 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
806 }
807
808 if (hglobal && SUCCEEDED(hr))
809 {
810 if (palette)
811 {
812 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
813 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x (%s)\n", hr, name);
814 }
815
816 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
817 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
818
819 if (palette)
820 {
821 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
822 ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr);
823 hr = S_OK;
824 }
825
826 i=0;
827 while (SUCCEEDED(hr) && srcs[i])
828 {
829 CreateTestBitmap(srcs[i], &src_obj);
830
831 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options);
832 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr);
833 if (SUCCEEDED(hr))
834 {
835 ok(options != NULL, "Encoder initialization has not created an property bag\n");
836 if(options)
837 test_encoder_properties(clsid_encoder, options);
838
839 if (settings)
840 {
841 int j;
842 for (j=0; settings[j].name; j++)
843 {
844 PROPBAG2 propbag;
845 VARIANT var;
846
847 memset(&propbag, 0, sizeof(propbag));
848 memset(&var, 0, sizeof(var));
849 propbag.pstrName = (LPOLESTR)settings[j].name;
850 propbag.dwType = settings[j].type;
851 V_VT(&var) = settings[j].vt;
852 V_UNKNOWN(&var) = settings[j].value;
853
854 hr = IPropertyBag2_Write(options, 1, &propbag, &var);
855 ok(SUCCEEDED(hr), "Writing property %s failed, hr=%x\n", wine_dbgstr_w(settings[j].name), hr);
856 }
857 }
858
859 if (palette)
860 {
861 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
862 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x\n", hr);
863 }
864
865 hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
866 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
867
868 memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
869 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
870 ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
871 ok(IsEqualGUID(&pixelformat, dsts[i]->format), "SetPixelFormat changed the format to %s (%s)\n",
872 wine_dbgstr_guid(&pixelformat), name);
873
874 hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
875 ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
876
877 if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
878 test_set_frame_palette(frameencode);
879
880 if (palette)
881 {
882 WICColor colors[256];
883
884 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
885 ok(SUCCEEDED(hr), "SetPalette failed, hr=%x (%s)\n", hr, name);
886
887 /* trash the assigned palette */
888 memset(colors, 0, sizeof(colors));
889 hr = IWICPalette_InitializeCustom(palette, colors, 256);
890 ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
891 }
892
893 hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, rc);
894 if (rc && (rc->Width <= 0 || rc->Height <= 0))
895 {
896 /* WriteSource fails but WriteSource_Proxy succeeds. */
897 ok(hr == E_INVALIDARG, "WriteSource should fail, hr=%x (%s)\n", hr, name);
898 hr = IWICBitmapFrameEncode_WriteSource_Proxy(frameencode, &src_obj->IWICBitmapSource_iface, rc);
899 ok(SUCCEEDED(hr), "WriteSource_Proxy failed, %dx%d, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
900 }
901 else
902 {
903 if (rc)
904 ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
905 else
906 ok(hr == S_OK ||
907 broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
908 "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
909 }
910
911 if (SUCCEEDED(hr))
912 {
913 hr = IWICBitmapFrameEncode_Commit(frameencode);
914 ok(SUCCEEDED(hr), "Commit failed, hr=%x (%s)\n", hr, name);
915 }
916
917 IWICBitmapFrameEncode_Release(frameencode);
918 IPropertyBag2_Release(options);
919 }
920
921 DeleteTestBitmap(src_obj);
922
923 i++;
924 }
925
926 if (clsid_decoder == NULL)
927 {
928 IStream_Release(stream);
929 IWICBitmapEncoder_Release(encoder);
930 return;
931 }
932
933 if (SUCCEEDED(hr))
934 {
935 hr = IWICBitmapEncoder_Commit(encoder);
936 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
937
938 check_bitmap_format(stream, clsid_encoder, dsts[0]->format);
939 }
940
941 if (SUCCEEDED(hr))
942 {
943 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER,
944 &IID_IWICBitmapDecoder, (void**)&decoder);
945 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
946 }
947
948 if (SUCCEEDED(hr))
949 {
950 IWICPalette *frame_palette;
951
952 hr = IWICImagingFactory_CreatePalette(factory, &frame_palette);
953 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
954
955 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
956 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
957
958 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
959 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
960
961 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
962 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
963
964 hr = S_OK;
965 i=0;
966 while (SUCCEEDED(hr) && dsts[i])
967 {
968 hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
969 ok(SUCCEEDED(hr), "GetFrame failed, hr=%x (%s)\n", hr, name);
970
971 if (SUCCEEDED(hr))
972 {
973 compare_bitmap_data(dsts[i], (IWICBitmapSource*)framedecode, name);
974
975 hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette);
976 if (winetest_debug > 1)
977 trace("%s, bpp %d, %s, hr %#x\n", name, dsts[i]->bpp, wine_dbgstr_guid(dsts[i]->format), hr);
978 if (dsts[i]->bpp > 8 || IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite))
979 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
980 else
981 {
982 UINT count, ret;
983 WICColor colors[256];
984
985 ok(hr == S_OK, "CopyPalette error %#x (%s)\n", hr, name);
986
987 count = 0;
988 hr = IWICPalette_GetColorCount(frame_palette, &count);
989 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
990
991 memset(colors, 0, sizeof(colors));
992 ret = 0;
993 hr = IWICPalette_GetColors(frame_palette, count, colors, &ret);
994 ok(hr == S_OK, "GetColors error %#x\n", hr);
995 ok(ret == count, "expected %u, got %u\n", count, ret);
996 if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder))
997 {
998 ok(count == 256 || count == 2 /* newer libpng versions */, "expected 256, got %u (%s)\n", count, name);
999
1000 ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name);
1001 ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name);
1002 if (count > 2)
1003 {
1004 ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name);
1005 ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name);
1006 ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
1007 ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
1008 }
1009 }
1010 else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) ||
1011 IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder))
1012 {
1013 if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite) ||
1014 IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat8bppIndexed))
1015 {
1016 ok(count == 256, "expected 256, got %u (%s)\n", count, name);
1017
1018 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1019 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1020 ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1021 ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1022 ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1023 ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1024 }
1025 else
1026 {
1027 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1028
1029 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1030 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1031 }
1032 }
1033 else
1034 {
1035 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1036
1037 ok(colors[0] == 0xff111111, "got %08x\n", colors[0]);
1038 ok(colors[1] == 0xff222222, "got %08x\n", colors[1]);
1039 }
1040 }
1041
1042 IWICBitmapFrameDecode_Release(framedecode);
1043 }
1044
1045 i++;
1046 }
1047
1048 IWICPalette_Release(frame_palette);
1049 IWICBitmapDecoder_Release(decoder);
1050 }
1051
1052 IStream_Release(stream);
1053 }
1054
1055 IWICBitmapEncoder_Release(encoder);
1056 }
1057 }
1058
1059 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder,
1060 const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name)
1061 {
1062 const struct bitmap_data *srcs[2];
1063 const struct bitmap_data *dsts[2];
1064 WICColor colors[256];
1065 IWICPalette *palette;
1066 HRESULT hr;
1067
1068 hr = IWICImagingFactory_CreatePalette(factory, &palette);
1069 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1070
1071 memset(colors, 0, sizeof(colors));
1072 colors[0] = 0x11111111;
1073 colors[1] = 0x22222222;
1074 colors[2] = 0x33333333;
1075 colors[3] = 0x44444444;
1076 colors[4] = 0x55555555;
1077 /* TIFF decoder fails to decode a 8bpp frame if palette has less than 256 colors */
1078 hr = IWICPalette_InitializeCustom(palette, colors, 256);
1079 ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1080
1081 srcs[0] = src;
1082 srcs[1] = NULL;
1083 dsts[0] = dst;
1084 dsts[1] = NULL;
1085
1086 test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name, palette);
1087
1088 IWICPalette_Release(palette);
1089 }
1090
1091 static void test_encoder_rects(void)
1092 {
1093 const struct bitmap_data *srcs[2];
1094 const struct bitmap_data *dsts[2];
1095 WICRect rc;
1096
1097 srcs[0] = &testdata_24bppBGR;
1098 srcs[1] = NULL;
1099 dsts[0] = &testdata_24bppBGR;
1100 dsts[1] = NULL;
1101
1102 rc.X = 0;
1103 rc.Y = 0;
1104 rc.Width = 4;
1105 rc.Height = 2;
1106
1107 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL);
1108
1109 rc.Width = 0;
1110 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0", NULL);
1111
1112 rc.Width = -1;
1113 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL);
1114
1115 rc.Width = 4;
1116 rc.Height = 0;
1117 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL);
1118
1119 rc.Height = -1;
1120 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1", NULL);
1121 }
1122
1123 static const struct bitmap_data *multiple_frames[3] = {
1124 &testdata_24bppBGR,
1125 &testdata_24bppBGR,
1126 NULL};
1127
1128 static const struct bitmap_data *single_frame[2] = {
1129 &testdata_24bppBGR,
1130 NULL};
1131
1132 static const struct setting png_interlace_settings[] = {
1133 {wszInterlaceOption, PROPBAG2_TYPE_DATA, VT_BOOL, (void*)VARIANT_TRUE},
1134 {NULL}
1135 };
1136
1137 START_TEST(converter)
1138 {
1139 HRESULT hr;
1140
1141 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1142
1143 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1144 &IID_IWICImagingFactory, (void **)&factory);
1145 ok(hr == S_OK, "failed to create factory: %#x\n", hr);
1146
1147 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE);
1148 test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE);
1149 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE);
1150
1151 test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE);
1152 test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE);
1153
1154 test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", FALSE);
1155 test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", FALSE);
1156
1157 test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", FALSE);
1158 test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", FALSE);
1159 test_conversion(&testdata_32bppBGRA, &testdata_24bppRGB, "32bppBGRA -> 24bppRGB", FALSE);
1160
1161 test_conversion(&testdata_24bppRGB, &testdata_32bppGrayFloat, "24bppRGB -> 32bppGrayFloat", FALSE);
1162 test_conversion(&testdata_32bppBGR, &testdata_32bppGrayFloat, "32bppBGR -> 32bppGrayFloat", FALSE);
1163
1164 test_conversion(&testdata_24bppBGR, &testdata_8bppGray, "24bppBGR -> 8bppGray", FALSE);
1165 test_conversion(&testdata_32bppBGR, &testdata_8bppGray, "32bppBGR -> 8bppGray", FALSE);
1166 test_conversion(&testdata_32bppGrayFloat, &testdata_24bppBGR_gray, "32bppGrayFloat -> 24bppBGR gray", FALSE);
1167 test_conversion(&testdata_32bppGrayFloat, &testdata_8bppGray, "32bppGrayFloat -> 8bppGray", FALSE);
1168
1169 test_invalid_conversion();
1170 test_default_converter();
1171
1172 test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder,
1173 &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite");
1174 test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder,
1175 &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed");
1176 test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder,
1177 &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed");
1178 test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
1179 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
1180
1181 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
1182 {
1183 test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
1184 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
1185 test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
1186 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
1187 test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
1188 &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
1189 }
1190 test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
1191 &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
1192
1193 test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder,
1194 &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite");
1195 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
1196 {
1197 test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
1198 &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
1199 test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
1200 &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
1201 }
1202 test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
1203 &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
1204
1205 test_encoder(&testdata_24bppBGR, &CLSID_WICJpegEncoder,
1206 &testdata_24bppBGR, NULL, "JPEG encoder 24bppBGR");
1207
1208 test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
1209 multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame", NULL);
1210
1211 test_encoder_rects();
1212
1213 test_multi_encoder(single_frame, &CLSID_WICPngEncoder,
1214 single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced", NULL);
1215
1216 IWICImagingFactory_Release(factory);
1217
1218 CoUninitialize();
1219 }