SDL_image: Synchronized with changes in the SDL2 branch

From 42842740c05d7aeb7320313f415f16b3b1b333ab Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 7 Feb 2025 10:07:45 -0800
Subject: [PATCH] Synchronized with changes in the SDL2 branch

---
 .github/workflows/main.yml |   1 +
 CMakeLists.txt             | 401 +++++++++++++++++++++++++------------
 VisualC/SDL_image.sln      |   3 +-
 external/libtiff           |   2 +-
 external/libwebp           |   2 +-
 5 files changed, 281 insertions(+), 128 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 33396818d..54ad2540f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -117,6 +117,7 @@ jobs:
         export CMAKE_CONFIGURATION_TYPES=Debug
         cmake -B build \
           -DSDL2IMAGE_VENDORED=${{ matrix.platform.vendored }} \
+          -DSDL2IMAGE_STRICT=ON \
           -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=$PWD/build \
           -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=$PWD/build \
           -DBUILD_SHARED_LIBS=ON \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e12d7eebd..d1ef8651b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,6 +63,14 @@ cmake_dependent_option(SDL2IMAGE_INSTALL "Enable SDL2_image install target" ${SD
 option(SDL2IMAGE_DEPS_SHARED "Load dependencies dynamically" ON)
 option(SDL2IMAGE_VENDORED "Use vendored third-party libraries" ${vendored_default})
 
+option(SDL2IMAGE_STRICT "Fail when a dependency could not be found" OFF)
+set(required "")
+set(fatal_error "STATUS")
+if(SDL2IMAGE_STRICT)
+    set(required "REQUIRED")
+    set(fatal_error "FATAL_ERROR")
+endif()
+
 option(SDL2IMAGE_SAMPLES "Build the SDL2_image sample program(s)" ${SDL2IMAGE_SAMPLES_DEFAULT})
 cmake_dependent_option(SDL2IMAGE_SAMPLES_INSTALL "Install the SDL2_image sample program(s)" OFF "SDL2IMAGE_SAMPLES;SDL2IMAGE_INSTALL" OFF)
 
@@ -312,13 +320,20 @@ endif()
 set(INSTALL_EXTRA_TARGETS)
 set(PC_LIBS)
 set(PC_REQUIRES)
+set(SDL2IMAGE_BACKENDS)
 
+list(APPEND SDL2IMAGE_BACKENDS STB)
+set(SDL2IMAGE_STB_ENABLED FALSE)
 if(SDL2IMAGE_BACKEND_STB)
+    set(SDL2IMAGE_STB_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE USE_STBIMAGE)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS IMAGEIO)
+set(SDL2IMAGE_IMAGEIO_ENABLED FALSE)
 if(APPLE)
     if(SDL2IMAGE_BACKEND_IMAGEIO)
+        set(SDL2IMAGE_IMAGEIO_ENABLED TRUE)
         if(CMAKE_SYSTEM_NAME MATCHES ".*(Darwin|MacOS).*")
             target_link_libraries(SDL2_image PRIVATE -Wl,-framework,ApplicationServices)
         endif()
@@ -338,13 +353,18 @@ if(APPLE)
     endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS WIC)
+set(SDL2IMAGE_WIC_ENABLED FALSE)
 if(SDL2IMAGE_BACKEND_WIC)
+    set(SDL2IMAGE_WIC_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE SDL_IMAGE_USE_WIC_BACKEND)
 endif()
 
 if(SDL2IMAGE_ZLIB)
     if(SDL2IMAGE_ZLIB_VENDORED)
         message(STATUS "${PROJECT_NAME}: Using vendored zlib")
