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_WICPixelFormat2bppIndexed))
908     {
909         ok(width == 32, "wrong width %u\n", width);
910         ok(height == 2, "wrong height %u\n", height);
911 
912         ok(bps == 2, "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 == 12, "wrong colormap %d\n", colormap);
916     }
917     else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
918     {
919         ok(width == 32, "wrong width %u\n", width);
920         ok(height == 2, "wrong height %u\n", height);
921 
922         ok(bps == 4, "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 == 48, "wrong colormap %d\n", colormap);
926     }
927     else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
928     {
929         ok(width == 32, "wrong width %u\n", width);
930         ok(height == 2, "wrong height %u\n", height);
931 
932         ok(bps == 8, "wrong bps %d\n", bps);
933         ok(photo == 3, "wrong photometric %d\n", photo);
934         ok(samples == 1, "wrong samples %d\n", samples);
935         ok(colormap == 768, "wrong colormap %d\n", colormap);
936     }
937     else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
938     {
939         ok(width == 32, "wrong width %u\n", width);
940         ok(height == 2, "wrong height %u\n", height);
941 
942         ok(bps == 3, "wrong bps %d\n", bps);
943         ok(photo == 2, "wrong photometric %d\n", photo);
944         ok(samples == 3, "wrong samples %d\n", samples);
945         ok(colormap == -1, "wrong colormap %d\n", colormap);
946     }
947     else
948         ok(0, "unknown TIFF pixel format %s\n", wine_dbgstr_guid(format));
949 }
950 
951 static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format)
952 {
953     HRESULT hr;
954     BITMAPFILEHEADER bfh;
955     BITMAPV5HEADER bih;
956 
957     hr = IStream_Read(stream, &bfh, sizeof(bfh), NULL);
958     ok(hr == S_OK, "IStream_Read error %#x\n", hr);
959 
960     ok(bfh.bfType == 0x4d42, "wrong BMP signature %02x\n", bfh.bfType);
961     ok(bfh.bfReserved1 == 0, "wrong bfReserved1 %02x\n", bfh.bfReserved1);
962     ok(bfh.bfReserved2 == 0, "wrong bfReserved2 %02x\n", bfh.bfReserved2);
963 
964     hr = IStream_Read(stream, &bih, sizeof(bih), NULL);
965     ok(hr == S_OK, "IStream_Read error %#x\n", hr);
966 
967     if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed))
968     {
969         ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
970 
971         ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
972         ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
973 
974         ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
975         ok(bih.bV5BitCount == 1, "wrong BitCount %d\n", bih.bV5BitCount);
976         ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
977         ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
978     }
979     else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed))
980     {
981         ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
982 
983         ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
984         ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
985 
986         ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
987         ok(bih.bV5BitCount == 2, "wrong BitCount %d\n", bih.bV5BitCount);
988         ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
989         ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
990     }
991     else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed))
992     {
993         ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
994 
995         ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
996         ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
997 
998         ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
999         ok(bih.bV5BitCount == 4, "wrong BitCount %d\n", bih.bV5BitCount);
1000         ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
1001         ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
1002     }
1003     else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
1004     {
1005         ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits);
1006 
1007         ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
1008         ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
1009 
1010         ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
1011         ok(bih.bV5BitCount == 8, "wrong BitCount %d\n", bih.bV5BitCount);
1012         ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
1013         ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
1014     }
1015     else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR))
1016     {
1017         ok(bfh.bfOffBits == 0x0036, "wrong bfOffBits %08x\n", bfh.bfOffBits);
1018 
1019         ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width);
1020         ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height);
1021 
1022         ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes);
1023         ok(bih.bV5BitCount == 32, "wrong BitCount %d\n", bih.bV5BitCount);
1024         ok(bih.bV5ClrUsed == 0, "wrong ClrUsed %d\n", bih.bV5ClrUsed);
1025         ok(bih.bV5ClrImportant == 0, "wrong ClrImportant %d\n", bih.bV5ClrImportant);
1026     }
1027     else
1028         ok(0, "unknown BMP pixel format %s\n", wine_dbgstr_guid(format));
1029 }
1030 
1031 static unsigned be_uint(unsigned val)
1032 {
1033     union
1034     {
1035         unsigned val;
1036         char c[4];
1037     } u;
1038 
1039     u.val = val;
1040     return (u.c[0] << 24) | (u.c[1] << 16) | (u.c[2] << 8) | u.c[3];
1041 }
1042 
1043 static void check_png_format(IStream *stream, const WICPixelFormatGUID *format)
1044 {
1045     static const char png_sig[8] = {0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
1046     static const char png_IHDR[8] = {0,0,0,0x0d,'I','H','D','R'};
1047     HRESULT hr;
1048     struct
1049     {
1050         char png_sig[8];
1051         char ihdr_sig[8];
1052         unsigned width, height;
1053         char bit_depth, color_type, compression, filter, interlace;
1054     } png;
1055 
1056     memset(&png, 0, sizeof(png));
1057     hr = IStream_Read(stream, &png, sizeof(png), NULL);
1058     ok(hr == S_OK, "IStream_Read error %#x\n", hr);
1059 
1060     ok(!memcmp(png.png_sig, png_sig, sizeof(png_sig)), "expected PNG signature\n");
1061     ok(!memcmp(png.ihdr_sig, png_IHDR, sizeof(png_IHDR)), "expected PNG IHDR\n");
1062 
1063     if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite))
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 == 1, "wrong bit_depth %d\n", png.bit_depth);
1069         ok(png.color_type == 0, "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_WICPixelFormat1bppIndexed))
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 == 1, "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_WICPixelFormat2bppIndexed))
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 == 2, "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_WICPixelFormat4bppIndexed))
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 == 4, "wrong bit_depth %d\n", png.bit_depth);
1102         ok(png.color_type == 3, "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, "wrong interlace %d\n", png.interlace);
1106     }
1107     else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed))
1108     {
1109         ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1110         ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1111 
1112         ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
1113         ok(png.color_type == 3, "wrong color_type %d\n", png.color_type);
1114         ok(png.compression == 0, "wrong compression %d\n", png.compression);
1115         ok(png.filter == 0, "wrong filter %d\n", png.filter);
1116         ok(png.interlace == 0, "wrong interlace %d\n", png.interlace);
1117     }
1118     else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR))
1119     {
1120         ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width));
1121         ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height));
1122 
1123         ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth);
1124         ok(png.color_type == 2, "wrong color_type %d\n", png.color_type);
1125         ok(png.compression == 0, "wrong compression %d\n", png.compression);
1126         ok(png.filter == 0, "wrong filter %d\n", png.filter);
1127         ok(png.interlace == 0 || png.interlace == 1, "wrong interlace %d\n", png.interlace);
1128     }
1129     else
1130         ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format));
1131 }
1132 
1133 static void check_gif_format(IStream *stream, const WICPixelFormatGUID *format)
1134 {
1135 #include "pshpack1.h"
1136     struct logical_screen_descriptor
1137     {
1138         char signature[6];
1139         USHORT width;
1140         USHORT height;
1141         BYTE packed;
1142         /* global_color_table_flag : 1;
1143          * color_resolution : 3;
1144          * sort_flag : 1;
1145          * global_color_table_size : 3;
1146          */
1147         BYTE background_color_index;
1148         BYTE pixel_aspect_ratio;
1149     } lsd;
1150 #include "poppack.h"
1151     UINT color_resolution;
1152     HRESULT hr;
1153 
1154     memset(&lsd, 0, sizeof(lsd));
1155     hr = IStream_Read(stream, &lsd, sizeof(lsd), NULL);
1156     ok(hr == S_OK, "IStream_Read error %#x\n", hr);
1157 
1158     ok(!memcmp(lsd.signature, "GIF89a", 6), "wrong GIF signature %.6s\n", lsd.signature);
1159 
1160     ok(lsd.width == 32, "wrong width %u\n", lsd.width);
1161     ok(lsd.height == 2, "wrong height %u\n", lsd.height);
1162     color_resolution = 1 << (((lsd.packed >> 4) & 0x07) + 1);
1163     ok(color_resolution == 256, "wrong color resolution %u\n", color_resolution);
1164     ok(lsd.pixel_aspect_ratio == 0, "wrong pixel_aspect_ratio %u\n", lsd.pixel_aspect_ratio);
1165 }
1166 
1167 static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format)
1168 {
1169     HRESULT hr;
1170     LARGE_INTEGER pos;
1171 
1172     pos.QuadPart = 0;
1173     hr = IStream_Seek(stream, pos, SEEK_SET, (ULARGE_INTEGER *)&pos);
1174     ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1175 
1176     if (IsEqualGUID(encoder, &CLSID_WICPngEncoder))
1177         check_png_format(stream, format);
1178     else if (IsEqualGUID(encoder, &CLSID_WICBmpEncoder))
1179         check_bmp_format(stream, format);
1180     else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder))
1181         check_tiff_format(stream, format);
1182     else if (IsEqualGUID(encoder, &CLSID_WICGifEncoder))
1183         check_gif_format(stream, format);
1184     else
1185         ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder));
1186 
1187     hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
1188     ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
1189 }
1190 
1191 struct setting {
1192     const WCHAR *name;
1193     PROPBAG2_TYPE type;
1194     VARTYPE vt;
1195     void *value;
1196 };
1197 
1198 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
1199 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
1200 {
1201     ULONG rc;
1202     IUnknown_AddRef(obj);
1203     rc = IUnknown_Release(obj);
1204     ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
1205 }
1206 
1207 static void test_set_frame_palette(IWICBitmapFrameEncode *frameencode)
1208 {
1209     IWICComponentFactory *factory;
1210     IWICPalette *palette;
1211     HRESULT hr;
1212 
1213     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1214         &IID_IWICComponentFactory, (void **)&factory);
1215     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
1216 
1217     hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
1218     ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
1219 
1220     hr = IWICComponentFactory_CreatePalette(factory, &palette);
1221     ok(hr == S_OK, "CreatePalette failed, hr=%x\n", hr);
1222 
1223     hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1224 todo_wine
1225     ok(hr == WINCODEC_ERR_NOTINITIALIZED, "Unexpected hr=%x\n", hr);
1226 
1227     hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeFixedHalftone256, FALSE);
1228     ok(hr == S_OK, "InitializePredefined failed, hr=%x\n", hr);
1229 
1230     EXPECT_REF(palette, 1);
1231     hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1232     ok(hr == S_OK, "SetPalette failed, hr=%x\n", hr);
1233     EXPECT_REF(palette, 1);
1234 
1235     hr = IWICBitmapFrameEncode_SetPalette(frameencode, NULL);
1236     ok(hr == E_INVALIDARG, "SetPalette failed, hr=%x\n", hr);
1237 
1238     IWICPalette_Release(palette);
1239     IWICComponentFactory_Release(factory);
1240 }
1241 
1242 static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* clsid_encoder,
1243     const struct bitmap_data **dsts, const CLSID *clsid_decoder, WICRect *rc,
1244     const struct setting *settings, const char *name, IWICPalette *palette)
1245 {
1246     HRESULT hr;
1247     IWICBitmapEncoder *encoder;
1248     BitmapTestSrc *src_obj;
1249     HGLOBAL hglobal;
1250     IStream *stream;
1251     IWICBitmapFrameEncode *frameencode;
1252     IPropertyBag2 *options=NULL;
1253     IWICBitmapDecoder *decoder;
1254     IWICBitmapFrameDecode *framedecode;
1255     WICPixelFormatGUID pixelformat;
1256     int i;
1257 
1258     hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
1259         &IID_IWICBitmapEncoder, (void **)&encoder);
1260     ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1261 
1262     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1263     ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
1264 
1265     hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
1266     ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1267 
1268     /* Encoder options are optional. */
1269     hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, NULL);
1270     ok(SUCCEEDED(hr), "Failed to create encode frame, hr %#x.\n", hr);
1271 
1272     IStream_Release(stream);
1273     IWICBitmapEncoder_Release(encoder);
1274     IWICBitmapFrameEncode_Release(frameencode);
1275 
1276     hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER,
1277         &IID_IWICBitmapEncoder, (void**)&encoder);
1278     ok(SUCCEEDED(hr), "CoCreateInstance(%s) failed, hr=%x\n", wine_dbgstr_guid(clsid_encoder), hr);
1279     if (SUCCEEDED(hr))
1280     {
1281         hglobal = GlobalAlloc(GMEM_MOVEABLE, 0);
1282         ok(hglobal != NULL, "GlobalAlloc failed\n");
1283         if (hglobal)
1284         {
1285             hr = CreateStreamOnHGlobal(hglobal, TRUE, &stream);
1286             ok(SUCCEEDED(hr), "CreateStreamOnHGlobal failed, hr=%x\n", hr);
1287         }
1288 
1289         if (hglobal && SUCCEEDED(hr))
1290         {
1291             if (palette)
1292             {
1293                 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
1294                 ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x (%s)\n", hr, name);
1295             }
1296 
1297             hr = IWICBitmapEncoder_Initialize(encoder, stream, WICBitmapEncoderNoCache);
1298             ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1299 
1300             if (palette)
1301             {
1302                 hr = IWICBitmapEncoder_SetPalette(encoder, palette);
1303                 if (IsEqualGUID(clsid_encoder, &CLSID_WICGifEncoder))
1304                     ok(hr == S_OK, "SetPalette failed, hr=%#x\n", hr);
1305                 else
1306                     ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr);
1307                 hr = S_OK;
1308             }
1309 
1310             i=0;
1311             while (SUCCEEDED(hr) && srcs[i])
1312             {
1313                 CreateTestBitmap(srcs[i], &src_obj);
1314 
1315                 hr = IWICBitmapEncoder_CreateNewFrame(encoder, &frameencode, &options);
1316                 ok(SUCCEEDED(hr), "CreateFrame failed, hr=%x\n", hr);
1317                 if (SUCCEEDED(hr))
1318                 {
1319                     ok(options != NULL, "Encoder initialization has not created an property bag\n");
1320                     if(options)
1321                         test_encoder_properties(clsid_encoder, options);
1322 
1323                     if (settings)
1324                     {
1325                         int j;
1326                         for (j=0; settings[j].name; j++)
1327                         {
1328                             PROPBAG2 propbag;
1329                             VARIANT var;
1330 
1331                             memset(&propbag, 0, sizeof(propbag));
1332                             memset(&var, 0, sizeof(var));
1333                             propbag.pstrName = (LPOLESTR)settings[j].name;
1334                             propbag.dwType = settings[j].type;
1335                             V_VT(&var) = settings[j].vt;
1336                             V_UNKNOWN(&var) = settings[j].value;
1337 
1338                             hr = IPropertyBag2_Write(options, 1, &propbag, &var);
1339                             ok(SUCCEEDED(hr), "Writing property %s failed, hr=%x\n", wine_dbgstr_w(settings[j].name), hr);
1340                         }
1341                     }
1342 
1343                     if (palette)
1344                     {
1345                         hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1346                         ok(hr == WINCODEC_ERR_NOTINITIALIZED, "wrong error %#x\n", hr);
1347                     }
1348 
1349                     hr = IWICBitmapFrameEncode_Initialize(frameencode, options);
1350                     ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1351 
1352                     memcpy(&pixelformat, srcs[i]->format, sizeof(GUID));
1353                     hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat);
1354                     ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr);
1355                     ok(IsEqualGUID(&pixelformat, dsts[i]->format) ||
1356                        broken(IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) ||
1357                        broken(IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)),
1358                        "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name);
1359 
1360                     hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height);
1361                     ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr);
1362 
1363                     if (IsEqualGUID(clsid_encoder, &CLSID_WICPngEncoder))
1364                         test_set_frame_palette(frameencode);
1365 
1366                     if (palette)
1367                     {
1368                         WICColor colors[256];
1369 
1370                         hr = IWICBitmapFrameEncode_SetPalette(frameencode, palette);
1371                         ok(SUCCEEDED(hr), "SetPalette failed, hr=%x (%s)\n", hr, name);
1372 
1373                         /* trash the assigned palette */
1374                         memset(colors, 0, sizeof(colors));
1375                         hr = IWICPalette_InitializeCustom(palette, colors, 256);
1376                         ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1377                     }
1378 
1379                     hr = IWICBitmapFrameEncode_WriteSource(frameencode, &src_obj->IWICBitmapSource_iface, rc);
1380                     if (rc && (rc->Width <= 0 || rc->Height <= 0))
1381                     {
1382                         /* WriteSource fails but WriteSource_Proxy succeeds. */
1383                         ok(hr == E_INVALIDARG, "WriteSource should fail, hr=%x (%s)\n", hr, name);
1384                         hr = IWICBitmapFrameEncode_WriteSource_Proxy(frameencode, &src_obj->IWICBitmapSource_iface, rc);
1385                         ok(SUCCEEDED(hr), "WriteSource_Proxy failed, %dx%d, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
1386                     }
1387                     else
1388                     {
1389                         if (rc)
1390                             ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name);
1391                         else
1392                             ok(hr == S_OK ||
1393                                broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) /* XP */ ||
1394                                broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) /* XP */ ||
1395                                broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */,
1396                                "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name);
1397                     }
1398 
1399                     if (SUCCEEDED(hr))
1400                     {
1401                         hr = IWICBitmapFrameEncode_Commit(frameencode);
1402                         ok(SUCCEEDED(hr), "Commit failed, hr=%x (%s)\n", hr, name);
1403                     }
1404 
1405                     IWICBitmapFrameEncode_Release(frameencode);
1406                     IPropertyBag2_Release(options);
1407                 }
1408 
1409                 DeleteTestBitmap(src_obj);
1410 
1411                 i++;
1412             }
1413 
1414             if (clsid_decoder == NULL)
1415             {
1416                 IStream_Release(stream);
1417                 IWICBitmapEncoder_Release(encoder);
1418                 return;
1419             }
1420 
1421             if (SUCCEEDED(hr))
1422             {
1423                 hr = IWICBitmapEncoder_Commit(encoder);
1424                 ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr);
1425 
1426                 if (IsEqualGUID(&pixelformat, dsts[0]->format))
1427                     check_bitmap_format(stream, clsid_encoder, dsts[0]->format);
1428             }
1429 
1430             if (SUCCEEDED(hr))
1431             {
1432                 hr = CoCreateInstance(clsid_decoder, NULL, CLSCTX_INPROC_SERVER,
1433                     &IID_IWICBitmapDecoder, (void**)&decoder);
1434                 ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr);
1435             }
1436 
1437             if (SUCCEEDED(hr))
1438             {
1439                 IWICPalette *frame_palette;
1440 
1441                 hr = IWICImagingFactory_CreatePalette(factory, &frame_palette);
1442                 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1443 
1444                 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
1445                 if (IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder))
1446                     ok(hr == WINCODEC_ERR_WRONGSTATE, "wrong error %#x\n", hr);
1447                 else
1448                     ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1449 
1450                 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
1451                 ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr);
1452 
1453                 hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette);
1454                 if (IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder))
1455                     ok(hr == S_OK || broken(hr == WINCODEC_ERR_FRAMEMISSING) /* XP */, "CopyPalette failed, hr=%#x\n", hr);
1456                 else
1457                     ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1458 
1459                 hr = S_OK;
1460                 i=0;
1461                 while (SUCCEEDED(hr) && dsts[i])
1462                 {
1463                     hr = IWICBitmapDecoder_GetFrame(decoder, i, &framedecode);
1464                     ok(SUCCEEDED(hr), "GetFrame failed, hr=%x (%s)\n", hr, name);
1465 
1466                     if (SUCCEEDED(hr))
1467                     {
1468                         hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &pixelformat);
1469                         ok(hr == S_OK, "GetPixelFormat) failed, hr=%x (%s)\n", hr, name);
1470                         if (IsEqualGUID(&pixelformat, dsts[i]->format))
1471                             compare_bitmap_data(srcs[i], dsts[i], (IWICBitmapSource*)framedecode, name);
1472 
1473                         hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette);
1474                         if (winetest_debug > 1)
1475                             trace("%s, bpp %d, %s, hr %#x\n", name, dsts[i]->bpp, wine_dbgstr_guid(dsts[i]->format), hr);
1476                         if (dsts[i]->bpp > 8 || IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite))
1477                             ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr);
1478                         else
1479                         {
1480                             UINT count, ret;
1481                             WICColor colors[256];
1482 
1483                             ok(hr == S_OK, "CopyPalette error %#x (%s)\n", hr, name);
1484 
1485                             count = 0;
1486                             hr = IWICPalette_GetColorCount(frame_palette, &count);
1487                             ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1488 
1489                             memset(colors, 0, sizeof(colors));
1490                             ret = 0;
1491                             hr = IWICPalette_GetColors(frame_palette, count, colors, &ret);
1492                             ok(hr == S_OK, "GetColors error %#x\n", hr);
1493                             ok(ret == count, "expected %u, got %u\n", count, ret);
1494                             if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder))
1495                             {
1496                                 /* Newer libpng versions don't accept larger palettes than the declared
1497                                  * bit depth, so we need to generate the palette of the correct length.
1498                                  */
1499                                 ok(count == 256 || (dsts[i]->bpp == 1 && count == 2) ||
1500                                    (dsts[i]->bpp == 2 && count == 4) || (dsts[i]->bpp == 4 && count == 16),
1501                                    "expected 256, got %u (%s)\n", count, name);
1502 
1503                                 ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name);
1504                                 ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name);
1505                                 if (count > 2)
1506                                 {
1507                                     ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name);
1508                                     ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name);
1509                                     if (count > 4)
1510                                     {
1511                                         ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name);
1512                                         ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name);
1513                                     }
1514                                 }
1515                             }
1516                             else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) ||
1517                                      IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder) ||
1518                                      IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder))
1519                             {
1520                                 if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormatBlackWhite) ||
1521                                     IsEqualGUID(&pixelformat, &GUID_WICPixelFormat8bppIndexed))
1522                                 {
1523                                     ok(count == 256, "expected 256, got %u (%s)\n", count, name);
1524 
1525                                     ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1526                                     ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1527                                     ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1528                                     ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1529                                     ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1530                                     ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1531                                 }
1532                                 else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat2bppIndexed))
1533                                 {
1534                                     ok(count == 4, "expected 4, got %u (%s)\n", count, name);
1535 
1536                                     ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1537                                     ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1538                                     ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1539                                     ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1540                                 }
1541                                 else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed))
1542                                 {
1543                                     ok(count == 16, "expected 16, got %u (%s)\n", count, name);
1544 
1545                                     ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1546                                     ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1547                                     ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name);
1548                                     ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name);
1549                                     ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name);
1550                                     ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name);
1551                                 }
1552                                 else
1553                                 {
1554                                     ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1555 
1556                                     ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name);
1557                                     ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name);
1558                                 }
1559                             }
1560                             else
1561                             {
1562                                 ok(count == 2, "expected 2, got %u (%s)\n", count, name);
1563 
1564                                 ok(colors[0] == 0xff111111, "got %08x\n", colors[0]);
1565                                 ok(colors[1] == 0xff222222, "got %08x\n", colors[1]);
1566                             }
1567                         }
1568 
1569                         IWICBitmapFrameDecode_Release(framedecode);
1570                     }
1571 
1572                     i++;
1573                 }
1574 
1575                 IWICPalette_Release(frame_palette);
1576                 IWICBitmapDecoder_Release(decoder);
1577             }
1578 
1579             IStream_Release(stream);
1580         }
1581 
1582         IWICBitmapEncoder_Release(encoder);
1583     }
1584 }
1585 
1586 static void test_encoder(const struct bitmap_data *src, const CLSID* clsid_encoder,
1587     const struct bitmap_data *dst, const CLSID *clsid_decoder, const char *name)
1588 {
1589     const struct bitmap_data *srcs[2];
1590     const struct bitmap_data *dsts[2];
1591     WICColor colors[256];
1592     IWICPalette *palette;
1593     HRESULT hr;
1594 
1595     hr = IWICImagingFactory_CreatePalette(factory, &palette);
1596     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1597 
1598     memset(colors, 0, sizeof(colors));
1599     colors[0] = 0x11111111;
1600     colors[1] = 0x22222222;
1601     colors[2] = 0x33333333;
1602     colors[3] = 0x44444444;
1603     colors[4] = 0x55555555;
1604     /* TIFF decoder fails to decode a 8bpp frame if palette has less than 256 colors */
1605     hr = IWICPalette_InitializeCustom(palette, colors, 256);
1606     ok(hr == S_OK, "InitializeCustom error %#x\n", hr);
1607 
1608     srcs[0] = src;
1609     srcs[1] = NULL;
1610     dsts[0] = dst;
1611     dsts[1] = NULL;
1612 
1613     test_multi_encoder(srcs, clsid_encoder, dsts, clsid_decoder, NULL, NULL, name, palette);
1614 
1615     IWICPalette_Release(palette);
1616 }
1617 
1618 static void test_encoder_rects(void)
1619 {
1620     const struct bitmap_data *srcs[2];
1621     const struct bitmap_data *dsts[2];
1622     WICRect rc;
1623 
1624     srcs[0] = &testdata_24bppBGR;
1625     srcs[1] = NULL;
1626     dsts[0] = &testdata_24bppBGR;
1627     dsts[1] = NULL;
1628 
1629     rc.X = 0;
1630     rc.Y = 0;
1631     rc.Width = 32;
1632     rc.Height = 2;
1633 
1634     test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL);
1635 
1636     rc.Width = 0;
1637     test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=0", NULL);
1638 
1639     rc.Width = -1;
1640     test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL);
1641 
1642     rc.Width = 32;
1643     rc.Height = 0;
1644     test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL);
1645 
1646     rc.Height = -1;
1647     test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=-1", NULL);
1648 }
1649 
1650 static const struct bitmap_data *multiple_frames[3] = {
1651     &testdata_24bppBGR,
1652     &testdata_24bppBGR,
1653     NULL};
1654 
1655 static const struct bitmap_data *single_frame[2] = {
1656     &testdata_24bppBGR,
1657     NULL};
1658 
1659 static const struct setting png_interlace_settings[] = {
1660     {wszInterlaceOption, PROPBAG2_TYPE_DATA, VT_BOOL, (void*)VARIANT_TRUE},
1661     {NULL}
1662 };
1663 
1664 static void test_converter_8bppIndexed(void)
1665 {
1666     HRESULT hr;
1667     BitmapTestSrc *src_obj;
1668     IWICFormatConverter *converter;
1669     IWICPalette *palette;
1670     UINT count, i;
1671     BYTE buf[32 * 2 * 3]; /* enough to hold 32x2 24bppBGR data */
1672 
1673     CreateTestBitmap(&testdata_24bppBGR, &src_obj);
1674 
1675     hr = IWICImagingFactory_CreatePalette(factory, &palette);
1676     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1677     count = 0xdeadbeef;
1678     hr = IWICPalette_GetColorCount(palette, &count);
1679     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1680     ok(count == 0, "expected 0, got %u\n", count);
1681 
1682     /* NULL palette + Custom type*/
1683     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1684     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1685     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1686                                         &GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone,
1687                                         NULL, 0.0, WICBitmapPaletteTypeCustom);
1688     ok(hr == S_OK, "Initialize error %#x\n", hr);
1689     hr = IWICFormatConverter_CopyPalette(converter, palette);
1690     ok(hr == 0xdeadbeef, "unexpected error %#x\n", hr);
1691     hr = IWICFormatConverter_CopyPixels(converter, NULL, 32 * 3, sizeof(buf), buf);
1692     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1693     IWICFormatConverter_Release(converter);
1694 
1695     /* NULL palette + Custom type*/
1696     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1697     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1698     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1699                                         &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1700                                         NULL, 0.0, WICBitmapPaletteTypeCustom);
1701     ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr);
1702     hr = IWICFormatConverter_CopyPalette(converter, palette);
1703     ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr);
1704     hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1705     ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr);
1706     IWICFormatConverter_Release(converter);
1707 
1708     /* empty palette + Custom type*/
1709     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1710     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1711     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1712                                         &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1713                                         palette, 0.0, WICBitmapPaletteTypeCustom);
1714     ok(hr == S_OK, "Initialize error %#x\n", hr);
1715     hr = IWICFormatConverter_CopyPalette(converter, palette);
1716     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1717     count = 0xdeadbeef;
1718     hr = IWICPalette_GetColorCount(palette, &count);
1719     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1720     ok(count == 0, "expected 0, got %u\n", count);
1721     memset(buf, 0xaa, sizeof(buf));
1722     hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1723     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1724     count = 0;
1725     for (i = 0; i < 32 * 2; i++)
1726         if (buf[i] != 0) count++;
1727     ok(count == 0, "expected 0\n");
1728     IWICFormatConverter_Release(converter);
1729 
1730     /* NULL palette + Predefined type*/
1731     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1732     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1733     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1734                                         &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1735                                         NULL, 0.0, WICBitmapPaletteTypeFixedGray16);
1736     ok(hr == S_OK, "Initialize error %#x\n", hr);
1737     hr = IWICFormatConverter_CopyPalette(converter, palette);
1738     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1739     count = 0xdeadbeef;
1740     hr = IWICPalette_GetColorCount(palette, &count);
1741     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1742     ok(count == 16, "expected 16, got %u\n", count);
1743     hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1744     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1745     count = 0;
1746     for (i = 0; i < 32 * 2; i++)
1747         if (buf[i] != 0) count++;
1748     ok(count != 0, "expected != 0\n");
1749     IWICFormatConverter_Release(converter);
1750 
1751     /* not empty palette + Predefined type*/
1752     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1753     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1754     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1755                                         &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1756                                         palette, 0.0, WICBitmapPaletteTypeFixedHalftone64);
1757     ok(hr == S_OK, "Initialize error %#x\n", hr);
1758     hr = IWICFormatConverter_CopyPalette(converter, palette);
1759     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1760     count = 0xdeadbeef;
1761     hr = IWICPalette_GetColorCount(palette, &count);
1762     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1763     ok(count == 16, "expected 16, got %u\n", count);
1764     hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1765     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1766     count = 0;
1767     for (i = 0; i < 32 * 2; i++)
1768         if (buf[i] != 0) count++;
1769     ok(count != 0, "expected != 0\n");
1770     IWICFormatConverter_Release(converter);
1771 
1772     /* not empty palette + MedianCut type*/
1773     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1774     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1775     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1776                                         &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1777                                         palette, 0.0, WICBitmapPaletteTypeMedianCut);
1778     ok(hr == S_OK, "Initialize error %#x\n", hr);
1779     hr = IWICFormatConverter_CopyPalette(converter, palette);
1780     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1781     count = 0xdeadbeef;
1782     hr = IWICPalette_GetColorCount(palette, &count);
1783     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1784     ok(count == 16, "expected 16, got %u\n", count);
1785     hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1786     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1787     count = 0;
1788     for (i = 0; i < 32 * 2; i++)
1789         if (buf[i] != 0) count++;
1790     ok(count != 0, "expected != 0\n");
1791     IWICFormatConverter_Release(converter);
1792 
1793     /* NULL palette + MedianCut type*/
1794     hr = IWICImagingFactory_CreateFormatConverter(factory, &converter);
1795     ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr);
1796     hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface,
1797                                         &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone,
1798                                         NULL, 0.0, WICBitmapPaletteTypeMedianCut);
1799     ok(hr == S_OK || broken(hr == E_INVALIDARG) /* XP */, "Initialize error %#x\n", hr);
1800     if (hr == S_OK)
1801     {
1802         hr = IWICFormatConverter_CopyPalette(converter, palette);
1803         ok(hr == S_OK, "CopyPalette error %#x\n", hr);
1804         count = 0xdeadbeef;
1805         hr = IWICPalette_GetColorCount(palette, &count);
1806         ok(hr == S_OK, "GetColorCount error %#x\n", hr);
1807         ok(count == 8, "expected 8, got %u\n", count);
1808         hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf);
1809         ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1810         count = 0;
1811         for (i = 0; i < 32 * 2; i++)
1812             if (buf[i] != 0) count++;
1813         ok(count != 0, "expected != 0\n");
1814     }
1815     IWICFormatConverter_Release(converter);
1816 
1817     IWICPalette_Release(palette);
1818     DeleteTestBitmap(src_obj);
1819 }
1820 
1821 START_TEST(converter)
1822 {
1823     HRESULT hr;
1824 
1825     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1826 
1827     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1828                           &IID_IWICImagingFactory, (void **)&factory);
1829     ok(hr == S_OK, "failed to create factory: %#x\n", hr);
1830 
1831     test_converter_8bppIndexed();
1832 
1833     test_conversion(&testdata_24bppRGB, &testdata_1bppIndexed, "24bppRGB -> 1bppIndexed", TRUE);
1834     test_conversion(&testdata_24bppRGB, &testdata_2bppIndexed, "24bppRGB -> 2bppIndexed", TRUE);
1835     test_conversion(&testdata_24bppRGB, &testdata_4bppIndexed, "24bppRGB -> 4bppIndexed", TRUE);
1836     test_conversion(&testdata_24bppRGB, &testdata_8bppIndexed, "24bppRGB -> 8bppIndexed", FALSE);
1837 
1838     test_conversion(&testdata_BlackWhite, &testdata_8bppIndexed_BW, "BlackWhite -> 8bppIndexed", TRUE);
1839     test_conversion(&testdata_1bppIndexed, &testdata_8bppIndexed_BW, "1bppIndexed -> 8bppIndexed", TRUE);
1840     test_conversion(&testdata_2bppIndexed, &testdata_8bppIndexed_4colors, "2bppIndexed -> 8bppIndexed", TRUE);
1841     test_conversion(&testdata_4bppIndexed, &testdata_8bppIndexed, "4bppIndexed -> 8bppIndexed", TRUE);
1842 
1843     test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE);
1844     test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE);
1845     test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE);
1846     test_conversion(&testdata_32bppBGRA80, &testdata_32bppPBGRA, "BGRA -> PBGRA", FALSE);
1847 
1848     test_conversion(&testdata_32bppRGBA, &testdata_32bppRGB, "RGBA -> RGB", FALSE);
1849     test_conversion(&testdata_32bppRGB, &testdata_32bppRGBA, "RGB -> RGBA", FALSE);
1850     test_conversion(&testdata_32bppRGBA, &testdata_32bppRGBA, "RGBA -> RGBA", FALSE);
1851     test_conversion(&testdata_32bppRGBA80, &testdata_32bppPRGBA, "RGBA -> PRGBA", FALSE);
1852 
1853     test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE);
1854     test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE);
1855 
1856     test_conversion(&testdata_24bppRGB, &testdata_24bppRGB, "24bppRGB -> 24bppRGB", FALSE);
1857     test_conversion(&testdata_24bppRGB, &testdata_24bppBGR, "24bppRGB -> 24bppBGR", FALSE);
1858 
1859     test_conversion(&testdata_32bppBGR, &testdata_24bppRGB, "32bppBGR -> 24bppRGB", FALSE);
1860     test_conversion(&testdata_24bppRGB, &testdata_32bppBGR, "24bppRGB -> 32bppBGR", FALSE);
1861     test_conversion(&testdata_32bppBGRA, &testdata_24bppRGB, "32bppBGRA -> 24bppRGB", FALSE);
1862 
1863     test_conversion(&testdata_24bppRGB, &testdata_32bppGrayFloat, "24bppRGB -> 32bppGrayFloat", FALSE);
1864     test_conversion(&testdata_32bppBGR, &testdata_32bppGrayFloat, "32bppBGR -> 32bppGrayFloat", FALSE);
1865 
1866     test_conversion(&testdata_24bppBGR, &testdata_8bppGray, "24bppBGR -> 8bppGray", FALSE);
1867     test_conversion(&testdata_32bppBGR, &testdata_8bppGray, "32bppBGR -> 8bppGray", FALSE);
1868     test_conversion(&testdata_32bppGrayFloat, &testdata_24bppBGR_gray, "32bppGrayFloat -> 24bppBGR gray", FALSE);
1869     test_conversion(&testdata_32bppGrayFloat, &testdata_8bppGray, "32bppGrayFloat -> 8bppGray", FALSE);
1870 
1871     test_invalid_conversion();
1872     test_default_converter();
1873 
1874     test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder,
1875                  &testdata_8bppIndexed, &CLSID_WICGifDecoder, "GIF encoder 8bppIndexed");
1876 
1877     test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder,
1878                  &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite");
1879     test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder,
1880                  &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed");
1881     test_encoder(&testdata_2bppIndexed, &CLSID_WICPngEncoder,
1882                  &testdata_2bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 2bppIndexed");
1883     test_encoder(&testdata_4bppIndexed, &CLSID_WICPngEncoder,
1884                  &testdata_4bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 4bppIndexed");
1885     test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder,
1886                  &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed");
1887     test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder,
1888                  &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR");
1889 if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */
1890 {
1891     test_encoder(&testdata_32bppBGR, &CLSID_WICPngEncoder,
1892                  &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 32bppBGR");
1893 }
1894 
1895     test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder,
1896                  &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite");
1897     test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder,
1898                  &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed");
1899     test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder,
1900                  &testdata_2bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed");
1901     test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder,
1902                  &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed");
1903     test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder,
1904                  &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed");
1905     test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder,
1906                  &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR");
1907 
1908     test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder,
1909                  &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite");
1910     test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder,
1911                  &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed");
1912     test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder,
1913                  &testdata_2bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed");
1914     test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder,
1915                  &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed");
1916     test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder,
1917                  &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed");
1918     test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder,
1919                  &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR");
1920 
1921     test_encoder(&testdata_24bppBGR, &CLSID_WICJpegEncoder,
1922                  &testdata_24bppBGR, NULL, "JPEG encoder 24bppBGR");
1923 
1924     test_multi_encoder(multiple_frames, &CLSID_WICTiffEncoder,
1925                        multiple_frames, &CLSID_WICTiffDecoder, NULL, NULL, "TIFF encoder multi-frame", NULL);
1926 
1927     test_encoder_rects();
1928 
1929     test_multi_encoder(single_frame, &CLSID_WICPngEncoder,
1930                        single_frame, &CLSID_WICPngDecoder, NULL, png_interlace_settings, "PNG encoder interlaced", NULL);
1931 
1932     IWICImagingFactory_Release(factory);
1933 
1934     CoUninitialize();
1935 }
1936