LibGfx: Split image decoders into a separate library

Move the image loader sources and decoder-only dependencies from LibGfx
into a new LibImageDecoders library. This keeps the APNG-enabled PNG
loader out of processes that only need core graphics and image writers.

Link the ImageDecoder service, direct decoder tests, fuzzers, test-web,
and the image utility against LibImageDecoders where they still decode
images in-process.
This commit is contained in:
Andreas Kling 2026-06-10 11:05:16 +02:00 committed by Andreas Kling
parent 5ef34ecb7a
commit 37e7526367
10 changed files with 88 additions and 63 deletions

View file

@ -28,6 +28,7 @@ add_subdirectory(LibXML)
if (ENABLE_GUI_TARGETS) if (ENABLE_GUI_TARGETS)
add_subdirectory(LibDevTools) add_subdirectory(LibDevTools)
add_subdirectory(LibGfx) add_subdirectory(LibGfx)
add_subdirectory(LibImageDecoders)
add_subdirectory(LibImageDecoderClient) add_subdirectory(LibImageDecoderClient)
add_subdirectory(LibMedia) add_subdirectory(LibMedia)
add_subdirectory(LibWeb) add_subdirectory(LibWeb)

View file

@ -22,20 +22,9 @@ set(SOURCES
FontCascadeList.cpp FontCascadeList.cpp
GradientPainting.cpp GradientPainting.cpp
Matrix4x4.cpp Matrix4x4.cpp
ImageFormats/AVIFLoader.cpp
ImageFormats/BMPLoader.cpp
ImageFormats/BMPWriter.cpp ImageFormats/BMPWriter.cpp
ImageFormats/CCITTDecoder.cpp
ImageFormats/GIFLoader.cpp
ImageFormats/ICOLoader.cpp
ImageFormats/ImageDecoder.cpp
ImageFormats/JPEGLoader.cpp
ImageFormats/JPEGWriter.cpp ImageFormats/JPEGWriter.cpp
ImageFormats/JPEGXLLoader.cpp
ImageFormats/PNGLoader.cpp
ImageFormats/PNGWriter.cpp ImageFormats/PNGWriter.cpp
ImageFormats/TIFFLoader.cpp
ImageFormats/WebPLoader.cpp
ImageFormats/WebPSharedLossless.cpp ImageFormats/WebPSharedLossless.cpp
ImageFormats/WebPWriter.cpp ImageFormats/WebPWriter.cpp
ImageFormats/WebPWriterLossless.cpp ImageFormats/WebPWriterLossless.cpp
@ -79,31 +68,7 @@ ladybird_lib(LibGfx gfx)
target_link_libraries(LibGfx PRIVATE LibCompress LibCore LibCrypto LibFileSystem LibTextCodec LibIPC LibSync LibUnicode) target_link_libraries(LibGfx PRIVATE LibCompress LibCore LibCrypto LibFileSystem LibTextCodec LibIPC LibSync LibUnicode)
set(generated_sources TIFFMetadata.h TIFFTagHandler.cpp) target_link_libraries(LibGfx PRIVATE PkgConfig::WOFF2 JPEG::JPEG PNG::PNG skia harfbuzz)
list(TRANSFORM generated_sources PREPEND "ImageFormats/")
add_custom_command(
OUTPUT ${generated_sources}
COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/TIFFGenerator.py" -o "${CMAKE_CURRENT_BINARY_DIR}/ImageFormats"
DEPENDS "TIFFGenerator.py"
VERBATIM
)
target_sources(LibGfx PRIVATE ${generated_sources})
add_custom_target(generate_tiff_files_handler DEPENDS ${generated_sources})
add_dependencies(ladybird_codegen_accumulator generate_tiff_files_handler)
add_dependencies(LibGfx generate_tiff_files_handler)
set(generated_headers ${generated_sources})
list(FILTER generated_headers INCLUDE REGEX "\\.h$")
list(TRANSFORM generated_headers PREPEND "${CMAKE_CURRENT_BINARY_DIR}/")
if (ENABLE_INSTALL_HEADERS)
list(TRANSFORM generated_sources PREPEND "${CMAKE_CURRENT_BINARY_DIR}/")
install(FILES ${generated_sources} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/LibGfx/ImageFormats")
endif()
target_link_libraries(LibGfx PRIVATE PkgConfig::WOFF2 JPEG::JPEG PNG::PNG avif WebP::webp WebP::webpdecoder
WebP::webpdemux WebP::libwebpmux skia harfbuzz)
import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libgfx_rust FFI_HEADER RustFFI.h) import_rust_crate(MANIFEST_PATH Rust/Cargo.toml CRATE_NAME libgfx_rust FFI_HEADER RustFFI.h)
target_link_libraries(LibGfx PRIVATE libgfx_rust) target_link_libraries(LibGfx PRIVATE libgfx_rust)
@ -112,20 +77,6 @@ if (HAS_FONTCONFIG)
target_link_libraries(LibGfx PRIVATE Fontconfig::Fontconfig) target_link_libraries(LibGfx PRIVATE Fontconfig::Fontconfig)
endif() endif()
set(CMAKE_REQUIRED_LIBRARIES PNG::PNG)
check_c_source_compiles([=[
#include <png.h>
#if !defined(PNG_APNG_SUPPORTED) || !defined(PNG_READ_APNG_SUPPORTED) || !defined(PNG_READ_APNG_SUPPORTED)
#error "APNG support is required"
#endif
int main() {}
]=] LIBPNG_HAS_APNG)
unset(CMAKE_REQUIRED_LIBRARIES)
if (NOT LIBPNG_HAS_APNG)
message(FATAL_ERROR "libpng does not support APNG, which is required by LibGfx.")
endif()
if (NOT ANDROID) if (NOT ANDROID)
# FIXME: Build vcpkg libraries with clang-cl so they can also build in sanitize. # FIXME: Build vcpkg libraries with clang-cl so they can also build in sanitize.
# https://github.com/LadybirdBrowser/ladybird/issues/5224 # https://github.com/LadybirdBrowser/ladybird/issues/5224
@ -134,9 +85,6 @@ if (NOT ANDROID)
# alone causes transitive issues in other TUs that depend on it # alone causes transitive issues in other TUs that depend on it
target_compile_options(LibGfx PRIVATE -fno-sanitize=address) target_compile_options(LibGfx PRIVATE -fno-sanitize=address)
endif() endif()
target_link_libraries(LibGfx PRIVATE PkgConfig::Jxl)
else()
target_link_libraries(LibGfx PRIVATE libjxl::libjxl hwy::hwy)
endif() endif()
if (APPLE) if (APPLE)

View file

@ -0,0 +1,74 @@
set(LIBGFX_IMAGE_FORMATS_DIR "${LADYBIRD_SOURCE_DIR}/Libraries/LibGfx/ImageFormats")
set(SOURCES
${LIBGFX_IMAGE_FORMATS_DIR}/AVIFLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/BMPLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/CCITTDecoder.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/GIFLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/ICOLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/ImageDecoder.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/JPEGLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/JPEGXLLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/PNGLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/TIFFLoader.cpp
${LIBGFX_IMAGE_FORMATS_DIR}/WebPLoader.cpp
)
ladybird_lib(LibImageDecoders imagedecoders)
target_link_libraries(LibImageDecoders PRIVATE
LibCompress
LibCore
LibCrypto
LibFileSystem
LibGfx
LibIPC
LibSync
LibTextCodec
LibUnicode
JPEG::JPEG
PNG::PNG
WebP::webp
WebP::webpdecoder
WebP::webpdemux
WebP::libwebpmux
avif
)
set(generated_sources TIFFMetadata.h TIFFTagHandler.cpp)
list(TRANSFORM generated_sources PREPEND "${CMAKE_BINARY_DIR}/Libraries/LibGfx/ImageFormats/")
add_custom_command(
OUTPUT ${generated_sources}
COMMAND ${Python3_EXECUTABLE} "${LADYBIRD_SOURCE_DIR}/Libraries/LibGfx/TIFFGenerator.py" -o "${CMAKE_BINARY_DIR}/Libraries/LibGfx/ImageFormats"
DEPENDS "${LADYBIRD_SOURCE_DIR}/Libraries/LibGfx/TIFFGenerator.py"
VERBATIM
)
target_sources(LibImageDecoders PRIVATE ${generated_sources})
add_custom_target(generate_tiff_files_handler DEPENDS ${generated_sources})
add_dependencies(ladybird_codegen_accumulator generate_tiff_files_handler)
add_dependencies(LibImageDecoders generate_tiff_files_handler)
if (ENABLE_INSTALL_HEADERS)
install(FILES ${generated_sources} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/LibGfx/ImageFormats")
endif()
set(CMAKE_REQUIRED_LIBRARIES PNG::PNG)
check_c_source_compiles([=[
#include <png.h>
#if !defined(PNG_APNG_SUPPORTED) || !defined(PNG_READ_APNG_SUPPORTED) || !defined(PNG_READ_APNG_SUPPORTED)
#error "APNG support is required"
#endif
int main() {}
]=] LIBPNG_HAS_APNG)
unset(CMAKE_REQUIRED_LIBRARIES)
if (NOT LIBPNG_HAS_APNG)
message(FATAL_ERROR "libpng does not support APNG, which is required by LibImageDecoders.")
endif()
if (NOT ANDROID)
target_link_libraries(LibImageDecoders PRIVATE PkgConfig::Jxl)
else()
target_link_libraries(LibImageDecoders PRIVATE libjxl::libjxl hwy::hwy)
endif()

View file

@ -13,7 +13,6 @@
#include <AK/Utf16FlyString.h> #include <AK/Utf16FlyString.h>
#include <LibCore/Promise.h> #include <LibCore/Promise.h>
#include <LibCore/Resource.h> #include <LibCore/Resource.h>
#include <LibGfx/ImageFormats/ImageDecoder.h>
#include <LibJS/Runtime/NativeFunction.h> #include <LibJS/Runtime/NativeFunction.h>
#include <LibTextCodec/Decoder.h> #include <LibTextCodec/Decoder.h>
#include <LibURL/URL.h> #include <LibURL/URL.h>

View file

@ -6,7 +6,6 @@
*/ */
#include <LibGfx/Bitmap.h> #include <LibGfx/Bitmap.h>
#include <LibGfx/ImageFormats/ImageDecoder.h>
#include <LibImageDecoderClient/Client.h> #include <LibImageDecoderClient/Client.h>
#include <LibWebView/Plugins/ImageCodecPlugin.h> #include <LibWebView/Plugins/ImageCodecPlugin.h>
#include <LibWebView/Utilities.h> #include <LibWebView/Utilities.h>

View file

@ -24,20 +24,20 @@ if (TARGET LibWeb)
endif() endif()
set(FUZZER_DEPENDENCIES_ASN1 LibCrypto LibTLS) set(FUZZER_DEPENDENCIES_ASN1 LibCrypto LibTLS)
set(FUZZER_DEPENDENCIES_BMPLoader LibGfx) set(FUZZER_DEPENDENCIES_BMPLoader LibGfx LibImageDecoders)
set(FUZZER_DEPENDENCIES_CSSParser LibWeb) set(FUZZER_DEPENDENCIES_CSSParser LibWeb)
set(FUZZER_DEPENDENCIES_ELF LibELF) set(FUZZER_DEPENDENCIES_ELF LibELF)
set(FUZZER_DEPENDENCIES_GIFLoader LibGfx) set(FUZZER_DEPENDENCIES_GIFLoader LibGfx LibImageDecoders)
set(FUZZER_DEPENDENCIES_ICOLoader LibGfx) set(FUZZER_DEPENDENCIES_ICOLoader LibGfx LibImageDecoders)
set(FUZZER_DEPENDENCIES_Js LibJS LibGC) set(FUZZER_DEPENDENCIES_Js LibJS LibGC)
set(FUZZER_DEPENDENCIES_MatroskaReader LibMedia) set(FUZZER_DEPENDENCIES_MatroskaReader LibMedia)
set(FUZZER_DEPENDENCIES_PEM LibCrypto) set(FUZZER_DEPENDENCIES_PEM LibCrypto)
set(FUZZER_DEPENDENCIES_PNGLoader LibGfx) set(FUZZER_DEPENDENCIES_PNGLoader LibGfx LibImageDecoders)
set(FUZZER_DEPENDENCIES_Poly1305 LibCrypto) set(FUZZER_DEPENDENCIES_Poly1305 LibCrypto)
set(FUZZER_DEPENDENCIES_RegexECMA262 LibRegex) set(FUZZER_DEPENDENCIES_RegexECMA262 LibRegex)
set(FUZZER_DEPENDENCIES_RSAKeyParsing LibCrypto) set(FUZZER_DEPENDENCIES_RSAKeyParsing LibCrypto)
set(FUZZER_DEPENDENCIES_TextDecoder LibTextCodec) set(FUZZER_DEPENDENCIES_TextDecoder LibTextCodec)
set(FUZZER_DEPENDENCIES_TIFFLoader LibGfx) set(FUZZER_DEPENDENCIES_TIFFLoader LibGfx LibImageDecoders)
set(FUZZER_DEPENDENCIES_TTF LibGfx) set(FUZZER_DEPENDENCIES_TTF LibGfx)
set(FUZZER_DEPENDENCIES_URL LibURL) set(FUZZER_DEPENDENCIES_URL LibURL)
set(FUZZER_DEPENDENCIES_WasmParser LibWasm) set(FUZZER_DEPENDENCIES_WasmParser LibWasm)

View file

@ -32,7 +32,7 @@ target_include_directories(imagedecoderservice PRIVATE ${CMAKE_CURRENT_BINARY_DI
target_include_directories(imagedecoderservice PRIVATE ${LADYBIRD_SOURCE_DIR}/Services/) target_include_directories(imagedecoderservice PRIVATE ${LADYBIRD_SOURCE_DIR}/Services/)
target_link_libraries(ImageDecoder PRIVATE imagedecoderservice LibCore LibMain LibSandbox LibThreading) target_link_libraries(ImageDecoder PRIVATE imagedecoderservice LibCore LibMain LibSandbox LibThreading)
target_link_libraries(imagedecoderservice PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain LibSync LibThreading) target_link_libraries(imagedecoderservice PRIVATE LibCore LibGfx LibImageDecoders LibIPC LibImageDecoderClient LibMain LibSync LibThreading)
if (WIN32) if (WIN32)
ladybird_windows_bin(ImageDecoder CONSOLE) ladybird_windows_bin(ImageDecoder CONSOLE)

View file

@ -14,4 +14,8 @@ foreach(source IN LISTS TEST_SOURCES)
ladybird_test("${source}" LibGfx LIBS LibGfx) ladybird_test("${source}" LibGfx LIBS LibGfx)
endforeach() endforeach()
target_link_libraries(BenchmarkJPEGLoader PRIVATE LibImageDecoders)
target_link_libraries(TestImageDecoder PRIVATE LibImageDecoders)
target_link_libraries(TestImageWriter PRIVATE LibImageDecoders)
ladybird_test(TestYUVData.cpp LibGfx LIBS LibGfx skia) ladybird_test(TestYUVData.cpp LibGfx LIBS LibGfx skia)

View file

@ -12,7 +12,7 @@ set(SOURCES
add_executable(test-web ${SOURCES}) add_executable(test-web ${SOURCES})
add_dependencies(test-web ladybird_build_resource_files ${ladybird_helper_processes}) add_dependencies(test-web ladybird_build_resource_files ${ladybird_helper_processes})
target_link_libraries(test-web PRIVATE AK LibCore LibDiff LibFileSystem LibGfx LibImageDecoderClient LibIPC LibJS LibMain LibRequests LibURL LibWeb LibWebView) target_link_libraries(test-web PRIVATE AK LibCore LibDiff LibFileSystem LibGfx LibImageDecoders LibImageDecoderClient LibIPC LibJS LibMain LibRequests LibURL LibWeb LibWebView)
if (APPLE) if (APPLE)
target_compile_definitions(test-web PRIVATE LADYBIRD_BINARY_PATH="$<TARGET_FILE_DIR:ladybird>") target_compile_definitions(test-web PRIVATE LADYBIRD_BINARY_PATH="$<TARGET_FILE_DIR:ladybird>")

View file

@ -9,7 +9,7 @@ ladybird_utility(xml SOURCES xml.cpp LIBS LibFileSystem LibMain LibXML LibURL)
ladybird_utility(dns SOURCES dns.cpp LIBS LibDNS LibMain LibTLS LibCrypto) ladybird_utility(dns SOURCES dns.cpp LIBS LibDNS LibMain LibTLS LibCrypto)
if (ENABLE_GUI_TARGETS) if (ENABLE_GUI_TARGETS)
ladybird_utility(image SOURCES image.cpp LIBS LibGfx LibMain) ladybird_utility(image SOURCES image.cpp LIBS LibGfx LibImageDecoders LibMain)
endif() endif()
# FIXME: Increase support for building targets on Windows # FIXME: Increase support for building targets on Windows