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