[THEMES]
[reactos.git] / rostests / winetests / windowscodecs / tiffformat.c
1 /*
2 * Copyright 2012 Dmitry Timoshkov
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 //#include <stdarg.h>
20 #include <stdio.h>
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24 #define COM_NO_WINDOWS_H
25
26 #define COBJMACROS
27
28 #include <windef.h>
29 #include <winbase.h>
30 #include <ole2.h>
31 #include <wincodec.h>
32 #include <wine/test.h>
33
34 #define IFD_BYTE 1
35 #define IFD_ASCII 2
36 #define IFD_SHORT 3
37 #define IFD_LONG 4
38 #define IFD_RATIONAL 5
39 #define IFD_SBYTE 6
40 #define IFD_UNDEFINED 7
41 #define IFD_SSHORT 8
42 #define IFD_SLONG 9
43 #define IFD_SRATIONAL 10
44 #define IFD_FLOAT 11
45 #define IFD_DOUBLE 12
46
47 #include <pshpack2.h>
48 struct IFD_entry
49 {
50 SHORT id;
51 SHORT type;
52 ULONG count;
53 LONG value;
54 };
55
56 struct IFD_rational
57 {
58 LONG numerator;
59 LONG denominator;
60 };
61
62 static const struct tiff_1bpp_data
63 {
64 USHORT byte_order;
65 USHORT version;
66 ULONG dir_offset;
67 USHORT number_of_entries;
68 struct IFD_entry entry[13];
69 ULONG next_IFD;
70 struct IFD_rational res;
71 BYTE pixel_data[4];
72 } tiff_1bpp_data =
73 {
74 #ifdef WORDS_BIGENDIAN
75 'M' | 'M' << 8,
76 #else
77 'I' | 'I' << 8,
78 #endif
79 42,
80 FIELD_OFFSET(struct tiff_1bpp_data, number_of_entries),
81 13,
82 {
83 { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */
84 { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */
85 { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */
86 { 0x102, IFD_SHORT, 1, 1 }, /* BITSPERSAMPLE */
87 { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */
88 { 0x106, IFD_SHORT, 1, 1 }, /* PHOTOMETRIC */
89 { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1bpp_data, pixel_data) }, /* STRIPOFFSETS */
90 { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */
91 { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */
92 { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */
93 { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1bpp_data, res) },
94 { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1bpp_data, res) },
95 { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */
96 },
97 0,
98 { 900, 3 },
99 { 0x11, 0x22, 0x33, 0 }
100 };
101 #include <poppack.h>
102
103 static IWICImagingFactory *factory;
104
105 static const char *debugstr_guid(const GUID *guid)
106 {
107 static char buf[50];
108
109 if (!guid) return "(null)";
110 sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
111 guid->Data1, guid->Data2, guid->Data3, guid->Data4[0],
112 guid->Data4[1], guid->Data4[2], guid->Data4[3], guid->Data4[4],
113 guid->Data4[5], guid->Data4[6], guid->Data4[7]);
114 return buf;
115 }
116
117 static IStream *create_stream(const void *data, int data_size)
118 {
119 HRESULT hr;
120 IStream *stream;
121 HGLOBAL hdata;
122 void *locked_data;
123
124 hdata = GlobalAlloc(GMEM_MOVEABLE, data_size);
125 ok(hdata != 0, "GlobalAlloc failed\n");
126 if (!hdata) return NULL;
127
128 locked_data = GlobalLock(hdata);
129 memcpy(locked_data, data, data_size);
130 GlobalUnlock(hdata);
131
132 hr = CreateStreamOnHGlobal(hdata, TRUE, &stream);
133 ok(hr == S_OK, "CreateStreamOnHGlobal failed, hr=%x\n", hr);
134
135 return stream;
136 }
137
138 static IWICBitmapDecoder *create_decoder(const void *image_data, UINT image_size)
139 {
140 HRESULT hr;
141 IStream *stream;
142 IWICBitmapDecoder *decoder = NULL;
143 GUID guid;
144
145 stream = create_stream(image_data, image_size);
146
147 hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
148 ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
149
150 hr = IWICBitmapDecoder_GetContainerFormat(decoder, &guid);
151 ok(hr == S_OK, "GetContainerFormat error %#x\n", hr);
152 ok(IsEqualGUID(&guid, &GUID_ContainerFormatTiff), "container format is not TIFF\n");
153
154 IStream_Release(stream);
155
156 return decoder;
157 }
158
159 static void test_tiff_palette(void)
160 {
161 HRESULT hr;
162 IWICBitmapDecoder *decoder;
163 IWICBitmapFrameDecode *frame;
164 IWICPalette *palette;
165 GUID format;
166
167 decoder = create_decoder(&tiff_1bpp_data, sizeof(tiff_1bpp_data));
168 ok(decoder != 0, "Failed to load TIFF image data\n");
169
170 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
171 ok(hr == S_OK, "GetFrame error %#x\n", hr);
172
173 hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format);
174 ok(hr == S_OK, "GetPixelFormat error %#x\n", hr);
175 ok(IsEqualGUID(&format, &GUID_WICPixelFormatBlackWhite),
176 "got wrong format %s\n", debugstr_guid(&format));
177
178 hr = IWICImagingFactory_CreatePalette(factory, &palette);
179 ok(hr == S_OK, "CreatePalette error %#x\n", hr);
180 hr = IWICBitmapFrameDecode_CopyPalette(frame, palette);
181 ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE,
182 "expected WINCODEC_ERR_PALETTEUNAVAILABLE, got %#x\n", hr);
183
184 IWICPalette_Release(palette);
185 IWICBitmapFrameDecode_Release(frame);
186 IWICBitmapDecoder_Release(decoder);
187 }
188
189 static void test_QueryCapability(void)
190 {
191 HRESULT hr;
192 IStream *stream;
193 IWICBitmapDecoder *decoder;
194 IWICBitmapFrameDecode *frame;
195 static const DWORD exp_caps = WICBitmapDecoderCapabilityCanDecodeAllImages |
196 WICBitmapDecoderCapabilityCanDecodeSomeImages |
197 WICBitmapDecoderCapabilityCanEnumerateMetadata;
198 static const DWORD exp_caps_xp = WICBitmapDecoderCapabilityCanDecodeAllImages |
199 WICBitmapDecoderCapabilityCanDecodeSomeImages;
200 DWORD capability;
201 LARGE_INTEGER pos;
202 ULARGE_INTEGER cur_pos;
203 UINT frame_count;
204
205 stream = create_stream(&tiff_1bpp_data, sizeof(tiff_1bpp_data));
206 if (!stream) return;
207
208 hr = IWICImagingFactory_CreateDecoder(factory, &GUID_ContainerFormatTiff, NULL, &decoder);
209 ok(hr == S_OK, "CreateDecoder error %#x\n", hr);
210
211 frame_count = 0xdeadbeef;
212 hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
213 ok(hr == S_OK || broken(hr == E_POINTER) /* XP */, "GetFrameCount error %#x\n", hr);
214 ok(frame_count == 0, "expected 0, got %u\n", frame_count);
215
216 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
217 ok(hr == WINCODEC_ERR_FRAMEMISSING || broken(hr == E_POINTER) /* XP */, "expected WINCODEC_ERR_FRAMEMISSING, got %#x\n", hr);
218
219 pos.QuadPart = 4;
220 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
221 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
222
223 capability = 0xdeadbeef;
224 hr = IWICBitmapDecoder_QueryCapability(decoder, stream, &capability);
225 ok(hr == S_OK, "QueryCapability error %#x\n", hr);
226 ok(capability == exp_caps || capability == exp_caps_xp,
227 "expected %#x, got %#x\n", exp_caps, capability);
228
229 frame_count = 0xdeadbeef;
230 hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
231 ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
232 ok(frame_count == 1, "expected 1, got %u\n", frame_count);
233
234 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
235 ok(hr == S_OK, "GetFrame error %#x\n", hr);
236 IWICBitmapFrameDecode_Release(frame);
237
238 pos.QuadPart = 0;
239 hr = IStream_Seek(stream, pos, SEEK_CUR, &cur_pos);
240 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
241 ok(cur_pos.QuadPart > 4 && cur_pos.QuadPart < sizeof(tiff_1bpp_data),
242 "current stream pos is at %x/%x\n", cur_pos.u.LowPart, cur_pos.u.HighPart);
243
244 hr = IWICBitmapDecoder_QueryCapability(decoder, stream, &capability);
245 ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
246
247 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
248 ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
249
250 IWICBitmapDecoder_Release(decoder);
251
252 hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
253 todo_wine
254 ok(hr == WINCODEC_ERR_COMPONENTNOTFOUND, "expected WINCODEC_ERR_COMPONENTNOTFOUND, got %#x\n", hr);
255
256 pos.QuadPart = 0;
257 hr = IStream_Seek(stream, pos, SEEK_SET, NULL);
258 ok(hr == S_OK, "IStream_Seek error %#x\n", hr);
259
260 hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder);
261 ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr);
262
263 frame_count = 0xdeadbeef;
264 hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count);
265 ok(hr == S_OK, "GetFrameCount error %#x\n", hr);
266 ok(frame_count == 1, "expected 1, got %u\n", frame_count);
267
268 hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame);
269 ok(hr == S_OK, "GetFrame error %#x\n", hr);
270 IWICBitmapFrameDecode_Release(frame);
271
272 hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand);
273 ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
274
275 hr = IWICBitmapDecoder_QueryCapability(decoder, stream, &capability);
276 ok(hr == WINCODEC_ERR_WRONGSTATE, "expected WINCODEC_ERR_WRONGSTATE, got %#x\n", hr);
277
278 IWICBitmapDecoder_Release(decoder);
279 IStream_Release(stream);
280 }
281
282 START_TEST(tiffformat)
283 {
284 HRESULT hr;
285
286 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
287
288 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
289 &IID_IWICImagingFactory, (void **)&factory);
290 ok(hr == S_OK, "CoCreateInstance error %#x\n", hr);
291 if (FAILED(hr)) return;
292
293 test_tiff_palette();
294 test_QueryCapability();
295
296 IWICImagingFactory_Release(factory);
297 CoUninitialize();
298 }