Release 1.6-rc2.
[wine/testsucceed.git] / dlls / windowscodecs / tests / converter.c
blobb77e45594c5e36098987b8b7e1c2a518c8c872a6
1 /*
2 * Copyright 2009 Vincent Povirk
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <math.h>
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include "windef.h"
26 #include "objbase.h"
27 #include "wincodec.h"
28 #include "wine/test.h"
30 typedef struct bitmap_data {
31 const WICPixelFormatGUID *format;
32 UINT bpp;
33 const BYTE *bits;
34 UINT width;
35 UINT height;
36 double xres;
37 double yres;
38 } bitmap_data;
40 typedef struct BitmapTestSrc {
41 IWICBitmapSource IWICBitmapSource_iface;
42 LONG ref;
43 const bitmap_data *data;
44 } BitmapTestSrc;
46 static inline BitmapTestSrc *impl_from_IWICBitmapSource(IWICBitmapSource *iface)
48 return CONTAINING_RECORD(iface, BitmapTestSrc, IWICBitmapSource_iface);
51 static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid,
52 void **ppv)
54 if (!ppv) return E_INVALIDARG;
56 if (IsEqualIID(&IID_IUnknown, iid) ||
57 IsEqualIID(&IID_IWICBitmapSource, iid))
58 *ppv = iface;
59 else
60 return E_NOINTERFACE;
62 IUnknown_AddRef((IUnknown*)*ppv);
63 return S_OK;
66 static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface)
68 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
69 ULONG ref = InterlockedIncrement(&This->ref);
70 return ref;
73 static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface)
75 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
76 ULONG ref = InterlockedDecrement(&This->ref);
77 return ref;
80 static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface,
81 UINT *puiWidth, UINT *puiHeight)
83 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
84 *puiWidth = This->data->width;
85 *puiHeight = This->data->height;
86 return S_OK;
89 static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface,
90 WICPixelFormatGUID *pPixelFormat)
92 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
93 memcpy(pPixelFormat, This->data->format, sizeof(GUID));
94 return S_OK;
97 static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface,
98 double *pDpiX, double *pDpiY)
100 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
101 *pDpiX = This->data->xres;
102 *pDpiY = This->data->yres;
103 return S_OK;
106 static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface,
107 IWICPalette *pIPalette)
109 return E_NOTIMPL;
112 static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface,
113 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
115 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
116 UINT bytesperrow;
117 UINT srcstride;
118 UINT row_offset;
119 WICRect rc;
121 if (!prc)
123 rc.X = 0;
124 rc.Y = 0;
125 rc.Width = This->data->width;
126 rc.Height = This->data->height;
127 prc = &rc;
129 else
131 if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->data->width || prc->Y+prc->Height > This->data->height)
132 return E_INVALIDARG;
135 bytesperrow = ((This->data->bpp * prc->Width)+7)/8;
136 srcstride = ((This->data->bpp * This->data->width)+7)/8;
138 if (cbStride < bytesperrow)
139 return E_INVALIDARG;
141 if ((cbStride * prc->Height) > cbBufferSize)
142 return E_INVALIDARG;
144 row_offset = prc->X * This->data->bpp;
146 if (row_offset % 8 == 0)
148 UINT row;
149 const BYTE *src;
150 BYTE *dst;
152 src = This->data->bits + (row_offset / 8) + prc->Y * srcstride;
153 dst = pbBuffer;
154 for (row=0; row < prc->Height; row++)
156 memcpy(dst, src, bytesperrow);
157 src += srcstride;
158 dst += cbStride;
160 return S_OK;
162 else
164 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface);
165 return E_FAIL;
169 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl = {
170 BitmapTestSrc_QueryInterface,
171 BitmapTestSrc_AddRef,
172 BitmapTestSrc_Release,
173 BitmapTestSrc_GetSize,
174 BitmapTestSrc_GetPixelFormat,
175 BitmapTestSrc_GetResolution,
176 BitmapTestSrc_CopyPalette,
177 BitmapTestSrc_CopyPixels
180 static void CreateTestBitmap(const bitmap_data *data, BitmapTestSrc **This)
182 *This = HeapAlloc(GetProcessHeap(), 0, sizeof(**This));
184 if (*This)
186 (*This)->IWICBitmapSource_iface.lpVtbl = &BitmapTestSrc_Vtbl;
187 (*This)->ref = 1;
188 (*This)->data = data;
192 static void DeleteTestBitmap(BitmapTestSrc *This)
194 ok(This->IWICBitmapSource_iface.lpVtbl == &BitmapTestSrc_Vtbl, "test bitmap %p deleted with incorrect vtable\n", This);
195 ok(This->ref == 1, "test bitmap %p deleted with %i references instead of 1\n", This, This->ref);
196 HeapFree(GetProcessHeap(), 0, This);
199 static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name)
201 BYTE *converted_bits;
202 UINT width, height;
203 double xres, yres;
204 WICRect prc;
205 UINT stride, buffersize;
206 GUID dst_pixelformat;
207 HRESULT hr;
209 hr = IWICBitmapSource_GetSize(source, &width, &height);
210 ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr);
211 ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name);
212 ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name);
214 hr = IWICBitmapSource_GetResolution(source, &xres, &yres);
215 ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr);
216 ok(fabs(xres - expect->xres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name);
217 ok(fabs(yres - expect->yres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name);
219 hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat);
220 ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr);
221 ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format (%s)\n", name);
223 prc.X = 0;
224 prc.Y = 0;
225 prc.Width = expect->width;
226 prc.Height = expect->height;
228 stride = (expect->bpp * expect->width + 7) / 8;
229 buffersize = stride * expect->height;
231 converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
232 hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits);
233 ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr);
234 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
236 /* ignore the padding byte when comparing data */
237 UINT i;
238 BOOL equal=TRUE;
239 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits;
240 for (i=0; i<(buffersize/4); i++)
241 if ((a[i]&0xffffff) != (b[i]&0xffffff))
243 equal = FALSE;
244 break;
246 ok(equal, "unexpected pixel data (%s)\n", name);
248 else
249 ok(memcmp(expect->bits, converted_bits, buffersize) == 0, "unexpected pixel data (%s)\n", name);
251 /* Test with NULL rectangle - should copy the whole bitmap */
252 hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits);
253 ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr);
254 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
256 /* ignore the padding byte when comparing data */
257 UINT i;
258 BOOL equal=TRUE;
259 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits;
260 for (i=0; i<(buffersize/4); i++)
261 if ((a[i]&0xffffff) != (b[i]&0xffffff))
263 equal = FALSE;
264 break;
266 ok(equal, "unexpected pixel data with rc=NULL (%s)\n", name);
268 else
269 ok(memcmp(expect->bits, converted_bits, buffersize) == 0, "unexpected pixel data with rc=NULL (%s)\n", name);
271 HeapFree(GetProcessHeap(), 0, converted_bits);
274 static const BYTE bits_24bppBGR[] = {
275 255,0,0, 0,255,0, 0,0,255, 0,0,0,
276 0,255,255, 255,0,255, 255,255,0, 255,255,255};
277 static const struct bitmap_data testdata_24bppBGR = {
278 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 4, 2, 96.0, 96.0};
280 static const BYTE bits_24bppRGB[] = {
281 0,0,255, 0,255,0, 255,0,0, 0,0,0,
282 255,255,0, 255,0,255, 0,255,255, 255,255,255};
283 static const struct bitmap_data testdata_24bppRGB = {
284 &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 4, 2, 96.0, 96.0};
286 static const BYTE bits_32bppBGR[] = {
287 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
288 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
289 static const struct bitmap_data testdata_32bppBGR = {
290 &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 4, 2, 96.0, 96.0};
292 static const BYTE bits_32bppBGRA[] = {
293 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
294 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
295 static const struct bitmap_data testdata_32bppBGRA = {
296 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 4, 2, 96.0, 96.0};
298 static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo)
300 BitmapTestSrc *src_obj;
301 IWICBitmapSource *dst_bitmap;
302 HRESULT hr;
304 CreateTestBitmap(src, &src_obj);
306 hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
307 if (todo)
308 todo_wine ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
309 else
310 ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
312 if (SUCCEEDED(hr))
314 compare_bitmap_data(dst, dst_bitmap, name);
316 IWICBitmapSource_Release(dst_bitmap);
319 DeleteTestBitmap(src_obj);
322 static void test_invalid_conversion(void)
324 BitmapTestSrc *src_obj;
325 IWICBitmapSource *dst_bitmap;
326 HRESULT hr;
328 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
330 /* convert to a non-pixel-format GUID */
331 hr = WICConvertBitmapSource(&GUID_VendorMicrosoft, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
332 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "WICConvertBitmapSource returned %x\n", hr);
334 DeleteTestBitmap(src_obj);
337 static void test_default_converter(void)
339 BitmapTestSrc *src_obj;
340 IWICFormatConverter *converter;
341 BOOL can_convert=1;
342 HRESULT hr;
344 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
346 hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER,
347 &IID_IWICFormatConverter, (void**)&converter);
348 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
349 if (SUCCEEDED(hr))
351 hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA,
352 &GUID_WICPixelFormat32bppBGR, &can_convert);
353 ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr);
354 ok(can_convert, "expected TRUE, got %i\n", can_convert);
356 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
357 &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.0,
358 WICBitmapPaletteTypeCustom);
359 ok(SUCCEEDED(hr), "Initialize returned %x\n", hr);
361 if (SUCCEEDED(hr))
362 compare_bitmap_data(&testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter");
364 IWICFormatConverter_Release(converter);
367 DeleteTestBitmap(src_obj);
370 typedef struct property_opt_test_data
372 LPCOLESTR name;
373 VARTYPE var_type;
374 VARTYPE initial_var_type;
375 int i_init_val;
376 float f_init_val;
377 } property_opt_test_data;
379 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};
380 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
382 static const struct property_opt_test_data testdata_tiff_props[] = {
383 { wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare },
384 { wszCompressionQuality, VT_R4, VT_EMPTY },
385 { NULL }
388 static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt)
390 int i;
391 for (i=0; i < all_prop_cnt; i++)
393 if (lstrcmpW(name, all_props[i].pstrName) == 0)
394 return i;
396 return -1;
399 static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt)
401 HRESULT hr;
402 int i = 0;
403 VARIANT pvarValue;
404 HRESULT phrError = S_OK;
406 while (data[i].name)
408 int idx = find_property_index(data[i].name, all_props, all_prop_cnt);
409 PROPBAG2 pb = {0};
410 pb.pstrName = (LPOLESTR)data[i].name;
412 hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError);
414 ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n",
415 wine_dbgstr_w(data[i].name));
416 if (idx >= 0)
418 ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n",
419 wine_dbgstr_w(data[i].name), all_props[idx].vt);
420 ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n",
421 wine_dbgstr_w(data[i].name), all_props[idx].dwType);
422 ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n",
423 wine_dbgstr_w(data[i].name), all_props[idx].cfType);
426 ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n",
427 wine_dbgstr_w(data[i].name), hr);
429 if (SUCCEEDED(hr))
431 /* On XP the initial type is always VT_EMPTY */
432 ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY,
433 "Property %s has unexpected initial type, V_VT=%i\n",
434 wine_dbgstr_w(data[i].name), V_VT(&pvarValue));
436 if(V_VT(&pvarValue) == data[i].initial_var_type)
438 switch (data[i].initial_var_type)
440 case VT_BOOL:
441 case VT_UI1:
442 ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n",
443 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal));
444 break;
445 case VT_R4:
446 ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n",
447 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal));
448 break;
449 default:
450 break;
454 VariantClear(&pvarValue);
457 i++;
461 static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *options)
463 HRESULT hr;
464 ULONG cProperties = 0;
465 ULONG cProperties2 = 0;
466 PROPBAG2 all_props[64] = {{0}}; /* Should be enough for every encoder out there */
467 int i;
469 /* CountProperties */
471 hr = IPropertyBag2_CountProperties(options, &cProperties);
472 ok(SUCCEEDED(hr), "Reading property count, hr=%x\n", hr);
475 /* GetPropertyInfo */
477 hr = IPropertyBag2_GetPropertyInfo(options, cProperties, 1, all_props, &cProperties2);
478 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - iProperty out of bounce handled wrong, hr=%x\n", hr);
480 hr = IPropertyBag2_GetPropertyInfo(options, 0, cProperties+1, all_props, &cProperties2);
481 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - cProperty out of bounce handled wrong, hr=%x\n", hr);
483 if (cProperties == 0) /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */
485 cProperties2 = cProperties;
486 hr = S_OK;
488 else
490 hr = IPropertyBag2_GetPropertyInfo(options, 0, min(64, cProperties), all_props, &cProperties2);
491 ok(SUCCEEDED(hr), "Reading infos from property bag failed, hr=%x\n", hr);
494 if (FAILED(hr))
495 return;
497 ok(cProperties == cProperties2, "Missmatch of property count (IPropertyBag2::CountProperties=%i, IPropertyBag2::GetPropertyInfo=%i)\n",
498 (int)cProperties, (int)cProperties2);
501 if (clsid_encoder == &CLSID_WICTiffEncoder)
502 test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2);
504 for (i=0; i < cProperties2; i++)
506 ok(all_props[i].pstrName != NULL, "Unset property name in output of IPropertyBag2::GetPropertyInfo\n");
507 CoTaskMemFree(all_props[i].pstrName);
511 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
512 const struct bitmap_data **dsts, const CLSID *clsid_decoder, const char *name)
514 HRESULT hr;
515 IWICBitmapEncoder *encoder;
516 BitmapTestSrc *src_obj;
517 HGLOBAL hglobal;
518 IStream *stream;
519 IWICBitmapFrameEncode *frameencode;
520 IPropertyBag2 *options=NULL;
521 IWICBitmapDecoder *decoder;
522 IWICBitmapFrameDecode *framedecode;
523 WICPixelFormatGUID pixelformat;
524 int i;
526 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
527 &IID_IWICBitmapEncoder, (void**)&encoder);
528 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
529 if (SUCCEEDED(hr))
531 hglobal = GlobalAlloc(GMEM_MOVEABLE, 0);
532 ok(hglobal != NULL, "GlobalAlloc failed\n");
533 if (hglobal)
535 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
536 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
539 if (hglobal && SUCCEEDED(hr))
541 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
542 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
544 i=0;
545 while (SUCCEEDED(hr) && srcs[i])
547 CreateTestBitmap(srcs[i], &src_obj);
549 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options);
550 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr);
551 if (SUCCEEDED(hr))
553 ok(options != NULL, "Encoder initialization has not created an property bag\n");
554 if(options)
555 test_encoder_properties(clsid_encoder, options);
557 hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
558 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
560 memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
561 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
562 ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
563 ok(IsEqualGUID(&pixelformat, srcs[i]->format), "SetPixelFormat changed the format\n");
565 hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
566 ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
568 hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, NULL);
569 ok(SUCCEEDED(hr), "WriteSource failed, hr=%x\n", hr);
571 hr = IWICBitmapFrameEncode_Commit(frameencode);
572 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
574 IWICBitmapFrameEncode_Release(frameencode);
575 IPropertyBag2_Release(options);
578 DeleteTestBitmap(src_obj);
580 i++;
583 if (SUCCEEDED(hr))
585 hr = IWICBitmapEncoder_Commit(encoder);
586 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
589 if (SUCCEEDED(hr))
591 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER,
592 &IID_IWICBitmapDecoder, (void**)&decoder);
593 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
596 if (SUCCEEDED(hr))
598 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
599 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
601 i=0;
602 while (SUCCEEDED(hr) && dsts[i])
604 hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
605 ok(SUCCEEDED(hr), "GetFrame failed, hr=%x\n", hr);
607 if (SUCCEEDED(hr))
609 compare_bitmap_data(dsts[i], (IWICBitmapSource*)framedecode, name);
611 IWICBitmapFrameDecode_Release(framedecode);
614 i++;
617 IWICBitmapDecoder_Release(decoder);
620 IStream_Release(stream);
623 IWICBitmapEncoder_Release(encoder);
627 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder,
628 const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name)
630 const struct bitmap_data *srcs[2];
631 const struct bitmap_data *dsts[2];
633 srcs[0] = src;
634 srcs[1] = NULL;
635 dsts[0] = dst;
636 dsts[1] = NULL;
638 test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, name);
641 static const struct bitmap_data *multiple_frames[3] = {
642 &testdata_24bppBGR,
643 &testdata_24bppBGR,
644 NULL};
646 START_TEST(converter)
648 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
650 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", 0);
651 test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", 0);
652 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", 0);
654 test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", 0);
655 test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", 0);
657 test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", 0);
658 test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", 0);
660 test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", 0);
661 test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", 0);
663 test_invalid_conversion();
664 test_default_converter();
666 test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
667 &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
669 test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
670 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
672 test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
673 &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
675 test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
676 multiple_frames, &CLSID_WICTiffDecoder, "TIFF encoder multi-frame");
678 CoUninitialize();