+        # disable build of zlib example programs:
+        set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "zlib examples" FORCE)
         sdl_check_project_in_subfolder(external/zlib zlib SDL2IMAGE_VENDORED)
         add_subdirectory(external/zlib EXCLUDE_FROM_ALL)
         set(ZLIB_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/external/zlib;${CMAKE_CURRENT_BINARY_DIR}/external/zlib")
@@ -357,6 +377,9 @@ if(SDL2IMAGE_ZLIB)
             set(ZLIB_LIBRARY zlibstatic)
             set(SKIP_INSTALL_CONFIG_FILE ON)
         endif()
+        if(NOT TARGET ZLIB::ZLIB)
+            add_library(ZLIB::ZLIB ALIAS ${ZLIB_LIBRARY})
+        endif()
         # ZLIB_INCLUDE_DIRS variable is used by vendored libpng
         set(ZLIB_INCLUDE_DIRS "${ZLIB_INCLUDE_DIR}")
         # ZLIB_LIBRARIES variable is used by vendored libpng
@@ -365,8 +388,7 @@ if(SDL2IMAGE_ZLIB)
         set_target_properties(${ZLIB_LIBRARY} PROPERTIES EXPORT_NAME external_zlib)
         add_library(SDL2_image::external_zlib ALIAS ${ZLIB_LIBRARY})
     else()
-        message(STATUS "${PROJECT_NAME}: Using system zlib")
-        find_package(ZLIB REQUIRED)
+        message(FATAL_ERROR "Internal error (zlib is only required when requesting vendored dependencies)")
     endif()
 endif()
 
@@ -377,13 +399,15 @@ if(SDL2IMAGE_DAV1D)
         set(DAV1D_LIBRARY dav1d)
         list(APPEND INSTALL_EXTRA_TARGETS dav1d)
     else()
-        message(FATAL_ERROR "Not implemented")
+        message(FATAL_ERROR "Internal error (dav1d is only required when requesting vendored dependencies)")
     endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS AVIF)
+set(SDL2IMAGE_AVIF_ENABLED FALSE)
 if(SDL2IMAGE_AVIF)
-    target_compile_definitions(SDL2_image PRIVATE LOAD_AVIF)
     if(SDL2IMAGE_AVIF_VENDORED)
+        set(SDL2IMAGE_AVIF_ENABLED TRUE)
         message(STATUS "${PROJECT_NAME}: Using vendored libavif")
         sdl_check_project_in_subfolder(external/libavif libavif SDL2IMAGE_VENDORED)
         set(BUILD_SHARED_LIBS ${SDL2IMAGE_AVIF_SHARED})
@@ -405,52 +429,65 @@ if(SDL2IMAGE_AVIF)
           endif()
         endif()
     else()
-        message(STATUS "${PROJECT_NAME}: Using system libavif")
         find_package(libavif 1.0 QUIET)
         if(NOT libavif_FOUND)
             message(STATUS "libavif-1.0 or compatible not found")
             find_package(libavif ${LIBAVIF_MINIMUM_VERSION} QUIET)
         endif()
         if(libavif_FOUND)
+            set(SDL2IMAGE_AVIF_ENABLED TRUE)
+            message(STATUS "${PROJECT_NAME}: Using system libavif")
             message(STATUS "libavif-${libavif_VERSION} found")
+            if(NOT SDL2IMAGE_AVIF_SHARED)
+                list(APPEND PC_REQUIRES libavif)
+            endif()
         else()
             message(STATUS "libavif-${LIBAVIF_MINIMUM_VERSION} or compatible not found")
-            message(FATAL_ERROR "libavif NOT found")
+            message(${fatal_error} "libavif NOT found")
         endif()
-        list(APPEND PC_REQUIRES libavif)
     endif()
-    if(SDL2IMAGE_AVIF_SHARED)
-        target_include_directories(SDL2_image PRIVATE
-            $<TARGET_PROPERTY:avif,INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:avif,INTERFACE_INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:avif,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-        )
-        target_get_dynamic_library(dynamic_avif avif)
-        message(STATUS "Dynamic libavif: ${dynamic_avif}")
-        target_compile_definitions(SDL2_image PRIVATE "LOAD_AVIF_DYNAMIC=\"${dynamic_avif}\"")
-        if(SDL2IMAGE_AVIF_VENDORED)
-            add_dependencies(SDL2_image avif)
+    if(SDL2IMAGE_AVIF_ENABLED)
+        target_compile_definitions(SDL2_image PRIVATE LOAD_AVIF)
+        if(SDL2IMAGE_AVIF_SHARED)
+            target_include_directories(SDL2_image PRIVATE
+                $<TARGET_PROPERTY:avif,INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:avif,INTERFACE_INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:avif,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+            )
+            target_get_dynamic_library(dynamic_avif avif)
+            message(STATUS "Dynamic libavif: ${dynamic_avif}")
+            target_compile_definitions(SDL2_image PRIVATE "LOAD_AVIF_DYNAMIC=\"${dynamic_avif}\"")
+            if(SDL2IMAGE_AVIF_VENDORED)
+                add_dependencies(SDL2_image avif)
+            endif()
+        else()
+            target_link_libraries(SDL2_image PRIVATE avif)
         endif()
