diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e54178..401cc14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,10 +31,18 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # External dependencies set(EXTERNALPROJECT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +option(USE_SYSTEM_LIBS "Use system-provided libraries" OFF) + +option(USE_SYSTEM_ZLIB "Use system-provided ZLib library" OFF) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.zlib.cmake) + +option(USE_SYSTEM_YATO "Use system-provided Yato library" OFF) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.yato.cmake) +option(USE_SYSTEM_LIBJPEG "Use system-provided LibJPEG library" OFF) option(FREEIMAGE_WITH_LIBJPEG "Compile with the LibJPEG backend" ON) +option(FREEIMAGE_WITH_LIBJPEG_TRANSFORMS "LibJPEG lossless transforms" ON) + if (FREEIMAGE_WITH_LIBJPEG) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.jpeg.cmake) endif() @@ -44,31 +52,37 @@ if (FREEIMAGE_WITH_LIBOPENJPEG) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.openjpeg.cmake) endif() +option(USE_SYSTEM_LIBOPENEXR "Use system-provided OpenEXR library" OFF) option(FREEIMAGE_WITH_LIBOPENEXR "Compile with the LibOpenEXR backend" ON) if (FREEIMAGE_WITH_LIBOPENEXR) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.openexr.cmake) endif() +option(USE_SYSTEM_LIBPNG "Use system-provided LibPNG library" OFF) option(FREEIMAGE_WITH_LIBPNG "Compile with the LibPNG backend" ON) if (FREEIMAGE_WITH_LIBPNG) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.png.cmake) endif() +option(USE_SYSTEM_LIBTIFF "Use system-provided LibTIFF library" OFF) option(FREEIMAGE_WITH_LIBTIFF "Compile with the LibTIFF backend" ON) if (FREEIMAGE_WITH_LIBTIFF) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.tiff.cmake) endif() +option(USE_SYSTEM_LIBWEBP "Use system-provided LibWEBP library" OFF) option(FREEIMAGE_WITH_LIBWEBP "Compile with the LibWEBP backend" ON) if (FREEIMAGE_WITH_LIBWEBP) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.webp.cmake) endif() +option(USE_SYSTEM_LIBRAW "Use system-provided LibRAW library" OFF) option(FREEIMAGE_WITH_LIBRAW "Compile with the LibRAW backend" ON) if (FREEIMAGE_WITH_LIBRAW) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.raw.cmake) endif() +option(USE_SYSTEM_LIBHEIF "Use system-provided LibHEIF library" OFF) option(FREEIMAGE_WITH_LIBHEIF "Compile with the LibHEIF backend" ON) if (FREEIMAGE_WITH_LIBHEIF) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.heif.cmake) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9e3d759..e3c7311 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -82,6 +82,9 @@ endif() if (FREEIMAGE_WITH_LIBJPEG) target_compile_definitions(FreeImage PUBLIC "-DFREEIMAGE_WITH_LIBJPEG=1") + if (FREEIMAGE_WITH_LIBJPEG_TRANSFORMS) + target_compile_definitions(FreeImage PUBLIC "-DFREEIMAGE_WITH_LIBJPEG_TRANSFORMS=1") + endif() target_link_libraries(FreeImage PRIVATE LibJPEG) list(APPEND freeimage_plugins Plugins/PluginJPEG.cpp) endif() diff --git a/Source/FreeImage/ZLibInterface.cpp b/Source/FreeImage/ZLibInterface.cpp index 2938d51..a4f5f72 100644 --- a/Source/FreeImage/ZLibInterface.cpp +++ b/Source/FreeImage/ZLibInterface.cpp @@ -22,7 +22,8 @@ #include "zlib.h" #include "FreeImage.h" #include "Utilities.h" -#include "zutil.h" /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */ + +constexpr uint8_t GZIP_OS_UNKNOWN = 255; /** Compresses a source buffer into a target buffer, using the ZLib library. @@ -115,7 +116,7 @@ FreeImage_ZLibGZip(uint8_t *target, uint32_t target_size, uint8_t *source, uint3 return 0; case Z_OK: { // patch header, setup crc and length (stolen from mod_trace_output) - uint8_t *p = target + 8; *p++ = 2; *p = OS_CODE; // xflags, os_code + uint8_t *p = target + 8; *p++ = 2; *p = GZIP_OS_UNKNOWN; // xflags, os_code crc = crc32(crc, source, source_size); memcpy(target + 4 + dest_len, &crc, 4); memcpy(target + 8 + dest_len, &source_size, 4); diff --git a/Source/FreeImageToolkit/JPEGTransform.cpp b/Source/FreeImageToolkit/JPEGTransform.cpp index 97c47ad..22984cc 100644 --- a/Source/FreeImageToolkit/JPEGTransform.cpp +++ b/Source/FreeImageToolkit/JPEGTransform.cpp @@ -28,10 +28,15 @@ extern "C" { #undef FAR #include -#include "jinclude.h" +#include +#include #include "jpeglib.h" #include "jerror.h" + +#if FREEIMAGE_WITH_LIBJPEG_TRANSFORMS #include "transupp.h" +#endif // FREEIMAGE_WITH_LIBJPEG_TRANSFORMS + } #endif // FREEIMAGE_WITH_LIBJPEG @@ -154,6 +159,7 @@ getCropString(char* crop, size_t cropSize, int* left, int* top, int* right, int* return TRUE; } +#if FREEIMAGE_WITH_LIBJPEG_TRANSFORMS static FIBOOL JPEGTransformFromHandle(FreeImageIO* src_io, fi_handle src_handle, FreeImageIO* dst_io, fi_handle dst_handle, FREE_IMAGE_JPEG_OPERATION operation, int* left, int* top, int* right, int* bottom, FIBOOL perfect) { const FIBOOL onlyReturnCropRect = (!dst_io || !dst_handle); @@ -368,13 +374,14 @@ JPEGTransformFromHandle(FreeImageIO* src_io, fi_handle src_handle, FreeImageIO* return TRUE; } -#else // FREEIMAGE_WITH_LIBJPEG +#else // FREEIMAGE_WITH_LIBJPEG_TRANSFORMS static FIBOOL JPEGTransformFromHandle(FreeImageIO*, fi_handle, FreeImageIO*, fi_handle, FREE_IMAGE_JPEG_OPERATION, int*, int*, int*, int*, FIBOOL) { return FALSE; } +#endif // FREEIMAGE_WITH_LIBJPEG_TRANSFORMS #endif // FREEIMAGE_WITH_LIBJPEG // ---------------------------------------------------------- diff --git a/Source/Plugins/PluginJPEG.cpp b/Source/Plugins/PluginJPEG.cpp index b951fdb..dd5ce4c 100644 --- a/Source/Plugins/PluginJPEG.cpp +++ b/Source/Plugins/PluginJPEG.cpp @@ -35,10 +35,10 @@ extern "C" { #undef FAR #include -#include "jinclude.h" +#include +#include #include "jpeglib.h" #include "jerror.h" -#include "jversion.h" #include "jmorecfg.h" } @@ -483,119 +483,6 @@ marker_is_icc(jpeg_saved_marker_ptr marker) { return FALSE; } -#ifndef JPEG_HAS_READ_ICC_PROFILE -/** - See if there was an ICC profile in the JPEG file being read; - if so, reassemble and return the profile data. - - TRUE is returned if an ICC profile was found, FALSE if not. - If TRUE is returned, *icc_data_ptr is set to point to the - returned data, and *icc_data_len is set to its length. - - IMPORTANT: the data at **icc_data_ptr has been allocated with malloc() - and must be freed by the caller with free() when the caller no longer - needs it. (Alternatively, we could write this routine to use the - IJG library's memory allocator, so that the data would be freed implicitly - at jpeg_finish_decompress() time. But it seems likely that many apps - will prefer to have the data stick around after decompression finishes.) - - NOTE: if the file contains invalid ICC APP2 markers, we just silently - return FALSE. You might want to issue an error message instead. -*/ -static FIBOOL -jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned *icc_data_len) { - jpeg_saved_marker_ptr marker; - int num_markers = 0; - int seq_no; - unsigned total_length; - - const int MAX_SEQ_NO = 255; // sufficient since marker numbers are bytes - uint8_t marker_present[MAX_SEQ_NO+1]; // 1 if marker found - unsigned data_length[MAX_SEQ_NO+1]; // size of profile data in marker - unsigned data_offset[MAX_SEQ_NO+1]; // offset for data in marker - - *icc_data_ptr = nullptr; // avoid confusion if FALSE return - *icc_data_len = 0; - - /** - this first pass over the saved markers discovers whether there are - any ICC markers and verifies the consistency of the marker numbering. - */ - - memset(marker_present, 0, (MAX_SEQ_NO + 1)); - - for (marker = cinfo->marker_list; marker; marker = marker->next) { - if (marker_is_icc(marker)) { - if (num_markers == 0) { - // number of markers - num_markers = GETJOCTET(marker->data[13]); - } - else if (num_markers != GETJOCTET(marker->data[13])) { - return FALSE; // inconsistent num_markers fields - } - // sequence number - seq_no = GETJOCTET(marker->data[12]); - if (seq_no <= 0 || seq_no > num_markers) { - return FALSE; // bogus sequence number - } - if (marker_present[seq_no]) { - return FALSE; // duplicate sequence numbers - } - marker_present[seq_no] = 1; - data_length[seq_no] = marker->data_length - ICC_HEADER_SIZE; - } - } - - if (num_markers == 0) - return FALSE; - - /** - check for missing markers, count total space needed, - compute offset of each marker's part of the data. - */ - - total_length = 0; - for (seq_no = 1; seq_no <= num_markers; seq_no++) { - if (marker_present[seq_no] == 0) { - return FALSE; // missing sequence number - } - data_offset[seq_no] = total_length; - total_length += data_length[seq_no]; - } - - if (total_length <= 0) { - return FALSE; // found only empty markers ? - } - - // allocate space for assembled data - std::unique_ptr icc_data(static_cast(malloc(total_length * sizeof(JOCTET))), &free); - if (!icc_data) { - return FALSE; // out of memory - } - - // and fill it in - for (marker = cinfo->marker_list; marker; marker = marker->next) { - if (marker_is_icc(marker)) { - JOCTET FAR *src_ptr; - JOCTET *dst_ptr; - unsigned length; - seq_no = GETJOCTET(marker->data[12]); - dst_ptr = icc_data.get() + data_offset[seq_no]; - src_ptr = marker->data + ICC_HEADER_SIZE; - length = data_length[seq_no]; - while (length--) { - *dst_ptr++ = *src_ptr++; - } - } - } - - *icc_data_ptr = icc_data.release(); - *icc_data_len = total_length; - - return TRUE; -} -#endif - /** Read JPEG_APPD marker (IPTC or Adobe Photoshop profile) */ diff --git a/Source/Plugins/PluginWebP.cpp b/Source/Plugins/PluginWebP.cpp index 25f2d98..bb3bdec 100644 --- a/Source/Plugins/PluginWebP.cpp +++ b/Source/Plugins/PluginWebP.cpp @@ -27,7 +27,26 @@ #include "webp/decode.h" #include "webp/encode.h" #include "webp/mux.h" -#include "dec/vp8i_dec.h" + +#include + +struct WebPVersion { + uint32_t major; + uint32_t minor; + uint32_t patch; +}; + +static WebPVersion GetWebPVersion() { + static char version[32]; + + const uint32_t v = WebPGetDecoderVersion(); + + return { + (v >> 16) & 0xff, + (v >> 8) & 0xff, + v & 0xff + }; +} // ========================================================== // Plugin Interface @@ -681,11 +700,22 @@ InitWEBP(Plugin *plugin, int format_id) { const FIDEPENDENCY* GetWebpDependencyInfo() { + static char fullVersion[32]; + + const auto version = GetWebPVersion(); + + std::snprintf(fullVersion, sizeof(fullVersion), + "LibWebP v%d.%d.%d", + version.major, + version.minor, + version.patch); + static const FIDEPENDENCY info = { .name = "LibWebP", - .fullVersion = "LibWebP v" FI_QUOTE(DEC_MAJ_VERSION) "." FI_QUOTE(DEC_MIN_VERSION) "." FI_QUOTE(DEC_REV_VERSION), - .majorVersion = DEC_MAJ_VERSION, - .minorVersion = DEC_MIN_VERSION + .fullVersion = fullVersion, + .majorVersion = version.major, + .minorVersion = version.minor }; + return &info; } diff --git a/cmake/dependency.heif.cmake b/cmake/dependency.heif.cmake index 0f1af8b..f202daf 100644 --- a/cmake/dependency.heif.cmake +++ b/cmake/dependency.heif.cmake @@ -3,6 +3,13 @@ # # Output target: LibHEIF +set(HEIF_VERSION "1.20.2") + +if (USE_SYSTEM_LIBHEIF OR USE_SYSTEM_LIBS) + find_package(libheif REQUIRED CONFIG) + add_library(LibHEIF ALIAS heif) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.de265.cmake) @@ -10,8 +17,6 @@ include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.kvazaar.cmake) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.dav1d.cmake) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.svtav1.cmake) -set(HEIF_VERSION "1.20.2") - ExternalProject_Add(HEIF PREFIX ${EXTERNALPROJECT_BINARY_ROOT}/heif URL "https://github.com/strukturag/libheif/releases/download/v${HEIF_VERSION}/libheif-${HEIF_VERSION}.tar.gz" diff --git a/cmake/dependency.jpeg.cmake b/cmake/dependency.jpeg.cmake index 129fa4f..13f7646 100644 --- a/cmake/dependency.jpeg.cmake +++ b/cmake/dependency.jpeg.cmake @@ -2,6 +2,12 @@ # # Output target: LibJPEG +if (USE_SYSTEM_LIBJPEG OR USE_SYSTEM_LIBS) + find_package(JPEG REQUIRED) + add_library(LibJPEG ALIAS JPEG::JPEG) + return() +endif() + include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) @@ -71,7 +77,6 @@ elseif(JPEG_REPOSITORY STREQUAL "JPEG-turbo") else() target_link_libraries(LibJPEG INTERFACE ${INSTALL_DIR}/lib/libturbojpeg${CMAKE_STATIC_LIBRARY_SUFFIX}) endif() - target_compile_options(LibJPEG INTERFACE "-DJPEG_HAS_READ_ICC_PROFILE=1") target_include_directories(LibJPEG INTERFACE ${INSTALL_DIR}/include) set_property(TARGET TURBOJPEG PROPERTY FOLDER "Dependencies") diff --git a/cmake/dependency.openexr.cmake b/cmake/dependency.openexr.cmake index eb32412..156f3d5 100644 --- a/cmake/dependency.openexr.cmake +++ b/cmake/dependency.openexr.cmake @@ -4,6 +4,11 @@ # Output target: LibOpenEXR # +if (USE_SYSTEM_LIBOPENEXR OR USE_SYSTEM_LIBS) + find_package(OpenEXR REQUIRED CONFIG) + add_library(LibOpenEXR ALIAS OpenEXR::OpenEXR) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.openjph.cmake) diff --git a/cmake/dependency.png.cmake b/cmake/dependency.png.cmake index 5b1e163..1c2d76c 100644 --- a/cmake/dependency.png.cmake +++ b/cmake/dependency.png.cmake @@ -3,6 +3,11 @@ # # Output target: LibPNG +if (USE_SYSTEM_LIBPNG OR USE_SYSTEM_LIBS) + find_package(PNG) + add_library(LibPNG ALIAS PNG::PNG) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) diff --git a/cmake/dependency.raw.cmake b/cmake/dependency.raw.cmake index 9f13ff3..ec6c751 100644 --- a/cmake/dependency.raw.cmake +++ b/cmake/dependency.raw.cmake @@ -3,6 +3,12 @@ # # Output target: LibRAW +if (USE_SYSTEM_LIBRAW OR USE_SYSTEM_LIBS) + find_package(PkgConfig) + pkg_check_modules(LIBRAW REQUIRED IMPORTED_TARGET libraw) + add_library(LibRAW ALIAS PkgConfig::LIBRAW) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) diff --git a/cmake/dependency.tiff.cmake b/cmake/dependency.tiff.cmake index e8ee2f9..7f3ccd5 100644 --- a/cmake/dependency.tiff.cmake +++ b/cmake/dependency.tiff.cmake @@ -3,6 +3,12 @@ # # Output targets: LibTIFF +if (USE_SYSTEM_LIBTIFF OR USE_SYSTEM_LIBS) + find_package(PkgConfig) + pkg_check_modules(LIBTIFF REQUIRED IMPORTED_TARGET libtiff-4) + add_library(libTIFF ALIAS PkgConfig::LIBTIFF) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) include(${EXTERNALPROJECT_INCLUDE_DIR}/dependency.imath.cmake) # Only for half.h diff --git a/cmake/dependency.webp.cmake b/cmake/dependency.webp.cmake index 9988a66..c57d2c2 100644 --- a/cmake/dependency.webp.cmake +++ b/cmake/dependency.webp.cmake @@ -3,6 +3,12 @@ # # Output target: LibWEBP +if (USE_SYSTEM_LIBWEBP OR USE_SYSTEM_LIBS) + find_package(PkgConfig) + pkg_check_modules(LIBWEBP REQUIRED IMPORTED_TARGET libwebp) + add_library(LibWEBP ALIAS PkgConfig::LIBWEBP) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) diff --git a/cmake/dependency.yato.cmake b/cmake/dependency.yato.cmake index c4eae69..0c1dbf6 100644 --- a/cmake/dependency.yato.cmake +++ b/cmake/dependency.yato.cmake @@ -4,6 +4,11 @@ # Output target: LibYato # YATO_INCLUDE_DIR - includes +if (USE_SYSTEM_YATO OR USE_SYSTEM_LIBS) + find_package(Yato REQUIRED CONFIG) + add_library(LibYato ALIAS Yato::Yato) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake) diff --git a/cmake/dependency.zlib.cmake b/cmake/dependency.zlib.cmake index 981643a..bad24f5 100644 --- a/cmake/dependency.zlib.cmake +++ b/cmake/dependency.zlib.cmake @@ -6,6 +6,11 @@ if(NOT _ZLIB_DEP_INCLUDE_GUARD_) set(_ZLIB_DEP_INCLUDE_GUARD_ ON) +if (USE_SYSTEM_ZLIB OR USE_SYSTEM_LIBS) + find_package(ZLIB REQUIRED) + add_library(LibZLIB ALIAS ZLIB::ZLIB) + return() +endif() include(${EXTERNALPROJECT_INCLUDE_DIR}/external_project_common.cmake)