22
33#include < cstddef>
44#include < cstdint>
5+ #include < cstdio>
56#include < cstring>
7+ #include < sstream>
8+ #include < string_view>
69#include < utility>
710
811#include < opencv2/imgproc.hpp>
@@ -26,6 +29,22 @@ namespace
2629{
2730constexpr bool MEMMAP_SUPPORTED = VC_MEMMAP_SUPPORTED;
2831
32+ void TIFFWarningHandler (const char * module , const char * fmt, va_list ap)
33+ {
34+ std::array<char , 1024 > buf{};
35+ std::vsnprintf (buf.data (), buf.size (), fmt, ap);
36+ vc::Logger ()->debug (
37+ " [TIFFIO] {}: {}" , module , std::string_view (buf.data ()));
38+ }
39+
40+ void TIFFErrorHandler (const char * module , const char * fmt, va_list ap)
41+ {
42+ std::array<char , 1024 > buf{};
43+ std::vsnprintf (buf.data (), buf.size (), fmt, ap);
44+ vc::Logger ()->error (
45+ " [TIFFIO] {}: {}" , module , std::string_view (buf.data ()));
46+ }
47+
2948// Return a CV Mat type using TIFF type (signed, unsigned, float),
3049// bit-depth, and number of channels
3150auto GetCVMatType (
@@ -144,7 +163,7 @@ auto ReadImage(lt::TIFF* tif, const TIFFHeader& hdr) -> cv::Mat
144163}
145164
146165// Returns whether this TIFF file is encoded for memory mapping
147- auto CanMMap (const TIFFHeader& hdr) -> bool
166+ auto CanMMap (const TIFFHeader& hdr) -> std::pair< bool, std::string>
148167{
149168 const auto isContig = hdr.config == PLANARCONFIG_CONTIG;
150169 const auto isUint = hdr.type == SAMPLEFORMAT_UINT;
@@ -153,8 +172,43 @@ auto CanMMap(const TIFFHeader& hdr) -> bool
153172 const auto uncompressed = hdr.compression == tio::Compression::NONE;
154173 const auto singleStrip = hdr.rowsPerStrip == hdr.height ;
155174 const auto endianMatch = hdr.bigEndian == vc::endian::big ();
156- return isContig and isUint and is16bpc and isMono and uncompressed and
157- singleStrip and endianMatch;
175+
176+ // build result string
177+ std::stringstream ss;
178+ ss << std::boolalpha;
179+ bool hasValue{false };
180+ if (not isContig) {
181+ ss << (hasValue ? " , " : " " ) << " not contig" ;
182+ hasValue = true ;
183+ }
184+ if (not isUint) {
185+ ss << (hasValue ? " , " : " " ) << " not uint" ;
186+ hasValue = true ;
187+ }
188+ if (not is16bpc) {
189+ ss << (hasValue ? " , " : " " ) << " not 16bpc" ;
190+ hasValue = true ;
191+ }
192+ if (not isMono) {
193+ ss << (hasValue ? " , " : " " ) << " not mono" ;
194+ hasValue = true ;
195+ }
196+ if (not uncompressed) {
197+ ss << (hasValue ? " , " : " " ) << " not uncompressed" ;
198+ hasValue = true ;
199+ }
200+ if (not singleStrip) {
201+ ss << (hasValue ? " , " : " " ) << " not single strip" ;
202+ hasValue = true ;
203+ }
204+ if (not endianMatch) {
205+ ss << (hasValue ? " , " : " " ) << " wrong endian" ;
206+ }
207+
208+ return {
209+ isContig and isUint and is16bpc and isMono and uncompressed and
210+ singleStrip and endianMatch,
211+ ss.str ()};
158212}
159213
160214// Memory mapp the tiff
@@ -189,6 +243,10 @@ auto tio::ReadTIFF(const fs::path& path, mmap_info* mmap_info) -> cv::Mat
189243 throw IOException (" File does not exist" );
190244 }
191245
246+ // Log errors and warnings to VC's logger
247+ lt::TIFFSetErrorHandler (TIFFErrorHandler);
248+ lt::TIFFSetWarningHandler (TIFFWarningHandler);
249+
192250 // Open the file read-only
193251 lt::TIFF* tif = lt::TIFFOpen (path.c_str (), " rc" );
194252 if (tif == nullptr ) {
@@ -200,7 +258,8 @@ auto tio::ReadTIFF(const fs::path& path, mmap_info* mmap_info) -> cv::Mat
200258 cv::Mat img;
201259
202260 // Load memmap'd image
203- if (MEMMAP_SUPPORTED and mmap_info and CanMMap (hdr)) {
261+ if (const auto [res, msg] = CanMMap (hdr);
262+ MEMMAP_SUPPORTED and mmap_info and res) {
204263 // Try to mmap
205264 std::tie (img, *mmap_info) = MMapImage (path, hdr);
206265 if (img.empty ()) {
@@ -212,9 +271,8 @@ auto tio::ReadTIFF(const fs::path& path, mmap_info* mmap_info) -> cv::Mat
212271 // If we requested memory mapping (and it's available), log the failure
213272 if (MEMMAP_SUPPORTED and mmap_info) {
214273 Logger ()->debug (
215- " TIFF cannot be memory mapped: {}. Image will be read into "
216- " memory instead" ,
217- path.string ());
274+ " TIFF cannot be memory mapped: {}. Reason: {}" , path.string (),
275+ msg);
218276 }
219277 img = ReadImage (tif, hdr);
220278 }
@@ -239,6 +297,10 @@ void tio::WriteTIFF(
239297 " Invalid file extension " + path.extension ().string ());
240298 }
241299
300+ // Log errors and warnings to VC's logger
301+ lt::TIFFSetErrorHandler (TIFFErrorHandler);
302+ lt::TIFFSetWarningHandler (TIFFWarningHandler);
303+
242304 // Image metadata
243305 const auto channels = img.channels ();
244306 const auto width = static_cast <unsigned >(img.cols );
0 commit comments