-    else()
-        target_link_libraries(SDL2_image PRIVATE avif)
     endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS BMP)
+set(SDL2IMAGE_BMP_ENABLED FALSE)
 if(SDL2IMAGE_BMP)
+    set(SDL2IMAGE_BMP_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_BMP)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS GIF)
+set(SDL2IMAGE_GIF_ENABLED FALSE)
 if(SDL2IMAGE_GIF)
+    set(SDL2IMAGE_GIF_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_GIF)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS JPG)
+set(SDL2IMAGE_JPG_ENABLED FALSE)
 if(SDL2IMAGE_JPG)
-    target_compile_definitions(SDL2_image PRIVATE
-        LOAD_JPG
-        SDL_IMAGE_SAVE_JPG=$<BOOL:${SDL2IMAGE_JPG_SAVE}>
-    )
-    if(NOT SDL2IMAGE_BACKEND_STB AND NOT SDL2IMAGE_BACKEND_WIC AND NOT SDL2IMAGE_BACKEND_IMAGEIO)
+    if(SDL2IMAGE_BACKEND_STB OR SDL2IMAGE_BACKEND_WIC OR SDL2IMAGE_BACKEND_IMAGEIO)
+        set(SDL2IMAGE_JPG_ENABLED TRUE)
+    else()
         if(SDL2IMAGE_JPG_VENDORED)
+            set(SDL2IMAGE_JPG_ENABLED TRUE)
             message(STATUS "${PROJECT_NAME}: Using vendored libjpeg")
             sdl_check_project_in_subfolder(external/jpeg libjpeg SDL2IMAGE_VENDORED)
             set(BUILD_SHARED_LIBS ${SDL2IMAGE_JPG_SHARED})
@@ -462,31 +499,48 @@ if(SDL2IMAGE_JPG)
                 list(APPEND PC_LIBS -l$<TARGET_FILE_BASE_NAME:jpeg>)
             endif()
         else()
-            message(STATUS "${PROJECT_NAME}: Using system libjpeg")
-            find_package(JPEG REQUIRED)
-            list(APPEND PC_REQUIRES libjpeg)
+            find_package(JPEG ${required})
+            if(JPEG_FOUND)
+                set(SDL2IMAGE_JPG_ENABLED TRUE)
+                message(STATUS "${PROJECT_NAME}: Using system libjpeg")
+                if(NOT SDL2IMAGE_JPG_SHARED)
+                    list(APPEND PC_REQUIRES libjpeg)
+                endif()
+            else()
+                message(${fatal_error} "libjpeg NOT found")
+            endif()
         endif()
-        if(SDL2IMAGE_JPG_SHARED)
-            target_include_directories(SDL2_image PRIVATE
-                $<TARGET_PROPERTY:JPEG::JPEG,INCLUDE_DIRECTORIES>
-                $<TARGET_PROPERTY:JPEG::JPEG,INTERFACE_INCLUDE_DIRECTORIES>
-                $<TARGET_PROPERTY:JPEG::JPEG,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-            )
-            target_get_dynamic_library(dynamic_jpeg JPEG::JPEG)
-            message(STATUS "Dynamic libjpeg: ${dynamic_jpeg}")
-            target_compile_definitions(SDL2_image PRIVATE "LOAD_JPG_DYNAMIC=\"${dynamic_jpeg}\"")
-            if(SDL2IMAGE_JPG_VENDORED)
-                add_dependencies(SDL2_image JPEG::JPEG)
+        if(SDL2IMAGE_JPG_ENABLED)
+            if(SDL2IMAGE_JPG_SHARED)
+                target_include_directories(SDL2_image PRIVATE
+                    $<TARGET_PROPERTY:JPEG::JPEG,INCLUDE_DIRECTORIES>
+                    $<TARGET_PROPERTY:JPEG::JPEG,INTERFACE_INCLUDE_DIRECTORIES>
+                    $<TARGET_PROPERTY:JPEG::JPEG,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+                )
+                target_get_dynamic_library(dynamic_jpeg JPEG::JPEG)
+                message(STATUS "Dynamic libjpeg: ${dynamic_jpeg}")
+                target_compile_definitions(SDL2_image PRIVATE "LOAD_JPG_DYNAMIC=\"${dynamic_jpeg}\"")
+                if(SDL2IMAGE_JPG_VENDORED)
+                    add_dependencies(SDL2_image JPEG::JPEG)
+                endif()
+            else()
+                target_link_libraries(SDL2_image PRIVATE JPEG::JPEG)
             endif()
