2 * Copyright 2010 Vincent Povirk for CodeWeavers
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.
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.
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
20 #include "wine/port.h"
37 #include "wincodecs_private.h"
39 #include "wine/debug.h"
40 #include "wine/library.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
46 static CRITICAL_SECTION init_tiff_cs
;
47 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug
=
50 { &init_tiff_cs_debug
.ProcessLocksList
,
51 &init_tiff_cs_debug
.ProcessLocksList
},
52 0, 0, { (DWORD_PTR
)(__FILE__
": init_tiff_cs") }
54 static CRITICAL_SECTION init_tiff_cs
= { &init_tiff_cs_debug
, -1, 0, 0, 0, 0 };
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
);
68 static void *load_libtiff(void)
72 EnterCriticalSection(&init_tiff_cs
);
74 if (!libtiff_handle
&&
75 (libtiff_handle
= wine_dlopen(SONAME_LIBTIFF
, RTLD_NOW
, NULL
, 0)) != NULL
)
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); \
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
);
97 result
= libtiff_handle
;
99 LeaveCriticalSection(&init_tiff_cs
);
103 static tsize_t
tiff_stream_read(thandle_t client_data
, tdata_t data
, tsize_t size
)
105 IStream
*stream
= (IStream
*)client_data
;
109 hr
= IStream_Read(stream
, data
, size
, &bytes_read
);
110 if (FAILED(hr
)) bytes_read
= 0;
114 static tsize_t
tiff_stream_write(thandle_t client_data
, tdata_t data
, tsize_t size
)
116 IStream
*stream
= (IStream
*)client_data
;
120 hr
= IStream_Write(stream
, data
, size
, &bytes_written
);
121 if (FAILED(hr
)) bytes_written
= 0;
122 return bytes_written
;
125 static toff_t
tiff_stream_seek(thandle_t client_data
, toff_t offset
, int whence
)
127 IStream
*stream
= (IStream
*)client_data
;
130 ULARGE_INTEGER new_position
;
133 move
.QuadPart
= offset
;
137 origin
= STREAM_SEEK_SET
;
140 origin
= STREAM_SEEK_CUR
;
143 origin
= STREAM_SEEK_END
;
146 ERR("unknown whence value %i\n", whence
);
150 hr
= IStream_Seek(stream
, move
, origin
, &new_position
);
151 if (SUCCEEDED(hr
)) return new_position
.QuadPart
;
155 static int tiff_stream_close(thandle_t client_data
)
157 /* Caller is responsible for releasing the stream object. */
161 static toff_t
tiff_stream_size(thandle_t client_data
)
163 IStream
*stream
= (IStream
*)client_data
;
167 hr
= IStream_Stat(stream
, &statstg
, STATFLAG_NONAME
);
169 if (SUCCEEDED(hr
)) return statstg
.cbSize
.QuadPart
;
173 static int tiff_stream_map(thandle_t client_data
, tdata_t
*addr
, toff_t
*size
)
175 /* Cannot mmap streams */
179 static void tiff_stream_unmap(thandle_t client_data
, tdata_t addr
, toff_t size
)
181 /* No need to ever do this, since we can't map things. */
184 static TIFF
* tiff_open_stream(IStream
*stream
, const char *mode
)
186 return pTIFFClientOpen("<IStream object>", mode
, stream
, tiff_stream_read
,
187 tiff_stream_write
, tiff_stream_seek
, tiff_stream_close
,
188 tiff_stream_size
, tiff_stream_map
, tiff_stream_unmap
);
192 const IWICBitmapDecoderVtbl
*lpVtbl
;
195 CRITICAL_SECTION lock
; /* Must be held when tiff is used or initiailzed is set */
201 const WICPixelFormatGUID
*format
;
208 int invert_grayscale
;
210 UINT tile_width
, tile_height
;
216 const IWICBitmapFrameDecodeVtbl
*lpVtbl
;
220 tiff_decode_info decode_info
;
221 INT cached_tile_x
, cached_tile_y
;
225 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl
;
227 static HRESULT
tiff_get_decode_info(TIFF
*tiff
, tiff_decode_info
*decode_info
)
229 uint16 photometric
, bps
, samples
, planar
;
232 decode_info
->indexed
= 0;
233 decode_info
->reverse_bgr
= 0;
234 decode_info
->invert_grayscale
= 0;
236 ret
= pTIFFGetField(tiff
, TIFFTAG_PHOTOMETRIC
, &photometric
);
239 WARN("missing PhotometricInterpretation tag\n");
243 ret
= pTIFFGetField(tiff
, TIFFTAG_BITSPERSAMPLE
, &bps
);
245 decode_info
->bps
= bps
;
247 ret
= pTIFFGetField(tiff
, TIFFTAG_SAMPLESPERPIXEL
, &samples
);
248 if (!ret
) samples
= 1;
249 decode_info
->samples
= samples
;
255 ret
= pTIFFGetField(tiff
, TIFFTAG_PLANARCONFIG
, &planar
);
256 if (!ret
) planar
= 1;
259 FIXME("unhandled planar configuration %u\n", planar
);
263 decode_info
->planar
= planar
;
267 case 0: /* WhiteIsZero */
268 decode_info
->invert_grayscale
= 1;
269 case 1: /* BlackIsZero */
272 FIXME("unhandled grayscale sample count %u\n", samples
);
276 decode_info
->bpp
= bps
;
280 decode_info
->format
= &GUID_WICPixelFormatBlackWhite
;
283 decode_info
->format
= &GUID_WICPixelFormat4bppGray
;
286 decode_info
->format
= &GUID_WICPixelFormat8bppGray
;
289 FIXME("unhandled greyscale bit count %u\n", bps
);
294 decode_info
->bpp
= bps
* samples
;
298 FIXME("unhandled RGB sample count %u\n", samples
);
305 decode_info
->reverse_bgr
= 1;
306 decode_info
->format
= &GUID_WICPixelFormat24bppBGR
;
309 decode_info
->format
= &GUID_WICPixelFormat48bppRGB
;
312 FIXME("unhandled RGB bit count %u\n", bps
);
316 case 3: /* RGB Palette */
319 FIXME("unhandled indexed sample count %u\n", samples
);
323 decode_info
->indexed
= 1;
324 decode_info
->bpp
= bps
;
328 decode_info
->format
= &GUID_WICPixelFormat4bppIndexed
;
331 decode_info
->format
= &GUID_WICPixelFormat8bppIndexed
;
334 FIXME("unhandled indexed bit count %u\n", bps
);
338 case 4: /* Transparency mask */
343 FIXME("unhandled PhotometricInterpretation %u\n", photometric
);
347 ret
= pTIFFGetField(tiff
, TIFFTAG_IMAGEWIDTH
, &decode_info
->width
);
350 WARN("missing image width\n");
354 ret
= pTIFFGetField(tiff
, TIFFTAG_IMAGELENGTH
, &decode_info
->height
);
357 WARN("missing image length\n");
361 ret
= pTIFFGetField(tiff
, TIFFTAG_ROWSPERSTRIP
, &decode_info
->tile_height
);
364 if (decode_info
->tile_height
> decode_info
->height
)
365 decode_info
->tile_height
= decode_info
->height
;
366 decode_info
->tile_width
= decode_info
->width
;
367 decode_info
->tile_stride
= ((decode_info
->bpp
* decode_info
->tile_width
+ 7)/8);
368 decode_info
->tile_size
= decode_info
->tile_height
* decode_info
->tile_stride
;
372 /* Probably a tiled image */
373 FIXME("missing RowsPerStrip value\n");
380 static HRESULT WINAPI
TiffDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
383 TiffDecoder
*This
= (TiffDecoder
*)iface
;
384 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
386 if (!ppv
) return E_INVALIDARG
;
388 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICBitmapDecoder
, iid
))
395 return E_NOINTERFACE
;
398 IUnknown_AddRef((IUnknown
*)*ppv
);
402 static ULONG WINAPI
TiffDecoder_AddRef(IWICBitmapDecoder
*iface
)
404 TiffDecoder
*This
= (TiffDecoder
*)iface
;
405 ULONG ref
= InterlockedIncrement(&This
->ref
);
407 TRACE("(%p) refcount=%u\n", iface
, ref
);
412 static ULONG WINAPI
TiffDecoder_Release(IWICBitmapDecoder
*iface
)
414 TiffDecoder
*This
= (TiffDecoder
*)iface
;
415 ULONG ref
= InterlockedDecrement(&This
->ref
);
417 TRACE("(%p) refcount=%u\n", iface
, ref
);
421 if (This
->tiff
) pTIFFClose(This
->tiff
);
422 if (This
->stream
) IStream_Release(This
->stream
);
423 This
->lock
.DebugInfo
->Spare
[0] = 0;
424 DeleteCriticalSection(&This
->lock
);
425 HeapFree(GetProcessHeap(), 0, This
);
431 static HRESULT WINAPI
TiffDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
432 DWORD
*pdwCapability
)
434 FIXME("(%p,%p,%p): stub\n", iface
, pIStream
, pdwCapability
);
438 static HRESULT WINAPI
TiffDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
439 WICDecodeOptions cacheOptions
)
441 TiffDecoder
*This
= (TiffDecoder
*)iface
;
445 TRACE("(%p,%p,%x): stub\n", iface
, pIStream
, cacheOptions
);
447 EnterCriticalSection(&This
->lock
);
449 if (This
->initialized
)
451 hr
= WINCODEC_ERR_WRONGSTATE
;
455 tiff
= tiff_open_stream(pIStream
, "r");
464 This
->stream
= pIStream
;
465 IStream_AddRef(pIStream
);
466 This
->initialized
= TRUE
;
469 LeaveCriticalSection(&This
->lock
);
473 static HRESULT WINAPI
TiffDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
474 GUID
*pguidContainerFormat
)
476 memcpy(pguidContainerFormat
, &GUID_ContainerFormatTiff
, sizeof(GUID
));
480 static HRESULT WINAPI
TiffDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
481 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
483 FIXME("(%p,%p): stub\n", iface
, ppIDecoderInfo
);
487 static HRESULT WINAPI
TiffDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
488 IWICPalette
*pIPalette
)
490 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
494 static HRESULT WINAPI
TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
495 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
497 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryReader
);
501 static HRESULT WINAPI
TiffDecoder_GetPreview(IWICBitmapDecoder
*iface
,
502 IWICBitmapSource
**ppIBitmapSource
)
504 FIXME("(%p,%p): stub\n", iface
, ppIBitmapSource
);
508 static HRESULT WINAPI
TiffDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
509 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
511 FIXME("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
515 static HRESULT WINAPI
TiffDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
516 IWICBitmapSource
**ppIThumbnail
)
518 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
519 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
522 static HRESULT WINAPI
TiffDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
525 TiffDecoder
*This
= (TiffDecoder
*)iface
;
529 WARN("(%p) <-- WINCODEC_ERR_WRONGSTATE\n", iface
);
530 return WINCODEC_ERR_WRONGSTATE
;
533 EnterCriticalSection(&This
->lock
);
534 while (pTIFFReadDirectory(This
->tiff
)) { }
535 *pCount
= pTIFFCurrentDirectory(This
->tiff
)+1;
536 LeaveCriticalSection(&This
->lock
);
538 TRACE("(%p) <-- %i\n", iface
, *pCount
);
543 static HRESULT WINAPI
TiffDecoder_GetFrame(IWICBitmapDecoder
*iface
,
544 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
546 TiffDecoder
*This
= (TiffDecoder
*)iface
;
547 TiffFrameDecode
*result
;
549 tiff_decode_info decode_info
;
552 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
555 return WINCODEC_ERR_WRONGSTATE
;
557 EnterCriticalSection(&This
->lock
);
558 res
= pTIFFSetDirectory(This
->tiff
, index
);
559 if (!res
) hr
= E_INVALIDARG
;
560 else hr
= tiff_get_decode_info(This
->tiff
, &decode_info
);
561 LeaveCriticalSection(&This
->lock
);
565 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode
));
569 result
->lpVtbl
= &TiffFrameDecode_Vtbl
;
571 result
->parent
= This
;
572 result
->index
= index
;
573 result
->decode_info
= decode_info
;
574 result
->cached_tile_x
= -1;
575 result
->cached_tile
= HeapAlloc(GetProcessHeap(), 0, decode_info
.tile_size
);
577 if (result
->cached_tile
)
578 *ppIBitmapFrame
= (IWICBitmapFrameDecode
*)result
;
582 HeapFree(GetProcessHeap(), 0, result
);
585 else hr
= E_OUTOFMEMORY
;
588 if (FAILED(hr
)) *ppIBitmapFrame
= NULL
;
593 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl
= {
594 TiffDecoder_QueryInterface
,
597 TiffDecoder_QueryCapability
,
598 TiffDecoder_Initialize
,
599 TiffDecoder_GetContainerFormat
,
600 TiffDecoder_GetDecoderInfo
,
601 TiffDecoder_CopyPalette
,
602 TiffDecoder_GetMetadataQueryReader
,
603 TiffDecoder_GetPreview
,
604 TiffDecoder_GetColorContexts
,
605 TiffDecoder_GetThumbnail
,
606 TiffDecoder_GetFrameCount
,
610 static HRESULT WINAPI
TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
613 TiffFrameDecode
*This
= (TiffFrameDecode
*)iface
;
614 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
616 if (!ppv
) return E_INVALIDARG
;
618 if (IsEqualIID(&IID_IUnknown
, iid
) ||
619 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
620 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
))
627 return E_NOINTERFACE
;
630 IUnknown_AddRef((IUnknown
*)*ppv
);
634 static ULONG WINAPI
TiffFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
636 TiffFrameDecode
*This
= (TiffFrameDecode
*)iface
;
637 ULONG ref
= InterlockedIncrement(&This
->ref
);
639 TRACE("(%p) refcount=%u\n", iface
, ref
);
644 static ULONG WINAPI
TiffFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
646 TiffFrameDecode
*This
= (TiffFrameDecode
*)iface
;
647 ULONG ref
= InterlockedDecrement(&This
->ref
);
649 TRACE("(%p) refcount=%u\n", iface
, ref
);
653 HeapFree(GetProcessHeap(), 0, This
->cached_tile
);
654 HeapFree(GetProcessHeap(), 0, This
);
660 static HRESULT WINAPI
TiffFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
661 UINT
*puiWidth
, UINT
*puiHeight
)
663 TiffFrameDecode
*This
= (TiffFrameDecode
*)iface
;
665 *puiWidth
= This
->decode_info
.width
;
666 *puiHeight
= This
->decode_info
.height
;
668 TRACE("(%p) <-- %ux%u\n", iface
, *puiWidth
, *puiHeight
);
673 static HRESULT WINAPI
TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
674 WICPixelFormatGUID
*pPixelFormat
)
676 TiffFrameDecode
*This
= (TiffFrameDecode
*)iface
;
678 memcpy(pPixelFormat
, This
->decode_info
.format
, sizeof(GUID
));
680 TRACE("(%p) <-- %s\n", This
, debugstr_guid(This
->decode_info
.format
));
685 static HRESULT WINAPI
TiffFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
686 double *pDpiX
, double *pDpiY
)
688 FIXME("(%p,%p,%p)\n", iface
, pDpiX
, pDpiY
);
692 static HRESULT WINAPI
TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
693 IWICPalette
*pIPalette
)
695 FIXME("(%p,%p)\n", iface
, pIPalette
);
699 static HRESULT
TiffFrameDecode_ReadTile(TiffFrameDecode
*This
, UINT tile_x
, UINT tile_y
)
705 swap_bytes
= pTIFFIsByteSwapped(This
->parent
->tiff
);
707 ret
= pTIFFSetDirectory(This
->parent
->tiff
, This
->index
);
714 ret
= pTIFFReadEncodedStrip(This
->parent
->tiff
, tile_y
, This
->cached_tile
, This
->decode_info
.tile_size
);
720 if (hr
== S_OK
&& This
->decode_info
.reverse_bgr
)
722 if (This
->decode_info
.format
== &GUID_WICPixelFormat24bppBGR
)
724 UINT i
, total_pixels
;
727 total_pixels
= This
->decode_info
.tile_width
* This
->decode_info
.tile_height
;
728 pixel
= This
->cached_tile
;
729 for (i
=0; i
<total_pixels
; i
++)
739 if (hr
== S_OK
&& swap_bytes
&& This
->decode_info
.bps
> 8)
741 UINT row
, i
, samples_per_row
;
744 samples_per_row
= This
->decode_info
.tile_width
* This
->decode_info
.samples
;
746 switch(This
->decode_info
.bps
)
749 for (row
=0; row
<This
->decode_info
.tile_height
; row
++)
751 sample
= This
->cached_tile
+ row
* This
->decode_info
.tile_stride
;
752 for (i
=0; i
<samples_per_row
; i
++)
755 sample
[1] = sample
[0];
762 ERR("unhandled bps for byte swap %u\n", This
->decode_info
.bps
);
767 if (hr
== S_OK
&& This
->decode_info
.invert_grayscale
)
771 if (This
->decode_info
.samples
!= 1)
773 ERR("cannot invert grayscale image with %u samples\n", This
->decode_info
.samples
);
777 end
= This
->cached_tile
+This
->decode_info
.tile_size
;
779 for (byte
= This
->cached_tile
; byte
!= end
; byte
++)
785 This
->cached_tile_x
= tile_x
;
786 This
->cached_tile_y
= tile_y
;
792 static HRESULT WINAPI
TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
793 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
795 TiffFrameDecode
*This
= (TiffFrameDecode
*)iface
;
796 UINT min_tile_x
, max_tile_x
, min_tile_y
, max_tile_y
;
803 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
805 if (prc
->X
< 0 || prc
->Y
< 0 || prc
->X
+prc
->Width
> This
->decode_info
.width
||
806 prc
->Y
+prc
->Height
> This
->decode_info
.height
)
809 bytesperrow
= ((This
->decode_info
.bpp
* prc
->Width
)+7)/8;
811 if (cbStride
< bytesperrow
)
814 if ((cbStride
* prc
->Height
) > cbBufferSize
)
817 min_tile_x
= prc
->X
/ This
->decode_info
.tile_width
;
818 min_tile_y
= prc
->Y
/ This
->decode_info
.tile_height
;
819 max_tile_x
= (prc
->X
+prc
->Width
-1) / This
->decode_info
.tile_width
;
820 max_tile_y
= (prc
->Y
+prc
->Height
-1) / This
->decode_info
.tile_height
;
822 EnterCriticalSection(&This
->parent
->lock
);
824 for (tile_x
=min_tile_x
; tile_x
<= max_tile_x
; tile_x
++)
826 for (tile_y
=min_tile_y
; tile_y
<= max_tile_y
; tile_y
++)
828 if (tile_x
!= This
->cached_tile_x
|| tile_y
!= This
->cached_tile_y
)
830 hr
= TiffFrameDecode_ReadTile(This
, tile_x
, tile_y
);
835 if (prc
->X
< tile_x
* This
->decode_info
.tile_width
)
838 rc
.X
= prc
->X
- tile_x
* This
->decode_info
.tile_width
;
840 if (prc
->Y
< tile_y
* This
->decode_info
.tile_height
)
843 rc
.Y
= prc
->Y
- tile_y
* This
->decode_info
.tile_height
;
845 if (prc
->X
+prc
->Width
> (tile_x
+1) * This
->decode_info
.tile_width
)
846 rc
.Width
= This
->decode_info
.tile_width
- rc
.X
;
847 else if (prc
->X
< tile_x
* This
->decode_info
.tile_width
)
848 rc
.Width
= prc
->Width
+ prc
->X
- tile_x
* This
->decode_info
.tile_width
;
850 rc
.Width
= prc
->Width
;
852 if (prc
->Y
+prc
->Height
> (tile_y
+1) * This
->decode_info
.tile_height
)
853 rc
.Height
= This
->decode_info
.tile_height
- rc
.Y
;
854 else if (prc
->Y
< tile_y
* This
->decode_info
.tile_height
)
855 rc
.Height
= prc
->Height
+ prc
->Y
- tile_y
* This
->decode_info
.tile_height
;
857 rc
.Height
= prc
->Height
;
859 dst_tilepos
= pbBuffer
+ (cbStride
* ((rc
.Y
+ tile_y
* This
->decode_info
.tile_height
) - prc
->Y
)) +
860 ((This
->decode_info
.bpp
* ((rc
.X
+ tile_x
* This
->decode_info
.tile_width
) - prc
->X
) + 7) / 8);
862 hr
= copy_pixels(This
->decode_info
.bpp
, This
->cached_tile
,
863 This
->decode_info
.tile_width
, This
->decode_info
.tile_height
, This
->decode_info
.tile_stride
,
864 &rc
, cbStride
, cbBufferSize
, dst_tilepos
);
869 LeaveCriticalSection(&This
->parent
->lock
);
870 TRACE("<-- 0x%x\n", hr
);
876 LeaveCriticalSection(&This
->parent
->lock
);
881 static HRESULT WINAPI
TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
882 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
884 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryReader
);
888 static HRESULT WINAPI
TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
889 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
891 FIXME("(%p,%u,%p,%p): stub\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
895 static HRESULT WINAPI
TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
896 IWICBitmapSource
**ppIThumbnail
)
898 FIXME("(%p,%p): stub\n", iface
, ppIThumbnail
);
902 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl
= {
903 TiffFrameDecode_QueryInterface
,
904 TiffFrameDecode_AddRef
,
905 TiffFrameDecode_Release
,
906 TiffFrameDecode_GetSize
,
907 TiffFrameDecode_GetPixelFormat
,
908 TiffFrameDecode_GetResolution
,
909 TiffFrameDecode_CopyPalette
,
910 TiffFrameDecode_CopyPixels
,
911 TiffFrameDecode_GetMetadataQueryReader
,
912 TiffFrameDecode_GetColorContexts
,
913 TiffFrameDecode_GetThumbnail
916 HRESULT
TiffDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
921 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
925 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
929 ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF
);
933 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder
));
934 if (!This
) return E_OUTOFMEMORY
;
936 This
->lpVtbl
= &TiffDecoder_Vtbl
;
939 InitializeCriticalSection(&This
->lock
);
940 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": TiffDecoder.lock");
942 This
->initialized
= FALSE
;
944 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
945 IUnknown_Release((IUnknown
*)This
);
950 #else /* !SONAME_LIBTIFF */
952 HRESULT
TiffDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
954 ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");