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