-        else()
-            target_link_libraries(SDL2_image PRIVATE JPEG::JPEG)
         endif()
     endif()
+    if(SDL2IMAGE_JPG_ENABLED)
+        target_compile_definitions(SDL2_image PRIVATE
+            LOAD_JPG
+            SDL_IMAGE_SAVE_JPG=$<BOOL:${SDL2IMAGE_JPG_SAVE}>
+        )
+    endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS JXL)
+set(SDL2IMAGE_JXL_ENABLED FALSE)
 if(SDL2IMAGE_JXL)
-    target_compile_definitions(SDL2_image PRIVATE LOAD_JXL)
     if(SDL2IMAGE_JXL_VENDORED)
+        set(SDL2IMAGE_JXL_ENABLED TRUE)
         enable_language(CXX)
         message(STATUS "${PROJECT_NAME}: Using vendored libjxl")
         # BUILD_TESTING variable is used by libjxl
@@ -523,42 +577,59 @@ if(SDL2IMAGE_JXL)
             add_library(libjxl::libjxl ALIAS ${jxl_lib})
         endif()
     else()
-        message(STATUS "${PROJECT_NAME}: Using system libjxl")
-        list(APPEND PC_REQUIRES libjxl)
-        find_package(libjxl REQUIRED)
+        find_package(libjxl ${required})
+        if(libjxl_FOUND)
+            set(SDL2IMAGE_JXL_ENABLED TRUE)
+            message(STATUS "${PROJECT_NAME}: Using system libjxl")
+            if(NOT SDL2IMAGE_JXL_SHARED)
+                list(APPEND PC_REQUIRES libjxl)
+            endif()
+        else()
+            message(${fatal_error} "libjxl NOT found")
+        endif()
     endif()
-    if(SDL2IMAGE_JXL_SHARED)
-        target_include_directories(SDL2_image PRIVATE
-            $<TARGET_PROPERTY:libjxl::libjxl,INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:libjxl::libjxl,INTERFACE_INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:libjxl::libjxl,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-        )
-        target_get_dynamic_library(dynamic_jxl libjxl::libjxl)
-        message(STATUS "Dynamic libjxl: ${dynamic_jxl}")
-        target_compile_definitions(SDL2_image PRIVATE "LOAD_JXL_DYNAMIC=\"${dynamic_jxl}\"")
-        if(SDL2IMAGE_JXL_VENDORED)
-            add_dependencies(SDL2_image libjxl::libjxl)
+    if(SDL2IMAGE_JXL_ENABLED)
+        target_compile_definitions(SDL2_image PRIVATE LOAD_JXL)
+        if(SDL2IMAGE_JXL_SHARED)
+            target_include_directories(SDL2_image PRIVATE
+                $<TARGET_PROPERTY:libjxl::libjxl,INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:libjxl::libjxl,INTERFACE_INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:libjxl::libjxl,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+            )
+            target_get_dynamic_library(dynamic_jxl libjxl::libjxl)
+            message(STATUS "Dynamic libjxl: ${dynamic_jxl}")
+            target_compile_definitions(SDL2_image PRIVATE "LOAD_JXL_DYNAMIC=\"${dynamic_jxl}\"")
+            if(SDL2IMAGE_JXL_VENDORED)
+                add_dependencies(SDL2_image libjxl::libjxl)
+            endif()
+        else()
+            target_link_libraries(SDL2_image PRIVATE libjxl::libjxl)
         endif()
-    else()
-        target_link_libraries(SDL2_image PRIVATE libjxl::libjxl)
     endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS LBM)
