1c2c66affSColin Finck /*
223ec1e5eSAmine Khaldi  * Copyright 2012,2016 Dmitry Timoshkov
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
1923ec1e5eSAmine Khaldi #include <math.h>
2023ec1e5eSAmine Khaldi #include <stdarg.h>
2123ec1e5eSAmine Khaldi #include <stdio.h>
2223ec1e5eSAmine Khaldi 
2323ec1e5eSAmine Khaldi #define COBJMACROS
2423ec1e5eSAmine Khaldi 
2523ec1e5eSAmine Khaldi #include "windef.h"
2623ec1e5eSAmine Khaldi #include "wincodec.h"
2723ec1e5eSAmine Khaldi #include "wine/test.h"
28c2c66affSColin Finck 
29eea81f52SAmine Khaldi #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
_expect_ref(IUnknown * obj,ULONG ref,int line)30eea81f52SAmine Khaldi static void _expect_ref(IUnknown* obj, ULONG ref, int line)
31eea81f52SAmine Khaldi {
32eea81f52SAmine Khaldi     ULONG rc;
33eea81f52SAmine Khaldi     IUnknown_AddRef(obj);
34eea81f52SAmine Khaldi     rc = IUnknown_Release(obj);
35eea81f52SAmine Khaldi     ok_(__FILE__,line)(rc == ref, "expected refcount %d, got %d\n", ref, rc);
36eea81f52SAmine Khaldi }
37eea81f52SAmine Khaldi 
38c2c66affSColin Finck #define IFD_BYTE 1
39c2c66affSColin Finck #define IFD_ASCII 2
40c2c66affSColin Finck #define IFD_SHORT 3
41c2c66affSColin Finck #define IFD_LONG 4
42c2c66affSColin Finck #define IFD_RATIONAL 5
43c2c66affSColin Finck #define IFD_SBYTE 6
44c2c66affSColin Finck #define IFD_UNDEFINED 7
45c2c66affSColin Finck #define IFD_SSHORT 8
46c2c66affSColin Finck #define IFD_SLONG 9
47c2c66affSColin Finck #define IFD_SRATIONAL 10
48c2c66affSColin Finck #define IFD_FLOAT 11
49c2c66affSColin Finck #define IFD_DOUBLE 12
50c2c66affSColin Finck 
51a5cb9a0aSAmine Khaldi #include "pshpack2.h"
52c2c66affSColin Finck struct IFD_entry
53c2c66affSColin Finck {
54c2c66affSColin Finck     SHORT id;
55c2c66affSColin Finck     SHORT type;
56c2c66affSColin Finck     ULONG count;
57c2c66affSColin Finck     LONG  value;
58c2c66affSColin Finck };
59c2c66affSColin Finck 
60c2c66affSColin Finck struct IFD_rational
61c2c66affSColin Finck {
62c2c66affSColin Finck     LONG numerator;
63c2c66affSColin Finck     LONG denominator;
64c2c66affSColin Finck };
65c2c66affSColin Finck 
66c2c66affSColin Finck static const struct tiff_1bpp_data
67c2c66affSColin Finck {
68c2c66affSColin Finck     USHORT byte_order;
69c2c66affSColin Finck     USHORT version;
70c2c66affSColin Finck     ULONG  dir_offset;
71c2c66affSColin Finck     USHORT number_of_entries;
72c2c66affSColin Finck     struct IFD_entry entry[13];
73c2c66affSColin Finck     ULONG next_IFD;
74c2c66affSColin Finck     struct IFD_rational res;
75c2c66affSColin Finck     BYTE pixel_data[4];
76c2c66affSColin Finck } tiff_1bpp_data =
77c2c66affSColin Finck {
78c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
79c2c66affSColin Finck     'M' | 'M' << 8,
80c2c66affSColin Finck #else
81c2c66affSColin Finck     'I' | 'I' << 8,
82c2c66affSColin Finck #endif
83c2c66affSColin Finck     42,
84c2c66affSColin Finck     FIELD_OFFSET(struct tiff_1bpp_data, number_of_entries),
85c2c66affSColin Finck     13,
86c2c66affSColin Finck     {
87c2c66affSColin Finck         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
88c2c66affSColin Finck         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
89c2c66affSColin Finck         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
90c2c66affSColin Finck         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
91c2c66affSColin Finck         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
92c2c66affSColin Finck         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
93c2c66affSColin Finck         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1bpp_data, pixel_data) }, /* STRIPOFFSETS */
94c2c66affSColin Finck         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
95c2c66affSColin Finck         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
96c2c66affSColin Finck         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
9723ec1e5eSAmine Khaldi         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1bpp_data, res) }, /* XRESOLUTION */
9823ec1e5eSAmine Khaldi         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1bpp_data, res) }, /* YRESOLUTION */
99c2c66affSColin Finck         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
100c2c66affSColin Finck     },
101c2c66affSColin Finck     0,
102c2c66affSColin Finck     { 900, 3 },
103c2c66affSColin Finck     { 0x11, 0x22, 0x33, 0 }
104c2c66affSColin Finck };
105c2c66affSColin Finck 
106c2c66affSColin Finck static const struct tiff_8bpp_alpha
107c2c66affSColin Finck {
108c2c66affSColin Finck     USHORT byte_order;
109c2c66affSColin Finck     USHORT version;
110c2c66affSColin Finck     ULONG  dir_offset;
111c2c66affSColin Finck     USHORT number_of_entries;
112c2c66affSColin Finck     struct IFD_entry entry[15];
113c2c66affSColin Finck     ULONG next_IFD;
114c2c66affSColin Finck     struct IFD_rational res;
115c2c66affSColin Finck     BYTE pixel_data[8];
116c2c66affSColin Finck } tiff_8bpp_alpha =
117c2c66affSColin Finck {
118c2c66affSColin Finck #ifdef WORDS_BIGENDIAN
119c2c66affSColin Finck     'M' | 'M' << 8,
120c2c66affSColin Finck #else
121c2c66affSColin Finck     'I' | 'I' << 8,
122c2c66affSColin Finck #endif
123c2c66affSColin Finck     42,
124c2c66affSColin Finck     FIELD_OFFSET(struct tiff_8bpp_alpha, number_of_entries),
125c2c66affSColin Finck     15,
126c2c66affSColin Finck     {
127c2c66affSColin Finck         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
128c2c66affSColin Finck         { 0x100, IFD_LONG, 1, 2 }, /* IMAGEWIDTH */
129c2c66affSColin Finck         { 0x101, IFD_LONG, 1, 2 }, /* IMAGELENGTH */
130c2c66affSColin Finck         { 0x102, IFD_SHORT, 2, MAKELONG(8, 8) }, /* BITSPERSAMPLE */
131c2c66affSColin Finck         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
132c2c66affSColin Finck         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
133c2c66affSColin Finck         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_8bpp_alpha, pixel_data) }, /* STRIPOFFSETS */
134c2c66affSColin Finck         { 0x115, IFD_SHORT, 1, 2 }, /* SAMPLESPERPIXEL */
135c2c66affSColin Finck         { 0x116, IFD_LONG, 1, 2 }, /* ROWSPERSTRIP */
136c2c66affSColin Finck         { 0x117, IFD_LONG, 1, 8 }, /* STRIPBYTECOUNT */
13723ec1e5eSAmine Khaldi         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_alpha, res) }, /* XRESOLUTION */
13823ec1e5eSAmine Khaldi         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_alpha, res) }, /* YRESOLUTION */
139c2c66affSColin Finck         { 0x11c, IFD_SHORT, 1, 1 }, /* PLANARCONFIGURATION */
140c2c66affSColin Finck         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
141c2c66affSColin Finck         { 0x152, IFD_SHORT, 1, 1 } /* EXTRASAMPLES: 1 - Associated alpha with pre-multiplied color */
142c2c66affSColin Finck     },
143c2c66affSColin Finck     0,
144c2c66affSColin Finck     { 96, 1 },
145c2c66affSColin Finck     { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 }
146c2c66affSColin Finck };
14723ec1e5eSAmine Khaldi 
14823ec1e5eSAmine Khaldi static const struct tiff_8bpp_data
14923ec1e5eSAmine Khaldi {
15023ec1e5eSAmine Khaldi     USHORT byte_order;
15123ec1e5eSAmine Khaldi     USHORT version;
15223ec1e5eSAmine Khaldi     ULONG  dir_offset;
15323ec1e5eSAmine Khaldi     USHORT number_of_entries;
15423ec1e5eSAmine Khaldi     struct IFD_entry entry[14];
15523ec1e5eSAmine Khaldi     ULONG next_IFD;
15623ec1e5eSAmine Khaldi     struct IFD_rational res;
15723ec1e5eSAmine Khaldi     short palette_data[3][256];
15823ec1e5eSAmine Khaldi     BYTE pixel_data[4];
15923ec1e5eSAmine Khaldi } tiff_8bpp_data =
16023ec1e5eSAmine Khaldi {
16123ec1e5eSAmine Khaldi #ifdef WORDS_BIGENDIAN
16223ec1e5eSAmine Khaldi     'M' | 'M' << 8,
16323ec1e5eSAmine Khaldi #else
16423ec1e5eSAmine Khaldi     'I' | 'I' << 8,
16523ec1e5eSAmine Khaldi #endif
16623ec1e5eSAmine Khaldi     42,
16723ec1e5eSAmine Khaldi     FIELD_OFFSET(struct tiff_8bpp_data, number_of_entries),
16823ec1e5eSAmine Khaldi     14,
16923ec1e5eSAmine Khaldi     {
17023ec1e5eSAmine Khaldi         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
17123ec1e5eSAmine Khaldi         { 0x100, IFD_LONG, 1, 4 }, /* IMAGEWIDTH */
17223ec1e5eSAmine Khaldi         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
17323ec1e5eSAmine Khaldi         { 0x102, IFD_SHORT, 1, 8 }, /* BITSPERSAMPLE: XP doesn't accept IFD_LONG here */
17423ec1e5eSAmine Khaldi         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
17523ec1e5eSAmine Khaldi         { 0x106, IFD_SHORT, 1, 3 }, /* PHOTOMETRIC */
17623ec1e5eSAmine Khaldi         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_8bpp_data, pixel_data) }, /* STRIPOFFSETS */
17723ec1e5eSAmine Khaldi         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
17823ec1e5eSAmine Khaldi         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
17923ec1e5eSAmine Khaldi         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
18023ec1e5eSAmine Khaldi         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_data, res) },
18123ec1e5eSAmine Khaldi         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_data, res) },
18223ec1e5eSAmine Khaldi         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
18323ec1e5eSAmine Khaldi         { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_8bpp_data, palette_data) } /* COLORMAP */
18423ec1e5eSAmine Khaldi     },
18523ec1e5eSAmine Khaldi     0,
18623ec1e5eSAmine Khaldi     { 96, 1 },
18723ec1e5eSAmine Khaldi     { { 0 } },
18823ec1e5eSAmine Khaldi     { 0,1,2,3 }
18923ec1e5eSAmine Khaldi };
19023ec1e5eSAmine Khaldi 
19123ec1e5eSAmine Khaldi static const struct tiff_resolution_test_data
19223ec1e5eSAmine Khaldi {
19323ec1e5eSAmine Khaldi     struct IFD_rational resx;
19423ec1e5eSAmine Khaldi     struct IFD_rational resy;
19523ec1e5eSAmine Khaldi     LONG resolution_unit;
19623ec1e5eSAmine Khaldi     double expected_dpi_x;
19723ec1e5eSAmine Khaldi     double expected_dpi_y;
19823ec1e5eSAmine Khaldi     /* if != 0: values for different behavior of some Windows versions */
19923ec1e5eSAmine Khaldi     double broken_dpi_x;
20023ec1e5eSAmine Khaldi     double broken_dpi_y;
20123ec1e5eSAmine Khaldi } tiff_resolution_test_data[] =
20223ec1e5eSAmine Khaldi {
20323ec1e5eSAmine Khaldi     { { 100, 1 }, {  50, 1 }, 0, 100.0,  50.0,     0,      0  }, /* invalid resolution unit */
20423ec1e5eSAmine Khaldi     { {  50, 1 }, { 100, 1 }, 0,  50.0, 100.0,     0,      0  },
20523ec1e5eSAmine Khaldi 
20623ec1e5eSAmine Khaldi     { { 100, 1 }, {  50, 1 }, 1, 100.0,  50.0,     0,      0  }, /* RESUNIT_NONE */
20723ec1e5eSAmine Khaldi     { {  50, 1 }, { 100, 1 }, 1,  50.0, 100.0,     0,      0  },
20823ec1e5eSAmine Khaldi 
20923ec1e5eSAmine Khaldi     { {  49, 1 }, {  49, 1 }, 2,  49.0,  49.0,     0,      0  }, /* same resolution for both X and Y */
21023ec1e5eSAmine Khaldi     { {  33, 1 }, {  55, 1 }, 2,  33.0,  55.0,     0,      0  }, /* different resolutions for X and Y */
21123ec1e5eSAmine Khaldi     { {  50, 2 }, {  66, 3 }, 2,  25.0,  22.0,     0,      0  }, /* denominator != 1 */
21223ec1e5eSAmine Khaldi 
21323ec1e5eSAmine Khaldi     { { 100, 1 }, { 200, 1 }, 3, 254.0, 508.0,     0,      0  }, /* unit = centimeters */
21423ec1e5eSAmine Khaldi 
21523ec1e5eSAmine Khaldi     /* XP and Server 2003 do not discard both resolution values if only one of them is invalid */
21623ec1e5eSAmine Khaldi     { {   0, 1 }, {  29, 1 }, 2,  96.0,  96.0,     0,   29.0  }, /* resolution 0 */
21723ec1e5eSAmine Khaldi     { {  58, 1 }, {  29, 0 }, 2,  96.0,  96.0,  58.0,      0  }, /* denominator 0 (division by zero) */
21823ec1e5eSAmine Khaldi 
21923ec1e5eSAmine Khaldi     /* XP and Server 2003 return 96 dots per centimeter (= 243.84 dpi) as fallback value */
22023ec1e5eSAmine Khaldi     { {   0, 1 }, { 100, 1 }, 3,  96.0,  96.0, 243.84, 254.0  }, /* resolution 0 and unit = centimeters */
22123ec1e5eSAmine Khaldi     { {  50, 1 }, {  72, 0 }, 3,  96.0,  96.0, 127.0,  243.84 }  /* denominator 0 and unit = centimeters */
22223ec1e5eSAmine Khaldi };
22323ec1e5eSAmine Khaldi 
22423ec1e5eSAmine Khaldi static struct tiff_resolution_image_data
22523ec1e5eSAmine Khaldi {
22623ec1e5eSAmine Khaldi     USHORT byte_order;
22723ec1e5eSAmine Khaldi     USHORT version;
22823ec1e5eSAmine Khaldi     ULONG dir_offset;
22923ec1e5eSAmine Khaldi     USHORT number_of_entries;
23023ec1e5eSAmine Khaldi     struct IFD_entry entry[13];
23123ec1e5eSAmine Khaldi     ULONG next_IFD;
23223ec1e5eSAmine Khaldi     struct IFD_rational resx;
23323ec1e5eSAmine Khaldi     struct IFD_rational resy;
23423ec1e5eSAmine Khaldi     BYTE pixel_data[4];
23523ec1e5eSAmine Khaldi } tiff_resolution_image_data =
23623ec1e5eSAmine Khaldi {
23723ec1e5eSAmine Khaldi #ifdef WORDS_BIGENDIAN
23823ec1e5eSAmine Khaldi     'M' | 'M' << 8,
23923ec1e5eSAmine Khaldi #else
24023ec1e5eSAmine Khaldi     'I' | 'I' << 8,
24123ec1e5eSAmine Khaldi #endif
24223ec1e5eSAmine Khaldi     42,
24323ec1e5eSAmine Khaldi     FIELD_OFFSET(struct tiff_resolution_image_data, number_of_entries),
24423ec1e5eSAmine Khaldi     13,
24523ec1e5eSAmine Khaldi     {
24623ec1e5eSAmine Khaldi         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
24723ec1e5eSAmine Khaldi         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
24823ec1e5eSAmine Khaldi         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
24923ec1e5eSAmine Khaldi         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
25023ec1e5eSAmine Khaldi         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
25123ec1e5eSAmine Khaldi         { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
25223ec1e5eSAmine Khaldi         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_resolution_image_data, pixel_data) }, /* STRIPOFFSETS */
25323ec1e5eSAmine Khaldi         { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
25423ec1e5eSAmine Khaldi         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
25523ec1e5eSAmine Khaldi         { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
25623ec1e5eSAmine Khaldi         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_resolution_image_data, resx) }, /* XRESOLUTION */
25723ec1e5eSAmine Khaldi         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_resolution_image_data, resy) }, /* YRESOLUTION */
25823ec1e5eSAmine Khaldi         { 0x128, IFD_SHORT, 1, 1 }, /* RESOLUTIONUNIT -- value will be filled with test data */
25923ec1e5eSAmine Khaldi     },
26023ec1e5eSAmine Khaldi     0,
26123ec1e5eSAmine Khaldi     { 72, 1 }, /* value will be filled with test data */
26223ec1e5eSAmine Khaldi     { 72, 1 }, /* value will be filled with test data */
26323ec1e5eSAmine Khaldi     { 0x11, 0x22, 0x33, 0 }
26423ec1e5eSAmine Khaldi };
265eea81f52SAmine Khaldi 
266eea81f52SAmine Khaldi static const struct tiff_24bpp_data
267eea81f52SAmine Khaldi {
268eea81f52SAmine Khaldi     USHORT byte_order;
269eea81f52SAmine Khaldi     USHORT version;
270eea81f52SAmine Khaldi     ULONG  dir_offset;
271eea81f52SAmine Khaldi     USHORT number_of_entries;
272eea81f52SAmine Khaldi     struct IFD_entry entry[13];
273eea81f52SAmine Khaldi     ULONG next_IFD;
274eea81f52SAmine Khaldi     struct IFD_rational res;
275eea81f52SAmine Khaldi     BYTE pixel_data[3];
276eea81f52SAmine Khaldi } tiff_24bpp_data =
277eea81f52SAmine Khaldi {
278eea81f52SAmine Khaldi #ifdef WORDS_BIGENDIAN
279eea81f52SAmine Khaldi     'M' | 'M' << 8,
280eea81f52SAmine Khaldi #else
281eea81f52SAmine Khaldi     'I' | 'I' << 8,
282eea81f52SAmine Khaldi #endif
283eea81f52SAmine Khaldi     42,
284eea81f52SAmine Khaldi     FIELD_OFFSET(struct tiff_1bpp_data, number_of_entries),
285eea81f52SAmine Khaldi     13,
286eea81f52SAmine Khaldi     {
287eea81f52SAmine Khaldi         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
288eea81f52SAmine Khaldi         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
289eea81f52SAmine Khaldi         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
290eea81f52SAmine Khaldi         { 0x102, IFD_SHORT, 1, 8 }, /* BITSPERSAMPLE */
291eea81f52SAmine Khaldi         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
292eea81f52SAmine Khaldi         { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
293eea81f52SAmine Khaldi         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_24bpp_data, pixel_data) }, /* STRIPOFFSETS */
294eea81f52SAmine Khaldi         { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */
295eea81f52SAmine Khaldi         { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
296eea81f52SAmine Khaldi         { 0x117, IFD_LONG, 1, 3 }, /* STRIPBYTECOUNT */
297eea81f52SAmine Khaldi         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_24bpp_data, res) }, /* XRESOLUTION */
298eea81f52SAmine Khaldi         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_24bpp_data, res) }, /* YRESOLUTION */
299eea81f52SAmine Khaldi         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
300eea81f52SAmine Khaldi     },
301eea81f52SAmine Khaldi     0,
302eea81f52SAmine Khaldi     { 900, 3 },
303eea81f52SAmine Khaldi     { 0x11, 0x22, 0x33 }
304eea81f52SAmine Khaldi };
305*3e9c4dadSThomas Faber 
306*3e9c4dadSThomas Faber static const struct tiff_4bps_bgra
307*3e9c4dadSThomas Faber {
308*3e9c4dadSThomas Faber     USHORT byte_order;
309*3e9c4dadSThomas Faber     USHORT version;
310*3e9c4dadSThomas Faber     ULONG  dir_offset;
311*3e9c4dadSThomas Faber     USHORT number_of_entries;
312*3e9c4dadSThomas Faber     struct IFD_entry entry[14];
313*3e9c4dadSThomas Faber     ULONG next_IFD;
314*3e9c4dadSThomas Faber     struct IFD_rational res;
315*3e9c4dadSThomas Faber     BYTE pixel_data[4];
316*3e9c4dadSThomas Faber } tiff_4bps_bgra =
317*3e9c4dadSThomas Faber {
318*3e9c4dadSThomas Faber #ifdef WORDS_BIGENDIAN
319*3e9c4dadSThomas Faber     'M' | 'M' << 8,
320*3e9c4dadSThomas Faber #else
321*3e9c4dadSThomas Faber     'I' | 'I' << 8,
322*3e9c4dadSThomas Faber #endif
323*3e9c4dadSThomas Faber     42,
324*3e9c4dadSThomas Faber     FIELD_OFFSET(struct tiff_4bps_bgra, number_of_entries),
325*3e9c4dadSThomas Faber     14,
326*3e9c4dadSThomas Faber     {
327*3e9c4dadSThomas Faber         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
328*3e9c4dadSThomas Faber         { 0x100, IFD_LONG, 1, 3 }, /* IMAGEWIDTH */
329*3e9c4dadSThomas Faber         { 0x101, IFD_LONG, 1, 2 }, /* IMAGELENGTH */
330*3e9c4dadSThomas Faber         { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
331*3e9c4dadSThomas Faber         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION */
332*3e9c4dadSThomas Faber         { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
333*3e9c4dadSThomas Faber         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_4bps_bgra, pixel_data) }, /* STRIPOFFSETS */
334*3e9c4dadSThomas Faber         { 0x115, IFD_SHORT, 1, 4 }, /* SAMPLESPERPIXEL */
335*3e9c4dadSThomas Faber         { 0x116, IFD_LONG, 1, 2 }, /* ROWSPERSTRIP */
336*3e9c4dadSThomas Faber         { 0x117, IFD_LONG, 1, 4 }, /* STRIPBYTECOUNT */
337*3e9c4dadSThomas Faber         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_4bps_bgra, res) }, /* XRESOLUTION */
338*3e9c4dadSThomas Faber         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_4bps_bgra, res) }, /* YRESOLUTION */
339*3e9c4dadSThomas Faber         { 0x11c, IFD_SHORT, 1, 1 }, /* PLANARCONFIGURATION */
340*3e9c4dadSThomas Faber         { 0x128, IFD_SHORT, 1, 2 } /* RESOLUTIONUNIT */
341*3e9c4dadSThomas Faber     },
342*3e9c4dadSThomas Faber     0,
343*3e9c4dadSThomas Faber     { 96, 1 },
344*3e9c4dadSThomas Faber     { 0x12,0x30, 0x47,0xe0 }
345*3e9c4dadSThomas Faber };
346c2c66affSColin Finck #include "poppack.h"
347c2c66affSColin Finck 
348c2c66affSColin Finck static IWICImagingFactory *factory;
349c2c66affSColin Finck 
create_stream(const void * data,int data_size)350c2c66affSColin Finck static IStream *create_stream(const void *data, int data_size)
351c2c66affSColin Finck {
352c2c66affSColin Finck     HRESULT hr;
353c2c66affSColin Finck     IStream *stream;
354c2c66affSColin Finck     HGLOBAL hdata;
355c2c66affSColin Finck     void *locked_data;
356c2c66affSColin Finck 
357c2c66affSColin Finck     hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
358c2c66affSColin Finck     ok(hdata != 0, "GlobalAlloc failed\n");
359c2c66affSColin Finck     if (!hdata) return NULL;
360c2c66affSColin Finck 
361c2c66affSColin Finck     locked_data = GlobalLock(hdata);
362c2c66affSColin Finck     memcpy(locked_data, data, data_size);
363c2c66affSColin Finck     GlobalUnlock(hdata);
364c2c66affSColin Finck 
365c2c66affSColin Finck     hr = CreateStreamOnHGlobal(hdata, TRUE, &stream);
366c2c66affSColin Finck     ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
367c2c66affSColin Finck 
368c2c66affSColin Finck     return stream;
369c2c66affSColin Finck }
370c2c66affSColin Finck 
create_decoder(const void * image_data,UINT image_size,IWICBitmapDecoder ** decoder)37123ec1e5eSAmine Khaldi static HRESULT create_decoder(const void *image_data, UINT image_size, IWICBitmapDecoder **decoder)
372c2c66affSColin Finck {
37323ec1e5eSAmine Khaldi     HGLOBAL hmem;
37423ec1e5eSAmine Khaldi     BYTE *data;
375c2c66affSColin Finck     HRESULT hr;
376c2c66affSColin Finck     IStream *stream;
37723ec1e5eSAmine Khaldi     GUID format;
37823ec1e5eSAmine Khaldi     LONG refcount;
379c2c66affSColin Finck 
38023ec1e5eSAmine Khaldi     *decoder = NULL;
381c2c66affSColin Finck 
38223ec1e5eSAmine Khaldi     hmem = GlobalAlloc(0, image_size);
38323ec1e5eSAmine Khaldi     data = GlobalLock(hmem);
38423ec1e5eSAmine Khaldi     memcpy(data, image_data, image_size);
38523ec1e5eSAmine Khaldi     GlobalUnlock(hmem);
386c2c66affSColin Finck 
38723ec1e5eSAmine Khaldi     hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
38823ec1e5eSAmine Khaldi     ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr);
38923ec1e5eSAmine Khaldi 
39023ec1e5eSAmine Khaldi     hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, decoder);
39123ec1e5eSAmine Khaldi     if (hr == S_OK)
39223ec1e5eSAmine Khaldi     {
39323ec1e5eSAmine Khaldi         hr = IWICBitmapDecoder_GetContainerFormat(*decoder, &format);
394c2c66affSColin Finck         ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
39523ec1e5eSAmine Khaldi         ok(IsEqualGUID(&format, &GUID_ContainerFormatTiff),
39623ec1e5eSAmine Khaldi            "wrong container format %s\n", wine_dbgstr_guid(&format));
397c2c66affSColin Finck 
39823ec1e5eSAmine Khaldi         refcount = IStream_Release(stream);
39923ec1e5eSAmine Khaldi         ok(refcount > 0, "expected stream refcount > 0\n");
400c2c66affSColin Finck     }
401c2c66affSColin Finck 
40223ec1e5eSAmine Khaldi     return hr;
40323ec1e5eSAmine Khaldi }
40423ec1e5eSAmine Khaldi 
get_pixelformat_info(const GUID * format,UINT * bpp,UINT * channels,BOOL * trasparency)40523ec1e5eSAmine Khaldi static HRESULT get_pixelformat_info(const GUID *format, UINT *bpp, UINT *channels, BOOL *trasparency)
40623ec1e5eSAmine Khaldi {
40723ec1e5eSAmine Khaldi     HRESULT hr;
40823ec1e5eSAmine Khaldi     IWICComponentInfo *info;
40923ec1e5eSAmine Khaldi     IWICPixelFormatInfo2 *formatinfo;
41023ec1e5eSAmine Khaldi 
41123ec1e5eSAmine Khaldi     hr = IWICImagingFactory_CreateComponentInfo(factory, format, &info);
41223ec1e5eSAmine Khaldi     ok(hr == S_OK, "CreateComponentInfo(%s) error %#x\n", wine_dbgstr_guid(format), hr);
41323ec1e5eSAmine Khaldi     if (hr == S_OK)
41423ec1e5eSAmine Khaldi     {
41523ec1e5eSAmine Khaldi         hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo2, (void **)&formatinfo);
41623ec1e5eSAmine Khaldi         if (hr == S_OK)
41723ec1e5eSAmine Khaldi         {
41823ec1e5eSAmine Khaldi             hr = IWICPixelFormatInfo2_SupportsTransparency(formatinfo, trasparency);
41923ec1e5eSAmine Khaldi             ok(hr == S_OK, "SupportsTransparency error %#x\n", hr);
42023ec1e5eSAmine Khaldi             IWICPixelFormatInfo2_Release(formatinfo);
42123ec1e5eSAmine Khaldi         }
42223ec1e5eSAmine Khaldi         hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo, (void **)&formatinfo);
42323ec1e5eSAmine Khaldi         if (hr == S_OK)
42423ec1e5eSAmine Khaldi         {
42523ec1e5eSAmine Khaldi             hr = IWICPixelFormatInfo2_GetBitsPerPixel(formatinfo, bpp);
42623ec1e5eSAmine Khaldi             ok(hr == S_OK, "GetBitsPerPixel error %#x\n", hr);
42723ec1e5eSAmine Khaldi             hr = IWICPixelFormatInfo2_GetChannelCount(formatinfo, channels);
42823ec1e5eSAmine Khaldi             ok(hr == S_OK, "GetChannelCount error %#x\n", hr);
42923ec1e5eSAmine Khaldi             IWICPixelFormatInfo2_Release(formatinfo);
43023ec1e5eSAmine Khaldi         }
43123ec1e5eSAmine Khaldi         IWICComponentInfo_Release(info);
43223ec1e5eSAmine Khaldi     }
43323ec1e5eSAmine Khaldi     return hr;
43423ec1e5eSAmine Khaldi }
43523ec1e5eSAmine Khaldi 
dump_tiff(void * buf)43623ec1e5eSAmine Khaldi static void dump_tiff(void *buf)
43723ec1e5eSAmine Khaldi {
43823ec1e5eSAmine Khaldi     UINT count, i;
43923ec1e5eSAmine Khaldi     struct tiff_1bpp_data *tiff;
44023ec1e5eSAmine Khaldi     struct IFD_entry *tag;
44123ec1e5eSAmine Khaldi 
44223ec1e5eSAmine Khaldi     tiff = buf;
44323ec1e5eSAmine Khaldi     count = *(short *)((char *)tiff + tiff->dir_offset);
44423ec1e5eSAmine Khaldi     tag = (struct IFD_entry *)((char *)tiff + tiff->dir_offset + sizeof(short));
44523ec1e5eSAmine Khaldi 
44623ec1e5eSAmine Khaldi     for (i = 0; i < count; i++)
44723ec1e5eSAmine Khaldi     {
44823ec1e5eSAmine Khaldi         printf("tag %u: id %04x, type %04x, count %u, value %d",
44923ec1e5eSAmine Khaldi                 i, tag[i].id, tag[i].type, tag[i].count, tag[i].value);
45023ec1e5eSAmine Khaldi         if (tag[i].id == 0x102 && tag[i].count > 2)
45123ec1e5eSAmine Khaldi         {
45223ec1e5eSAmine Khaldi             short *bps = (short *)((char *)tiff + tag[i].value);
45323ec1e5eSAmine Khaldi             printf(" (%d,%d,%d,%d)\n", bps[0], bps[1], bps[2], bps[3]);
45423ec1e5eSAmine Khaldi         }
45523ec1e5eSAmine Khaldi         else
45623ec1e5eSAmine Khaldi             printf("\n");
45723ec1e5eSAmine Khaldi     }
45823ec1e5eSAmine Khaldi }
45923ec1e5eSAmine Khaldi 
test_tiff_1bpp_palette(void)46023ec1e5eSAmine Khaldi static void test_tiff_1bpp_palette(void)
461c2c66affSColin Finck {
462c2c66affSColin Finck     HRESULT hr;
463c2c66affSColin Finck     IWICBitmapDecoder *decoder;
464c2c66affSColin Finck     IWICBitmapFrameDecode *frame;
465c2c66affSColin Finck     IWICPalette *palette;
466c2c66affSColin Finck     GUID format;
467c2c66affSColin Finck 
46823ec1e5eSAmine Khaldi     hr = create_decoder(&tiff_1bpp_data, sizeof(tiff_1bpp_data), &decoder);
46923ec1e5eSAmine Khaldi     ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
47023ec1e5eSAmine Khaldi     if (hr != S_OK) return;
471c2c66affSColin Finck 
472c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
473c2c66affSColin Finck     ok(hr == S_OK, "GetFrame error %#x\n", hr);
474c2c66affSColin Finck 
475c2c66affSColin Finck     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
476c2c66affSColin Finck     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
477c2c66affSColin Finck     ok(IsEqualGUID(&format, &GUID_WICPixelFormatBlackWhite),
478c2c66affSColin Finck        "got wrong format %s\n", wine_dbgstr_guid(&format));
479c2c66affSColin Finck 
480c2c66affSColin Finck     hr = IWICImagingFactory_CreatePalette(factory, &palette);
481c2c66affSColin Finck     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
482c2c66affSColin Finck     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
483c2c66affSColin Finck     ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE,
484c2c66affSColin Finck        "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %#x\n", hr);
485c2c66affSColin Finck 
486c2c66affSColin Finck     IWICPalette_Release(palette);
487c2c66affSColin Finck     IWICBitmapFrameDecode_Release(frame);
488c2c66affSColin Finck     IWICBitmapDecoder_Release(decoder);
489c2c66affSColin Finck }
490c2c66affSColin Finck 
test_QueryCapability(void)491c2c66affSColin Finck static void test_QueryCapability(void)
492c2c66affSColin Finck {
493c2c66affSColin Finck     HRESULT hr;
494c2c66affSColin Finck     IStream *stream;
495c2c66affSColin Finck     IWICBitmapDecoder *decoder;
496c2c66affSColin Finck     IWICBitmapFrameDecode *frame;
497c2c66affSColin Finck     static const DWORD exp_caps = WICBitmapDecoderCapabilityCanDecodeAllImages |
498c2c66affSColin Finck                                   WICBitmapDecoderCapabilityCanDecodeSomeImages |
499c2c66affSColin Finck                                   WICBitmapDecoderCapabilityCanEnumerateMetadata;
500c2c66affSColin Finck     static const DWORD exp_caps_xp = WICBitmapDecoderCapabilityCanDecodeAllImages |
501c2c66affSColin Finck                                      WICBitmapDecoderCapabilityCanDecodeSomeImages;
502c2c66affSColin Finck     DWORD capability;
503c2c66affSColin Finck     LARGE_INTEGER pos;
504c2c66affSColin Finck     ULARGE_INTEGER cur_pos;
505c2c66affSColin Finck     UINT frame_count;
506c2c66affSColin Finck 
507c2c66affSColin Finck     stream = create_stream(&tiff_1bpp_data, sizeof(tiff_1bpp_data));
508c2c66affSColin Finck     if (!stream) return;
509c2c66affSColin Finck 
510c2c66affSColin Finck     hr = IWICImagingFactory_CreateDecoder(factory, &GUID_ContainerFormatTiff, NULL, &decoder);
511c2c66affSColin Finck     ok(hr == S_OK, "CreateDecoder error %#x\n", hr);
512c2c66affSColin Finck     if (FAILED(hr)) return;
513c2c66affSColin Finck 
514c2c66affSColin Finck     frame_count = 0xdeadbeef;
515c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
516c2c66affSColin Finck     ok(hr == S_OK || broken(hr == E_POINTER) /* XP */, "GetFrameCount error %#x\n", hr);
517c2c66affSColin Finck     ok(frame_count == 0, "expected 0, got %u\n", frame_count);
518c2c66affSColin Finck 
519c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
520c2c66affSColin Finck     ok(hr == WINCODEC_ERR_FRAMEMISSING || broken(hr == E_POINTER) /* XP */, "expected WINCODEC_ERR_FRAMEMISSING, got %#x\n", hr);
521c2c66affSColin Finck 
522c2c66affSColin Finck     pos.QuadPart = 4;
523c2c66affSColin Finck     hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
524c2c66affSColin Finck     ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
525c2c66affSColin Finck 
526c2c66affSColin Finck     capability = 0xdeadbeef;
527c2c66affSColin Finck     hr = IWICBitmapDecoder_QueryCapability(decoder, stream, &capability);
528c2c66affSColin Finck     ok(hr == S_OK, "QueryCapability error %#x\n", hr);
529c2c66affSColin Finck     ok(capability == exp_caps || capability == exp_caps_xp,
530c2c66affSColin Finck        "expected %#x, got %#x\n", exp_caps, capability);
531c2c66affSColin Finck 
532c2c66affSColin Finck     frame_count = 0xdeadbeef;
533c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
534c2c66affSColin Finck     ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
535c2c66affSColin Finck     ok(frame_count == 1, "expected 1, got %u\n", frame_count);
536c2c66affSColin Finck 
537c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
538c2c66affSColin Finck     ok(hr == S_OK, "GetFrame error %#x\n", hr);
539c2c66affSColin Finck     IWICBitmapFrameDecode_Release(frame);
540c2c66affSColin Finck 
541c2c66affSColin Finck     pos.QuadPart = 0;
542c2c66affSColin Finck     hr = IStream_Seek(stream, pos, SEEK_CUR, &cur_pos);
543c2c66affSColin Finck     ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
544c2c66affSColin Finck     ok(cur_pos.QuadPart > 4 && cur_pos.QuadPart < sizeof(tiff_1bpp_data),
545c2c66affSColin Finck        "current stream pos is at %x/%x\n", cur_pos.u.LowPart, cur_pos.u.HighPart);
546c2c66affSColin Finck 
547c2c66affSColin Finck     hr = IWICBitmapDecoder_QueryCapability(decoder, stream, &capability);
548c2c66affSColin Finck     ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
549c2c66affSColin Finck 
550c2c66affSColin Finck     hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
551c2c66affSColin Finck     ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
552c2c66affSColin Finck 
553c2c66affSColin Finck     IWICBitmapDecoder_Release(decoder);
554c2c66affSColin Finck 
555c2c66affSColin Finck     hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
556c2c66affSColin Finck todo_wine
557c2c66affSColin Finck     ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "expected WINCODEC_ERR_COMPONENTNOTFOUND, got %#x\n", hr);
558c2c66affSColin Finck 
559c2c66affSColin Finck     if (SUCCEEDED(hr))
560c2c66affSColin Finck         IWICBitmapDecoder_Release(decoder);
561c2c66affSColin Finck 
562c2c66affSColin Finck     pos.QuadPart = 0;
563c2c66affSColin Finck     hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
564c2c66affSColin Finck     ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
565c2c66affSColin Finck 
566c2c66affSColin Finck     hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
567c2c66affSColin Finck     ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
568c2c66affSColin Finck 
569c2c66affSColin Finck     frame_count = 0xdeadbeef;
570c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
571c2c66affSColin Finck     ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
572c2c66affSColin Finck     ok(frame_count == 1, "expected 1, got %u\n", frame_count);
573c2c66affSColin Finck 
574c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
575c2c66affSColin Finck     ok(hr == S_OK, "GetFrame error %#x\n", hr);
576c2c66affSColin Finck     IWICBitmapFrameDecode_Release(frame);
577c2c66affSColin Finck 
578c2c66affSColin Finck     hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
579c2c66affSColin Finck     ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
580c2c66affSColin Finck 
581c2c66affSColin Finck     hr = IWICBitmapDecoder_QueryCapability(decoder, stream, &capability);
582c2c66affSColin Finck     ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
583c2c66affSColin Finck 
584c2c66affSColin Finck     IWICBitmapDecoder_Release(decoder);
585c2c66affSColin Finck     IStream_Release(stream);
586c2c66affSColin Finck }
587c2c66affSColin Finck 
test_tiff_8bpp_alpha(void)588c2c66affSColin Finck static void test_tiff_8bpp_alpha(void)
589c2c66affSColin Finck {
590c2c66affSColin Finck     HRESULT hr;
591c2c66affSColin Finck     IWICBitmapDecoder *decoder;
592c2c66affSColin Finck     IWICBitmapFrameDecode *frame;
593c2c66affSColin Finck     UINT frame_count, width, height, i;
594c2c66affSColin Finck     double dpi_x, dpi_y;
595c2c66affSColin Finck     IWICPalette *palette;
596c2c66affSColin Finck     GUID format;
597c2c66affSColin Finck     WICRect rc;
598c2c66affSColin Finck     BYTE data[16];
599c2c66affSColin Finck     static const BYTE expected_data[16] = { 0x11,0x11,0x11,0x22,0x33,0x33,0x33,0x44,
600c2c66affSColin Finck                                             0x55,0x55,0x55,0x66,0x77,0x77,0x77,0x88 };
601c2c66affSColin Finck 
60223ec1e5eSAmine Khaldi     hr = create_decoder(&tiff_8bpp_alpha, sizeof(tiff_8bpp_alpha), &decoder);
60323ec1e5eSAmine Khaldi     ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
60423ec1e5eSAmine Khaldi     if (hr != S_OK) return;
605c2c66affSColin Finck 
606c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
607c2c66affSColin Finck     ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
608c2c66affSColin Finck     ok(frame_count == 1, "expected 1, got %u\n", frame_count);
609c2c66affSColin Finck 
610eea81f52SAmine Khaldi     EXPECT_REF(decoder, 1);
611c2c66affSColin Finck     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
612c2c66affSColin Finck     ok(hr == S_OK, "GetFrame error %#x\n", hr);
613eea81f52SAmine Khaldi     EXPECT_REF(decoder, 2);
614eea81f52SAmine Khaldi     IWICBitmapDecoder_Release(decoder);
615c2c66affSColin Finck 
616c2c66affSColin Finck     hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
617c2c66affSColin Finck     ok(hr == S_OK, "GetSize error %#x\n", hr);
618c2c66affSColin Finck     ok(width == 2, "expected 2, got %u\n", width);
619c2c66affSColin Finck     ok(height == 2, "expected 2, got %u\n", height);
620c2c66affSColin Finck 
621c2c66affSColin Finck     hr = IWICBitmapFrameDecode_GetResolution(frame, &dpi_x, &dpi_y);
622c2c66affSColin Finck     ok(hr == S_OK, "GetResolution error %#x\n", hr);
623c2c66affSColin Finck     ok(dpi_x == 96.0, "expected 96.0, got %f\n", dpi_x);
624c2c66affSColin Finck     ok(dpi_y == 96.0, "expected 96.0, got %f\n", dpi_y);
625c2c66affSColin Finck 
626c2c66affSColin Finck     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
627c2c66affSColin Finck     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
628c2c66affSColin Finck     ok(IsEqualGUID(&format, &GUID_WICPixelFormat32bppPBGRA),
629c2c66affSColin Finck        "got wrong format %s\n", wine_dbgstr_guid(&format));
630c2c66affSColin Finck 
631c2c66affSColin Finck     hr = IWICImagingFactory_CreatePalette(factory, &palette);
632c2c66affSColin Finck     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
633c2c66affSColin Finck     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
634c2c66affSColin Finck     ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE,
635c2c66affSColin Finck        "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %#x\n", hr);
636c2c66affSColin Finck     IWICPalette_Release(palette);
637c2c66affSColin Finck 
638c2c66affSColin Finck     rc.X = 0;
639c2c66affSColin Finck     rc.Y = 0;
640c2c66affSColin Finck     rc.Width = 2;
641c2c66affSColin Finck     rc.Height = 2;
642c2c66affSColin Finck     hr = IWICBitmapFrameDecode_CopyPixels(frame, &rc, 8, sizeof(data), data);
643c2c66affSColin Finck     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
644c2c66affSColin Finck 
645c2c66affSColin Finck     for (i = 0; i < sizeof(data); i++)
646c2c66affSColin Finck         ok(data[i] == expected_data[i], "%u: expected %02x, got %02x\n", i, expected_data[i], data[i]);
647c2c66affSColin Finck 
648c2c66affSColin Finck     IWICBitmapFrameDecode_Release(frame);
649c2c66affSColin Finck }
650c2c66affSColin Finck 
generate_tiff_palette(void * buf,unsigned count)65123ec1e5eSAmine Khaldi static void generate_tiff_palette(void *buf, unsigned count)
65223ec1e5eSAmine Khaldi {
65323ec1e5eSAmine Khaldi     unsigned short *r, *g, *b;
65423ec1e5eSAmine Khaldi     unsigned i;
65523ec1e5eSAmine Khaldi 
65623ec1e5eSAmine Khaldi     r = buf;
65723ec1e5eSAmine Khaldi     g = r + count;
65823ec1e5eSAmine Khaldi     b = g + count;
65923ec1e5eSAmine Khaldi 
66023ec1e5eSAmine Khaldi     r[0] = 0x11 * 257;
66123ec1e5eSAmine Khaldi     g[0] = 0x22 * 257;
66223ec1e5eSAmine Khaldi     b[0] = 0x33 * 257;
66323ec1e5eSAmine Khaldi     r[1] = 0x44 * 257;
66423ec1e5eSAmine Khaldi     g[1] = 0x55 * 257;
66523ec1e5eSAmine Khaldi     b[1] = 0x66 * 257;
66623ec1e5eSAmine Khaldi     r[2] = 0x77 * 257;
66723ec1e5eSAmine Khaldi     g[2] = 0x88 * 257;
66823ec1e5eSAmine Khaldi     b[2] = 0x99 * 257;
66923ec1e5eSAmine Khaldi     r[3] = 0xa1 * 257;
67023ec1e5eSAmine Khaldi     g[3] = 0xb5 * 257;
67123ec1e5eSAmine Khaldi     b[3] = 0xff * 257;
67223ec1e5eSAmine Khaldi 
67323ec1e5eSAmine Khaldi     for (i = 4; i < count; i++)
67423ec1e5eSAmine Khaldi     {
67523ec1e5eSAmine Khaldi         r[i] = i * 257;
67623ec1e5eSAmine Khaldi         g[i] = (i | 0x40) * 257;
67723ec1e5eSAmine Khaldi         b[i] = (i | 0x80) * 257;
67823ec1e5eSAmine Khaldi     }
67923ec1e5eSAmine Khaldi }
68023ec1e5eSAmine Khaldi 
test_tiff_8bpp_palette(void)68123ec1e5eSAmine Khaldi static void test_tiff_8bpp_palette(void)
68223ec1e5eSAmine Khaldi {
68323ec1e5eSAmine Khaldi     char buf[sizeof(tiff_8bpp_data)];
68423ec1e5eSAmine Khaldi     HRESULT hr;
68523ec1e5eSAmine Khaldi     IWICBitmapDecoder *decoder;
68623ec1e5eSAmine Khaldi     IWICBitmapFrameDecode *frame;
68723ec1e5eSAmine Khaldi     IWICPalette *palette;
68823ec1e5eSAmine Khaldi     GUID format;
68923ec1e5eSAmine Khaldi     UINT count, ret;
69023ec1e5eSAmine Khaldi     WICColor color[256];
69123ec1e5eSAmine Khaldi 
69223ec1e5eSAmine Khaldi     memcpy(buf, &tiff_8bpp_data, sizeof(tiff_8bpp_data));
69323ec1e5eSAmine Khaldi     generate_tiff_palette(buf + FIELD_OFFSET(struct tiff_8bpp_data, palette_data), 256);
69423ec1e5eSAmine Khaldi 
69523ec1e5eSAmine Khaldi     hr = create_decoder(buf, sizeof(buf), &decoder);
69623ec1e5eSAmine Khaldi     ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
69723ec1e5eSAmine Khaldi     if (hr != S_OK) return;
69823ec1e5eSAmine Khaldi 
69923ec1e5eSAmine Khaldi     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
70023ec1e5eSAmine Khaldi     ok(hr == S_OK, "GetFrame error %#x\n", hr);
70123ec1e5eSAmine Khaldi 
70223ec1e5eSAmine Khaldi     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
70323ec1e5eSAmine Khaldi     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
70423ec1e5eSAmine Khaldi     ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed),
70523ec1e5eSAmine Khaldi        "expected GUID_WICPixelFormat8bppIndexed, got %s\n", wine_dbgstr_guid(&format));
70623ec1e5eSAmine Khaldi 
70723ec1e5eSAmine Khaldi     hr = IWICImagingFactory_CreatePalette(factory, &palette);
70823ec1e5eSAmine Khaldi     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
70923ec1e5eSAmine Khaldi     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
71023ec1e5eSAmine Khaldi     ok(hr == S_OK, "CopyPalette error %#x\n", hr);
71123ec1e5eSAmine Khaldi 
71223ec1e5eSAmine Khaldi     hr = IWICPalette_GetColorCount(palette, &count);
71323ec1e5eSAmine Khaldi     ok(hr == S_OK, "GetColorCount error %#x\n", hr);
71423ec1e5eSAmine Khaldi     ok(count == 256, "expected 256, got %u\n", count);
71523ec1e5eSAmine Khaldi 
71623ec1e5eSAmine Khaldi     hr = IWICPalette_GetColors(palette, 256, color, &ret);
71723ec1e5eSAmine Khaldi     ok(hr == S_OK, "GetColors error %#x\n", hr);
71823ec1e5eSAmine Khaldi     ok(ret == count, "expected %u, got %u\n", count, ret);
71923ec1e5eSAmine Khaldi     ok(color[0] == 0xff112233, "got %#x\n", color[0]);
72023ec1e5eSAmine Khaldi     ok(color[1] == 0xff445566, "got %#x\n", color[1]);
72123ec1e5eSAmine Khaldi     ok(color[2] == 0xff778899, "got %#x\n", color[2]);
72223ec1e5eSAmine Khaldi     ok(color[3] == 0xffa1b5ff, "got %#x\n", color[3]);
72323ec1e5eSAmine Khaldi 
72423ec1e5eSAmine Khaldi     IWICPalette_Release(palette);
72523ec1e5eSAmine Khaldi     IWICBitmapFrameDecode_Release(frame);
72623ec1e5eSAmine Khaldi     IWICBitmapDecoder_Release(decoder);
72723ec1e5eSAmine Khaldi }
72823ec1e5eSAmine Khaldi 
test_tiff_resolution(void)72923ec1e5eSAmine Khaldi static void test_tiff_resolution(void)
73023ec1e5eSAmine Khaldi {
73123ec1e5eSAmine Khaldi     HRESULT hr;
73223ec1e5eSAmine Khaldi     IWICBitmapDecoder *decoder;
73323ec1e5eSAmine Khaldi     IWICBitmapFrameDecode *frame;
73423ec1e5eSAmine Khaldi     double dpi_x, dpi_y;
73523ec1e5eSAmine Khaldi     int i;
73623ec1e5eSAmine Khaldi 
737eea81f52SAmine Khaldi     for (i = 0; i < ARRAY_SIZE(tiff_resolution_test_data); i++)
73823ec1e5eSAmine Khaldi     {
73923ec1e5eSAmine Khaldi         const struct tiff_resolution_test_data *test_data = &tiff_resolution_test_data[i];
74023ec1e5eSAmine Khaldi         tiff_resolution_image_data.resx = test_data->resx;
74123ec1e5eSAmine Khaldi         tiff_resolution_image_data.resy = test_data->resy;
74223ec1e5eSAmine Khaldi         tiff_resolution_image_data.entry[12].value = test_data->resolution_unit;
74323ec1e5eSAmine Khaldi 
74423ec1e5eSAmine Khaldi         hr = create_decoder(&tiff_resolution_image_data, sizeof(tiff_resolution_image_data), &decoder);
74523ec1e5eSAmine Khaldi         ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
74623ec1e5eSAmine Khaldi         if (hr != S_OK) return;
74723ec1e5eSAmine Khaldi 
74823ec1e5eSAmine Khaldi         hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
74923ec1e5eSAmine Khaldi         ok(hr == S_OK, "%d: GetFrame error %#x\n", i, hr);
75023ec1e5eSAmine Khaldi 
75123ec1e5eSAmine Khaldi         hr = IWICBitmapFrameDecode_GetResolution(frame, &dpi_x, &dpi_y);
75223ec1e5eSAmine Khaldi         ok(hr == S_OK, "%d: GetResolution error %#x\n", i, hr);
75323ec1e5eSAmine Khaldi 
75423ec1e5eSAmine Khaldi         if (test_data->broken_dpi_x != 0)
75523ec1e5eSAmine Khaldi         {
75623ec1e5eSAmine Khaldi             ok(fabs(dpi_x - test_data->expected_dpi_x) < 0.01 || broken(fabs(dpi_x - test_data->broken_dpi_x) < 0.01),
75723ec1e5eSAmine Khaldi                 "%d: x: expected %f or %f, got %f\n", i, test_data->expected_dpi_x, test_data->broken_dpi_x, dpi_x);
75823ec1e5eSAmine Khaldi         }
75923ec1e5eSAmine Khaldi         else
76023ec1e5eSAmine Khaldi         {
76123ec1e5eSAmine Khaldi             ok(fabs(dpi_x - test_data->expected_dpi_x) < 0.01,
76223ec1e5eSAmine Khaldi                 "%d: x: expected %f, got %f\n", i, test_data->expected_dpi_x, dpi_x);
76323ec1e5eSAmine Khaldi         }
76423ec1e5eSAmine Khaldi 
76523ec1e5eSAmine Khaldi         if (test_data->broken_dpi_y != 0)
76623ec1e5eSAmine Khaldi         {
76723ec1e5eSAmine Khaldi             ok(fabs(dpi_y - test_data->expected_dpi_y) < 0.01 || broken(fabs(dpi_y - test_data->broken_dpi_y) < 0.01),
76823ec1e5eSAmine Khaldi                 "%d: y: expected %f or %f, got %f\n", i, test_data->expected_dpi_y, test_data->broken_dpi_y, dpi_y);
76923ec1e5eSAmine Khaldi         }
77023ec1e5eSAmine Khaldi         else
77123ec1e5eSAmine Khaldi         {
77223ec1e5eSAmine Khaldi             ok(fabs(dpi_y - test_data->expected_dpi_y) < 0.01,
77323ec1e5eSAmine Khaldi                 "%d: y: expected %f, got %f\n", i, test_data->expected_dpi_y, dpi_y);
77423ec1e5eSAmine Khaldi         }
77523ec1e5eSAmine Khaldi 
77623ec1e5eSAmine Khaldi         IWICBitmapFrameDecode_Release(frame);
77723ec1e5eSAmine Khaldi         IWICBitmapDecoder_Release(decoder);
77823ec1e5eSAmine Khaldi     }
77923ec1e5eSAmine Khaldi }
78023ec1e5eSAmine Khaldi 
test_tiff_24bpp(void)781eea81f52SAmine Khaldi static void test_tiff_24bpp(void)
782eea81f52SAmine Khaldi {
783eea81f52SAmine Khaldi     HRESULT hr;
784eea81f52SAmine Khaldi     IWICBitmapDecoder *decoder;
785eea81f52SAmine Khaldi     IWICBitmapFrameDecode *frame;
786eea81f52SAmine Khaldi     UINT count, width, height, i, stride;
787eea81f52SAmine Khaldi     double dpi_x, dpi_y;
788eea81f52SAmine Khaldi     GUID format;
789eea81f52SAmine Khaldi     WICRect rc;
790eea81f52SAmine Khaldi     BYTE data[3];
791eea81f52SAmine Khaldi     static const BYTE expected_data[] = { 0x33,0x22,0x11 };
792eea81f52SAmine Khaldi 
793eea81f52SAmine Khaldi     hr = create_decoder(&tiff_24bpp_data, sizeof(tiff_24bpp_data), &decoder);
794cc48f9d4SAmine Khaldi     ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
795cc48f9d4SAmine Khaldi     if (hr != S_OK) return;
796eea81f52SAmine Khaldi     ok(decoder != NULL, "Failed to load TIFF image data\n");
797eea81f52SAmine Khaldi 
798eea81f52SAmine Khaldi     hr = IWICBitmapDecoder_GetFrameCount(decoder, &count);
799eea81f52SAmine Khaldi     ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
800eea81f52SAmine Khaldi     ok(count == 1, "got %u\n", count);
801eea81f52SAmine Khaldi 
802eea81f52SAmine Khaldi     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
803eea81f52SAmine Khaldi     ok(hr == S_OK, "GetFrame error %#x\n", hr);
804eea81f52SAmine Khaldi 
805eea81f52SAmine Khaldi     hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
806eea81f52SAmine Khaldi     ok(hr == S_OK, "GetSize error %#x\n", hr);
807eea81f52SAmine Khaldi     ok(width == 1, "got %u\n", width);
808eea81f52SAmine Khaldi     ok(height == 1, "got %u\n", height);
809eea81f52SAmine Khaldi 
810eea81f52SAmine Khaldi     hr = IWICBitmapFrameDecode_GetResolution(frame, &dpi_x, &dpi_y);
811eea81f52SAmine Khaldi     ok(hr == S_OK, "GetResolution error %#x\n", hr);
812eea81f52SAmine Khaldi     ok(dpi_x == 300.0, "got %f\n", dpi_x);
813eea81f52SAmine Khaldi     ok(dpi_y == 300.0, "got %f\n", dpi_y);
814eea81f52SAmine Khaldi 
815eea81f52SAmine Khaldi     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
816eea81f52SAmine Khaldi     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
817eea81f52SAmine Khaldi     ok(IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR),
818eea81f52SAmine Khaldi        "got wrong format %s\n", wine_dbgstr_guid(&format));
819eea81f52SAmine Khaldi 
820eea81f52SAmine Khaldi     for (stride = 0; stride <= 32; stride++)
821eea81f52SAmine Khaldi     {
822eea81f52SAmine Khaldi         memset(data, 0, sizeof(data));
823eea81f52SAmine Khaldi         rc.X = 0;
824eea81f52SAmine Khaldi         rc.Y = 0;
825eea81f52SAmine Khaldi         rc.Width = 1;
826eea81f52SAmine Khaldi         rc.Height = 1;
827eea81f52SAmine Khaldi         hr = IWICBitmapFrameDecode_CopyPixels(frame, &rc, stride, sizeof(data), data);
828eea81f52SAmine Khaldi         if (stride < 3)
829eea81f52SAmine Khaldi             ok(hr == E_INVALIDARG, "CopyPixels(%u) should fail: %#x\n", stride, hr);
830eea81f52SAmine Khaldi         else
831eea81f52SAmine Khaldi         {
832eea81f52SAmine Khaldi             ok(hr == S_OK, "CopyPixels(%u) error %#x\n", stride, hr);
833eea81f52SAmine Khaldi 
834eea81f52SAmine Khaldi             for (i = 0; i < sizeof(data); i++)
835eea81f52SAmine Khaldi                 ok(data[i] == expected_data[i], "%u: expected %02x, got %02x\n", i, expected_data[i], data[i]);
836eea81f52SAmine Khaldi         }
837eea81f52SAmine Khaldi     }
838eea81f52SAmine Khaldi 
839eea81f52SAmine Khaldi     IWICBitmapFrameDecode_Release(frame);
840eea81f52SAmine Khaldi     IWICBitmapDecoder_Release(decoder);
841eea81f52SAmine Khaldi }
842eea81f52SAmine Khaldi 
84323ec1e5eSAmine Khaldi #include "pshpack2.h"
84423ec1e5eSAmine Khaldi static const struct tiff_1x1_data
84523ec1e5eSAmine Khaldi {
84623ec1e5eSAmine Khaldi     USHORT byte_order;
84723ec1e5eSAmine Khaldi     USHORT version;
84823ec1e5eSAmine Khaldi     ULONG  dir_offset;
84923ec1e5eSAmine Khaldi     USHORT number_of_entries;
85023ec1e5eSAmine Khaldi     struct IFD_entry entry[12];
85123ec1e5eSAmine Khaldi     ULONG next_IFD;
85223ec1e5eSAmine Khaldi     struct IFD_rational res;
85323ec1e5eSAmine Khaldi     short palette_data[3][256];
85423ec1e5eSAmine Khaldi     short bps_data[4];
85523ec1e5eSAmine Khaldi     BYTE pixel_data[32];
85623ec1e5eSAmine Khaldi } tiff_1x1_data =
85723ec1e5eSAmine Khaldi {
85823ec1e5eSAmine Khaldi #ifdef WORDS_BIGENDIAN
85923ec1e5eSAmine Khaldi     'M' | 'M' << 8,
86023ec1e5eSAmine Khaldi #else
86123ec1e5eSAmine Khaldi     'I' | 'I' << 8,
86223ec1e5eSAmine Khaldi #endif
86323ec1e5eSAmine Khaldi     42,
86423ec1e5eSAmine Khaldi     FIELD_OFFSET(struct tiff_1x1_data, number_of_entries),
86523ec1e5eSAmine Khaldi     12,
86623ec1e5eSAmine Khaldi     {
86723ec1e5eSAmine Khaldi         { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
86823ec1e5eSAmine Khaldi         { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
86923ec1e5eSAmine Khaldi         { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
87023ec1e5eSAmine Khaldi         { 0x102, IFD_SHORT, 3, FIELD_OFFSET(struct tiff_1x1_data, bps_data) }, /* BITSPERSAMPLE */
87123ec1e5eSAmine Khaldi         { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
87223ec1e5eSAmine Khaldi         { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */
87323ec1e5eSAmine Khaldi         { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1x1_data, pixel_data) }, /* STRIPOFFSETS */
87423ec1e5eSAmine Khaldi         { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */
87523ec1e5eSAmine Khaldi         { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) },
87623ec1e5eSAmine Khaldi         { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) },
87723ec1e5eSAmine Khaldi         { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
87823ec1e5eSAmine Khaldi         { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_1x1_data, palette_data) } /* COLORMAP */
87923ec1e5eSAmine Khaldi     },
88023ec1e5eSAmine Khaldi     0,
88123ec1e5eSAmine Khaldi     { 96, 1 },
88223ec1e5eSAmine Khaldi     { { 0 } },
88323ec1e5eSAmine Khaldi     { 8,8,8,0 },
88423ec1e5eSAmine Khaldi     { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 }
88523ec1e5eSAmine Khaldi };
88623ec1e5eSAmine Khaldi #include "poppack.h"
88723ec1e5eSAmine Khaldi 
width_bytes(UINT width,UINT bpp)88823ec1e5eSAmine Khaldi static UINT width_bytes(UINT width, UINT bpp)
88923ec1e5eSAmine Khaldi {
89023ec1e5eSAmine Khaldi     return (width * bpp + 7) / 8;
89123ec1e5eSAmine Khaldi }
89223ec1e5eSAmine Khaldi 
test_color_formats(void)89323ec1e5eSAmine Khaldi static void test_color_formats(void)
89423ec1e5eSAmine Khaldi {
89523ec1e5eSAmine Khaldi     struct bitmap_data
89623ec1e5eSAmine Khaldi     {
89723ec1e5eSAmine Khaldi         UINT bpp;
89823ec1e5eSAmine Khaldi         UINT width;
89923ec1e5eSAmine Khaldi         UINT height;
90023ec1e5eSAmine Khaldi         const WICPixelFormatGUID *format;
90123ec1e5eSAmine Khaldi         const BYTE *bits;
90223ec1e5eSAmine Khaldi     };
90323ec1e5eSAmine Khaldi     static const BYTE bits_1bpsBGR[] = { 0,255,0,255,0,255,255,255,0,0,0,255,255,0,0,0,255,255,255,255,255,0,0,0,0,255,0,255,0,255 };
90423ec1e5eSAmine Khaldi     static const struct bitmap_data data_1bpsBGR =
90523ec1e5eSAmine Khaldi     {
90623ec1e5eSAmine Khaldi         24, 10, 2, &GUID_WICPixelFormat24bppBGR, bits_1bpsBGR
90723ec1e5eSAmine Khaldi     };
90823ec1e5eSAmine Khaldi     static const BYTE bits_4bpsBGR[] = { 204,85,85,136,187,51,0,85,85,85,0,68,0,102,0,136,0,119,0,153,0 };
90923ec1e5eSAmine Khaldi     static const struct bitmap_data data_4bpsBGR =
91023ec1e5eSAmine Khaldi     {
91123ec1e5eSAmine Khaldi         24, 5, 2, &GUID_WICPixelFormat24bppBGR, bits_4bpsBGR
91223ec1e5eSAmine Khaldi     };
91323ec1e5eSAmine Khaldi     static const BYTE bits_8bpsBGR[] = { 2,0,1,5,4,3,8,7,6 };
91423ec1e5eSAmine Khaldi     static const struct bitmap_data data_8bpsBGR =
91523ec1e5eSAmine Khaldi     {
91623ec1e5eSAmine Khaldi         24, 3, 1, &GUID_WICPixelFormat24bppBGR, bits_8bpsBGR
91723ec1e5eSAmine Khaldi     };
91823ec1e5eSAmine Khaldi     static const BYTE bits_48bppRGB[] = { 1,0,2,3,4,5,6,7,8,9,0,1 };
91923ec1e5eSAmine Khaldi     static const struct bitmap_data data_48bppRGB =
92023ec1e5eSAmine Khaldi     {
92123ec1e5eSAmine Khaldi         48, 2, 1, &GUID_WICPixelFormat48bppRGB, bits_48bppRGB
92223ec1e5eSAmine Khaldi     };
92323ec1e5eSAmine Khaldi     static const BYTE bits_1bpsBGRA[] = { 0,255,0,255,0,255,0,255,0,255,255,0,255,0,0,255,255,0,255,255,0,0,255,0,0,255,0,255,0,255,0,255,0,0,0,0,0,255,0,0 };
92423ec1e5eSAmine Khaldi     static const struct bitmap_data data_1bpsBGRA =
92523ec1e5eSAmine Khaldi     {
92623ec1e5eSAmine Khaldi         32, 5, 2, &GUID_WICPixelFormat32bppBGRA, bits_1bpsBGRA
92723ec1e5eSAmine Khaldi     };
92823ec1e5eSAmine Khaldi     static const BYTE bits_4bpsBGRA[] = { 204,85,85,51,85,136,187,85,0,68,0,85,0,102,0,119,0,136,0,153,0,0,0,17,0,34,0,51 };
92923ec1e5eSAmine Khaldi     static const struct bitmap_data data_4bpsBGRA =
93023ec1e5eSAmine Khaldi     {
93123ec1e5eSAmine Khaldi         32, 5, 2, &GUID_WICPixelFormat32bppBGRA, bits_4bpsBGRA
93223ec1e5eSAmine Khaldi     };
93323ec1e5eSAmine Khaldi     static const BYTE bits_8bpsBGRA[] = { 2,0,1,3,6,5,4,7,0,9,8,1,4,3,2,5 };
93423ec1e5eSAmine Khaldi     static const struct bitmap_data data_8bpsBGRA =
93523ec1e5eSAmine Khaldi     {
93623ec1e5eSAmine Khaldi         32, 4, 1, &GUID_WICPixelFormat32bppBGRA, bits_8bpsBGRA
93723ec1e5eSAmine Khaldi     };
93823ec1e5eSAmine Khaldi     static const BYTE bits_64bppRGBA[] = { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 };
93923ec1e5eSAmine Khaldi     static const struct bitmap_data data_64bppRGBA =
94023ec1e5eSAmine Khaldi     {
94123ec1e5eSAmine Khaldi         64, 2, 1, &GUID_WICPixelFormat64bppRGBA, bits_64bppRGBA
94223ec1e5eSAmine Khaldi     };
94323ec1e5eSAmine Khaldi     static const BYTE bits_BlackWhite[] = { 85,195,184,85 };
94423ec1e5eSAmine Khaldi     static const struct bitmap_data data_BlackWhite =
94523ec1e5eSAmine Khaldi     {
94623ec1e5eSAmine Khaldi         1, 30, 1, &GUID_WICPixelFormatBlackWhite, bits_BlackWhite
94723ec1e5eSAmine Khaldi     };
94823ec1e5eSAmine Khaldi     static const BYTE bits_BlackWhite_xp[] = { 85,195,184,84 };
94923ec1e5eSAmine Khaldi     static const struct bitmap_data data_BlackWhite_xp =
95023ec1e5eSAmine Khaldi     {
95123ec1e5eSAmine Khaldi         1, 30, 1, &GUID_WICPixelFormatBlackWhite, bits_BlackWhite_xp
95223ec1e5eSAmine Khaldi     };
95323ec1e5eSAmine Khaldi     static const BYTE bits_4bppGray[] = { 85,195,184,85 };
95423ec1e5eSAmine Khaldi     static const struct bitmap_data data_4bppGray =
95523ec1e5eSAmine Khaldi     {
95623ec1e5eSAmine Khaldi         4, 7, 1, &GUID_WICPixelFormat4bppGray, bits_4bppGray
95723ec1e5eSAmine Khaldi     };
95823ec1e5eSAmine Khaldi     static const BYTE bits_4bppGray_xp[] = { 85,195,184,80 };
95923ec1e5eSAmine Khaldi     static const struct bitmap_data data_4bppGray_xp =
96023ec1e5eSAmine Khaldi     {
96123ec1e5eSAmine Khaldi         4, 7, 1, &GUID_WICPixelFormat4bppGray, bits_4bppGray_xp
96223ec1e5eSAmine Khaldi     };
96323ec1e5eSAmine Khaldi     static const BYTE bits_8bppGray[] = { 1,0,2,3,4,5,6,7,8,9 };
96423ec1e5eSAmine Khaldi     static const struct bitmap_data data_8bppGray =
96523ec1e5eSAmine Khaldi     {
96623ec1e5eSAmine Khaldi         8, 10, 1, &GUID_WICPixelFormat8bppGray, bits_8bppGray
96723ec1e5eSAmine Khaldi     };
96823ec1e5eSAmine Khaldi     static const BYTE bits_16bppGray[] = { 1,0,2,3,4,5 };
96923ec1e5eSAmine Khaldi     static const struct bitmap_data data_16bppGray =
97023ec1e5eSAmine Khaldi     {
97123ec1e5eSAmine Khaldi         16, 3, 1, &GUID_WICPixelFormat16bppGray, bits_16bppGray
97223ec1e5eSAmine Khaldi     };
97323ec1e5eSAmine Khaldi     static const BYTE bits_32bppGrayFloat[] = { 1,0,2,3,4,5,6,7,8,9,0,1 };
97423ec1e5eSAmine Khaldi     static const struct bitmap_data data_32bppGrayFloat =
97523ec1e5eSAmine Khaldi     {
97623ec1e5eSAmine Khaldi         32, 3, 1, &GUID_WICPixelFormat32bppGrayFloat, bits_32bppGrayFloat
97723ec1e5eSAmine Khaldi     };
97823ec1e5eSAmine Khaldi #if 0 /* FIXME */
97923ec1e5eSAmine Khaldi     static const BYTE bits_96bpp3Channels[] = { 0 };
98023ec1e5eSAmine Khaldi     static const struct bitmap_data data_96bpp3Channels =
98123ec1e5eSAmine Khaldi     {
98223ec1e5eSAmine Khaldi         64, 1, 1, &GUID_WICPixelFormat96bpp3Channels, bits_96bpp3Channels
98323ec1e5eSAmine Khaldi     };
98423ec1e5eSAmine Khaldi #endif
98523ec1e5eSAmine Khaldi     static const BYTE bits_128bppRGBAFloat[] = { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 };
98623ec1e5eSAmine Khaldi     static const struct bitmap_data data_128bppRGBAFloat =
98723ec1e5eSAmine Khaldi     {
98823ec1e5eSAmine Khaldi         128, 1, 1, &GUID_WICPixelFormat128bppRGBAFloat, bits_128bppRGBAFloat
98923ec1e5eSAmine Khaldi     };
99023ec1e5eSAmine Khaldi     static const BYTE bits_1bppIndexed[] = { 85,195,184,85 };
99123ec1e5eSAmine Khaldi     static const struct bitmap_data data_1bppIndexed =
99223ec1e5eSAmine Khaldi     {
99323ec1e5eSAmine Khaldi         1, 32, 1, &GUID_WICPixelFormat1bppIndexed, bits_1bppIndexed
99423ec1e5eSAmine Khaldi     };
99523ec1e5eSAmine Khaldi     static const BYTE bits_4bppIndexed[] = { 85,195,184,85 };
99623ec1e5eSAmine Khaldi     static const struct bitmap_data data_4bppIndexed =
99723ec1e5eSAmine Khaldi     {
99823ec1e5eSAmine Khaldi         4, 7, 1, &GUID_WICPixelFormat4bppIndexed, bits_4bppIndexed
99923ec1e5eSAmine Khaldi     };
100023ec1e5eSAmine Khaldi     static const BYTE bits_4bppIndexed_xp[] = { 85,195,184,80 };
100123ec1e5eSAmine Khaldi     static const struct bitmap_data data_4bppIndexed_xp =
100223ec1e5eSAmine Khaldi     {
100323ec1e5eSAmine Khaldi         4, 7, 1, &GUID_WICPixelFormat4bppIndexed, bits_4bppIndexed_xp
100423ec1e5eSAmine Khaldi     };
100523ec1e5eSAmine Khaldi     static const BYTE bits_8bppIndexed[] = { 1,0,2,3,4,5,6,7,8,9 };
100623ec1e5eSAmine Khaldi     static const struct bitmap_data data_8bppIndexed =
100723ec1e5eSAmine Khaldi     {
100823ec1e5eSAmine Khaldi         8, 3, 1, &GUID_WICPixelFormat8bppIndexed, bits_8bppIndexed
100923ec1e5eSAmine Khaldi     };
101023ec1e5eSAmine Khaldi     static const BYTE bits_32bppCMYK[] = { 1,0,2,3,4,5,6,7,8,9,0,1 };
101123ec1e5eSAmine Khaldi     static const struct bitmap_data data_32bppCMYK =
101223ec1e5eSAmine Khaldi     {
101323ec1e5eSAmine Khaldi         32, 3, 1, &GUID_WICPixelFormat32bppCMYK, bits_32bppCMYK
101423ec1e5eSAmine Khaldi     };
101523ec1e5eSAmine Khaldi     static const BYTE bits_64bppCMYK[] = { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 };
101623ec1e5eSAmine Khaldi     static const struct bitmap_data data_64bppCMYK =
101723ec1e5eSAmine Khaldi     {
101823ec1e5eSAmine Khaldi         64, 2, 1, &GUID_WICPixelFormat64bppCMYK, bits_64bppCMYK
101923ec1e5eSAmine Khaldi     };
102023ec1e5eSAmine Khaldi     static const struct
102123ec1e5eSAmine Khaldi     {
102223ec1e5eSAmine Khaldi         int photometric; /* PhotometricInterpretation */
102323ec1e5eSAmine Khaldi         int samples; /* SamplesPerPixel */
102423ec1e5eSAmine Khaldi         int bps; /* BitsPerSample */
102523ec1e5eSAmine Khaldi         const struct bitmap_data *data;
102623ec1e5eSAmine Khaldi         const struct bitmap_data *alt_data;
102723ec1e5eSAmine Khaldi     } td[] =
102823ec1e5eSAmine Khaldi     {
102923ec1e5eSAmine Khaldi         /* 2 - RGB */
103023ec1e5eSAmine Khaldi         { 2, 3, 1, &data_1bpsBGR },
103123ec1e5eSAmine Khaldi         { 2, 3, 4, &data_4bpsBGR },
103223ec1e5eSAmine Khaldi         { 2, 3, 8, &data_8bpsBGR },
103323ec1e5eSAmine Khaldi         { 2, 3, 16, &data_48bppRGB },
103423ec1e5eSAmine Khaldi         { 2, 3, 24, NULL },
103523ec1e5eSAmine Khaldi #if 0 /* FIXME */
103623ec1e5eSAmine Khaldi         { 2, 3, 32, &data_96bpp3Channels },
103723ec1e5eSAmine Khaldi #endif
103823ec1e5eSAmine Khaldi         { 2, 4, 1, &data_1bpsBGRA },
103923ec1e5eSAmine Khaldi         { 2, 4, 4, &data_4bpsBGRA },
104023ec1e5eSAmine Khaldi         { 2, 4, 8, &data_8bpsBGRA },
104123ec1e5eSAmine Khaldi         { 2, 4, 16, &data_64bppRGBA },
104223ec1e5eSAmine Khaldi         { 2, 4, 24, NULL },
104323ec1e5eSAmine Khaldi         { 2, 4, 32, &data_128bppRGBAFloat },
104423ec1e5eSAmine Khaldi         /* 1 - BlackIsZero (Bilevel) */
104523ec1e5eSAmine Khaldi         { 1, 1, 1, &data_BlackWhite, &data_BlackWhite_xp },
104623ec1e5eSAmine Khaldi         { 1, 1, 4, &data_4bppGray, &data_4bppGray_xp },
104723ec1e5eSAmine Khaldi         { 1, 1, 8, &data_8bppGray },
104823ec1e5eSAmine Khaldi         { 1, 1, 16, &data_16bppGray },
104923ec1e5eSAmine Khaldi         { 1, 1, 24, NULL },
105023ec1e5eSAmine Khaldi         { 1, 1, 32, &data_32bppGrayFloat },
105123ec1e5eSAmine Khaldi         /* 3 - Palette Color */
105223ec1e5eSAmine Khaldi         { 3, 1, 1, &data_1bppIndexed },
105323ec1e5eSAmine Khaldi         { 3, 1, 4, &data_4bppIndexed, &data_4bppIndexed_xp },
105423ec1e5eSAmine Khaldi         { 3, 1, 8, &data_8bppIndexed },
105523ec1e5eSAmine Khaldi #if 0 /* FIXME: for some reason libtiff replaces photometric 3 by 1 for bps > 8 */
105623ec1e5eSAmine Khaldi         { 3, 1, 16, &data_8bppIndexed },
105723ec1e5eSAmine Khaldi         { 3, 1, 24, &data_8bppIndexed },
105823ec1e5eSAmine Khaldi         { 3, 1, 32, &data_8bppIndexed },
105923ec1e5eSAmine Khaldi #endif
106023ec1e5eSAmine Khaldi         /* 5 - Separated */
106123ec1e5eSAmine Khaldi         { 5, 4, 1, NULL },
106223ec1e5eSAmine Khaldi         { 5, 4, 4, NULL },
106323ec1e5eSAmine Khaldi         { 5, 4, 8, &data_32bppCMYK },
106423ec1e5eSAmine Khaldi         { 5, 4, 16, &data_64bppCMYK },
106523ec1e5eSAmine Khaldi         { 5, 4, 24, NULL },
106623ec1e5eSAmine Khaldi         { 5, 4, 32, NULL },
106723ec1e5eSAmine Khaldi     };
106823ec1e5eSAmine Khaldi     BYTE buf[sizeof(tiff_1x1_data)];
106923ec1e5eSAmine Khaldi     BYTE pixels[256];
107023ec1e5eSAmine Khaldi     HRESULT hr;
107123ec1e5eSAmine Khaldi     IWICBitmapDecoder *decoder;
107223ec1e5eSAmine Khaldi     IWICBitmapFrameDecode *frame;
107323ec1e5eSAmine Khaldi     GUID format;
107423ec1e5eSAmine Khaldi     UINT count, i, bpp, channels, ret;
107523ec1e5eSAmine Khaldi     BOOL trasparency;
107623ec1e5eSAmine Khaldi     struct IFD_entry *tag, *tag_photo = NULL, *tag_bps = NULL, *tag_samples = NULL, *tag_colormap = NULL;
107723ec1e5eSAmine Khaldi     struct IFD_entry *tag_width = NULL, *tag_height = NULL;
107823ec1e5eSAmine Khaldi     short *bps;
107923ec1e5eSAmine Khaldi 
108023ec1e5eSAmine Khaldi     memcpy(buf, &tiff_1x1_data, sizeof(tiff_1x1_data));
108123ec1e5eSAmine Khaldi     generate_tiff_palette(buf + FIELD_OFFSET(struct tiff_1x1_data, palette_data), 256);
108223ec1e5eSAmine Khaldi 
108323ec1e5eSAmine Khaldi     count = *(short *)(buf + tiff_1x1_data.dir_offset);
108423ec1e5eSAmine Khaldi     tag = (struct IFD_entry *)(buf + tiff_1x1_data.dir_offset + sizeof(short));
108523ec1e5eSAmine Khaldi 
108623ec1e5eSAmine Khaldi     /* verify the TIFF structure */
108723ec1e5eSAmine Khaldi     for (i = 0; i < count; i++)
108823ec1e5eSAmine Khaldi     {
108923ec1e5eSAmine Khaldi         if (tag[i].id == 0x100) /* ImageWidth */
109023ec1e5eSAmine Khaldi             tag_width = &tag[i];
109123ec1e5eSAmine Khaldi         else if (tag[i].id == 0x101) /* ImageLength */
109223ec1e5eSAmine Khaldi             tag_height = &tag[i];
109323ec1e5eSAmine Khaldi         else if (tag[i].id == 0x102) /* BitsPerSample */
109423ec1e5eSAmine Khaldi             tag_bps = &tag[i];
109523ec1e5eSAmine Khaldi         else if (tag[i].id == 0x106) /* PhotometricInterpretation */
109623ec1e5eSAmine Khaldi             tag_photo = &tag[i];
109723ec1e5eSAmine Khaldi         else if (tag[i].id == 0x115) /* SamplesPerPixel */
109823ec1e5eSAmine Khaldi             tag_samples = &tag[i];
109923ec1e5eSAmine Khaldi         else if (tag[i].id == 0x140) /* ColorMap */
110023ec1e5eSAmine Khaldi             tag_colormap = &tag[i];
110123ec1e5eSAmine Khaldi     }
110223ec1e5eSAmine Khaldi 
110323ec1e5eSAmine Khaldi     ok(tag_bps && tag_photo && tag_samples && tag_colormap, "tag 0x102,0x106,0x115 or 0x140 is missing\n");
110423ec1e5eSAmine Khaldi     if (!tag_bps || !tag_photo || !tag_samples || !tag_colormap) return;
110523ec1e5eSAmine Khaldi 
110623ec1e5eSAmine Khaldi     ok(tag_bps->type == IFD_SHORT, "tag 0x102 should have type IFD_SHORT\n");
110723ec1e5eSAmine Khaldi     bps = (short *)(buf + tag_bps->value);
110823ec1e5eSAmine Khaldi     ok(bps[0] == 8 && bps[1] == 8 && bps[2] == 8 && bps[3] == 0,
110923ec1e5eSAmine Khaldi        "expected bps 8,8,8,0 got %d,%d,%d,%d\n", bps[0], bps[1], bps[2], bps[3]);
111023ec1e5eSAmine Khaldi 
111123ec1e5eSAmine Khaldi     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
111223ec1e5eSAmine Khaldi     {
111323ec1e5eSAmine Khaldi         if (td[i].data)
111423ec1e5eSAmine Khaldi         {
111523ec1e5eSAmine Khaldi             bpp = td[i].samples * td[i].bps;
111623ec1e5eSAmine Khaldi             if (winetest_debug > 1)
111723ec1e5eSAmine Khaldi                 trace("samples %u, bps %u, bpp %u, width %u => width_bytes %u\n", td[i].samples, td[i].bps, bpp,
111823ec1e5eSAmine Khaldi                       td[i].data->width, width_bytes(td[i].data->width, bpp));
111923ec1e5eSAmine Khaldi             tag_width->value = td[i].data->width;
112023ec1e5eSAmine Khaldi             tag_height->value = td[i].data->height;
112123ec1e5eSAmine Khaldi         }
112223ec1e5eSAmine Khaldi         else
112323ec1e5eSAmine Khaldi         {
112423ec1e5eSAmine Khaldi             tag_width->value = 1;
112523ec1e5eSAmine Khaldi             tag_height->value = 1;
112623ec1e5eSAmine Khaldi         }
112723ec1e5eSAmine Khaldi 
112823ec1e5eSAmine Khaldi         tag_colormap->count = (1 << td[i].bps) * 3;
112923ec1e5eSAmine Khaldi 
113023ec1e5eSAmine Khaldi         if (td[i].bps < 8)
113123ec1e5eSAmine Khaldi         {
113223ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data)] = 0x55;
113323ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 1] = 0xc3;
113423ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 2] = 0xb8;
113523ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 3] = 0x55;
113623ec1e5eSAmine Khaldi         }
113723ec1e5eSAmine Khaldi         else
113823ec1e5eSAmine Khaldi         {
113923ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data)] = 1;
114023ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 1] = 0;
114123ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 2] = 2;
114223ec1e5eSAmine Khaldi             buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 3] = 3;
114323ec1e5eSAmine Khaldi         }
114423ec1e5eSAmine Khaldi 
114523ec1e5eSAmine Khaldi         tag_photo->value = td[i].photometric;
114623ec1e5eSAmine Khaldi         tag_bps->count = td[i].samples;
114723ec1e5eSAmine Khaldi         tag_samples->value = td[i].samples;
114823ec1e5eSAmine Khaldi 
114923ec1e5eSAmine Khaldi         if (td[i].samples == 1)
115023ec1e5eSAmine Khaldi             tag_bps->value = td[i].bps;
115123ec1e5eSAmine Khaldi         else if (td[i].samples == 2)
115223ec1e5eSAmine Khaldi             tag_bps->value = MAKELONG(td[i].bps, td[i].bps);
115323ec1e5eSAmine Khaldi         else if (td[i].samples == 3)
115423ec1e5eSAmine Khaldi         {
115523ec1e5eSAmine Khaldi             tag_bps->value = (BYTE *)bps - buf;
115623ec1e5eSAmine Khaldi             bps[0] = bps[1] = bps[2] = td[i].bps;
115723ec1e5eSAmine Khaldi         }
115823ec1e5eSAmine Khaldi         else if (td[i].samples == 4)
115923ec1e5eSAmine Khaldi         {
116023ec1e5eSAmine Khaldi             tag_bps->value = (BYTE *)bps - buf;
116123ec1e5eSAmine Khaldi             bps[0] = bps[1] = bps[2] = bps[3] = td[i].bps;
116223ec1e5eSAmine Khaldi         }
116323ec1e5eSAmine Khaldi         else
116423ec1e5eSAmine Khaldi         {
116523ec1e5eSAmine Khaldi             ok(0, "%u: unsupported samples count %d\n", i, td[i].samples);
116623ec1e5eSAmine Khaldi             continue;
116723ec1e5eSAmine Khaldi         }
116823ec1e5eSAmine Khaldi 
116923ec1e5eSAmine Khaldi         hr = create_decoder(buf, sizeof(buf), &decoder);
117023ec1e5eSAmine Khaldi         if (!td[i].data)
117123ec1e5eSAmine Khaldi         {
117223ec1e5eSAmine Khaldi             ok(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT || hr == WINCODEC_ERR_COMPONENTNOTFOUND /* win8+ */ || WINCODEC_ERR_BADIMAGE /* XP */,
117323ec1e5eSAmine Khaldi                "%u: (%d,%d,%d) wrong error %#x\n", i, td[i].photometric, td[i].samples, td[i].bps, hr);
117423ec1e5eSAmine Khaldi             if (hr == S_OK)
117523ec1e5eSAmine Khaldi             {
117623ec1e5eSAmine Khaldi                 IWICBitmapDecoder_Release(decoder);
117723ec1e5eSAmine Khaldi                 dump_tiff(buf);
117823ec1e5eSAmine Khaldi             }
117923ec1e5eSAmine Khaldi             continue;
118023ec1e5eSAmine Khaldi         }
118123ec1e5eSAmine Khaldi         else
118223ec1e5eSAmine Khaldi             ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT || hr == WINCODEC_ERR_BADIMAGE) /* XP */,
118323ec1e5eSAmine Khaldi                "%u: failed to load TIFF image data (%d,%d,%d) %#x\n",
118423ec1e5eSAmine Khaldi                i, td[i].photometric, td[i].samples, td[i].bps, hr);
118523ec1e5eSAmine Khaldi         if (hr != S_OK) continue;
118623ec1e5eSAmine Khaldi 
118723ec1e5eSAmine Khaldi         hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
118823ec1e5eSAmine Khaldi         ok(hr == S_OK, "%u: GetFrame error %#x\n", i, hr);
118923ec1e5eSAmine Khaldi 
119023ec1e5eSAmine Khaldi         hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
119123ec1e5eSAmine Khaldi         ok(hr == S_OK, "%u: GetPixelFormat error %#x\n", i, hr);
119223ec1e5eSAmine Khaldi         ok(IsEqualGUID(&format, td[i].data->format),
119323ec1e5eSAmine Khaldi            "%u (%d,%d,%d): expected %s, got %s\n",
119423ec1e5eSAmine Khaldi             i, td[i].photometric, td[i].samples, td[i].bps,
119523ec1e5eSAmine Khaldi             wine_dbgstr_guid(td[i].data->format), wine_dbgstr_guid(&format));
119623ec1e5eSAmine Khaldi 
119723ec1e5eSAmine Khaldi         trasparency = (td[i].photometric == 2 && td[i].samples == 4); /* for XP */
119823ec1e5eSAmine Khaldi         hr = get_pixelformat_info(&format, &bpp, &channels, &trasparency);
119923ec1e5eSAmine Khaldi         ok(hr == S_OK, "%u: get_pixelformat_bpp error %#x\n", i, hr);
120023ec1e5eSAmine Khaldi         ok(bpp == td[i].data->bpp, "%u: expected %u, got %u\n", i, td[i].data->bpp, bpp);
120123ec1e5eSAmine Khaldi         ok(channels == td[i].samples, "%u: expected %u, got %u\n", i, td[i].samples, channels);
120223ec1e5eSAmine Khaldi         ok(trasparency == (td[i].photometric == 2 && td[i].samples == 4), "%u: got %u\n", i, trasparency);
120323ec1e5eSAmine Khaldi 
120423ec1e5eSAmine Khaldi         memset(pixels, 0, sizeof(pixels));
120523ec1e5eSAmine Khaldi         hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, width_bytes(td[i].data->width, bpp), sizeof(pixels), pixels);
120623ec1e5eSAmine Khaldi         ok(hr == S_OK, "%u: CopyPixels error %#x\n", i, hr);
120723ec1e5eSAmine Khaldi         ret = memcmp(pixels, td[i].data->bits, width_bytes(td[i].data->width, bpp));
120823ec1e5eSAmine Khaldi         if (ret && td[i].alt_data)
120923ec1e5eSAmine Khaldi             ret = memcmp(pixels, td[i].alt_data->bits, width_bytes(td[i].data->width, bpp));
121023ec1e5eSAmine Khaldi         ok(ret == 0, "%u: (%d,%d,%d) wrong pixel data\n", i, td[i].photometric, td[i].samples, td[i].bps);
121123ec1e5eSAmine Khaldi         if (ret)
121223ec1e5eSAmine Khaldi         {
121323ec1e5eSAmine Khaldi             UINT j, n = width_bytes(td[i].data->width, bpp);
121423ec1e5eSAmine Khaldi             for (j = 0; j < n; j++)
121523ec1e5eSAmine Khaldi                 printf("%u%s", pixels[j], (j + 1) < n ? "," : "\n");
121623ec1e5eSAmine Khaldi         }
121723ec1e5eSAmine Khaldi 
121823ec1e5eSAmine Khaldi         IWICBitmapFrameDecode_Release(frame);
121923ec1e5eSAmine Khaldi         IWICBitmapDecoder_Release(decoder);
122023ec1e5eSAmine Khaldi     }
122123ec1e5eSAmine Khaldi }
122223ec1e5eSAmine Khaldi 
test_tiff_4bps_bgra(void)1223*3e9c4dadSThomas Faber static void test_tiff_4bps_bgra(void)
1224*3e9c4dadSThomas Faber {
1225*3e9c4dadSThomas Faber     HRESULT hr;
1226*3e9c4dadSThomas Faber     IWICBitmapDecoder *decoder;
1227*3e9c4dadSThomas Faber     IWICBitmapFrameDecode *frame;
1228*3e9c4dadSThomas Faber     UINT frame_count, width, height, i;
1229*3e9c4dadSThomas Faber     double dpi_x, dpi_y;
1230*3e9c4dadSThomas Faber     IWICPalette *palette;
1231*3e9c4dadSThomas Faber     GUID format;
1232*3e9c4dadSThomas Faber     WICRect rc;
1233*3e9c4dadSThomas Faber     BYTE data[24];
1234*3e9c4dadSThomas Faber     static const BYTE expected_data[24] = { 0,0,0,0xff, 0xff,0,0,0, 0xff,0,0,0xff,
1235*3e9c4dadSThomas Faber                                             0,0xff,0,0, 0xff,0xff,0,0xff, 0xff,0xff,0xff,0 };
1236*3e9c4dadSThomas Faber 
1237*3e9c4dadSThomas Faber     hr = create_decoder(&tiff_4bps_bgra, sizeof(tiff_4bps_bgra), &decoder);
1238*3e9c4dadSThomas Faber     ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr);
1239*3e9c4dadSThomas Faber     if (hr != S_OK) return;
1240*3e9c4dadSThomas Faber 
1241*3e9c4dadSThomas Faber     hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
1242*3e9c4dadSThomas Faber     ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
1243*3e9c4dadSThomas Faber     ok(frame_count == 1, "expected 1, got %u\n", frame_count);
1244*3e9c4dadSThomas Faber 
1245*3e9c4dadSThomas Faber     hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
1246*3e9c4dadSThomas Faber     ok(hr == S_OK, "GetFrame error %#x\n", hr);
1247*3e9c4dadSThomas Faber 
1248*3e9c4dadSThomas Faber     hr = IWICBitmapFrameDecode_GetSize(frame, &width, &height);
1249*3e9c4dadSThomas Faber     ok(hr == S_OK, "GetSize error %#x\n", hr);
1250*3e9c4dadSThomas Faber     ok(width == 3, "got %u\n", width);
1251*3e9c4dadSThomas Faber     ok(height == 2, "got %u\n", height);
1252*3e9c4dadSThomas Faber 
1253*3e9c4dadSThomas Faber     hr = IWICBitmapFrameDecode_GetResolution(frame, &dpi_x, &dpi_y);
1254*3e9c4dadSThomas Faber     ok(hr == S_OK, "GetResolution error %#x\n", hr);
1255*3e9c4dadSThomas Faber     ok(dpi_x == 96.0, "expected 96.0, got %f\n", dpi_x);
1256*3e9c4dadSThomas Faber     ok(dpi_y == 96.0, "expected 96.0, got %f\n", dpi_y);
1257*3e9c4dadSThomas Faber 
1258*3e9c4dadSThomas Faber     hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
1259*3e9c4dadSThomas Faber     ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
1260*3e9c4dadSThomas Faber     ok(IsEqualGUID(&format, &GUID_WICPixelFormat32bppBGRA),
1261*3e9c4dadSThomas Faber        "got wrong format %s\n", wine_dbgstr_guid(&format));
1262*3e9c4dadSThomas Faber 
1263*3e9c4dadSThomas Faber     hr = IWICImagingFactory_CreatePalette(factory, &palette);
1264*3e9c4dadSThomas Faber     ok(hr == S_OK, "CreatePalette error %#x\n", hr);
1265*3e9c4dadSThomas Faber     hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
1266*3e9c4dadSThomas Faber     ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE,
1267*3e9c4dadSThomas Faber        "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %#x\n", hr);
1268*3e9c4dadSThomas Faber     IWICPalette_Release(palette);
1269*3e9c4dadSThomas Faber 
1270*3e9c4dadSThomas Faber     memset(data, 0xaa, sizeof(data));
1271*3e9c4dadSThomas Faber     rc.X = 0;
1272*3e9c4dadSThomas Faber     rc.Y = 0;
1273*3e9c4dadSThomas Faber     rc.Width = 3;
1274*3e9c4dadSThomas Faber     rc.Height = 2;
1275*3e9c4dadSThomas Faber     hr = IWICBitmapFrameDecode_CopyPixels(frame, &rc, 12, sizeof(data), data);
1276*3e9c4dadSThomas Faber     ok(hr == S_OK, "CopyPixels error %#x\n", hr);
1277*3e9c4dadSThomas Faber 
1278*3e9c4dadSThomas Faber     for (i = 0; i < sizeof(data); i++)
1279*3e9c4dadSThomas Faber         ok(data[i] == expected_data[i], "%u: expected %02x, got %02x\n", i, expected_data[i], data[i]);
1280*3e9c4dadSThomas Faber 
1281*3e9c4dadSThomas Faber     IWICBitmapFrameDecode_Release(frame);
1282*3e9c4dadSThomas Faber     IWICBitmapDecoder_Release(decoder);
1283*3e9c4dadSThomas Faber }
1284*3e9c4dadSThomas Faber 
START_TEST(tiffformat)1285c2c66affSColin Finck START_TEST(tiffformat)
1286c2c66affSColin Finck {
1287c2c66affSColin Finck     HRESULT hr;
1288c2c66affSColin Finck 
1289c2c66affSColin Finck     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1290c2c66affSColin Finck 
1291c2c66affSColin Finck     hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
1292c2c66affSColin Finck                           &IID_IWICImagingFactory, (void **)&factory);
1293c2c66affSColin Finck     ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
1294c2c66affSColin Finck     if (FAILED(hr)) return;
1295c2c66affSColin Finck 
1296*3e9c4dadSThomas Faber     test_tiff_4bps_bgra();
129723ec1e5eSAmine Khaldi     test_color_formats();
129823ec1e5eSAmine Khaldi     test_tiff_1bpp_palette();
129923ec1e5eSAmine Khaldi     test_tiff_8bpp_palette();
1300c2c66affSColin Finck     test_QueryCapability();
1301c2c66affSColin Finck     test_tiff_8bpp_alpha();
130223ec1e5eSAmine Khaldi     test_tiff_resolution();
1303eea81f52SAmine Khaldi     test_tiff_24bpp();
1304c2c66affSColin Finck 
1305c2c66affSColin Finck     IWICImagingFactory_Release(factory);
1306c2c66affSColin Finck     CoUninitialize();
1307c2c66affSColin Finck }
1308