GSoC Project Technical Details
This post serves as a supplement to my final report on my Google Summer of Code project.
The code changes I made are available for viewing on Gerrit (the code review software used by LibreOffice), and it is spread across 5 separate patchsets.
Adding libjxl and Dependencies to LibreOffice Build System
- https://gerrit.libreoffice.org/c/core/+/207706/14 (external: add highway)
- https://gerrit.libreoffice.org/c/core/+/208008/11 (external: add brotli)
- https://gerrit.libreoffice.org/c/core/+/207085/20 (external: add libjxl)
libjxl (https://github.com/libjxl/libjxl) was the library used to help
with the importing. highway and brotli were dependencies of
libjxl.
Building these libraries is mostly done with Makefile code in .mk files.
The main code for adding these libraries to the build system is in
external/{library}/ (where {library} is the respective name of the
library). The external/{library}/StaticLibrary_{library}.mk files contain
specific instructions for compiling the libraries. A lot of the rest of the
files added or changed are boilerplate necessary for the libraries to compile.
There are also some instructions in RepositoryExternal.mk related to
including these files in the build system.
libjxl in particular needed some flags set in
external/libjxl/StaticLibrary_libjxl.mk and RepositoryExternal.mk
in order to build properly. One of these flags was related to building some
JPEG related parts, which were not needed for this project, and the other flags
were important to make sure that the correct compiler directives were set for
Windows. On Windows, __declspec(dllexport) had to be set for some
functions rather than __declspec(dllimport), otherwise the compiler would
not allow the tagged functions to be defined. By defining
-DJXL_INTERNAL_LIBRARY_BUILD,
-DJXL_THREADS_INTERNAL_LIBRARY_BUILD, and -Djxl_cms_EXPORTS,
this ensured that the proper compiler directives were set on Windows.
Main Implementation
- https://gerrit.libreoffice.org/c/core/+/208352/8 (tdf#156931 add import support for JPEG XL image format)
A previous patch that added WebP support was used as a reference for the main implementation.
Most of the code in this patchset is boilerplate needed to add a new image file type.
The main code (and the code that interacts with the libjxl library)
is in vcl/source/filter/jxl/reader.cxx. Here, a stream of data is
progressively read and decoded. The read data is put into a bitmap and
finally a Graphic type. The ImportJxlGraphic function defined
here is what is used in other files to read JPEG XL files.
vcl/source/filter/graphicfilter.cxx and
vcl/source/filter/graphicfilter2.cxx also contain important code
related to importing.
vcl/source/filter/GraphicFormatDetector.cxx checks that some
metadata about the image being read is correct. (Specifically it
verifies that something called the magic number is correct).
vcl/workben/fftester.cxx has code for a simple program that
attempts to import an image as a particular type. This program is useful
for debugging. JPEG XL support was added here as well.
Automated Tests
- https://gerrit.libreoffice.org/c/core/+/208999/3 (tdf#156931 unit tests for importing JPEG XL images)
The patch that added WebP support was used as a reference for the tests as well.
The main tests added check that .jxl files are read correctly. The code for this is in vcl/qa/cppunit/graphicfilter/filters-jxl-test.cxx and
the sample images used in these tests are in
vcl/qa/cppunit/graphicfilter/data/jxl/. These tests are added to
the build system in vcl/CppunitTest_vcl_filters_test.mk.
There were also some tests for checking that .jxl files are detected
correctly (in vcl/qa/cppunit/GraphicFormatDetectorTest.cxx) and
that some properties of the image are read correctly (in
vcl/qa/cppunit/GraphicTest.cxx). These smaller tests use
vcl/qa/cppunit/data/TypeDetectionExample.jxl as the test image.
There was also a fuzzer added. The main code for it is in
vcl/workben/jxlfuzzer.cxx, while the instructions to actually
build the fuzzer are in vcl/Executable_jxlfuzzer.mk,
vcl/Module_vcl.mk, and Repository.mk.