diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 967ac608b9..bd1bb2ddfb 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -297,6 +297,16 @@ if(JPEG_SUPPORT AND old-jpeg) set(OJPEG_SUPPORT TRUE) endif() +# WEBP +set(WEBP_SUPPORT FALSE) +if(HAVE_WEBP) + set(WEBP_SUPPORT TRUE) + if(TARGET ${WEBP_LIBRARY} AND DEFINED ${WEBP_LIBRARY}_BINARY_DIR) + include_directories("${${WEBP_LIBRARY}_BINARY_DIR}") + endif() + include_directories(${WEBP_INCLUDE_DIR}) +endif() + # OpenCV: turned off set(JBIG_SUPPORT 0) set(LZMA_SUPPORT 0) # OpenCV: turned off @@ -329,6 +339,9 @@ endif() if(JPEG12_INCLUDE_DIR) list(APPEND TIFF_INCLUDES ${JPEG12_INCLUDE_DIR}) endif() +if(WEBP_INCLUDE_DIR) + list(APPEND TIFF_INCLUDES ${WEBP_INCLUDE_DIR}) +endif() if(JBIG_INCLUDE_DIR) list(APPEND TIFF_INCLUDES ${JBIG_INCLUDE_DIR}) endif() @@ -347,6 +360,9 @@ endif() if(JPEG_LIBRARIES) list(APPEND TIFF_LIBRARY_DEPS ${JPEG_LIBRARIES}) endif() +if(WEBP_LIBRARIES) + list(APPEND TIFF_LIBRARY_DEPS ${WEBPLIBRARIES}) +endif() if(JPEG12_LIBRARIES) list(APPEND TIFF_LIBRARY_DEPS ${JPEG12_LIBRARIES}) endif() @@ -462,6 +478,9 @@ ocv_warnings_disable(CMAKE_C_FLAGS /wd4267 /wd4244 /wd4018 /wd4311 /wd4312) add_library(${TIFF_LIBRARY} STATIC ${OPENCV_3RDPARTY_EXCLUDE_FROM_ALL} ${lib_srcs}) target_link_libraries(${TIFF_LIBRARY} ${ZLIB_LIBRARIES}) +if(HAVE_WEBP) + target_link_libraries(${TIFF_LIBRARY} ${WEBP_LIBRARY}) +endif() set_target_properties(${TIFF_LIBRARY} PROPERTIES diff --git a/3rdparty/libtiff/tiffconf.h.cmake.in b/3rdparty/libtiff/tiffconf.h.cmake.in index a5789bbb0a..df61973911 100644 --- a/3rdparty/libtiff/tiffconf.h.cmake.in +++ b/3rdparty/libtiff/tiffconf.h.cmake.in @@ -108,6 +108,9 @@ /* Support libdeflate enhanced compression */ #cmakedefine LIBDEFLATE_SUPPORT 1 +/* Support webp compression */ +#cmakedefine WEBP_SUPPORT 1 + /* Support strip chopping (whether or not to convert single-strip uncompressed images to multiple strips of ~8Kb to reduce memory usage) */ #cmakedefine STRIPCHOP_DEFAULT TIFF_STRIPCHOP diff --git a/cmake/OpenCVFindLibsGrfmt.cmake b/cmake/OpenCVFindLibsGrfmt.cmake index c97169ee7b..d205dc814f 100644 --- a/cmake/OpenCVFindLibsGrfmt.cmake +++ b/cmake/OpenCVFindLibsGrfmt.cmake @@ -145,61 +145,6 @@ if(WITH_JPEG) set(HAVE_JPEG YES) endif() -# --- libtiff (optional, should be searched after zlib and libjpeg) --- -if(WITH_TIFF) - if(BUILD_TIFF) - ocv_clear_vars(TIFF_FOUND) - else() - ocv_clear_internal_cache_vars(TIFF_LIBRARY TIFF_INCLUDE_DIR) - if(QNX) - set(TIFF_LIBRARY tiff) - set(TIFF_LIBRARIES tiff) - set(TIFF_FOUND TRUE) - else() - include(FindTIFF) - endif() - if(TIFF_FOUND) - ocv_parse_header("${TIFF_INCLUDE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) - endif() - endif() - - if(NOT TIFF_FOUND) - if(NOT BUILD_TIFF) - message(WARNING "TIFF library has not been found, falling back to built-in version. " - "Add the external installation prefix to CMAKE_PREFIX_PATH, or set TIFF_INCLUDE_DIR " - "and TIFF_LIBRARY, so that FindTIFF can locate it. " - "See FindTIFF cmake documentation for details.") - endif() - ocv_clear_vars(TIFF_LIBRARY TIFF_LIBRARIES TIFF_INCLUDE_DIR) - - set(TIFF_LIBRARY libtiff CACHE INTERNAL "") - set(TIFF_LIBRARIES ${TIFF_LIBRARY}) - add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libtiff") - set(TIFF_INCLUDE_DIR "${${TIFF_LIBRARY}_SOURCE_DIR}" "${${TIFF_LIBRARY}_BINARY_DIR}" CACHE INTERNAL "") - ocv_parse_header("${${TIFF_LIBRARY}_SOURCE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) - endif() - - if(TIFF_VERSION_CLASSIC AND NOT TIFF_VERSION) - set(TIFF_VERSION ${TIFF_VERSION_CLASSIC}) - endif() - - if(TIFF_BIGTIFF_VERSION AND NOT TIFF_VERSION_BIG) - set(TIFF_VERSION_BIG ${TIFF_BIGTIFF_VERSION}) - endif() - - if(NOT TIFF_VERSION_STRING AND TIFF_INCLUDE_DIR) - foreach(_TIFF_INCLUDE_DIR IN LISTS TIFF_INCLUDE_DIR) - if(EXISTS "${_TIFF_INCLUDE_DIR}/tiffvers.h") - file(STRINGS "${_TIFF_INCLUDE_DIR}/tiffvers.h" tiff_version_str REGEX "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version .*") - string(REGEX REPLACE "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version +([^ \\n]*).*" "\\1" TIFF_VERSION_STRING "${tiff_version_str}") - unset(tiff_version_str) - endif() - endforeach() - endif() - - set(HAVE_TIFF YES) -endif() - # --- libwebp (optional) --- if(WITH_WEBP) @@ -263,6 +208,61 @@ if(NOT WEBP_VERSION AND WEBP_INCLUDE_DIR) set(WEBP_VERSION "decoder: ${WEBP_DECODER_ABI_VERSION}, encoder: ${WEBP_ENCODER_ABI_VERSION}, demux: ${WEBP_DEMUX_ABI_VERSION}") endif() +# --- libtiff (optional, should be searched after zlib, libjpeg and libwebp) --- +if(WITH_TIFF) + if(BUILD_TIFF) + ocv_clear_vars(TIFF_FOUND) + else() + ocv_clear_internal_cache_vars(TIFF_LIBRARY TIFF_INCLUDE_DIR) + if(QNX) + set(TIFF_LIBRARY tiff) + set(TIFF_LIBRARIES tiff) + set(TIFF_FOUND TRUE) + else() + include(FindTIFF) + endif() + if(TIFF_FOUND) + ocv_parse_header("${TIFF_INCLUDE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) + endif() + endif() + + if(NOT TIFF_FOUND) + if(NOT BUILD_TIFF) + message(WARNING "TIFF library has not been found, falling back to built-in version. " + "Add the external installation prefix to CMAKE_PREFIX_PATH, or set TIFF_INCLUDE_DIR " + "and TIFF_LIBRARY, so that FindTIFF can locate it. " + "See FindTIFF cmake documentation for details.") + endif() + ocv_clear_vars(TIFF_LIBRARY TIFF_LIBRARIES TIFF_INCLUDE_DIR) + + set(TIFF_LIBRARY libtiff CACHE INTERNAL "") + set(TIFF_LIBRARIES ${TIFF_LIBRARY}) + add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/libtiff") + set(TIFF_INCLUDE_DIR "${${TIFF_LIBRARY}_SOURCE_DIR}" "${${TIFF_LIBRARY}_BINARY_DIR}" CACHE INTERNAL "") + ocv_parse_header("${${TIFF_LIBRARY}_SOURCE_DIR}/tiff.h" TIFF_VERSION_LINES TIFF_VERSION_CLASSIC TIFF_VERSION_BIG TIFF_VERSION TIFF_BIGTIFF_VERSION) + endif() + + if(TIFF_VERSION_CLASSIC AND NOT TIFF_VERSION) + set(TIFF_VERSION ${TIFF_VERSION_CLASSIC}) + endif() + + if(TIFF_BIGTIFF_VERSION AND NOT TIFF_VERSION_BIG) + set(TIFF_VERSION_BIG ${TIFF_BIGTIFF_VERSION}) + endif() + + if(NOT TIFF_VERSION_STRING AND TIFF_INCLUDE_DIR) + foreach(_TIFF_INCLUDE_DIR IN LISTS TIFF_INCLUDE_DIR) + if(EXISTS "${_TIFF_INCLUDE_DIR}/tiffvers.h") + file(STRINGS "${_TIFF_INCLUDE_DIR}/tiffvers.h" tiff_version_str REGEX "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version .*") + string(REGEX REPLACE "^#define[\t ]+TIFFLIB_VERSION_STR[\t ]+\"LIBTIFF, Version +([^ \\n]*).*" "\\1" TIFF_VERSION_STRING "${tiff_version_str}") + unset(tiff_version_str) + endif() + endforeach() + endif() + + set(HAVE_TIFF YES) +endif() + # --- libjxl (optional) --- if(WITH_JPEGXL) ocv_clear_vars(HAVE_JPEGXL) diff --git a/modules/imgcodecs/test/test_tiff.cpp b/modules/imgcodecs/test/test_tiff.cpp index 66232cf6ff..927aa390e6 100644 --- a/modules/imgcodecs/test/test_tiff.cpp +++ b/modules/imgcodecs/test/test_tiff.cpp @@ -1886,6 +1886,40 @@ INSTANTIATE_TEST_CASE_P(Imgcodecs_Tiff, Imgcodecs_Tiff_compress_level, testing::ValuesIn(supportedMethod_minLevel_maxLevel) ); +TEST(Imgcodecs_Tiff, support_webp) +{ + //build a dummy image that can be heavily compressed + cv::Mat src(cv::Size(640, 480), CV_8UC3); + src.forEach([&](cv::Vec3b& pixel, const int* pos) { + const int y = pos[0]; + const int x = pos[1]; + const uchar value = static_cast(y*src.cols+x); + pixel = cv::Vec3b(value, value, value); + }); + + vector bufNone; + vector bufWebP; + vector bufLZW; + ASSERT_NO_THROW(ASSERT_TRUE(imencode(".tif", src, bufNone, {IMWRITE_TIFF_COMPRESSION, IMWRITE_TIFF_COMPRESSION_NONE}))); + ASSERT_NO_THROW(ASSERT_TRUE(imencode(".tif", src, bufWebP, {IMWRITE_TIFF_COMPRESSION, IMWRITE_TIFF_COMPRESSION_WEBP}))); + ASSERT_NO_THROW(ASSERT_TRUE(imencode(".tif", src, bufLZW, {IMWRITE_TIFF_COMPRESSION, IMWRITE_TIFF_COMPRESSION_LZW}))); + + std::cout << "TIFF-None: " << bufNone.size() << " bytes" << std::endl; + std::cout << "TIFF-LZW: " << bufLZW.size() << " bytes" << std::endl; + std::cout << "TIFF-WebP: " << bufWebP.size() << " bytes" << std::endl; + + // If the size of the TIFF file compressed with WebP matches + // the size compressed with LZW, it indicates that the underlying + // libtiff configuration does not support TIFF-WebP, and OpenCV + // has fallen back to LZW. This is an expected environment-dependent + // behavior rather than a test failure, so we gracefully skip the test. + if (bufWebP.size() == bufLZW.size()) { + throw SkipTestException("TIFF-WebP appears to be unsupported (compressed size is identical to LZW)."); + } + + // We expect WebP compressed size must be smaller than None. + ASSERT_LE(bufWebP.size(), bufNone.size()); +} #endif