+set(SDL2IMAGE_LBM_ENABLED FALSE)
 if(SDL2IMAGE_LBM)
+    set(SDL2IMAGE_LBM_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_LBM)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS PCX)
+set(SDL2IMAGE_PCX_ENABLED FALSE)
 if(SDL2IMAGE_PCX)
+    set(SDL2IMAGE_PCX_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_PCX)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS PNG)
+set(SDL2IMAGE_PNG_ENABLED FALSE)
 if(SDL2IMAGE_PNG)
-    target_compile_definitions(SDL2_image PRIVATE
-        LOAD_PNG
-        SDL_IMAGE_SAVE_PNG=$<BOOL:${SDL2IMAGE_PNG_SAVE}>
-    )
-    if(NOT SDL2IMAGE_BACKEND_STB AND NOT SDL2IMAGE_BACKEND_WIC AND NOT SDL2IMAGE_BACKEND_IMAGEIO)
+    if(SDL2IMAGE_BACKEND_STB OR SDL2IMAGE_BACKEND_WIC OR SDL2IMAGE_BACKEND_IMAGEIO)
+        set(SDL2IMAGE_PNG_ENABLED TRUE)
+    else()
         if(SDL2IMAGE_PNG_VENDORED)
+            set(SDL2IMAGE_PNG_ENABLED TRUE)
             message(STATUS "${PROJECT_NAME}: Using vendored libpng")
             sdl_check_project_in_subfolder(external/libpng libpng SDL2IMAGE_VENDORED)
             add_subdirectory(external/libpng EXCLUDE_FROM_ALL)
@@ -581,47 +652,76 @@ if(SDL2IMAGE_PNG)
                 endif()
             endif()
         else()
-            message(STATUS "${PROJECT_NAME}: Using system libpng")
-            find_package(PNG REQUIRED)
-            list(APPEND PC_REQUIRES libpng)
+            find_package(PNG ${required})
+            if(PNG_FOUND)
+                set(SDL2IMAGE_PNG_ENABLED TRUE)
+                message(STATUS "${PROJECT_NAME}: Using system libpng")
+                if(NOT SDL2IMAGE_PNG_SHARED)
+                    list(APPEND PC_REQUIRES libpng)
+                endif()
+            else()
+                message(${FATAL_ERROR} "libpng NOT found")
+            endif()
         endif()
-        if(SDL2IMAGE_PNG_SHARED)
-            target_include_directories(SDL2_image PRIVATE
-                $<TARGET_PROPERTY:PNG::PNG,INCLUDE_DIRECTORIES>
-                $<TARGET_PROPERTY:PNG::PNG,INTERFACE_INCLUDE_DIRECTORIES>
-                $<TARGET_PROPERTY:PNG::PNG,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-            )
-            target_get_dynamic_library(dynamic_png PNG::PNG)
-            message(STATUS "Dynamic libpng: ${dynamic_png}")
-            target_compile_definitions(SDL2_image PRIVATE "LOAD_PNG_DYNAMIC=\"${dynamic_png}\"")
-            if(SDL2IMAGE_PNG_VENDORED)
-                add_dependencies(SDL2_image PNG::PNG)
+        if(SDL2IMAGE_PNG_ENABLED)
+            if(SDL2IMAGE_PNG_SHARED)
+                target_include_directories(SDL2_image PRIVATE
+                    $<TARGET_PROPERTY:PNG::PNG,INCLUDE_DIRECTORIES>
+                    $<TARGET_PROPERTY:PNG::PNG,INTERFACE_INCLUDE_DIRECTORIES>
+                    $<TARGET_PROPERTY:PNG::PNG,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+                )
+                target_get_dynamic_library(dynamic_png PNG::PNG)
+                message(STATUS "Dynamic libpng: ${dynamic_png}")
+                target_compile_definitions(SDL2_image PRIVATE "LOAD_PNG_DYNAMIC=\"${dynamic_png}\"")
+                if(SDL2IMAGE_PNG_VENDORED)
+                    add_dependencies(SDL2_image PNG::PNG)
+                endif()
+            else()
+                target_link_libraries(SDL2_image PRIVATE PNG::PNG)
             endif()
-        else()
-            target_link_libraries(SDL2_image PRIVATE PNG::PNG)
         endif()
     endif()
