1 /*
2  * Copyright 2009 Vincent Povirk for CodeWeavers
3  * Copyright 2012,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 <assert.h>
22 
23 #define COBJMACROS
24 
25 #include "windef.h"
26 #include "objbase.h"
27 #include "wincodec.h"
28 #include "wine/test.h"
29 
30 static IWICImagingFactory *factory;
31 
32 static void test_custom_palette(void)
33 {
34     IWICPalette *palette, *palette2;
35     HRESULT hr;
36     WICBitmapPaletteType type=0xffffffff;
37     UINT count=1;
38     const WICColor initcolors[4]={0xff000000,0xff0000ff,0xffffff00,0xffffffff};
39     WICColor colors[4];
40     BOOL boolresult;
41 
42     hr = IWICImagingFactory_CreatePalette(factory, &palette);
43     ok(SUCCEEDED(hr), "CreatePalette failed, hr=%x\n", hr);
44     if (SUCCEEDED(hr))
45     {
46         hr = IWICPalette_GetType(palette, &type);
47         ok(SUCCEEDED(hr), "GetType failed, hr=%x\n", hr);
48         ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %x\n", type);
49 
50         hr = IWICPalette_GetColorCount(palette, &count);
51         ok(SUCCEEDED(hr), "GetColorCount failed, hr=%x\n", hr);
52         ok(count == 0, "expected 0, got %u\n", count);
53 
54         hr = IWICPalette_GetColors(palette, 0, colors, &count);
55         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
56         ok(count == 0, "expected 0, got %u\n", count);
57 
58         hr = IWICPalette_GetColors(palette, 4, colors, &count);
59         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
60         ok(count == 0, "expected 0, got %u\n", count);
61 
62         memcpy(colors, initcolors, sizeof(initcolors));
63         hr = IWICPalette_InitializeCustom(palette, colors, 4);
64         ok(SUCCEEDED(hr), "InitializeCustom failed, hr=%x\n", hr);
65 
66         hr = IWICPalette_GetType(palette, &type);
67         ok(SUCCEEDED(hr), "GetType failed, hr=%x\n", hr);
68         ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %x\n", type);
69 
70         hr = IWICPalette_GetColorCount(palette, &count);
71         ok(SUCCEEDED(hr), "GetColorCount failed, hr=%x\n", hr);
72         ok(count == 4, "expected 4, got %u\n", count);
73 
74         memset(colors, 0, sizeof(colors));
75         count = 0;
76         hr = IWICPalette_GetColors(palette, 4, colors, &count);
77         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
78         ok(count == 4, "expected 4, got %u\n", count);
79         ok(!memcmp(colors, initcolors, sizeof(colors)), "got unexpected palette data\n");
80 
81         memset(colors, 0, sizeof(colors));
82         count = 0;
83         hr = IWICPalette_GetColors(palette, 2, colors, &count);
84         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
85         ok(count == 2, "expected 2, got %u\n", count);
86         ok(!memcmp(colors, initcolors, sizeof(WICColor)*2), "got unexpected palette data\n");
87 
88         count = 0;
89         hr = IWICPalette_GetColors(palette, 6, colors, &count);
90         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
91         ok(count == 4, "expected 4, got %u\n", count);
92 
93         hr = IWICPalette_HasAlpha(palette, &boolresult);
94         ok(SUCCEEDED(hr), "HasAlpha failed, hr=%x\n", hr);
95         ok(!boolresult, "expected FALSE, got TRUE\n");
96 
97         hr = IWICPalette_IsBlackWhite(palette, &boolresult);
98         ok(SUCCEEDED(hr), "IsBlackWhite failed, hr=%x\n", hr);
99         ok(!boolresult, "expected FALSE, got TRUE\n");
100 
101         hr = IWICPalette_IsGrayscale(palette, &boolresult);
102         ok(SUCCEEDED(hr), "IsGrayscale failed, hr=%x\n", hr);
103         ok(!boolresult, "expected FALSE, got TRUE\n");
104 
105         hr = IWICImagingFactory_CreatePalette(factory, &palette2);
106         ok(SUCCEEDED(hr), "CreatePalette failed, hr=%x\n", hr);
107 
108         hr = IWICPalette_InitializeFromPalette(palette2, palette);
109         ok(SUCCEEDED(hr), "InitializeFromPalette failed, hr=%x\n", hr);
110 
111         type = 0xdeadbeef;
112         hr = IWICPalette_GetType(palette2, &type);
113         ok(SUCCEEDED(hr), "GetType failed, hr=%x\n", hr);
114         ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %x\n", type);
115 
116         count = 0xdeadbeef;
117         hr = IWICPalette_GetColorCount(palette2, &count);
118         ok(SUCCEEDED(hr), "GetColorCount failed, hr=%x\n", hr);
119         ok(count == 4, "expected 4, got %u\n", count);
120 
121         memset(colors, 0, sizeof(colors));
122         count = 0xdeadbeef;
123         hr = IWICPalette_GetColors(palette2, 4, colors, &count);
124         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
125         ok(count == 4, "expected 4, got %u\n", count);
126         ok(!memcmp(colors, initcolors, sizeof(colors)), "got unexpected palette data\n");
127 
128         /* try a palette with some alpha in it */
129         colors[2] = 0x80ffffff;
130         hr = IWICPalette_InitializeCustom(palette, colors, 4);
131         ok(SUCCEEDED(hr), "InitializeCustom failed, hr=%x\n", hr);
132 
133         hr = IWICPalette_HasAlpha(palette, &boolresult);
134         ok(SUCCEEDED(hr), "HasAlpha failed, hr=%x\n", hr);
135         ok(boolresult, "expected TRUE, got FALSE\n");
136 
137         /* setting to a 0-color palette is acceptable */
138         hr = IWICPalette_InitializeCustom(palette, NULL, 0);
139         ok(SUCCEEDED(hr), "InitializeCustom failed, hr=%x\n", hr);
140 
141         type = 0xdeadbeef;
142         hr = IWICPalette_GetType(palette, &type);
143         ok(SUCCEEDED(hr), "GetType failed, hr=%x\n", hr);
144         ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %x\n", type);
145 
146         count = 0xdeadbeef;
147         hr = IWICPalette_GetColorCount(palette, &count);
148         ok(SUCCEEDED(hr), "GetColorCount failed, hr=%x\n", hr);
149         ok(count == 0, "expected 0, got %u\n", count);
150 
151         count = 0xdeadbeef;
152         hr = IWICPalette_GetColors(palette, 4, colors, &count);
153         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
154         ok(count == 0, "expected 0, got %u\n", count);
155 
156         hr = IWICPalette_InitializeFromPalette(palette2, palette);
157         ok(SUCCEEDED(hr), "InitializeFromPalette failed, hr=%x\n", hr);
158 
159         type = 0xdeadbeef;
160         hr = IWICPalette_GetType(palette2, &type);
161         ok(SUCCEEDED(hr), "GetType failed, hr=%x\n", hr);
162         ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %x\n", type);
163 
164         count = 0xdeadbeef;
165         hr = IWICPalette_GetColorCount(palette2, &count);
166         ok(SUCCEEDED(hr), "GetColorCount failed, hr=%x\n", hr);
167         ok(count == 0, "expected 0, got %u\n", count);
168 
169         memset(colors, 0, sizeof(colors));
170         count = 0xdeadbeef;
171         hr = IWICPalette_GetColors(palette2, 4, colors, &count);
172         ok(SUCCEEDED(hr), "GetColors failed, hr=%x\n", hr);
173         ok(count == 0, "expected 0, got %u\n", count);
174 
175         /* IWICPalette is paranoid about NULL pointers */
176         hr = IWICPalette_GetType(palette, NULL);
177         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
178 
179         hr = IWICPalette_GetColorCount(palette, NULL);
180         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
181 
182         hr = IWICPalette_InitializeCustom(palette, NULL, 4);
183         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
184 
185         hr = IWICPalette_GetColors(palette, 4, NULL, &count);
186         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
187 
188         hr = IWICPalette_GetColors(palette, 4, colors, NULL);
189         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
190 
191         hr = IWICPalette_HasAlpha(palette, NULL);
192         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
193 
194         hr = IWICPalette_IsBlackWhite(palette, NULL);
195         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
196 
197         hr = IWICPalette_IsGrayscale(palette, NULL);
198         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
199 
200         hr = IWICPalette_InitializeFromPalette(palette, NULL);
201         ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %x\n", hr);
202 
203         IWICPalette_Release(palette2);
204         IWICPalette_Release(palette);
205     }
206 }
207 
208 static void generate_gray16_palette(DWORD *entries, UINT count)
209 {
210     UINT i;
211 
212     assert(count == 16);
213 
214     for (i = 0; i < 16; i++)
215     {
216         entries[i] = 0xff000000;
217         entries[i] |= (i << 20) | (i << 16) | (i << 12) | (i << 8) | (i << 4) | i;
218     }
219 }
220 
221 static void generate_gray256_palette(DWORD *entries, UINT count)
222 {
223     UINT i;
224 
225     assert(count == 256);
226 
227     for (i = 0; i < 256; i++)
228     {
229         entries[i] = 0xff000000;
230         entries[i] |= (i << 16) | (i << 8) | i;
231     }
232 }
233 
234 static void generate_halftone8_palette(DWORD *entries, UINT count, BOOL add_transparent)
235 {
236     UINT i;
237 
238     if (add_transparent)
239         ok(count == 17, "expected 17, got %u\n", count);
240     else
241         ok(count == 16, "expected 16, got %u\n", count);
242 
243     for (i = 0; i < 8; i++)
244     {
245         entries[i] = 0xff000000;
246         if (i & 1) entries[i] |= 0xff;
247         if (i & 2) entries[i] |= 0xff00;
248         if (i & 4) entries[i] |= 0xff0000;
249     }
250 
251     for (i = 8; i < 16; i++)
252     {
253         static const DWORD halftone[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
254                                            0x000080, 0x808000, 0x800080, 0x008080 };
255         entries[i] = 0xff000000;
256         entries[i] |= halftone[i-8];
257     }
258 
259     if (add_transparent)
260         entries[i] = 0;
261 }
262 
263 static void generate_halftone27_palette(DWORD *entries, UINT count, BOOL add_transparent)
264 {
265     static const BYTE halftone_values[4] = { 0x00,0x80,0xff };
266     UINT i;
267 
268     if (add_transparent)
269         ok(count == 29, "expected 29, got %u\n", count);
270     else
271         ok(count == 28, "expected 28, got %u\n", count);
272 
273     for (i = 0; i < 27; i++)
274     {
275         entries[i] = 0xff000000;
276         entries[i] |= halftone_values[i%3];
277         entries[i] |= halftone_values[(i/3)%3] << 8;
278         entries[i] |= halftone_values[(i/9)%3] << 16;
279     }
280 
281     entries[i++] = 0xffc0c0c0;
282     if (add_transparent)
283         entries[i] = 0;
284 }
285 
286 static void generate_halftone64_palette(DWORD *entries, UINT count, BOOL add_transparent)
287 {
288     static const BYTE halftone_values[4] = { 0x00,0x55,0xaa,0xff };
289     UINT i;
290 
291     if (add_transparent)
292         ok(count == 73, "expected 73, got %u\n", count);
293     else
294         ok(count == 72, "expected 72, got %u\n", count);
295 
296     for (i = 0; i < 64; i++)
297     {
298         entries[i] = 0xff000000;
299         entries[i] |= halftone_values[i%4];
300         entries[i] |= halftone_values[(i/4)%4] << 8;
301         entries[i] |= halftone_values[(i/16)%4] << 16;
302     }
303 
304     for (i = 64; i < 72; i++)
305     {
306         static const DWORD halftone[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
307                                            0x000080, 0x808000, 0x800080, 0x008080 };
308         entries[i] = 0xff000000;
309         entries[i] |= halftone[i-64];
310     }
311 
312     if (add_transparent)
313         entries[i] = 0;
314 }
315 
316 static void generate_halftone125_palette(DWORD *entries, UINT count, BOOL add_transparent)
317 {
318     static const BYTE halftone_values[5] = { 0x00, 0x40, 0x80, 0xbf, 0xff };
319     UINT i;
320 
321     if (add_transparent)
322         ok(count == 127, "expected 127, got %u\n", count);
323     else
324         ok(count == 126, "expected 126, got %u\n", count);
325 
326     for (i = 0; i < 125; i++)
327     {
328         entries[i] = 0xff000000;
329         entries[i] |= halftone_values[i%5];
330         entries[i] |= halftone_values[(i/5)%5] << 8;
331         entries[i] |= halftone_values[(i/25)%5] << 16;
332     }
333 
334     entries[i++] = 0xffc0c0c0;
335     if (add_transparent)
336         entries[i] = 0;
337 }
338 
339 static void generate_halftone216_palette(DWORD *entries, UINT count, BOOL add_transparent)
340 {
341     static const BYTE halftone_values[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
342     UINT i;
343 
344     if (add_transparent)
345         ok(count == 225, "expected 225, got %u\n", count);
346     else
347         ok(count == 224, "expected 224, got %u\n", count);
348 
349     for (i = 0; i < 216; i++)
350     {
351         entries[i] = 0xff000000;
352         entries[i] |= halftone_values[i%6];
353         entries[i] |= halftone_values[(i/6)%6] << 8;
354         entries[i] |= halftone_values[(i/36)%6] << 16;
355     }
356 
357     for (i = 216; i < 224; i++)
358     {
359         static const DWORD halftone[8] = { 0xc0c0c0, 0x808080, 0x800000, 0x008000,
360                                            0x000080, 0x808000, 0x800080, 0x008080 };
361         entries[i] = 0xff000000;
362         entries[i] |= halftone[i-216];
363     }
364 
365     if (add_transparent)
366         entries[i] = 0;
367 }
368 
369 static void generate_halftone252_palette(DWORD *entries, UINT count, BOOL add_transparent)
370 {
371     static const BYTE halftone_values_rb[6] = { 0x00,0x33,0x66,0x99,0xcc,0xff };
372     static const BYTE halftone_values_g[7] = { 0x00,0x2b,0x55,0x80,0xaa,0xd5,0xff };
373     UINT i;
374 
375     if (add_transparent)
376         ok(count == 253, "expected 253, got %u\n", count);
377     else
378         ok(count == 252, "expected 252, got %u\n", count);
379 
380     for (i = 0; i < 252; i++)
381     {
382         entries[i] = 0xff000000;
383         entries[i] |= halftone_values_rb[i%6];
384         entries[i] |= halftone_values_g[(i/6)%7] << 8;
385         entries[i] |= halftone_values_rb[(i/42)%6] << 16;
386     }
387 
388     if (add_transparent)
389         entries[i] = 0;
390 }
391 
392 static void generate_halftone256_palette(DWORD *entries, UINT count, BOOL add_transparent)
393 {
394     static const BYTE halftone_values_b[4] = { 0x00,0x55,0xaa,0xff };
395     static const BYTE halftone_values_gr[8] = { 0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff };
396     UINT i;
397 
398     assert(count == 256);
399 
400     for (i = 0; i < 256; i++)
401     {
402         entries[i] = 0xff000000;
403         entries[i] |= halftone_values_b[i%4];
404         entries[i] |= halftone_values_gr[(i/4)%8] << 8;
405         entries[i] |= halftone_values_gr[(i/32)%8] << 16;
406     }
407 
408     if (add_transparent)
409         entries[255] = 0;
410 }
411 
412 static void test_predefined_palette(void)
413 {
414     static struct test_data
415     {
416         WICBitmapPaletteType type;
417         BOOL is_bw, is_gray;
418         UINT count;
419         WICColor color[256];
420         BOOL add_transparent;
421     } td[] =
422     {
423         { WICBitmapPaletteTypeFixedBW, 1, 1, 2, { 0xff000000, 0xffffffff } },
424         { WICBitmapPaletteTypeFixedBW, 1, 1, 2, { 0xff000000, 0xffffffff }, 1 },
425         { WICBitmapPaletteTypeFixedGray4, 0, 1, 4,
426           { 0xff000000, 0xff555555, 0xffaaaaaa, 0xffffffff } },
427         { WICBitmapPaletteTypeFixedGray4, 0, 1, 4,
428           { 0xff000000, 0xff555555, 0xffaaaaaa, 0xffffffff }, 1 },
429         { WICBitmapPaletteTypeFixedGray16, 0, 1, 16, { 0 } },
430         { WICBitmapPaletteTypeFixedGray16, 0, 1, 16, { 0 }, 1 },
431         { WICBitmapPaletteTypeFixedGray256, 0, 1, 256, { 0 } },
432         { WICBitmapPaletteTypeFixedGray256, 0, 1, 256, { 0 }, 1 },
433         { WICBitmapPaletteTypeFixedHalftone8, 0, 0, 16, { 0 } },
434         { WICBitmapPaletteTypeFixedHalftone8, 0, 0, 17, { 0 }, 1 },
435         { WICBitmapPaletteTypeFixedHalftone27, 0, 0, 28, { 0 } },
436         { WICBitmapPaletteTypeFixedHalftone27, 0, 0, 29, { 0 }, 1 },
437         { WICBitmapPaletteTypeFixedHalftone64, 0, 0, 72, { 0 } },
438         { WICBitmapPaletteTypeFixedHalftone64, 0, 0, 73, { 0 }, 1 },
439         { WICBitmapPaletteTypeFixedHalftone125, 0, 0, 126, { 0 } },
440         { WICBitmapPaletteTypeFixedHalftone125, 0, 0, 127, { 0 }, 1 },
441         { WICBitmapPaletteTypeFixedHalftone216, 0, 0, 224, { 0 } },
442         { WICBitmapPaletteTypeFixedHalftone216, 0, 0, 225, { 0 }, 1 },
443         { WICBitmapPaletteTypeFixedHalftone252, 0, 0, 252, { 0 } },
444         { WICBitmapPaletteTypeFixedHalftone252, 0, 0, 253, { 0 }, 1 },
445         { WICBitmapPaletteTypeFixedHalftone256, 0, 0, 256, { 0 } },
446         { WICBitmapPaletteTypeFixedHalftone256, 0, 0, 256, { 0 }, 1 }
447     };
448     IWICPalette *palette;
449     HRESULT hr;
450     WICBitmapPaletteType type;
451     UINT count, i, ret;
452     BOOL bret;
453     WICColor color[256];
454 
455     hr = IWICImagingFactory_CreatePalette(factory, &palette);
456     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
457     hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeCustom, FALSE);
458     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
459     hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeMedianCut, FALSE);
460     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
461     hr = IWICPalette_InitializePredefined(palette, 0x0f, FALSE);
462     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
463     IWICPalette_Release(palette);
464 
465     for (i = 0; i < ARRAY_SIZE(td); i++)
466     {
467         hr = IWICImagingFactory_CreatePalette(factory, &palette);
468         ok(hr == S_OK, "%u: CreatePalette error %#x\n", i, hr);
469 
470         hr = IWICPalette_InitializePredefined(palette, td[i].type, td[i].add_transparent);
471         ok(hr == S_OK, "%u: InitializePredefined error %#x\n", i, hr);
472 
473         bret = -1;
474         hr = IWICPalette_IsBlackWhite(palette, &bret);
475         ok(hr == S_OK, "%u: IsBlackWhite error %#x\n", i, hr);
476         ok(bret == td[i].is_bw ||
477            broken(td[i].type == WICBitmapPaletteTypeFixedBW && bret != td[i].is_bw), /* XP */
478            "%u: expected %d, got %d\n",i, td[i].is_bw, bret);
479 
480         bret = -1;
481         hr = IWICPalette_IsGrayscale(palette, &bret);
482         ok(hr == S_OK, "%u: IsGrayscale error %#x\n", i, hr);
483         ok(bret == td[i].is_gray, "%u: expected %d, got %d\n", i, td[i].is_gray, bret);
484 
485         type = -1;
486         hr = IWICPalette_GetType(palette, &type);
487         ok(hr == S_OK, "%u: GetType error %#x\n", i, hr);
488         ok(type == td[i].type, "%u: expected %#x, got %#x\n", i, td[i].type, type);
489 
490         count = 0xdeadbeef;
491         hr = IWICPalette_GetColorCount(palette, &count);
492         ok(hr == S_OK, "%u: GetColorCount error %#x\n", i, hr);
493         ok(count == td[i].count, "%u: expected %u, got %u\n", i, td[i].count, count);
494 
495         hr = IWICPalette_GetColors(palette, count, color, &ret);
496         ok(hr == S_OK, "%u: GetColors error %#x\n", i, hr);
497         ok(ret == count, "%u: expected %u, got %u\n", i, count, ret);
498         if (ret == td[i].count)
499         {
500             UINT j;
501 
502             if (td[i].type == WICBitmapPaletteTypeFixedGray16)
503                 generate_gray16_palette(td[i].color, td[i].count);
504             else if (td[i].type == WICBitmapPaletteTypeFixedGray256)
505                 generate_gray256_palette(td[i].color, td[i].count);
506             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone8)
507                 generate_halftone8_palette(td[i].color, td[i].count, td[i].add_transparent);
508             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone27)
509                 generate_halftone27_palette(td[i].color, td[i].count, td[i].add_transparent);
510             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone64)
511                 generate_halftone64_palette(td[i].color, td[i].count, td[i].add_transparent);
512             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone125)
513                 generate_halftone125_palette(td[i].color, td[i].count, td[i].add_transparent);
514             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone216)
515                 generate_halftone216_palette(td[i].color, td[i].count, td[i].add_transparent);
516             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone252)
517                 generate_halftone252_palette(td[i].color, td[i].count, td[i].add_transparent);
518             else if (td[i].type == WICBitmapPaletteTypeFixedHalftone256)
519                 generate_halftone256_palette(td[i].color, td[i].count, td[i].add_transparent);
520 
521             for (j = 0; j < count; j++)
522             {
523                 ok(color[j] == td[i].color[j], "%u:[%u]: expected %#x, got %#x\n",
524                    i, j, td[i].color[j], color[j]);
525             }
526         }
527 
528         IWICPalette_Release(palette);
529     }
530 }
531 
532 static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride)
533 {
534     BYTE *src;
535     UINT i, j, scale;
536 
537     *width = 256;
538     *height = 256;
539     *stride = (*width * 3 + 3) & ~3;
540     trace("width %d, height %d, stride %d\n", *width, *height, *stride);
541 
542     src = HeapAlloc(GetProcessHeap(), 0, *stride * *height);
543 
544     scale = 256 / *width;
545     if (!scale) scale = 1;
546 
547     for (i = 0; i < *height; i++)
548     {
549         for (j = 0; j < *width; j++)
550         {
551             src[i * *stride + j*3 + 0] = scale * i;
552             src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2);
553             src[i * *stride + j*3 + 2] = scale * j;
554         }
555     }
556 
557     return src;
558 }
559 
560 static void test_palette_from_bitmap(void)
561 {
562     HRESULT hr;
563     BYTE *data;
564     IWICBitmap *bitmap;
565     IWICPalette *palette;
566     WICBitmapPaletteType type;
567     UINT width, height, stride, count, ret;
568     WICColor color[257];
569 
570     data = init_bitmap(&width, &height, &stride);
571 
572     hr = IWICImagingFactory_CreateBitmapFromMemory(factory, width, height, &GUID_WICPixelFormat24bppRGB,
573                                                    stride, stride * height, data, &bitmap);
574     ok(hr == S_OK, "CreateBitmapFromMemory error %#x\n", hr);
575 
576     hr = IWICImagingFactory_CreatePalette(factory, &palette);
577     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
578 
579     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 0, FALSE);
580     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
581 
582     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 1, FALSE);
583     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
584 
585     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 257, FALSE);
586     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
587 
588     hr = IWICPalette_InitializeFromBitmap(palette, NULL, 16, FALSE);
589     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr);
590 
591     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, FALSE);
592     ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr);
593     count = 0;
594     hr = IWICPalette_GetColorCount(palette, &count);
595     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
596     ok(count == 2, "expected 2, got %u\n", count);
597 
598     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, TRUE);
599     ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr);
600     count = 0;
601     hr = IWICPalette_GetColorCount(palette, &count);
602     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
603     ok(count == 2, "expected 2, got %u\n", count);
604 
605     /* without transparent color */
606     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, FALSE);
607     ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr);
608     type = -1;
609     hr = IWICPalette_GetType(palette, &type);
610     ok(hr == S_OK, "GetType error %#x\n", hr);
611     ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type);
612     count = 0;
613     hr = IWICPalette_GetColorCount(palette, &count);
614     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
615     ok(count == 16, "expected 16, got %u\n", count);
616     memset(color, 0, sizeof(color));
617     hr = IWICPalette_GetColors(palette, count, color, &ret);
618     ok(hr == S_OK, "GetColors error %#x\n", hr);
619     ok(ret == count, "expected %u, got %u\n", count, ret);
620     ok(color[count - 1] != 0, "expected !0, got %08x\n", color[count - 1]);
621 
622     /* with transparent color */
623     hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, TRUE);
624     ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr);
625     type = -1;
626     hr = IWICPalette_GetType(palette, &type);
627     ok(hr == S_OK, "GetType error %#x\n", hr);
628     ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type);
629     count = 0;
630     hr = IWICPalette_GetColorCount(palette, &count);
631     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
632     ok(count == 16, "expected 16, got %u\n", count);
633     memset(color, 0xff, sizeof(color));
634     hr = IWICPalette_GetColors(palette, count, color, &ret);
635     ok(hr == S_OK, "GetColors error %#x\n", hr);
636     ok(ret == count, "expected %u, got %u\n", count, ret);
637     ok(color[count - 1] == 0, "expected 0, got %08x\n", color[count - 1]);
638 
639     IWICPalette_Release(palette);
640     IWICBitmap_Release(bitmap);
641 
642     HeapFree(GetProcessHeap(), 0, data);
643 }
644 
645 START_TEST(palette)
646 {
647     HRESULT hr;
648 
649     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
650 
651     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
652                           &IID_IWICImagingFactory, (void **)&factory);
653     ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
654 
655     test_custom_palette();
656     test_predefined_palette();
657     test_palette_from_bitmap();
658 
659     IWICImagingFactory_Release(factory);
660 
661     CoUninitialize();
662 }
663