1 // Copyright 2008-present Contributors to the OpenImageIO project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/OpenImageIO/oiio/blob/master/LICENSE.md
4
5
6 #include <algorithm>
7 #include <cmath>
8 #include <cstdio>
9 #include <cstdlib>
10
11 #define AVOID_WIN32_FILEIO
12 #include <tiffio.h>
13 #include <zlib.h>
14
15 #include <OpenImageIO/dassert.h>
16 #include <OpenImageIO/filesystem.h>
17 #include <OpenImageIO/fmath.h>
18 #include <OpenImageIO/imageio.h>
19 #include <OpenImageIO/parallel.h>
20 #include <OpenImageIO/strutil.h>
21 #include <OpenImageIO/thread.h>
22 #include <OpenImageIO/tiffutils.h>
23 #include <OpenImageIO/typedesc.h>
24
25 #include "imageio_pvt.h"
26
27
28 OIIO_PLUGIN_NAMESPACE_BEGIN
29
30
31 // General TIFF information:
32 // TIFF 6.0 spec:
33 // http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf
34 // Other Adobe TIFF docs:
35 // http://partners.adobe.com/public/developer/tiff/index.html
36 // Adobe extensions to allow 16 (and 24) bit float in TIFF (ugh, not on
37 // their developer page, only on Chris Cox's web site?):
38 // http://chriscox.org/TIFFTN3d1.pdf
39 // Libtiff:
40 // http://remotesensing.org/libtiff/
41
42
43
44 // Helper struct for constructing tables of TIFF tags
45 struct TIFF_tag_info {
46 int tifftag; // TIFF tag used for this info
47 const char* name; // Attribute name we use, or NULL to ignore the tag
48 TIFFDataType tifftype; // Data type that TIFF wants
49 };
50
51
52
53 // Note about MIP-maps versus subimages:
54 //
55 // TIFF files support subimages, but do not explicitly support
56 // multiresolution/MIP maps. So we have always used subimages to store
57 // MIP levels.
58 //
59 // At present, TIFF is the only format people use for multires textures
60 // that don't explicitly support it, so rather than make the
61 // TextureSystem have to handle both cases, we choose instead to emulate
62 // MIP with subimage in a way that's purely within the TIFFInput class.
63 // To the outside world, it really does look MIP-mapped. This only
64 // kicks in for TIFF files that have the "textureformat" metadata set.
65 //
66 // The internal m_subimage really does contain the subimage, but for the
67 // MIP emulation case, we report the subimage as the MIP level, and 0 as
68 // the subimage. It is indeed a tangled web of deceit we weave.
69
70
71
72 class TIFFInput final : public ImageInput {
73 public:
74 TIFFInput();
75 virtual ~TIFFInput();
format_name(void) const76 virtual const char* format_name(void) const override { return "tiff"; }
77 virtual bool valid_file(const std::string& filename) const override;
supports(string_view feature) const78 virtual int supports(string_view feature) const override
79 {
80 return (feature == "exif" || feature == "iptc" || feature == "ioproxy");
81 // N.B. No support for arbitrary metadata.
82 }
83 virtual bool open(const std::string& name, ImageSpec& newspec) override;
84 virtual bool open(const std::string& name, ImageSpec& newspec,
85 const ImageSpec& config) override;
86 virtual bool close() override;
current_subimage(void) const87 virtual int current_subimage(void) const override
88 {
89 // If m_emulate_mipmap is true, pretend subimages are mipmap levels
90 lock_guard lock(m_mutex);
91 return m_emulate_mipmap ? 0 : m_subimage;
92 }
current_miplevel(void) const93 virtual int current_miplevel(void) const override
94 {
95 // If m_emulate_mipmap is true, pretend subimages are mipmap levels
96 lock_guard lock(m_mutex);
97 return m_emulate_mipmap ? m_subimage : 0;
98 }
99 virtual bool seek_subimage(int subimage, int miplevel) override;
100 virtual ImageSpec spec(int subimage, int miplevel) override;
101 virtual ImageSpec spec_dimensions(int subimage, int miplevel) override;
spec(void) const102 const ImageSpec& spec(void) const override { return m_spec; }
103 virtual bool read_native_scanline(int subimage, int miplevel, int y, int z,
104 void* data) override;
105 virtual bool read_native_scanlines(int subimage, int miplevel, int ybegin,
106 int yend, int z, void* data) override;
107 virtual bool read_native_tile(int subimage, int miplevel, int x, int y,
108 int z, void* data) override;
109 virtual bool read_native_tiles(int subimage, int miplevel, int xbegin,
110 int xend, int ybegin, int yend, int zbegin,
111 int zend, void* data) override;
112 virtual bool read_scanline(int y, int z, TypeDesc format, void* data,
113 stride_t xstride) override;
114 virtual bool read_scanlines(int subimage, int miplevel, int ybegin,
115 int yend, int z, int chbegin, int chend,
116 TypeDesc format, void* data, stride_t xstride,
117 stride_t ystride) override;
118 virtual bool read_tile(int x, int y, int z, TypeDesc format, void* data,
119 stride_t xstride, stride_t ystride,
120 stride_t zstride) override;
121 virtual bool read_tiles(int subimage, int miplevel, int xbegin, int xend,
122 int ybegin, int yend, int zbegin, int zend,
123 int chbegin, int chend, TypeDesc format, void* data,
124 stride_t xstride, stride_t ystride,
125 stride_t zstride) override;
set_ioproxy(Filesystem::IOProxy * ioproxy)126 virtual bool set_ioproxy(Filesystem::IOProxy* ioproxy) override
127 {
128 m_io = ioproxy;
129 return true;
130 }
131
132 private:
133 TIFF* m_tif; ///< libtiff handle
134 std::string m_filename; ///< Stash the filename
135 std::vector<unsigned char> m_scratch; ///< Scratch space for us to use
136 std::vector<unsigned char> m_scratch2; ///< More scratch
137 int m_subimage; ///< What subimage are we looking at?
138 int m_next_scanline; ///< Next scanline we'll read
139 bool m_no_random_access; ///< Should we avoid random access?
140 bool m_emulate_mipmap; ///< Should we emulate mip with subimage?
141 bool m_keep_unassociated_alpha; ///< If the image is unassociated, please
142 ///< try to keep it that way!
143 bool m_raw_color; ///< If the image is not RGB, don't
144 ///< transform the color.
145 bool m_convert_alpha; ///< Do we need to associate alpha?
146 bool m_separate; ///< Separate planarconfig?
147 bool m_testopenconfig; ///< Debug aid to test open-with-config
148 bool m_use_rgba_interface; ///< Sometimes we punt
149 bool m_is_byte_swapped; ///< Is the file opposite our endian?
150 int m_rowsperstrip; ///< For scanline imgs, rows per strip
151 unsigned short m_planarconfig; ///< Planar config of the file
152 unsigned short m_bitspersample; ///< Of the *file*, not the client's view
153 unsigned short m_photometric; ///< Of the *file*, not the client's view
154 unsigned short m_compression; ///< TIFF compression tag
155 unsigned short m_predictor; ///< TIFF compression predictor tag
156 unsigned short m_inputchannels; ///< Channels in the file (careful with CMYK)
157 std::vector<unsigned short> m_colormap; ///< Color map for palette images
158 std::vector<uint32_t> m_rgbadata; ///< Sometimes we punt
159 std::vector<ImageSpec> m_subimage_specs; ///< Cached subimage specs
160 Filesystem::IOProxy* m_io = nullptr;
161
162 // Reset everything to initial state
init()163 void init()
164 {
165 m_tif = NULL;
166 m_subimage = -1;
167 m_emulate_mipmap = false;
168 m_keep_unassociated_alpha = false;
169 m_raw_color = false;
170 m_convert_alpha = false;
171 m_separate = false;
172 m_inputchannels = 0;
173 m_testopenconfig = false;
174 m_colormap.clear();
175 m_use_rgba_interface = false;
176 m_subimage_specs.clear();
177 m_io = nullptr;
178 }
179
180 // Just close the TIFF file handle, but don't forget anything we
181 // learned about the contents of the file or any configuration hints.
close_tif()182 void close_tif()
183 {
184 if (m_tif) {
185 TIFFClose(m_tif);
186 m_tif = NULL;
187 m_rgbadata.clear();
188 m_rgbadata.shrink_to_fit();
189 }
190 }
191
192 // Read tags from the current directory of m_tif and fill out spec.
193 // If read_meta is false, assume that m_spec already contains valid
194 // metadata and should not be cleared or rewritten.
195 void readspec(bool read_meta = true);
196
197 // Figure out all the photometric-related aspects of the header
198 void readspec_photometric();
199
200 // Convert planar separate to contiguous data format
201 void separate_to_contig(int nplanes, int nvals,
202 const unsigned char* separate,
203 unsigned char* contig);
204
205 // Convert palette to RGB
206 void palette_to_rgb(int n, const unsigned char* palettepels,
207 unsigned char* rgb);
208
209 // Convert in-bits to out-bits (outbits must be 8, 16, 32, and
210 // inbits < outbits)
211 void bit_convert(int n, const unsigned char* in, int inbits, void* out,
212 int outbits);
213
214 void invert_photometric(int n, void* data);
215
216 #ifdef TIFF_VERSION_BIG
find_field(int tifftag,TIFFDataType tifftype=TIFF_ANY)217 const TIFFField* find_field(int tifftag, TIFFDataType tifftype = TIFF_ANY)
218 {
219 return TIFFFindField(m_tif, tifftag, tifftype);
220 }
221 #else
find_field(int tifftag,TIFFDataType tifftype=TIFF_ANY)222 const TIFFFieldInfo* find_field(int tifftag,
223 TIFFDataType tifftype = TIFF_ANY)
224 {
225 return TIFFFindFieldInfo(m_tif, tifftag, tifftype);
226 }
227 #endif
228
229 OIIO_NODISCARD
tiffgetfieldtype(string_view name OIIO_MAYBE_UNUSED,int tag)230 TypeDesc tiffgetfieldtype(string_view name OIIO_MAYBE_UNUSED, int tag)
231 {
232 auto field = find_field(tag);
233 if (!field)
234 return TypeUnknown;
235 TIFFDataType tiffdatatype = TIFFFieldDataType(field);
236 int passcount = TIFFFieldPassCount(field);
237 int readcount = TIFFFieldReadCount(field);
238 if (!passcount && readcount > 0)
239 return tiff_datatype_to_typedesc(tiffdatatype, readcount);
240 return TypeUnknown;
241 }
242
243 OIIO_NODISCARD
safe_tiffgetfield(string_view name OIIO_MAYBE_UNUSED,int tag,TypeDesc expected,void * dest)244 bool safe_tiffgetfield(string_view name OIIO_MAYBE_UNUSED, int tag,
245 TypeDesc expected, void* dest)
246 {
247 TypeDesc type = tiffgetfieldtype(name, tag);
248 // Caller expects a specific type and the tag doesn't match? Punt.
249 if (expected != TypeUnknown && !equivalent(expected, type))
250 return false;
251 auto field = find_field(tag);
252 if (!field)
253 return false;
254
255 // TIFFDataType tiffdatatype = TIFFFieldDataType(field);
256 int passcount = TIFFFieldPassCount(field);
257 int readcount = TIFFFieldReadCount(field);
258 if (!passcount && readcount > 0) {
259 return TIFFGetField(m_tif, tag, dest);
260 }
261 // OIIO::debugf(" stgf %s tag %d %s datatype %d passcount %d readcount %d\n",
262 // name, tag, type, int(TIFFFieldDataType(field)), passcount, readcount);
263 return false;
264 }
265
266 // Get a string tiff tag field and save it it as a string_view. The
267 // return value will be true if the tag was found, otherwise false.
268 OIIO_NODISCARD
tiff_get_string_field(int tag,string_view name OIIO_MAYBE_UNUSED,string_view & result)269 bool tiff_get_string_field(int tag, string_view name OIIO_MAYBE_UNUSED,
270 string_view& result)
271 {
272 auto field = find_field(tag);
273 if (!field)
274 return false;
275 TIFFDataType tiffdatatype = TIFFFieldDataType(field);
276 int passcount = TIFFFieldPassCount(field);
277 int readcount = TIFFFieldReadCount(field);
278 // Strutil::printf(" tgsf %s tag %d datatype %d passcount %d readcount %d\n",
279 // name, tag, int(tiffdatatype), passcount, readcount);
280 char* s = nullptr;
281 uint32_t count = 0;
282 bool ok = false;
283 if (tiffdatatype == TIFF_ASCII && passcount
284 && readcount == TIFF_VARIABLE) {
285 uint16_t shortcount = 0;
286 ok = TIFFGetField(m_tif, tag, &shortcount, &s);
287 count = shortcount;
288 } else if (tiffdatatype == TIFF_ASCII && passcount
289 && readcount == TIFF_VARIABLE2) {
290 ok = TIFFGetField(m_tif, tag, &count, &s);
291 } else if (readcount > 0) {
292 ok = TIFFGetField(m_tif, tag, &s);
293 count = readcount;
294 } else if (tiffdatatype == TIFF_ASCII) {
295 ok = TIFFGetField(m_tif, tag, &s);
296 if (ok && s && *s)
297 count = strlen(s);
298 } else {
299 // Some other type, we should not have been asking for this
300 // as ASCII, or maybe the tag is just the wrong data type in
301 // the file. Punt.
302 }
303 if (ok && s && *s) {
304 result = string_view(s, count);
305 // Strip off sometimes-errant extra null characters
306 while (result.size() && result.back() == '\0')
307 result.remove_suffix(1);
308 }
309 return ok;
310 }
311
312 // Get a string tiff tag field and put it into extra_params
get_string_attribute(string_view name,int tag)313 void get_string_attribute(string_view name, int tag)
314 {
315 string_view s;
316 if (tiff_get_string_field(tag, name, s)) {
317 m_spec.attribute(name, s);
318 // TODO: If the length is 0, erase the attrib rather than
319 // setting it to the empty string.
320 }
321 }
322
323 // Get a matrix tiff tag field and put it into extra_params
get_matrix_attribute(string_view name,int tag)324 void get_matrix_attribute(string_view name, int tag)
325 {
326 float* f = nullptr;
327 if (safe_tiffgetfield(name, tag, TypeUnknown, &f) && f)
328 m_spec.attribute(name, TypeMatrix, f);
329 }
330
331 // Get a float tiff tag field and put it into extra_params
get_float_attribute(string_view name,int tag)332 void get_float_attribute(string_view name, int tag)
333 {
334 float f[16];
335 if (safe_tiffgetfield(name, tag, TypeUnknown, f))
336 m_spec.attribute(name, f[0]);
337 }
338
339 // Get an int tiff tag field and put it into extra_params
get_int_attribute(string_view name,int tag)340 void get_int_attribute(string_view name, int tag)
341 {
342 int i = 0;
343 if (safe_tiffgetfield(name, tag, TypeUnknown, &i))
344 m_spec.attribute(name, i);
345 }
346
347 // Get an int tiff tag field and put it into extra_params
get_short_attribute(string_view name,int tag)348 void get_short_attribute(string_view name, int tag)
349 {
350 // Make room for two shorts, in case the tag is not the type we
351 // expect, and libtiff writes a long instead.
352 unsigned short s[2] = { 0, 0 };
353 if (safe_tiffgetfield(name, tag, TypeUInt16, &s)) {
354 int i = s[0];
355 m_spec.attribute(name, i);
356 }
357 }
358
359 // Search for TIFF tag having type 'tifftype', and if found,
360 // add it in the obvious way to m_spec under the name 'oiioname'.
find_tag(int tifftag,TIFFDataType tifftype,string_view oiioname)361 void find_tag(int tifftag, TIFFDataType tifftype, string_view oiioname)
362 {
363 auto info = find_field(tifftag, tifftype);
364 if (!info) {
365 // Something has gone wrong, libtiff doesn't think the field type
366 // is the same as we do.
367 return;
368 }
369 if (tifftype == TIFF_ASCII)
370 get_string_attribute(oiioname, tifftag);
371 else if (tifftype == TIFF_SHORT)
372 get_short_attribute(oiioname, tifftag);
373 else if (tifftype == TIFF_LONG)
374 get_int_attribute(oiioname, tifftag);
375 else if (tifftype == TIFF_RATIONAL || tifftype == TIFF_SRATIONAL
376 || tifftype == TIFF_FLOAT || tifftype == TIFF_DOUBLE)
377 get_float_attribute(oiioname, tifftag);
378 }
379
380 // If we're at scanline y, where does the next strip start?
next_strip_boundary(int y)381 int next_strip_boundary(int y)
382 {
383 return round_to_multiple(y - m_spec.y, m_rowsperstrip) + m_spec.y;
384 }
385
is_strip_boundary(int y)386 bool is_strip_boundary(int y)
387 {
388 return y == next_strip_boundary(y) || y == m_spec.height;
389 }
390
391 // Copy a height x width x chans region of src to dst, un-applying a
392 // horizontal predictor to each row. It is permitted for src and dst to
393 // be the same.
394 template<typename T>
undo_horizontal_predictor(T * dst,const T * src,int chans,int width,int height)395 void undo_horizontal_predictor(T* dst, const T* src, int chans, int width,
396 int height)
397 {
398 for (int y = 0; y < height;
399 ++y, src += chans * width, dst += chans * width)
400 for (int c = 0; c < chans; ++c) {
401 dst[c] = src[c]; // element 0
402 for (int x = 1; x < width; ++x)
403 dst[x * chans + c] = src[(x - 1) * chans + c]
404 + src[x * chans + c];
405 }
406 }
407
uncompress_one_strip(void * compressed_buf,unsigned long csize,void * uncompressed_buf,size_t strip_bytes,int channels,int width,int height,bool * ok)408 void uncompress_one_strip(void* compressed_buf, unsigned long csize,
409 void* uncompressed_buf, size_t strip_bytes,
410 int channels, int width, int height, bool* ok)
411 {
412 OIIO_DASSERT (m_compression == COMPRESSION_ADOBE_DEFLATE /*||
413 m_compression == COMPRESSION_NONE*/);
414 if (m_compression == COMPRESSION_NONE) {
415 // just copy if there's no compression
416 memcpy(uncompressed_buf, compressed_buf, csize);
417 if (m_is_byte_swapped && m_spec.format == TypeUInt16)
418 TIFFSwabArrayOfShort((unsigned short*)uncompressed_buf,
419 width * height * channels);
420 return;
421 }
422 uLong uncompressed_size = (uLong)strip_bytes;
423 auto zok = uncompress((Bytef*)uncompressed_buf, &uncompressed_size,
424 (const Bytef*)compressed_buf, csize);
425 if (zok != Z_OK || uncompressed_size != strip_bytes) {
426 *ok = false;
427 return;
428 }
429 if (m_is_byte_swapped && m_spec.format == TypeUInt16)
430 TIFFSwabArrayOfShort((unsigned short*)uncompressed_buf,
431 width * height * channels);
432 if (m_predictor == PREDICTOR_HORIZONTAL) {
433 if (m_spec.format == TypeUInt8)
434 undo_horizontal_predictor((unsigned char*)uncompressed_buf,
435 (unsigned char*)uncompressed_buf,
436 channels, width, height);
437 else if (m_spec.format == TypeUInt16)
438 undo_horizontal_predictor((unsigned short*)uncompressed_buf,
439 (unsigned short*)uncompressed_buf,
440 channels, width, height);
441 }
442 }
443
tile_index(int x,int y,int z)444 int tile_index(int x, int y, int z)
445 {
446 int xtile = (x - m_spec.x) / m_spec.tile_width;
447 int ytile = (y - m_spec.y) / m_spec.tile_height;
448 int ztile = (z - m_spec.z) / m_spec.tile_depth;
449 int nxtiles = (m_spec.width + m_spec.tile_width - 1)
450 / m_spec.tile_width;
451 int nytiles = (m_spec.height + m_spec.tile_height - 1)
452 / m_spec.tile_height;
453 return xtile + ytile * nxtiles + ztile * nxtiles * nytiles;
454 }
455
456 bool valid_file(const std::string& filename, Filesystem::IOProxy* io) const;
457 };
458
459
460
461 // Obligatory material to make this a recognizeable imageio plugin:
462 OIIO_PLUGIN_EXPORTS_BEGIN
463
464 OIIO_EXPORT ImageInput*
tiff_input_imageio_create()465 tiff_input_imageio_create()
466 {
467 return new TIFFInput;
468 }
469
470 // OIIO_EXPORT int tiff_imageio_version = OIIO_PLUGIN_VERSION; // it's in tiffoutput.cpp
471
472 OIIO_EXPORT const char* tiff_input_extensions[]
473 = { "tif", "tiff", "tx", "env", "sm", "vsm", nullptr };
474
475 OIIO_PLUGIN_EXPORTS_END
476
477
478
479 // Someplace to store an error message from the TIFF error handler
480 // To avoid thread oddities, we have the storage area buffering error
481 // messages for seterror()/geterror() be thread-specific.
482 static thread_local std::string thread_error_msg;
483 static atomic_int handler_set;
484 static spin_mutex handler_mutex;
485
486
487
488 std::string&
oiio_tiff_last_error()489 oiio_tiff_last_error()
490 {
491 return thread_error_msg;
492 }
493
494
495
496 static void
my_error_handler(const char *,const char * format,va_list ap)497 my_error_handler(const char* /*str*/, const char* format, va_list ap)
498 {
499 oiio_tiff_last_error() = Strutil::vsprintf(format, ap);
500 }
501
502
503
504 void
oiio_tiff_set_error_handler()505 oiio_tiff_set_error_handler()
506 {
507 if (!handler_set) {
508 spin_lock lock(handler_mutex);
509 if (!handler_set) {
510 TIFFSetErrorHandler(my_error_handler);
511 TIFFSetWarningHandler(my_error_handler);
512 handler_set = 1;
513 }
514 }
515 }
516
517
518
519 static tsize_t
readproc(thandle_t handle,tdata_t data,tsize_t size)520 readproc(thandle_t handle, tdata_t data, tsize_t size)
521 {
522 auto io = static_cast<Filesystem::IOProxy*>(handle);
523 // Strutil::print("iop read {} {} @ {}\n",
524 // io->filename(), size, io->tell());
525 auto r = io->read(data, size);
526 // for (size_t i = 0; i < r; ++i)
527 // Strutil::print(" {:02x}",
528 // int(((unsigned char *)data)[i]));
529 // Strutil::print("\n");
530 return tsize_t(r);
531 }
532
533 static tsize_t
writeproc(thandle_t,tdata_t,tsize_t size)534 writeproc(thandle_t, tdata_t, tsize_t size)
535 {
536 return tsize_t(0);
537 }
538
539 static toff_t
seekproc(thandle_t handle,toff_t offset,int origin)540 seekproc(thandle_t handle, toff_t offset, int origin)
541 {
542 auto io = static_cast<Filesystem::IOProxy*>(handle);
543 // Strutil::print("iop seek {} {} ({})\n",
544 // io->filename(), offset, origin);
545 return (io->seek(offset, origin)) ? toff_t(io->tell()) : toff_t(-1);
546 }
547
548 static int
closeproc(thandle_t handle)549 closeproc(thandle_t handle)
550 {
551 // auto io = static_cast<Filesystem::IOProxy*>(handle);
552 // if (io && io->opened()) {
553 // // Strutil::print("iop close {}\n\n",
554 // // io->filename());
555 // // io->seek(0);
556 // io->close();
557 // }
558 return 0;
559 }
560
561 static toff_t
sizeproc(thandle_t handle)562 sizeproc(thandle_t handle)
563 {
564 auto io = static_cast<Filesystem::IOProxy*>(handle);
565 // Strutil::print("iop size\n");
566 return toff_t(io->size());
567 }
568
569 static int
mapproc(thandle_t,tdata_t *,toff_t *)570 mapproc(thandle_t, tdata_t*, toff_t*)
571 {
572 return 0;
573 }
574
unmapproc(thandle_t,tdata_t,toff_t)575 static void unmapproc(thandle_t, tdata_t, toff_t) {}
576
577
578
579 struct CompressionCode {
580 int code;
581 const char* name;
582 };
583
584 // clang-format off
585
586 static CompressionCode tiff_compressions[] = {
587 { COMPRESSION_NONE, "none" }, // no compression
588 { COMPRESSION_LZW, "lzw" }, // LZW
589 { COMPRESSION_ADOBE_DEFLATE, "zip" }, // deflate / zip
590 { COMPRESSION_DEFLATE, "zip" }, // deflate / zip
591 { COMPRESSION_CCITTRLE, "ccittrle" }, // CCITT RLE
592 { COMPRESSION_CCITTFAX3, "ccittfax3" }, // CCITT group 3 fax
593 { COMPRESSION_CCITT_T4, "ccitt_t4" }, // CCITT T.4
594 { COMPRESSION_CCITTFAX4, "ccittfax4" }, // CCITT group 4 fax
595 { COMPRESSION_CCITT_T6, "ccitt_t6" }, // CCITT T.6
596 { COMPRESSION_OJPEG, "ojpeg" }, // old (pre-TIFF6.0) JPEG
597 { COMPRESSION_JPEG, "jpeg" }, // JPEG
598 { COMPRESSION_NEXT, "next" }, // NeXT 2-bit RLE
599 { COMPRESSION_CCITTRLEW, "ccittrle2" }, // #1 w/ word alignment
600 { COMPRESSION_PACKBITS, "packbits" }, // Macintosh RLE
601 { COMPRESSION_THUNDERSCAN, "thunderscan" }, // ThundeScan RLE
602 { COMPRESSION_IT8CTPAD, "IT8CTPAD" }, // IT8 CT w/ patting
603 { COMPRESSION_IT8LW, "IT8LW" }, // IT8 linework RLE
604 { COMPRESSION_IT8MP, "IT8MP" }, // IT8 monochrome picture
605 { COMPRESSION_IT8BL, "IT8BL" }, // IT8 binary line art
606 { COMPRESSION_PIXARFILM, "pixarfilm" }, // Pixar 10 bit LZW
607 { COMPRESSION_PIXARLOG, "pixarlog" }, // Pixar 11 bit ZIP
608 { COMPRESSION_DCS, "dcs" }, // Kodak DCS encoding
609 { COMPRESSION_JBIG, "isojbig" }, // ISO JBIG
610 { COMPRESSION_SGILOG, "sgilog" }, // SGI log luminance RLE
611 { COMPRESSION_SGILOG24, "sgilog24" }, // SGI log 24bit
612 { COMPRESSION_JP2000, "jp2000" }, // Leadtools JPEG2000
613 #if defined(TIFF_VERSION_BIG) && TIFFLIB_VERSION >= 20120922
614 // Others supported in more recent TIFF library versions.
615 { COMPRESSION_T85, "T85" }, // TIFF/FX T.85 JBIG
616 { COMPRESSION_T43, "T43" }, // TIFF/FX T.43 color layered JBIG
617 { COMPRESSION_LZMA, "lzma" }, // LZMA2
618 #endif
619 { -1, NULL }
620 };
621
622 // clang-format on
623
624 static const char*
tiff_compression_name(int code)625 tiff_compression_name(int code)
626 {
627 for (int i = 0; tiff_compressions[i].name; ++i)
628 if (code == tiff_compressions[i].code)
629 return tiff_compressions[i].name;
630 return NULL;
631 }
632
633
634
TIFFInput()635 TIFFInput::TIFFInput()
636 {
637 oiio_tiff_set_error_handler();
638 init();
639 }
640
641
642
~TIFFInput()643 TIFFInput::~TIFFInput()
644 {
645 // Close, if not already done.
646 close();
647 }
648
649
650
651 bool
valid_file(const std::string & filename,Filesystem::IOProxy * io) const652 TIFFInput::valid_file(const std::string& filename,
653 Filesystem::IOProxy* io) const
654 {
655 std::unique_ptr<Filesystem::IOProxy> local_io;
656 if (!io) {
657 io = new Filesystem::IOFile(filename, Filesystem::IOProxy::Read);
658 local_io.reset(io);
659 }
660 if (!io || !io->opened())
661 return false; // needs to be able to open
662 uint16_t magic[2] = { 0, 0 };
663 size_t numRead = io->pread(magic, 2 * sizeof(uint16_t), 0);
664 if (numRead != 2 * sizeof(uint16_t)) // read failed
665 return false;
666 if (magic[0] != TIFF_LITTLEENDIAN && magic[0] != TIFF_BIGENDIAN)
667 return false; // not the right byte order
668 if ((magic[0] == TIFF_LITTLEENDIAN) != littleendian())
669 swap_endian(&magic[1], 1);
670 return (magic[1] == 42 /* Classic TIFF */ || magic[1] == 43 /* Big TIFF */);
671 // local_io, if used, will automatically close and free. A passed in
672 // proxy will remain in its prior state.
673 }
674
675
676
677 bool
valid_file(const std::string & filename) const678 TIFFInput::valid_file(const std::string& filename) const
679 {
680 return valid_file(filename, nullptr);
681 }
682
683
684
685 bool
open(const std::string & name,ImageSpec & newspec)686 TIFFInput::open(const std::string& name, ImageSpec& newspec)
687 {
688 oiio_tiff_set_error_handler();
689 m_filename = name;
690 m_subimage = -1;
691
692 bool ok = seek_subimage(0, 0);
693 newspec = spec();
694 return ok;
695 }
696
697
698
699 bool
open(const std::string & name,ImageSpec & newspec,const ImageSpec & config)700 TIFFInput::open(const std::string& name, ImageSpec& newspec,
701 const ImageSpec& config)
702 {
703 const ParamValue* param = config.find_attribute("oiio:ioproxy",
704 TypeDesc::PTR);
705 if (param)
706 m_io = param->get<Filesystem::IOProxy*>();
707
708 // Check 'config' for any special requests
709 if (config.get_int_attribute("oiio:UnassociatedAlpha", 0) == 1)
710 m_keep_unassociated_alpha = true;
711 if (config.get_int_attribute("oiio:RawColor", 0) == 1)
712 m_raw_color = true;
713 // This configuration hint has no function other than as a debugging aid
714 // for testing whether configurations are received properly from other
715 // OIIO components.
716 if (config.get_int_attribute("oiio:DebugOpenConfig!", 0))
717 m_testopenconfig = true;
718 return open(name, newspec);
719 }
720
721
722
723 bool
seek_subimage(int subimage,int miplevel)724 TIFFInput::seek_subimage(int subimage, int miplevel)
725 {
726 if (subimage < 0) // Illegal
727 return false;
728 if (m_emulate_mipmap) {
729 // Emulating MIPmap? Pretend one subimage, many MIP levels.
730 if (subimage != 0)
731 return false;
732 subimage = miplevel;
733 } else {
734 // No MIPmap emulation
735 if (miplevel != 0)
736 return false;
737 }
738
739 if (subimage == m_subimage) {
740 // We're already pointing to the right subimage
741 return true;
742 }
743
744 // If we're emulating a MIPmap, only resolution is allowed to change
745 // between MIP levels, so if we already have a valid level in m_spec,
746 // we don't need to re-parse metadata, it's guaranteed to be the same.
747 bool read_meta = !(m_emulate_mipmap && m_tif && m_subimage >= 0);
748
749 if (!m_tif) {
750 if (m_io) {
751 static_assert(sizeof(thandle_t) == sizeof(void*),
752 "thandle_t must be same size as void*");
753 // Strutil::print("\n\nOpening client \"{}\"\n", m_filename);
754 m_io->seek(0);
755 m_tif = TIFFClientOpen(m_filename.c_str(), "rm", m_io, readproc,
756 writeproc, seekproc, closeproc, sizeproc,
757 mapproc, unmapproc);
758 } else {
759 #ifdef _WIN32
760 std::wstring wfilename = Strutil::utf8_to_utf16(m_filename);
761 m_tif = TIFFOpenW(wfilename.c_str(), "rm");
762 #else
763 m_tif = TIFFOpen(m_filename.c_str(), "rm");
764 #endif
765 }
766 if (m_tif == NULL) {
767 std::string e = oiio_tiff_last_error();
768 errorf("Could not open file: %s", e.length() ? e : m_filename);
769 return false;
770 }
771 m_is_byte_swapped = TIFFIsByteSwapped(m_tif);
772 m_subimage = 0;
773 }
774
775 m_next_scanline = 0; // next scanline we'll read
776 if (subimage == m_subimage || TIFFSetDirectory(m_tif, subimage)) {
777 m_subimage = subimage;
778 readspec(read_meta);
779 // OK, some edge cases we just don't handle. For those, fall back on
780 // the TIFFRGBA interface.
781 bool is_jpeg = (m_compression == COMPRESSION_JPEG
782 || m_compression == COMPRESSION_OJPEG);
783 bool is_nonspectral = (m_photometric == PHOTOMETRIC_YCBCR
784 || m_photometric == PHOTOMETRIC_CIELAB
785 || m_photometric == PHOTOMETRIC_ICCLAB
786 || m_photometric == PHOTOMETRIC_ITULAB
787 || m_photometric == PHOTOMETRIC_LOGL
788 || m_photometric == PHOTOMETRIC_LOGLUV);
789 m_use_rgba_interface = false;
790 m_rgbadata.clear();
791 if ((is_jpeg && m_spec.nchannels != 3)
792 || (is_nonspectral && !m_raw_color)) {
793 char emsg[1024];
794 m_use_rgba_interface = true;
795 if (!TIFFRGBAImageOK(m_tif, emsg)) {
796 errorf("No support for this flavor of TIFF file (%s)", emsg);
797 return false;
798 }
799 // This falls back to looking like uint8 images
800 m_spec.format = TypeDesc::UINT8;
801 m_spec.channelformats.clear();
802 m_photometric = PHOTOMETRIC_RGB;
803 }
804 if (size_t(subimage) >= m_subimage_specs.size()) // make room
805 m_subimage_specs.resize(
806 subimage > 0 ? round_to_multiple(subimage + 1, 4) : 1);
807 if (m_subimage_specs[subimage]
808 .undefined()) // haven't cached this spec yet
809 m_subimage_specs[subimage] = m_spec;
810 if (m_spec.format == TypeDesc::UNKNOWN) {
811 errorf("No support for data format of \"%s\"", m_filename);
812 return false;
813 }
814 return true;
815 } else {
816 std::string e = oiio_tiff_last_error();
817 errorf("%s", e.length() ? e : m_filename);
818 m_subimage = -1;
819 return false;
820 }
821 }
822
823
824
825 ImageSpec
spec(int subimage,int miplevel)826 TIFFInput::spec(int subimage, int miplevel)
827 {
828 ImageSpec ret;
829
830 // s == index of the spec list to retrieve. Start by presuming it's
831 // the sublevel number.
832 int s = subimage;
833 if (m_emulate_mipmap) {
834 // This is the kind of TIFF file where we are emulating MIPmap
835 // levels with TIFF subimages.
836 if (subimage != 0)
837 return ret; // Invalid subimage request, return the empty spec
838 // Index into the spec list by miplevel instead, because that's
839 // what it really contains.
840 s = miplevel;
841 }
842
843 lock_guard lock(m_mutex);
844 if (s >= 0 && s < int(m_subimage_specs.size())
845 && !m_subimage_specs[s].undefined()) {
846 // If we've cached this spec, we don't need to seek and read
847 ret = m_subimage_specs[s];
848 } else {
849 if (seek_subimage(subimage, miplevel))
850 ret = m_spec;
851 }
852 return ret;
853 }
854
855
856
857 ImageSpec
spec_dimensions(int subimage,int miplevel)858 TIFFInput::spec_dimensions(int subimage, int miplevel)
859 {
860 ImageSpec ret;
861
862 // s == index of the spec list to retrieve. Start by presuming it's
863 // the sublevel number.
864 int s = subimage;
865 if (m_emulate_mipmap) {
866 // This is the kind of TIFF file where we are emulating MIPmap
867 // levels with TIFF subimages.
868 if (subimage != 0)
869 return ret; // Invalid subimage request, return the empty spec
870 // Index into the spec list by miplevel instead, because that's
871 // what it really contains.
872 s = miplevel;
873 }
874
875 lock_guard lock(m_mutex);
876 if (s >= 0 && s < int(m_subimage_specs.size())
877 && !m_subimage_specs[s].undefined()) {
878 // If we've cached this spec, we don't need to seek and read
879 ret.copy_dimensions(m_subimage_specs[s]);
880 } else {
881 if (seek_subimage(subimage, miplevel))
882 ret.copy_dimensions(m_spec);
883 }
884 return ret;
885 }
886
887
888
889 #define ICC_PROFILE_ATTR "ICCProfile"
890
891
892 void
readspec(bool read_meta)893 TIFFInput::readspec(bool read_meta)
894 {
895 uint32_t width = 0, height = 0, depth = 0;
896 TIFFGetField(m_tif, TIFFTAG_IMAGEWIDTH, &width);
897 TIFFGetField(m_tif, TIFFTAG_IMAGELENGTH, &height);
898 TIFFGetFieldDefaulted(m_tif, TIFFTAG_IMAGEDEPTH, &depth);
899 TIFFGetFieldDefaulted(m_tif, TIFFTAG_SAMPLESPERPIXEL, &m_inputchannels);
900
901 if (read_meta) {
902 // clear the whole m_spec and start fresh
903 m_spec = ImageSpec((int)width, (int)height, (int)m_inputchannels);
904 } else {
905 // assume m_spec is valid, except for things that might differ
906 // between MIP levels
907 m_spec.width = (int)width;
908 m_spec.height = (int)height;
909 m_spec.depth = (int)depth;
910 m_spec.nchannels = (int)m_inputchannels;
911 }
912
913 float xpos = 0, ypos = 0;
914 TIFFGetField(m_tif, TIFFTAG_XPOSITION, &xpos);
915 TIFFGetField(m_tif, TIFFTAG_YPOSITION, &ypos);
916 if (xpos || ypos) {
917 // In the TIFF files, the positions are in resolutionunit. But we
918 // didn't used to interpret it that way, hence the mess below.
919 float xres = 1, yres = 1;
920 TIFFGetField(m_tif, TIFFTAG_XRESOLUTION, &xres);
921 TIFFGetField(m_tif, TIFFTAG_YRESOLUTION, &yres);
922 // See if the 'Software' field has a clue about what version of OIIO
923 // wrote the TIFF file. This can save us from embarrassing mistakes
924 // misinterpreting the image offset.
925 int oiio_write_version = 0;
926 string_view software;
927 if (tiff_get_string_field(TIFFTAG_SOFTWARE, "Software", software)
928 && Strutil::parse_prefix(software, "OpenImageIO")) {
929 int major = 0, minor = 0, patch = 0;
930 if (Strutil::parse_int(software, major)
931 && Strutil::parse_char(software, '.')
932 && Strutil::parse_int(software, minor)
933 && Strutil::parse_char(software, '.')
934 && Strutil::parse_int(software, patch)) {
935 oiio_write_version = major * 10000 + minor * 100 + patch;
936 }
937 }
938 // Old version of OIIO did not write the field correctly, so try
939 // to compensate.
940 if (oiio_write_version && oiio_write_version < 10803) {
941 xres = yres = 1.0f;
942 }
943 m_spec.x = (int)(xpos * xres);
944 m_spec.y = (int)(ypos * yres);
945 } else {
946 m_spec.x = 0;
947 m_spec.y = 0;
948 }
949 m_spec.z = 0;
950
951 // Start by assuming the "full" (aka display) window is the same as the
952 // data window. That's what we'll stick to if there is no further
953 // information in the file. But if the file has tags for hte "full"
954 // size, assume a display window with origin (0,0) and those dimensions.
955 // (Unfortunately, there are no TIFF tags for "full" origin.)
956 m_spec.full_x = m_spec.x;
957 m_spec.full_y = m_spec.y;
958 m_spec.full_z = m_spec.z;
959 m_spec.full_width = m_spec.width;
960 m_spec.full_height = m_spec.height;
961 m_spec.full_depth = m_spec.depth;
962 if (TIFFGetField(m_tif, TIFFTAG_PIXAR_IMAGEFULLWIDTH, &width) == 1
963 && TIFFGetField(m_tif, TIFFTAG_PIXAR_IMAGEFULLLENGTH, &height) == 1
964 && width > 0 && height > 0) {
965 m_spec.full_width = width;
966 m_spec.full_height = height;
967 m_spec.full_x = 0;
968 m_spec.full_y = 0;
969 }
970
971 if (TIFFIsTiled(m_tif)) {
972 TIFFGetField(m_tif, TIFFTAG_TILEWIDTH, &m_spec.tile_width);
973 TIFFGetField(m_tif, TIFFTAG_TILELENGTH, &m_spec.tile_height);
974 TIFFGetFieldDefaulted(m_tif, TIFFTAG_TILEDEPTH, &m_spec.tile_depth);
975 } else {
976 m_spec.tile_width = 0;
977 m_spec.tile_height = 0;
978 m_spec.tile_depth = 0;
979 }
980
981 m_bitspersample = 8;
982 TIFFGetField(m_tif, TIFFTAG_BITSPERSAMPLE, &m_bitspersample);
983 m_spec.attribute("oiio:BitsPerSample", (int)m_bitspersample);
984
985 unsigned short sampleformat = SAMPLEFORMAT_UINT;
986 TIFFGetFieldDefaulted(m_tif, TIFFTAG_SAMPLEFORMAT, &sampleformat);
987 switch (m_bitspersample) {
988 case 1:
989 case 2:
990 case 4:
991 case 6:
992 // Make 1, 2, 4, 6 bpp look like byte images
993 case 8:
994 if (sampleformat == SAMPLEFORMAT_UINT)
995 m_spec.set_format(TypeDesc::UINT8);
996 else if (sampleformat == SAMPLEFORMAT_INT)
997 m_spec.set_format(TypeDesc::INT8);
998 else
999 m_spec.set_format(TypeDesc::UINT8); // punt
1000 break;
1001 case 10:
1002 case 12:
1003 case 14:
1004 // Make 10, 12, 14 bpp look like 16 bit images
1005 case 16:
1006 if (sampleformat == SAMPLEFORMAT_UINT)
1007 m_spec.set_format(TypeDesc::UINT16);
1008 else if (sampleformat == SAMPLEFORMAT_INT)
1009 m_spec.set_format(TypeDesc::INT16);
1010 else if (sampleformat == SAMPLEFORMAT_IEEEFP) {
1011 m_spec.set_format(TypeDesc::HALF);
1012 // Adobe extension, see http://chriscox.org/TIFFTN3d1.pdf
1013 } else
1014 m_spec.set_format(TypeDesc::UNKNOWN);
1015 break;
1016 case 24:
1017 // Make 24 bit look like 32 bit
1018 case 32:
1019 if (sampleformat == SAMPLEFORMAT_IEEEFP)
1020 m_spec.set_format(TypeDesc::FLOAT);
1021 else if (sampleformat == SAMPLEFORMAT_UINT)
1022 m_spec.set_format(TypeDesc::UINT32);
1023 else if (sampleformat == SAMPLEFORMAT_INT)
1024 m_spec.set_format(TypeDesc::INT32);
1025 else
1026 m_spec.set_format(TypeDesc::UNKNOWN);
1027 break;
1028 case 64:
1029 if (sampleformat == SAMPLEFORMAT_IEEEFP)
1030 m_spec.set_format(TypeDesc::DOUBLE);
1031 else
1032 m_spec.set_format(TypeDesc::UNKNOWN);
1033 break;
1034 default: m_spec.set_format(TypeDesc::UNKNOWN); break;
1035 }
1036
1037 // Use the table for all the obvious things that can be mindlessly
1038 // shoved into the image spec.
1039 if (read_meta) {
1040 for (const auto& tag : tag_table("TIFF"))
1041 find_tag(tag.tifftag, tag.tifftype, tag.name);
1042 for (const auto& tag : tag_table("Exif"))
1043 find_tag(tag.tifftag, tag.tifftype, tag.name);
1044 }
1045
1046 // Now we need to get fields "by hand" for anything else that is less
1047 // straightforward...
1048
1049 readspec_photometric();
1050
1051 TIFFGetFieldDefaulted(m_tif, TIFFTAG_PLANARCONFIG, &m_planarconfig);
1052 m_separate = (m_planarconfig == PLANARCONFIG_SEPARATE
1053 && m_spec.nchannels > 1
1054 && m_photometric != PHOTOMETRIC_PALETTE);
1055 m_spec.attribute("tiff:PlanarConfiguration", (int)m_planarconfig);
1056 if (m_planarconfig == PLANARCONFIG_SEPARATE)
1057 m_spec.attribute("planarconfig", "separate");
1058 else
1059 m_spec.attribute("planarconfig", "contig");
1060
1061 m_compression = 0;
1062 TIFFGetFieldDefaulted(m_tif, TIFFTAG_COMPRESSION, &m_compression);
1063 m_spec.attribute("tiff:Compression", (int)m_compression);
1064 if (const char* compressname = tiff_compression_name(m_compression))
1065 m_spec.attribute("compression", compressname);
1066 m_predictor = PREDICTOR_NONE;
1067 if (!safe_tiffgetfield("Predictor", TIFFTAG_PREDICTOR, TypeUInt16,
1068 &m_predictor))
1069 m_predictor = PREDICTOR_NONE;
1070
1071 m_rowsperstrip = -1;
1072 if (!m_spec.tile_width) {
1073 TIFFGetField(m_tif, TIFFTAG_ROWSPERSTRIP, &m_rowsperstrip);
1074 if (m_rowsperstrip > 0)
1075 m_spec.attribute("tiff:RowsPerStrip", m_rowsperstrip);
1076 }
1077
1078 // The libtiff docs say that only uncompressed images, or those with
1079 // rowsperstrip==1, support random access to scanlines.
1080 m_no_random_access = (m_compression != COMPRESSION_NONE
1081 && m_rowsperstrip != 1);
1082
1083 // Do we care about fillorder? No, the TIFF spec says, "We
1084 // recommend that FillOrder=2 (lsb-to-msb) be used only in
1085 // special-purpose applications". So OIIO will assume msb-to-lsb
1086 // convention until somebody finds a TIFF file in the wild that
1087 // breaks this assumption.
1088
1089 unsigned short* sampleinfo = NULL;
1090 unsigned short extrasamples = 0;
1091 TIFFGetFieldDefaulted(m_tif, TIFFTAG_EXTRASAMPLES, &extrasamples,
1092 &sampleinfo);
1093 // std::cerr << "Extra samples = " << extrasamples << "\n";
1094 bool alpha_is_unassociated = false; // basic assumption
1095 if (extrasamples) {
1096 // If the TIFF ExtraSamples tag was specified, use that to figure
1097 // out the meaning of alpha.
1098 int colorchannels = 3;
1099 if (m_photometric == PHOTOMETRIC_MINISWHITE
1100 || m_photometric == PHOTOMETRIC_MINISBLACK
1101 || m_photometric == PHOTOMETRIC_PALETTE
1102 || m_photometric == PHOTOMETRIC_MASK)
1103 colorchannels = 1;
1104 for (int i = 0, c = colorchannels;
1105 i < extrasamples && c < m_inputchannels; ++i, ++c) {
1106 // std::cerr << " extra " << i << " " << sampleinfo[i] << "\n";
1107 if (sampleinfo[i] == EXTRASAMPLE_ASSOCALPHA) {
1108 // This is the alpha channel, associated as usual
1109 m_spec.alpha_channel = c;
1110 } else if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA) {
1111 // This is the alpha channel, but color is unassociated
1112 m_spec.alpha_channel = c;
1113 alpha_is_unassociated = true;
1114 if (m_keep_unassociated_alpha)
1115 m_spec.attribute("oiio:UnassociatedAlpha", 1);
1116 } else {
1117 OIIO_DASSERT(sampleinfo[i] == EXTRASAMPLE_UNSPECIFIED);
1118 // This extra channel is not alpha at all. Undo any
1119 // assumptions we previously made about this channel.
1120 if (m_spec.alpha_channel == c) {
1121 m_spec.channelnames[c] = Strutil::sprintf("channel%d", c);
1122 m_spec.alpha_channel = -1;
1123 }
1124 }
1125 }
1126 if (m_spec.alpha_channel >= 0) {
1127 m_spec.channelnames[m_spec.alpha_channel] = "A";
1128 // Special case: "R","A" should really be named "Y","A", since
1129 // the first channel is luminance, not red.
1130 if (m_spec.nchannels == 2 && m_spec.alpha_channel == 1)
1131 m_spec.channelnames[0] = "Y";
1132 }
1133 }
1134 if (alpha_is_unassociated)
1135 m_spec.attribute("tiff:UnassociatedAlpha", 1);
1136 // Will we need to do alpha conversions?
1137 m_convert_alpha = (m_spec.alpha_channel >= 0 && alpha_is_unassociated
1138 && !m_keep_unassociated_alpha);
1139
1140 // N.B. we currently ignore the following TIFF fields:
1141 // GrayResponseCurve GrayResponseUnit
1142 // MaxSampleValue MinSampleValue
1143 // NewSubfileType SubfileType(deprecated)
1144 // Colorimetry fields
1145
1146 // If we've been instructed to skip reading metadata, because it is
1147 // assumed to be identical to what we already have in m_spec,
1148 // skip everything following.
1149 if (!read_meta)
1150 return;
1151
1152 short resunit = -1;
1153 TIFFGetField(m_tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
1154 switch (resunit) {
1155 case RESUNIT_NONE: m_spec.attribute("ResolutionUnit", "none"); break;
1156 case RESUNIT_INCH: m_spec.attribute("ResolutionUnit", "in"); break;
1157 case RESUNIT_CENTIMETER: m_spec.attribute("ResolutionUnit", "cm"); break;
1158 }
1159 float xdensity = m_spec.get_float_attribute("XResolution", 0.0f);
1160 float ydensity = m_spec.get_float_attribute("YResolution", 0.0f);
1161 if (xdensity && ydensity)
1162 m_spec.attribute("PixelAspectRatio", ydensity / xdensity);
1163
1164 get_matrix_attribute("worldtocamera", TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA);
1165 get_matrix_attribute("worldtoscreen", TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN);
1166 get_int_attribute("tiff:subfiletype", TIFFTAG_SUBFILETYPE);
1167 // FIXME -- should subfiletype be "conventionized" and used for all
1168 // plugins uniformly?
1169
1170 // Special names for shadow maps
1171 char* s = NULL;
1172 TIFFGetField(m_tif, TIFFTAG_PIXAR_TEXTUREFORMAT, &s);
1173 if (s)
1174 m_emulate_mipmap = true;
1175 if (s && !strcmp(s, "Shadow")) {
1176 for (int c = 0; c < m_spec.nchannels; ++c)
1177 m_spec.channelnames[c] = "z";
1178 }
1179
1180 /// read color profile
1181 unsigned int icc_datasize = 0;
1182 unsigned char* icc_buf = NULL;
1183 TIFFGetField(m_tif, TIFFTAG_ICCPROFILE, &icc_datasize, &icc_buf);
1184 if (icc_datasize && icc_buf)
1185 m_spec.attribute(ICC_PROFILE_ATTR,
1186 TypeDesc(TypeDesc::UINT8, icc_datasize), icc_buf);
1187
1188 #if TIFFLIB_VERSION > 20050912 /* compat with old TIFF libs - skip Exif */
1189 // Search for an EXIF IFD in the TIFF file, and if found, rummage
1190 // around for Exif fields.
1191 toff_t exifoffset = 0;
1192 if (TIFFGetField(m_tif, TIFFTAG_EXIFIFD, &exifoffset)) {
1193 if (TIFFReadEXIFDirectory(m_tif, exifoffset)) {
1194 for (const auto& tag : tag_table("Exif"))
1195 find_tag(tag.tifftag, tag.tifftype, tag.name);
1196 // Look for a Makernote
1197 auto makerfield = find_field(EXIF_MAKERNOTE, TIFF_UNDEFINED);
1198 // std::unique_ptr<uint32_t[]> buf (new uint32_t[]);
1199 if (makerfield) {
1200 // bool ok = TIFFGetField (m_tif, tag, dest, &ptr);
1201 unsigned int mn_datasize = 0;
1202 unsigned char* mn_buf = NULL;
1203 TIFFGetField(m_tif, EXIF_MAKERNOTE, &mn_datasize, &mn_buf);
1204 }
1205 // Exif spec says that anything other than 0xffff==uncalibrated
1206 // should be interpreted to be sRGB.
1207 if (m_spec.get_int_attribute("Exif:ColorSpace") != 0xffff)
1208 m_spec.attribute("oiio:ColorSpace", "sRGB");
1209 }
1210 // TIFFReadEXIFDirectory seems to do something to the internal state
1211 // that requires a TIFFSetDirectory to set things straight again.
1212 TIFFSetDirectory(m_tif, m_subimage);
1213 }
1214 #endif
1215
1216 #if TIFFLIB_VERSION >= 20051230
1217 // Search for IPTC metadata in IIM form -- but older versions of
1218 // libtiff botch the size, so ignore it for very old libtiff.
1219 int iptcsize = 0;
1220 const void* iptcdata = NULL;
1221 if (TIFFGetField(m_tif, TIFFTAG_RICHTIFFIPTC, &iptcsize, &iptcdata)) {
1222 std::vector<uint32_t> iptc((uint32_t*)iptcdata,
1223 (uint32_t*)iptcdata + iptcsize);
1224 if (TIFFIsByteSwapped(m_tif))
1225 TIFFSwabArrayOfLong((uint32_t*)&iptc[0], iptcsize);
1226 decode_iptc_iim(&iptc[0], iptcsize * 4, m_spec);
1227 }
1228 #endif
1229
1230 // Search for an XML packet containing XMP (IPTC, Exif, etc.)
1231 int xmlsize = 0;
1232 const void* xmldata = NULL;
1233 if (TIFFGetField(m_tif, TIFFTAG_XMLPACKET, &xmlsize, &xmldata)) {
1234 // std::cerr << "Found XML data, size " << xmlsize << "\n";
1235 if (xmldata && xmlsize) {
1236 std::string xml((const char*)xmldata, xmlsize);
1237 decode_xmp(xml, m_spec);
1238 }
1239 }
1240
1241 #if 0
1242 // Experimental -- look for photoshop data
1243 int photoshopsize = 0;
1244 const void *photoshopdata = NULL;
1245 if (TIFFGetField (m_tif, TIFFTAG_PHOTOSHOP, &photoshopsize, &photoshopdata)) {
1246 std::cerr << "Found PHOTOSHOP data, size " << photoshopsize << "\n";
1247 if (photoshopdata && photoshopsize) {
1248 // std::string photoshop ((const char *)photoshopdata, photoshopsize);
1249 // std::cerr << "PHOTOSHOP:\n" << photoshop << "\n---\n";
1250 }
1251 }
1252 #endif
1253
1254 // If Software and IPTC:OriginatingProgram are identical, kill the latter
1255 if (m_spec.get_string_attribute("Software")
1256 == m_spec.get_string_attribute("IPTC:OriginatingProgram"))
1257 m_spec.erase_attribute("IPTC:OriginatingProgram");
1258
1259 std::string desc = m_spec.get_string_attribute("ImageDescription");
1260 // If ImageDescription and IPTC:Caption are identical, kill the latter
1261 if (desc == m_spec.get_string_attribute("IPTC:Caption"))
1262 m_spec.erase_attribute("IPTC:Caption");
1263
1264 // Because TIFF doesn't support arbitrary metadata, we look for certain
1265 // hints in the ImageDescription and turn them into metadata, also
1266 // removing them from the ImageDescrption.
1267 bool updatedDesc = false;
1268 auto cc = Strutil::excise_string_after_head(desc, "oiio:ConstantColor=");
1269 if (cc.size()) {
1270 m_spec.attribute("oiio:ConstantColor", cc);
1271 updatedDesc = true;
1272 }
1273 auto ac = Strutil::excise_string_after_head(desc, "oiio:AverageColor=");
1274 if (ac.size()) {
1275 m_spec.attribute("oiio:AverageColor", ac);
1276 updatedDesc = true;
1277 }
1278 std::string sha = Strutil::excise_string_after_head(desc, "oiio:SHA-1=");
1279 if (sha.empty()) // back compatibility with OIIO < 1.5
1280 sha = Strutil::excise_string_after_head(desc, "SHA-1=");
1281 if (sha.size()) {
1282 m_spec.attribute("oiio:SHA-1", sha);
1283 updatedDesc = true;
1284 }
1285
1286 if (updatedDesc) {
1287 string_view d(desc);
1288 Strutil::skip_whitespace(d); // erase if it's only whitespace
1289 if (d.size())
1290 m_spec.attribute("ImageDescription", desc);
1291 else
1292 m_spec.erase_attribute("ImageDescription");
1293 }
1294
1295 // Squash some problematic texture metadata if we suspect it's wrong
1296 pvt::check_texture_metadata_sanity(m_spec);
1297
1298 if (m_testopenconfig) // open-with-config debugging
1299 m_spec.attribute("oiio:DebugOpenConfig!", 42);
1300 }
1301
1302
1303
1304 void
readspec_photometric()1305 TIFFInput::readspec_photometric()
1306 {
1307 m_photometric = (m_spec.nchannels == 1 ? PHOTOMETRIC_MINISBLACK
1308 : PHOTOMETRIC_RGB);
1309 TIFFGetField(m_tif, TIFFTAG_PHOTOMETRIC, &m_photometric);
1310 m_spec.attribute("tiff:PhotometricInterpretation", (int)m_photometric);
1311 switch (m_photometric) {
1312 case PHOTOMETRIC_SEPARATED: {
1313 // Photometric "separated" is "usually CMYK".
1314 m_spec.channelnames.clear();
1315 short inkset = INKSET_CMYK;
1316 short numberofinks = 0;
1317 TIFFGetFieldDefaulted(m_tif, TIFFTAG_INKSET, &inkset);
1318 TIFFGetFieldDefaulted(m_tif, TIFFTAG_NUMBEROFINKS, &numberofinks);
1319 if (inkset == INKSET_CMYK && m_spec.nchannels == 4) {
1320 // True CMYK
1321 m_spec.attribute("tiff:ColorSpace", "CMYK");
1322 if (m_raw_color) {
1323 m_spec.channelnames.resize(4);
1324 m_spec.channelnames[0] = "C";
1325 m_spec.channelnames[1] = "M";
1326 m_spec.channelnames[2] = "Y";
1327 m_spec.channelnames[3] = "K";
1328 m_spec.attribute("oiio:ColorSpace", "CMYK");
1329 } else {
1330 // Silently convert to RGB
1331 m_spec.nchannels = 3;
1332 m_spec.default_channel_names();
1333 }
1334 } else {
1335 // Non-CMYK ink set
1336 m_spec.attribute("tiff:ColorSpace", "color separated");
1337 m_spec.attribute("oiio:ColorSpace", "color separated");
1338 m_raw_color = true; // Conversion to RGB doesn't make sense
1339 const char* inknames = NULL;
1340 if (safe_tiffgetfield("tiff:InkNames", TIFFTAG_INKNAMES,
1341 TypeUnknown, &inknames)
1342 && inknames && inknames[0] && numberofinks) {
1343 m_spec.channelnames.clear();
1344 // Decode the ink names, which are all concatenated together.
1345 for (int i = 0; i < int(numberofinks); ++i) {
1346 string_view ink(inknames);
1347 if (ink.size()) {
1348 m_spec.channelnames.emplace_back(ink);
1349 inknames += ink.size() + 1;
1350 } else {
1351 // Run out of road
1352 numberofinks = i;
1353 }
1354 }
1355 } else {
1356 numberofinks = 0;
1357 }
1358 // No ink names. Make it up.
1359 for (int i = numberofinks; i < m_spec.nchannels; ++i)
1360 m_spec.channelnames.emplace_back(Strutil::sprintf("ink%d", i));
1361 }
1362 break;
1363 }
1364 case PHOTOMETRIC_YCBCR: m_spec.attribute("tiff:ColorSpace", "YCbCr"); break;
1365 case PHOTOMETRIC_CIELAB:
1366 m_spec.attribute("tiff:ColorSpace", "CIELAB");
1367 break;
1368 case PHOTOMETRIC_ICCLAB:
1369 m_spec.attribute("tiff:ColorSpace", "ICCLAB");
1370 break;
1371 case PHOTOMETRIC_ITULAB:
1372 m_spec.attribute("tiff:ColorSpace", "ITULAB");
1373 break;
1374 case PHOTOMETRIC_LOGL: m_spec.attribute("tiff:ColorSpace", "LOGL"); break;
1375 case PHOTOMETRIC_LOGLUV:
1376 m_spec.attribute("tiff:ColorSpace", "LOGLUV");
1377 break;
1378 case PHOTOMETRIC_PALETTE: {
1379 m_spec.attribute("tiff:ColorSpace", "palette");
1380 // Read the color map
1381 unsigned short *r = NULL, *g = NULL, *b = NULL;
1382 TIFFGetField(m_tif, TIFFTAG_COLORMAP, &r, &g, &b);
1383 OIIO_ASSERT(r != NULL && g != NULL && b != NULL);
1384 m_colormap.clear();
1385 m_colormap.insert(m_colormap.end(), r, r + (1 << m_bitspersample));
1386 m_colormap.insert(m_colormap.end(), g, g + (1 << m_bitspersample));
1387 m_colormap.insert(m_colormap.end(), b, b + (1 << m_bitspersample));
1388 // Palette TIFF images are always 3 channels (to the client)
1389 m_spec.nchannels = 3;
1390 m_spec.default_channel_names();
1391 if (m_bitspersample != m_spec.format.size() * 8) {
1392 // For palette images with unusual bits per sample, set
1393 // oiio:BitsPerSample to the "full" version, to avoid problems
1394 // when copying the file back to a TIFF file (we don't write
1395 // palette images), but do leave "tiff:BitsPerSample" to reflect
1396 // the original file.
1397 m_spec.attribute("tiff:BitsPerSample", (int)m_bitspersample);
1398 m_spec.attribute("oiio:BitsPerSample",
1399 (int)m_spec.format.size() * 8);
1400 }
1401 // FIXME - what about palette + extra (alpha?) channels? Is that
1402 // allowed? And if so, ever encountered in the wild?
1403 break;
1404 }
1405 }
1406 }
1407
1408
1409
1410 bool
close()1411 TIFFInput::close()
1412 {
1413 close_tif();
1414 init(); // Reset to initial state
1415 return true;
1416 }
1417
1418
1419
1420 /// Helper: Convert n pixels from separate (RRRGGGBBB) to contiguous
1421 /// (RGBRGBRGB) planarconfig.
1422 void
separate_to_contig(int nplanes,int nvals,const unsigned char * separate,unsigned char * contig)1423 TIFFInput::separate_to_contig(int nplanes, int nvals,
1424 const unsigned char* separate,
1425 unsigned char* contig)
1426 {
1427 int channelbytes = m_spec.channel_bytes();
1428 for (int p = 0; p < nvals; ++p) // loop over pixels
1429 for (int c = 0; c < nplanes; ++c) // loop over channels
1430 for (int i = 0; i < channelbytes; ++i) // loop over data bytes
1431 contig[(p * nplanes + c) * channelbytes + i]
1432 = separate[(c * nvals + p) * channelbytes + i];
1433 }
1434
1435
1436
1437 void
palette_to_rgb(int n,const unsigned char * palettepels,unsigned char * rgb)1438 TIFFInput::palette_to_rgb(int n, const unsigned char* palettepels,
1439 unsigned char* rgb)
1440 {
1441 size_t vals_per_byte = 8 / m_bitspersample;
1442 size_t entries = 1 << m_bitspersample;
1443 int highest = entries - 1;
1444 OIIO_DASSERT(m_spec.nchannels == 3);
1445 OIIO_DASSERT(m_colormap.size() == 3 * entries);
1446 for (int x = 0; x < n; ++x) {
1447 int i = palettepels[x / vals_per_byte];
1448 i >>= (m_bitspersample * (vals_per_byte - 1 - (x % vals_per_byte)));
1449 i &= highest;
1450 *rgb++ = m_colormap[0 * entries + i] / 257;
1451 *rgb++ = m_colormap[1 * entries + i] / 257;
1452 *rgb++ = m_colormap[2 * entries + i] / 257;
1453 }
1454 }
1455
1456
1457
1458 void
bit_convert(int n,const unsigned char * in,int inbits,void * out,int outbits)1459 TIFFInput::bit_convert(int n, const unsigned char* in, int inbits, void* out,
1460 int outbits)
1461 {
1462 OIIO_DASSERT(inbits >= 1 && inbits < 32); // surely bugs if not
1463 uint32_t highest = (1 << inbits) - 1;
1464 int B = 0, b = 0;
1465 // Invariant:
1466 // So far, we have used in[0..B-1] and the high b bits of in[B].
1467 for (int i = 0; i < n; ++i) {
1468 long long val = 0;
1469 int valbits = 0; // bits so far we've accumulated in val
1470 while (valbits < inbits) {
1471 // Invariant: we have already accumulated valbits of the next
1472 // needed value (of a total of inbits), living in the valbits
1473 // low bits of val.
1474 int out_left = inbits - valbits; // How much more we still need
1475 int in_left = 8 - b; // Bits still available in in[B].
1476 if (in_left <= out_left) {
1477 // Eat the rest of this byte:
1478 // |---------|--------|
1479 // b in_left
1480 val <<= in_left;
1481 val |= in[B] & ~(0xffffffff << in_left);
1482 ++B;
1483 b = 0;
1484 valbits += in_left;
1485 } else {
1486 // Eat just the bits we need:
1487 // |--|---------|-----|
1488 // b out_left extra
1489 val <<= out_left;
1490 int extra = 8 - b - out_left;
1491 val |= (in[B] >> extra) & ~(0xffffffff << out_left);
1492 b += out_left;
1493 valbits = inbits;
1494 }
1495 }
1496 if (outbits == 8)
1497 ((unsigned char*)out)[i] = (unsigned char)((val * 0xff) / highest);
1498 else if (outbits == 16)
1499 ((unsigned short*)out)[i] = (unsigned short)((val * 0xffff)
1500 / highest);
1501 else
1502 ((unsigned int*)out)[i] = (unsigned int)((val * 0xffffffff)
1503 / highest);
1504 }
1505 }
1506
1507
1508
1509 void
invert_photometric(int n,void * data)1510 TIFFInput::invert_photometric(int n, void* data)
1511 {
1512 switch (m_spec.format.basetype) {
1513 case TypeDesc::UINT8: {
1514 unsigned char* d = (unsigned char*)data;
1515 for (int i = 0; i < n; ++i)
1516 d[i] = 255 - d[i];
1517 break;
1518 }
1519 default: break;
1520 }
1521 }
1522
1523
1524
1525 template<typename T>
1526 static void
cmyk_to_rgb(int n,const T * cmyk,size_t cmyk_stride,T * rgb,size_t rgb_stride)1527 cmyk_to_rgb(int n, const T* cmyk, size_t cmyk_stride, T* rgb, size_t rgb_stride)
1528 {
1529 for (; n; --n, cmyk += cmyk_stride, rgb += rgb_stride) {
1530 float C = convert_type<T, float>(cmyk[0]);
1531 float M = convert_type<T, float>(cmyk[1]);
1532 float Y = convert_type<T, float>(cmyk[2]);
1533 float K = convert_type<T, float>(cmyk[3]);
1534 float R = (1.0f - C) * (1.0f - K);
1535 float G = (1.0f - M) * (1.0f - K);
1536 float B = (1.0f - Y) * (1.0f - K);
1537 rgb[0] = convert_type<float, T>(R);
1538 rgb[1] = convert_type<float, T>(G);
1539 rgb[2] = convert_type<float, T>(B);
1540 }
1541 }
1542
1543
1544
1545 bool
read_native_scanline(int subimage,int miplevel,int y,int,void * data)1546 TIFFInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
1547 void* data)
1548 {
1549 lock_guard lock(m_mutex);
1550 if (!seek_subimage(subimage, miplevel))
1551 return false;
1552 y -= m_spec.y;
1553
1554 if (m_use_rgba_interface) {
1555 // We punted and used the RGBA image interface -- copy from buffer.
1556 // libtiff has no way to read just one scanline as RGBA. So we
1557 // buffer the whole image.
1558 if (!m_rgbadata.size()) { // first time through: allocate & read
1559 m_rgbadata.resize(m_spec.width * m_spec.height * m_spec.depth);
1560 bool ok = TIFFReadRGBAImageOriented(m_tif, m_spec.width,
1561 m_spec.height, &m_rgbadata[0],
1562 ORIENTATION_TOPLEFT, 0);
1563 if (!ok) {
1564 errorf("Unknown error trying to read TIFF as RGBA");
1565 return false;
1566 }
1567 }
1568 copy_image(m_spec.nchannels, m_spec.width, 1, 1,
1569 &m_rgbadata[y * m_spec.width], m_spec.nchannels, 4,
1570 4 * m_spec.width, AutoStride, data, m_spec.nchannels,
1571 m_spec.width * m_spec.nchannels, AutoStride);
1572 return true;
1573 }
1574
1575 // Make sure there's enough scratch space
1576 int nvals = m_spec.width * m_inputchannels;
1577 m_scratch.resize(nvals * m_spec.format.size());
1578
1579 // How many color planes to read
1580 int planes = m_separate ? m_inputchannels : 1;
1581
1582 // For compression modes that don't support random access to scanlines
1583 // (which I *think* is only LZW), we need to emulate random access by
1584 // re-seeking.
1585 if (m_no_random_access && m_next_scanline != y) {
1586 if (m_next_scanline > y) {
1587 // User is trying to read an earlier scanline than the one we're
1588 // up to. Easy fix: start over.
1589 // FIXME: I'm too tired to look into it now, but I wonder if
1590 // it is able to randomly seek to the first line in any
1591 // "strip", in which case we don't need to start from 0, just
1592 // start from the beginning of the strip we need.
1593 ImageSpec dummyspec;
1594 int old_subimage = current_subimage();
1595 int old_miplevel = current_miplevel();
1596 // We need to close the TIFF file s that we can re-open and
1597 // seek back to the beginning of this subimage. The close_tif()
1598 // accomplishes that. It's important not to do a full close()
1599 // here, because that would also call init() to fully reset
1600 // to a fresh ImageInput, thus forgetting any configuration
1601 // settings such as raw_color or keep_unassociated_alpha.
1602 close_tif();
1603 if (!open(m_filename, dummyspec)
1604 || !seek_subimage(old_subimage, old_miplevel)) {
1605 return false; // Somehow, the re-open failed
1606 }
1607 OIIO_DASSERT(m_next_scanline == 0
1608 && current_subimage() == old_subimage
1609 && current_miplevel() == old_miplevel);
1610 }
1611 while (m_next_scanline < y) {
1612 // Keep reading until we're read the scanline we really need
1613 for (int c = 0; c < planes; ++c) { /* planes==1 for contig */
1614 if (TIFFReadScanline(m_tif, &m_scratch[0], m_next_scanline, c)
1615 < 0) {
1616 errorf("%s", oiio_tiff_last_error());
1617 return false;
1618 }
1619 }
1620 ++m_next_scanline;
1621 }
1622 }
1623 m_next_scanline = y + 1;
1624
1625 bool need_bit_convert = (m_bitspersample != 8 && m_bitspersample != 16
1626 && m_bitspersample != 32);
1627 if (m_photometric == PHOTOMETRIC_PALETTE) {
1628 // Convert from palette to RGB
1629 if (TIFFReadScanline(m_tif, &m_scratch[0], y) < 0) {
1630 errorf("%s", oiio_tiff_last_error());
1631 return false;
1632 }
1633 palette_to_rgb(m_spec.width, &m_scratch[0], (unsigned char*)data);
1634 return true;
1635 }
1636 // Not palette...
1637
1638 int plane_bytes = m_spec.width * m_spec.format.size();
1639 int input_bytes = plane_bytes * m_inputchannels;
1640 // Where to read? Directly into user data if no channel shuffling, bit
1641 // shifting, or CMYK conversion is needed, otherwise into scratch space.
1642 unsigned char* readbuf = (unsigned char*)data;
1643 if (need_bit_convert || m_separate
1644 || (m_photometric == PHOTOMETRIC_SEPARATED && !m_raw_color))
1645 readbuf = &m_scratch[0];
1646 // Perform the reads. Note that for contig, planes==1, so it will
1647 // only do one TIFFReadScanline.
1648 for (int c = 0; c < planes; ++c) { /* planes==1 for contig */
1649 if (TIFFReadScanline(m_tif, &readbuf[plane_bytes * c], y, c) < 0) {
1650 errorf("%s", oiio_tiff_last_error());
1651 return false;
1652 }
1653 }
1654
1655 // Handle less-than-full bit depths
1656 if (m_bitspersample < 8) {
1657 // m_scratch now holds nvals n-bit values, contig or separate
1658 m_scratch2.resize(input_bytes);
1659 m_scratch.swap(m_scratch2);
1660 for (int c = 0; c < planes; ++c) /* planes==1 for contig */
1661 bit_convert(m_separate ? m_spec.width : nvals,
1662 &m_scratch2[plane_bytes * c], m_bitspersample,
1663 m_separate ? &m_scratch[plane_bytes * c]
1664 : (unsigned char*)data + plane_bytes * c,
1665 8);
1666 } else if (m_bitspersample > 8 && m_bitspersample < 16) {
1667 // m_scratch now holds nvals n-bit values, contig or separate
1668 m_scratch2.resize(input_bytes);
1669 m_scratch.swap(m_scratch2);
1670 for (int c = 0; c < planes; ++c) /* planes==1 for contig */
1671 bit_convert(m_separate ? m_spec.width : nvals,
1672 &m_scratch2[plane_bytes * c], m_bitspersample,
1673 m_separate ? &m_scratch[plane_bytes * c]
1674 : (unsigned char*)data + plane_bytes * c,
1675 16);
1676 } else if (m_bitspersample > 16 && m_bitspersample < 32) {
1677 // m_scratch now holds nvals n-bit values, contig or separate
1678 m_scratch2.resize(input_bytes);
1679 m_scratch.swap(m_scratch2);
1680 for (int c = 0; c < planes; ++c) /* planes==1 for contig */
1681 bit_convert(m_separate ? m_spec.width : nvals,
1682 &m_scratch2[plane_bytes * c], m_bitspersample,
1683 m_separate ? &m_scratch[plane_bytes * c]
1684 : (unsigned char*)data + plane_bytes * c,
1685 32);
1686 }
1687
1688 // Handle "separate" planarconfig
1689 if (m_separate) {
1690 // Convert from separate (RRRGGGBBB) to contiguous (RGBRGBRGB).
1691 // We know the data is in m_scratch at this point, so
1692 // contiguize it into the user data area.
1693 if (m_photometric == PHOTOMETRIC_SEPARATED && !m_raw_color) {
1694 // CMYK->RGB means we need temp storage.
1695 m_scratch2.resize(input_bytes);
1696 separate_to_contig(planes, m_spec.width, &m_scratch[0],
1697 &m_scratch2[0]);
1698 m_scratch.swap(m_scratch2);
1699 } else {
1700 // If no CMYK->RGB conversion is necessary, we can "separate"
1701 // straight into the data area.
1702 separate_to_contig(planes, m_spec.width, &m_scratch[0],
1703 (unsigned char*)data);
1704 }
1705 }
1706
1707 // Handle CMYK
1708 if (m_photometric == PHOTOMETRIC_SEPARATED && !m_raw_color) {
1709 // The CMYK will be in m_scratch.
1710 if (spec().format == TypeDesc::UINT8) {
1711 cmyk_to_rgb(m_spec.width, (unsigned char*)&m_scratch[0],
1712 m_inputchannels, (unsigned char*)data,
1713 m_spec.nchannels);
1714 } else if (spec().format == TypeDesc::UINT16) {
1715 cmyk_to_rgb(m_spec.width, (unsigned short*)&m_scratch[0],
1716 m_inputchannels, (unsigned short*)data,
1717 m_spec.nchannels);
1718 } else {
1719 errorf("CMYK only supported for UINT8, UINT16");
1720 return false;
1721 }
1722 }
1723
1724 if (m_photometric == PHOTOMETRIC_MINISWHITE)
1725 invert_photometric(nvals, data);
1726
1727 return true;
1728 }
1729
1730
1731
1732 bool
read_native_scanlines(int subimage,int miplevel,int ybegin,int yend,int z,void * data)1733 TIFFInput::read_native_scanlines(int subimage, int miplevel, int ybegin,
1734 int yend, int z, void* data)
1735 {
1736 // If the stars all align properly, try to read strips, and use the
1737 // thread pool to parallelize the decompression. This can give a large
1738 // speedup (5x or more!) because the zip decompression dwarfs the
1739 // actual raw I/O. But libtiff is totally serialized, so we can only
1740 // parallelize by reading raw (compressed) strips then making calls to
1741 // zlib ourselves to decompress. Don't bother trying to handle any of
1742 // the uncommon cases with strips. This covers most real-world cases.
1743 lock_guard lock(m_mutex);
1744 if (!seek_subimage(subimage, miplevel))
1745 return false;
1746 yend = std::min(yend, spec().y + spec().height);
1747 int nstrips = (yend - ybegin + m_rowsperstrip - 1) / m_rowsperstrip;
1748
1749 // See if it's easy to read this scanline range as strips. For edge
1750 // cases we don't with to deal with here, we just call the base class
1751 // read_native_scanlines, which in turn will loop over each scanline in
1752 // the range to call our read_native_scanline, which does handle the
1753 // full range of cases.
1754 bool read_as_strips =
1755 // we're reading more than one scanline
1756 (yend - ybegin) > 1 // no advantage to strips for single scanlines
1757 // scanline range must be complete strips
1758 && is_strip_boundary(ybegin)
1759 && is_strip_boundary(yend)
1760 // and not palette or cmyk color separated conversions
1761 && (m_photometric != PHOTOMETRIC_SEPARATED
1762 && m_photometric != PHOTOMETRIC_PALETTE)
1763 // no non-multiple-of-8 bits per sample
1764 && (spec().format.size() * 8 == m_bitspersample)
1765 // No other unusual cases
1766 && !m_use_rgba_interface;
1767 if (!read_as_strips) {
1768 // Punt and call the base class, which loops over scanlines.
1769 return ImageInput::read_native_scanlines(subimage, miplevel, ybegin,
1770 yend, z, data);
1771 }
1772
1773 // Are we reading raw (compressed) strips and doing the decompression
1774 // ourselves?
1775 bool read_raw_strips =
1776 // only deflate/zip compression
1777 (m_compression
1778 == COMPRESSION_ADOBE_DEFLATE /*|| m_compression == COMPRESSION_NONE*/)
1779 // only horizontal predictor (or none)
1780 && (m_predictor == PREDICTOR_HORIZONTAL
1781 || m_predictor == PREDICTOR_NONE)
1782 // contig planarconfig only (for now?)
1783 && !m_separate
1784 // only uint8, uint16
1785 && (m_spec.format == TypeUInt8 || m_spec.format == TypeUInt16);
1786
1787 // We know we wish to read as strips. But additionally, there are some
1788 // circumstances in which we want to read RAW strips, and do the
1789 // decompression ourselves, which we can feed to the thread pool to
1790 // perform in parallel.
1791 thread_pool* pool = default_thread_pool();
1792 bool parallelize =
1793 // and more than one, or no point parallelizing
1794 nstrips > 1
1795 // only if we are reading scanlines in order
1796 && ybegin == m_next_scanline
1797 // only if we're threading and don't enter the thread pool recursively!
1798 && pool->size() > 1
1799 && !pool->is_worker()
1800 // and not if the feature is turned off
1801 && m_spec.get_int_attribute("tiff:multithread",
1802 OIIO::get_int_attribute("tiff:multithread"));
1803
1804 // Make room for, and read the raw (still compressed) strips. As each
1805 // one is read, kick off the decompress and any other extras, to execute
1806 // in parallel.
1807 task_set tasks(pool);
1808 bool ok = true; // failed compression will stash a false here
1809 int y = ybegin;
1810 size_t ystride = m_spec.scanline_bytes(true);
1811 int stripchans = m_separate ? 1 : m_spec.nchannels; // chans in each strip
1812 int planes = m_separate ? m_spec.nchannels : 1; // color planes
1813 // N.B. "separate" planarconfig stores only one channel in a strip
1814 int stripvals = m_spec.width * stripchans
1815 * m_rowsperstrip; // values in a strip
1816 imagesize_t strip_bytes = stripvals * m_spec.format.size();
1817 size_t cbound = compressBound((uLong)strip_bytes);
1818 std::unique_ptr<char[]> compressed_scratch;
1819 std::unique_ptr<char[]> separate_tmp(
1820 m_separate ? new char[strip_bytes * nstrips * planes] : nullptr);
1821
1822 if (read_raw_strips) {
1823 // Make room for, and read the raw (still compressed) strips. As each
1824 // one is read, kick off the decompress and any other extras, to execute
1825 // in parallel.
1826 compressed_scratch.reset(new char[cbound * nstrips * planes]);
1827 for (size_t stripidx = 0; y + m_rowsperstrip <= yend;
1828 y += m_rowsperstrip, ++stripidx) {
1829 char* cbuf = compressed_scratch.get() + stripidx * cbound;
1830 tstrip_t stripnum = (y - m_spec.y) / m_rowsperstrip;
1831 tsize_t csize = TIFFReadRawStrip(m_tif, stripnum, cbuf,
1832 tmsize_t(cbound));
1833 if (csize < 0) {
1834 std::string err = oiio_tiff_last_error();
1835 errorf("TIFFRead%sStrip failed reading line y=%d,z=%d: %s",
1836 read_raw_strips ? "Raw" : "Encoded", y, z,
1837 err.size() ? err.c_str() : "unknown error");
1838 ok = false;
1839 }
1840 auto out = this;
1841 auto uncompress_etc = [=, &ok](int /*id*/) {
1842 out->uncompress_one_strip(cbuf, (unsigned long)csize, data,
1843 strip_bytes, out->m_spec.nchannels,
1844 out->m_spec.width,
1845 out->m_rowsperstrip, &ok);
1846 if (out->m_photometric == PHOTOMETRIC_MINISWHITE)
1847 out->invert_photometric(stripvals * stripchans, data);
1848 };
1849 if (parallelize) {
1850 // Push the rest of the work onto the thread pool queue
1851 tasks.push(pool->push(uncompress_etc));
1852 } else {
1853 uncompress_etc(0);
1854 }
1855 data = (char*)data + strip_bytes * planes;
1856 }
1857
1858 } else {
1859 // One of the cases where we don't bother reading raw, we read
1860 // encoded strips. Still can be a lot more efficient than reading
1861 // individual scanlines. This is the clause that has to handle
1862 // "separate" planarconfig.
1863 int strips_in_file = (m_spec.height + m_rowsperstrip - 1)
1864 / m_rowsperstrip;
1865 for (size_t stripidx = 0; y < yend; y += m_rowsperstrip, ++stripidx) {
1866 int myrps = std::min(yend - y, m_rowsperstrip);
1867 int strip_endy = std::min(y + m_rowsperstrip, yend);
1868 int mystripvals = m_spec.width * stripchans * (strip_endy - y);
1869 imagesize_t mystrip_bytes = mystripvals * m_spec.format.size();
1870 for (int c = 0; c < planes; ++c) {
1871 tstrip_t stripnum = ((y - m_spec.y) / m_rowsperstrip)
1872 + c * strips_in_file;
1873 tsize_t csize = TIFFReadEncodedStrip(m_tif, stripnum,
1874 (char*)data
1875 + c * mystrip_bytes,
1876 tmsize_t(mystrip_bytes));
1877 if (csize < 0) {
1878 std::string err = oiio_tiff_last_error();
1879 errorf(
1880 "TIFFReadEncodedStrip failed reading line y=%d,z=%d: %s",
1881 y, z, err.size() ? err.c_str() : "unknown error");
1882 ok = false;
1883 }
1884 }
1885 if (m_photometric == PHOTOMETRIC_MINISWHITE)
1886 invert_photometric(mystripvals * planes, data);
1887 if (m_separate) {
1888 // handle "separate" planarconfig: copy to temp area, then
1889 // separate_to_contig it back.
1890 char* sepbuf = separate_tmp.get()
1891 + stripidx * mystrip_bytes * planes;
1892 memcpy(sepbuf, data, mystrip_bytes * planes);
1893 separate_to_contig(planes, m_spec.width * myrps,
1894 (unsigned char*)sepbuf,
1895 (unsigned char*)data);
1896 }
1897 data = (char*)data + mystrip_bytes * planes;
1898 }
1899 }
1900
1901 // If we have left over scanlines, read them serially
1902 m_next_scanline = y;
1903 for (; y < yend; ++y) {
1904 bool ok = read_native_scanline(subimage, miplevel, y, z, data);
1905 if (!ok)
1906 return false;
1907 data = (char*)data + ystride;
1908 }
1909 tasks.wait();
1910 return true;
1911 }
1912
1913
1914
1915 bool
read_native_tile(int subimage,int miplevel,int x,int y,int z,void * data)1916 TIFFInput::read_native_tile(int subimage, int miplevel, int x, int y, int z,
1917 void* data)
1918 {
1919 lock_guard lock(m_mutex);
1920 if (!seek_subimage(subimage, miplevel))
1921 return false;
1922 x -= m_spec.x;
1923 y -= m_spec.y;
1924
1925 if (m_use_rgba_interface) {
1926 // We punted and used the RGBA image interface
1927 // libtiff has a call to read just one tile as RGBA. So that's all
1928 // we need to do, not buffer the whole image.
1929 m_rgbadata.resize(m_spec.tile_pixels() * 4);
1930 bool ok = TIFFReadRGBATile(m_tif, x, y, &m_rgbadata[0]);
1931 if (!ok) {
1932 errorf("Unknown error trying to read TIFF as RGBA");
1933 return false;
1934 }
1935 // Copy, and use stride magic to reverse top-to-bottom, because
1936 // TIFFReadRGBATile always returns data in bottom-to-top order.
1937 int tw = std::min(m_spec.tile_width, m_spec.width - x);
1938 int th = std::min(m_spec.tile_height, m_spec.height - y);
1939
1940 // When the vertical read size is smaller that the tile size
1941 // the actual data is in the bottom end of the tile
1942 // so copy_image should start from tile_height - read_height.
1943 // (Again, because TIFFReadRGBATile reverses the scanline order.)
1944 int vert_offset = m_spec.tile_height - th;
1945
1946 copy_image(m_spec.nchannels, tw, th, 1,
1947 &m_rgbadata[vert_offset * m_spec.tile_width
1948 + (th - 1) * m_spec.tile_width],
1949 m_spec.nchannels, 4, -m_spec.tile_width * 4, AutoStride,
1950 data, m_spec.nchannels, m_spec.nchannels * m_spec.tile_width,
1951 AutoStride);
1952 return true;
1953 }
1954
1955 imagesize_t tile_pixels = m_spec.tile_pixels();
1956 imagesize_t nvals = tile_pixels * m_spec.nchannels;
1957 m_scratch.resize(m_spec.tile_bytes());
1958 bool no_bit_convert = (m_bitspersample == 8 || m_bitspersample == 16
1959 || m_bitspersample == 32);
1960 if (m_photometric == PHOTOMETRIC_PALETTE) {
1961 // Convert from palette to RGB
1962 if (TIFFReadTile(m_tif, &m_scratch[0], x, y, z, 0) < 0) {
1963 errorf("%s", oiio_tiff_last_error());
1964 return false;
1965 }
1966 palette_to_rgb(tile_pixels, &m_scratch[0], (unsigned char*)data);
1967 } else {
1968 // Not palette
1969 imagesize_t plane_bytes = m_spec.tile_pixels() * m_spec.format.size();
1970 int planes = m_separate ? m_spec.nchannels : 1;
1971 std::vector<unsigned char> scratch2(m_separate ? m_spec.tile_bytes()
1972 : 0);
1973 // Where to read? Directly into user data if no channel shuffling
1974 // or bit shifting is needed, otherwise into scratch space.
1975 unsigned char* readbuf = (no_bit_convert && !m_separate)
1976 ? (unsigned char*)data
1977 : &m_scratch[0];
1978 // Perform the reads. Note that for contig, planes==1, so it will
1979 // only do one TIFFReadTile.
1980 for (int c = 0; c < planes; ++c) /* planes==1 for contig */
1981 if (TIFFReadTile(m_tif, &readbuf[plane_bytes * c], x, y, z, c)
1982 < 0) {
1983 errorf("%s", oiio_tiff_last_error());
1984 return false;
1985 }
1986 if (m_bitspersample < 8) {
1987 // m_scratch now holds nvals n-bit values, contig or separate
1988 std::swap(m_scratch, scratch2);
1989 for (int c = 0; c < planes; ++c) /* planes==1 for contig */
1990 bit_convert(m_separate ? tile_pixels : nvals,
1991 &scratch2[plane_bytes * c], m_bitspersample,
1992 m_separate ? &m_scratch[plane_bytes * c]
1993 : (unsigned char*)data + plane_bytes * c,
1994 8);
1995 } else if (m_bitspersample > 8 && m_bitspersample < 16) {
1996 // m_scratch now holds nvals n-bit values, contig or separate
1997 std::swap(m_scratch, scratch2);
1998 for (int c = 0; c < planes; ++c) /* planes==1 for contig */
1999 bit_convert(m_separate ? tile_pixels : nvals,
2000 &scratch2[plane_bytes * c], m_bitspersample,
2001 m_separate ? &m_scratch[plane_bytes * c]
2002 : (unsigned char*)data + plane_bytes * c,
2003 16);
2004 }
2005 if (m_separate) {
2006 // Convert from separate (RRRGGGBBB) to contiguous (RGBRGBRGB).
2007 // We know the data is in m_scratch at this point, so
2008 // contiguize it into the user data area.
2009 separate_to_contig(planes, tile_pixels, &m_scratch[0],
2010 (unsigned char*)data);
2011 }
2012 }
2013
2014 if (m_photometric == PHOTOMETRIC_MINISWHITE)
2015 invert_photometric(nvals, data);
2016
2017 return true;
2018 }
2019
2020
2021
2022 bool
read_native_tiles(int subimage,int miplevel,int xbegin,int xend,int ybegin,int yend,int zbegin,int zend,void * data)2023 TIFFInput::read_native_tiles(int subimage, int miplevel, int xbegin, int xend,
2024 int ybegin, int yend, int zbegin, int zend,
2025 void* data)
2026 {
2027 lock_guard lock(m_mutex);
2028 if (!seek_subimage(subimage, miplevel))
2029 return false;
2030 if (!m_spec.valid_tile_range(xbegin, xend, ybegin, yend, zbegin, zend))
2031 return false;
2032
2033 // If the stars all align properly, use the thread pool to parallelize
2034 // the decompression. This can give a large speedup (5x or more!)
2035 // because the zip decompression dwarfs the actual raw I/O. But libtiff
2036 // is totally serialized, so we can only parallelize by making calls to
2037 // zlib ourselves and then writing "raw" (compressed) strips. Don't
2038 // bother trying to handle any of the uncommon cases with strips. This
2039 // covers most real-world cases.
2040 thread_pool* pool = default_thread_pool();
2041 OIIO_DASSERT(m_spec.tile_depth >= 1);
2042 size_t ntiles = size_t(
2043 (xend - xbegin + m_spec.tile_width - 1) / m_spec.tile_width
2044 * (yend - ybegin + m_spec.tile_height - 1) / m_spec.tile_height
2045 * (zend - zbegin + m_spec.tile_depth - 1) / m_spec.tile_depth);
2046 bool parallelize =
2047 // more than one tile, or no point parallelizing
2048 ntiles > 1
2049 // and not palette or cmyk color separated conversions
2050 && (m_photometric != PHOTOMETRIC_SEPARATED
2051 && m_photometric != PHOTOMETRIC_PALETTE)
2052 // no non-multiple-of-8 bits per sample
2053 && (spec().format.size() * 8 == m_bitspersample)
2054 // contig planarconfig only (for now?)
2055 && !m_separate
2056 // only deflate/zip compression with horizontal predictor
2057 && m_compression == COMPRESSION_ADOBE_DEFLATE
2058 && m_predictor == PREDICTOR_HORIZONTAL
2059 // only uint8, uint16
2060 && (m_spec.format == TypeUInt8 || m_spec.format == TypeUInt16)
2061 // No other unusual cases
2062 && !m_use_rgba_interface
2063 // only if we're threading and don't enter the thread pool recursively!
2064 && pool->size() > 1
2065 && !pool->is_worker()
2066 // and not if the feature is turned off
2067 && m_spec.get_int_attribute("tiff:multithread",
2068 OIIO::get_int_attribute("tiff:multithread"));
2069
2070 // If we're not parallelizing, just call the parent class default
2071 // implementaiton of read_native_tiles, which will loop over the tiles
2072 // and read each one individually.
2073 if (!parallelize) {
2074 return ImageInput::read_native_tiles(subimage, miplevel, xbegin, xend,
2075 ybegin, yend, zbegin, zend, data);
2076 }
2077
2078 // Make room for, and read the raw (still compressed) tiles. As each one
2079 // is read, kick off the decompress and any other extras, to execute in
2080 // parallel.
2081 stride_t pixel_bytes = (stride_t)m_spec.pixel_bytes(true);
2082 stride_t tileystride = pixel_bytes * m_spec.tile_width;
2083 stride_t tilezstride = tileystride * m_spec.tile_height;
2084 stride_t ystride = (xend - xbegin) * pixel_bytes;
2085 stride_t zstride = (yend - ybegin) * ystride;
2086 imagesize_t tile_bytes = m_spec.tile_bytes(true);
2087 int tilevals = m_spec.tile_pixels() * m_spec.nchannels;
2088 size_t cbound = compressBound((uLong)tile_bytes);
2089 std::unique_ptr<char[]> compressed_scratch(new char[cbound * ntiles]);
2090 std::unique_ptr<char[]> scratch(new char[tile_bytes * ntiles]);
2091 task_set tasks(pool);
2092 bool ok = true; // failed compression will stash a false here
2093
2094 // Strutil::printf ("Parallel tile case %d %d %d %d %d %d\n",
2095 // xbegin, xend, ybegin, yend, zbegin, zend);
2096 size_t tileidx = 0;
2097 for (int z = zbegin; z < zend; z += m_spec.tile_depth) {
2098 for (int y = ybegin; y < yend; y += m_spec.tile_height) {
2099 for (int x = xbegin; x < xend; x += m_spec.tile_width, ++tileidx) {
2100 char* cbuf = compressed_scratch.get() + tileidx * cbound;
2101 char* ubuf = scratch.get() + tileidx * tile_bytes;
2102 auto csize = TIFFReadRawTile(m_tif, tile_index(x, y, z), cbuf,
2103 tmsize_t(cbound));
2104 if (csize < 0) {
2105 std::string err = oiio_tiff_last_error();
2106 errorf(
2107 "TIFFReadRawTile failed reading tile x=%d,y=%d,z=%d: %s",
2108 x, y, z, err.size() ? err.c_str() : "unknown error");
2109 return false;
2110 }
2111 // Push the rest of the work onto the thread pool queue
2112 auto out = this;
2113 tasks.push(pool->push([=, &ok](int /*id*/) {
2114 out->uncompress_one_strip(cbuf, (unsigned long)csize, ubuf,
2115 tile_bytes, out->m_spec.nchannels,
2116 out->m_spec.tile_width,
2117 out->m_spec.tile_height
2118 * out->m_spec.tile_depth,
2119 &ok);
2120 if (out->m_photometric == PHOTOMETRIC_MINISWHITE)
2121 out->invert_photometric(tilevals, ubuf);
2122 copy_image(out->m_spec.nchannels, out->m_spec.tile_width,
2123 out->m_spec.tile_height, out->m_spec.tile_depth,
2124 ubuf, size_t(pixel_bytes), pixel_bytes,
2125 tileystride, tilezstride,
2126 (char*)data + (z - zbegin) * zstride
2127 + (y - ybegin) * ystride
2128 + (x - xbegin) * pixel_bytes,
2129 pixel_bytes, ystride, zstride);
2130 }));
2131 }
2132 }
2133 }
2134 return ok;
2135 }
2136
2137
2138
2139 bool
read_scanline(int y,int z,TypeDesc format,void * data,stride_t xstride)2140 TIFFInput::read_scanline(int y, int z, TypeDesc format, void* data,
2141 stride_t xstride)
2142 {
2143 bool ok = ImageInput::read_scanline(y, z, format, data, xstride);
2144 if (ok && m_convert_alpha) {
2145 // If alpha is unassociated and we aren't requested to keep it that
2146 // way, multiply the colors by alpha per the usual OIIO conventions
2147 // to deliver associated color & alpha. Any auto-premultiplication
2148 // by alpha should happen after we've already done data format
2149 // conversions. That's why we do it here, rather than in
2150 // read_native_blah.
2151 {
2152 lock_guard lock(m_mutex);
2153 if (format
2154 == TypeUnknown) // unknown means retrieve the native type
2155 format = m_spec.format;
2156 }
2157 OIIO::premult(m_spec.nchannels, m_spec.width, 1, 1, 0 /*chbegin*/,
2158 m_spec.nchannels /*chend*/, format, data, xstride,
2159 AutoStride, AutoStride, m_spec.alpha_channel,
2160 m_spec.z_channel);
2161 }
2162 return ok;
2163 }
2164
2165
2166
2167 bool
read_scanlines(int subimage,int miplevel,int ybegin,int yend,int z,int chbegin,int chend,TypeDesc format,void * data,stride_t xstride,stride_t ystride)2168 TIFFInput::read_scanlines(int subimage, int miplevel, int ybegin, int yend,
2169 int z, int chbegin, int chend, TypeDesc format,
2170 void* data, stride_t xstride, stride_t ystride)
2171 {
2172 bool ok = ImageInput::read_scanlines(subimage, miplevel, ybegin, yend, z,
2173 chbegin, chend, format, data, xstride,
2174 ystride);
2175 if (ok && m_convert_alpha) {
2176 // If alpha is unassociated and we aren't requested to keep it that
2177 // way, multiply the colors by alpha per the usual OIIO conventions
2178 // to deliver associated color & alpha. Any auto-premultiplication
2179 // by alpha should happen after we've already done data format
2180 // conversions. That's why we do it here, rather than in
2181 // read_native_blah.
2182 int nchannels, alpha_channel, z_channel, width;
2183 {
2184 lock_guard lock(m_mutex);
2185 seek_subimage(subimage, miplevel);
2186 nchannels = m_spec.nchannels;
2187 alpha_channel = m_spec.alpha_channel;
2188 z_channel = m_spec.z_channel;
2189 width = m_spec.width;
2190 if (format == TypeUnknown) // unknown == native type
2191 format = m_spec.format;
2192 }
2193 // NOTE: if the channel range we read doesn't include the alpha
2194 // channel, we don't have the alpha data to do the premult, so skip
2195 // this. Pity the hapless soul who tries to read only the first
2196 // three channels of an RGBA file with unassociated alpha. They will
2197 // not get the premultiplication they deserve.
2198 if (alpha_channel >= chbegin && alpha_channel < chend)
2199 OIIO::premult(nchannels, width, yend - ybegin, 1, chbegin, chend,
2200 format, data, xstride, ystride, AutoStride,
2201 alpha_channel, z_channel);
2202 }
2203 return ok;
2204 }
2205
2206
2207
2208 bool
read_tile(int x,int y,int z,TypeDesc format,void * data,stride_t xstride,stride_t ystride,stride_t zstride)2209 TIFFInput::read_tile(int x, int y, int z, TypeDesc format, void* data,
2210 stride_t xstride, stride_t ystride, stride_t zstride)
2211 {
2212 bool ok = ImageInput::read_tile(x, y, z, format, data, xstride, ystride,
2213 zstride);
2214 if (ok && m_convert_alpha) {
2215 // If alpha is unassociated and we aren't requested to keep it that
2216 // way, multiply the colors by alpha per the usual OIIO conventions
2217 // to deliver associated color & alpha. Any auto-premultiplication
2218 // by alpha should happen after we've already done data format
2219 // conversions. That's why we do it here, rather than in
2220 // read_native_blah.
2221 {
2222 lock_guard lock(m_mutex);
2223 if (format
2224 == TypeUnknown) // unknown means retrieve the native type
2225 format = m_spec.format;
2226 }
2227 OIIO::premult(m_spec.nchannels, m_spec.tile_width, m_spec.tile_height,
2228 std::max(1, m_spec.tile_depth), 0, m_spec.nchannels,
2229 format, data, xstride, ystride, zstride,
2230 m_spec.alpha_channel, m_spec.z_channel);
2231 }
2232 return ok;
2233 }
2234
2235
2236
2237 bool
read_tiles(int subimage,int miplevel,int xbegin,int xend,int ybegin,int yend,int zbegin,int zend,int chbegin,int chend,TypeDesc format,void * data,stride_t xstride,stride_t ystride,stride_t zstride)2238 TIFFInput::read_tiles(int subimage, int miplevel, int xbegin, int xend,
2239 int ybegin, int yend, int zbegin, int zend, int chbegin,
2240 int chend, TypeDesc format, void* data, stride_t xstride,
2241 stride_t ystride, stride_t zstride)
2242 {
2243 bool ok = ImageInput::read_tiles(subimage, miplevel, xbegin, xend, ybegin,
2244 yend, zbegin, zend, chbegin, chend, format,
2245 data, xstride, ystride, zstride);
2246 if (ok && m_convert_alpha) {
2247 // If alpha is unassociated and we aren't requested to keep it that
2248 // way, multiply the colors by alpha per the usual OIIO conventions
2249 // to deliver associated color & alpha. Any auto-premultiplication
2250 // by alpha should happen after we've already done data format
2251 // conversions. That's why we do it here, rather than in
2252 // read_native_blah.
2253 int nchannels, alpha_channel, z_channel;
2254 {
2255 lock_guard lock(m_mutex);
2256 seek_subimage(subimage, miplevel);
2257 nchannels = m_spec.nchannels;
2258 alpha_channel = m_spec.alpha_channel;
2259 z_channel = m_spec.z_channel;
2260 if (format == TypeUnknown) // unknown == native type
2261 format = m_spec.format;
2262 }
2263 // NOTE: if the channel range we read doesn't include the alpha
2264 // channel, we don't have the alpha data to do the premult, so skip
2265 // this. Pity the hapless soul who tries to read only the first
2266 // three channels of an RGBA file with unassociated alpha. They will
2267 // not get the premultiplication they deserve.
2268 if (alpha_channel >= chbegin && alpha_channel < chend)
2269 OIIO::premult(nchannels, xend - xbegin, yend - ybegin,
2270 zend - zbegin, chbegin, chend, format, data, xstride,
2271 ystride, zstride, alpha_channel, z_channel);
2272 }
2273 return ok;
2274 }
2275
2276 OIIO_PLUGIN_NAMESPACE_END
2277