+    if(SDL2IMAGE_PNG_ENABLED)
+        target_compile_definitions(SDL2_image PRIVATE
+            LOAD_PNG
+            SDL_IMAGE_SAVE_PNG=$<BOOL:${SDL2IMAGE_PNG_SAVE}>
+        )
+    endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS PNM)
+set(SDL2IMAGE_PNM_ENABLED FALSE)
 if(SDL2IMAGE_PNM)
+    set(SDL2IMAGE_PNM_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_PNM)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS QOI)
+set(SDL2IMAGE_QOI_ENABLED FALSE)
 if(SDL2IMAGE_QOI)
+    set(SDL2IMAGE_QOI_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_QOI)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS SVG)
+set(SDL2IMAGE_SVG_ENABLED FALSE)
 if(SDL2IMAGE_SVG)
+    set(SDL2IMAGE_SVG_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_SVG)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS TGA)
+set(SDL2IMAGE_TGA_ENABLED FALSE)
 if(SDL2IMAGE_TGA)
+    set(SDL2IMAGE_TGA_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_TGA)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS TIF)
+set(SDL2IMAGE_TIF_ENABLED FALSE)
 if(SDL2IMAGE_TIF)
-    target_compile_definitions(SDL2_image PRIVATE LOAD_TIF)
     if(SDL2IMAGE_TIF_VENDORED)
+        set(SDL2IMAGE_TIF_ENABLED TRUE)
         message(STATUS "${PROJECT_NAME}: Using vendored libtiff")
         # jpeg variable is used by vendored libtiff
         set(jpeg OFF CACHE BOOL "libtiff: jpeg option" FORCE)
@@ -655,38 +755,50 @@ if(SDL2IMAGE_TIF)
             list(APPEND PC_LIBS -l$<TARGET_FILE_BASE_NAME:tiff>)
         endif()
     else()
-        message(STATUS "${PROJECT_NAME}: Using system libtiff")
-        find_package(TIFF REQUIRED)
-        if(TARGET TIFF::tiff)
-            # Introduced in CMake 3.28
-            # TIFF::TIFF still exists, but it is an INTERFACE library linking to TIFF::tiff (no ALIAS library)
-            set(SDL2IMAGE_TIF_TARGET "TIFF::tiff")
+        find_package(TIFF ${required})
+        if(TIFF_FOUND)
+            set(SDL2IMAGE_TIF_ENABLED TRUE)
+            message(STATUS "${PROJECT_NAME}: Using system libtiff")
+            if(NOT SDL2IMAGE_TIF_SHARED)
+                list(APPEND PC_REQUIRES libtiff-4)
+            endif()
+            if(TARGET TIFF::tiff)
+                # Introduced in CMake 3.28
+                # TIFF::TIFF still exists, but it is an INTERFACE library linking to TIFF::tiff (no ALIAS library)
+                set(SDL2IMAGE_TIF_TARGET "TIFF::tiff")
+            else()
+                set(SDL2IMAGE_TIF_TARGET "TIFF::TIFF")
+            endif()
         else()
-            set(SDL2IMAGE_TIF_TARGET "TIFF::TIFF")
+            message(${fatal_error} "libtiff NOT found")
         endif()
-        list(APPEND PC_REQUIRES libtiff-4)
     endif()
