windowscodecs/tests: Add a bunch of new tests for indexed format conversions.
[wine.git] / dlls / windowscodecs / tests / converter.c
blob481e5636b9afef72a8cfc9cfc8153be49ed36e5c
1 /*
2 * Copyright 2009 Vincent Povirk
3 * Copyright 2016 Dmitry Timoshkov
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.
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.
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
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <math.h>
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include "windef.h"
28 #include "objbase.h"
29 #include "wincodec.h"
30 #include "wincodecsdk.h"
31 #include "wine/test.h"
33 static IWICImagingFactory *factory;
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;
46 typedef struct BitmapTestSrc {
47 IWICBitmapSource IWICBitmapSource_iface;
48 LONG ref;
49 const bitmap_data *data;
50 } BitmapTestSrc;
52 extern HRESULT STDMETHODCALLTYPE IWICBitmapFrameEncode_WriteSource_Proxy(IWICBitmapFrameEncode* This,
53 IWICBitmapSource *pIBitmapSource, WICRect *prc);
55 static BOOL near_equal(float a, float b)
57 return fabsf(a - b) < 0.001;
60 static inline BitmapTestSrc *impl_from_IWICBitmapSource(IWICBitmapSource *iface)
62 return CONTAINING_RECORD(iface, BitmapTestSrc, IWICBitmapSource_iface);
65 static HRESULT WINAPI BitmapTestSrc_QueryInterface(IWICBitmapSource *iface, REFIID iid,
66 void **ppv)
68 if (!ppv) return E_INVALIDARG;
70 if (IsEqualIID(&IID_IUnknown, iid) ||
71 IsEqualIID(&IID_IWICBitmapSource, iid))
72 *ppv = iface;
73 else
74 return E_NOINTERFACE;
76 IUnknown_AddRef((IUnknown*)*ppv);
77 return S_OK;
80 static ULONG WINAPI BitmapTestSrc_AddRef(IWICBitmapSource *iface)
82 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
83 ULONG ref = InterlockedIncrement(&This->ref);
84 return ref;
87 static ULONG WINAPI BitmapTestSrc_Release(IWICBitmapSource *iface)
89 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
90 ULONG ref = InterlockedDecrement(&This->ref);
91 return ref;
94 static HRESULT WINAPI BitmapTestSrc_GetSize(IWICBitmapSource *iface,
95 UINT *puiWidth, UINT *puiHeight)
97 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
98 *puiWidth = This->data->width;
99 *puiHeight = This->data->height;
100 return S_OK;
103 static HRESULT WINAPI BitmapTestSrc_GetPixelFormat(IWICBitmapSource *iface,
104 WICPixelFormatGUID *pPixelFormat)
106 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
107 memcpy(pPixelFormat, This->data->format, sizeof(GUID));
108 return S_OK;
111 static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface,
112 double *pDpiX, double *pDpiY)
114 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
115 *pDpiX = This->data->xres;
116 *pDpiY = This->data->yres;
117 return S_OK;
120 static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface,
121 IWICPalette *palette)
123 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
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))
130 WICColor colors[8];
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);
143 /* unique error marker */
144 return 0xdeadbeef;
147 static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface,
148 const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
150 BitmapTestSrc *This = impl_from_IWICBitmapSource(iface);
151 UINT bytesperrow;
152 UINT srcstride;
153 UINT row_offset;
154 WICRect rc;
156 if (!prc)
158 rc.X = 0;
159 rc.Y = 0;
160 rc.Width = This->data->width;
161 rc.Height = This->data->height;
162 prc = &rc;
164 else
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;
170 bytesperrow = ((This->data->bpp * prc->Width)+7)/8;
171 srcstride = ((This->data->bpp * This->data->width)+7)/8;
173 if (cbStride < bytesperrow)
174 return E_INVALIDARG;
176 if ((cbStride * prc->Height) > cbBufferSize)
177 return E_INVALIDARG;
179 row_offset = prc->X * This->data->bpp;
181 if (row_offset % 8 == 0)
183 UINT row;
184 const BYTE *src;
185 BYTE *dst;
187 src = This->data->bits + (row_offset / 8) + prc->Y * srcstride;
188 dst = pbBuffer;
189 for (row=0; row < prc->Height; row++)
191 memcpy(dst, src, bytesperrow);
192 src += srcstride;
193 dst += cbStride;
195 return S_OK;
197 else
199 ok(0, "bitmap %p was asked to copy pixels not aligned on a byte boundary\n", iface);
200 return E_FAIL;
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
215 static void CreateTestBitmap(const bitmap_data *data, BitmapTestSrc **This)
217 *This = HeapAlloc(GetProcessHeap(), 0, sizeof(**This));
219 if (*This)
221 (*This)->IWICBitmapSource_iface.lpVtbl = &BitmapTestSrc_Vtbl;
222 (*This)->ref = 1;
223 (*This)->data = data;
227 static void DeleteTestBitmap(BitmapTestSrc *This)
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);
234 static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, const BYTE *converted_bits)
236 BOOL equal;
238 if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppBGR))
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))
247 equal = FALSE;
248 break;
251 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat32bppGrayFloat))
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]))
259 equal = FALSE;
260 break;
263 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormatBlackWhite) ||
264 IsEqualGUID(expect->format, &GUID_WICPixelFormat1bppIndexed))
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 */)
272 equal = FALSE;
273 break;
276 else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat2bppIndexed) ||
277 IsEqualGUID(expect->format, &GUID_WICPixelFormat4bppIndexed) ||
278 IsEqualGUID(expect->format, &GUID_WICPixelFormat8bppIndexed))
280 UINT i;
281 const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits;
282 equal=TRUE;
284 for (i=0; i<buffersize; i++)
285 if (a[i] != b[i])
287 equal = FALSE;
288 break;
291 else
292 equal = (memcmp(expect->bits, converted_bits, buffersize) == 0);
294 if (!equal && expect->alt_data)
295 equal = compare_bits(expect->alt_data, buffersize, converted_bits);
297 return equal;
300 static BOOL is_indexed_format(const GUID *format)
302 if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed) ||
303 IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed) ||
304 IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed) ||
305 IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
306 return TRUE;
308 return FALSE;
311 static void compare_bitmap_data(const struct bitmap_data *src, const struct bitmap_data *expect,
312 IWICBitmapSource *source, const char *name)
314 BYTE *converted_bits;
315 UINT width, height;
316 double xres, yres;
317 WICRect prc;
318 UINT stride, buffersize;
319 GUID dst_pixelformat;
320 HRESULT hr;
322 hr = IWICBitmapSource_GetSize(source, &width, &height);
323 ok(SUCCEEDED(hr), "GetSize(%s) failed, hr=%x\n", name, hr);
324 ok(width == expect->width, "expecting %u, got %u (%s)\n", expect->width, width, name);
325 ok(height == expect->height, "expecting %u, got %u (%s)\n", expect->height, height, name);
327 hr = IWICBitmapSource_GetResolution(source, &xres, &yres);
328 ok(SUCCEEDED(hr), "GetResolution(%s) failed, hr=%x\n", name, hr);
329 ok(fabs(xres - expect->xres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->xres, xres, name);
330 ok(fabs(yres - expect->yres) < 0.02, "expecting %0.2f, got %0.2f (%s)\n", expect->yres, yres, name);
332 hr = IWICBitmapSource_GetPixelFormat(source, &dst_pixelformat);
333 ok(SUCCEEDED(hr), "GetPixelFormat(%s) failed, hr=%x\n", name, hr);
334 ok(IsEqualGUID(&dst_pixelformat, expect->format), "got unexpected pixel format %s (%s)\n", wine_dbgstr_guid(&dst_pixelformat), name);
336 prc.X = 0;
337 prc.Y = 0;
338 prc.Width = expect->width;
339 prc.Height = expect->height;
341 stride = (expect->bpp * expect->width + 7) / 8;
342 buffersize = stride * expect->height;
344 converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize);
345 memset(converted_bits, 0xaa, buffersize);
346 hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits);
347 ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr);
349 /* The result of conversion of color to indexed formats depends on
350 * optimized palette generation implementation. We either need to
351 * assign our own palette, or just skip the comparison.
353 if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format)))
354 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name);
356 /* Test with NULL rectangle - should copy the whole bitmap */
357 memset(converted_bits, 0xaa, buffersize);
358 hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits);
359 ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr);
360 /* see comment above */
361 if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format)))
362 ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name);
364 HeapFree(GetProcessHeap(), 0, converted_bits);
367 /* some encoders (like BMP) require data to be 4-bytes aligned */
368 static const BYTE bits_1bpp[] = {
369 0x55,0x55,0x55,0x55, /*01010101*/
370 0xaa,0xaa,0xaa,0xaa}; /*10101010*/
371 static const struct bitmap_data testdata_BlackWhite = {
372 &GUID_WICPixelFormatBlackWhite, 1, bits_1bpp, 32, 2, 96.0, 96.0};
373 static const struct bitmap_data testdata_1bppIndexed = {
374 &GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0};
376 /* some encoders (like BMP) require data to be 4-bytes aligned */
377 static const BYTE bits_2bpp[] = {
378 0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,
379 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24};
380 static const struct bitmap_data testdata_2bppIndexed = {
381 &GUID_WICPixelFormat2bppIndexed, 2, bits_2bpp, 32, 2, 96.0, 96.0};
383 /* some encoders (like BMP) require data to be 4-bytes aligned */
384 static const BYTE bits_4bpp[] = {
385 0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,0x34,0x43,
386 0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44};
388 static const struct bitmap_data testdata_4bppIndexed = {
389 &GUID_WICPixelFormat4bppIndexed, 4, bits_4bpp, 32, 2, 96.0, 96.0};
391 static const BYTE bits_8bpp_BW[] = {
392 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,
393 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};
394 static const struct bitmap_data testdata_8bppIndexed_BW = {
395 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_BW, 32, 2, 96.0, 96.0};
397 static const BYTE bits_8bpp_4colors[] = {
398 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,
399 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};
400 static const struct bitmap_data testdata_8bppIndexed_4colors = {
401 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_4colors, 32, 2, 96.0, 96.0};
403 static const BYTE bits_8bpp[] = {
404 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,
405 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
406 static const struct bitmap_data testdata_8bppIndexed = {
407 &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 32, 2, 96.0, 96.0};
409 static const BYTE bits_24bppBGR[] = {
410 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
411 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
412 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
413 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0,
414 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255,
415 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255,
416 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255,
417 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255};
418 static const struct bitmap_data testdata_24bppBGR = {
419 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 32, 2, 96.0, 96.0};
421 static const BYTE bits_24bppRGB[] = {
422 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
423 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
424 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
425 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0,
426 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255,
427 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255,
428 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255,
429 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255 };
430 static const struct bitmap_data testdata_24bppRGB = {
431 &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 32, 2, 96.0, 96.0};
433 static const BYTE bits_32bppBGR[] = {
434 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,
435 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,
436 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,
437 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,
438 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,
439 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,
440 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,
441 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};
442 static const struct bitmap_data testdata_32bppBGR = {
443 &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 32, 2, 96.0, 96.0};
445 static const BYTE bits_32bppBGRA[] = {
446 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,
447 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,
448 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,
449 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,
450 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,
451 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,
452 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,
453 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};
454 static const struct bitmap_data testdata_32bppBGRA = {
455 &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0};
457 /* XP and 2003 use linear color conversion, later versions use sRGB gamma */
458 static const float bits_32bppGrayFloat_xp[] = {
459 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
460 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
461 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
462 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f,
463 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f,
464 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f,
465 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f,
466 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f};
467 static const struct bitmap_data testdata_32bppGrayFloat_xp = {
468 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat_xp, 32, 2, 96.0, 96.0};
470 static const float bits_32bppGrayFloat[] = {
471 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
472 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
473 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
474 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f,
475 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f,
476 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f,
477 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f,
478 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f};
479 static const struct bitmap_data testdata_32bppGrayFloat = {
480 &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 32, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp};
482 static const BYTE bits_8bppGray_xp[] = {
483 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0,
484 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0,
485 226,105,179,255,226,105,179,255,226,105,179,255,226,105,179,255,
486 226,105,179,255,226,105,179,255,226,105,179,255,226,105,179,255};
487 static const struct bitmap_data testdata_8bppGray_xp = {
488 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray_xp, 32, 2, 96.0, 96.0};
490 static const BYTE bits_8bppGray[] = {
491 76,220,127,0,76,220,127,0,76,220,127,0,76,220,127,0,
492 76,220,127,0,76,220,127,0,76,220,127,0,76,220,127,0,
493 247,145,230,255,247,145,230,255,247,145,230,255,247,145,230,255,
494 247,145,230,255,247,145,230,255,247,145,230,255,247,145,230,255};
495 static const struct bitmap_data testdata_8bppGray = {
496 &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray, 32, 2, 96.0, 96.0, &testdata_8bppGray_xp};
498 static const BYTE bits_24bppBGR_gray[] = {
499 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
500 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
501 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
502 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0,
503 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255,
504 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255,
505 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255,
506 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255};
507 static const struct bitmap_data testdata_24bppBGR_gray = {
508 &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_gray, 32, 2, 96.0, 96.0};
510 static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo)
512 BitmapTestSrc *src_obj;
513 IWICBitmapSource *dst_bitmap;
514 HRESULT hr;
516 CreateTestBitmap(src, &src_obj);
518 hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
519 todo_wine_if (todo)
520 ok(hr == S_OK ||
521 broken(hr == E_INVALIDARG) /* XP */, "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr);
523 if (hr == S_OK)
525 compare_bitmap_data(src, dst, dst_bitmap, name);
527 IWICBitmapSource_Release(dst_bitmap);
530 DeleteTestBitmap(src_obj);
533 static void test_invalid_conversion(void)
535 BitmapTestSrc *src_obj;
536 IWICBitmapSource *dst_bitmap;
537 HRESULT hr;
539 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
541 /* convert to a non-pixel-format GUID */
542 hr = WICConvertBitmapSource(&GUID_VendorMicrosoft, &src_obj->IWICBitmapSource_iface, &dst_bitmap);
543 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "WICConvertBitmapSource returned %x\n", hr);
545 DeleteTestBitmap(src_obj);
548 static void test_default_converter(void)
550 BitmapTestSrc *src_obj;
551 IWICFormatConverter *converter;
552 BOOL can_convert = TRUE;
553 HRESULT hr;
555 CreateTestBitmap(&testdata_32bppBGRA, &src_obj);
557 hr = CoCreateInstance(&CLSID_WICDefaultFormatConverter, NULL, CLSCTX_INPROC_SERVER,
558 &IID_IWICFormatConverter, (void**)&converter);
559 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
560 if (SUCCEEDED(hr))
562 hr = IWICFormatConverter_CanConvert(converter, &GUID_WICPixelFormat32bppBGRA,
563 &GUID_WICPixelFormat32bppBGR, &can_convert);
564 ok(SUCCEEDED(hr), "CanConvert returned %x\n", hr);
565 ok(can_convert, "expected TRUE, got %i\n", can_convert);
567 hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
568 &GUID_WICPixelFormat32bppBGR, WICBitmapDitherTypeNone, NULL, 0.0,
569 WICBitmapPaletteTypeCustom);
570 ok(SUCCEEDED(hr), "Initialize returned %x\n", hr);
572 if (SUCCEEDED(hr))
573 compare_bitmap_data(&testdata_32bppBGRA, &testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter");
575 IWICFormatConverter_Release(converter);
578 DeleteTestBitmap(src_obj);
581 typedef struct property_opt_test_data
583 LPCOLESTR name;
584 VARTYPE var_type;
585 VARTYPE initial_var_type;
586 int i_init_val;
587 float f_init_val;
588 BOOL skippable;
589 } property_opt_test_data;
591 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};
592 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
593 static const WCHAR wszInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
594 static const WCHAR wszFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
595 static const WCHAR wszImageQuality[] = {'I','m','a','g','e','Q','u','a','l','i','t','y',0};
596 static const WCHAR wszBitmapTransform[] = {'B','i','t','m','a','p','T','r','a','n','s','f','o','r','m',0};
597 static const WCHAR wszLuminance[] = {'L','u','m','i','n','a','n','c','e',0};
598 static const WCHAR wszChrominance[] = {'C','h','r','o','m','i','n','a','n','c','e',0};
599 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};
600 static const WCHAR wszSuppressApp0[] = {'S','u','p','p','r','e','s','s','A','p','p','0',0};
601 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};
603 static const struct property_opt_test_data testdata_tiff_props[] = {
604 { wszTiffCompressionMethod, VT_UI1, VT_UI1, WICTiffCompressionDontCare },
605 { wszCompressionQuality, VT_R4, VT_EMPTY },
606 { NULL }
609 static const struct property_opt_test_data testdata_png_props[] = {
610 { wszInterlaceOption, VT_BOOL, VT_BOOL, 0 },
611 { wszFilterOption, VT_UI1, VT_UI1, WICPngFilterUnspecified, 0.0f, TRUE /* not supported on XP/2k3 */},
612 { NULL }
615 static const struct property_opt_test_data testdata_jpeg_props[] = {
616 { wszImageQuality, VT_R4, VT_EMPTY },
617 { wszBitmapTransform, VT_UI1, VT_UI1, WICBitmapTransformRotate0 },
618 { wszLuminance, VT_I4|VT_ARRAY, VT_EMPTY },
619 { wszChrominance, VT_I4|VT_ARRAY, VT_EMPTY },
620 { wszJpegYCrCbSubsampling, VT_UI1, VT_UI1, WICJpegYCrCbSubsamplingDefault, 0.0f, TRUE }, /* not supported on XP/2k3 */
621 { wszSuppressApp0, VT_BOOL, VT_BOOL, FALSE },
622 { NULL }
625 static const struct property_opt_test_data testdata_bmp_props[] = {
626 { wszEnableV5Header32bppBGRA, VT_BOOL, VT_BOOL, VARIANT_FALSE, 0.0f, TRUE }, /* Supported since Win7 */
627 { NULL }
630 static int find_property_index(const WCHAR* name, PROPBAG2* all_props, int all_prop_cnt)
632 int i;
633 for (i=0; i < all_prop_cnt; i++)
635 if (lstrcmpW(name, all_props[i].pstrName) == 0)
636 return i;
638 return -1;
641 static void test_specific_encoder_properties(IPropertyBag2 *options, const property_opt_test_data* data, PROPBAG2* all_props, int all_prop_cnt)
643 HRESULT hr;
644 int i = 0;
645 VARIANT pvarValue;
646 HRESULT phrError = S_OK;
648 while (data[i].name)
650 int idx = find_property_index(data[i].name, all_props, all_prop_cnt);
651 PROPBAG2 pb = {0};
652 pb.pstrName = (LPOLESTR)data[i].name;
654 hr = IPropertyBag2_Read(options, 1, &pb, NULL, &pvarValue, &phrError);
656 if (data[i].skippable && idx == -1)
658 win_skip("Property %s is not supported on this machine.\n", wine_dbgstr_w(data[i].name));
659 i++;
660 continue;
663 ok(idx >= 0, "Property %s not in output of GetPropertyInfo\n",
664 wine_dbgstr_w(data[i].name));
665 if (idx >= 0)
667 ok(all_props[idx].vt == data[i].var_type, "Property %s has unexpected vt type, vt=%i\n",
668 wine_dbgstr_w(data[i].name), all_props[idx].vt);
669 ok(all_props[idx].dwType == PROPBAG2_TYPE_DATA, "Property %s has unexpected dw type, vt=%i\n",
670 wine_dbgstr_w(data[i].name), all_props[idx].dwType);
671 ok(all_props[idx].cfType == 0, "Property %s has unexpected cf type, vt=%i\n",
672 wine_dbgstr_w(data[i].name), all_props[idx].cfType);
675 ok(SUCCEEDED(hr), "Reading property %s from bag failed, hr=%x\n",
676 wine_dbgstr_w(data[i].name), hr);
678 if (SUCCEEDED(hr))
680 /* On XP the initial type is always VT_EMPTY */
681 ok(V_VT(&pvarValue) == data[i].initial_var_type || V_VT(&pvarValue) == VT_EMPTY,
682 "Property %s has unexpected initial type, V_VT=%i\n",
683 wine_dbgstr_w(data[i].name), V_VT(&pvarValue));
685 if(V_VT(&pvarValue) == data[i].initial_var_type)
687 switch (data[i].initial_var_type)
689 case VT_BOOL:
690 case VT_UI1:
691 ok(V_UNION(&pvarValue, bVal) == data[i].i_init_val, "Property %s has an unexpected initial value, pvarValue=%i\n",
692 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, bVal));
693 break;
694 case VT_R4:
695 ok(V_UNION(&pvarValue, fltVal) == data[i].f_init_val, "Property %s has an unexpected initial value, pvarValue=%f\n",
696 wine_dbgstr_w(data[i].name), V_UNION(&pvarValue, fltVal));
697 break;
698 default:
699 break;
703 VariantClear(&pvarValue);
706 i++;
710 static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *options)
712 HRESULT hr;
713 ULONG cProperties = 0;
714 ULONG cProperties2 = 0;
715 PROPBAG2 all_props[64] = {{0}}; /* Should be enough for every encoder out there */
716 int i;
718 /* CountProperties */
720 hr = IPropertyBag2_CountProperties(options, &cProperties);
721 ok(SUCCEEDED(hr), "Reading property count, hr=%x\n", hr);
724 /* GetPropertyInfo */
726 hr = IPropertyBag2_GetPropertyInfo(options, cProperties, 1, all_props, &cProperties2);
727 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - iProperty out of bounce handled wrong, hr=%x\n", hr);
729 hr = IPropertyBag2_GetPropertyInfo(options, 0, cProperties+1, all_props, &cProperties2);
730 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, "IPropertyBag2::GetPropertyInfo - cProperty out of bounce handled wrong, hr=%x\n", hr);
732 if (cProperties == 0) /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */
734 cProperties2 = cProperties;
735 hr = S_OK;
737 else
739 hr = IPropertyBag2_GetPropertyInfo(options, 0, min(64, cProperties), all_props, &cProperties2);
740 ok(SUCCEEDED(hr), "Reading infos from property bag failed, hr=%x\n", hr);
743 if (FAILED(hr))
744 return;
746 ok(cProperties == cProperties2, "Mismatch of property count (IPropertyBag2::CountProperties=%i, IPropertyBag2::GetPropertyInfo=%i)\n",
747 (int)cProperties, (int)cProperties2);
750 if (IsEqualCLSID(clsid_encoder, &CLSID_WICTiffEncoder))
751 test_specific_encoder_properties(options, testdata_tiff_props, all_props, cProperties2);
752 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICPngEncoder))
753 test_specific_encoder_properties(options, testdata_png_props, all_props, cProperties2);
754 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICJpegEncoder))
755 test_specific_encoder_properties(options, testdata_jpeg_props, all_props, cProperties2);
756 else if (IsEqualCLSID(clsid_encoder, &CLSID_WICBmpEncoder))
757 test_specific_encoder_properties(options, testdata_bmp_props, all_props, cProperties2);
759 for (i=0; i < cProperties2; i++)
761 ok(all_props[i].pstrName != NULL, "Unset property name in output of IPropertyBag2::GetPropertyInfo\n");
762 CoTaskMemFree(all_props[i].pstrName);
766 static void load_stream(IUnknown *reader, IStream *stream)
768 HRESULT hr;
769 IWICPersistStream *persist;
770 #ifdef WORDS_BIGENDIAN
771 DWORD persist_options = WICPersistOptionBigEndian;
772 #else
773 DWORD persist_options = WICPersistOptionLittleEndian;
774 #endif
776 hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist);
777 ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
779 hr = IWICPersistStream_LoadEx(persist, stream, NULL, persist_options);
780 ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr);
782 IWICPersistStream_Release(persist);
785 static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format)
787 HRESULT hr;
788 IWICMetadataReader *reader;
789 PROPVARIANT id, value;
790 struct
792 USHORT byte_order;
793 USHORT version;
794 ULONG dir_offset;
795 } tiff;
796 LARGE_INTEGER pos;
797 UINT count, i;
798 int width, height, bps, photo, samples, colormap;
799 struct
801 int id, *value;
802 } tag[] =
804 { 0x100, &width }, { 0x101, &height }, { 0x102, &bps },
805 { 0x106, &photo }, { 0x115, &samples }, { 0x140, &colormap }
808 memset(&tiff, 0, sizeof(tiff));
809 hr = IStream_Read(stream, &tiff, sizeof(tiff), NULL);
810 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
811 ok(tiff.byte_order == MAKEWORD('I','I') || tiff.byte_order == MAKEWORD('M','M'),
812 "wrong TIFF byte order mark %02x\n", tiff.byte_order);
813 ok(tiff.version == 42, "wrong TIFF version %u\n", tiff.version);
815 pos.QuadPart = tiff.dir_offset;
816 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
817 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
819 hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER,
820 &IID_IWICMetadataReader, (void **)&reader);
821 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
823 load_stream((IUnknown *)reader, stream);
825 hr = IWICMetadataReader_GetCount(reader, &count);
826 ok(hr == S_OK, "GetCount error %#x\n", hr);
827 ok(count != 0, "wrong count %u\n", count);
829 for (i = 0; i < ARRAY_SIZE(tag); i++)
831 PropVariantInit(&id);
832 PropVariantInit(&value);
834 id.vt = VT_UI2;
835 U(id).uiVal = tag[i].id;
836 hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value);
837 ok(hr == S_OK || (tag[i].id == 0x140 && hr == WINCODEC_ERR_PROPERTYNOTFOUND),
838 "GetValue(%04x) error %#x\n", tag[i].id, hr);
839 if (hr == S_OK)
841 ok(value.vt == VT_UI2 || value.vt == VT_UI4 || value.vt == (VT_UI2 | VT_VECTOR), "wrong vt: %d\n", value.vt);
842 tag[i].value[0] = U(value).uiVal;
844 else
845 tag[i].value[0] = -1;
848 IWICMetadataReader_Release(reader);
850 if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
852 ok(width == 32, "wrong width %u\n", width);
853 ok(height == 2, "wrong height %u\n", height);
855 ok(bps == 1, "wrong bps %d\n", bps);
856 ok(photo == 1, "wrong photometric %d\n", photo);
857 ok(samples == 1, "wrong samples %d\n", samples);
858 ok(colormap == -1, "wrong colormap %d\n", colormap);
860 else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
862 ok(width == 32, "wrong width %u\n", width);
863 ok(height == 2, "wrong height %u\n", height);
865 ok(bps == 1, "wrong bps %d\n", bps);
866 ok(photo == 3, "wrong photometric %d\n", photo);
867 ok(samples == 1, "wrong samples %d\n", samples);
868 ok(colormap == 6, "wrong colormap %d\n", colormap);
870 else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
872 ok(width == 32, "wrong width %u\n", width);
873 ok(height == 2, "wrong height %u\n", height);
875 ok(bps == 4, "wrong bps %d\n", bps);
876 ok(photo == 3, "wrong photometric %d\n", photo);
877 ok(samples == 1, "wrong samples %d\n", samples);
878 ok(colormap == 48, "wrong colormap %d\n", colormap);
880 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
882 ok(width == 32, "wrong width %u\n", width);
883 ok(height == 2, "wrong height %u\n", height);
885 ok(bps == 8, "wrong bps %d\n", bps);
886 ok(photo == 3, "wrong photometric %d\n", photo);
887 ok(samples == 1, "wrong samples %d\n", samples);
888 ok(colormap == 768, "wrong colormap %d\n", colormap);
890 else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
892 ok(width == 32, "wrong width %u\n", width);
893 ok(height == 2, "wrong height %u\n", height);
895 ok(bps == 3, "wrong bps %d\n", bps);
896 ok(photo == 2, "wrong photometric %d\n", photo);
897 ok(samples == 3, "wrong samples %d\n", samples);
898 ok(colormap == -1, "wrong colormap %d\n", colormap);
900 else
901 ok(0, "unknown TIFF pixel format %s\n", wine_dbgstr_guid(format));
904 static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
906 HRESULT hr;
907 BITMAPFILEHEADER bfh;
908 BITMAPV5HEADER bih;
910 hr = IStream_Read(stream, &bfh, sizeof(bfh), NULL);
911 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
913 ok(bfh.bfType == 0x4d42, "wrong BMP signature %02x\n", bfh.bfType);
914 ok(bfh.bfReserved1 == 0, "wrong bfReserved1 %02x\n", bfh.bfReserved1);
915 ok(bfh.bfReserved2 == 0, "wrong bfReserved2 %02x\n", bfh.bfReserved2);
917 hr = IStream_Read(stream, &bih, sizeof(bih), NULL);
918 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
920 if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
922 ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
924 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
925 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
927 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
928 ok(bih.bV5BitCount == 1, "wrong BitCount %d\n", bih.bV5BitCount);
929 ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
930 ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
932 else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
934 ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
936 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
937 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
939 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
940 ok(bih.bV5BitCount == 4, "wrong BitCount %d\n", bih.bV5BitCount);
941 ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
942 ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
944 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
946 ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
948 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
949 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
951 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
952 ok(bih.bV5BitCount == 8, "wrong BitCount %d\n", bih.bV5BitCount);
953 ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
954 ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
956 else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
958 ok(bfh.bfOffBits == 0x0036, "wrong bfOffBits %08x\n", bfh.bfOffBits);
960 ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
961 ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
963 ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
964 ok(bih.bV5BitCount == 32, "wrong BitCount %d\n", bih.bV5BitCount);
965 ok(bih.bV5ClrUsed == 0, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
966 ok(bih.bV5ClrImportant == 0, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
968 else
969 ok(0, "unknown BMP pixel format %s\n", wine_dbgstr_guid(format));
972 static unsigned be_uint(unsigned val)
974 union
976 unsigned val;
977 char c[4];
978 } u;
980 u.val = val;
981 return (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3];
984 static void check_png_format(IStream *stream, const WICPixelFormatGUID *format)
986 static const char png_sig[8] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
987 static const char png_IHDR[8] = {0,0,0,0x0d,'I','H','D','R'};
988 HRESULT hr;
989 struct
991 char png_sig[8];
992 char ihdr_sig[8];
993 unsigned width, height;
994 char bit_depth, color_type, compression, filter, interlace;
995 } png;
997 memset(&png, 0, sizeof(png));
998 hr = IStream_Read(stream, &png, sizeof(png), NULL);
999 ok(hr == S_OK, "IStream_Read error %#x\n", hr);
1001 ok(!memcmp(png.png_sig, png_sig, sizeof(png_sig)), "expected PNG signature\n");
1002 ok(!memcmp(png.ihdr_sig, png_IHDR, sizeof(png_IHDR)), "expected PNG IHDR\n");
1004 if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
1006 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1007 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1009 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
1010 ok(png.color_type == 0, "wrong color_type %d\n", png.color_type);
1011 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1012 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1013 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1015 else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
1017 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1018 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1020 ok(png.bit_depth == 1, "wrong bit_depth %d\n", png.bit_depth);
1021 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1022 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1023 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1024 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1026 else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
1028 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1029 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1031 ok(png.bit_depth == 2, "wrong bit_depth %d\n", png.bit_depth);
1032 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1033 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1034 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1035 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1037 else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
1039 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1040 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1042 ok(png.bit_depth == 4, "wrong bit_depth %d\n", png.bit_depth);
1043 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1044 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1045 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1046 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1048 else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
1050 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1051 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1053 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
1054 ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1055 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1056 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1057 ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1059 else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
1061 ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1062 ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1064 ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
1065 ok(png.color_type == 2, "wrong color_type %d\n", png.color_type);
1066 ok(png.compression == 0, "wrong compression %d\n", png.compression);
1067 ok(png.filter == 0, "wrong filter %d\n", png.filter);
1068 ok(png.interlace == 0 || png.interlace == 1, "wrong interlace %d\n", png.interlace);
1070 else
1071 ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format));
1074 static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format)
1076 HRESULT hr;
1077 LARGE_INTEGER pos;
1079 pos.QuadPart = 0;
1080 hr = IStream_Seek(stream, pos, SEEK_SET, (ULARGE_INTEGER *)&pos);
1081 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1083 if (IsEqualGUID(encoder, &CLSID_WICPngEncoder))
1084 check_png_format(stream, format);
1085 else if (IsEqualGUID(encoder, &CLSID_WICBmpEncoder))
1086 check_bmp_format(stream, format);
1087 else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder))
1088 check_tiff_format(stream, format);
1089 else
1090 ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder));
1092 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
1093 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1096 struct setting {
1097 const WCHAR *name;
1098 PROPBAG2_TYPE type;
1099 VARTYPE vt;
1100 void *value;
1103 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
1104 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
1106 ULONG rc;
1107 IUnknown_AddRef(obj);
1108 rc = IUnknown_Release(obj);
1109 ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
1112 static void test_set_frame_palette(IWICBitmapFrameEncode *frameencode)
1114 IWICComponentFactory *factory;
1115 IWICPalette *palette;
1116 HRESULT hr;
1118 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1119 &IID_IWICComponentFactory, (void **)&factory);
1120 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
1122 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
1123 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
1125 hr = IWICComponentFactory_CreatePalette(factory, &palette);
1126 ok(hr == S_OK, "CreatePalette failed, hr=%x\n", hr);
1128 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1129 todo_wine
1130 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr=%x\n", hr);
1132 hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedHalftone256, FALSE);
1133 ok(hr == S_OK, "InitializePredefined failed, hr=%x\n", hr);
1135 EXPECT_REF(palette, 1);
1136 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1137 ok(hr == S_OK, "SetPalette failed, hr=%x\n", hr);
1138 EXPECT_REF(palette, 1);
1140 hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
1141 ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
1143 IWICPalette_Release(palette);
1144 IWICComponentFactory_Release(factory);
1147 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
1148 const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc,
1149 const struct setting *settings, const char *name, IWICPalette *palette)
1151 const GUID *container_format = NULL;
1152 HRESULT hr;
1153 IWICBitmapEncoder *encoder;
1154 BitmapTestSrc *src_obj;
1155 HGLOBAL hglobal;
1156 IStream *stream;
1157 IWICBitmapFrameEncode *frameencode;
1158 IPropertyBag2 *options=NULL;
1159 IWICBitmapDecoder *decoder;
1160 IWICBitmapFrameDecode *framedecode;
1161 WICPixelFormatGUID pixelformat;
1162 GUID guid;
1163 int i;
1165 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
1166 &IID_IWICBitmapEncoder, (void **)&encoder);
1167 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1169 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1170 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
1172 hr = IWICBitmapEncoder_GetContainerFormat(encoder, NULL);
1173 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1175 if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
1176 container_format = &GUID_ContainerFormatPng;
1177 else if (IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder))
1178 container_format = &GUID_ContainerFormatBmp;
1179 else if (IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder))
1180 container_format = &GUID_ContainerFormatTiff;
1181 else if (IsEqualGUID(clsid_encoder, &CLSID_WICJpegEncoder))
1182 container_format = &GUID_ContainerFormatJpeg;
1183 else
1184 ok(0, "Unknown encoder %s.\n", wine_dbgstr_guid(clsid_encoder));
1186 if (container_format)
1188 memset(&guid, 0, sizeof(guid));
1189 hr = IWICBitmapEncoder_GetContainerFormat(encoder, &guid);
1190 ok(SUCCEEDED(hr), "Failed to get container format, hr %#x.\n", hr);
1191 ok(IsEqualGUID(container_format, &guid), "Unexpected container format %s.\n", wine_dbgstr_guid(&guid));
1194 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
1195 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1197 /* Encoder options are optional. */
1198 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, NULL);
1199 ok(SUCCEEDED(hr), "Failed to create encode frame, hr %#x.\n", hr);
1201 IStream_Release(stream);
1202 IWICBitmapEncoder_Release(encoder);
1203 IWICBitmapFrameEncode_Release(frameencode);
1205 hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
1206 &IID_IWICBitmapEncoder, (void**)&encoder);
1207 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1208 if (SUCCEEDED(hr))
1210 hglobal = GlobalAlloc(GMEM_MOVEABLE, 0);
1211 ok(hglobal != NULL, "GlobalAlloc failed\n");
1212 if (hglobal)
1214 hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
1215 ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
1218 if (hglobal && SUCCEEDED(hr))
1220 if (palette)
1222 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
1223 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x (%s)\n", hr, name);
1226 hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
1227 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1229 if (palette)
1231 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
1232 ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr);
1233 hr = S_OK;
1236 i=0;
1237 while (SUCCEEDED(hr) && srcs[i])
1239 CreateTestBitmap(srcs[i], &src_obj);
1241 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options);
1242 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr);
1243 if (SUCCEEDED(hr))
1245 ok(options != NULL, "Encoder initialization has not created an property bag\n");
1246 if(options)
1247 test_encoder_properties(clsid_encoder, options);
1249 if (settings)
1251 int j;
1252 for (j=0; settings[j].name; j++)
1254 PROPBAG2 propbag;
1255 VARIANT var;
1257 memset(&propbag, 0, sizeof(propbag));
1258 memset(&var, 0, sizeof(var));
1259 propbag.pstrName = (LPOLESTR)settings[j].name;
1260 propbag.dwType = settings[j].type;
1261 V_VT(&var) = settings[j].vt;
1262 V_UNKNOWN(&var) = settings[j].value;
1264 hr = IPropertyBag2_Write(options, 1, &propbag, &var);
1265 ok(SUCCEEDED(hr), "Writing property %s failed, hr=%x\n", wine_dbgstr_w(settings[j].name), hr);
1269 if (palette)
1271 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1272 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x\n", hr);
1275 hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
1276 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1278 memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
1279 hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
1280 ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
1281 ok(IsEqualGUID(&pixelformat, dsts[i]->format) ||
1282 (IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) ||
1283 (IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
1284 "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
1286 hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
1287 ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
1289 if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
1290 test_set_frame_palette(frameencode);
1292 if (palette)
1294 WICColor colors[256];
1296 hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1297 ok(SUCCEEDED(hr), "SetPalette failed, hr=%x (%s)\n", hr, name);
1299 /* trash the assigned palette */
1300 memset(colors, 0, sizeof(colors));
1301 hr = IWICPalette_InitializeCustom(palette, colors, 256);
1302 ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1305 hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, rc);
1306 if (rc && (rc->Width <= 0 || rc->Height <= 0))
1308 /* WriteSource fails but WriteSource_Proxy succeeds. */
1309 ok(hr == E_INVALIDARG, "WriteSource should fail, hr=%x (%s)\n", hr, name);
1310 hr = IWICBitmapFrameEncode_WriteSource_Proxy(frameencode, &src_obj->IWICBitmapSource_iface, rc);
1311 ok(SUCCEEDED(hr), "WriteSource_Proxy failed, %dx%d, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
1313 else
1315 if (rc)
1316 ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
1317 else
1318 ok(hr == S_OK ||
1319 (FAILED(hr) && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) /* XP */ ||
1320 (FAILED(hr) && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) /* XP */ ||
1321 broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
1322 "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
1325 if (SUCCEEDED(hr))
1327 hr = IWICBitmapFrameEncode_Commit(frameencode);
1328 ok(SUCCEEDED(hr), "Commit failed, hr=%x (%s)\n", hr, name);
1331 IWICBitmapFrameEncode_Release(frameencode);
1332 IPropertyBag2_Release(options);
1335 DeleteTestBitmap(src_obj);
1337 i++;
1340 if (clsid_decoder == NULL)
1342 IStream_Release(stream);
1343 IWICBitmapEncoder_Release(encoder);
1344 return;
1347 if (SUCCEEDED(hr))
1349 hr = IWICBitmapEncoder_Commit(encoder);
1350 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
1352 if (IsEqualGUID(&pixelformat, dsts[0]->format))
1353 check_bitmap_format(stream, clsid_encoder, dsts[0]->format);
1356 if (SUCCEEDED(hr))
1358 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER,
1359 &IID_IWICBitmapDecoder, (void**)&decoder);
1360 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1363 if (SUCCEEDED(hr))
1365 IWICPalette *frame_palette;
1367 hr = IWICImagingFactory_CreatePalette(factory, &frame_palette);
1368 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1370 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
1371 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1373 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
1374 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1376 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
1377 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1379 hr = S_OK;
1380 i=0;
1381 while (SUCCEEDED(hr) && dsts[i])
1383 hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
1384 ok(SUCCEEDED(hr), "GetFrame failed, hr=%x (%s)\n", hr, name);
1386 if (SUCCEEDED(hr))
1388 hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &pixelformat);
1389 ok(hr == S_OK, "GetPixelFormat) failed, hr=%x (%s)\n", hr, name);
1390 if (IsEqualGUID(&pixelformat, dsts[i]->format))
1391 compare_bitmap_data(srcs[i], dsts[i], (IWICBitmapSource*)framedecode, name);
1393 hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette);
1394 if (winetest_debug > 1)
1395 trace("%s, bpp %d, %s, hr %#x\n", name, dsts[i]->bpp, wine_dbgstr_guid(dsts[i]->format), hr);
1396 if (dsts[i]->bpp > 8 || IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite))
1397 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1398 else
1400 UINT count, ret;
1401 WICColor colors[256];
1403 ok(hr == S_OK, "CopyPalette error %#x (%s)\n", hr, name);
1405 count = 0;
1406 hr = IWICPalette_GetColorCount(frame_palette, &count);
1407 ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1409 memset(colors, 0, sizeof(colors));
1410 ret = 0;
1411 hr = IWICPalette_GetColors(frame_palette, count, colors, &ret);
1412 ok(hr == S_OK, "GetColors error %#x\n", hr);
1413 ok(ret == count, "expected %u, got %u\n", count, ret);
1414 if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder))
1416 /* Newer libpng versions don't accept larger palettes than the declared
1417 * bit depth, so we need to generate the palette of the correct length.
1419 ok(count == 256 || (dsts[i]->bpp == 1 && count == 2) ||
1420 (dsts[i]->bpp == 2 && count == 4) || (dsts[i]->bpp == 4 && count == 16),
1421 "expected 256, got %u (%s)\n", count, name);
1423 ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name);
1424 ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name);
1425 if (count > 2)
1427 ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name);
1428 ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name);
1429 if (count > 4)
1431 ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
1432 ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
1436 else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) ||
1437 IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder))
1439 if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormatBlackWhite) ||
1440 IsEqualGUID(&pixelformat, &GUID_WICPixelFormat8bppIndexed))
1442 ok(count == 256, "expected 256, got %u (%s)\n", count, name);
1444 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1445 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1446 ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1447 ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1448 ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1449 ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1451 else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed))
1453 ok(count == 16, "expected 16, got %u (%s)\n", count, name);
1455 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1456 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1457 ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1458 ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1459 ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1460 ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1462 else
1464 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1466 ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1467 ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1470 else
1472 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1474 ok(colors[0] == 0xff111111, "got %08x\n", colors[0]);
1475 ok(colors[1] == 0xff222222, "got %08x\n", colors[1]);
1479 IWICBitmapFrameDecode_Release(framedecode);
1482 i++;
1485 IWICPalette_Release(frame_palette);
1486 IWICBitmapDecoder_Release(decoder);
1489 IStream_Release(stream);
1492 IWICBitmapEncoder_Release(encoder);
1496 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder,
1497 const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name)
1499 const struct bitmap_data *srcs[2];
1500 const struct bitmap_data *dsts[2];
1501 WICColor colors[256];
1502 IWICPalette *palette;
1503 HRESULT hr;
1505 hr = IWICImagingFactory_CreatePalette(factory, &palette);
1506 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1508 memset(colors, 0, sizeof(colors));
1509 colors[0] = 0x11111111;
1510 colors[1] = 0x22222222;
1511 colors[2] = 0x33333333;
1512 colors[3] = 0x44444444;
1513 colors[4] = 0x55555555;
1514 /* TIFF decoder fails to decode a 8bpp frame if palette has less than 256 colors */
1515 hr = IWICPalette_InitializeCustom(palette, colors, 256);
1516 ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1518 srcs[0] = src;
1519 srcs[1] = NULL;
1520 dsts[0] = dst;
1521 dsts[1] = NULL;
1523 test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name, palette);
1525 IWICPalette_Release(palette);
1528 static void test_encoder_rects(void)
1530 const struct bitmap_data *srcs[2];
1531 const struct bitmap_data *dsts[2];
1532 WICRect rc;
1534 srcs[0] = &testdata_24bppBGR;
1535 srcs[1] = NULL;
1536 dsts[0] = &testdata_24bppBGR;
1537 dsts[1] = NULL;
1539 rc.X = 0;
1540 rc.Y = 0;
1541 rc.Width = 32;
1542 rc.Height = 2;
1544 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL);
1546 rc.Width = 0;
1547 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0", NULL);
1549 rc.Width = -1;
1550 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL);
1552 rc.Width = 32;
1553 rc.Height = 0;
1554 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL);
1556 rc.Height = -1;
1557 test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1", NULL);
1560 static const struct bitmap_data *multiple_frames[3] = {
1561 &testdata_24bppBGR,
1562 &testdata_24bppBGR,
1563 NULL};
1565 static const struct bitmap_data *single_frame[2] = {
1566 &testdata_24bppBGR,
1567 NULL};
1569 static const struct setting png_interlace_settings[] = {
1570 {wszInterlaceOption, PROPBAG2_TYPE_DATA, VT_BOOL, (void*)VARIANT_TRUE},
1571 {NULL}
1574 START_TEST(converter)
1576 HRESULT hr;
1578 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1580 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1581 &IID_IWICImagingFactory, (void **)&factory);
1582 ok(hr == S_OK, "failed to create factory: %#x\n", hr);
1584 test_conversion(&testdata_24bppRGB, &testdata_1bppIndexed, "24bppRGB -> 1bppIndexed", TRUE);
1585 test_conversion(&testdata_24bppRGB, &testdata_2bppIndexed, "24bppRGB -> 2bppIndexed", TRUE);
1586 test_conversion(&testdata_24bppRGB, &testdata_4bppIndexed, "24bppRGB -> 4bppIndexed", TRUE);
1587 test_conversion(&testdata_24bppRGB, &testdata_8bppIndexed, "24bppRGB -> 8bppIndexed", FALSE);
1589 test_conversion(&testdata_BlackWhite, &testdata_8bppIndexed_BW, "BlackWhite -> 8bppIndexed", TRUE);
1590 test_conversion(&testdata_1bppIndexed, &testdata_8bppIndexed_BW, "1bppIndexed -> 8bppIndexed", TRUE);
1591 test_conversion(&testdata_2bppIndexed, &testdata_8bppIndexed_4colors, "2bppIndexed -> 8bppIndexed", TRUE);
1592 test_conversion(&testdata_4bppIndexed, &testdata_8bppIndexed, "4bppIndexed -> 8bppIndexed", TRUE);
1594 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE);
1595 test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE);
1596 test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE);
1598 test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE);
1599 test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE);
1601 test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", FALSE);
1602 test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", FALSE);
1604 test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", FALSE);
1605 test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", FALSE);
1606 test_conversion(&testdata_32bppBGRA, &testdata_24bppRGB, "32bppBGRA -> 24bppRGB", FALSE);
1608 test_conversion(&testdata_24bppRGB, &testdata_32bppGrayFloat, "24bppRGB -> 32bppGrayFloat", FALSE);
1609 test_conversion(&testdata_32bppBGR, &testdata_32bppGrayFloat, "32bppBGR -> 32bppGrayFloat", FALSE);
1611 test_conversion(&testdata_24bppBGR, &testdata_8bppGray, "24bppBGR -> 8bppGray", FALSE);
1612 test_conversion(&testdata_32bppBGR, &testdata_8bppGray, "32bppBGR -> 8bppGray", FALSE);
1613 test_conversion(&testdata_32bppGrayFloat, &testdata_24bppBGR_gray, "32bppGrayFloat -> 24bppBGR gray", FALSE);
1614 test_conversion(&testdata_32bppGrayFloat, &testdata_8bppGray, "32bppGrayFloat -> 8bppGray", FALSE);
1616 test_invalid_conversion();
1617 test_default_converter();
1619 test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder,
1620 &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite");
1621 test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder,
1622 &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed");
1623 test_encoder(&testdata_2bppIndexed, &CLSID_WICPngEncoder,
1624 &testdata_2bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 2bppIndexed");
1625 test_encoder(&testdata_4bppIndexed, &CLSID_WICPngEncoder,
1626 &testdata_4bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 4bppIndexed");
1627 test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder,
1628 &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed");
1629 test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
1630 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
1631 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
1633 test_encoder(&testdata_32bppBGR, &CLSID_WICPngEncoder,
1634 &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 32bppBGR");
1637 test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
1638 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
1639 test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
1640 &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
1641 test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder,
1642 &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
1643 test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder,
1644 &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
1645 test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
1646 &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
1647 test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
1648 &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
1650 test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder,
1651 &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite");
1652 test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
1653 &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
1654 test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder,
1655 &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
1656 test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder,
1657 &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed");
1658 test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
1659 &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
1660 test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
1661 &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
1663 test_encoder(&testdata_24bppBGR, &CLSID_WICJpegEncoder,
1664 &testdata_24bppBGR, NULL, "JPEG encoder 24bppBGR");
1666 test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
1667 multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame", NULL);
1669 test_encoder_rects();
1671 test_multi_encoder(single_frame, &CLSID_WICPngEncoder,
1672 single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced", NULL);
1674 IWICImagingFactory_Release(factory);
1676 CoUninitialize();