winealsa.drv: Re-add capcontrols initialization.
[wine] / dlls / windowscodecs / tiffformat.c
1 /*
2  * Copyright 2010 Vincent Povirk for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <stdarg.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #ifdef HAVE_TIFFIO_H
27 #include <tiffio.h>
28 #endif
29
30 #define COBJMACROS
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "objbase.h"
35 #include "wincodec.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 static CRITICAL_SECTION init_tiff_cs;
47 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug =
48 {
49     0, 0, &init_tiff_cs,
50     { &init_tiff_cs_debug.ProcessLocksList,
51       &init_tiff_cs_debug.ProcessLocksList },
52     0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") }
53 };
54 static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
55
56 static void *libtiff_handle;
57 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
58 MAKE_FUNCPTR(TIFFClientOpen);
59 MAKE_FUNCPTR(TIFFClose);
60 MAKE_FUNCPTR(TIFFCurrentDirectory);
61 MAKE_FUNCPTR(TIFFGetField);
62 MAKE_FUNCPTR(TIFFIsByteSwapped);
63 MAKE_FUNCPTR(TIFFReadDirectory);
64 MAKE_FUNCPTR(TIFFReadEncodedStrip);
65 MAKE_FUNCPTR(TIFFSetDirectory);
66 #undef MAKE_FUNCPTR
67
68 static void *load_libtiff(void)
69 {
70     void *result;
71
72     EnterCriticalSection(&init_tiff_cs);
73
74     if (!libtiff_handle &&
75         (libtiff_handle = wine_dlopen(SONAME_LIBTIFF, RTLD_NOW, NULL, 0)) != NULL)
76     {
77
78 #define LOAD_FUNCPTR(f) \
79     if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \
80         ERR("failed to load symbol %s\n", #f); \
81         libtiff_handle = NULL; \
82         LeaveCriticalSection(&init_tiff_cs); \
83         return NULL; \
84     }
85         LOAD_FUNCPTR(TIFFClientOpen);
86         LOAD_FUNCPTR(TIFFClose);
87         LOAD_FUNCPTR(TIFFCurrentDirectory);
88         LOAD_FUNCPTR(TIFFGetField);
89         LOAD_FUNCPTR(TIFFIsByteSwapped);
90         LOAD_FUNCPTR(TIFFReadDirectory);
91         LOAD_FUNCPTR(TIFFReadEncodedStrip);
92         LOAD_FUNCPTR(TIFFSetDirectory);
93 #undef LOAD_FUNCPTR
94
95     }
96
97     result = libtiff_handle;
98
99     LeaveCriticalSection(&init_tiff_cs);
100     return result;
101 }
102
103 static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size)
104 {
105     IStream *stream = (IStream*)client_data;
106     ULONG bytes_read;
107     HRESULT hr;
108
109     hr = IStream_Read(stream, data, size, &bytes_read);
110     if (FAILED(hr)) bytes_read = 0;
111     return bytes_read;
112 }
113
114 static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
115 {
116     IStream *stream = (IStream*)client_data;
117     ULONG bytes_written;
118     HRESULT hr;
119
120     hr = IStream_Write(stream, data, size, &bytes_written);
121     if (FAILED(hr)) bytes_written = 0;
122     return bytes_written;
123 }
124
125 static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
126 {
127     IStream *stream = (IStream*)client_data;
128     LARGE_INTEGER move;
129     DWORD origin;
130     ULARGE_INTEGER new_position;
131     HRESULT hr;
132
133     move.QuadPart = offset;
134     switch (whence)
135     {
136         case SEEK_SET:
137             origin = STREAM_SEEK_SET;
138             break;
139         case SEEK_CUR:
140             origin = STREAM_SEEK_CUR;
141             break;
142         case SEEK_END:
143             origin = STREAM_SEEK_END;
144             break;
145         default:
146             ERR("unknown whence value %i\n", whence);
147             return -1;
148     }
149
150     hr = IStream_Seek(stream, move, origin, &new_position);
151     if (SUCCEEDED(hr)) return new_position.QuadPart;
152     else return -1;
153 }
154
155 static int tiff_stream_close(thandle_t client_data)
156 {
157     /* Caller is responsible for releasing the stream object. */
158     return 0;
159 }
160
161 static toff_t tiff_stream_size(thandle_t client_data)
162 {
163     IStream *stream = (IStream*)client_data;
164     STATSTG statstg;
165     HRESULT hr;
166
167     hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
168
169     if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart;
170     else return -1;
171 }
172
173 static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
174 {
175     /* Cannot mmap streams */
176     return 0;
177 }
178
179 static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size)
180 {
181     /* No need to ever do this, since we can't map things. */
182 }
183
184 static TIFF* tiff_open_stream(IStream *stream, const char *mode)
185 {
186     LARGE_INTEGER zero;
187
188     zero.QuadPart = 0;
189     IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
190
191     return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read,
192         tiff_stream_write, tiff_stream_seek, tiff_stream_close,
193         tiff_stream_size, tiff_stream_map, tiff_stream_unmap);
194 }
195
196 typedef struct {
197     IWICBitmapDecoder IWICBitmapDecoder_iface;
198     LONG ref;
199     IStream *stream;
200     CRITICAL_SECTION lock; /* Must be held when tiff is used or initiailzed is set */
201     TIFF *tiff;
202     BOOL initialized;
203 } TiffDecoder;
204
205 typedef struct {
206     const WICPixelFormatGUID *format;
207     int bps;
208     int samples;
209     int bpp;
210     int planar;
211     int indexed;
212     int reverse_bgr;
213     int invert_grayscale;
214     UINT width, height;
215     UINT tile_width, tile_height;
216     UINT tile_stride;
217     UINT tile_size;
218 } tiff_decode_info;
219
220 typedef struct {
221     IWICBitmapFrameDecode IWICBitmapFrameDecode_iface;
222     LONG ref;
223     TiffDecoder *parent;
224     UINT index;
225     tiff_decode_info decode_info;
226     INT cached_tile_x, cached_tile_y;
227     BYTE *cached_tile;
228 } TiffFrameDecode;
229
230 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl;
231
232 static inline TiffDecoder *impl_from_IWICBitmapDecoder(IWICBitmapDecoder *iface)
233 {
234     return CONTAINING_RECORD(iface, TiffDecoder, IWICBitmapDecoder_iface);
235 }
236
237 static inline TiffFrameDecode *impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode *iface)
238 {
239     return CONTAINING_RECORD(iface, TiffFrameDecode, IWICBitmapFrameDecode_iface);
240 }
241
242 static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info)
243 {
244     uint16 photometric, bps, samples, planar;
245     uint16 extra_sample_count, *extra_samples;
246     int ret;
247
248     decode_info->indexed = 0;
249     decode_info->reverse_bgr = 0;
250     decode_info->invert_grayscale = 0;
251
252     ret = pTIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);
253     if (!ret)
254     {
255         WARN("missing PhotometricInterpretation tag\n");
256         return E_FAIL;
257     }
258
259     ret = pTIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bps);
260     if (!ret) bps = 1;
261     decode_info->bps = bps;
262
263     ret = pTIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples);
264     if (!ret) samples = 1;
265     decode_info->samples = samples;
266
267     if (samples == 1)
268         planar = 1;
269     else
270     {
271         ret = pTIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar);
272         if (!ret) planar = 1;
273         if (planar != 1)
274         {
275             FIXME("unhandled planar configuration %u\n", planar);
276             return E_FAIL;
277         }
278     }
279     decode_info->planar = planar;
280
281     switch(photometric)
282     {
283     case 0: /* WhiteIsZero */
284         decode_info->invert_grayscale = 1;
285     case 1: /* BlackIsZero */
286         if (samples != 1)
287         {
288             FIXME("unhandled grayscale sample count %u\n", samples);
289             return E_FAIL;
290         }
291
292         decode_info->bpp = bps;
293         switch (bps)
294         {
295         case 1:
296             decode_info->format = &GUID_WICPixelFormatBlackWhite;
297             break;
298         case 4:
299             decode_info->format = &GUID_WICPixelFormat4bppGray;
300             break;
301         case 8:
302             decode_info->format = &GUID_WICPixelFormat8bppGray;
303             break;
304         default:
305             FIXME("unhandled greyscale bit count %u\n", bps);
306             return E_FAIL;
307         }
308         break;
309     case 2: /* RGB */
310         decode_info->bpp = bps * samples;
311
312         if (samples == 4)
313         {
314             ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples);
315             if (!ret)
316             {
317                 WARN("Cannot get extra sample type for RGB data, ret=%i count=%i\n", ret, extra_sample_count);
318                 return E_FAIL;
319             }
320         }
321         else if (samples != 3)
322         {
323             FIXME("unhandled RGB sample count %u\n", samples);
324             return E_FAIL;
325         }
326
327         switch(bps)
328         {
329         case 8:
330             decode_info->reverse_bgr = 1;
331             if (samples == 3)
332                 decode_info->format = &GUID_WICPixelFormat24bppBGR;
333             else
334                 switch(extra_samples[0])
335                 {
336                 case 1: /* Associated (pre-multiplied) alpha data */
337                     decode_info->format = &GUID_WICPixelFormat32bppPBGRA;
338                     break;
339                 case 2: /* Unassociated alpha data */
340                     decode_info->format = &GUID_WICPixelFormat32bppBGRA;
341                     break;
342                 default:
343                     FIXME("unhandled extra sample type %i\n", extra_samples[0]);
344                     return E_FAIL;
345                 }
346             break;
347         case 16:
348             if (samples == 3)
349                 decode_info->format = &GUID_WICPixelFormat48bppRGB;
350             else
351                 switch(extra_samples[0])
352                 {
353                 case 1: /* Associated (pre-multiplied) alpha data */
354                     decode_info->format = &GUID_WICPixelFormat64bppPRGBA;
355                     break;
356                 case 2: /* Unassociated alpha data */
357                     decode_info->format = &GUID_WICPixelFormat64bppRGBA;
358                     break;
359                 default:
360                     FIXME("unhandled extra sample type %i\n", extra_samples[0]);
361                     return E_FAIL;
362                 }
363             break;
364         default:
365             FIXME("unhandled RGB bit count %u\n", bps);
366             return E_FAIL;
367         }
368         break;
369     case 3: /* RGB Palette */
370         if (samples != 1)
371         {
372             FIXME("unhandled indexed sample count %u\n", samples);
373             return E_FAIL;
374         }
375
376         decode_info->indexed = 1;
377         decode_info->bpp = bps;
378         switch (bps)
379         {
380         case 4:
381             decode_info->format = &GUID_WICPixelFormat4bppIndexed;
382             break;
383         case 8:
384             decode_info->format = &GUID_WICPixelFormat8bppIndexed;
385             break;
386         default:
387             FIXME("unhandled indexed bit count %u\n", bps);
388             return E_FAIL;
389         }
390         break;
391     case 4: /* Transparency mask */
392     case 5: /* CMYK */
393     case 6: /* YCbCr */
394     case 8: /* CIELab */
395     default:
396         FIXME("unhandled PhotometricInterpretation %u\n", photometric);
397         return E_FAIL;
398     }
399
400     ret = pTIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &decode_info->width);
401     if (!ret)
402     {
403         WARN("missing image width\n");
404         return E_FAIL;
405     }
406
407     ret = pTIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &decode_info->height);
408     if (!ret)
409     {
410         WARN("missing image length\n");
411         return E_FAIL;
412     }
413
414     ret = pTIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &decode_info->tile_height);
415     if (ret)
416     {
417         if (decode_info->tile_height > decode_info->height)
418             decode_info->tile_height = decode_info->height;
419         decode_info->tile_width = decode_info->width;
420         decode_info->tile_stride = ((decode_info->bpp * decode_info->tile_width + 7)/8);
421         decode_info->tile_size = decode_info->tile_height * decode_info->tile_stride;
422     }
423     else
424     {
425         /* Probably a tiled image */
426         FIXME("missing RowsPerStrip value\n");
427         return E_FAIL;
428     }
429
430     return S_OK;
431 }
432
433 static HRESULT WINAPI TiffDecoder_QueryInterface(IWICBitmapDecoder *iface, REFIID iid,
434     void **ppv)
435 {
436     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
437     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
438
439     if (!ppv) return E_INVALIDARG;
440
441     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IWICBitmapDecoder, iid))
442     {
443         *ppv = This;
444     }
445     else
446     {
447         *ppv = NULL;
448         return E_NOINTERFACE;
449     }
450
451     IUnknown_AddRef((IUnknown*)*ppv);
452     return S_OK;
453 }
454
455 static ULONG WINAPI TiffDecoder_AddRef(IWICBitmapDecoder *iface)
456 {
457     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
458     ULONG ref = InterlockedIncrement(&This->ref);
459
460     TRACE("(%p) refcount=%u\n", iface, ref);
461
462     return ref;
463 }
464
465 static ULONG WINAPI TiffDecoder_Release(IWICBitmapDecoder *iface)
466 {
467     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
468     ULONG ref = InterlockedDecrement(&This->ref);
469
470     TRACE("(%p) refcount=%u\n", iface, ref);
471
472     if (ref == 0)
473     {
474         if (This->tiff) pTIFFClose(This->tiff);
475         if (This->stream) IStream_Release(This->stream);
476         This->lock.DebugInfo->Spare[0] = 0;
477         DeleteCriticalSection(&This->lock);
478         HeapFree(GetProcessHeap(), 0, This);
479     }
480
481     return ref;
482 }
483
484 static HRESULT WINAPI TiffDecoder_QueryCapability(IWICBitmapDecoder *iface, IStream *pIStream,
485     DWORD *pdwCapability)
486 {
487     FIXME("(%p,%p,%p): stub\n", iface, pIStream, pdwCapability);
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream *pIStream,
492     WICDecodeOptions cacheOptions)
493 {
494     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
495     TIFF *tiff;
496     HRESULT hr=S_OK;
497
498     TRACE("(%p,%p,%x): stub\n", iface, pIStream, cacheOptions);
499
500     EnterCriticalSection(&This->lock);
501
502     if (This->initialized)
503     {
504         hr = WINCODEC_ERR_WRONGSTATE;
505         goto exit;
506     }
507
508     tiff = tiff_open_stream(pIStream, "r");
509
510     if (!tiff)
511     {
512         hr = E_FAIL;
513         goto exit;
514     }
515
516     This->tiff = tiff;
517     This->stream = pIStream;
518     IStream_AddRef(pIStream);
519     This->initialized = TRUE;
520
521 exit:
522     LeaveCriticalSection(&This->lock);
523     return hr;
524 }
525
526 static HRESULT WINAPI TiffDecoder_GetContainerFormat(IWICBitmapDecoder *iface,
527     GUID *pguidContainerFormat)
528 {
529     memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
530     return S_OK;
531 }
532
533 static HRESULT WINAPI TiffDecoder_GetDecoderInfo(IWICBitmapDecoder *iface,
534     IWICBitmapDecoderInfo **ppIDecoderInfo)
535 {
536     FIXME("(%p,%p): stub\n", iface, ppIDecoderInfo);
537     return E_NOTIMPL;
538 }
539
540 static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface,
541     IWICPalette *pIPalette)
542 {
543     FIXME("(%p,%p): stub\n", iface, pIPalette);
544     return E_NOTIMPL;
545 }
546
547 static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface,
548     IWICMetadataQueryReader **ppIMetadataQueryReader)
549 {
550     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
551     return E_NOTIMPL;
552 }
553
554 static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface,
555     IWICBitmapSource **ppIBitmapSource)
556 {
557     FIXME("(%p,%p): stub\n", iface, ppIBitmapSource);
558     return E_NOTIMPL;
559 }
560
561 static HRESULT WINAPI TiffDecoder_GetColorContexts(IWICBitmapDecoder *iface,
562     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
563 {
564     FIXME("(%p,%u,%p,%p)\n", iface, cCount, ppIColorContexts, pcActualCount);
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI TiffDecoder_GetThumbnail(IWICBitmapDecoder *iface,
569     IWICBitmapSource **ppIThumbnail)
570 {
571     TRACE("(%p,%p)\n", iface, ppIThumbnail);
572     return WINCODEC_ERR_CODECNOTHUMBNAIL;
573 }
574
575 static HRESULT WINAPI TiffDecoder_GetFrameCount(IWICBitmapDecoder *iface,
576     UINT *pCount)
577 {
578     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
579
580     if (!This->tiff)
581     {
582         WARN("(%p) <-- WINCODEC_ERR_WRONGSTATE\n", iface);
583         return WINCODEC_ERR_WRONGSTATE;
584     }
585
586     EnterCriticalSection(&This->lock);
587     while (pTIFFReadDirectory(This->tiff)) { }
588     *pCount = pTIFFCurrentDirectory(This->tiff)+1;
589     LeaveCriticalSection(&This->lock);
590
591     TRACE("(%p) <-- %i\n", iface, *pCount);
592
593     return S_OK;
594 }
595
596 static HRESULT WINAPI TiffDecoder_GetFrame(IWICBitmapDecoder *iface,
597     UINT index, IWICBitmapFrameDecode **ppIBitmapFrame)
598 {
599     TiffDecoder *This = impl_from_IWICBitmapDecoder(iface);
600     TiffFrameDecode *result;
601     int res;
602     tiff_decode_info decode_info;
603     HRESULT hr;
604
605     TRACE("(%p,%u,%p)\n", iface, index, ppIBitmapFrame);
606
607     if (!This->tiff)
608         return WINCODEC_ERR_WRONGSTATE;
609
610     EnterCriticalSection(&This->lock);
611     res = pTIFFSetDirectory(This->tiff, index);
612     if (!res) hr = E_INVALIDARG;
613     else hr = tiff_get_decode_info(This->tiff, &decode_info);
614     LeaveCriticalSection(&This->lock);
615
616     if (SUCCEEDED(hr))
617     {
618         result = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode));
619
620         if (result)
621         {
622             result->IWICBitmapFrameDecode_iface.lpVtbl = &TiffFrameDecode_Vtbl;
623             result->ref = 1;
624             result->parent = This;
625             result->index = index;
626             result->decode_info = decode_info;
627             result->cached_tile_x = -1;
628             result->cached_tile = HeapAlloc(GetProcessHeap(), 0, decode_info.tile_size);
629
630             if (result->cached_tile)
631                 *ppIBitmapFrame = (IWICBitmapFrameDecode*)result;
632             else
633             {
634                 hr = E_OUTOFMEMORY;
635                 HeapFree(GetProcessHeap(), 0, result);
636             }
637         }
638         else hr = E_OUTOFMEMORY;
639     }
640
641     if (FAILED(hr)) *ppIBitmapFrame = NULL;
642
643     return hr;
644 }
645
646 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl = {
647     TiffDecoder_QueryInterface,
648     TiffDecoder_AddRef,
649     TiffDecoder_Release,
650     TiffDecoder_QueryCapability,
651     TiffDecoder_Initialize,
652     TiffDecoder_GetContainerFormat,
653     TiffDecoder_GetDecoderInfo,
654     TiffDecoder_CopyPalette,
655     TiffDecoder_GetMetadataQueryReader,
656     TiffDecoder_GetPreview,
657     TiffDecoder_GetColorContexts,
658     TiffDecoder_GetThumbnail,
659     TiffDecoder_GetFrameCount,
660     TiffDecoder_GetFrame
661 };
662
663 static HRESULT WINAPI TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode *iface, REFIID iid,
664     void **ppv)
665 {
666     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
667     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
668
669     if (!ppv) return E_INVALIDARG;
670
671     if (IsEqualIID(&IID_IUnknown, iid) ||
672         IsEqualIID(&IID_IWICBitmapSource, iid) ||
673         IsEqualIID(&IID_IWICBitmapFrameDecode, iid))
674     {
675         *ppv = This;
676     }
677     else
678     {
679         *ppv = NULL;
680         return E_NOINTERFACE;
681     }
682
683     IUnknown_AddRef((IUnknown*)*ppv);
684     return S_OK;
685 }
686
687 static ULONG WINAPI TiffFrameDecode_AddRef(IWICBitmapFrameDecode *iface)
688 {
689     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
690     ULONG ref = InterlockedIncrement(&This->ref);
691
692     TRACE("(%p) refcount=%u\n", iface, ref);
693
694     return ref;
695 }
696
697 static ULONG WINAPI TiffFrameDecode_Release(IWICBitmapFrameDecode *iface)
698 {
699     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
700     ULONG ref = InterlockedDecrement(&This->ref);
701
702     TRACE("(%p) refcount=%u\n", iface, ref);
703
704     if (ref == 0)
705     {
706         HeapFree(GetProcessHeap(), 0, This->cached_tile);
707         HeapFree(GetProcessHeap(), 0, This);
708     }
709
710     return ref;
711 }
712
713 static HRESULT WINAPI TiffFrameDecode_GetSize(IWICBitmapFrameDecode *iface,
714     UINT *puiWidth, UINT *puiHeight)
715 {
716     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
717
718     *puiWidth = This->decode_info.width;
719     *puiHeight = This->decode_info.height;
720
721     TRACE("(%p) <-- %ux%u\n", iface, *puiWidth, *puiHeight);
722
723     return S_OK;
724 }
725
726 static HRESULT WINAPI TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode *iface,
727     WICPixelFormatGUID *pPixelFormat)
728 {
729     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
730
731     memcpy(pPixelFormat, This->decode_info.format, sizeof(GUID));
732
733     TRACE("(%p) <-- %s\n", This, debugstr_guid(This->decode_info.format));
734
735     return S_OK;
736 }
737
738 static HRESULT WINAPI TiffFrameDecode_GetResolution(IWICBitmapFrameDecode *iface,
739     double *pDpiX, double *pDpiY)
740 {
741     FIXME("(%p,%p,%p)\n", iface, pDpiX, pDpiY);
742     return E_NOTIMPL;
743 }
744
745 static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface,
746     IWICPalette *pIPalette)
747 {
748     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
749     uint16 *red, *green, *blue;
750     WICColor colors[256];
751     int color_count, ret, i;
752
753     TRACE("(%p,%p)\n", iface, pIPalette);
754
755     color_count = 1<<This->decode_info.bps;
756
757     EnterCriticalSection(&This->parent->lock);
758     ret = pTIFFGetField(This->parent->tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
759     LeaveCriticalSection(&This->parent->lock);
760
761     if (!ret)
762     {
763         WARN("Couldn't read color map\n");
764         return E_FAIL;
765     }
766
767     for (i=0; i<color_count; i++)
768     {
769         colors[i] = 0xff000000 |
770             ((red[i]<<8) & 0xff0000) |
771             (green[i] & 0xff00) |
772             ((blue[i]>>8) & 0xff);
773     }
774
775     return IWICPalette_InitializeCustom(pIPalette, colors, color_count);
776 }
777
778 static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y)
779 {
780     HRESULT hr=S_OK;
781     tsize_t ret;
782     int swap_bytes;
783
784     swap_bytes = pTIFFIsByteSwapped(This->parent->tiff);
785
786     ret = pTIFFSetDirectory(This->parent->tiff, This->index);
787
788     if (ret == -1)
789         hr = E_FAIL;
790
791     if (hr == S_OK)
792     {
793         ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size);
794
795         if (ret == -1)
796             hr = E_FAIL;
797     }
798
799     if (hr == S_OK && This->decode_info.reverse_bgr)
800     {
801         if (This->decode_info.bps == 8)
802         {
803             UINT i, total_pixels, sample_count;
804             BYTE *pixel, temp;
805
806             total_pixels = This->decode_info.tile_width * This->decode_info.tile_height;
807             pixel = This->cached_tile;
808             sample_count = This->decode_info.samples;
809             for (i=0; i<total_pixels; i++)
810             {
811                 temp = pixel[2];
812                 pixel[2] = pixel[0];
813                 pixel[0] = temp;
814                 pixel += sample_count;
815             }
816         }
817     }
818
819     if (hr == S_OK && swap_bytes && This->decode_info.bps > 8)
820     {
821         UINT row, i, samples_per_row;
822         BYTE *sample, temp;
823
824         samples_per_row = This->decode_info.tile_width * This->decode_info.samples;
825
826         switch(This->decode_info.bps)
827         {
828         case 16:
829             for (row=0; row<This->decode_info.tile_height; row++)
830             {
831                 sample = This->cached_tile + row * This->decode_info.tile_stride;
832                 for (i=0; i<samples_per_row; i++)
833                 {
834                     temp = sample[1];
835                     sample[1] = sample[0];
836                     sample[0] = temp;
837                     sample += 2;
838                 }
839             }
840             break;
841         default:
842             ERR("unhandled bps for byte swap %u\n", This->decode_info.bps);
843             return E_FAIL;
844         }
845     }
846
847     if (hr == S_OK && This->decode_info.invert_grayscale)
848     {
849         BYTE *byte, *end;
850
851         if (This->decode_info.samples != 1)
852         {
853             ERR("cannot invert grayscale image with %u samples\n", This->decode_info.samples);
854             return E_FAIL;
855         }
856
857         end = This->cached_tile+This->decode_info.tile_size;
858
859         for (byte = This->cached_tile; byte != end; byte++)
860             *byte = ~(*byte);
861     }
862
863     if (hr == S_OK)
864     {
865         This->cached_tile_x = tile_x;
866         This->cached_tile_y = tile_y;
867     }
868
869     return hr;
870 }
871
872 static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface,
873     const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
874 {
875     TiffFrameDecode *This = impl_from_IWICBitmapFrameDecode(iface);
876     UINT min_tile_x, max_tile_x, min_tile_y, max_tile_y;
877     UINT tile_x, tile_y;
878     WICRect rc;
879     HRESULT hr=S_OK;
880     BYTE *dst_tilepos;
881     UINT bytesperrow;
882     WICRect rect;
883
884     TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);
885
886     if (!prc)
887     {
888         rect.X = 0;
889         rect.Y = 0;
890         rect.Width = This->decode_info.width;
891         rect.Height = This->decode_info.height;
892         prc = &rect;
893     }
894     else
895     {
896         if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->decode_info.width ||
897             prc->Y+prc->Height > This->decode_info.height)
898             return E_INVALIDARG;
899     }
900
901     bytesperrow = ((This->decode_info.bpp * prc->Width)+7)/8;
902
903     if (cbStride < bytesperrow)
904         return E_INVALIDARG;
905
906     if ((cbStride * prc->Height) > cbBufferSize)
907         return E_INVALIDARG;
908
909     min_tile_x = prc->X / This->decode_info.tile_width;
910     min_tile_y = prc->Y / This->decode_info.tile_height;
911     max_tile_x = (prc->X+prc->Width-1) / This->decode_info.tile_width;
912     max_tile_y = (prc->Y+prc->Height-1) / This->decode_info.tile_height;
913
914     EnterCriticalSection(&This->parent->lock);
915
916     for (tile_x=min_tile_x; tile_x <= max_tile_x; tile_x++)
917     {
918         for (tile_y=min_tile_y; tile_y <= max_tile_y; tile_y++)
919         {
920             if (tile_x != This->cached_tile_x || tile_y != This->cached_tile_y)
921             {
922                 hr = TiffFrameDecode_ReadTile(This, tile_x, tile_y);
923             }
924
925             if (SUCCEEDED(hr))
926             {
927                 if (prc->X < tile_x * This->decode_info.tile_width)
928                     rc.X = 0;
929                 else
930                     rc.X = prc->X - tile_x * This->decode_info.tile_width;
931
932                 if (prc->Y < tile_y * This->decode_info.tile_height)
933                     rc.Y = 0;
934                 else
935                     rc.Y = prc->Y - tile_y * This->decode_info.tile_height;
936
937                 if (prc->X+prc->Width > (tile_x+1) * This->decode_info.tile_width)
938                     rc.Width = This->decode_info.tile_width - rc.X;
939                 else if (prc->X < tile_x * This->decode_info.tile_width)
940                     rc.Width = prc->Width + prc->X - tile_x * This->decode_info.tile_width;
941                 else
942                     rc.Width = prc->Width;
943
944                 if (prc->Y+prc->Height > (tile_y+1) * This->decode_info.tile_height)
945                     rc.Height = This->decode_info.tile_height - rc.Y;
946                 else if (prc->Y < tile_y * This->decode_info.tile_height)
947                     rc.Height = prc->Height + prc->Y - tile_y * This->decode_info.tile_height;
948                 else
949                     rc.Height = prc->Height;
950
951                 dst_tilepos = pbBuffer + (cbStride * ((rc.Y + tile_y * This->decode_info.tile_height) - prc->Y)) +
952                     ((This->decode_info.bpp * ((rc.X + tile_x * This->decode_info.tile_width) - prc->X) + 7) / 8);
953
954                 hr = copy_pixels(This->decode_info.bpp, This->cached_tile,
955                     This->decode_info.tile_width, This->decode_info.tile_height, This->decode_info.tile_stride,
956                     &rc, cbStride, cbBufferSize, dst_tilepos);
957             }
958
959             if (FAILED(hr))
960             {
961                 LeaveCriticalSection(&This->parent->lock);
962                 TRACE("<-- 0x%x\n", hr);
963                 return hr;
964             }
965         }
966     }
967
968     LeaveCriticalSection(&This->parent->lock);
969
970     return S_OK;
971 }
972
973 static HRESULT WINAPI TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode *iface,
974     IWICMetadataQueryReader **ppIMetadataQueryReader)
975 {
976     FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader);
977     return E_NOTIMPL;
978 }
979
980 static HRESULT WINAPI TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode *iface,
981     UINT cCount, IWICColorContext **ppIColorContexts, UINT *pcActualCount)
982 {
983     FIXME("(%p,%u,%p,%p): stub\n", iface, cCount, ppIColorContexts, pcActualCount);
984     return E_NOTIMPL;
985 }
986
987 static HRESULT WINAPI TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode *iface,
988     IWICBitmapSource **ppIThumbnail)
989 {
990     FIXME("(%p,%p): stub\n", iface, ppIThumbnail);
991     return E_NOTIMPL;
992 }
993
994 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl = {
995     TiffFrameDecode_QueryInterface,
996     TiffFrameDecode_AddRef,
997     TiffFrameDecode_Release,
998     TiffFrameDecode_GetSize,
999     TiffFrameDecode_GetPixelFormat,
1000     TiffFrameDecode_GetResolution,
1001     TiffFrameDecode_CopyPalette,
1002     TiffFrameDecode_CopyPixels,
1003     TiffFrameDecode_GetMetadataQueryReader,
1004     TiffFrameDecode_GetColorContexts,
1005     TiffFrameDecode_GetThumbnail
1006 };
1007
1008 HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
1009 {
1010     HRESULT ret;
1011     TiffDecoder *This;
1012
1013     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
1014
1015     *ppv = NULL;
1016
1017     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
1018
1019     if (!load_libtiff())
1020     {
1021         ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF);
1022         return E_FAIL;
1023     }
1024
1025     This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder));
1026     if (!This) return E_OUTOFMEMORY;
1027
1028     This->IWICBitmapDecoder_iface.lpVtbl = &TiffDecoder_Vtbl;
1029     This->ref = 1;
1030     This->stream = NULL;
1031     InitializeCriticalSection(&This->lock);
1032     This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffDecoder.lock");
1033     This->tiff = NULL;
1034     This->initialized = FALSE;
1035
1036     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
1037     IUnknown_Release((IUnknown*)This);
1038
1039     return ret;
1040 }
1041
1042 #else /* !SONAME_LIBTIFF */
1043
1044 HRESULT TiffDecoder_CreateInstance(IUnknown *pUnkOuter, REFIID iid, void** ppv)
1045 {
1046     ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
1047     return E_FAIL;
1048 }
1049
1050 #endif