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