2 * Copyright 2010 Vincent Povirk for CodeWeavers
3 * Copyright 2016 Dmitry Timoshkov
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.
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.
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
25 #include "wine/port.h"
36 #define WIN32_NO_STATUS
42 #include "wincodecs_private.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(wincodecs
);
50 /* Workaround for broken libtiff 4.x headers on some 64-bit hosts which
51 * define TIFF_UINT64_T/toff_t as 32-bit for 32-bit builds, while they
52 * are supposed to be always 64-bit.
53 * TIFF_UINT64_T doesn't exist in libtiff 3.x, it was introduced in 4.x.
57 # define toff_t UINT64
60 static CRITICAL_SECTION init_tiff_cs
;
61 static CRITICAL_SECTION_DEBUG init_tiff_cs_debug
=
64 { &init_tiff_cs_debug
.ProcessLocksList
,
65 &init_tiff_cs_debug
.ProcessLocksList
},
66 0, 0, { (DWORD_PTR
)(__FILE__
": init_tiff_cs") }
68 static CRITICAL_SECTION init_tiff_cs
= { &init_tiff_cs_debug
, -1, 0, 0, 0, 0 };
70 static void *libtiff_handle
;
71 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
72 MAKE_FUNCPTR(TIFFClientOpen
);
73 MAKE_FUNCPTR(TIFFClose
);
74 MAKE_FUNCPTR(TIFFCurrentDirOffset
);
75 MAKE_FUNCPTR(TIFFGetField
);
76 MAKE_FUNCPTR(TIFFIsByteSwapped
);
77 MAKE_FUNCPTR(TIFFNumberOfDirectories
);
78 MAKE_FUNCPTR(TIFFReadDirectory
);
79 MAKE_FUNCPTR(TIFFReadEncodedStrip
);
80 MAKE_FUNCPTR(TIFFReadEncodedTile
);
81 MAKE_FUNCPTR(TIFFSetDirectory
);
82 MAKE_FUNCPTR(TIFFSetField
);
83 MAKE_FUNCPTR(TIFFWriteDirectory
);
84 MAKE_FUNCPTR(TIFFWriteScanline
);
87 static void *load_libtiff(void)
91 RtlEnterCriticalSection(&init_tiff_cs
);
93 if (!libtiff_handle
&&
94 (libtiff_handle
= dlopen(SONAME_LIBTIFF
, RTLD_NOW
)) != NULL
)
96 void * (*pTIFFSetWarningHandler
)(void *);
97 void * (*pTIFFSetWarningHandlerExt
)(void *);
99 #define LOAD_FUNCPTR(f) \
100 if((p##f = dlsym(libtiff_handle, #f)) == NULL) { \
101 ERR("failed to load symbol %s\n", #f); \
102 libtiff_handle = NULL; \
103 RtlLeaveCriticalSection(&init_tiff_cs); \
106 LOAD_FUNCPTR(TIFFClientOpen
);
107 LOAD_FUNCPTR(TIFFClose
);
108 LOAD_FUNCPTR(TIFFCurrentDirOffset
);
109 LOAD_FUNCPTR(TIFFGetField
);
110 LOAD_FUNCPTR(TIFFIsByteSwapped
);
111 LOAD_FUNCPTR(TIFFNumberOfDirectories
);
112 LOAD_FUNCPTR(TIFFReadDirectory
);
113 LOAD_FUNCPTR(TIFFReadEncodedStrip
);
114 LOAD_FUNCPTR(TIFFReadEncodedTile
);
115 LOAD_FUNCPTR(TIFFSetDirectory
);
116 LOAD_FUNCPTR(TIFFSetField
);
117 LOAD_FUNCPTR(TIFFWriteDirectory
);
118 LOAD_FUNCPTR(TIFFWriteScanline
);
121 if ((pTIFFSetWarningHandler
= dlsym(libtiff_handle
, "TIFFSetWarningHandler")))
122 pTIFFSetWarningHandler(NULL
);
123 if ((pTIFFSetWarningHandlerExt
= dlsym(libtiff_handle
, "TIFFSetWarningHandlerExt")))
124 pTIFFSetWarningHandlerExt(NULL
);
127 result
= libtiff_handle
;
129 RtlLeaveCriticalSection(&init_tiff_cs
);
133 static tsize_t
tiff_stream_read(thandle_t client_data
, tdata_t data
, tsize_t size
)
135 IStream
*stream
= (IStream
*)client_data
;
139 hr
= stream_read(stream
, data
, size
, &bytes_read
);
140 if (FAILED(hr
)) bytes_read
= 0;
144 static tsize_t
tiff_stream_write(thandle_t client_data
, tdata_t data
, tsize_t size
)
146 IStream
*stream
= (IStream
*)client_data
;
150 hr
= stream_write(stream
, data
, size
, &bytes_written
);
151 if (FAILED(hr
)) bytes_written
= 0;
152 return bytes_written
;
155 static toff_t
tiff_stream_seek(thandle_t client_data
, toff_t offset
, int whence
)
157 IStream
*stream
= (IStream
*)client_data
;
159 ULONGLONG new_position
;
165 origin
= STREAM_SEEK_SET
;
168 origin
= STREAM_SEEK_CUR
;
171 origin
= STREAM_SEEK_END
;
174 ERR("unknown whence value %i\n", whence
);
178 hr
= stream_seek(stream
, offset
, origin
, &new_position
);
179 if (SUCCEEDED(hr
)) return new_position
;
183 static int tiff_stream_close(thandle_t client_data
)
185 /* Caller is responsible for releasing the stream object. */
189 static toff_t
tiff_stream_size(thandle_t client_data
)
191 IStream
*stream
= (IStream
*)client_data
;
195 hr
= stream_getsize(stream
, &size
);
197 if (SUCCEEDED(hr
)) return size
;
201 static int tiff_stream_map(thandle_t client_data
, tdata_t
*addr
, toff_t
*size
)
203 /* Cannot mmap streams */
207 static void tiff_stream_unmap(thandle_t client_data
, tdata_t addr
, toff_t size
)
209 /* No need to ever do this, since we can't map things. */
212 static TIFF
* tiff_open_stream(IStream
*stream
, const char *mode
)
214 stream_seek(stream
, 0, STREAM_SEEK_SET
, NULL
);
216 return pTIFFClientOpen("<IStream object>", mode
, stream
, tiff_stream_read
,
217 tiff_stream_write
, (void *)tiff_stream_seek
, tiff_stream_close
,
218 (void *)tiff_stream_size
, (void *)tiff_stream_map
, (void *)tiff_stream_unmap
);
222 struct decoder_frame frame
;
229 int invert_grayscale
;
230 UINT tile_width
, tile_height
;
239 struct decoder decoder
;
244 tiff_decode_info cached_decode_info
;
245 INT cached_tile_x
, cached_tile_y
;
249 static inline struct tiff_decoder
*impl_from_decoder(struct decoder
* iface
)
251 return CONTAINING_RECORD(iface
, struct tiff_decoder
, decoder
);
254 static HRESULT
tiff_get_decode_info(TIFF
*tiff
, tiff_decode_info
*decode_info
)
256 uint16 photometric
, bps
, samples
, planar
;
257 uint16 extra_sample_count
, extra_sample
, *extra_samples
;
258 uint16
*red
, *green
, *blue
;
259 UINT resolution_unit
;
260 float xres
=0.0, yres
=0.0;
265 decode_info
->indexed
= 0;
266 decode_info
->reverse_bgr
= 0;
267 decode_info
->invert_grayscale
= 0;
268 decode_info
->tiled
= 0;
269 decode_info
->source_bpp
= 0;
271 ret
= pTIFFGetField(tiff
, TIFFTAG_PHOTOMETRIC
, &photometric
);
274 WARN("missing PhotometricInterpretation tag\n");
278 ret
= pTIFFGetField(tiff
, TIFFTAG_BITSPERSAMPLE
, &bps
);
280 decode_info
->bps
= bps
;
282 ret
= pTIFFGetField(tiff
, TIFFTAG_SAMPLESPERPIXEL
, &samples
);
283 if (!ret
) samples
= 1;
284 decode_info
->samples
= samples
;
290 ret
= pTIFFGetField(tiff
, TIFFTAG_PLANARCONFIG
, &planar
);
291 if (!ret
) planar
= 1;
294 FIXME("unhandled planar configuration %u\n", planar
);
298 decode_info
->planar
= planar
;
300 TRACE("planar %u, photometric %u, samples %u, bps %u\n", planar
, photometric
, samples
, bps
);
304 case 0: /* WhiteIsZero */
305 decode_info
->invert_grayscale
= 1;
307 case 1: /* BlackIsZero */
310 ret
= pTIFFGetField(tiff
, TIFFTAG_EXTRASAMPLES
, &extra_sample_count
, &extra_samples
);
313 extra_sample_count
= 1;
315 extra_samples
= &extra_sample
;
318 else if (samples
!= 1)
320 FIXME("unhandled %dbpp sample count %u\n", bps
, samples
);
324 decode_info
->frame
.bpp
= bps
* samples
;
325 decode_info
->source_bpp
= decode_info
->frame
.bpp
;
331 FIXME("unhandled 1bpp sample count %u\n", samples
);
334 decode_info
->frame
.pixel_format
= GUID_WICPixelFormatBlackWhite
;
339 FIXME("unhandled 4bpp grayscale sample count %u\n", samples
);
342 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat4bppGray
;
346 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat8bppGray
;
349 decode_info
->frame
.bpp
= 32;
351 switch(extra_samples
[0])
353 case 1: /* Associated (pre-multiplied) alpha data */
354 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat32bppPBGRA
;
356 case 0: /* Unspecified data */
357 case 2: /* Unassociated alpha data */
358 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat32bppBGRA
;
361 FIXME("unhandled extra sample type %u\n", extra_samples
[0]);
369 FIXME("unhandled 16bpp grayscale sample count %u\n", samples
);
370 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
372 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat16bppGray
;
377 FIXME("unhandled 32bpp grayscale sample count %u\n", samples
);
378 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
380 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat32bppGrayFloat
;
383 WARN("unhandled greyscale bit count %u\n", bps
);
384 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
390 ret
= pTIFFGetField(tiff
, TIFFTAG_EXTRASAMPLES
, &extra_sample_count
, &extra_samples
);
393 extra_sample_count
= 1;
395 extra_samples
= &extra_sample
;
398 else if (samples
!= 3)
400 FIXME("unhandled RGB sample count %u\n", samples
);
404 decode_info
->frame
.bpp
= max(bps
, 8) * samples
;
405 decode_info
->source_bpp
= bps
* samples
;
411 decode_info
->reverse_bgr
= 1;
413 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat24bppBGR
;
415 switch(extra_samples
[0])
417 case 1: /* Associated (pre-multiplied) alpha data */
418 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat32bppPBGRA
;
420 case 0: /* Unspecified data */
421 case 2: /* Unassociated alpha data */
422 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat32bppBGRA
;
425 FIXME("unhandled extra sample type %i\n", extra_samples
[0]);
431 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat48bppRGB
;
433 switch(extra_samples
[0])
435 case 1: /* Associated (pre-multiplied) alpha data */
436 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat64bppPRGBA
;
438 case 0: /* Unspecified data */
439 case 2: /* Unassociated alpha data */
440 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat64bppRGBA
;
443 FIXME("unhandled extra sample type %i\n", extra_samples
[0]);
449 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat96bppRGBFloat
;
451 switch(extra_samples
[0])
453 case 1: /* Associated (pre-multiplied) alpha data */
454 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat128bppPRGBAFloat
;
456 case 0: /* Unspecified data */
457 case 2: /* Unassociated alpha data */
458 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat128bppRGBAFloat
;
461 FIXME("unhandled extra sample type %i\n", extra_samples
[0]);
466 WARN("unhandled RGB bit count %u\n", bps
);
467 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
470 case 3: /* RGB Palette */
473 FIXME("unhandled indexed sample count %u\n", samples
);
477 decode_info
->indexed
= 1;
478 decode_info
->frame
.bpp
= bps
;
482 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat1bppIndexed
;
485 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat2bppIndexed
;
488 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat4bppIndexed
;
491 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat8bppIndexed
;
494 FIXME("unhandled indexed bit count %u\n", bps
);
499 case 5: /* Separated */
502 FIXME("unhandled Separated sample count %u\n", samples
);
506 decode_info
->frame
.bpp
= bps
* samples
;
510 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat32bppCMYK
;
513 decode_info
->frame
.pixel_format
= GUID_WICPixelFormat64bppCMYK
;
517 WARN("unhandled Separated bit count %u\n", bps
);
518 return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT
;
522 case 4: /* Transparency mask */
526 FIXME("unhandled PhotometricInterpretation %u\n", photometric
);
530 ret
= pTIFFGetField(tiff
, TIFFTAG_IMAGEWIDTH
, &decode_info
->frame
.width
);
533 WARN("missing image width\n");
537 ret
= pTIFFGetField(tiff
, TIFFTAG_IMAGELENGTH
, &decode_info
->frame
.height
);
540 WARN("missing image length\n");
544 if ((ret
= pTIFFGetField(tiff
, TIFFTAG_TILEWIDTH
, &decode_info
->tile_width
)))
546 decode_info
->tiled
= 1;
548 ret
= pTIFFGetField(tiff
, TIFFTAG_TILELENGTH
, &decode_info
->tile_height
);
551 WARN("missing tile height\n");
555 decode_info
->tile_stride
= ((decode_info
->frame
.bpp
* decode_info
->tile_width
+ 7)/8);
556 decode_info
->tile_size
= decode_info
->tile_height
* decode_info
->tile_stride
;
557 decode_info
->tiles_across
= (decode_info
->frame
.width
+ decode_info
->tile_width
- 1) / decode_info
->tile_width
;
559 else if ((ret
= pTIFFGetField(tiff
, TIFFTAG_ROWSPERSTRIP
, &decode_info
->tile_height
)))
561 if (decode_info
->tile_height
> decode_info
->frame
.height
)
562 decode_info
->tile_height
= decode_info
->frame
.height
;
563 decode_info
->tile_width
= decode_info
->frame
.width
;
564 decode_info
->tile_stride
= ((decode_info
->frame
.bpp
* decode_info
->tile_width
+ 7)/8);
565 decode_info
->tile_size
= decode_info
->tile_height
* decode_info
->tile_stride
;
569 /* Some broken TIFF files have a single strip and lack the RowsPerStrip tag */
570 decode_info
->tile_height
= decode_info
->frame
.height
;
571 decode_info
->tile_width
= decode_info
->frame
.width
;
572 decode_info
->tile_stride
= ((decode_info
->frame
.bpp
* decode_info
->tile_width
+ 7)/8);
573 decode_info
->tile_size
= decode_info
->tile_height
* decode_info
->tile_stride
;
577 pTIFFGetField(tiff
, TIFFTAG_RESOLUTIONUNIT
, &resolution_unit
);
579 ret
= pTIFFGetField(tiff
, TIFFTAG_XRESOLUTION
, &xres
);
582 WARN("missing X resolution\n");
584 /* Emulate the behavior of current libtiff versions (libtiff commit a39f6131)
585 * yielding 0 instead of INFINITY for IFD_RATIONAL fields with denominator 0. */
591 ret
= pTIFFGetField(tiff
, TIFFTAG_YRESOLUTION
, &yres
);
594 WARN("missing Y resolution\n");
601 if (xres
== 0.0 || yres
== 0.0)
603 decode_info
->frame
.dpix
= decode_info
->frame
.dpiy
= 96.0;
607 switch (resolution_unit
)
610 FIXME("unknown resolution unit %i\n", resolution_unit
);
612 case 0: /* Not set */
613 case 1: /* Relative measurements */
615 decode_info
->frame
.dpix
= xres
;
616 decode_info
->frame
.dpiy
= yres
;
618 case 3: /* Centimeter */
619 decode_info
->frame
.dpix
= xres
* 2.54;
620 decode_info
->frame
.dpiy
= yres
* 2.54;
625 if (decode_info
->indexed
&&
626 pTIFFGetField(tiff
, TIFFTAG_COLORMAP
, &red
, &green
, &blue
))
628 decode_info
->frame
.num_colors
= 1 << decode_info
->bps
;
629 for (i
=0; i
<decode_info
->frame
.num_colors
; i
++)
631 decode_info
->frame
.palette
[i
] = 0xff000000 |
632 ((red
[i
]<<8) & 0xff0000) |
633 (green
[i
] & 0xff00) |
634 ((blue
[i
]>>8) & 0xff);
639 decode_info
->frame
.num_colors
= 0;
642 if (pTIFFGetField(tiff
, TIFFTAG_ICCPROFILE
, &len
, &profile
))
643 decode_info
->frame
.num_color_contexts
= 1;
645 decode_info
->frame
.num_color_contexts
= 0;
650 static HRESULT CDECL
tiff_decoder_initialize(struct decoder
* iface
, IStream
*stream
, struct decoder_stat
*st
)
652 struct tiff_decoder
*This
= impl_from_decoder(iface
);
655 This
->tiff
= tiff_open_stream(stream
, "r");
659 This
->frame_count
= pTIFFNumberOfDirectories(This
->tiff
);
660 This
->cached_frame
= 0;
661 hr
= tiff_get_decode_info(This
->tiff
, &This
->cached_decode_info
);
665 st
->frame_count
= This
->frame_count
;
666 st
->flags
= WICBitmapDecoderCapabilityCanDecodeAllImages
|
667 WICBitmapDecoderCapabilityCanDecodeSomeImages
|
668 WICBitmapDecoderCapabilityCanEnumerateMetadata
;
672 pTIFFClose(This
->tiff
);
677 static HRESULT
tiff_decoder_select_frame(struct tiff_decoder
* This
, DWORD frame
)
683 if (frame
>= This
->frame_count
)
686 if (This
->cached_frame
== frame
)
689 prev_tile_size
= This
->cached_tile
? This
->cached_decode_info
.tile_size
: 0;
691 res
= pTIFFSetDirectory(This
->tiff
, frame
);
695 hr
= tiff_get_decode_info(This
->tiff
, &This
->cached_decode_info
);
697 This
->cached_tile_x
= -1;
701 This
->cached_frame
= frame
;
702 if (This
->cached_decode_info
.tile_size
> prev_tile_size
)
704 free(This
->cached_tile
);
705 This
->cached_tile
= NULL
;
710 /* Set an invalid value to ensure we'll refresh cached_decode_info before using it. */
711 This
->cached_frame
= This
->frame_count
;
712 free(This
->cached_tile
);
713 This
->cached_tile
= NULL
;
719 static HRESULT CDECL
tiff_decoder_get_frame_info(struct decoder
* iface
, UINT frame
, struct decoder_frame
*info
)
721 struct tiff_decoder
*This
= impl_from_decoder(iface
);
724 hr
= tiff_decoder_select_frame(This
, frame
);
727 *info
= This
->cached_decode_info
.frame
;
733 static HRESULT
tiff_decoder_read_tile(struct tiff_decoder
*This
, UINT tile_x
, UINT tile_y
)
737 tiff_decode_info
*info
= &This
->cached_decode_info
;
739 swap_bytes
= pTIFFIsByteSwapped(This
->tiff
);
742 ret
= pTIFFReadEncodedTile(This
->tiff
, tile_x
+ tile_y
* info
->tiles_across
, This
->cached_tile
, info
->tile_size
);
744 ret
= pTIFFReadEncodedStrip(This
->tiff
, tile_y
, This
->cached_tile
, info
->tile_size
);
750 if (info
->source_bpp
== 3 && info
->samples
== 3 && info
->frame
.bpp
== 24)
752 BYTE
*srcdata
, *src
, *dst
;
753 DWORD x
, y
, count
, width_bytes
= (info
->tile_width
* 3 + 7) / 8;
755 count
= width_bytes
* info
->tile_height
;
757 srcdata
= malloc(count
);
758 if (!srcdata
) return E_OUTOFMEMORY
;
759 memcpy(srcdata
, This
->cached_tile
, count
);
761 for (y
= 0; y
< info
->tile_height
; y
++)
763 src
= srcdata
+ y
* width_bytes
;
764 dst
= This
->cached_tile
+ y
* info
->tile_width
* 3;
766 for (x
= 0; x
< info
->tile_width
; x
+= 8)
768 dst
[2] = (src
[0] & 0x80) ? 0xff : 0; /* R */
769 dst
[1] = (src
[0] & 0x40) ? 0xff : 0; /* G */
770 dst
[0] = (src
[0] & 0x20) ? 0xff : 0; /* B */
771 if (x
+ 1 < info
->tile_width
)
773 dst
[5] = (src
[0] & 0x10) ? 0xff : 0; /* R */
774 dst
[4] = (src
[0] & 0x08) ? 0xff : 0; /* G */
775 dst
[3] = (src
[0] & 0x04) ? 0xff : 0; /* B */
777 if (x
+ 2 < info
->tile_width
)
779 dst
[8] = (src
[0] & 0x02) ? 0xff : 0; /* R */
780 dst
[7] = (src
[0] & 0x01) ? 0xff : 0; /* G */
781 dst
[6] = (src
[1] & 0x80) ? 0xff : 0; /* B */
783 if (x
+ 3 < info
->tile_width
)
785 dst
[11] = (src
[1] & 0x40) ? 0xff : 0; /* R */
786 dst
[10] = (src
[1] & 0x20) ? 0xff : 0; /* G */
787 dst
[9] = (src
[1] & 0x10) ? 0xff : 0; /* B */
789 if (x
+ 4 < info
->tile_width
)
791 dst
[14] = (src
[1] & 0x08) ? 0xff : 0; /* R */
792 dst
[13] = (src
[1] & 0x04) ? 0xff : 0; /* G */
793 dst
[12] = (src
[1] & 0x02) ? 0xff : 0; /* B */
795 if (x
+ 5 < info
->tile_width
)
797 dst
[17] = (src
[1] & 0x01) ? 0xff : 0; /* R */
798 dst
[16] = (src
[2] & 0x80) ? 0xff : 0; /* G */
799 dst
[15] = (src
[2] & 0x40) ? 0xff : 0; /* B */
801 if (x
+ 6 < info
->tile_width
)
803 dst
[20] = (src
[2] & 0x20) ? 0xff : 0; /* R */
804 dst
[19] = (src
[2] & 0x10) ? 0xff : 0; /* G */
805 dst
[18] = (src
[2] & 0x08) ? 0xff : 0; /* B */
807 if (x
+ 7 < info
->tile_width
)
809 dst
[23] = (src
[2] & 0x04) ? 0xff : 0; /* R */
810 dst
[22] = (src
[2] & 0x02) ? 0xff : 0; /* G */
811 dst
[21] = (src
[2] & 0x01) ? 0xff : 0; /* B */
821 else if (info
->source_bpp
== 12 && info
->samples
== 3 && info
->frame
.bpp
== 24)
823 BYTE
*srcdata
, *src
, *dst
;
824 DWORD x
, y
, count
, width_bytes
= (info
->tile_width
* 12 + 7) / 8;
826 count
= width_bytes
* info
->tile_height
;
828 srcdata
= malloc(count
);
829 if (!srcdata
) return E_OUTOFMEMORY
;
830 memcpy(srcdata
, This
->cached_tile
, count
);
832 for (y
= 0; y
< info
->tile_height
; y
++)
834 src
= srcdata
+ y
* width_bytes
;
835 dst
= This
->cached_tile
+ y
* info
->tile_width
* 3;
837 for (x
= 0; x
< info
->tile_width
; x
+= 2)
839 dst
[0] = ((src
[1] & 0xf0) >> 4) * 17; /* B */
840 dst
[1] = (src
[0] & 0x0f) * 17; /* G */
841 dst
[2] = ((src
[0] & 0xf0) >> 4) * 17; /* R */
842 if (x
+ 1 < info
->tile_width
)
844 dst
[5] = (src
[1] & 0x0f) * 17; /* B */
845 dst
[4] = ((src
[2] & 0xf0) >> 4) * 17; /* G */
846 dst
[3] = (src
[2] & 0x0f) * 17; /* R */
856 else if (info
->source_bpp
== 4 && info
->samples
== 4 && info
->frame
.bpp
== 32)
858 BYTE
*srcdata
, *src
, *dst
;
859 DWORD x
, y
, count
, width_bytes
= (info
->tile_width
* 3 + 7) / 8;
861 count
= width_bytes
* info
->tile_height
;
863 srcdata
= malloc(count
);
864 if (!srcdata
) return E_OUTOFMEMORY
;
865 memcpy(srcdata
, This
->cached_tile
, count
);
867 for (y
= 0; y
< info
->tile_height
; y
++)
869 src
= srcdata
+ y
* width_bytes
;
870 dst
= This
->cached_tile
+ y
* info
->tile_width
* 4;
872 /* 1 source byte expands to 2 BGRA samples */
874 for (x
= 0; x
< info
->tile_width
; x
+= 2)
876 dst
[0] = (src
[0] & 0x20) ? 0xff : 0; /* B */
877 dst
[1] = (src
[0] & 0x40) ? 0xff : 0; /* G */
878 dst
[2] = (src
[0] & 0x80) ? 0xff : 0; /* R */
879 dst
[3] = (src
[0] & 0x10) ? 0xff : 0; /* A */
880 if (x
+ 1 < info
->tile_width
)
882 dst
[4] = (src
[0] & 0x02) ? 0xff : 0; /* B */
883 dst
[5] = (src
[0] & 0x04) ? 0xff : 0; /* G */
884 dst
[6] = (src
[0] & 0x08) ? 0xff : 0; /* R */
885 dst
[7] = (src
[0] & 0x01) ? 0xff : 0; /* A */
895 else if (info
->source_bpp
== 16 && info
->samples
== 4 && info
->frame
.bpp
== 32)
897 BYTE
*srcdata
, *src
, *dst
;
898 DWORD x
, y
, count
, width_bytes
= (info
->tile_width
* 12 + 7) / 8;
900 count
= width_bytes
* info
->tile_height
;
902 srcdata
= malloc(count
);
903 if (!srcdata
) return E_OUTOFMEMORY
;
904 memcpy(srcdata
, This
->cached_tile
, count
);
906 for (y
= 0; y
< info
->tile_height
; y
++)
908 src
= srcdata
+ y
* width_bytes
;
909 dst
= This
->cached_tile
+ y
* info
->tile_width
* 4;
911 for (x
= 0; x
< info
->tile_width
; x
++)
913 dst
[0] = ((src
[1] & 0xf0) >> 4) * 17; /* B */
914 dst
[1] = (src
[0] & 0x0f) * 17; /* G */
915 dst
[2] = ((src
[0] & 0xf0) >> 4) * 17; /* R */
916 dst
[3] = (src
[1] & 0x0f) * 17; /* A */
924 /* 8bpp grayscale with extra alpha */
925 else if (info
->source_bpp
== 16 && info
->samples
== 2 && info
->frame
.bpp
== 32)
928 DWORD
*dst
, count
= info
->tile_width
* info
->tile_height
;
930 src
= This
->cached_tile
+ info
->tile_width
* info
->tile_height
* 2 - 2;
931 dst
= (DWORD
*)(This
->cached_tile
+ info
->tile_size
- 4);
935 *dst
-- = src
[0] | (src
[0] << 8) | (src
[0] << 16) | (src
[1] << 24);
940 if (info
->reverse_bgr
)
944 UINT sample_count
= info
->samples
;
946 reverse_bgr8(sample_count
, This
->cached_tile
, info
->tile_width
,
947 info
->tile_height
, info
->tile_width
* sample_count
);
951 if (swap_bytes
&& info
->bps
> 8)
953 UINT row
, i
, samples_per_row
;
956 samples_per_row
= info
->tile_width
* info
->samples
;
961 for (row
=0; row
<info
->tile_height
; row
++)
963 sample
= This
->cached_tile
+ row
* info
->tile_stride
;
964 for (i
=0; i
<samples_per_row
; i
++)
967 sample
[1] = sample
[0];
974 ERR("unhandled bps for byte swap %u\n", info
->bps
);
979 if (info
->invert_grayscale
)
983 if (info
->samples
!= 1)
985 ERR("cannot invert grayscale image with %u samples\n", info
->samples
);
989 end
= This
->cached_tile
+info
->tile_size
;
991 for (byte
= This
->cached_tile
; byte
!= end
; byte
++)
995 This
->cached_tile_x
= tile_x
;
996 This
->cached_tile_y
= tile_y
;
1001 static HRESULT CDECL
tiff_decoder_copy_pixels(struct decoder
* iface
, UINT frame
,
1002 const WICRect
*prc
, UINT stride
, UINT buffersize
, BYTE
*buffer
)
1004 struct tiff_decoder
*This
= impl_from_decoder(iface
);
1006 UINT min_tile_x
, max_tile_x
, min_tile_y
, max_tile_y
;
1007 UINT tile_x
, tile_y
;
1010 tiff_decode_info
*info
= &This
->cached_decode_info
;
1012 hr
= tiff_decoder_select_frame(This
, frame
);
1016 if (!This
->cached_tile
)
1018 This
->cached_tile
= malloc(info
->tile_size
);
1019 if (!This
->cached_tile
)
1020 return E_OUTOFMEMORY
;
1023 min_tile_x
= prc
->X
/ info
->tile_width
;
1024 min_tile_y
= prc
->Y
/ info
->tile_height
;
1025 max_tile_x
= (prc
->X
+prc
->Width
-1) / info
->tile_width
;
1026 max_tile_y
= (prc
->Y
+prc
->Height
-1) / info
->tile_height
;
1028 for (tile_x
=min_tile_x
; tile_x
<= max_tile_x
; tile_x
++)
1030 for (tile_y
=min_tile_y
; tile_y
<= max_tile_y
; tile_y
++)
1032 if (tile_x
!= This
->cached_tile_x
|| tile_y
!= This
->cached_tile_y
)
1034 hr
= tiff_decoder_read_tile(This
, tile_x
, tile_y
);
1039 if (prc
->X
< tile_x
* info
->tile_width
)
1042 rc
.X
= prc
->X
- tile_x
* info
->tile_width
;
1044 if (prc
->Y
< tile_y
* info
->tile_height
)
1047 rc
.Y
= prc
->Y
- tile_y
* info
->tile_height
;
1049 if (prc
->X
+prc
->Width
> (tile_x
+1) * info
->tile_width
)
1050 rc
.Width
= info
->tile_width
- rc
.X
;
1051 else if (prc
->X
< tile_x
* info
->tile_width
)
1052 rc
.Width
= prc
->Width
+ prc
->X
- tile_x
* info
->tile_width
;
1054 rc
.Width
= prc
->Width
;
1056 if (prc
->Y
+prc
->Height
> (tile_y
+1) * info
->tile_height
)
1057 rc
.Height
= info
->tile_height
- rc
.Y
;
1058 else if (prc
->Y
< tile_y
* info
->tile_height
)
1059 rc
.Height
= prc
->Height
+ prc
->Y
- tile_y
* info
->tile_height
;
1061 rc
.Height
= prc
->Height
;
1063 dst_tilepos
= buffer
+ (stride
* ((rc
.Y
+ tile_y
* info
->tile_height
) - prc
->Y
)) +
1064 ((info
->frame
.bpp
* ((rc
.X
+ tile_x
* info
->tile_width
) - prc
->X
) + 7) / 8);
1066 hr
= copy_pixels(info
->frame
.bpp
, This
->cached_tile
,
1067 info
->tile_width
, info
->tile_height
, info
->tile_stride
,
1068 &rc
, stride
, buffersize
, dst_tilepos
);
1073 TRACE("<-- 0x%x\n", hr
);
1082 static HRESULT CDECL
tiff_decoder_get_color_context(struct decoder
*iface
,
1083 UINT frame
, UINT num
, BYTE
**data
, DWORD
*datasize
)
1085 struct tiff_decoder
*This
= impl_from_decoder(iface
);
1086 const BYTE
*profile
;
1090 hr
= tiff_decoder_select_frame(This
, frame
);
1094 if (!pTIFFGetField(This
->tiff
, TIFFTAG_ICCPROFILE
, &len
, &profile
))
1096 return E_UNEXPECTED
;
1100 *data
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
1102 return E_OUTOFMEMORY
;
1104 memcpy(*data
, profile
, len
);
1109 static HRESULT CDECL
tiff_decoder_get_metadata_blocks(struct decoder
*iface
,
1110 UINT frame
, UINT
*count
, struct decoder_block
**blocks
)
1112 struct tiff_decoder
*This
= impl_from_decoder(iface
);
1115 struct decoder_block result
;
1117 hr
= tiff_decoder_select_frame(This
, frame
);
1123 result
.offset
= pTIFFCurrentDirOffset(This
->tiff
);
1126 byte_swapped
= pTIFFIsByteSwapped(This
->tiff
);
1127 #ifdef WORDS_BIGENDIAN
1128 result
.options
= byte_swapped
? WICPersistOptionLittleEndian
: WICPersistOptionBigEndian
;
1130 result
.options
= byte_swapped
? WICPersistOptionBigEndian
: WICPersistOptionLittleEndian
;
1132 result
.options
|= WICPersistOptionNoCacheStream
|DECODER_BLOCK_FULL_STREAM
|DECODER_BLOCK_READER_CLSID
;
1133 result
.reader_clsid
= CLSID_WICIfdMetadataReader
;
1135 *blocks
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(**blocks
));
1141 static void CDECL
tiff_decoder_destroy(struct decoder
* iface
)
1143 struct tiff_decoder
*This
= impl_from_decoder(iface
);
1144 if (This
->tiff
) pTIFFClose(This
->tiff
);
1145 free(This
->cached_tile
);
1146 RtlFreeHeap(GetProcessHeap(), 0, This
);
1149 static const struct decoder_funcs tiff_decoder_vtable
= {
1150 tiff_decoder_initialize
,
1151 tiff_decoder_get_frame_info
,
1152 tiff_decoder_copy_pixels
,
1153 tiff_decoder_get_metadata_blocks
,
1154 tiff_decoder_get_color_context
,
1155 tiff_decoder_destroy
1158 HRESULT CDECL
tiff_decoder_create(struct decoder_info
*info
, struct decoder
**result
)
1160 struct tiff_decoder
*This
;
1162 if (!load_libtiff())
1164 ERR("Failed reading TIFF because unable to load %s\n",SONAME_LIBTIFF
);
1168 This
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This
));
1169 if (!This
) return E_OUTOFMEMORY
;
1171 This
->decoder
.vtable
= &tiff_decoder_vtable
;
1173 This
->cached_tile
= NULL
;
1174 This
->cached_tile_x
= -1;
1175 *result
= &This
->decoder
;
1177 info
->container_format
= GUID_ContainerFormatTiff
;
1178 info
->block_format
= GUID_ContainerFormatTiff
;
1179 info
->clsid
= CLSID_WICTiffDecoder
;
1184 struct tiff_encode_format
{
1185 const WICPixelFormatGUID
*guid
;
1191 int extra_sample_type
;
1196 static const struct tiff_encode_format formats
[] = {
1197 {&GUID_WICPixelFormat24bppBGR
, 2, 8, 3, 24, 0, 0, 1},
1198 {&GUID_WICPixelFormat24bppRGB
, 2, 8, 3, 24, 0, 0, 0},
1199 {&GUID_WICPixelFormatBlackWhite
, 1, 1, 1, 1, 0, 0, 0},
1200 {&GUID_WICPixelFormat4bppGray
, 1, 4, 1, 4, 0, 0, 0},
1201 {&GUID_WICPixelFormat8bppGray
, 1, 8, 1, 8, 0, 0, 0},
1202 {&GUID_WICPixelFormat32bppBGRA
, 2, 8, 4, 32, 1, 2, 1},
1203 {&GUID_WICPixelFormat32bppPBGRA
, 2, 8, 4, 32, 1, 1, 1},
1204 {&GUID_WICPixelFormat48bppRGB
, 2, 16, 3, 48, 0, 0, 0},
1205 {&GUID_WICPixelFormat64bppRGBA
, 2, 16, 4, 64, 1, 2, 0},
1206 {&GUID_WICPixelFormat64bppPRGBA
, 2, 16, 4, 64, 1, 1, 0},
1207 {&GUID_WICPixelFormat1bppIndexed
, 3, 1, 1, 1, 0, 0, 0, 1},
1208 {&GUID_WICPixelFormat4bppIndexed
, 3, 4, 1, 4, 0, 0, 0, 1},
1209 {&GUID_WICPixelFormat8bppIndexed
, 3, 8, 1, 8, 0, 0, 0, 1},
1213 typedef struct tiff_encoder
{
1214 struct encoder encoder
;
1216 const struct tiff_encode_format
*format
;
1217 struct encoder_frame encoder_frame
;
1219 DWORD lines_written
;
1222 static inline struct tiff_encoder
*impl_from_encoder(struct encoder
* iface
)
1224 return CONTAINING_RECORD(iface
, struct tiff_encoder
, encoder
);
1227 static HRESULT CDECL
tiff_encoder_initialize(struct encoder
* iface
, IStream
*stream
)
1229 struct tiff_encoder
* This
= impl_from_encoder(iface
);
1232 tiff
= tiff_open_stream(stream
, "w");
1242 static HRESULT CDECL
tiff_encoder_get_supported_format(struct encoder
*iface
,
1243 GUID
*pixel_format
, DWORD
*bpp
, BOOL
*indexed
)
1247 if (IsEqualGUID(pixel_format
, &GUID_WICPixelFormat2bppIndexed
))
1248 *pixel_format
= GUID_WICPixelFormat4bppIndexed
;
1250 for (i
=0; formats
[i
].guid
; i
++)
1252 if (IsEqualGUID(formats
[i
].guid
, pixel_format
))
1256 if (!formats
[i
].guid
) i
= 0;
1258 *pixel_format
= *formats
[i
].guid
;
1259 *bpp
= formats
[i
].bpp
;
1260 *indexed
= formats
[i
].indexed
;
1265 static HRESULT CDECL
tiff_encoder_create_frame(struct encoder
* iface
, const struct encoder_frame
*frame
)
1267 struct tiff_encoder
* This
= impl_from_encoder(iface
);
1270 if (This
->num_frames
!= 0)
1271 pTIFFWriteDirectory(This
->tiff
);
1274 This
->lines_written
= 0;
1275 This
->encoder_frame
= *frame
;
1277 for (i
=0; formats
[i
].guid
; i
++)
1279 if (IsEqualGUID(formats
[i
].guid
, &frame
->pixel_format
))
1283 This
->format
= &formats
[i
];
1285 pTIFFSetField(This
->tiff
, TIFFTAG_PHOTOMETRIC
, (uint16
)This
->format
->photometric
);
1286 pTIFFSetField(This
->tiff
, TIFFTAG_PLANARCONFIG
, (uint16
)1);
1287 pTIFFSetField(This
->tiff
, TIFFTAG_BITSPERSAMPLE
, (uint16
)This
->format
->bps
);
1288 pTIFFSetField(This
->tiff
, TIFFTAG_SAMPLESPERPIXEL
, (uint16
)This
->format
->samples
);
1290 if (This
->format
->extra_sample
)
1292 uint16 extra_samples
;
1293 extra_samples
= This
->format
->extra_sample_type
;
1295 pTIFFSetField(This
->tiff
, TIFFTAG_EXTRASAMPLES
, (uint16
)1, &extra_samples
);
1298 pTIFFSetField(This
->tiff
, TIFFTAG_IMAGEWIDTH
, (uint32
)frame
->width
);
1299 pTIFFSetField(This
->tiff
, TIFFTAG_IMAGELENGTH
, (uint32
)frame
->height
);
1301 if (frame
->dpix
!= 0.0 && frame
->dpiy
!= 0.0)
1303 pTIFFSetField(This
->tiff
, TIFFTAG_RESOLUTIONUNIT
, (uint16
)2); /* Inch */
1304 pTIFFSetField(This
->tiff
, TIFFTAG_XRESOLUTION
, (float)frame
->dpix
);
1305 pTIFFSetField(This
->tiff
, TIFFTAG_YRESOLUTION
, (float)frame
->dpiy
);
1308 if (This
->format
->bpp
<= 8 && frame
->num_colors
&& This
->format
->indexed
)
1310 uint16 red
[256], green
[256], blue
[256];
1313 for (i
= 0; i
< frame
->num_colors
; i
++)
1315 red
[i
] = (frame
->palette
[i
] >> 8) & 0xff00;
1316 green
[i
] = frame
->palette
[i
] & 0xff00;
1317 blue
[i
] = (frame
->palette
[i
] << 8) & 0xff00;
1320 pTIFFSetField(This
->tiff
, TIFFTAG_COLORMAP
, red
, green
, blue
);
1326 static HRESULT CDECL
tiff_encoder_write_lines(struct encoder
* iface
,
1327 BYTE
*data
, DWORD line_count
, DWORD stride
)
1329 struct tiff_encoder
* This
= impl_from_encoder(iface
);
1330 BYTE
*row_data
, *swapped_data
= NULL
;
1331 UINT i
, j
, line_size
;
1333 line_size
= ((This
->encoder_frame
.width
* This
->format
->bpp
)+7)/8;
1335 if (This
->format
->reverse_bgr
)
1337 swapped_data
= malloc(line_size
);
1339 return E_OUTOFMEMORY
;
1342 for (i
=0; i
<line_count
; i
++)
1344 row_data
= data
+ i
* stride
;
1346 if (This
->format
->reverse_bgr
&& This
->format
->bps
== 8)
1348 memcpy(swapped_data
, row_data
, line_size
);
1349 for (j
=0; j
<line_size
; j
+= This
->format
->samples
)
1352 temp
= swapped_data
[j
];
1353 swapped_data
[j
] = swapped_data
[j
+2];
1354 swapped_data
[j
+2] = temp
;
1356 row_data
= swapped_data
;
1359 pTIFFWriteScanline(This
->tiff
, (tdata_t
)row_data
, i
+This
->lines_written
, 0);
1362 This
->lines_written
+= line_count
;
1367 static HRESULT CDECL
tiff_encoder_commit_frame(struct encoder
* iface
)
1372 static HRESULT CDECL
tiff_encoder_commit_file(struct encoder
* iface
)
1374 struct tiff_encoder
* This
= impl_from_encoder(iface
);
1376 pTIFFClose(This
->tiff
);
1382 static void CDECL
tiff_encoder_destroy(struct encoder
* iface
)
1384 struct tiff_encoder
*This
= impl_from_encoder(iface
);
1386 if (This
->tiff
) pTIFFClose(This
->tiff
);
1387 RtlFreeHeap(GetProcessHeap(), 0, This
);
1390 static const struct encoder_funcs tiff_encoder_vtable
= {
1391 tiff_encoder_initialize
,
1392 tiff_encoder_get_supported_format
,
1393 tiff_encoder_create_frame
,
1394 tiff_encoder_write_lines
,
1395 tiff_encoder_commit_frame
,
1396 tiff_encoder_commit_file
,
1397 tiff_encoder_destroy
1400 HRESULT CDECL
tiff_encoder_create(struct encoder_info
*info
, struct encoder
**result
)
1402 struct tiff_encoder
*This
;
1404 if (!load_libtiff())
1406 ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF
);
1410 This
= RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This
));
1411 if (!This
) return E_OUTOFMEMORY
;
1413 This
->encoder
.vtable
= &tiff_encoder_vtable
;
1415 This
->num_frames
= 0;
1417 info
->flags
= ENCODER_FLAGS_MULTI_FRAME
| ENCODER_FLAGS_SUPPORTS_METADATA
;
1418 info
->container_format
= GUID_ContainerFormatTiff
;
1419 info
->clsid
= CLSID_WICTiffEncoder
;
1420 info
->encoder_options
[0] = ENCODER_OPTION_COMPRESSION_METHOD
;
1421 info
->encoder_options
[1] = ENCODER_OPTION_COMPRESSION_QUALITY
;
1422 info
->encoder_options
[2] = ENCODER_OPTION_END
;
1424 *result
= &This
->encoder
;
1429 #else /* !SONAME_LIBTIFF */
1431 HRESULT CDECL
tiff_decoder_create(struct decoder_info
*info
, struct decoder
**result
)
1433 ERR("Trying to load TIFF picture, but Wine was compiled without TIFF support.\n");
1437 HRESULT CDECL
tiff_encoder_create(struct encoder_info
*info
, struct encoder
**result
)
1439 ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");