c7b516c42a8235d8f61e59f9e31bb7731fcdf8ac
[reactos.git] / rostests / winetests / windowscodecs / converter.c
1 /*
2 * Copyright 2009 Vincent Povirk
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include <stdarg.h>
20 #include <math.h>
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #define COBJMACROS
27 #define CONST_VTABLE
28
29 #include <windef.h>
30 #include <winbase.h>
31 #include <ole2.h>
32 #include <wincodec.h>
33 #include <wine/test.h>
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 } bitmap_data;
44
45 typedef struct BitmapTestSrc {
46 IWICBitmapSource IWICBitmapSource_iface;
47 LONG ref;
48 const bitmap_data *data;
49 } BitmapTestSrc;
50
51 static inline BitmapTestSrc *impl_from_IWICBitmapSource(IWICBitmapSource *iface)
52 {
53 return CONTAINING_RECORD(iface, BitmapTestSrc, IWICBitmapSource_iface);
54 }
55
56 static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid,
57 void **ppv)
58 {
59 if (!ppv) return E_INVALIDARG;
60
61 if (IsEqualIID(&IID_IUnknown, iid) ||
62 IsEqualIID(&IID_IWICBitmapSource, iid))
63 *ppv = iface;
64 else
65 return E_NOINTERFACE;
66
67 IUnknown_AddRef((IUnknown*)*ppv);
68 return S_OK;
69 }
70
71 static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface)
72 {
73 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
74 ULONG ref = InterlockedIncrement(&This->ref);
75 return ref;
76 }
77
78 static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface)
79 {
80 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
81 ULONG ref = InterlockedDecrement(&This->ref);
82 return ref;
83 }
84
85 static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface,
86 UINT *puiWidth, UINT *puiHeight)
87 {
88 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
89 *puiWidth = This->data->width;
90 *puiHeight = This->data->height;
91 return S_OK;
92 }
93
94 static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface,
95 WICPixelFormatGUID *pPixelFormat)
96 {
97 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
98 memcpy(pPixelFormat, This->data->format, sizeof(GUID));
99 return S_OK;
100 }
101
102 static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface,
103 double *pDpiX, double *pDpiY)
104 {
105 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
106 *pDpiX = This->data->xres;
107 *pDpiY = This->data->yres;
108 return S_OK;
109 }
110
111 static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface,
112 IWICPalette *pIPalette)
113 {
114 return E_NOTIMPL;
115 }
116
117 static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface,
118 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
119 {
120 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
121 UINT bytesperrow;
122 UINT srcstride;
123 UINT row_offset;
124 WICRect rc;
125
126 if (!prc)
127 {
128 rc.X = 0;
129 rc.Y = 0;
130 rc.Width = This->data->width;
131 rc.Height = This->data->height;
132 prc = &rc;
133 }
134 else
135 {
136 if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->data->width || prc->Y+prc->Height > This->data->height)
137 return E_INVALIDARG;
138 }
139
140 bytesperrow = ((This->data->bpp * prc->Width)+7)/8;
141 srcstride = ((This->data->bpp * This->data->width)+7)/8;
142
143 if (cbStride < bytesperrow)
144 return E_INVALIDARG;
145
146 if ((cbStride * prc->Height) > cbBufferSize)
147 return E_INVALIDARG;
148
149 row_offset = prc->X * This->data->bpp;
150
151 if (row_offset % 8 == 0)
152 {
153 UINT row;
154 const BYTE *src;
155 BYTE *dst;
156
157 src = This->data->bits + (row_offset / 8) + prc->Y * srcstride;
158 dst = pbBuffer;
159 for (row=0; row < prc->Height; row++)
160 {
161 memcpy(dst, src, bytesperrow);
162 src += srcstride;
163 dst += cbStride;
164 }
165 return S_OK;
166 }
167 else
168 {
169 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface);
170 return E_FAIL;
171 }
172 }
173
174 static const IWICBitmapSourceVtbl BitmapTestSrc_Vtbl = {
175 BitmapTestSrc_QueryInterface,
176 BitmapTestSrc_AddRef,
177 BitmapTestSrc_Release,
178 BitmapTestSrc_GetSize,
179 BitmapTestSrc_GetPixelFormat,
180 BitmapTestSrc_GetResolution,
181 BitmapTestSrc_CopyPalette,
182 BitmapTestSrc_CopyPixels
183 };
184
185 static void CreateTestBitmap(const bitmap_data *data, BitmapTestSrc **This)
186 {
187 *This = HeapAlloc(GetProcessHeap(), 0, sizeof(**This));
188
189 if (*This)
190 {
191 (*This)->IWICBitmapSource_iface.lpVtbl = &BitmapTestSrc_Vtbl;
192 (*This)->ref = 1;
193 (*This)->data = data;
194 }
195 }
196
197 static void DeleteTestBitmap(BitmapTestSrc *This)
198 {
199 ok(This->IWICBitmapSource_iface.lpVtbl == &BitmapTestSrc_Vtbl, "test bitmap %p deleted with incorrect vtable\n", This);
200 ok(This->ref == 1, "test bitmap %p deleted with %i references instead of 1\n", This, This->ref);
201 HeapFree(GetProcessHeap(), 0, This);
202 }
203
204 static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name)
205 {
206 BYTE *converted_bits;
207 UINT width, height;
208 double xres, yres;
209 WICRect prc;
210 UINT stride, buffersize;
211 GUID dst_pixelformat;
212 HRESULT hr;
213
214 hr = IWICBitmapSource_GetSize(source, &width, &height);
215 ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr);
216 ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name);
217 ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name);
218
219 hr = IWICBitmapSource_GetResolution(source, &xres, &yres);
220 ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr);
221 ok(fabs(xres - expect->xres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name);
222 ok(fabs(yres - expect->yres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name);
223
224 hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat);
225 ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr);
226 ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format (%s)\n", name);
227
228 prc.X = 0;
229 prc.Y = 0;
230 prc.Width = expect->width;
231 prc.Height = expect->height;
232
233 stride = (expect->bpp * expect->width + 7) / 8;
234 buffersize = stride * expect->height;
235
236 converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
237 hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits);
238 ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr);
239 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
240 {
241 /* ignore the padding byte when comparing data */
242 UINT i;
243 BOOL equal=TRUE;
244 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits;
245 for (i=0; i<(buffersize/4); i++)
246 if ((a[i]&0xffffff) != (b[i]&0xffffff))
247 {
248 equal = FALSE;
249 break;
250 }
251 ok(equal, "unexpected pixel data (%s)\n", name);
252 }
253 else
254 ok(memcmp(expect->bits, converted_bits, buffersize) == 0, "unexpected pixel data (%s)\n", name);
255
256 /* Test with NULL rectangle - should copy the whole bitmap */
257 hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits);
258 ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr);
259 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
260 {
261 /* ignore the padding byte when comparing data */
262 UINT i;
263 BOOL equal=TRUE;
264 const DWORD *a=(const DWORD*)expect->bits, *b=(const DWORD*)converted_bits;
265 for (i=0; i<(buffersize/4); i++)
266 if ((a[i]&0xffffff) != (b[i]&0xffffff))
267 {
268 equal = FALSE;
269 break;
270 }
271 ok(equal, "unexpected pixel data with rc=NULL (%s)\n", name);
272 }
273 else
274 ok(memcmp(expect->bits, converted_bits, buffersize) == 0, "unexpected pixel data with rc=NULL (%s)\n", name);
275
276 HeapFree(GetProcessHeap(), 0, converted_bits);
277 }
278
279 static const BYTE bits_24bppBGR[] = {
280 255,0,0, 0,255,0, 0,0,255, 0,0,0,
281 0,255,255, 255,0,255, 255,255,0, 255,255,255};
282 static const struct bitmap_data testdata_24bppBGR = {
283 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 4, 2, 96.0, 96.0};
284
285 static const BYTE bits_24bppRGB[] = {
286 0,0,255, 0,255,0, 255,0,0, 0,0,0,
287 255,255,0, 255,0,255, 0,255,255, 255,255,255};
288 static const struct bitmap_data testdata_24bppRGB = {
289 &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 4, 2, 96.0, 96.0};
290
291 static const BYTE bits_32bppBGR[] = {
292 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80,
293 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80};
294 static const struct bitmap_data testdata_32bppBGR = {
295 &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 4, 2, 96.0, 96.0};
296
297 static const BYTE bits_32bppBGRA[] = {
298 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255,
299 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255};
300 static const struct bitmap_data testdata_32bppBGRA = {
301 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 4, 2, 96.0, 96.0};
302
303 static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo)
304 {
305 BitmapTestSrc *src_obj;
306 IWICBitmapSource *dst_bitmap;
307 HRESULT hr;
308
309 CreateTestBitmap(src, &src_obj);
310
311 hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
312 if (todo)
313 todo_wine ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
314 else
315 ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
316
317 if (SUCCEEDED(hr))
318 {
319 compare_bitmap_data(dst, dst_bitmap, name);
320
321 IWICBitmapSource_Release(dst_bitmap);
322 }
323
324 DeleteTestBitmap(src_obj);
325 }
326
327 static void test_invalid_conversion(void)
328 {
329 BitmapTestSrc *src_obj;
330 IWICBitmapSource *dst_bitmap;
331 HRESULT hr;
332
333 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
334
335 /* convert to a non-pixel-format GUID */
336 hr = WICConvertBitmapSource(&GUID_VendorMicrosoft, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
337 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "WICConvertBitmapSource returned %x\n", hr);
338
339 DeleteTestBitmap(src_obj);
340 }
341
342 static void test_default_converter(void)
343 {
344 BitmapTestSrc *src_obj;
345 IWICFormatConverter *converter;
346 BOOL can_convert=1;
347 HRESULT hr;
348
349 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
350
351 hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER,
352 &IID_IWICFormatConverter, (void**)&converter);
353 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
354 if (SUCCEEDED(hr))
355 {
356 hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA,
357 &GUID_WICPixelFormat32bppBGR, &can_convert);
358 ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr);
359 ok(can_convert, "expected TRUE, got %i\n", can_convert);
360
361 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
362 &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.0,
363 WICBitmapPaletteTypeCustom);
364 ok(SUCCEEDED(hr), "Initialize returned %x\n", hr);
365
366 if (SUCCEEDED(hr))
367 compare_bitmap_data(&testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter");
368
369 IWICFormatConverter_Release(converter);
370 }
371
372 DeleteTestBitmap(src_obj);
373 }
374
375 typedef struct property_opt_test_data
376 {
377 LPCOLESTR name;
378 VARTYPE var_type;
379 VARTYPE initial_var_type;
380 int i_init_val;
381 float f_init_val;
382 } property_opt_test_data;
383
384 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};
385 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
386
387 static const struct property_opt_test_data testdata_tiff_props[] = {
388 { wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare },
389 { wszCompressionQuality, VT_R4, VT_EMPTY },
390 { NULL }
391 };
392
393 static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt)
394 {
395 int i;
396 for (i=0; i < all_prop_cnt; i++)
397 {
398 if (lstrcmpW(name, all_props[i].pstrName) == 0)
399 return i;
400 }
401 return -1;
402 }
403
404 static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt)
405 {
406 HRESULT hr;
407 int i = 0;
408 VARIANT pvarValue;
409 HRESULT phrError = S_OK;
410
411 while (data[i].name)
412 {
413 int idx = find_property_index(data[i].name, all_props, all_prop_cnt);
414 PROPBAG2 pb = {0};
415 pb.pstrName = (LPOLESTR)data[i].name;
416
417 hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError);
418
419 ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n",
420 wine_dbgstr_w(data[i].name));
421 if (idx >= 0)
422 {
423 ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n",
424 wine_dbgstr_w(data[i].name), all_props[idx].vt);
425 ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n",
426 wine_dbgstr_w(data[i].name), all_props[idx].dwType);
427 ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n",
428 wine_dbgstr_w(data[i].name), all_props[idx].cfType);
429 }
430
431 ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n",
432 wine_dbgstr_w(data[i].name), hr);
433
434 if (SUCCEEDED(hr))
435 {
436 /* On XP the initial type is always VT_EMPTY */
437 ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY,
438 "Property %s has unexpected initial type, V_VT=%i\n",
439 wine_dbgstr_w(data[i].name), V_VT(&pvarValue));
440
441 if(V_VT(&pvarValue) == data[i].initial_var_type)
442 {
443 switch (data[i].initial_var_type)
444 {
445 case VT_BOOL:
446 case VT_UI1:
447 ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n",
448 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal));
449 break;
450 case VT_R4:
451 ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n",
452 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal));
453 break;
454 default:
455 break;
456 }
457 }
458
459 VariantClear(&pvarValue);
460 }
461
462 i++;
463 }
464 }
465
466 static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *options)
467 {
468 HRESULT hr;
469 ULONG cProperties = 0;
470 ULONG cProperties2 = 0;
471 PROPBAG2 all_props[64] = {{0}}; /* Should be enough for every encoder out there */
472 int i;
473
474 /* CountProperties */
475 {
476 hr = IPropertyBag2_CountProperties(options, &cProperties);
477 ok(SUCCEEDED(hr), "Reading property count, hr=%x\n", hr);
478 }
479
480 /* GetPropertyInfo */
481 {
482 hr = IPropertyBag2_GetPropertyInfo(options, cProperties, 1, all_props, &cProperties2);
483 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - iProperty out of bounce handled wrong, hr=%x\n", hr);
484
485 hr = IPropertyBag2_GetPropertyInfo(options, 0, cProperties+1, all_props, &cProperties2);
486 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - cProperty out of bounce handled wrong, hr=%x\n", hr);
487
488 if (cProperties == 0) /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */
489 {
490 cProperties2 = cProperties;
491 hr = S_OK;
492 }
493 else
494 {
495 hr = IPropertyBag2_GetPropertyInfo(options, 0, min(64, cProperties), all_props, &cProperties2);
496 ok(SUCCEEDED(hr), "Reading infos from property bag failed, hr=%x\n", hr);
497 }
498
499 if (FAILED(hr))
500 return;
501
502 ok(cProperties == cProperties2, "Missmatch of property count (IPropertyBag2::CountProperties=%i, IPropertyBag2::GetPropertyInfo=%i)\n",
503 (int)cProperties, (int)cProperties2);
504 }
505
506 if (clsid_encoder == &CLSID_WICTiffEncoder)
507 test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2);
508
509 for (i=0; i < cProperties2; i++)
510 {
511 ok(all_props[i].pstrName != NULL, "Unset property name in output of IPropertyBag2::GetPropertyInfo\n");
512 CoTaskMemFree(all_props[i].pstrName);
513 }
514 }
515
516 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
517 const struct bitmap_data **dsts, const CLSID *clsid_decoder, const char *name)
518 {
519 HRESULT hr;
520 IWICBitmapEncoder *encoder;
521 BitmapTestSrc *src_obj;
522 HGLOBAL hglobal;
523 IStream *stream;
524 IWICBitmapFrameEncode *frameencode;
525 IPropertyBag2 *options=NULL;
526 IWICBitmapDecoder *decoder;
527 IWICBitmapFrameDecode *framedecode;
528 WICPixelFormatGUID pixelformat;
529 int i;
530
531 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
532 &IID_IWICBitmapEncoder, (void**)&encoder);
533 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
534 if (SUCCEEDED(hr))
535 {
536 hglobal = GlobalAlloc(GMEM_MOVEABLE, 0);
537 ok(hglobal != NULL, "GlobalAlloc failed\n");
538 if (hglobal)
539 {
540 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
541 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
542 }
543
544 if (hglobal && SUCCEEDED(hr))
545 {
546 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
547 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
548
549 i=0;
550 while (SUCCEEDED(hr) && srcs[i])
551 {
552 CreateTestBitmap(srcs[i], &src_obj);
553
554 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options);
555 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr);
556 if (SUCCEEDED(hr))
557 {
558 ok(options != NULL, "Encoder initialization has not created an property bag\n");
559 if(options)
560 test_encoder_properties(clsid_encoder, options);
561
562 hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
563 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
564
565 memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
566 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
567 ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
568 ok(IsEqualGUID(&pixelformat, srcs[i]->format), "SetPixelFormat changed the format\n");
569
570 hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
571 ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
572
573 hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, NULL);
574 ok(SUCCEEDED(hr), "WriteSource failed, hr=%x\n", hr);
575
576 hr = IWICBitmapFrameEncode_Commit(frameencode);
577 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
578
579 IWICBitmapFrameEncode_Release(frameencode);
580 IPropertyBag2_Release(options);
581 }
582
583 DeleteTestBitmap(src_obj);
584
585 i++;
586 }
587
588 if (SUCCEEDED(hr))
589 {
590 hr = IWICBitmapEncoder_Commit(encoder);
591 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
592 }
593
594 if (SUCCEEDED(hr))
595 {
596 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER,
597 &IID_IWICBitmapDecoder, (void**)&decoder);
598 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
599 }
600
601 if (SUCCEEDED(hr))
602 {
603 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
604 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
605
606 i=0;
607 while (SUCCEEDED(hr) && dsts[i])
608 {
609 hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
610 ok(SUCCEEDED(hr), "GetFrame failed, hr=%x\n", hr);
611
612 if (SUCCEEDED(hr))
613 {
614 compare_bitmap_data(dsts[i], (IWICBitmapSource*)framedecode, name);
615
616 IWICBitmapFrameDecode_Release(framedecode);
617 }
618
619 i++;
620 }
621
622 IWICBitmapDecoder_Release(decoder);
623 }
624
625 IStream_Release(stream);
626 }
627
628 IWICBitmapEncoder_Release(encoder);
629 }
630 }
631
632 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder,
633 const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name)
634 {
635 const struct bitmap_data *srcs[2];
636 const struct bitmap_data *dsts[2];
637
638 srcs[0] = src;
639 srcs[1] = NULL;
640 dsts[0] = dst;
641 dsts[1] = NULL;
642
643 test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, name);
644 }
645
646 static const struct bitmap_data *multiple_frames[3] = {
647 &testdata_24bppBGR,
648 &testdata_24bppBGR,
649 NULL};
650
651 START_TEST(converter)
652 {
653 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
654
655 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", 0);
656 test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", 0);
657 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", 0);
658
659 test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", 0);
660 test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", 0);
661
662 test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", 0);
663 test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", 0);
664
665 test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", 0);
666 test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", 0);
667
668 test_invalid_conversion();
669 test_default_converter();
670
671 test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
672 &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
673
674 test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
675 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
676
677 test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
678 &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
679
680 test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
681 multiple_frames, &CLSID_WICTiffDecoder, "TIFF encoder multi-frame");
682
683 CoUninitialize();
684 }