Skip to content

Commit ae2231a

Browse files
pango_image: Add basic Tiff loading support.
1 parent 118a1ba commit ae2231a

File tree

3 files changed

+85
-3
lines changed

3 files changed

+85
-3
lines changed

components/pango_image/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ option(BUILD_PANGOLIN_LIBTIFF "Build support for libtiff image input" ON)
2626
if(BUILD_PANGOLIN_LIBTIFF)
2727
find_package(TIFF QUIET)
2828
if(TIFF_FOUND)
29-
target_compile_definitions(${COMPONENT} PRIVATE HAVE_TIFF)
29+
target_compile_definitions(${COMPONENT} PRIVATE HAVE_LIBTIFF)
3030
target_include_directories(${COMPONENT} PRIVATE ${TIFF_INCLUDE_DIR} )
3131
target_link_libraries(${COMPONENT} PRIVATE ${TIFF_LIBRARY})
3232
message(STATUS "libtiff Found and Enabled")
@@ -99,6 +99,7 @@ PRIVATE
9999
${CMAKE_CURRENT_LIST_DIR}/src/image_io_bmp.cpp
100100
${CMAKE_CURRENT_LIST_DIR}/src/image_io_zstd.cpp
101101
${CMAKE_CURRENT_LIST_DIR}/src/image_io_libraw.cpp
102+
${CMAKE_CURRENT_LIST_DIR}/src/image_io_tiff.cpp
102103
)
103104

104105
target_link_libraries(${COMPONENT} PUBLIC pango_core)

components/pango_image/src/image_io.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ void SavePacked12bit(const Image<unsigned char>& image, const pangolin::PixelFor
7373
// LibRaw raw camera files
7474
TypedImage LoadLibRaw(const std::string& filename);
7575

76+
// TIFF
77+
TypedImage LoadTiff(const std::string& filename);
78+
7679
TypedImage LoadImage(std::istream& in, ImageFileType file_type)
7780
{
7881
switch (file_type) {
@@ -118,9 +121,9 @@ TypedImage LoadImage(const std::string& filename, ImageFileType file_type)
118121
case ImageFileTypePango:
119122
return LoadPango(filename);
120123
case ImageFileTypeArw:
121-
[[fallthrough]];
122-
case ImageFileTypeTiff:
123124
return LoadLibRaw(filename);
125+
case ImageFileTypeTiff:
126+
return LoadTiff(filename);
124127
default:
125128
throw std::runtime_error("Unsupported image file type, '" + filename + "'");
126129
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <cassert>
2+
#include <pangolin/image/typed_image.h>
3+
4+
#ifdef HAVE_LIBTIFF
5+
# include <tiffio.h>
6+
#endif
7+
8+
namespace pangolin {
9+
10+
#ifdef HAVE_LIBTIFF
11+
template<typename T>
12+
T GetOrThrow(TIFF* tif, uint32_t tag)
13+
{
14+
T r;
15+
if (TIFFGetField(tif, tag, &r) != 1) {
16+
throw std::runtime_error("Expected tag missing when reading tiff (" + std::to_string(tag) + ")");
17+
}
18+
return r;
19+
}
20+
21+
template<typename T>
22+
T GetOrDefault(TIFF* tif, uint32_t tag, T default_val)
23+
{
24+
T r = default_val;
25+
TIFFGetField(tif, tag, &r);
26+
return r;
27+
}
28+
#endif
29+
30+
TypedImage LoadTiff(
31+
const std::string& filename
32+
) {
33+
#ifdef HAVE_LIBTIFF
34+
TIFF* tif = TIFFOpen(filename.c_str(),"r");
35+
if (!tif) {
36+
throw std::runtime_error("libtiff failed to open " + filename);
37+
}
38+
39+
const auto width = GetOrThrow<uint32_t>(tif, TIFFTAG_IMAGEWIDTH);
40+
const auto height = GetOrThrow<uint32_t>(tif, TIFFTAG_IMAGELENGTH);
41+
const auto channels = GetOrThrow<uint16_t>(tif, TIFFTAG_SAMPLESPERPIXEL);
42+
const auto bits_per_channel = GetOrThrow<uint16_t>(tif, TIFFTAG_BITSPERSAMPLE);
43+
const auto sample_format = GetOrDefault<uint16_t>(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
44+
const auto planar = GetOrThrow<uint16_t>(tif, TIFFTAG_PLANARCONFIG);
45+
// const auto photom = GetOrThrow<uint16_t>(tif, TIFFTAG_PHOTOMETRIC);
46+
47+
assert(width >= 0 && height >= 0 && channels >= 0 && bits_per_channel > 0);
48+
49+
if(planar != PLANARCONFIG_CONTIG /*|| photom != PHOTOMETRIC_RGB*/ || bits_per_channel % 8 != 0 || !(channels == 1 || channels == 3))
50+
throw std::runtime_error("TIFF support is currently limited. Consider contributing to image_io_tiff.cpp.");
51+
52+
std::string sfmt;
53+
switch(sample_format) {
54+
case SAMPLEFORMAT_UINT: sfmt = (channels == 3) ? "RGB24" : "GRAY8"; break;
55+
case SAMPLEFORMAT_IEEEFP: sfmt = (channels == 3) ? "RGB96F" : "GRAY32F"; break;
56+
default: throw std::runtime_error("TIFF support is currently limited. Consider contributing to image_io_tiff.cpp.");
57+
}
58+
59+
TypedImage image(width, height, PixelFormatFromString(sfmt));
60+
const tsize_t scanlength_bytes = TIFFScanlineSize(tif);
61+
if(scanlength_bytes != image.pitch)
62+
throw std::runtime_error("TIFF: unexpected scanline length");
63+
64+
for (size_t row = 0; row < height; ++row) {
65+
TIFFReadScanline(tif, image.RowPtr(row), row);
66+
}
67+
68+
TIFFClose(tif);
69+
70+
return image;
71+
#else
72+
PANGOLIN_UNUSED(filename);
73+
throw std::runtime_error("Rebuild Pangolin for libtiff support.");
74+
#endif
75+
}
76+
77+
}
78+

0 commit comments

Comments
 (0)