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