1 /*
2  * Copyright 2010 Vincent Povirk for CodeWeavers
3  * Copyright 2016 Dmitry Timoshkov
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 
20 #include "config.h"
21 #include "wine/port.h"
22 
23 #include <stdarg.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27 #ifdef HAVE_TIFFIO_H
28 #include <tiffio.h>
29 #endif
30 
31 #define COBJMACROS
32 
33 #include "windef.h"
34 #include "winbase.h"
35 #include "objbase.h"
36 
37 #include "wincodecs_private.h"
38 
39 #include "wine/debug.h"
40 #include "wine/library.h"
41 
42 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
43 
44 #ifdef SONAME_LIBTIFF
45 
46 /* Workaround for broken libtiff 4.x headers on some 64-bit hosts which
47  * define TIFF_UINT64_T/toff_t as 32-bit for 32-bit builds, while they
48  * are supposed to be always 64-bit.
49  * TIFF_UINT64_T doesn't exist in libtiff 3.x, it was introduced in 4.x.
50  */
51 #ifdef TIFF_UINT64_T
52 # undef toff_t
53 # define toff_t UINT64
54 #endif
55 
56 static CRITICAL_SECTION init_tiff_cs;
57 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug =
58 {
59     0, 0, &init_tiff_cs,
60     { &init_tiff_cs_debug.ProcessLocksList,
61       &init_tiff_cs_debug.ProcessLocksList },
62     0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") }
63 };
64 static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
65 
66 static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0};
67 static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
68 
69 static void *libtiff_handle;
70 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
71 MAKE_FUNCPTR(TIFFClientOpen);
72 MAKE_FUNCPTR(TIFFClose);
73 MAKE_FUNCPTR(TIFFCurrentDirOffset);
74 MAKE_FUNCPTR(TIFFGetField);
75 MAKE_FUNCPTR(TIFFIsByteSwapped);
76 MAKE_FUNCPTR(TIFFNumberOfDirectories);
77 MAKE_FUNCPTR(TIFFReadDirectory);
78 MAKE_FUNCPTR(TIFFReadEncodedStrip);
79 MAKE_FUNCPTR(TIFFReadEncodedTile);
80 MAKE_FUNCPTR(TIFFSetDirectory);
81 MAKE_FUNCPTR(TIFFSetField);
82 MAKE_FUNCPTR(TIFFWriteDirectory);
83 MAKE_FUNCPTR(TIFFWriteScanline);
84 #undef MAKE_FUNCPTR
85 
86 static void *load_libtiff(void)
87 {
88     void *result;
89 
90     EnterCriticalSection(&init_tiff_cs);
91 
92     if (!libtiff_handle &&
93         (libtiff_handle = wine_dlopen(SONAME_LIBTIFF, RTLD_NOW, NULL, 0)) != NULL)
94     {
95         void * (*pTIFFSetWarningHandler)(void *);
96         void * (*pTIFFSetWarningHandlerExt)(void *);
97 
98 #define LOAD_FUNCPTR(f) \
99     if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \
100         ERR("failed to load symbol %s\n", #f); \
101         libtiff_handle = NULL; \
102         LeaveCriticalSection(&init_tiff_cs); \
103         return NULL; \
104     }
105         LOAD_FUNCPTR(TIFFClientOpen);
106         LOAD_FUNCPTR(TIFFClose);
107         LOAD_FUNCPTR(TIFFCurrentDirOffset);
108         LOAD_FUNCPTR(TIFFGetField);
109         LOAD_FUNCPTR(TIFFIsByteSwapped);
110         LOAD_FUNCPTR(TIFFNumberOfDirectories);
111         LOAD_FUNCPTR(TIFFReadDirectory);
112         LOAD_FUNCPTR(TIFFReadEncodedStrip);
113         LOAD_FUNCPTR(TIFFReadEncodedTile);
114         LOAD_FUNCPTR(TIFFSetDirectory);
115         LOAD_FUNCPTR(TIFFSetField);
116         LOAD_FUNCPTR(TIFFWriteDirectory);
117         LOAD_FUNCPTR(TIFFWriteScanline);
118 #undef LOAD_FUNCPTR
119 
120         if ((pTIFFSetWarningHandler = wine_dlsym(libtiff_handle, "TIFFSetWarningHandler", NULL, 0)))
121             pTIFFSetWarningHandler(NULL);
122         if ((pTIFFSetWarningHandlerExt = wine_dlsym(libtiff_handle, "TIFFSetWarningHandlerExt", NULL, 0)))
123             pTIFFSetWarningHandlerExt(NULL);
124     }
125 
126     result = libtiff_handle;
127 
128     LeaveCriticalSection(&init_tiff_cs);
129     return result;
130 }
131 
132 static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size)
133 {
134     IStream *stream = (IStream*)client_data;
135     ULONG bytes_read;
136     HRESULT hr;
137 
138     hr = IStream_Read(stream, data, size, &bytes_read);
139     if (FAILED(hr)) bytes_read = 0;
140     return bytes_read;
141 }
142 
143 static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
144 {
145     IStream *stream = (IStream*)client_data;
146     ULONG bytes_written;
147     HRESULT hr;
148 
149     hr = IStream_Write(stream, data, size, &bytes_written);
150     if (FAILED(hr)) bytes_written = 0;
151     return bytes_written;
152 }
153 
154 static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
155 {
156     IStream *stream = (IStream*)client_data;
157     LARGE_INTEGER move;
158     DWORD origin;
159     ULARGE_INTEGER new_position;
160     HRESULT hr;
161 
162     move.QuadPart = offset;
163     switch (whence)
164     {
165         case SEEK_SET:
166             origin = STREAM_SEEK_SET;
167             break;
168         case SEEK_CUR:
169             origin = STREAM_SEEK_CUR;
170             break;
171         case SEEK_END:
172             origin = STREAM_SEEK_END;
173             break;
174         default:
175             ERR("unknown whence value %i\n", whence);
176             return -1;
177     }
178 
179     hr = IStream_Seek(stream, move, origin, &new_position);
180     if (SUCCEEDED(hr)) return new_position.QuadPart;
181     else return -1;
182 }
183 
184 static int tiff_stream_close(thandle_t client_data)
185 {
186     /* Caller is responsible for releasing the stream object. */
187     return 0;
188 }
189 
190 static toff_t tiff_stream_size(thandle_t client_data)
191 {
192     IStream *stream = (IStream*)client_data;
193     STATSTG statstg;
194     HRESULT hr;
195 
196     hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
197 
198     if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart;
199     else return -1;
200 }
201 
202 static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
203 {
204     /* Cannot mmap streams */
205     return 0;
206 }
207 
208 static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size)
209 {
210     /* No need to ever do this, since we can't map things. */
211 }
212 
213 static TIFF* tiff_open_stream(IStream *stream, const char *mode)
214 {
215     LARGE_INTEGER zero;
216 
217     zero.QuadPart = 0;
218     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
219 
220     return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read,
221         tiff_stream_write, (void *)tiff_stream_seek, tiff_stream_close,
222         (void *)tiff_stream_size, (void *)tiff_stream_map, (void *)tiff_stream_unmap);
223 }
224 
225 typedef struct {
226     IWICBitmapDecoder IWICBitmapDecoder_iface;
227     LONG ref;
228     IStream *stream;
229     CRITICAL_SECTION lock; /* Must be held when tiff is used or initialized is set */
230     TIFF *tiff;
231     BOOL initialized;
232 } TiffDecoder;
233 
234 typedef struct {
235     const WICPixelFormatGUID *format;
236     int bps;
237     int samples;
238     int bpp, source_bpp;
239     int planar;
240     int indexed;
241     int reverse_bgr;
242     int invert_grayscale;
243     UINT width, height;
244     UINT tile_width, tile_height;
245     UINT tile_stride;
246     UINT tile_size;
247     int tiled;
248     UINT tiles_across;
249     UINT resolution_unit;
250     float xres, yres;
251 } tiff_decode_info;
252 
253 typedef struct {
254     IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
255     IWICMetadataBlockReader IWICMetadataBlockReader_iface;
256     LONG ref;
257     TiffDecoder *parent;
258     UINT index;
259     tiff_decode_info decode_info;
260     INT cached_tile_x, cached_tile_y;
261     BYTE *cached_tile;
262 } TiffFrameDecode;
263 
264 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl;
265 static const IWICMetadataBlockReaderVtbl TiffFrameDecode_BlockVtbl;
266 
267 static inline TiffDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
268 {
269     return CONTAINING_RECORD(iface, TiffDecoder, IWICBitmapDecoder_iface);
270 }
271 
272 static inline TiffFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
273 {
274     return CONTAINING_RECORD(iface, TiffFrameDecode, IWICBitmapFrameDecode_iface);
275 }
276 
277 static inline TiffFrameDecode *impl_from_IWICMetadataBlockReader(IWICMetadataBlockReader *iface)
278 {
279     return CONTAINING_RECORD(iface, TiffFrameDecode, IWICMetadataBlockReader_iface);
280 }
281 
282 static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
283 {
284     uint16 photometric, bps, samples, planar;
285     uint16 extra_sample_count, extra_sample, *extra_samples;
286     int ret;
287 
288     decode_info->indexed = 0;
289     decode_info->reverse_bgr = 0;
290     decode_info->invert_grayscale = 0;
291     decode_info->tiled = 0;
292 
293     ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
294     if (!ret)
295     {
296         WARN("missing PhotometricInterpretation tag\n");
297         return E_FAIL;
298     }
299 
300     ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
301     if (!ret) bps = 1;
302     decode_info->bps = bps;
303 
304     ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples);
305     if (!ret) samples = 1;
306     decode_info->samples = samples;
307 
308     if (samples == 1)
309         planar = 1;
310     else
311     {
312         ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar);
313         if (!ret) planar = 1;
314         if (planar != 1)
315         {
316             FIXME("unhandled planar configuration %u\n", planar);
317             return E_FAIL;
318         }
319     }
320     decode_info->planar = planar;
321 
322     TRACE("planar %u, photometric %u, samples %u, bps %u\n", planar, photometric, samples, bps);
323 
324     switch(photometric)
325     {
326     case 0: /* WhiteIsZero */
327         decode_info->invert_grayscale = 1;
328         /* fall through */
329     case 1: /* BlackIsZero */
330         if (samples == 2)
331         {
332             ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
333             if (!ret)
334             {
335                 extra_sample_count = 1;
336                 extra_sample = 0;
337                 extra_samples = &extra_sample;
338             }
339         }
340         else if (samples != 1)
341         {
342             FIXME("unhandled %dbpp sample count %u\n", bps, samples);
343             return E_FAIL;
344         }
345 
346         decode_info->bpp = bps * samples;
347         decode_info->source_bpp = decode_info->bpp;
348         switch (bps)
349         {
350         case 1:
351             if (samples != 1)
352             {
353                 FIXME("unhandled 1bpp sample count %u\n", samples);
354                 return E_FAIL;
355             }
356             decode_info->format = &GUID_WICPixelFormatBlackWhite;
357             break;
358         case 4:
359             if (samples != 1)
360             {
361                 FIXME("unhandled 4bpp grayscale sample count %u\n", samples);
362                 return E_FAIL;
363             }
364             decode_info->format = &GUID_WICPixelFormat4bppGray;
365             break;
366         case 8:
367             if (samples == 1)
368                 decode_info->format = &GUID_WICPixelFormat8bppGray;
369             else
370             {
371                 decode_info->bpp = 32;
372 
373                 switch(extra_samples[0])
374                 {
375                 case 1: /* Associated (pre-multiplied) alpha data */
376                     decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
377                     break;
378                 case 0: /* Unspecified data */
379                 case 2: /* Unassociated alpha data */
380                     decode_info->format = &GUID_WICPixelFormat32bppBGRA;
381                     break;
382                 default:
383                     FIXME("unhandled extra sample type %u\n", extra_samples[0]);
384                     return E_FAIL;
385                 }
386             }
387             break;
388         case 16:
389             if (samples != 1)
390             {
391                 FIXME("unhandled 16bpp grayscale sample count %u\n", samples);
392                 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
393             }
394             decode_info->format = &GUID_WICPixelFormat16bppGray;
395             break;
396         case 32:
397             if (samples != 1)
398             {
399                 FIXME("unhandled 32bpp grayscale sample count %u\n", samples);
400                 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
401             }
402             decode_info->format = &GUID_WICPixelFormat32bppGrayFloat;
403             break;
404         default:
405             WARN("unhandled greyscale bit count %u\n", bps);
406             return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
407         }
408         break;
409     case 2: /* RGB */
410         if (samples == 4)
411         {
412             ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
413             if (!ret)
414             {
415                 extra_sample_count = 1;
416                 extra_sample = 0;
417                 extra_samples = &extra_sample;
418             }
419         }
420         else if (samples != 3)
421         {
422             FIXME("unhandled RGB sample count %u\n", samples);
423             return E_FAIL;
424         }
425 
426         decode_info->bpp = max(bps, 8) * samples;
427         decode_info->source_bpp = bps * samples;
428         switch(bps)
429         {
430         case 1:
431         case 4:
432         case 8:
433             decode_info->reverse_bgr = 1;
434             if (samples == 3)
435                 decode_info->format = &GUID_WICPixelFormat24bppBGR;
436             else
437                 switch(extra_samples[0])
438                 {
439                 case 1: /* Associated (pre-multiplied) alpha data */
440                     decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
441                     break;
442                 case 0: /* Unspecified data */
443                 case 2: /* Unassociated alpha data */
444                     decode_info->format = &GUID_WICPixelFormat32bppBGRA;
445                     break;
446                 default:
447                     FIXME("unhandled extra sample type %i\n", extra_samples[0]);
448                     return E_FAIL;
449                 }
450             break;
451         case 16:
452             if (samples == 3)
453                 decode_info->format = &GUID_WICPixelFormat48bppRGB;
454             else
455                 switch(extra_samples[0])
456                 {
457                 case 1: /* Associated (pre-multiplied) alpha data */
458                     decode_info->format = &GUID_WICPixelFormat64bppPRGBA;
459                     break;
460                 case 0: /* Unspecified data */
461                 case 2: /* Unassociated alpha data */
462                     decode_info->format = &GUID_WICPixelFormat64bppRGBA;
463                     break;
464                 default:
465                     FIXME("unhandled extra sample type %i\n", extra_samples[0]);
466                     return E_FAIL;
467                 }
468             break;
469         case 32:
470             if (samples != 4)
471             {
472                 FIXME("unhandled 32bpp RGB sample count %u\n", samples);
473                 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
474             }
475             decode_info->format = &GUID_WICPixelFormat128bppRGBAFloat;
476             break;
477         default:
478             WARN("unhandled RGB bit count %u\n", bps);
479             return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
480         }
481         break;
482     case 3: /* RGB Palette */
483         if (samples != 1)
484         {
485             FIXME("unhandled indexed sample count %u\n", samples);
486             return E_FAIL;
487         }
488 
489         decode_info->indexed = 1;
490         decode_info->bpp = bps;
491         switch (bps)
492         {
493         case 1:
494             decode_info->format = &GUID_WICPixelFormat1bppIndexed;
495             break;
496         case 2:
497             decode_info->format = &GUID_WICPixelFormat2bppIndexed;
498             break;
499         case 4:
500             decode_info->format = &GUID_WICPixelFormat4bppIndexed;
501             break;
502         case 8:
503             decode_info->format = &GUID_WICPixelFormat8bppIndexed;
504             break;
505         default:
506             FIXME("unhandled indexed bit count %u\n", bps);
507             return E_FAIL;
508         }
509         break;
510 
511     case 5: /* Separated */
512         if (samples != 4)
513         {
514             FIXME("unhandled Separated sample count %u\n", samples);
515             return E_FAIL;
516         }
517 
518         decode_info->bpp = bps * samples;
519         switch(bps)
520         {
521         case 8:
522             decode_info->format = &GUID_WICPixelFormat32bppCMYK;
523             break;
524         case 16:
525             decode_info->format = &GUID_WICPixelFormat64bppCMYK;
526             break;
527 
528         default:
529             WARN("unhandled Separated bit count %u\n", bps);
530             return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT;
531         }
532         break;
533 
534     case 4: /* Transparency mask */
535     case 6: /* YCbCr */
536     case 8: /* CIELab */
537     default:
538         FIXME("unhandled PhotometricInterpretation %u\n", photometric);
539         return E_FAIL;
540     }
541 
542     ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width);
543     if (!ret)
544     {
545         WARN("missing image width\n");
546         return E_FAIL;
547     }
548 
549     ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height);
550     if (!ret)
551     {
552         WARN("missing image length\n");
553         return E_FAIL;
554     }
555 
556     if ((ret = pTIFFGetField(tiff, TIFFTAG_TILEWIDTH, &decode_info->tile_width)))
557     {
558         decode_info->tiled = 1;
559 
560         ret = pTIFFGetField(tiff, TIFFTAG_TILELENGTH, &decode_info->tile_height);
561         if (!ret)
562         {
563             WARN("missing tile height\n");
564             return E_FAIL;
565         }
566 
567         decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
568         decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
569         decode_info->tiles_across = (decode_info->width + decode_info->tile_width - 1) / decode_info->tile_width;
570     }
571     else if ((ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height)))
572     {
573         if (decode_info->tile_height > decode_info->height)
574             decode_info->tile_height = decode_info->height;
575         decode_info->tile_width = decode_info->width;
576         decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
577         decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
578     }
579     else
580     {
581         /* Some broken TIFF files have a single strip and lack the RowsPerStrip tag */
582         decode_info->tile_height = decode_info->height;
583         decode_info->tile_width = decode_info->width;
584         decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
585         decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
586     }
587 
588     decode_info->resolution_unit = 0;
589     pTIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &decode_info->resolution_unit);
590 
591     ret = pTIFFGetField(tiff, TIFFTAG_XRESOLUTION, &decode_info->xres);
592     if (!ret)
593     {
594         WARN("missing X resolution\n");
595     }
596     /* Emulate the behavior of current libtiff versions (libtiff commit a39f6131)
597      * yielding 0 instead of INFINITY for IFD_RATIONAL fields with denominator 0. */
598     if (!isfinite(decode_info->xres))
599     {
600         decode_info->xres = 0.0;
601     }
602 
603     ret = pTIFFGetField(tiff, TIFFTAG_YRESOLUTION, &decode_info->yres);
604     if (!ret)
605     {
606         WARN("missing Y resolution\n");
607     }
608     if (!isfinite(decode_info->yres))
609     {
610         decode_info->yres = 0.0;
611     }
612 
613     return S_OK;
614 }
615 
616 static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
617     void **ppv)
618 {
619     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
620     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
621 
622     if (!ppv) return E_INVALIDARG;
623 
624     if (IsEqualIID(&IID_IUnknown, iid) ||
625         IsEqualIID(&IID_IWICBitmapDecoder, iid))
626     {
627         *ppv = &This->IWICBitmapDecoder_iface;
628     }
629     else
630     {
631         *ppv = NULL;
632         return E_NOINTERFACE;
633     }
634 
635     IUnknown_AddRef((IUnknown*)*ppv);
636     return S_OK;
637 }
638 
639 static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface)
640 {
641     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
642     ULONG ref = InterlockedIncrement(&This->ref);
643 
644     TRACE("(%p) refcount=%u\n", iface, ref);
645 
646     return ref;
647 }
648 
649 static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface)
650 {
651     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
652     ULONG ref = InterlockedDecrement(&This->ref);
653 
654     TRACE("(%p) refcount=%u\n", iface, ref);
655 
656     if (ref == 0)
657     {
658         if (This->tiff) pTIFFClose(This->tiff);
659         if (This->stream) IStream_Release(This->stream);
660         This->lock.DebugInfo->Spare[0] = 0;
661         DeleteCriticalSection(&This->lock);
662         HeapFree(GetProcessHeap(), 0, This);
663     }
664 
665     return ref;
666 }
667 
668 static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *stream,
669     DWORD *capability)
670 {
671     HRESULT hr;
672 
673     TRACE("(%p,%p,%p)\n", iface, stream, capability);
674 
675     if (!stream || !capability) return E_INVALIDARG;
676 
677     hr = IWICBitmapDecoder_Initialize(iface, stream, WICDecodeMetadataCacheOnDemand);
678     if (hr != S_OK) return hr;
679 
680     *capability = WICBitmapDecoderCapabilityCanDecodeAllImages |
681                   WICBitmapDecoderCapabilityCanDecodeSomeImages |
682                   WICBitmapDecoderCapabilityCanEnumerateMetadata;
683     return S_OK;
684 }
685 
686 static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
687     WICDecodeOptions cacheOptions)
688 {
689     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
690     TIFF *tiff;
691     tiff_decode_info decode_info;
692     HRESULT hr=S_OK;
693 
694     TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions);
695 
696     EnterCriticalSection(&This->lock);
697 
698     if (This->initialized)
699     {
700         hr = WINCODEC_ERR_WRONGSTATE;
701         goto exit;
702     }
703 
704     tiff = tiff_open_stream(pIStream, "r");
705     if (!tiff)
706     {
707         hr = E_FAIL;
708         goto exit;
709     }
710 
711     /* make sure that TIFF format is supported */
712     hr = tiff_get_decode_info(tiff, &decode_info);
713     if (hr != S_OK)
714     {
715         pTIFFClose(tiff);
716         goto exit;
717     }
718 
719     This->tiff = tiff;
720     This->stream = pIStream;
721     IStream_AddRef(pIStream);
722     This->initialized = TRUE;
723 
724 exit:
725     LeaveCriticalSection(&This->lock);
726     return hr;
727 }
728 
729 static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
730     GUID *pguidContainerFormat)
731 {
732     if (!pguidContainerFormat) return E_INVALIDARG;
733 
734     memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
735     return S_OK;
736 }
737 
738 static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
739     IWICBitmapDecoderInfo **ppIDecoderInfo)
740 {
741     HRESULT hr;
742     IWICComponentInfo *compinfo;
743 
744     TRACE("(%p,%p)\n", iface, ppIDecoderInfo);
745 
746     hr = CreateComponentInfo(&CLSID_WICTiffDecoder, &compinfo);
747     if (FAILED(hr)) return hr;
748 
749     hr = IWICComponentInfo_QueryInterface(compinfo, &IID_IWICBitmapDecoderInfo,
750         (void**)ppIDecoderInfo);
751 
752     IWICComponentInfo_Release(compinfo);
753 
754     return hr;
755 }
756 
757 static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
758     IWICPalette *palette)
759 {
760     TRACE("(%p,%p)\n", iface, palette);
761     return WINCODEC_ERR_PALETTEUNAVAILABLE;
762 }
763 
764 static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
765     IWICMetadataQueryReader **ppIMetadataQueryReader)
766 {
767     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
768 
769     if (!ppIMetadataQueryReader) return E_INVALIDARG;
770 
771     *ppIMetadataQueryReader = NULL;
772     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
773 }
774 
775 static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface,
776     IWICBitmapSource **ppIBitmapSource)
777 {
778     TRACE("(%p,%p)\n", iface, ppIBitmapSource);
779 
780     if (!ppIBitmapSource) return E_INVALIDARG;
781 
782     *ppIBitmapSource = NULL;
783     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
784 }
785 
786 static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface,
787     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
788 {
789     FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
790     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
791 }
792 
793 static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface,
794     IWICBitmapSource **ppIThumbnail)
795 {
796     TRACE("(%p,%p)\n", iface, ppIThumbnail);
797 
798     if (!ppIThumbnail) return E_INVALIDARG;
799 
800     *ppIThumbnail = NULL;
801     return WINCODEC_ERR_CODECNOTHUMBNAIL;
802 }
803 
804 static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface,
805     UINT *pCount)
806 {
807     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
808 
809     if (!pCount) return E_INVALIDARG;
810 
811     EnterCriticalSection(&This->lock);
812     *pCount = This->tiff ? pTIFFNumberOfDirectories(This->tiff) : 0;
813     LeaveCriticalSection(&This->lock);
814 
815     TRACE("(%p) <-- %i\n", iface, *pCount);
816 
817     return S_OK;
818 }
819 
820 static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface,
821     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
822 {
823     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
824     TiffFrameDecode *result;
825     int res;
826     tiff_decode_info decode_info;
827     HRESULT hr;
828 
829     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
830 
831     if (!This->tiff)
832         return WINCODEC_ERR_FRAMEMISSING;
833 
834     EnterCriticalSection(&This->lock);
835     res = pTIFFSetDirectory(This->tiff, index);
836     if (!res) hr = E_INVALIDARG;
837     else hr = tiff_get_decode_info(This->tiff, &decode_info);
838     LeaveCriticalSection(&This->lock);
839 
840     if (SUCCEEDED(hr))
841     {
842         result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode));
843 
844         if (result)
845         {
846             result->IWICBitmapFrameDecode_iface.lpVtbl = &TiffFrameDecode_Vtbl;
847             result->IWICMetadataBlockReader_iface.lpVtbl = &TiffFrameDecode_BlockVtbl;
848             result->ref = 1;
849             result->parent = This;
850             result->index = index;
851             result->decode_info = decode_info;
852             result->cached_tile_x = -1;
853             result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size);
854 
855             if (result->cached_tile)
856                 *ppIBitmapFrame = &result->IWICBitmapFrameDecode_iface;
857             else
858             {
859                 hr = E_OUTOFMEMORY;
860                 HeapFree(GetProcessHeap(), 0, result);
861             }
862         }
863         else hr = E_OUTOFMEMORY;
864     }
865 
866     if (FAILED(hr)) *ppIBitmapFrame = NULL;
867 
868     return hr;
869 }
870 
871 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = {
872     TiffDecoder_QueryInterface,
873     TiffDecoder_AddRef,
874     TiffDecoder_Release,
875     TiffDecoder_QueryCapability,
876     TiffDecoder_Initialize,
877     TiffDecoder_GetContainerFormat,
878     TiffDecoder_GetDecoderInfo,
879     TiffDecoder_CopyPalette,
880     TiffDecoder_GetMetadataQueryReader,
881     TiffDecoder_GetPreview,
882     TiffDecoder_GetColorContexts,
883     TiffDecoder_GetThumbnail,
884     TiffDecoder_GetFrameCount,
885     TiffDecoder_GetFrame
886 };
887 
888 static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
889     void **ppv)
890 {
891     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
892     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
893 
894     if (!ppv) return E_INVALIDARG;
895 
896     if (IsEqualIID(&IID_IUnknown, iid) ||
897         IsEqualIID(&IID_IWICBitmapSource, iid) ||
898         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
899     {
900         *ppv = &This->IWICBitmapFrameDecode_iface;
901     }
902     else if (IsEqualIID(&IID_IWICMetadataBlockReader, iid))
903     {
904         *ppv = &This->IWICMetadataBlockReader_iface;
905     }
906     else
907     {
908         *ppv = NULL;
909         return E_NOINTERFACE;
910     }
911 
912     IUnknown_AddRef((IUnknown*)*ppv);
913     return S_OK;
914 }
915 
916 static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
917 {
918     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
919     ULONG ref = InterlockedIncrement(&This->ref);
920 
921     TRACE("(%p) refcount=%u\n", iface, ref);
922 
923     return ref;
924 }
925 
926 static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface)
927 {
928     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
929     ULONG ref = InterlockedDecrement(&This->ref);
930 
931     TRACE("(%p) refcount=%u\n", iface, ref);
932 
933     if (ref == 0)
934     {
935         HeapFree(GetProcessHeap(), 0, This->cached_tile);
936         HeapFree(GetProcessHeap(), 0, This);
937     }
938 
939     return ref;
940 }
941 
942 static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
943     UINT *puiWidth, UINT *puiHeight)
944 {
945     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
946 
947     *puiWidth = This->decode_info.width;
948     *puiHeight = This->decode_info.height;
949 
950     TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight);
951 
952     return S_OK;
953 }
954 
955 static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
956     WICPixelFormatGUID *pPixelFormat)
957 {
958     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
959 
960     memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID));
961 
962     TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format));
963 
964     return S_OK;
965 }
966 
967 static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
968     double *pDpiX, double *pDpiY)
969 {
970     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
971 
972     if (This->decode_info.xres == 0 || This->decode_info.yres == 0)
973     {
974         *pDpiX = *pDpiY = 96.0;
975     }
976     else
977     {
978         switch (This->decode_info.resolution_unit)
979         {
980         default:
981             FIXME("unknown resolution unit %i\n", This->decode_info.resolution_unit);
982             /* fall through */
983         case 0: /* Not set */
984         case 1: /* Relative measurements */
985         case 2: /* Inch */
986             *pDpiX = This->decode_info.xres;
987             *pDpiY = This->decode_info.yres;
988             break;
989         case 3: /* Centimeter */
990             *pDpiX = This->decode_info.xres * 2.54;
991             *pDpiY = This->decode_info.yres * 2.54;
992             break;
993         }
994     }
995 
996     TRACE("(%p) <-- %f,%f unit=%i\n", iface, *pDpiX, *pDpiY, This->decode_info.resolution_unit);
997 
998     return S_OK;
999 }
1000 
1001 static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
1002     IWICPalette *pIPalette)
1003 {
1004     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1005     uint16 *red, *green, *blue;
1006     WICColor colors[256];
1007     int color_count, ret, i;
1008 
1009     TRACE("(%p,%p)\n", iface, pIPalette);
1010 
1011     color_count = 1<<This->decode_info.bps;
1012 
1013     EnterCriticalSection(&This->parent->lock);
1014     ret = pTIFFGetField(This->parent->tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
1015     LeaveCriticalSection(&This->parent->lock);
1016 
1017     if (!ret)
1018     {
1019         WARN("Couldn't read color map\n");
1020         return WINCODEC_ERR_PALETTEUNAVAILABLE;
1021     }
1022 
1023     for (i=0; i<color_count; i++)
1024     {
1025         colors[i] = 0xff000000 |
1026             ((red[i]<<8) & 0xff0000) |
1027             (green[i] & 0xff00) |
1028             ((blue[i]>>8) & 0xff);
1029     }
1030 
1031     return IWICPalette_InitializeCustom(pIPalette, colors, color_count);
1032 }
1033 
1034 static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y)
1035 {
1036     tsize_t ret;
1037     int swap_bytes;
1038 
1039     swap_bytes = pTIFFIsByteSwapped(This->parent->tiff);
1040 
1041     ret = pTIFFSetDirectory(This->parent->tiff, This->index);
1042     if (ret == -1)
1043         return E_FAIL;
1044 
1045     if (This->decode_info.tiled)
1046         ret = pTIFFReadEncodedTile(This->parent->tiff, tile_x + tile_y * This->decode_info.tiles_across, This->cached_tile, This->decode_info.tile_size);
1047     else
1048         ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size);
1049 
1050     if (ret == -1)
1051         return E_FAIL;
1052 
1053     /* 3bpp RGB */
1054     if (This->decode_info.source_bpp == 3 && This->decode_info.samples == 3 && This->decode_info.bpp == 24)
1055     {
1056         BYTE *srcdata, *src, *dst;
1057         DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 3 + 7) / 8;
1058 
1059         count = width_bytes * This->decode_info.tile_height;
1060 
1061         srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1062         if (!srcdata) return E_OUTOFMEMORY;
1063         memcpy(srcdata, This->cached_tile, count);
1064 
1065         for (y = 0; y < This->decode_info.tile_height; y++)
1066         {
1067             src = srcdata + y * width_bytes;
1068             dst = This->cached_tile + y * This->decode_info.tile_width * 3;
1069 
1070             for (x = 0; x < This->decode_info.tile_width; x += 8)
1071             {
1072                 dst[2] = (src[0] & 0x80) ? 0xff : 0; /* R */
1073                 dst[1] = (src[0] & 0x40) ? 0xff : 0; /* G */
1074                 dst[0] = (src[0] & 0x20) ? 0xff : 0; /* B */
1075                 if (x + 1 < This->decode_info.tile_width)
1076                 {
1077                     dst[5] = (src[0] & 0x10) ? 0xff : 0; /* R */
1078                     dst[4] = (src[0] & 0x08) ? 0xff : 0; /* G */
1079                     dst[3] = (src[0] & 0x04) ? 0xff : 0; /* B */
1080                 }
1081                 if (x + 2 < This->decode_info.tile_width)
1082                 {
1083                     dst[8] = (src[0] & 0x02) ? 0xff : 0; /* R */
1084                     dst[7] = (src[0] & 0x01) ? 0xff : 0; /* G */
1085                     dst[6]  = (src[1] & 0x80) ? 0xff : 0; /* B */
1086                 }
1087                 if (x + 3 < This->decode_info.tile_width)
1088                 {
1089                     dst[11] = (src[1] & 0x40) ? 0xff : 0; /* R */
1090                     dst[10] = (src[1] & 0x20) ? 0xff : 0; /* G */
1091                     dst[9]  = (src[1] & 0x10) ? 0xff : 0; /* B */
1092                 }
1093                 if (x + 4 < This->decode_info.tile_width)
1094                 {
1095                     dst[14] = (src[1] & 0x08) ? 0xff : 0; /* R */
1096                     dst[13] = (src[1] & 0x04) ? 0xff : 0; /* G */
1097                     dst[12] = (src[1] & 0x02) ? 0xff : 0; /* B */
1098                 }
1099                 if (x + 5 < This->decode_info.tile_width)
1100                 {
1101                     dst[17] = (src[1] & 0x01) ? 0xff : 0; /* R */
1102                     dst[16] = (src[2] & 0x80) ? 0xff : 0; /* G */
1103                     dst[15] = (src[2] & 0x40) ? 0xff : 0; /* B */
1104                 }
1105                 if (x + 6 < This->decode_info.tile_width)
1106                 {
1107                     dst[20] = (src[2] & 0x20) ? 0xff : 0; /* R */
1108                     dst[19] = (src[2] & 0x10) ? 0xff : 0; /* G */
1109                     dst[18] = (src[2] & 0x08) ? 0xff : 0; /* B */
1110                 }
1111                 if (x + 7 < This->decode_info.tile_width)
1112                 {
1113                     dst[23] = (src[2] & 0x04) ? 0xff : 0; /* R */
1114                     dst[22] = (src[2] & 0x02) ? 0xff : 0; /* G */
1115                     dst[21] = (src[2] & 0x01) ? 0xff : 0; /* B */
1116                 }
1117                 src += 3;
1118                 dst += 24;
1119             }
1120         }
1121 
1122         HeapFree(GetProcessHeap(), 0, srcdata);
1123     }
1124     /* 12bpp RGB */
1125     else if (This->decode_info.source_bpp == 12 && This->decode_info.samples == 3 && This->decode_info.bpp == 24)
1126     {
1127         BYTE *srcdata, *src, *dst;
1128         DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 12 + 7) / 8;
1129 
1130         count = width_bytes * This->decode_info.tile_height;
1131 
1132         srcdata = HeapAlloc(GetProcessHeap(), 0, count);
1133         if (!srcdata) return E_OUTOFMEMORY;
1134         memcpy(srcdata, This->cached_tile, count);
1135 
1136         for (y = 0; y < This->decode_info.tile_height; y++)
1137         {
1138             src = srcdata + y * width_bytes;
1139             dst = This->cached_tile + y * This->decode_info.tile_width * 3;
1140 
1141             for (x = 0; x < This->decode_info.tile_width; x += 2)
1142             {
1143                 dst[0] = ((src[1] & 0xf0) >> 4) * 17; /* B */
1144                 dst[1] = (src[0] & 0x0f) * 17; /* G */
1145                 dst[2] = ((src[0] & 0xf0) >> 4) * 17; /* R */
1146                 if (x + 1 < This->decode_info.tile_width)
1147                 {
1148                     dst[5] = (src[1] & 0x0f) * 17; /* B */
1149                     dst[4] = ((src[2] & 0xf0) >> 4) * 17; /* G */
1150                     dst[3] = (src[2] & 0x0f) * 17; /* R */
1151                 }
1152                 src += 3;
1153                 dst += 6;
1154             }
1155         }
1156 
1157         HeapFree(GetProcessHeap(), 0, srcdata);
1158     }
1159     /* 4bpp RGBA */
1160     else if (This->decode_info.source_bpp == 4 && This->decode_info.samples == 4 && This->decode_info.bpp == 32)
1161     {
1162         BYTE *src, *dst;
1163         DWORD count;
1164 
1165         /* 1 source byte expands to 2 BGRA samples */
1166         count = (This->decode_info.tile_width * This->decode_info.tile_height + 1) / 2;
1167 
1168         src = This->cached_tile + count - 1;
1169         dst = This->cached_tile + This->decode_info.tile_size;
1170 
1171         while (count--)
1172         {
1173             BYTE b = *src--;
1174 
1175             dst -= 8;
1176             dst[2] = (b & 0x80) ? 0xff : 0; /* R */
1177             dst[1] = (b & 0x40) ? 0xff : 0; /* G */
1178             dst[0] = (b & 0x20) ? 0xff : 0; /* B */
1179             dst[3] = (b & 0x10) ? 0xff : 0; /* A */
1180             dst[6] = (b & 0x08) ? 0xff : 0; /* R */
1181             dst[5] = (b & 0x04) ? 0xff : 0; /* G */
1182             dst[4] = (b & 0x02) ? 0xff : 0; /* B */
1183             dst[7] = (b & 0x01) ? 0xff : 0; /* A */
1184         }
1185     }
1186     /* 16bpp RGBA */
1187     else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 4 && This->decode_info.bpp == 32)
1188     {
1189         BYTE *src, *dst;
1190         DWORD count = This->decode_info.tile_width * This->decode_info.tile_height;
1191 
1192         src = This->cached_tile + count * 2;
1193         dst = This->cached_tile + This->decode_info.tile_size;
1194 
1195         while (count--)
1196         {
1197             BYTE b[2];
1198 
1199             src -= 2;
1200             dst -= 4;
1201 
1202             b[0] = src[0];
1203             b[1] = src[1];
1204 
1205             dst[0] = ((b[1] & 0xf0) >> 4) * 17; /* B */
1206             dst[1] = (b[0] & 0x0f) * 17; /* G */
1207             dst[2] = ((b[0] & 0xf0) >> 4) * 17; /* R */
1208             dst[3] = (b[1] & 0x0f) * 17; /* A */
1209         }
1210     }
1211     /* 8bpp grayscale with extra alpha */
1212     else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32)
1213     {
1214         BYTE *src;
1215         DWORD *dst, count = This->decode_info.tile_width * This->decode_info.tile_height;
1216 
1217         src = This->cached_tile + This->decode_info.tile_width * This->decode_info.tile_height * 2 - 2;
1218         dst = (DWORD *)(This->cached_tile + This->decode_info.tile_size - 4);
1219 
1220         while (count--)
1221         {
1222             *dst-- = src[0] | (src[0] << 8) | (src[0] << 16) | (src[1] << 24);
1223             src -= 2;
1224         }
1225     }
1226 
1227     if (This->decode_info.reverse_bgr)
1228     {
1229         if (This->decode_info.bps == 8)
1230         {
1231             UINT sample_count = This->decode_info.samples;
1232 
1233             reverse_bgr8(sample_count, This->cached_tile, This->decode_info.tile_width,
1234                 This->decode_info.tile_height, This->decode_info.tile_width * sample_count);
1235         }
1236     }
1237 
1238     if (swap_bytes && This->decode_info.bps > 8)
1239     {
1240         UINT row, i, samples_per_row;
1241         BYTE *sample, temp;
1242 
1243         samples_per_row = This->decode_info.tile_width * This->decode_info.samples;
1244 
1245         switch(This->decode_info.bps)
1246         {
1247         case 16:
1248             for (row=0; row<This->decode_info.tile_height; row++)
1249             {
1250                 sample = This->cached_tile + row * This->decode_info.tile_stride;
1251                 for (i=0; i<samples_per_row; i++)
1252                 {
1253                     temp = sample[1];
1254                     sample[1] = sample[0];
1255                     sample[0] = temp;
1256                     sample += 2;
1257                 }
1258             }
1259             break;
1260         default:
1261             ERR("unhandled bps for byte swap %u\n", This->decode_info.bps);
1262             return E_FAIL;
1263         }
1264     }
1265 
1266     if (This->decode_info.invert_grayscale)
1267     {
1268         BYTE *byte, *end;
1269 
1270         if (This->decode_info.samples != 1)
1271         {
1272             ERR("cannot invert grayscale image with %u samples\n", This->decode_info.samples);
1273             return E_FAIL;
1274         }
1275 
1276         end = This->cached_tile+This->decode_info.tile_size;
1277 
1278         for (byte = This->cached_tile; byte != end; byte++)
1279             *byte = ~(*byte);
1280     }
1281 
1282     This->cached_tile_x = tile_x;
1283     This->cached_tile_y = tile_y;
1284 
1285     return S_OK;
1286 }
1287 
1288 static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
1289     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
1290 {
1291     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1292     UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y;
1293     UINT tile_x, tile_y;
1294     WICRect rc;
1295     HRESULT hr=S_OK;
1296     BYTE *dst_tilepos;
1297     UINT bytesperrow;
1298     WICRect rect;
1299 
1300     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
1301 
1302     if (!prc)
1303     {
1304         rect.X = 0;
1305         rect.Y = 0;
1306         rect.Width = This->decode_info.width;
1307         rect.Height = This->decode_info.height;
1308         prc = &rect;
1309     }
1310     else
1311     {
1312         if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width ||
1313             prc->Y+prc->Height > This->decode_info.height)
1314             return E_INVALIDARG;
1315     }
1316 
1317     bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8;
1318 
1319     if (cbStride < bytesperrow)
1320         return E_INVALIDARG;
1321 
1322     if ((cbStride * (prc->Height-1)) + ((prc->Width * This->decode_info.bpp) + 7)/8 > cbBufferSize)
1323         return E_INVALIDARG;
1324 
1325     min_tile_x = prc->X / This->decode_info.tile_width;
1326     min_tile_y = prc->Y / This->decode_info.tile_height;
1327     max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width;
1328     max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height;
1329 
1330     EnterCriticalSection(&This->parent->lock);
1331 
1332     for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++)
1333     {
1334         for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++)
1335         {
1336             if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y)
1337             {
1338                 hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y);
1339             }
1340 
1341             if (SUCCEEDED(hr))
1342             {
1343                 if (prc->X < tile_x * This->decode_info.tile_width)
1344                     rc.X = 0;
1345                 else
1346                     rc.X = prc->X - tile_x * This->decode_info.tile_width;
1347 
1348                 if (prc->Y < tile_y * This->decode_info.tile_height)
1349                     rc.Y = 0;
1350                 else
1351                     rc.Y = prc->Y - tile_y * This->decode_info.tile_height;
1352 
1353                 if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width)
1354                     rc.Width = This->decode_info.tile_width - rc.X;
1355                 else if (prc->X < tile_x * This->decode_info.tile_width)
1356                     rc.Width = prc->Width + prc->X - tile_x * This->decode_info.tile_width;
1357                 else
1358                     rc.Width = prc->Width;
1359 
1360                 if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height)
1361                     rc.Height = This->decode_info.tile_height - rc.Y;
1362                 else if (prc->Y < tile_y * This->decode_info.tile_height)
1363                     rc.Height = prc->Height + prc->Y - tile_y * This->decode_info.tile_height;
1364                 else
1365                     rc.Height = prc->Height;
1366 
1367                 dst_tilepos = pbBuffer + (cbStride * ((rc.Y + tile_y * This->decode_info.tile_height) - prc->Y)) +
1368                     ((This->decode_info.bpp * ((rc.X + tile_x * This->decode_info.tile_width) - prc->X) + 7) / 8);
1369 
1370                 hr = copy_pixels(This->decode_info.bpp, This->cached_tile,
1371                     This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride,
1372                     &rc, cbStride, cbBufferSize, dst_tilepos);
1373             }
1374 
1375             if (FAILED(hr))
1376             {
1377                 LeaveCriticalSection(&This->parent->lock);
1378                 TRACE("<-- 0x%x\n", hr);
1379                 return hr;
1380             }
1381         }
1382     }
1383 
1384     LeaveCriticalSection(&This->parent->lock);
1385 
1386     return S_OK;
1387 }
1388 
1389 static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
1390     IWICMetadataQueryReader **ppIMetadataQueryReader)
1391 {
1392     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1393 
1394     TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader);
1395 
1396     if (!ppIMetadataQueryReader)
1397         return E_INVALIDARG;
1398 
1399     return MetadataQueryReader_CreateInstance(&This->IWICMetadataBlockReader_iface, NULL, ppIMetadataQueryReader);
1400 }
1401 
1402 static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
1403     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
1404 {
1405     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
1406     const BYTE *profile;
1407     UINT len;
1408     HRESULT hr;
1409 
1410     TRACE("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
1411 
1412     EnterCriticalSection(&This->parent->lock);
1413 
1414     if (pTIFFGetField(This->parent->tiff, TIFFTAG_ICCPROFILE, &len, &profile))
1415     {
1416         if (cCount && ppIColorContexts)
1417         {
1418             hr = IWICColorContext_InitializeFromMemory(*ppIColorContexts, profile, len);
1419             if (FAILED(hr))
1420             {
1421                 LeaveCriticalSection(&This->parent->lock);
1422                 return hr;
1423             }
1424         }
1425         *pcActualCount = 1;
1426     }
1427     else
1428         *pcActualCount = 0;
1429 
1430     LeaveCriticalSection(&This->parent->lock);
1431 
1432     return S_OK;
1433 }
1434 
1435 static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
1436     IWICBitmapSource **ppIThumbnail)
1437 {
1438     TRACE("(%p,%p)\n", iface, ppIThumbnail);
1439 
1440     if (!ppIThumbnail) return E_INVALIDARG;
1441 
1442     *ppIThumbnail = NULL;
1443     return WINCODEC_ERR_CODECNOTHUMBNAIL;
1444 }
1445 
1446 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = {
1447     TiffFrameDecode_QueryInterface,
1448     TiffFrameDecode_AddRef,
1449     TiffFrameDecode_Release,
1450     TiffFrameDecode_GetSize,
1451     TiffFrameDecode_GetPixelFormat,
1452     TiffFrameDecode_GetResolution,
1453     TiffFrameDecode_CopyPalette,
1454     TiffFrameDecode_CopyPixels,
1455     TiffFrameDecode_GetMetadataQueryReader,
1456     TiffFrameDecode_GetColorContexts,
1457     TiffFrameDecode_GetThumbnail
1458 };
1459 
1460 static HRESULT WINAPI TiffFrameDecode_Block_QueryInterface(IWICMetadataBlockReader *iface,
1461     REFIID iid, void **ppv)
1462 {
1463     TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1464     return IWICBitmapFrameDecode_QueryInterface(&This->IWICBitmapFrameDecode_iface, iid, ppv);
1465 }
1466 
1467 static ULONG WINAPI TiffFrameDecode_Block_AddRef(IWICMetadataBlockReader *iface)
1468 {
1469     TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1470     return IWICBitmapFrameDecode_AddRef(&This->IWICBitmapFrameDecode_iface);
1471 }
1472 
1473 static ULONG WINAPI TiffFrameDecode_Block_Release(IWICMetadataBlockReader *iface)
1474 {
1475     TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1476     return IWICBitmapFrameDecode_Release(&This->IWICBitmapFrameDecode_iface);
1477 }
1478 
1479 static HRESULT WINAPI TiffFrameDecode_Block_GetContainerFormat(IWICMetadataBlockReader *iface,
1480     GUID *guid)
1481 {
1482     TRACE("(%p,%p)\n", iface, guid);
1483 
1484     if (!guid) return E_INVALIDARG;
1485 
1486     *guid = GUID_ContainerFormatTiff;
1487     return S_OK;
1488 }
1489 
1490 static HRESULT WINAPI TiffFrameDecode_Block_GetCount(IWICMetadataBlockReader *iface,
1491     UINT *count)
1492 {
1493     TRACE("%p,%p\n", iface, count);
1494 
1495     if (!count) return E_INVALIDARG;
1496 
1497     *count = 1;
1498     return S_OK;
1499 }
1500 
1501 static HRESULT create_metadata_reader(TiffFrameDecode *This, IWICMetadataReader **reader)
1502 {
1503     HRESULT hr;
1504     LARGE_INTEGER dir_offset;
1505     IWICMetadataReader *metadata_reader;
1506     IWICPersistStream *persist;
1507 
1508     /* FIXME: Use IWICComponentFactory_CreateMetadataReader once it's implemented */
1509 
1510     hr = IfdMetadataReader_CreateInstance(&IID_IWICMetadataReader, (void **)&metadata_reader);
1511     if (FAILED(hr)) return hr;
1512 
1513     hr = IWICMetadataReader_QueryInterface(metadata_reader, &IID_IWICPersistStream, (void **)&persist);
1514     if (FAILED(hr))
1515     {
1516         IWICMetadataReader_Release(metadata_reader);
1517         return hr;
1518     }
1519 
1520     EnterCriticalSection(&This->parent->lock);
1521 
1522     dir_offset.QuadPart = pTIFFCurrentDirOffset(This->parent->tiff);
1523     hr = IStream_Seek(This->parent->stream, dir_offset, STREAM_SEEK_SET, NULL);
1524     if (SUCCEEDED(hr))
1525     {
1526         BOOL byte_swapped = pTIFFIsByteSwapped(This->parent->tiff);
1527 #ifdef WORDS_BIGENDIAN
1528         DWORD persist_options = byte_swapped ? WICPersistOptionLittleEndian : WICPersistOptionBigEndian;
1529 #else
1530         DWORD persist_options = byte_swapped ? WICPersistOptionBigEndian : WICPersistOptionLittleEndian;
1531 #endif
1532         persist_options |= WICPersistOptionNoCacheStream;
1533         hr = IWICPersistStream_LoadEx(persist, This->parent->stream, NULL, persist_options);
1534         if (FAILED(hr))
1535             ERR("IWICPersistStream_LoadEx error %#x\n", hr);
1536     }
1537 
1538     LeaveCriticalSection(&This->parent->lock);
1539 
1540     IWICPersistStream_Release(persist);
1541 
1542     if (FAILED(hr))
1543     {
1544         IWICMetadataReader_Release(metadata_reader);
1545         return hr;
1546     }
1547 
1548     *reader = metadata_reader;
1549     return S_OK;
1550 }
1551 
1552 static HRESULT WINAPI TiffFrameDecode_Block_GetReaderByIndex(IWICMetadataBlockReader *iface,
1553     UINT index, IWICMetadataReader **reader)
1554 {
1555     TiffFrameDecode *This = impl_from_IWICMetadataBlockReader(iface);
1556 
1557     TRACE("(%p,%u,%p)\n", iface, index, reader);
1558 
1559     if (!reader || index != 0) return E_INVALIDARG;
1560 
1561     return create_metadata_reader(This, reader);
1562 }
1563 
1564 static HRESULT WINAPI TiffFrameDecode_Block_GetEnumerator(IWICMetadataBlockReader *iface,
1565     IEnumUnknown **enum_metadata)
1566 {
1567     FIXME("(%p,%p): stub\n", iface, enum_metadata);
1568     return E_NOTIMPL;
1569 }
1570 
1571 static const IWICMetadataBlockReaderVtbl TiffFrameDecode_BlockVtbl =
1572 {
1573     TiffFrameDecode_Block_QueryInterface,
1574     TiffFrameDecode_Block_AddRef,
1575     TiffFrameDecode_Block_Release,
1576     TiffFrameDecode_Block_GetContainerFormat,
1577     TiffFrameDecode_Block_GetCount,
1578     TiffFrameDecode_Block_GetReaderByIndex,
1579     TiffFrameDecode_Block_GetEnumerator
1580 };
1581 
1582 HRESULT TiffDecoder_CreateInstance(REFIID iid, void** ppv)
1583 {
1584     HRESULT ret;
1585     TiffDecoder *This;
1586 
1587     TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
1588 
1589     *ppv = NULL;
1590 
1591     if (!load_libtiff())
1592     {
1593         ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF);
1594         return E_FAIL;
1595     }
1596 
1597     This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder));
1598     if (!This) return E_OUTOFMEMORY;
1599 
1600     This->IWICBitmapDecoder_iface.lpVtbl = &TiffDecoder_Vtbl;
1601     This->ref = 1;
1602     This->stream = NULL;
1603     InitializeCriticalSection(&This->lock);
1604     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock");
1605     This->tiff = NULL;
1606     This->initialized = FALSE;
1607 
1608     ret = IWICBitmapDecoder_QueryInterface(&This->IWICBitmapDecoder_iface, iid, ppv);
1609     IWICBitmapDecoder_Release(&This->IWICBitmapDecoder_iface);
1610 
1611     return ret;
1612 }
1613 
1614 struct tiff_encode_format {
1615     const WICPixelFormatGUID *guid;
1616     int photometric;
1617     int bps;
1618     int samples;
1619     int bpp;
1620     int extra_sample;
1621     int extra_sample_type;
1622     int reverse_bgr;
1623 };
1624 
1625 static const struct tiff_encode_format formats[] = {
1626     {&GUID_WICPixelFormat24bppBGR, 2, 8, 3, 24, 0, 0, 1},
1627     {&GUID_WICPixelFormat24bppRGB, 2, 8, 3, 24, 0, 0, 0},
1628     {&GUID_WICPixelFormatBlackWhite, 1, 1, 1, 1, 0, 0, 0},
1629     {&GUID_WICPixelFormat4bppGray, 1, 4, 1, 4, 0, 0, 0},
1630     {&GUID_WICPixelFormat8bppGray, 1, 8, 1, 8, 0, 0, 0},
1631     {&GUID_WICPixelFormat32bppBGRA, 2, 8, 4, 32, 1, 2, 1},
1632     {&GUID_WICPixelFormat32bppPBGRA, 2, 8, 4, 32, 1, 1, 1},
1633     {&GUID_WICPixelFormat48bppRGB, 2, 16, 3, 48, 0, 0, 0},
1634     {&GUID_WICPixelFormat64bppRGBA, 2, 16, 4, 64, 1, 2, 0},
1635     {&GUID_WICPixelFormat64bppPRGBA, 2, 16, 4, 64, 1, 1, 0},
1636     {&GUID_WICPixelFormat1bppIndexed, 3, 1, 1, 1, 0, 0, 0},
1637     {&GUID_WICPixelFormat2bppIndexed, 3, 2, 1, 2, 0, 0, 0},
1638     {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0},
1639     {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0},
1640     {0}
1641 };
1642 
1643 typedef struct TiffEncoder {
1644     IWICBitmapEncoder IWICBitmapEncoder_iface;
1645     LONG ref;
1646     IStream *stream;
1647     CRITICAL_SECTION lock; /* Must be held when tiff is used or fields below are set */
1648     TIFF *tiff;
1649     BOOL initialized;
1650     BOOL committed;
1651     ULONG num_frames;
1652     ULONG num_frames_committed;
1653 } TiffEncoder;
1654 
1655 static inline TiffEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
1656 {
1657     return CONTAINING_RECORD(iface, TiffEncoder, IWICBitmapEncoder_iface);
1658 }
1659 
1660 typedef struct TiffFrameEncode {
1661     IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
1662     LONG ref;
1663     TiffEncoder *parent;
1664     /* fields below are protected by parent->lock */
1665     BOOL initialized;
1666     BOOL info_written;
1667     BOOL committed;
1668     const struct tiff_encode_format *format;
1669     UINT width, height;
1670     double xres, yres;
1671     UINT lines_written;
1672     WICColor palette[256];
1673     UINT colors;
1674 } TiffFrameEncode;
1675 
1676 static inline TiffFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
1677 {
1678     return CONTAINING_RECORD(iface, TiffFrameEncode, IWICBitmapFrameEncode_iface);
1679 }
1680 
1681 static HRESULT WINAPI TiffFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
1682     void **ppv)
1683 {
1684     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1685     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
1686 
1687     if (!ppv) return E_INVALIDARG;
1688 
1689     if (IsEqualIID(&IID_IUnknown, iid) ||
1690         IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
1691     {
1692         *ppv = &This->IWICBitmapFrameEncode_iface;
1693     }
1694     else
1695     {
1696         *ppv = NULL;
1697         return E_NOINTERFACE;
1698     }
1699 
1700     IUnknown_AddRef((IUnknown*)*ppv);
1701     return S_OK;
1702 }
1703 
1704 static ULONG WINAPI TiffFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
1705 {
1706     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1707     ULONG ref = InterlockedIncrement(&This->ref);
1708 
1709     TRACE("(%p) refcount=%u\n", iface, ref);
1710 
1711     return ref;
1712 }
1713 
1714 static ULONG WINAPI TiffFrameEncode_Release(IWICBitmapFrameEncode *iface)
1715 {
1716     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1717     ULONG ref = InterlockedDecrement(&This->ref);
1718 
1719     TRACE("(%p) refcount=%u\n", iface, ref);
1720 
1721     if (ref == 0)
1722     {
1723         IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
1724         HeapFree(GetProcessHeap(), 0, This);
1725     }
1726 
1727     return ref;
1728 }
1729 
1730 static HRESULT WINAPI TiffFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
1731     IPropertyBag2 *pIEncoderOptions)
1732 {
1733     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1734     TRACE("(%p,%p)\n", iface, pIEncoderOptions);
1735 
1736     EnterCriticalSection(&This->parent->lock);
1737 
1738     if (This->initialized)
1739     {
1740         LeaveCriticalSection(&This->parent->lock);
1741         return WINCODEC_ERR_WRONGSTATE;
1742     }
1743 
1744     This->initialized = TRUE;
1745 
1746     LeaveCriticalSection(&This->parent->lock);
1747 
1748     return S_OK;
1749 }
1750 
1751 static HRESULT WINAPI TiffFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
1752     UINT uiWidth, UINT uiHeight)
1753 {
1754     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1755     TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
1756 
1757     EnterCriticalSection(&This->parent->lock);
1758 
1759     if (!This->initialized || This->info_written)
1760     {
1761         LeaveCriticalSection(&This->parent->lock);
1762         return WINCODEC_ERR_WRONGSTATE;
1763     }
1764 
1765     This->width = uiWidth;
1766     This->height = uiHeight;
1767 
1768     LeaveCriticalSection(&This->parent->lock);
1769 
1770     return S_OK;
1771 }
1772 
1773 static HRESULT WINAPI TiffFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
1774     double dpiX, double dpiY)
1775 {
1776     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1777     TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
1778 
1779     EnterCriticalSection(&This->parent->lock);
1780 
1781     if (!This->initialized || This->info_written)
1782     {
1783         LeaveCriticalSection(&This->parent->lock);
1784         return WINCODEC_ERR_WRONGSTATE;
1785     }
1786 
1787     This->xres = dpiX;
1788     This->yres = dpiY;
1789 
1790     LeaveCriticalSection(&This->parent->lock);
1791 
1792     return S_OK;
1793 }
1794 
1795 static HRESULT WINAPI TiffFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
1796     WICPixelFormatGUID *pPixelFormat)
1797 {
1798     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1799     int i;
1800 
1801     TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
1802 
1803     EnterCriticalSection(&This->parent->lock);
1804 
1805     if (!This->initialized || This->info_written)
1806     {
1807         LeaveCriticalSection(&This->parent->lock);
1808         return WINCODEC_ERR_WRONGSTATE;
1809     }
1810 
1811     for (i=0; formats[i].guid; i++)
1812     {
1813         if (memcmp(formats[i].guid, pPixelFormat, sizeof(GUID)) == 0)
1814             break;
1815     }
1816 
1817     if (!formats[i].guid) i = 0;
1818 
1819     This->format = &formats[i];
1820     memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
1821 
1822     LeaveCriticalSection(&This->parent->lock);
1823 
1824     return S_OK;
1825 }
1826 
1827 static HRESULT WINAPI TiffFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
1828     UINT cCount, IWICColorContext **ppIColorContext)
1829 {
1830     FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
1831     return E_NOTIMPL;
1832 }
1833 
1834 static HRESULT WINAPI TiffFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
1835     IWICPalette *palette)
1836 {
1837     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1838     HRESULT hr;
1839 
1840     TRACE("(%p,%p)\n", iface, palette);
1841 
1842     if (!palette) return E_INVALIDARG;
1843 
1844     EnterCriticalSection(&This->parent->lock);
1845 
1846     if (This->initialized)
1847         hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
1848     else
1849         hr = WINCODEC_ERR_NOTINITIALIZED;
1850 
1851     LeaveCriticalSection(&This->parent->lock);
1852     return hr;
1853 }
1854 
1855 static HRESULT WINAPI TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
1856     IWICBitmapSource *pIThumbnail)
1857 {
1858     FIXME("(%p,%p): stub\n", iface, pIThumbnail);
1859     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
1860 }
1861 
1862 static HRESULT WINAPI TiffFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
1863     UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
1864 {
1865     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1866     BYTE *row_data, *swapped_data = NULL;
1867     UINT i, j, line_size;
1868 
1869     TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
1870 
1871     EnterCriticalSection(&This->parent->lock);
1872 
1873     if (!This->initialized || !This->width || !This->height || !This->format)
1874     {
1875         LeaveCriticalSection(&This->parent->lock);
1876         return WINCODEC_ERR_WRONGSTATE;
1877     }
1878 
1879     if (lineCount == 0 || lineCount + This->lines_written > This->height)
1880     {
1881         LeaveCriticalSection(&This->parent->lock);
1882         return E_INVALIDARG;
1883     }
1884 
1885     line_size = ((This->width * This->format->bpp)+7)/8;
1886 
1887     if (This->format->reverse_bgr)
1888     {
1889         swapped_data = HeapAlloc(GetProcessHeap(), 0, line_size);
1890         if (!swapped_data)
1891         {
1892             LeaveCriticalSection(&This->parent->lock);
1893             return E_OUTOFMEMORY;
1894         }
1895     }
1896 
1897     if (!This->info_written)
1898     {
1899         pTIFFSetField(This->parent->tiff, TIFFTAG_PHOTOMETRIC, (uint16)This->format->photometric);
1900         pTIFFSetField(This->parent->tiff, TIFFTAG_PLANARCONFIG, (uint16)1);
1901         pTIFFSetField(This->parent->tiff, TIFFTAG_BITSPERSAMPLE, (uint16)This->format->bps);
1902         pTIFFSetField(This->parent->tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)This->format->samples);
1903 
1904         if (This->format->extra_sample)
1905         {
1906             uint16 extra_samples;
1907             extra_samples = This->format->extra_sample_type;
1908 
1909             pTIFFSetField(This->parent->tiff, TIFFTAG_EXTRASAMPLES, (uint16)1, &extra_samples);
1910         }
1911 
1912         pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGEWIDTH, (uint32)This->width);
1913         pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGELENGTH, (uint32)This->height);
1914 
1915         if (This->xres != 0.0 && This->yres != 0.0)
1916         {
1917             pTIFFSetField(This->parent->tiff, TIFFTAG_RESOLUTIONUNIT, (uint16)2); /* Inch */
1918             pTIFFSetField(This->parent->tiff, TIFFTAG_XRESOLUTION, (float)This->xres);
1919             pTIFFSetField(This->parent->tiff, TIFFTAG_YRESOLUTION, (float)This->yres);
1920         }
1921 
1922         if (This->format->bpp <= 8 && This->colors && !IsEqualGUID(This->format->guid, &GUID_WICPixelFormatBlackWhite))
1923         {
1924             uint16 red[256], green[256], blue[256];
1925             UINT i;
1926 
1927             for (i = 0; i < This->colors; i++)
1928             {
1929                 red[i] = (This->palette[i] >> 8) & 0xff00;
1930                 green[i] = This->palette[i] & 0xff00;
1931                 blue[i] = (This->palette[i] << 8) & 0xff00;
1932             }
1933 
1934             pTIFFSetField(This->parent->tiff, TIFFTAG_COLORMAP, red, green, blue);
1935         }
1936 
1937         This->info_written = TRUE;
1938     }
1939 
1940     for (i=0; i<lineCount; i++)
1941     {
1942         row_data = pbPixels + i * cbStride;
1943 
1944         if (This->format->reverse_bgr && This->format->bps == 8)
1945         {
1946             memcpy(swapped_data, row_data, line_size);
1947             for (j=0; j<line_size; j += This->format->samples)
1948             {
1949                 BYTE temp;
1950                 temp = swapped_data[j];
1951                 swapped_data[j] = swapped_data[j+2];
1952                 swapped_data[j+2] = temp;
1953             }
1954             row_data = swapped_data;
1955         }
1956 
1957         pTIFFWriteScanline(This->parent->tiff, (tdata_t)row_data, i+This->lines_written, 0);
1958     }
1959 
1960     This->lines_written += lineCount;
1961 
1962     LeaveCriticalSection(&This->parent->lock);
1963 
1964     HeapFree(GetProcessHeap(), 0, swapped_data);
1965 
1966     return S_OK;
1967 }
1968 
1969 static HRESULT WINAPI TiffFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
1970     IWICBitmapSource *pIBitmapSource, WICRect *prc)
1971 {
1972     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1973     HRESULT hr;
1974 
1975     TRACE("(%p,%p,%p)\n", iface, pIBitmapSource, prc);
1976 
1977     if (!This->initialized)
1978         return WINCODEC_ERR_WRONGSTATE;
1979 
1980     hr = configure_write_source(iface, pIBitmapSource, prc,
1981         This->format ? This->format->guid : NULL, This->width, This->height,
1982         This->xres, This->yres);
1983 
1984     if (SUCCEEDED(hr))
1985     {
1986         hr = write_source(iface, pIBitmapSource, prc,
1987             This->format->guid, This->format->bpp, This->width, This->height);
1988     }
1989 
1990     return hr;
1991 }
1992 
1993 static HRESULT WINAPI TiffFrameEncode_Commit(IWICBitmapFrameEncode *iface)
1994 {
1995     TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
1996 
1997     TRACE("(%p)\n", iface);
1998 
1999     EnterCriticalSection(&This->parent->lock);
2000 
2001     if (!This->info_written || This->lines_written != This->height || This->committed)
2002     {
2003         LeaveCriticalSection(&This->parent->lock);
2004         return WINCODEC_ERR_WRONGSTATE;
2005     }
2006 
2007     /* libtiff will commit the data when creating a new frame or closing the file */
2008 
2009     This->committed = TRUE;
2010     This->parent->num_frames_committed++;
2011 
2012     LeaveCriticalSection(&This->parent->lock);
2013 
2014     return S_OK;
2015 }
2016 
2017 static HRESULT WINAPI TiffFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
2018     IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2019 {
2020     FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
2021     return E_NOTIMPL;
2022 }
2023 
2024 static const IWICBitmapFrameEncodeVtbl TiffFrameEncode_Vtbl = {
2025     TiffFrameEncode_QueryInterface,
2026     TiffFrameEncode_AddRef,
2027     TiffFrameEncode_Release,
2028     TiffFrameEncode_Initialize,
2029     TiffFrameEncode_SetSize,
2030     TiffFrameEncode_SetResolution,
2031     TiffFrameEncode_SetPixelFormat,
2032     TiffFrameEncode_SetColorContexts,
2033     TiffFrameEncode_SetPalette,
2034     TiffFrameEncode_SetThumbnail,
2035     TiffFrameEncode_WritePixels,
2036     TiffFrameEncode_WriteSource,
2037     TiffFrameEncode_Commit,
2038     TiffFrameEncode_GetMetadataQueryWriter
2039 };
2040 
2041 static HRESULT WINAPI TiffEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
2042     void **ppv)
2043 {
2044     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2045     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2046 
2047     if (!ppv) return E_INVALIDARG;
2048 
2049     if (IsEqualIID(&IID_IUnknown, iid) ||
2050         IsEqualIID(&IID_IWICBitmapEncoder, iid))
2051     {
2052         *ppv = &This->IWICBitmapEncoder_iface;
2053     }
2054     else
2055     {
2056         *ppv = NULL;
2057         return E_NOINTERFACE;
2058     }
2059 
2060     IUnknown_AddRef((IUnknown*)*ppv);
2061     return S_OK;
2062 }
2063 
2064 static ULONG WINAPI TiffEncoder_AddRef(IWICBitmapEncoder *iface)
2065 {
2066     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2067     ULONG ref = InterlockedIncrement(&This->ref);
2068 
2069     TRACE("(%p) refcount=%u\n", iface, ref);
2070 
2071     return ref;
2072 }
2073 
2074 static ULONG WINAPI TiffEncoder_Release(IWICBitmapEncoder *iface)
2075 {
2076     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2077     ULONG ref = InterlockedDecrement(&This->ref);
2078 
2079     TRACE("(%p) refcount=%u\n", iface, ref);
2080 
2081     if (ref == 0)
2082     {
2083         if (This->tiff) pTIFFClose(This->tiff);
2084         if (This->stream) IStream_Release(This->stream);
2085         This->lock.DebugInfo->Spare[0] = 0;
2086         DeleteCriticalSection(&This->lock);
2087         HeapFree(GetProcessHeap(), 0, This);
2088     }
2089 
2090     return ref;
2091 }
2092 
2093 static HRESULT WINAPI TiffEncoder_Initialize(IWICBitmapEncoder *iface,
2094     IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
2095 {
2096     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2097     TIFF *tiff;
2098     HRESULT hr=S_OK;
2099 
2100     TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
2101 
2102     EnterCriticalSection(&This->lock);
2103 
2104     if (This->initialized || This->committed)
2105     {
2106         hr = WINCODEC_ERR_WRONGSTATE;
2107         goto exit;
2108     }
2109 
2110     tiff = tiff_open_stream(pIStream, "w");
2111 
2112     if (!tiff)
2113     {
2114         hr = E_FAIL;
2115         goto exit;
2116     }
2117 
2118     This->tiff = tiff;
2119     This->stream = pIStream;
2120     IStream_AddRef(pIStream);
2121     This->initialized = TRUE;
2122 
2123 exit:
2124     LeaveCriticalSection(&This->lock);
2125     return hr;
2126 }
2127 
2128 static HRESULT WINAPI TiffEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
2129     GUID *pguidContainerFormat)
2130 {
2131     memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
2132     return S_OK;
2133 }
2134 
2135 static HRESULT WINAPI TiffEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
2136 {
2137     IWICComponentInfo *comp_info;
2138     HRESULT hr;
2139 
2140     TRACE("%p,%p\n", iface, info);
2141 
2142     if (!info) return E_INVALIDARG;
2143 
2144     hr = CreateComponentInfo(&CLSID_WICTiffEncoder, &comp_info);
2145     if (hr == S_OK)
2146     {
2147         hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
2148         IWICComponentInfo_Release(comp_info);
2149     }
2150     return hr;
2151 }
2152 
2153 static HRESULT WINAPI TiffEncoder_SetColorContexts(IWICBitmapEncoder *iface,
2154     UINT cCount, IWICColorContext **ppIColorContext)
2155 {
2156     FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
2157     return E_NOTIMPL;
2158 }
2159 
2160 static HRESULT WINAPI TiffEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
2161 {
2162     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2163     HRESULT hr;
2164 
2165     TRACE("(%p,%p)\n", iface, palette);
2166 
2167     EnterCriticalSection(&This->lock);
2168 
2169     hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
2170 
2171     LeaveCriticalSection(&This->lock);
2172 
2173     return hr;
2174 }
2175 
2176 static HRESULT WINAPI TiffEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
2177 {
2178     TRACE("(%p,%p)\n", iface, pIThumbnail);
2179     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
2180 }
2181 
2182 static HRESULT WINAPI TiffEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
2183 {
2184     TRACE("(%p,%p)\n", iface, pIPreview);
2185     return WINCODEC_ERR_UNSUPPORTEDOPERATION;
2186 }
2187 
2188 static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
2189     IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
2190 {
2191     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2192     TiffFrameEncode *result;
2193     static const PROPBAG2 opts[2] =
2194     {
2195         { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTiffCompressionMethod },
2196         { PROPBAG2_TYPE_DATA, VT_R4,  0, 0, (LPOLESTR)wszCompressionQuality },
2197     };
2198     HRESULT hr=S_OK;
2199 
2200     TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
2201 
2202     EnterCriticalSection(&This->lock);
2203 
2204     if (!This->initialized || This->committed)
2205     {
2206         hr = WINCODEC_ERR_WRONGSTATE;
2207     }
2208     else if (This->num_frames != This->num_frames_committed)
2209     {
2210         FIXME("New frame created before previous frame was committed\n");
2211         hr = E_FAIL;
2212     }
2213 
2214     if (ppIEncoderOptions && SUCCEEDED(hr))
2215     {
2216         hr = CreatePropertyBag2(opts, sizeof(opts)/sizeof(opts[0]), ppIEncoderOptions);
2217         if (SUCCEEDED(hr))
2218         {
2219             VARIANT v;
2220             VariantInit(&v);
2221             V_VT(&v) = VT_UI1;
2222             V_UI1(&v) = WICTiffCompressionDontCare;
2223             hr = IPropertyBag2_Write(*ppIEncoderOptions, 1, (PROPBAG2 *)opts, &v);
2224             VariantClear(&v);
2225             if (FAILED(hr))
2226             {
2227                 IPropertyBag2_Release(*ppIEncoderOptions);
2228                 *ppIEncoderOptions = NULL;
2229             }
2230         }
2231     }
2232 
2233     if (SUCCEEDED(hr))
2234     {
2235         result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result));
2236 
2237         if (result)
2238         {
2239             result->IWICBitmapFrameEncode_iface.lpVtbl = &TiffFrameEncode_Vtbl;
2240             result->ref = 1;
2241             result->parent = This;
2242             result->initialized = FALSE;
2243             result->info_written = FALSE;
2244             result->committed = FALSE;
2245             result->format = NULL;
2246             result->width = 0;
2247             result->height = 0;
2248             result->xres = 0.0;
2249             result->yres = 0.0;
2250             result->lines_written = 0;
2251             result->colors = 0;
2252 
2253             IWICBitmapEncoder_AddRef(iface);
2254             *ppIFrameEncode = &result->IWICBitmapFrameEncode_iface;
2255 
2256             if (This->num_frames != 0)
2257                 pTIFFWriteDirectory(This->tiff);
2258 
2259             This->num_frames++;
2260         }
2261         else
2262             hr = E_OUTOFMEMORY;
2263 
2264         if (FAILED(hr))
2265         {
2266             IPropertyBag2_Release(*ppIEncoderOptions);
2267             *ppIEncoderOptions = NULL;
2268         }
2269     }
2270 
2271     LeaveCriticalSection(&This->lock);
2272 
2273     return hr;
2274 }
2275 
2276 static HRESULT WINAPI TiffEncoder_Commit(IWICBitmapEncoder *iface)
2277 {
2278     TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
2279 
2280     TRACE("(%p)\n", iface);
2281 
2282     EnterCriticalSection(&This->lock);
2283 
2284     if (!This->initialized || This->committed)
2285     {
2286         LeaveCriticalSection(&This->lock);
2287         return WINCODEC_ERR_WRONGSTATE;
2288     }
2289 
2290     pTIFFClose(This->tiff);
2291     IStream_Release(This->stream);
2292     This->stream = NULL;
2293     This->tiff = NULL;
2294 
2295     This->committed = TRUE;
2296 
2297     LeaveCriticalSection(&This->lock);
2298 
2299     return S_OK;
2300 }
2301 
2302 static HRESULT WINAPI TiffEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
2303     IWICMetadataQueryWriter **ppIMetadataQueryWriter)
2304 {
2305     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
2306     return E_NOTIMPL;
2307 }
2308 
2309 static const IWICBitmapEncoderVtbl TiffEncoder_Vtbl = {
2310     TiffEncoder_QueryInterface,
2311     TiffEncoder_AddRef,
2312     TiffEncoder_Release,
2313     TiffEncoder_Initialize,
2314     TiffEncoder_GetContainerFormat,
2315     TiffEncoder_GetEncoderInfo,
2316     TiffEncoder_SetColorContexts,
2317     TiffEncoder_SetPalette,
2318     TiffEncoder_SetThumbnail,
2319     TiffEncoder_SetPreview,
2320     TiffEncoder_CreateNewFrame,
2321     TiffEncoder_Commit,
2322     TiffEncoder_GetMetadataQueryWriter
2323 };
2324 
2325 HRESULT TiffEncoder_CreateInstance(REFIID iid, void** ppv)
2326 {
2327     TiffEncoder *This;
2328     HRESULT ret;
2329 
2330     TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
2331 
2332     *ppv = NULL;
2333 
2334     if (!load_libtiff())
2335     {
2336         ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF);
2337         return E_FAIL;
2338     }
2339 
2340     This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffEncoder));
2341     if (!This) return E_OUTOFMEMORY;
2342 
2343     This->IWICBitmapEncoder_iface.lpVtbl = &TiffEncoder_Vtbl;
2344     This->ref = 1;
2345     This->stream = NULL;
2346     InitializeCriticalSection(&This->lock);
2347     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffEncoder.lock");
2348     This->tiff = NULL;
2349     This->initialized = FALSE;
2350     This->num_frames = 0;
2351     This->num_frames_committed = 0;
2352     This->committed = FALSE;
2353 
2354     ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
2355     IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
2356 
2357     return ret;
2358 }
2359 
2360 #else /* !SONAME_LIBTIFF */
2361 
2362 HRESULT TiffDecoder_CreateInstance(REFIID iid, void** ppv)
2363 {
2364     ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
2365     return E_FAIL;
2366 }
2367 
2368 HRESULT TiffEncoder_CreateInstance(REFIID iid, void** ppv)
2369 {
2370     ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");
2371     return E_FAIL;
2372 }
2373 
2374 #endif
2375