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(TIFFReadEncodedTile
);
66 MAKE_FUNCPTR(TIFFSetDirectory
);
67 MAKE_FUNCPTR(TIFFWriteDirectory
);
70 static void *load_libtiff(void)
74 EnterCriticalSection(&init_tiff_cs
);
76 if (!libtiff_handle
&&
77 (libtiff_handle
= wine_dlopen(SONAME_LIBTIFF
, RTLD_NOW
, NULL
, 0)) != NULL
)
80 #define LOAD_FUNCPTR(f) \
81 if((p##f = wine_dlsym(libtiff_handle, #f, NULL, 0)) == NULL) { \
82 ERR("failed to load symbol %s\n", #f); \
83 libtiff_handle = NULL; \
84 LeaveCriticalSection(&init_tiff_cs); \
87 LOAD_FUNCPTR(TIFFClientOpen
);
88 LOAD_FUNCPTR(TIFFClose
);
89 LOAD_FUNCPTR(TIFFCurrentDirectory
);
90 LOAD_FUNCPTR(TIFFGetField
);
91 LOAD_FUNCPTR(TIFFIsByteSwapped
);
92 LOAD_FUNCPTR(TIFFReadDirectory
);
93 LOAD_FUNCPTR(TIFFReadEncodedStrip
);
94 LOAD_FUNCPTR(TIFFReadEncodedTile
);
95 LOAD_FUNCPTR(TIFFSetDirectory
);
96 LOAD_FUNCPTR(TIFFWriteDirectory
);
101 result
= libtiff_handle
;
103 LeaveCriticalSection(&init_tiff_cs
);
107 static tsize_t
tiff_stream_read(thandle_t client_data
, tdata_t data
, tsize_t size
)
109 IStream
*stream
= (IStream
*)client_data
;
113 hr
= IStream_Read(stream
, data
, size
, &bytes_read
);
114 if (FAILED(hr
)) bytes_read
= 0;
118 static tsize_t
tiff_stream_write(thandle_t client_data
, tdata_t data
, tsize_t size
)
120 IStream
*stream
= (IStream
*)client_data
;
124 hr
= IStream_Write(stream
, data
, size
, &bytes_written
);
125 if (FAILED(hr
)) bytes_written
= 0;
126 return bytes_written
;
129 static toff_t
tiff_stream_seek(thandle_t client_data
, toff_t offset
, int whence
)
131 IStream
*stream
= (IStream
*)client_data
;
134 ULARGE_INTEGER new_position
;
137 move
.QuadPart
= offset
;
141 origin
= STREAM_SEEK_SET
;
144 origin
= STREAM_SEEK_CUR
;
147 origin
= STREAM_SEEK_END
;
150 ERR("unknown whence value %i\n", whence
);
154 hr
= IStream_Seek(stream
, move
, origin
, &new_position
);
155 if (SUCCEEDED(hr
)) return new_position
.QuadPart
;
159 static int tiff_stream_close(thandle_t client_data
)
161 /* Caller is responsible for releasing the stream object. */
165 static toff_t
tiff_stream_size(thandle_t client_data
)
167 IStream
*stream
= (IStream
*)client_data
;
171 hr
= IStream_Stat(stream
, &statstg
, STATFLAG_NONAME
);
173 if (SUCCEEDED(hr
)) return statstg
.cbSize
.QuadPart
;
177 static int tiff_stream_map(thandle_t client_data
, tdata_t
*addr
, toff_t
*size
)
179 /* Cannot mmap streams */
183 static void tiff_stream_unmap(thandle_t client_data
, tdata_t addr
, toff_t size
)
185 /* No need to ever do this, since we can't map things. */
188 static TIFF
* tiff_open_stream(IStream
*stream
, const char *mode
)
193 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
195 return pTIFFClientOpen("<IStream object>", mode
, stream
, tiff_stream_read
,
196 tiff_stream_write
, tiff_stream_seek
, tiff_stream_close
,
197 tiff_stream_size
, tiff_stream_map
, tiff_stream_unmap
);
201 IWICBitmapDecoder IWICBitmapDecoder_iface
;
204 CRITICAL_SECTION lock
; /* Must be held when tiff is used or initiailzed is set */
210 const WICPixelFormatGUID
*format
;
217 int invert_grayscale
;
219 UINT tile_width
, tile_height
;
224 UINT resolution_unit
;
229 IWICBitmapFrameDecode IWICBitmapFrameDecode_iface
;
233 tiff_decode_info decode_info
;
234 INT cached_tile_x
, cached_tile_y
;
238 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl
;
240 static inline TiffDecoder
*impl_from_IWICBitmapDecoder(IWICBitmapDecoder
*iface
)
242 return CONTAINING_RECORD(iface
, TiffDecoder
, IWICBitmapDecoder_iface
);
245 static inline TiffFrameDecode
*impl_from_IWICBitmapFrameDecode(IWICBitmapFrameDecode
*iface
)
247 return CONTAINING_RECORD(iface
, TiffFrameDecode
, IWICBitmapFrameDecode_iface
);
250 static HRESULT
tiff_get_decode_info(TIFF
*tiff
, tiff_decode_info
*decode_info
)
252 uint16 photometric
, bps
, samples
, planar
;
253 uint16 extra_sample_count
, *extra_samples
;
256 decode_info
->indexed
= 0;
257 decode_info
->reverse_bgr
= 0;
258 decode_info
->invert_grayscale
= 0;
259 decode_info
->tiled
= 0;
261 ret
= pTIFFGetField(tiff
, TIFFTAG_PHOTOMETRIC
, &photometric
);
264 WARN("missing PhotometricInterpretation tag\n");
268 ret
= pTIFFGetField(tiff
, TIFFTAG_BITSPERSAMPLE
, &bps
);
270 decode_info
->bps
= bps
;
272 ret
= pTIFFGetField(tiff
, TIFFTAG_SAMPLESPERPIXEL
, &samples
);
273 if (!ret
) samples
= 1;
274 decode_info
->samples
= samples
;
280 ret
= pTIFFGetField(tiff
, TIFFTAG_PLANARCONFIG
, &planar
);
281 if (!ret
) planar
= 1;
284 FIXME("unhandled planar configuration %u\n", planar
);
288 decode_info
->planar
= planar
;
292 case 0: /* WhiteIsZero */
293 decode_info
->invert_grayscale
= 1;
294 case 1: /* BlackIsZero */
297 FIXME("unhandled grayscale sample count %u\n", samples
);
301 decode_info
->bpp
= bps
;
305 decode_info
->format
= &GUID_WICPixelFormatBlackWhite
;
308 decode_info
->format
= &GUID_WICPixelFormat4bppGray
;
311 decode_info
->format
= &GUID_WICPixelFormat8bppGray
;
314 FIXME("unhandled greyscale bit count %u\n", bps
);
319 decode_info
->bpp
= bps
* samples
;
323 ret
= pTIFFGetField(tiff
, TIFFTAG_EXTRASAMPLES
, &extra_sample_count
, &extra_samples
);
326 WARN("Cannot get extra sample type for RGB data, ret=%i count=%i\n", ret
, extra_sample_count
);
330 else if (samples
!= 3)
332 FIXME("unhandled RGB sample count %u\n", samples
);
339 decode_info
->reverse_bgr
= 1;
341 decode_info
->format
= &GUID_WICPixelFormat24bppBGR
;
343 switch(extra_samples
[0])
345 case 0: /* Unspecified data */
346 decode_info
->format
= &GUID_WICPixelFormat32bppBGR
;
348 case 1: /* Associated (pre-multiplied) alpha data */
349 decode_info
->format
= &GUID_WICPixelFormat32bppPBGRA
;
351 case 2: /* Unassociated alpha data */
352 decode_info
->format
= &GUID_WICPixelFormat32bppBGRA
;
355 FIXME("unhandled extra sample type %i\n", extra_samples
[0]);
361 decode_info
->format
= &GUID_WICPixelFormat48bppRGB
;
363 switch(extra_samples
[0])
365 case 0: /* Unspecified data */
366 /* decode_info->format = &GUID_WICPixelFormat64bppRGB; */
367 FIXME("64-bit RGB is unsupported\n");
369 case 1: /* Associated (pre-multiplied) alpha data */
370 decode_info
->format
= &GUID_WICPixelFormat64bppPRGBA
;
372 case 2: /* Unassociated alpha data */
373 decode_info
->format
= &GUID_WICPixelFormat64bppRGBA
;
376 FIXME("unhandled extra sample type %i\n", extra_samples
[0]);
381 FIXME("unhandled RGB bit count %u\n", bps
);
385 case 3: /* RGB Palette */
388 FIXME("unhandled indexed sample count %u\n", samples
);
392 decode_info
->indexed
= 1;
393 decode_info
->bpp
= bps
;
397 decode_info
->format
= &GUID_WICPixelFormat4bppIndexed
;
400 decode_info
->format
= &GUID_WICPixelFormat8bppIndexed
;
403 FIXME("unhandled indexed bit count %u\n", bps
);
407 case 4: /* Transparency mask */
412 FIXME("unhandled PhotometricInterpretation %u\n", photometric
);
416 ret
= pTIFFGetField(tiff
, TIFFTAG_IMAGEWIDTH
, &decode_info
->width
);
419 WARN("missing image width\n");
423 ret
= pTIFFGetField(tiff
, TIFFTAG_IMAGELENGTH
, &decode_info
->height
);
426 WARN("missing image length\n");
430 if ((ret
= pTIFFGetField(tiff
, TIFFTAG_TILEWIDTH
, &decode_info
->tile_width
)))
432 decode_info
->tiled
= 1;
436 WARN("missing tile width\n");
440 ret
= pTIFFGetField(tiff
, TIFFTAG_TILELENGTH
, &decode_info
->tile_height
);
443 WARN("missing tile height\n");
447 decode_info
->tile_stride
= ((decode_info
->bpp
* decode_info
->tile_width
+ 7)/8);
448 decode_info
->tile_size
= decode_info
->tile_height
* decode_info
->tile_stride
;
449 decode_info
->tiles_across
= (decode_info
->width
+ decode_info
->tile_width
- 1) / decode_info
->tile_width
;
451 else if ((ret
= pTIFFGetField(tiff
, TIFFTAG_ROWSPERSTRIP
, &decode_info
->tile_height
)))
453 if (decode_info
->tile_height
> decode_info
->height
)
454 decode_info
->tile_height
= decode_info
->height
;
455 decode_info
->tile_width
= decode_info
->width
;
456 decode_info
->tile_stride
= ((decode_info
->bpp
* decode_info
->tile_width
+ 7)/8);
457 decode_info
->tile_size
= decode_info
->tile_height
* decode_info
->tile_stride
;
461 FIXME("missing RowsPerStrip value\n");
465 decode_info
->resolution_unit
= 0;
466 pTIFFGetField(tiff
, TIFFTAG_RESOLUTIONUNIT
, &decode_info
->resolution_unit
);
467 if (decode_info
->resolution_unit
!= 0)
469 ret
= pTIFFGetField(tiff
, TIFFTAG_XRESOLUTION
, &decode_info
->xres
);
472 WARN("missing X resolution\n");
473 decode_info
->resolution_unit
= 0;
476 ret
= pTIFFGetField(tiff
, TIFFTAG_YRESOLUTION
, &decode_info
->yres
);
479 WARN("missing Y resolution\n");
480 decode_info
->resolution_unit
= 0;
487 static HRESULT WINAPI
TiffDecoder_QueryInterface(IWICBitmapDecoder
*iface
, REFIID iid
,
490 TiffDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
491 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
493 if (!ppv
) return E_INVALIDARG
;
495 if (IsEqualIID(&IID_IUnknown
, iid
) || IsEqualIID(&IID_IWICBitmapDecoder
, iid
))
502 return E_NOINTERFACE
;
505 IUnknown_AddRef((IUnknown
*)*ppv
);
509 static ULONG WINAPI
TiffDecoder_AddRef(IWICBitmapDecoder
*iface
)
511 TiffDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
512 ULONG ref
= InterlockedIncrement(&This
->ref
);
514 TRACE("(%p) refcount=%u\n", iface
, ref
);
519 static ULONG WINAPI
TiffDecoder_Release(IWICBitmapDecoder
*iface
)
521 TiffDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
522 ULONG ref
= InterlockedDecrement(&This
->ref
);
524 TRACE("(%p) refcount=%u\n", iface
, ref
);
528 if (This
->tiff
) pTIFFClose(This
->tiff
);
529 if (This
->stream
) IStream_Release(This
->stream
);
530 This
->lock
.DebugInfo
->Spare
[0] = 0;
531 DeleteCriticalSection(&This
->lock
);
532 HeapFree(GetProcessHeap(), 0, This
);
538 static HRESULT WINAPI
TiffDecoder_QueryCapability(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
539 DWORD
*pdwCapability
)
541 FIXME("(%p,%p,%p): stub\n", iface
, pIStream
, pdwCapability
);
545 static HRESULT WINAPI
TiffDecoder_Initialize(IWICBitmapDecoder
*iface
, IStream
*pIStream
,
546 WICDecodeOptions cacheOptions
)
548 TiffDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
552 TRACE("(%p,%p,%x): stub\n", iface
, pIStream
, cacheOptions
);
554 EnterCriticalSection(&This
->lock
);
556 if (This
->initialized
)
558 hr
= WINCODEC_ERR_WRONGSTATE
;
562 tiff
= tiff_open_stream(pIStream
, "r");
571 This
->stream
= pIStream
;
572 IStream_AddRef(pIStream
);
573 This
->initialized
= TRUE
;
576 LeaveCriticalSection(&This
->lock
);
580 static HRESULT WINAPI
TiffDecoder_GetContainerFormat(IWICBitmapDecoder
*iface
,
581 GUID
*pguidContainerFormat
)
583 memcpy(pguidContainerFormat
, &GUID_ContainerFormatTiff
, sizeof(GUID
));
587 static HRESULT WINAPI
TiffDecoder_GetDecoderInfo(IWICBitmapDecoder
*iface
,
588 IWICBitmapDecoderInfo
**ppIDecoderInfo
)
590 FIXME("(%p,%p): stub\n", iface
, ppIDecoderInfo
);
594 static HRESULT WINAPI
TiffDecoder_CopyPalette(IWICBitmapDecoder
*iface
,
595 IWICPalette
*pIPalette
)
597 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
601 static HRESULT WINAPI
TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder
*iface
,
602 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
604 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryReader
);
608 static HRESULT WINAPI
TiffDecoder_GetPreview(IWICBitmapDecoder
*iface
,
609 IWICBitmapSource
**ppIBitmapSource
)
611 FIXME("(%p,%p): stub\n", iface
, ppIBitmapSource
);
615 static HRESULT WINAPI
TiffDecoder_GetColorContexts(IWICBitmapDecoder
*iface
,
616 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
618 FIXME("(%p,%u,%p,%p)\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
622 static HRESULT WINAPI
TiffDecoder_GetThumbnail(IWICBitmapDecoder
*iface
,
623 IWICBitmapSource
**ppIThumbnail
)
625 TRACE("(%p,%p)\n", iface
, ppIThumbnail
);
626 return WINCODEC_ERR_CODECNOTHUMBNAIL
;
629 static HRESULT WINAPI
TiffDecoder_GetFrameCount(IWICBitmapDecoder
*iface
,
632 TiffDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
636 WARN("(%p) <-- WINCODEC_ERR_WRONGSTATE\n", iface
);
637 return WINCODEC_ERR_WRONGSTATE
;
640 EnterCriticalSection(&This
->lock
);
641 while (pTIFFReadDirectory(This
->tiff
)) { }
642 *pCount
= pTIFFCurrentDirectory(This
->tiff
)+1;
643 LeaveCriticalSection(&This
->lock
);
645 TRACE("(%p) <-- %i\n", iface
, *pCount
);
650 static HRESULT WINAPI
TiffDecoder_GetFrame(IWICBitmapDecoder
*iface
,
651 UINT index
, IWICBitmapFrameDecode
**ppIBitmapFrame
)
653 TiffDecoder
*This
= impl_from_IWICBitmapDecoder(iface
);
654 TiffFrameDecode
*result
;
656 tiff_decode_info decode_info
;
659 TRACE("(%p,%u,%p)\n", iface
, index
, ppIBitmapFrame
);
662 return WINCODEC_ERR_WRONGSTATE
;
664 EnterCriticalSection(&This
->lock
);
665 res
= pTIFFSetDirectory(This
->tiff
, index
);
666 if (!res
) hr
= E_INVALIDARG
;
667 else hr
= tiff_get_decode_info(This
->tiff
, &decode_info
);
668 LeaveCriticalSection(&This
->lock
);
672 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(TiffFrameDecode
));
676 result
->IWICBitmapFrameDecode_iface
.lpVtbl
= &TiffFrameDecode_Vtbl
;
678 result
->parent
= This
;
679 result
->index
= index
;
680 result
->decode_info
= decode_info
;
681 result
->cached_tile_x
= -1;
682 result
->cached_tile
= HeapAlloc(GetProcessHeap(), 0, decode_info
.tile_size
);
684 if (result
->cached_tile
)
685 *ppIBitmapFrame
= (IWICBitmapFrameDecode
*)result
;
689 HeapFree(GetProcessHeap(), 0, result
);
692 else hr
= E_OUTOFMEMORY
;
695 if (FAILED(hr
)) *ppIBitmapFrame
= NULL
;
700 static const IWICBitmapDecoderVtbl TiffDecoder_Vtbl
= {
701 TiffDecoder_QueryInterface
,
704 TiffDecoder_QueryCapability
,
705 TiffDecoder_Initialize
,
706 TiffDecoder_GetContainerFormat
,
707 TiffDecoder_GetDecoderInfo
,
708 TiffDecoder_CopyPalette
,
709 TiffDecoder_GetMetadataQueryReader
,
710 TiffDecoder_GetPreview
,
711 TiffDecoder_GetColorContexts
,
712 TiffDecoder_GetThumbnail
,
713 TiffDecoder_GetFrameCount
,
717 static HRESULT WINAPI
TiffFrameDecode_QueryInterface(IWICBitmapFrameDecode
*iface
, REFIID iid
,
720 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
721 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
723 if (!ppv
) return E_INVALIDARG
;
725 if (IsEqualIID(&IID_IUnknown
, iid
) ||
726 IsEqualIID(&IID_IWICBitmapSource
, iid
) ||
727 IsEqualIID(&IID_IWICBitmapFrameDecode
, iid
))
734 return E_NOINTERFACE
;
737 IUnknown_AddRef((IUnknown
*)*ppv
);
741 static ULONG WINAPI
TiffFrameDecode_AddRef(IWICBitmapFrameDecode
*iface
)
743 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
744 ULONG ref
= InterlockedIncrement(&This
->ref
);
746 TRACE("(%p) refcount=%u\n", iface
, ref
);
751 static ULONG WINAPI
TiffFrameDecode_Release(IWICBitmapFrameDecode
*iface
)
753 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
754 ULONG ref
= InterlockedDecrement(&This
->ref
);
756 TRACE("(%p) refcount=%u\n", iface
, ref
);
760 HeapFree(GetProcessHeap(), 0, This
->cached_tile
);
761 HeapFree(GetProcessHeap(), 0, This
);
767 static HRESULT WINAPI
TiffFrameDecode_GetSize(IWICBitmapFrameDecode
*iface
,
768 UINT
*puiWidth
, UINT
*puiHeight
)
770 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
772 *puiWidth
= This
->decode_info
.width
;
773 *puiHeight
= This
->decode_info
.height
;
775 TRACE("(%p) <-- %ux%u\n", iface
, *puiWidth
, *puiHeight
);
780 static HRESULT WINAPI
TiffFrameDecode_GetPixelFormat(IWICBitmapFrameDecode
*iface
,
781 WICPixelFormatGUID
*pPixelFormat
)
783 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
785 memcpy(pPixelFormat
, This
->decode_info
.format
, sizeof(GUID
));
787 TRACE("(%p) <-- %s\n", This
, debugstr_guid(This
->decode_info
.format
));
792 static HRESULT WINAPI
TiffFrameDecode_GetResolution(IWICBitmapFrameDecode
*iface
,
793 double *pDpiX
, double *pDpiY
)
795 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
797 switch (This
->decode_info
.resolution_unit
)
800 FIXME("unknown resolution unit %i\n", This
->decode_info
.resolution_unit
);
802 case 0: /* Not set */
803 *pDpiX
= *pDpiY
= 96.0;
805 case 1: /* Relative measurements */
807 *pDpiY
= 96.0 * This
->decode_info
.yres
/ This
->decode_info
.xres
;
810 *pDpiX
= This
->decode_info
.xres
;
811 *pDpiY
= This
->decode_info
.yres
;
813 case 3: /* Centimeter */
814 *pDpiX
= This
->decode_info
.xres
/ 2.54;
815 *pDpiY
= This
->decode_info
.yres
/ 2.54;
819 TRACE("(%p) <-- %f,%f unit=%i\n", iface
, *pDpiX
, *pDpiY
, This
->decode_info
.resolution_unit
);
824 static HRESULT WINAPI
TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode
*iface
,
825 IWICPalette
*pIPalette
)
827 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
828 uint16
*red
, *green
, *blue
;
829 WICColor colors
[256];
830 int color_count
, ret
, i
;
832 TRACE("(%p,%p)\n", iface
, pIPalette
);
834 color_count
= 1<<This
->decode_info
.bps
;
836 EnterCriticalSection(&This
->parent
->lock
);
837 ret
= pTIFFGetField(This
->parent
->tiff
, TIFFTAG_COLORMAP
, &red
, &green
, &blue
);
838 LeaveCriticalSection(&This
->parent
->lock
);
842 WARN("Couldn't read color map\n");
846 for (i
=0; i
<color_count
; i
++)
848 colors
[i
] = 0xff000000 |
849 ((red
[i
]<<8) & 0xff0000) |
850 (green
[i
] & 0xff00) |
851 ((blue
[i
]>>8) & 0xff);
854 return IWICPalette_InitializeCustom(pIPalette
, colors
, color_count
);
857 static HRESULT
TiffFrameDecode_ReadTile(TiffFrameDecode
*This
, UINT tile_x
, UINT tile_y
)
863 swap_bytes
= pTIFFIsByteSwapped(This
->parent
->tiff
);
865 ret
= pTIFFSetDirectory(This
->parent
->tiff
, This
->index
);
872 if (This
->decode_info
.tiled
)
874 ret
= pTIFFReadEncodedTile(This
->parent
->tiff
, tile_x
+ tile_y
* This
->decode_info
.tiles_across
, This
->cached_tile
, This
->decode_info
.tile_size
);
878 ret
= pTIFFReadEncodedStrip(This
->parent
->tiff
, tile_y
, This
->cached_tile
, This
->decode_info
.tile_size
);
885 if (hr
== S_OK
&& This
->decode_info
.reverse_bgr
)
887 if (This
->decode_info
.bps
== 8)
889 UINT sample_count
= This
->decode_info
.samples
;
891 reverse_bgr8(sample_count
, This
->cached_tile
, This
->decode_info
.tile_width
,
892 This
->decode_info
.tile_height
, This
->decode_info
.tile_width
* sample_count
);
896 if (hr
== S_OK
&& swap_bytes
&& This
->decode_info
.bps
> 8)
898 UINT row
, i
, samples_per_row
;
901 samples_per_row
= This
->decode_info
.tile_width
* This
->decode_info
.samples
;
903 switch(This
->decode_info
.bps
)
906 for (row
=0; row
<This
->decode_info
.tile_height
; row
++)
908 sample
= This
->cached_tile
+ row
* This
->decode_info
.tile_stride
;
909 for (i
=0; i
<samples_per_row
; i
++)
912 sample
[1] = sample
[0];
919 ERR("unhandled bps for byte swap %u\n", This
->decode_info
.bps
);
924 if (hr
== S_OK
&& This
->decode_info
.invert_grayscale
)
928 if (This
->decode_info
.samples
!= 1)
930 ERR("cannot invert grayscale image with %u samples\n", This
->decode_info
.samples
);
934 end
= This
->cached_tile
+This
->decode_info
.tile_size
;
936 for (byte
= This
->cached_tile
; byte
!= end
; byte
++)
942 This
->cached_tile_x
= tile_x
;
943 This
->cached_tile_y
= tile_y
;
949 static HRESULT WINAPI
TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode
*iface
,
950 const WICRect
*prc
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbBuffer
)
952 TiffFrameDecode
*This
= impl_from_IWICBitmapFrameDecode(iface
);
953 UINT min_tile_x
, max_tile_x
, min_tile_y
, max_tile_y
;
961 TRACE("(%p,%p,%u,%u,%p)\n", iface
, prc
, cbStride
, cbBufferSize
, pbBuffer
);
967 rect
.Width
= This
->decode_info
.width
;
968 rect
.Height
= This
->decode_info
.height
;
973 if (prc
->X
< 0 || prc
->Y
< 0 || prc
->X
+prc
->Width
> This
->decode_info
.width
||
974 prc
->Y
+prc
->Height
> This
->decode_info
.height
)
978 bytesperrow
= ((This
->decode_info
.bpp
* prc
->Width
)+7)/8;
980 if (cbStride
< bytesperrow
)
983 if ((cbStride
* prc
->Height
) > cbBufferSize
)
986 min_tile_x
= prc
->X
/ This
->decode_info
.tile_width
;
987 min_tile_y
= prc
->Y
/ This
->decode_info
.tile_height
;
988 max_tile_x
= (prc
->X
+prc
->Width
-1) / This
->decode_info
.tile_width
;
989 max_tile_y
= (prc
->Y
+prc
->Height
-1) / This
->decode_info
.tile_height
;
991 EnterCriticalSection(&This
->parent
->lock
);
993 for (tile_x
=min_tile_x
; tile_x
<= max_tile_x
; tile_x
++)
995 for (tile_y
=min_tile_y
; tile_y
<= max_tile_y
; tile_y
++)
997 if (tile_x
!= This
->cached_tile_x
|| tile_y
!= This
->cached_tile_y
)
999 hr
= TiffFrameDecode_ReadTile(This
, tile_x
, tile_y
);
1004 if (prc
->X
< tile_x
* This
->decode_info
.tile_width
)
1007 rc
.X
= prc
->X
- tile_x
* This
->decode_info
.tile_width
;
1009 if (prc
->Y
< tile_y
* This
->decode_info
.tile_height
)
1012 rc
.Y
= prc
->Y
- tile_y
* This
->decode_info
.tile_height
;
1014 if (prc
->X
+prc
->Width
> (tile_x
+1) * This
->decode_info
.tile_width
)
1015 rc
.Width
= This
->decode_info
.tile_width
- rc
.X
;
1016 else if (prc
->X
< tile_x
* This
->decode_info
.tile_width
)
1017 rc
.Width
= prc
->Width
+ prc
->X
- tile_x
* This
->decode_info
.tile_width
;
1019 rc
.Width
= prc
->Width
;
1021 if (prc
->Y
+prc
->Height
> (tile_y
+1) * This
->decode_info
.tile_height
)
1022 rc
.Height
= This
->decode_info
.tile_height
- rc
.Y
;
1023 else if (prc
->Y
< tile_y
* This
->decode_info
.tile_height
)
1024 rc
.Height
= prc
->Height
+ prc
->Y
- tile_y
* This
->decode_info
.tile_height
;
1026 rc
.Height
= prc
->Height
;
1028 dst_tilepos
= pbBuffer
+ (cbStride
* ((rc
.Y
+ tile_y
* This
->decode_info
.tile_height
) - prc
->Y
)) +
1029 ((This
->decode_info
.bpp
* ((rc
.X
+ tile_x
* This
->decode_info
.tile_width
) - prc
->X
) + 7) / 8);
1031 hr
= copy_pixels(This
->decode_info
.bpp
, This
->cached_tile
,
1032 This
->decode_info
.tile_width
, This
->decode_info
.tile_height
, This
->decode_info
.tile_stride
,
1033 &rc
, cbStride
, cbBufferSize
, dst_tilepos
);
1038 LeaveCriticalSection(&This
->parent
->lock
);
1039 TRACE("<-- 0x%x\n", hr
);
1045 LeaveCriticalSection(&This
->parent
->lock
);
1050 static HRESULT WINAPI
TiffFrameDecode_GetMetadataQueryReader(IWICBitmapFrameDecode
*iface
,
1051 IWICMetadataQueryReader
**ppIMetadataQueryReader
)
1053 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryReader
);
1057 static HRESULT WINAPI
TiffFrameDecode_GetColorContexts(IWICBitmapFrameDecode
*iface
,
1058 UINT cCount
, IWICColorContext
**ppIColorContexts
, UINT
*pcActualCount
)
1060 FIXME("(%p,%u,%p,%p): stub\n", iface
, cCount
, ppIColorContexts
, pcActualCount
);
1064 static HRESULT WINAPI
TiffFrameDecode_GetThumbnail(IWICBitmapFrameDecode
*iface
,
1065 IWICBitmapSource
**ppIThumbnail
)
1067 FIXME("(%p,%p): stub\n", iface
, ppIThumbnail
);
1071 static const IWICBitmapFrameDecodeVtbl TiffFrameDecode_Vtbl
= {
1072 TiffFrameDecode_QueryInterface
,
1073 TiffFrameDecode_AddRef
,
1074 TiffFrameDecode_Release
,
1075 TiffFrameDecode_GetSize
,
1076 TiffFrameDecode_GetPixelFormat
,
1077 TiffFrameDecode_GetResolution
,
1078 TiffFrameDecode_CopyPalette
,
1079 TiffFrameDecode_CopyPixels
,
1080 TiffFrameDecode_GetMetadataQueryReader
,
1081 TiffFrameDecode_GetColorContexts
,
1082 TiffFrameDecode_GetThumbnail
1085 HRESULT
TiffDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1090 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1094 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1096 if (!load_libtiff())
1098 ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF
);
1102 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(TiffDecoder
));
1103 if (!This
) return E_OUTOFMEMORY
;
1105 This
->IWICBitmapDecoder_iface
.lpVtbl
= &TiffDecoder_Vtbl
;
1107 This
->stream
= NULL
;
1108 InitializeCriticalSection(&This
->lock
);
1109 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": TiffDecoder.lock");
1111 This
->initialized
= FALSE
;
1113 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
1114 IUnknown_Release((IUnknown
*)This
);
1119 typedef struct TiffEncoder
{
1120 IWICBitmapEncoder IWICBitmapEncoder_iface
;
1123 CRITICAL_SECTION lock
; /* Must be held when tiff is used or fields below are set */
1127 ULONG num_frames_committed
;
1130 static inline TiffEncoder
*impl_from_IWICBitmapEncoder(IWICBitmapEncoder
*iface
)
1132 return CONTAINING_RECORD(iface
, TiffEncoder
, IWICBitmapEncoder_iface
);
1135 typedef struct TiffFrameEncode
{
1136 IWICBitmapFrameEncode IWICBitmapFrameEncode_iface
;
1138 TiffEncoder
*parent
;
1141 static inline TiffFrameEncode
*impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode
*iface
)
1143 return CONTAINING_RECORD(iface
, TiffFrameEncode
, IWICBitmapFrameEncode_iface
);
1146 static HRESULT WINAPI
TiffFrameEncode_QueryInterface(IWICBitmapFrameEncode
*iface
, REFIID iid
,
1149 TiffFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1150 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1152 if (!ppv
) return E_INVALIDARG
;
1154 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1155 IsEqualIID(&IID_IWICBitmapFrameEncode
, iid
))
1157 *ppv
= &This
->IWICBitmapFrameEncode_iface
;
1162 return E_NOINTERFACE
;
1165 IUnknown_AddRef((IUnknown
*)*ppv
);
1169 static ULONG WINAPI
TiffFrameEncode_AddRef(IWICBitmapFrameEncode
*iface
)
1171 TiffFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1172 ULONG ref
= InterlockedIncrement(&This
->ref
);
1174 TRACE("(%p) refcount=%u\n", iface
, ref
);
1179 static ULONG WINAPI
TiffFrameEncode_Release(IWICBitmapFrameEncode
*iface
)
1181 TiffFrameEncode
*This
= impl_from_IWICBitmapFrameEncode(iface
);
1182 ULONG ref
= InterlockedDecrement(&This
->ref
);
1184 TRACE("(%p) refcount=%u\n", iface
, ref
);
1188 IWICBitmapEncoder_Release(&This
->parent
->IWICBitmapEncoder_iface
);
1189 HeapFree(GetProcessHeap(), 0, This
);
1195 static HRESULT WINAPI
TiffFrameEncode_Initialize(IWICBitmapFrameEncode
*iface
,
1196 IPropertyBag2
*pIEncoderOptions
)
1198 FIXME("(%p,%p): stub\n", iface
, pIEncoderOptions
);
1202 static HRESULT WINAPI
TiffFrameEncode_SetSize(IWICBitmapFrameEncode
*iface
,
1203 UINT uiWidth
, UINT uiHeight
)
1205 FIXME("(%p,%u,%u): stub\n", iface
, uiWidth
, uiHeight
);
1209 static HRESULT WINAPI
TiffFrameEncode_SetResolution(IWICBitmapFrameEncode
*iface
,
1210 double dpiX
, double dpiY
)
1212 FIXME("(%p,%0.2f,%0.2f): stub\n", iface
, dpiX
, dpiY
);
1216 static HRESULT WINAPI
TiffFrameEncode_SetPixelFormat(IWICBitmapFrameEncode
*iface
,
1217 WICPixelFormatGUID
*pPixelFormat
)
1219 FIXME("(%p,%s)\n", iface
, debugstr_guid(pPixelFormat
));
1223 static HRESULT WINAPI
TiffFrameEncode_SetColorContexts(IWICBitmapFrameEncode
*iface
,
1224 UINT cCount
, IWICColorContext
**ppIColorContext
)
1226 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
1230 static HRESULT WINAPI
TiffFrameEncode_SetPalette(IWICBitmapFrameEncode
*iface
,
1231 IWICPalette
*pIPalette
)
1233 FIXME("(%p,%p): stub\n", iface
, pIPalette
);
1234 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1237 static HRESULT WINAPI
TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode
*iface
,
1238 IWICBitmapSource
*pIThumbnail
)
1240 FIXME("(%p,%p): stub\n", iface
, pIThumbnail
);
1241 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1244 static HRESULT WINAPI
TiffFrameEncode_WritePixels(IWICBitmapFrameEncode
*iface
,
1245 UINT lineCount
, UINT cbStride
, UINT cbBufferSize
, BYTE
*pbPixels
)
1247 FIXME("(%p,%u,%u,%u,%p): stub\n", iface
, lineCount
, cbStride
, cbBufferSize
, pbPixels
);
1251 static HRESULT WINAPI
TiffFrameEncode_WriteSource(IWICBitmapFrameEncode
*iface
,
1252 IWICBitmapSource
*pIBitmapSource
, WICRect
*prc
)
1254 FIXME("(%p,%p,%p): stub\n", iface
, pIBitmapSource
, prc
);
1258 static HRESULT WINAPI
TiffFrameEncode_Commit(IWICBitmapFrameEncode
*iface
)
1260 FIXME("(%p): stub\n", iface
);
1264 static HRESULT WINAPI
TiffFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode
*iface
,
1265 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
1267 FIXME("(%p, %p): stub\n", iface
, ppIMetadataQueryWriter
);
1271 static const IWICBitmapFrameEncodeVtbl TiffFrameEncode_Vtbl
= {
1272 TiffFrameEncode_QueryInterface
,
1273 TiffFrameEncode_AddRef
,
1274 TiffFrameEncode_Release
,
1275 TiffFrameEncode_Initialize
,
1276 TiffFrameEncode_SetSize
,
1277 TiffFrameEncode_SetResolution
,
1278 TiffFrameEncode_SetPixelFormat
,
1279 TiffFrameEncode_SetColorContexts
,
1280 TiffFrameEncode_SetPalette
,
1281 TiffFrameEncode_SetThumbnail
,
1282 TiffFrameEncode_WritePixels
,
1283 TiffFrameEncode_WriteSource
,
1284 TiffFrameEncode_Commit
,
1285 TiffFrameEncode_GetMetadataQueryWriter
1288 static HRESULT WINAPI
TiffEncoder_QueryInterface(IWICBitmapEncoder
*iface
, REFIID iid
,
1291 TiffEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1292 TRACE("(%p,%s,%p)\n", iface
, debugstr_guid(iid
), ppv
);
1294 if (!ppv
) return E_INVALIDARG
;
1296 if (IsEqualIID(&IID_IUnknown
, iid
) ||
1297 IsEqualIID(&IID_IWICBitmapEncoder
, iid
))
1304 return E_NOINTERFACE
;
1307 IUnknown_AddRef((IUnknown
*)*ppv
);
1311 static ULONG WINAPI
TiffEncoder_AddRef(IWICBitmapEncoder
*iface
)
1313 TiffEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1314 ULONG ref
= InterlockedIncrement(&This
->ref
);
1316 TRACE("(%p) refcount=%u\n", iface
, ref
);
1321 static ULONG WINAPI
TiffEncoder_Release(IWICBitmapEncoder
*iface
)
1323 TiffEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1324 ULONG ref
= InterlockedDecrement(&This
->ref
);
1326 TRACE("(%p) refcount=%u\n", iface
, ref
);
1330 if (This
->tiff
) pTIFFClose(This
->tiff
);
1331 if (This
->stream
) IStream_Release(This
->stream
);
1332 This
->lock
.DebugInfo
->Spare
[0] = 0;
1333 DeleteCriticalSection(&This
->lock
);
1334 HeapFree(GetProcessHeap(), 0, This
);
1340 static HRESULT WINAPI
TiffEncoder_Initialize(IWICBitmapEncoder
*iface
,
1341 IStream
*pIStream
, WICBitmapEncoderCacheOption cacheOption
)
1343 TiffEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1347 TRACE("(%p,%p,%u)\n", iface
, pIStream
, cacheOption
);
1349 EnterCriticalSection(&This
->lock
);
1351 if (This
->initialized
)
1353 hr
= WINCODEC_ERR_WRONGSTATE
;
1357 tiff
= tiff_open_stream(pIStream
, "w");
1366 This
->stream
= pIStream
;
1367 IStream_AddRef(pIStream
);
1368 This
->initialized
= TRUE
;
1371 LeaveCriticalSection(&This
->lock
);
1375 static HRESULT WINAPI
TiffEncoder_GetContainerFormat(IWICBitmapEncoder
*iface
,
1376 GUID
*pguidContainerFormat
)
1378 FIXME("(%p,%s): stub\n", iface
, debugstr_guid(pguidContainerFormat
));
1382 static HRESULT WINAPI
TiffEncoder_GetEncoderInfo(IWICBitmapEncoder
*iface
,
1383 IWICBitmapEncoderInfo
**ppIEncoderInfo
)
1385 FIXME("(%p,%p): stub\n", iface
, ppIEncoderInfo
);
1389 static HRESULT WINAPI
TiffEncoder_SetColorContexts(IWICBitmapEncoder
*iface
,
1390 UINT cCount
, IWICColorContext
**ppIColorContext
)
1392 FIXME("(%p,%u,%p): stub\n", iface
, cCount
, ppIColorContext
);
1396 static HRESULT WINAPI
TiffEncoder_SetPalette(IWICBitmapEncoder
*iface
, IWICPalette
*pIPalette
)
1398 TRACE("(%p,%p)\n", iface
, pIPalette
);
1399 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1402 static HRESULT WINAPI
TiffEncoder_SetThumbnail(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIThumbnail
)
1404 TRACE("(%p,%p)\n", iface
, pIThumbnail
);
1405 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1408 static HRESULT WINAPI
TiffEncoder_SetPreview(IWICBitmapEncoder
*iface
, IWICBitmapSource
*pIPreview
)
1410 TRACE("(%p,%p)\n", iface
, pIPreview
);
1411 return WINCODEC_ERR_UNSUPPORTEDOPERATION
;
1414 static HRESULT WINAPI
TiffEncoder_CreateNewFrame(IWICBitmapEncoder
*iface
,
1415 IWICBitmapFrameEncode
**ppIFrameEncode
, IPropertyBag2
**ppIEncoderOptions
)
1417 TiffEncoder
*This
= impl_from_IWICBitmapEncoder(iface
);
1418 TiffFrameEncode
*result
;
1422 TRACE("(%p,%p,%p)\n", iface
, ppIFrameEncode
, ppIEncoderOptions
);
1424 EnterCriticalSection(&This
->lock
);
1426 if (This
->num_frames
!= This
->num_frames_committed
)
1428 FIXME("New frame created before previous frame was committed\n");
1434 hr
= CreatePropertyBag2(ppIEncoderOptions
);
1439 result
= HeapAlloc(GetProcessHeap(), 0, sizeof(*result
));
1443 result
->IWICBitmapFrameEncode_iface
.lpVtbl
= &TiffFrameEncode_Vtbl
;
1445 result
->parent
= This
;
1447 IWICBitmapEncoder_AddRef(iface
);
1448 *ppIFrameEncode
= &result
->IWICBitmapFrameEncode_iface
;
1450 if (This
->num_frames
!= 0)
1451 pTIFFWriteDirectory(This
->tiff
);
1460 IPropertyBag2_Release(*ppIEncoderOptions
);
1461 *ppIEncoderOptions
= NULL
;
1465 LeaveCriticalSection(&This
->lock
);
1470 static HRESULT WINAPI
TiffEncoder_Commit(IWICBitmapEncoder
*iface
)
1472 FIXME("(%p): stub\n", iface
);
1476 static HRESULT WINAPI
TiffEncoder_GetMetadataQueryWriter(IWICBitmapEncoder
*iface
,
1477 IWICMetadataQueryWriter
**ppIMetadataQueryWriter
)
1479 FIXME("(%p,%p): stub\n", iface
, ppIMetadataQueryWriter
);
1483 static const IWICBitmapEncoderVtbl TiffEncoder_Vtbl
= {
1484 TiffEncoder_QueryInterface
,
1486 TiffEncoder_Release
,
1487 TiffEncoder_Initialize
,
1488 TiffEncoder_GetContainerFormat
,
1489 TiffEncoder_GetEncoderInfo
,
1490 TiffEncoder_SetColorContexts
,
1491 TiffEncoder_SetPalette
,
1492 TiffEncoder_SetThumbnail
,
1493 TiffEncoder_SetPreview
,
1494 TiffEncoder_CreateNewFrame
,
1496 TiffEncoder_GetMetadataQueryWriter
1499 HRESULT
TiffEncoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1504 TRACE("(%p,%s,%p)\n", pUnkOuter
, debugstr_guid(iid
), ppv
);
1508 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
1510 if (!load_libtiff())
1512 ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF
);
1516 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(TiffEncoder
));
1517 if (!This
) return E_OUTOFMEMORY
;
1519 This
->IWICBitmapEncoder_iface
.lpVtbl
= &TiffEncoder_Vtbl
;
1521 This
->stream
= NULL
;
1522 InitializeCriticalSection(&This
->lock
);
1523 This
->lock
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": TiffEncoder.lock");
1525 This
->initialized
= FALSE
;
1526 This
->num_frames
= 0;
1527 This
->num_frames_committed
= 0;
1529 ret
= IUnknown_QueryInterface((IUnknown
*)This
, iid
, ppv
);
1530 IUnknown_Release((IUnknown
*)This
);
1535 #else /* !SONAME_LIBTIFF */
1537 HRESULT
TiffDecoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1539 ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
1543 HRESULT
TiffEncoder_CreateInstance(IUnknown
*pUnkOuter
, REFIID iid
, void** ppv
)
1545 ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");