-    if(SDL2IMAGE_TIF_SHARED)
-        target_include_directories(SDL2_image PRIVATE
-            $<TARGET_PROPERTY:${SDL2IMAGE_TIF_TARGET},INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:${SDL2IMAGE_TIF_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:${SDL2IMAGE_TIF_TARGET},INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-        )
-        target_get_dynamic_library(dynamic_tif ${SDL2IMAGE_TIF_TARGET})
-        message(STATUS "Dynamic libtiff: ${dynamic_tif}")
-        target_compile_definitions(SDL2_image PRIVATE "LOAD_TIF_DYNAMIC=\"${dynamic_tif}\"")
-        if(SDL2IMAGE_TIF_VENDORED)
-            add_dependencies(SDL2_image ${SDL2IMAGE_TIF_TARGET})
+    if(SDL2IMAGE_TIF_ENABLED)
+        target_compile_definitions(SDL2_image PRIVATE LOAD_TIF)
+        if(SDL2IMAGE_TIF_SHARED)
+            target_include_directories(SDL2_image PRIVATE
+                $<TARGET_PROPERTY:${SDL2IMAGE_TIF_TARGET},INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:${SDL2IMAGE_TIF_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:${SDL2IMAGE_TIF_TARGET},INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+            )
+            target_get_dynamic_library(dynamic_tif ${SDL2IMAGE_TIF_TARGET})
+            message(STATUS "Dynamic libtiff: ${dynamic_tif}")
+            target_compile_definitions(SDL2_image PRIVATE "LOAD_TIF_DYNAMIC=\"${dynamic_tif}\"")
+            if(SDL2IMAGE_TIF_VENDORED)
+                add_dependencies(SDL2_image ${SDL2IMAGE_TIF_TARGET})
+            endif()
+        else()
+            target_link_libraries(SDL2_image PRIVATE ${SDL2IMAGE_TIF_TARGET})
         endif()
-    else()
-        target_link_libraries(SDL2_image PRIVATE ${SDL2IMAGE_TIF_TARGET})
     endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS WEBP)
+set(SDL2IMAGE_WEBP_ENABLED FALSE)
 if(SDL2IMAGE_WEBP)
-    target_compile_definitions(SDL2_image PRIVATE LOAD_WEBP)
     # missing cpufeatures
     if(SDL2IMAGE_WEBP_VENDORED)
+        set(SDL2IMAGE_WEBP_ENABLED TRUE)
         message(STATUS "${PROJECT_NAME}: Using vendored libwebp")
         sdl_check_project_in_subfolder(external/libwebp libwebp SDL2IMAGE_VENDORED)
         set(BUILD_SHARED_LIBS ${SDL2IMAGE_WEBP_SHARED})
@@ -698,42 +810,61 @@ if(SDL2IMAGE_WEBP)
         set_target_properties(webp PROPERTIES EXPORT_NAME "external_libwebp")
         add_library(SDL2_image::external_libwebp ALIAS webp)
     else()
-        message(STATUS "${PROJECT_NAME}: Using system libwebp")
-        find_package(webp REQUIRED)
-        list(APPEND PC_REQUIRES libwebp libwebpdemux)
+        find_package(webp ${required})
+        if(webp_FOUND)
+            set(SDL2IMAGE_WEBP_ENABLED TRUE)
+            message(STATUS "${PROJECT_NAME}: Using system libwebp")
+            if(NOT SDL2IMAGE_WEBP_SHARED)
+                list(APPEND PC_REQUIRES libwebp libwebpdemux)
+            endif()
+        else()
+            message(${fatal_error} "libwebp NOT found")
+        endif()
     endif()
-    if(SDL2IMAGE_WEBP_SHARED)
-        target_include_directories(SDL2_image PRIVATE
-            $<TARGET_PROPERTY:WebP::webp,INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:WebP::webp,INTERFACE_INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:WebP::webp,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:WebP::webpdemux,INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:WebP::webpdemux,INTERFACE_INCLUDE_DIRECTORIES>
-            $<TARGET_PROPERTY:WebP::webpdemux,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
-        )
-        target_get_dynamic_library(dynamic_webpdemux WebP::webpdemux)
-        message(STATUS "Dynamic libwebpdemux: ${dynamic_webpdemux}")
-        target_compile_definitions(SDL2_image PRIVATE "LOAD_WEBPDEMUX_DYNAMIC=\"${dynamic_webpdemux}\"")
-        target_get_dynamic_library(dynamic_webp WebP::webp)
-        message(STATUS "Dynamic libwebp: ${dynamic_webp}")
-        target_compile_definitions(SDL2_image PRIVATE "LOAD_WEBP_DYNAMIC=\"${dynamic_webp}\"")
-        if(SDL2IMAGE_WEBP_VENDORED)
-            add_dependencies(SDL2_image WebP::webp WebP::webpdemux)
+    if(SDL2IMAGE_WEBP_ENABLED)
+        target_compile_definitions(SDL2_image PRIVATE LOAD_WEBP)
+        if(SDL2IMAGE_WEBP_SHARED)
+            target_include_directories(SDL2_image PRIVATE
+                $<TARGET_PROPERTY:WebP::webp,INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:WebP::webp,INTERFACE_INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:WebP::webp,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:WebP::webpdemux,INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:WebP::webpdemux,INTERFACE_INCLUDE_DIRECTORIES>
+                $<TARGET_PROPERTY:WebP::webpdemux,INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>
+            )
+            target_get_dynamic_library(dynamic_webpdemux WebP::webpdemux)
+            message(STATUS "Dynamic libwebpdemux: ${dynamic_webpdemux}")
+            target_compile_definitions(SDL2_image PRIVATE "LOAD_WEBPDEMUX_DYNAMIC=\"${dynamic_webpdemux}\"")
+            target_get_dynamic_library(dynamic_webp WebP::webp)
+            message(STATUS "Dynamic libwebp: ${dynamic_webp}")
+            target_compile_definitions(SDL2_image PRIVATE "LOAD_WEBP_DYNAMIC=\"${dynamic_webp}\"")
+            if(SDL2IMAGE_WEBP_VENDORED)
+                add_dependencies(SDL2_image WebP::webp WebP::webpdemux)
+            endif()
+        else()
+            target_link_libraries(SDL2_image PRIVATE WebP::webp WebP::webpdemux)
         endif()
-    else()
-        target_link_libraries(SDL2_image PRIVATE WebP::webp WebP::webpdemux)
     endif()
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS XCF)
+set(SDL2IMAGE_XCF_ENABLED FALSE)
 if(SDL2IMAGE_XCF)
