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