+    set(SDL2IMAGE_XCF_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_XCF)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS XPM)
+set(SDL2IMAGE_XPM_ENABLED FALSE)
 if(SDL2IMAGE_XPM)
+    set(SDL2IMAGE_XPM_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_XPM)
 endif()
 
+list(APPEND SDL2IMAGE_BACKENDS XV)
+set(SDL2IMAGE_XV_ENABLED FALSE)
 if(SDL2IMAGE_XV)
+    set(SDL2IMAGE_XV_ENABLED TRUE)
     target_compile_definitions(SDL2_image PRIVATE LOAD_XV)
 endif()
 
@@ -878,3 +1009,25 @@ if(SDL2IMAGE_TESTS)
     enable_testing()
     add_subdirectory(test)
 endif()
+
+
+set(available_deps)
+set(unavailable_deps)
+foreach(dep IN LISTS SDL2IMAGE_BACKENDS)
+    set(var SDL2IMAGE_${dep}_ENABLED)
+    if(NOT DEFINED ${var})
+        message(AUTHOR_WARNING "${var} not defined")
+    endif()
+    if(${var})
+        list(APPEND available_deps ${dep})
+    else()
+        list(APPEND unavailable_deps ${dep})
+    endif()
+endforeach()
+string(JOIN " " avail_str ${available_deps})
+string(TOLOWER "${avail_str}" avail_str)
+string(JOIN " " unavail_str ${unavailable_deps})
+string(TOLOWER "${unavail_str}" unavail_str)
+message(STATUS "SDL2_image backends:")
+message(STATUS "- enabled:  ${avail_str}")
+message(STATUS "- disabled: ${unavail_str}")
diff --git a/VisualC/SDL_image.sln b/VisualC/SDL_image.sln
index 0c7849ddf..763a00283 100644
--- a/VisualC/SDL_image.sln
+++ b/VisualC/SDL_image.sln
@@ -1,5 +1,4 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
+Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2010
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2_image", "SDL_image.vcxproj", "{2BD5534E-00E2-4BEA-AC96-D9A92EA24696}"
 EndProject
diff --git a/external/libtiff b/external/libtiff
index f0b67bbb5..5201ffee7 160000
--- a/external/libtiff
+++ b/external/libtiff
@@ -1 +1 @@
-Subproject commit f0b67bbb55584c7c48dd2e0a20823c3c3ed0dc75
+Subproject commit 5201ffee79beb91f38c57171bafe79c11271c01a
diff --git a/external/libwebp b/external/libwebp
index fa992316e..05b15cb85 160000
--- a/external/libwebp
+++ b/external/libwebp
@@ -1 +1 @@
-Subproject commit fa992316e4517b25a4e667a3668b930170becd56
+Subproject commit 05b15cb850e7bed3b4fed1d360873de352411659