Issue #1769 - Part 1: Add vendored libjxl and highway sources.

Used old-configure to add the build option for enabling JPEG-XL support.
Highway version: 1.0.2
libjxl version: 0.7.0
This commit is contained in:
Job Bautista 2022-06-19 15:34:18 +08:00 committed by roytam1
commit 7983f5d8ba
953 changed files with 231544 additions and 0 deletions

View file

@ -0,0 +1,4 @@
BasedOnStyle: Google
IncludeCategories:
- Regex: '^<hwy/'
Priority: 2

View file

@ -0,0 +1,70 @@
# Disabled checks:
# - google-readability-todo: We don't use the google TODO format.
#
# - modernize-deprecated-headers: We don't use std:: versions of the standard
# types and functions like size_t or printf, so we should include <stdio.h>
# instead <cstdio>.
# - modernize-return-braced-init-list: this often doesn't improve readability.
# - modernize-use-auto: is too aggressive towards using auto.
# - modernize-use-default-member-init: with a mix of constructors and default
# member initialization this can be confusing if enforced.
# - modernize-use-trailing-return-type: does not improve readability when used
# systematically.
# - modernize-use-using: typedefs are ok.
#
# - readability-else-after-return: It doesn't always improve readability.
# - readability-static-accessed-through-instance
# It is often more useful and readable to access a constant of a passed
# variable (like d.N) instead of using the type of the variable that could be
# long and complex.
# - readability-uppercase-literal-suffix: we write 1.0f, not 1.0F.
Checks: >-
bugprone-*,
clang-*,
-clang-diagnostic-unused-command-line-argument,
google-*,
modernize-*,
performance-*,
readability-*,
-google-readability-todo,
-modernize-deprecated-headers,
-modernize-return-braced-init-list,
-modernize-use-auto,
-modernize-use-default-member-init,
-modernize-use-trailing-return-type,
-modernize-use-using,
-readability-else-after-return,
-readability-function-cognitive-complexity,
-readability-static-accessed-through-instance,
-readability-uppercase-literal-suffix,
WarningsAsErrors: >-
bugprone-argument-comment,
bugprone-macro-parentheses,
bugprone-suspicious-string-compare,
bugprone-use-after-move,
clang-*,
clang-analyzer-*,
-clang-diagnostic-unused-command-line-argument,
google-build-using-namespace,
google-explicit-constructor,
google-readability-braces-around-statements,
google-readability-namespace-comments,
modernize-use-override,
readability-inconsistent-declaration-parameter-name
# We are only interested in the headers from this projects, excluding
# third_party/ and build/.
HeaderFilterRegex: '^.*/(lib|tools)/.*\.h$'
CheckOptions:
- key: readability-braces-around-statements.ShortStatementLines
value: '2'
- key: google-readability-braces-around-statements.ShortStatementLines
value: '2'
- key: readability-implicit-bool-conversion.AllowPointerConditions
value: '1'
- key: readability-implicit-bool-conversion.AllowIntegerConditions
value: '1'

17
media/libjxl/src/.gitignore vendored Normal file
View file

@ -0,0 +1,17 @@
# Build output directories
/build
/build*
/docker/*.log
# The downloaded corpora files for benchmark.
/third_party/corpora
# hdrvdp source code
third_party/hdrvdp-2.2.2
third_party/hdrvdp-2.2.2.zip
third_party/hdrvdp-2.2.2.zip.tmp
# Output plots
tools/benchmark/metrics/plots
tools/benchmark/metrics/results.csv
tools/conformance/__pycache__

27
media/libjxl/src/.gitmodules vendored Normal file
View file

@ -0,0 +1,27 @@
[submodule "third_party/brotli"]
path = third_party/brotli
url = https://github.com/google/brotli
[submodule "third_party/lcms"]
path = third_party/lcms
url = https://github.com/mm2/Little-CMS
[submodule "third_party/googletest"]
path = third_party/googletest
url = https://github.com/google/googletest
[submodule "third_party/sjpeg"]
path = third_party/sjpeg
url = https://github.com/webmproject/sjpeg.git
[submodule "third_party/skcms"]
path = third_party/skcms
url = https://skia.googlesource.com/skcms
[submodule "third_party/highway"]
path = third_party/highway
url = https://github.com/google/highway
[submodule "third_party/libpng"]
path = third_party/libpng
url = https://github.com/glennrp/libpng.git
[submodule "third_party/zlib"]
path = third_party/zlib
url = https://github.com/madler/zlib.git
[submodule "third_party/testdata"]
path = testdata
url = https://github.com/libjxl/testdata

View file

@ -0,0 +1,17 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
#
# readthedocs.io configuration file. See:
# https://docs.readthedocs.io/en/stable/config-file/v2.html
version: 2
sphinx:
configuration: doc/sphinx/conf.py
python:
version: "3.7"
install:
- requirements: doc/sphinx/requirements.txt

54
media/libjxl/src/AUTHORS Normal file
View file

@ -0,0 +1,54 @@
# List of the project authors for copyright purposes. When contributing to the
# project add your name or your organization's name to this list. See
# CONTRIBUTING.md for details.
#
# For organizations:
# Organization <email pattern: *@domain>
#
# For individuals:
# Name <email address>
#
# Please keep each list sorted. If you wish to change your email address please
# send a pull request.
# Organizations:
Cloudinary Ltd. <*@cloudinary.com>
Google LLC <*@google.com>
# Individuals:
Alex Xu (Hello71) <alex_y_xu@yahoo.ca>
Alexander Sago <cagelight@gmail.com>
Andrius Lukas Narbutas <andrius4669@gmail.com>
Aous Naman <aous@unsw.edu.au>
Artem Selishchev
Biswapriyo Nath <nathbappai@gmail.com>
CanadianBaconBoi <beamconnor@gmail.com>
Daniel Novomeský <dnovomesky@gmail.com>
David Burnett <vargolsoft@gmail.com>
Dirk Lemstra <dirk@lemstra.org>
Don Olmstead <don.j.olmstead@gmail.com>
Even Rouault <even.rouault@spatialys.com>
Heiko Becker <heirecka@exherbo.org>
Jon Sneyers <jon@cloudinary.com>
Kai Hollberg <Schweinepriester@users.noreply.github.com>
Kleis Auke Wolthuizen <github@kleisauke.nl>
L. E. Segovia
Leo Izen <leo.izen@gmail.com>
Lovell Fuller
Maarten DB <anonymous.maarten@gmail.com>
Marcin Konicki <ahwayakchih@gmail.com>
Martin Strunz
Mathieu Malaterre <mathieu.malaterre@gmail.com>
Mikk Leini <mikk.leini@krakul.eu>
Misaki Kasumi <misakikasumi@outlook.com>
Petr Diblík
Pieter Wuille
roland-rollo
Samuel Leong <wvvwvvvvwvvw@gmail.com>
Sandro <sandro.jaeckel@gmail.com>
Stephan T. Lavavej <stl@nuwen.net>
Thomas Bonfort <thomas.bonfort@airbus.com>
Vincent Torri <vincent.torri@gmail.com>
xiota
Yonatan Nebenzhal <yonatan.nebenzhl@gmail.com>
Ziemowit Zabawa <ziemek.zabawa@outlook.com>

View file

@ -0,0 +1,261 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
## [0.7] - 2022-07-21
### Added
- Export version information in headers.
- decoder API: Ability to decode the content of metadata boxes:
`JXL_DEC_BOX`, `JXL_DEC_BOX_NEED_MORE_OUTPUT`, `JxlDecoderSetBoxBuffer`,
`JxlDecoderGetBoxType`, `JxlDecoderGetBoxSizeRaw` and
`JxlDecoderSetDecompressBoxes`.
- decoder API: ability to mark the input is finished: `JxlDecoderCloseInput`.
- decoder API: ability to request updates on different progressive events using
`JxlDecoderSetProgressiveDetail`; currently supported events are
`kDC`, `kLastPasses` and `kPasses`.
- decoder API: ability to specify desired intensity target using
`JxlDecoderSetDesiredIntensityTarget`
- decoder API: new function `JxlDecoderSetCoalesced` to allow decoding
non-coalesced (unblended) frames, e.g. layers of a composite still image
or the cropped frames of a recompressed GIF/APNG.
- decoder API: new function `JxlDecoderSetUnpremultiplyAlpha` to set
preference for getting an associated alpha channel with premultiplied or
unpremultiplied colors.
- decoder API: field added to `JxlFrameHeader`: a `JxlLayerInfo` struct
that contains crop dimensions and offsets and blending information for
the non-coalesced case.
- decoder API: new function `JxlDecoderGetExtraChannelBlendInfo` to get
the blending information for extra channels in the non-coalesced case.
- decoder API: new function `JxlDecoderSetMultithreadedImageOutCallback`,
allowing output callbacks to receive more information about the number of
threads on which they are running.
- decoder API: new function `JxlDecoderSkipCurrentFrame` to skip processing
the current frame after a progressive detail is reached.
- decoder API: new function `JxlDecoderGetIntendedDownsamplingRatio` to get
the intended downsampling ratio of progressive steps, based on the
information in the frame header.
- decoder API: new function `JxlDecoderSetRenderSpotcolors` to allow disabling
rendering of spot colors.
- decoder/encoder API: add two fields to `JXLBasicInfo`: `intrinsic_xsize`
and `intrinsic_ysize` to signal the intrinsic size.
- encoder API: ability to add metadata boxes, added new functions
`JxlEncoderAddBox`, `JxlEncoderUseBoxes`, `JxlEncoderCloseBoxes` and
`JxlEncoderCloseFrames`.
- encoder API: added ability to set several encoder options / extra fields to
frames using `JxlEncoderSetFrameName`, `JxlEncoderFrameSettingsSetOption`,
`JxlEncoderFrameSettingsSetFloatOption`.
- encoder API: added ability to check required codestream compatibility level
and force specified using `JxlEncoderGetRequiredCodestreamLevel` and
`JxlEncoderSetCodestreamLevel`.
- encoder API: added ability to force emitting box-based container format
using `JxlEncoderUseContainer`.
- encoder API: added ability to store JPEG metadata for lossless reconstruction
using `JxlEncoderStoreJPEGMetadata`
- encoder API: new functions `JxlEncoderSetFrameHeader` and
`JxlEncoderSetExtraChannelBlendInfo` to set animation
and blending parameters of the frame, and `JxlEncoderInitFrameHeader` and
`JxlEncoderInitBlendInfo` to initialize the structs to set.
- encoder API: ability to encode arbitrary extra channels:
`JxlEncoderInitExtraChannelInfo`, `JxlEncoderSetExtraChannelInfo`,
`JxlEncoderSetExtraChannelName` and `JxlEncoderSetExtraChannelBuffer`.
- encoder API: ability to plug custom CMS implementation using
`JxlEncoderSetCms(JxlEncoder* enc, JxlCmsInterface cms)`
- encoder API: added `JxlEncoderGetError` to retrieve last encoder error.
### Changed
- decoder API: using `JxlDecoderCloseInput` at the end of all input is required
when using JXL_DEC_BOX, and is now also encouraged in other cases, but not
required in those other cases for backwards compatibility.
- encoder API: `JxlEncoderCloseInput` now closes both frames and boxes input.
- CLI: `cjxl` and `djxl` have been reimplemented on the base of public decoder
and encoder API; dropped dependency on `gflags` for argument parsing.
### Deprecated
- decoder API: `JXL_DEC_EXTENSIONS` event: use `JXL_DEC_BASIC_INFO`
- decoder / encoder API: pixel types `JXL_TYPE_BOOLEAN` and `JXL_TYPE_UINT32`:
consider using `JXL_TYPE_UINT8` and `JXL_TYPE_FLOAT` correspondingly.
- decoder API: pixel format parameter for `JxlDecoderGetColorAsEncodedProfile`
and `JxlDecoderGetICCProfileSize`: pass `NULL`.
- decoder API: `JxlDecoderDefaultPixelFormat`
- encoder API: `JxlEncoderOptions`: use `JxlEncoderFrameSettings` instead.
- encoder API: `JxlEncoderOptionsCreate`: use `JxlEncoderFrameSettingsCreate`
instead.
- encoder API: `JxlEncoderOptionsSetDistance`: use `JxlEncoderSetFrameDistance`
instead.
- encoder API: `JxlEncoderOptionsSetLossless`: use `JxlEncoderSetFrameLossless`
instead.
- encoder API: `JxlEncoderOptionsSetEffort`: use
`JxlEncoderFrameSettingsSetOption(frame_settings, JXL_ENC_FRAME_SETTING_EFFORT, effort)`
instead.
- encoder API: `JxlEncoderOptionsSetDecodingSpeed`: use
`JxlEncoderFrameSettingsSetOption(frame_settings, JXL_ENC_FRAME_SETTING_DECODING_SPEED, tier)`
instead.
- encoder API: deprecated `JXL_ENC_NOT_SUPPORTED`, the encoder returns
`JXL_ENC_ERROR` instead and there is no need to handle
`JXL_ENC_NOT_SUPPORTED`.
## [0.6.1] - 2021-10-29
### Changed
- Security: Fix OOB read in splines rendering (#735 -
[CVE-2021-22563](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-22563))
- Security: Fix OOB copy (read/write) in out-of-order/multi-threaded decoding
(#708 - [CVE-2021-22564](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-22564))
- Fix segfault in `djxl` tool with `--allow_partial_files` flag (#781).
- Fix border in extra channels when using upsampling (#796)
## [0.6] - 2021-10-04
### Added
- API: New functions to decode extra channels:
`JxlDecoderExtraChannelBufferSize` and `JxlDecoderSetExtraChannelBuffer`.
- API: New function `JxlEncoderInitBasicInfo` to initialize `JxlBasicInfo`
(only needed when encoding). NOTE: it is now required to call this function
when using the encoder. Padding was added to the struct for forward
compatibility.
- API: Support for encoding oriented images.
- API: FLOAT16 support in the encoder API.
- Rewrite of the GDK pixbuf loader plugin. Added proper color management and
animation support.
- Rewrite of GIMP plugin. Added compression parameters dialog and switched to
using the public C API.
- Debian packages for GDK pixbuf loader (`libjxl-gdk-pixbuf`) and GIMP
(`libjxl-gimp-plugin`) plugins.
- `cjxl`/`djxl` support for `stdin` and `stdout`.
### Changed
- API: Renamed the field `alpha_associated` in `JxlExtraChannelInfo` to
`alpha_premultiplied`, to match the corresponding name in `JxlBasicInfo`.
- Improved the 2x2 downscaling method in the encoder for the optional color
channel resampling for low bit rates.
- Fixed: the combination of floating point original data, XYB color encoding,
and Modular mode was broken (in both encoder and decoder). It now works.
NOTE: this can cause the current encoder to write jxl bitstreams that do
not decode with the old decoder. In particular this will happen when using
cjxl with PFM, EXR, or floating point PSD input, and a combination of XYB
and modular mode is used (which caused an encoder error before), e.g.
using options like `-m -q 80` (lossy modular), `-d 4.5` or `--progressive_dc=1`
(modular DC frame), or default lossy encoding on an image where patches
end up being used. There is no problem when using cjxl with PNG, JPEG, GIF,
APNG, PPM, PGM, PGX, or integer (8-bit or 16-bit) PSD input.
- `libjxl` static library now bundles skcms, fixing static linking in
downstream projects when skcms is used.
- Spline rendering performance improvements.
- Butteraugli changes for less visual masking.
## [0.5] - 2021-08-02
### Added
- API: New function to decode the image using a callback outputting a part of a
row per call.
- API: 16-bit float output support.
- API: `JxlDecoderRewind` and `JxlDecoderSkipFrames` functions to skip more
efficiently to earlier animation frames.
- API: `JxlDecoderSetPreferredColorProfile` function to choose color profile in
certain circumstances.
- encoder: Adding `center_x` and `center_y` flags for more control of the tile
order.
- New encoder speeds `lightning` (1) and `thunder` (2).
### Changed
- Re-licensed the project under a BSD 3-Clause license. See the
[LICENSE](LICENSE) and [PATENTS](PATENTS) files for details.
- Full JPEG XL part 1 specification support: Implemented all the spec required
to decode files to pixels, including cases that are not used by the encoder
yet. Part 2 of the spec (container format) is final but not fully implemented
here.
- Butteraugli metric improvements. Exact numbers are different from previous
versions.
- Memory reductions during decoding.
- Reduce the size of the jxl_dec library by removing dependencies.
- A few encoding speedups.
- Clarify the security policy.
- Significant encoding improvements (~5 %) and less ringing.
- Butteraugli metric to have some less masking.
- `cjxl` flag `--speed` is deprecated and replaced by the `--effort` synonym.
### Removed
- API for returning a downsampled DC was deprecated
(`JxlDecoderDCOutBufferSize` and `JxlDecoderSetDCOutBuffer`) and will be
removed in the next release.
## [0.3.7] - 2021-03-29
### Changed
- Fix a rounding issue in 8-bit decoding.
## [0.3.6] - 2021-03-25
### Changed
- Fix a bug that could result in the generation of invalid codestreams as
well as failure to decode valid streams.
## [0.3.5] - 2021-03-23
### Added
- New encode-time options for faster decoding at the cost of quality.
- Man pages for cjxl and djxl.
### Changed
- Memory usage improvements.
- Faster decoding to 8-bit output with the C API.
- GIMP plugin: avoid the sRGB conversion dialog for sRGB images, do not show
a console window on Windows.
- Various bug fixes.
## [0.3.4] - 2021-03-16
### Changed
- Improved box parsing.
- Improved metadata handling.
- Performance and memory usage improvements.
## [0.3.3] - 2021-03-05
### Changed
- Performance improvements for small images.
- Add a (flag-protected) non-high-precision mode with better speed.
- Significantly speed up the PQ EOTF.
- Allow optional HDR tone mapping in djxl (--tone_map, --display_nits).
- Change the behavior of djxl -j to make it consistent with cjxl (#153).
- Improve image quality.
- Improve EXIF handling.
## [0.3.2] - 2021-02-12
### Changed
- Fix embedded ICC encoding regression
[#149](https://gitlab.com/wg1/jpeg-xl/-/issues/149).
## [0.3.1] - 2021-02-10
### Changed
- New experimental Butteraugli API (`jxl/butteraugli.h`).
- Encoder improvements to low quality settings.
- Bug fixes, including fuzzer-found potential security bug fixes.
- Fixed `-q 100` and `-d 0` not triggering lossless modes.
## [0.3] - 2021-01-29
### Changed
- Minor change to the Decoder C API to accommodate future work for other ways
to provide input.
- Future decoder C API changes will be backwards compatible.
- Lots of bug fixes since the previous version.
## [0.2] - 2020-12-24
### Added
- JPEG XL bitstream format is frozen. Files encoded with 0.2 will be supported
by future versions.
### Changed
- Files encoded with previous versions are not supported.
## [0.1.1] - 2020-12-01
## [0.1] - 2020-11-14
### Added
- Initial release of an encoder (`cjxl`) and decoder (`djxl`) that work
together as well as a benchmark tool for comparison with other codecs
(`benchmark_xl`).
- Note: JPEG XL format is in the final stages of standardization, minor changes
to the codestream format are still possible but we are not expecting any
changes beyond what is required by bug fixing.
- API: new decoder API in C, check the `examples/` directory for its example
usage. The C API is a work in progress and likely to change both in API and
ABI in future releases.

View file

@ -0,0 +1,472 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Ubuntu bionic ships with cmake 3.10.
cmake_minimum_required(VERSION 3.10)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Honor VISIBILITY_INLINES_HIDDEN on all types of targets.
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif()
# Pass CMAKE_EXE_LINKER_FLAGS to CC and CXX compilers when testing if they work.
if(POLICY CMP0065)
cmake_policy(SET CMP0065 NEW)
endif()
# Set PIE flags for POSITION_INDEPENDENT_CODE targets, added in 3.14.
if(POLICY CMP0083)
cmake_policy(SET CMP0083 NEW)
endif()
project(LIBJXL LANGUAGES C CXX)
include(CheckCXXSourceCompiles)
check_cxx_source_compiles(
"int main() {
#if !defined(__EMSCRIPTEN__)
static_assert(false, \"__EMSCRIPTEN__ is not defined\");
#endif
return 0;
}"
JPEGXL_EMSCRIPTEN
)
message(STATUS "CMAKE_SYSTEM_PROCESSOR is ${CMAKE_SYSTEM_PROCESSOR}")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-fsanitize=fuzzer-no-link" CXX_FUZZERS_SUPPORTED)
check_cxx_compiler_flag("-Xclang -mconstructor-aliases" CXX_CONSTRUCTOR_ALIASES_SUPPORTED)
check_cxx_compiler_flag("-fmacro-prefix-map=OLD=NEW" CXX_MACRO_PREFIX_MAP)
check_cxx_compiler_flag("-fno-rtti" CXX_NO_RTTI_SUPPORTED)
# Enabled PIE binaries by default if supported.
include(CheckPIESupported OPTIONAL RESULT_VARIABLE CHECK_PIE_SUPPORTED)
if(CHECK_PIE_SUPPORTED)
check_pie_supported(LANGUAGES CXX)
if(CMAKE_CXX_LINK_PIE_SUPPORTED)
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
endif()
endif()
### Project build options:
if(CXX_FUZZERS_SUPPORTED)
# Enabled by default except on arm64, Windows and Apple builds.
set(ENABLE_FUZZERS_DEFAULT true)
endif()
find_package(PkgConfig)
if(NOT APPLE AND NOT WIN32 AND NOT HAIKU AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
pkg_check_modules(TCMallocMinimalVersionCheck QUIET IMPORTED_TARGET
libtcmalloc_minimal)
if(TCMallocMinimalVersionCheck_FOUND AND
NOT TCMallocMinimalVersionCheck_VERSION VERSION_EQUAL 2.8.0)
# Enabled by default except on Windows and Apple builds for
# tcmalloc != 2.8.0. tcmalloc 2.8.1 already has a fix for this issue.
set(ENABLE_TCMALLOC_DEFAULT true)
else()
message(STATUS
"tcmalloc version ${TCMallocMinimalVersionCheck_VERSION} -- "
"tcmalloc 2.8.0 disabled due to "
"https://github.com/gperftools/gperftools/issues/1204")
endif()
endif()
check_cxx_source_compiles(
"int main() {
#if !defined(HWY_DISABLED_TARGETS)
static_assert(false, \"HWY_DISABLED_TARGETS is not defined\");
#endif
return 0;
}"
JXL_HWY_DISABLED_TARGETS_FORCED
)
set(WARNINGS_AS_ERRORS_DEFAULT false)
if((SANITIZER STREQUAL "msan") OR JPEGXL_EMSCRIPTEN)
set(BUNDLE_LIBPNG_DEFAULT YES)
else()
set(BUNDLE_LIBPNG_DEFAULT NO)
endif()
# Standard cmake naming for building shared libraries.
get_property(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
option(BUILD_SHARED_LIBS "Build shared libraries instead of static ones" ${SHARED_LIBS_SUPPORTED})
set(JPEGXL_ENABLE_FUZZERS ${ENABLE_FUZZERS_DEFAULT} CACHE BOOL
"Build JPEGXL fuzzer targets.")
set(JPEGXL_ENABLE_DEVTOOLS false CACHE BOOL
"Build JPEGXL developer tools.")
set(JPEGXL_ENABLE_TOOLS true CACHE BOOL
"Build JPEGXL user tools: cjxl and djxl.")
set(JPEGXL_ENABLE_DOXYGEN true CACHE BOOL
"Generate C API documentation using Doxygen.")
set(JPEGXL_ENABLE_MANPAGES true CACHE BOOL
"Build and install man pages for the command-line tools.")
set(JPEGXL_ENABLE_BENCHMARK true CACHE BOOL
"Build JPEGXL benchmark tools.")
set(JPEGXL_ENABLE_EXAMPLES true CACHE BOOL
"Build JPEGXL library usage examples.")
set(JPEGXL_BUNDLE_LIBPNG ${BUNDLE_LIBPNG_DEFAULT} CACHE BOOL
"Build libpng from source and link it statically.")
set(JPEGXL_ENABLE_JNI true CACHE BOOL
"Build JPEGXL JNI Java wrapper, if Java dependencies are installed.")
set(JPEGXL_ENABLE_SJPEG true CACHE BOOL
"Build JPEGXL with support for encoding with sjpeg.")
set(JPEGXL_ENABLE_OPENEXR true CACHE BOOL
"Build JPEGXL with support for OpenEXR if available.")
set(JPEGXL_ENABLE_SKCMS true CACHE BOOL
"Build with skcms instead of lcms2.")
set(JPEGXL_BUNDLE_SKCMS true CACHE BOOL
"When building with skcms, bundle it into libjxl.a.")
set(JPEGXL_ENABLE_VIEWERS false CACHE BOOL
"Build JPEGXL viewer tools for evaluation.")
set(JPEGXL_ENABLE_TCMALLOC ${ENABLE_TCMALLOC_DEFAULT} CACHE BOOL
"Build JPEGXL using gperftools (tcmalloc) allocator.")
set(JPEGXL_ENABLE_PLUGINS false CACHE BOOL
"Build third-party plugins to support JPEG XL in other applications.")
set(JPEGXL_ENABLE_COVERAGE false CACHE BOOL
"Enable code coverage tracking for libjxl. This also enables debug and disables optimizations.")
set(JPEGXL_ENABLE_PROFILER false CACHE BOOL
"Builds in support for profiling (printed by tools if extra flags given)")
set(JPEGXL_ENABLE_SIZELESS_VECTORS false CACHE BOOL
"Builds in support for SVE/RVV vectorization")
set(JPEGXL_ENABLE_TRANSCODE_JPEG true CACHE BOOL
"Builds in support for decoding transcoded JXL files back to JPEG,\
disabling it makes the decoder reject JXL_DEC_JPEG_RECONSTRUCTION events,\
(default enabled)")
set(JPEGXL_STATIC false CACHE BOOL
"Build tools as static binaries.")
set(JPEGXL_WARNINGS_AS_ERRORS ${WARNINGS_AS_ERRORS_DEFAULT} CACHE BOOL
"Treat warnings as errors during compilation.")
set(JPEGXL_DEP_LICENSE_DIR "" CACHE STRING
"Directory where to search for system dependencies \"copyright\" files.")
set(JPEGXL_FORCE_NEON false CACHE BOOL
"Set flags to enable NEON in arm if not enabled by your toolchain.")
# Force system dependencies.
set(JPEGXL_FORCE_SYSTEM_BROTLI false CACHE BOOL
"Force using system installed brotli instead of third_party/brotli source.")
set(JPEGXL_FORCE_SYSTEM_GTEST false CACHE BOOL
"Force using system installed googletest (gtest/gmock) instead of third_party/googletest source.")
set(JPEGXL_FORCE_SYSTEM_LCMS2 false CACHE BOOL
"Force using system installed lcms2 instead of third_party/lcms source.")
set(JPEGXL_FORCE_SYSTEM_HWY false CACHE BOOL
"Force using system installed highway (libhwy-dev) instead of third_party/highway source.")
# Check minimum compiler versions. Older compilers are not supported and fail
# with hard to understand errors.
if (NOT CMAKE_C_COMPILER_ID STREQUAL CMAKE_CXX_COMPILER_ID)
message(FATAL_ERROR "Different C/C++ compilers set: "
"${CMAKE_C_COMPILER_ID} vs ${CMAKE_CXX_COMPILER_ID}")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Android NDK's toolchain.cmake fakes the clang version in
# CMAKE_CXX_COMPILER_VERSION with an incorrect number, so ignore this.
if (NOT CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION MATCHES "clang"
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
message(FATAL_ERROR
"Minimum Clang version required is Clang 5, please update.")
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7)
message(FATAL_ERROR
"Minimum GCC version required is 7, please update.")
endif()
endif()
message(STATUS
"Compiled IDs C:${CMAKE_C_COMPILER_ID}, C++:${CMAKE_CXX_COMPILER_ID}")
# CMAKE_EXPORT_COMPILE_COMMANDS is used to generate the compilation database
# used by clang-tidy.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
if(JPEGXL_STATIC)
set(BUILD_SHARED_LIBS 0)
# Clang developers say that in case to use "static" we have to build stdlib
# ourselves; for real use case we don't care about stdlib, as it is "granted",
# so just linking all other libraries is fine.
if (NOT MSVC AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
endif()
endif() # JPEGXL_STATIC
# Threads
set(THREADS_PREFER_PTHREAD_FLAG YES)
find_package(Threads REQUIRED)
# These settings are important to drive check_cxx_source_compiles
# See CMP0067 (min cmake version is 3.10 anyway)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
# Atomics
find_package(Atomics REQUIRED)
if(JPEGXL_STATIC)
if (MINGW)
# In MINGW libstdc++ uses pthreads directly. When building statically a
# program (regardless of whether the source code uses pthread or not) the
# toolchain will add stdc++ and pthread to the linking step but stdc++ will
# be linked statically while pthread will be linked dynamically.
# To avoid this and have pthread statically linked with need to pass it in
# the command line with "-Wl,-Bstatic -lpthread -Wl,-Bdynamic" but the
# linker will discard it if not used by anything else up to that point in
# the linker command line. If the program or any dependency don't use
# pthread directly -lpthread is discarded and libstdc++ (added by the
# toolchain later) will then use the dynamic version. For this we also need
# to pass -lstdc++ explicitly before -lpthread. For pure C programs -lstdc++
# will be discarded anyway.
# This adds these flags as dependencies for *all* targets. Adding this to
# CMAKE_EXE_LINKER_FLAGS instead would cause them to be included before any
# object files and therefore discarded. This should be set in the
# INTERFACE_LINK_LIBRARIES of Threads::Threads but some third_part targets
# don't depend on it.
link_libraries(-Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic)
elseif(CMAKE_USE_PTHREADS_INIT)
# "whole-archive" is not supported on OSX.
if (NOT APPLE)
# Set pthreads as a whole-archive, otherwise weak symbols in the static
# libraries will discard pthreads symbols leading to segmentation fault at
# runtime.
message(STATUS "Using -lpthread as --whole-archive")
set_target_properties(Threads::Threads PROPERTIES
INTERFACE_LINK_LIBRARIES
"-Wl,--whole-archive;-lpthread;-Wl,--no-whole-archive")
endif()
endif()
endif() # JPEGXL_STATIC
if (JPEGXL_EMSCRIPTEN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
endif()
if (CXX_MACRO_PREFIX_MAP)
add_compile_options(-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}=.)
endif()
if (CXX_NO_RTTI_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
if (MSVC)
# TODO(janwas): add flags
else ()
# Global compiler flags for all targets here and in subdirectories.
add_definitions(
# Avoid changing the binary based on the current time and date.
-D__DATE__="redacted"
-D__TIMESTAMP__="redacted"
-D__TIME__="redacted"
)
# Avoid log spam from fopen etc.
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
# TODO(eustas): JXL currently compiles, but does not pass tests...
if (NOT JXL_HWY_DISABLED_TARGETS_FORCED AND NOT JPEGXL_ENABLE_SIZELESS_VECTORS)
add_definitions(-DHWY_DISABLED_TARGETS=\(HWY_SVE|HWY_SVE2|HWY_SVE_256|HWY_SVE2_128|HWY_RVV\))
message("Warning: HWY_SVE, HWY_SVE2, HWY_SVE_256, HWY_SVE2_128 and HWY_RVV CPU targets are disabled")
endif()
# In CMake before 3.12 it is problematic to pass repeated flags like -Xclang.
# For this reason we place them in CMAKE_CXX_FLAGS instead.
# See https://gitlab.kitware.com/cmake/cmake/issues/15826
# Machine flags.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -funwind-tables")
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -mrelax-all")
endif()
if (CXX_CONSTRUCTOR_ALIASES_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Xclang -mconstructor-aliases")
endif()
if(WIN32)
# Not supported by clang-cl, but frame pointers are default on Windows
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
endif()
# CPU flags - remove once we have NEON dynamic dispatch
# TODO(janwas): this also matches M1, but only ARMv7 is intended/needed.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
if(JPEGXL_FORCE_NEON)
# GCC requires these flags, otherwise __ARM_NEON is undefined.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
-mfpu=neon-vfpv4 -mfloat-abi=hard")
endif()
endif()
# Force build with optimizations in release mode.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
add_compile_options(
# Ignore this to allow redefining __DATE__ and others.
-Wno-builtin-macro-redefined
# Global warning settings.
-Wall
)
if (JPEGXL_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif ()
endif () # !MSVC
include(GNUInstallDirs)
# Separately build/configure testing frameworks and other third_party libraries
# to allow disabling tests in those libraries.
include(third_party/testing.cmake)
add_subdirectory(third_party)
# Copy the JXL license file to the output build directory.
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
${PROJECT_BINARY_DIR}/LICENSE.jpeg-xl COPYONLY)
# Enable tests regardless of where they are defined.
enable_testing()
include(CTest)
# Specify default location of `testdata`:
if(NOT DEFINED JPEGXL_TEST_DATA_PATH)
set(JPEGXL_TEST_DATA_PATH "${PROJECT_SOURCE_DIR}/testdata")
endif()
# Libraries.
add_subdirectory(lib)
if(BUILD_TESTING)
# Script to run tests over the source code in bash.
find_program (BASH_PROGRAM bash)
if(BASH_PROGRAM)
add_test(
NAME bash_test
COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/bash_test.sh)
endif()
endif() # BUILD_TESTING
# Documentation generated by Doxygen
if(JPEGXL_ENABLE_DOXYGEN)
find_package(Doxygen)
if(DOXYGEN_FOUND)
set(DOXYGEN_GENERATE_HTML "YES")
set(DOXYGEN_GENERATE_XML "YES")
set(DOXYGEN_STRIP_FROM_PATH "${CMAKE_CURRENT_SOURCE_DIR}/lib/include")
set(DOXYGEN_USE_MDFILE_AS_MAINPAGE "README.md")
if(JPEGXL_WARNINGS_AS_ERRORS)
set(DOXYGEN_WARN_AS_ERROR "YES")
endif()
set(DOXYGEN_QUIET "YES")
doxygen_add_docs(doc
"${CMAKE_CURRENT_SOURCE_DIR}/lib/include"
"${CMAKE_CURRENT_SOURCE_DIR}/doc/api.txt"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "Generating C API documentation")
# Add sphinx doc build step for readthedocs.io (requires doxygen too).
find_program(SPHINX_BUILD_PROGRAM sphinx-build)
if(SPHINX_BUILD_PROGRAM)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/rtd/nonexistent"
COMMENT "Generating readthedocs.io output on ${CMAKE_CURRENT_BINARY_DIR}/rtd"
COMMAND ${SPHINX_BUILD_PROGRAM} -q -W -b html -j auto
${CMAKE_SOURCE_DIR}/doc/sphinx
${CMAKE_CURRENT_BINARY_DIR}/rtd
DEPENDS doc
)
# This command runs the documentation generation every time since the output
# target file doesn't exist.
add_custom_target(rtd-html
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/rtd/nonexistent
)
else() # SPHINX_BUILD_PROGRAM\
message(WARNING "sphinx-build not found, skipping rtd documentation")
endif() # SPHINX_BUILD_PROGRAM
else()
# Create a "doc" target for compatibility since "doc" is not otherwise added to
# the build when doxygen is not installed.
add_custom_target(doc false
COMMENT "Error: Can't generate doc since Doxygen not installed.")
endif() # DOXYGEN_FOUND
endif() # JPEGXL_ENABLE_DOXYGEN
if(JPEGXL_ENABLE_MANPAGES)
find_program(ASCIIDOC a2x)
if(ASCIIDOC)
file(STRINGS "${ASCIIDOC}" ASCIIDOC_SHEBANG LIMIT_COUNT 1)
if(ASCIIDOC_SHEBANG MATCHES "/sh|/bash")
set(ASCIIDOC_PY_FOUND ON)
# Run the program directly and set ASCIIDOC as empty.
set(ASCIIDOC_PY "${ASCIIDOC}")
set(ASCIIDOC "")
elseif(ASCIIDOC_SHEBANG MATCHES "python2")
find_package(Python2 COMPONENTS Interpreter)
set(ASCIIDOC_PY_FOUND "${Python2_Interpreter_FOUND}")
set(ASCIIDOC_PY Python2::Interpreter)
elseif(ASCIIDOC_SHEBANG MATCHES "python3")
find_package(Python3 COMPONENTS Interpreter)
set(ASCIIDOC_PY_FOUND "${Python3_Interpreter_FOUND}")
set(ASCIIDOC_PY Python3::Interpreter)
else()
find_package(Python COMPONENTS Interpreter QUIET)
if(NOT Python_Interpreter_FOUND)
find_program(ASCIIDOC_PY python)
if(ASCIIDOC_PY)
set(ASCIIDOC_PY_FOUND ON)
endif()
else()
set(ASCIIDOC_PY_FOUND "${Python_Interpreter_FOUND}")
set(ASCIIDOC_PY Python::Interpreter)
endif()
endif()
if (ASCIIDOC_PY_FOUND)
set(MANPAGE_FILES "")
set(MANPAGES "")
foreach(PAGE IN ITEMS cjxl djxl)
# Invoking the Python interpreter ourselves instead of running the a2x binary
# directly is necessary on MSYS2, otherwise it is run through cmd.exe which
# does not recognize it.
add_custom_command(
OUTPUT "${PAGE}.1"
COMMAND "${ASCIIDOC_PY}"
ARGS ${ASCIIDOC}
--format manpage --destination-dir="${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/doc/man/${PAGE}.txt"
MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/doc/man/${PAGE}.txt")
list(APPEND MANPAGE_FILES "${CMAKE_CURRENT_BINARY_DIR}/${PAGE}.1")
list(APPEND MANPAGES "${PAGE}.1")
endforeach()
add_custom_target(manpages ALL DEPENDS ${MANPAGES})
install(FILES ${MANPAGE_FILES} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif() # ASCIIDOC_PY_FOUND
else()
message(WARNING "asciidoc was not found, the man pages will not be installed.")
endif() # ASCIIDOC
endif() # JPEGXL_ENABLE_MANPAGES
# Example usage code.
if (JPEGXL_ENABLE_EXAMPLES)
include(examples/examples.cmake)
endif ()
# Plugins for third-party software
if (JPEGXL_ENABLE_PLUGINS)
add_subdirectory(plugins)
endif ()
# Binary tools
add_subdirectory(tools)

View file

@ -0,0 +1,93 @@
# Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of
experience, education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, or to ban temporarily or permanently any
contributor for other behaviors that they deem inappropriate, threatening,
offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
This Code of Conduct also applies outside the project spaces when the Project
Steward has a reasonable belief that an individual's behavior may have a
negative impact on the project or its community.
## Conflict Resolution
We do not believe that all conflict is bad; healthy debate and disagreement
often yield positive results. However, it is never okay to be disrespectful or
to engage in behavior that violates the projects code of conduct.
If you see someone violating the code of conduct, you are encouraged to address
the behavior directly with those involved. Many issues can be resolved quickly
and easily, and this gives people more control over the outcome of their
dispute. If you are unable to resolve the matter for any reason, or if the
behavior is threatening or harassing, report it. We are dedicated to providing
an environment where participants feel welcome and safe.
Reports should be directed to Jyrki Alakuijala <jyrki@google.com>, the
Project Steward(s) for JPEG XL. It is the Project Stewards duty to
receive and address reported violations of the code of conduct. They will then
work with a committee consisting of representatives from the Open Source
Programs Office and the Google Open Source Strategy team. If for any reason you
are uncomfortable reaching out to the Project Steward, please email
opensource@google.com.
We will investigate every complaint, but you may not receive a direct response.
We will use our discretion in determining when and how to follow up on reported
incidents, which may range from not taking action to permanent expulsion from
the project and project-sponsored spaces. We will notify the accused of the
report and provide them an opportunity to discuss it before any action is taken.
The identity of the reporter will be omitted from the details of the report
supplied to the accused. In potentially harmful situations, such as ongoing
harassment or threats to anyone's safety, we may take action without notice.
## Attribution
This Code of Conduct is adapted from the Contributor Covenant, version 1.4,
available at
https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

View file

@ -0,0 +1,132 @@
# Contributing to libjxl
## Contributing with bug reports
For security-related issues please see [SECURITY.md](SECURITY.md).
We welcome suggestions, feature requests and bug reports. Before opening a new
issue please take a look if there is already an existing one in the following
link:
* https://github.com/libjxl/libjxl/issues
## Contributing with patches and Pull Requests
We'd love to accept your contributions to the JPEG XL Project. Please read
through this section before sending a Pull Request.
### Contributor License Agreements
Our project is open source under the terms outlined in the [LICENSE](LICENSE)
and [PATENTS](PATENTS) files. Before we can accept your contributions, even for
small changes, there are just a few small guidelines you need to follow:
Please fill out either the individual or corporate Contributor License Agreement
(CLA) with Google. JPEG XL Project is an an effort by multiple individuals and
companies, including the initial contributors Cloudinary and Google, but Google
is the legal entity in charge of receiving these CLA and relicensing this
software:
* If you are an individual writing original source code and you're sure you
own the intellectual property, then you'll need to sign an [individual
CLA](https://code.google.com/legal/individual-cla-v1.0.html).
* If you work for a company that wants to allow you to contribute your work,
then you'll need to sign a [corporate
CLA](https://code.google.com/legal/corporate-cla-v1.0.html).
Follow either of the two links above to access the appropriate CLA and
instructions for how to sign and return it. Once we receive it, we'll be able
to accept your pull requests.
***NOTE***: Only original source code from you and other people that have signed
the CLA can be accepted into the main repository.
### License
Contributions are licensed under the project's [LICENSE](LICENSE). Each new
file must include the following header when possible, with comment style adapted
to the language as needed:
```
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
```
### Code Reviews
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
### Contribution philosophy
* Prefer small changes, even if they don't implement a complete feature. Small
changes are easier to review and can be submitted faster. Think about what's
the smallest unit you can send that makes sense to review and submit in
isolation. For example, new modules that are not yet used by the tools but
have their own unittests are ok. If you have unrelated changes that
you discovered while working on something else, please send them in a
different Pull Request. If your are refactoring code and changing
functionality try to send the refactor first without any change in
functionality. Reviewers may ask you to split a Pull Request and it is
easier to create a smaller change from the beginning.
* Describe your commits. Add a meaningful description to your commit message, explain what you are changing if it is not trivially obvious, but more importantly explain *why* you are making those changes. For example "Fix
build" is not a good commit message, describe what build and if it makes sense
why is this fixing it or why was it failing without this. It is very likely
that people far in the future without any context you have right now will be
looking at your commit trying to figure out why was the change introduced. If
related to an issue in this or another repository include a link to it.
* Code Style: We follow the [Google C++ Coding
Style](https://google.github.io/styleguide/cppguide.html). A
[clang-format](https://clang.llvm.org/docs/ClangFormat.html) configuration
file is available to automatically format your code, you can invoke it with
the `./ci.sh lint` helper tool.
* Testing: Test your change and explain in the commit message *how* your
commit was tested. For example adding unittests or in some cases just testing
with the existing ones is enough. In any case, mention what testing was
performed so reviewers can evaluate whether that's enough testing. In many
cases, testing that the Continuous Integration workflow passes is enough.
* Make one commit per Pull Request / review, unless there's a good reason not
to. If you have multiple changes send multiple Pull Requests and each one can
have its own review.
* When addressing comments from reviewers prefer to squash or fixup your
edits and force-push your commit. When merging changes into the repository we
don't want to include the history of code review back and forth changes or
typos. Reviewers can click on the "force-pushed" automatic comment on a Pull
Request to see the changes between versions. We use "Rebase and merge" policy
to keep a linear git history which is easier to reason about.
* Your change must pass the build and test workflows. There's a `ci.sh` script
to help building and testing these configurations. See [building and
testing](doc/building_and_testing.md) for more details.
### Contributing checklist.
* Sign the CLA (only needed once per user, see above).
* AUTHORS: If this is your first contribution, add your name or your
company name to the [AUTHORS](AUTHORS) file for copyright tracking purposes.
* Style guide. Check `./ci.sh lint`.
* Meaningful commit description: What and *why*, links to issues, testing
procedure.
* Squashed multiple edits into a single commit.
* Upload your changes to your fork and [create a Pull
Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
# Community Guidelines
This project follows [Google's Open Source Community
Guidelines](https://opensource.google.com/conduct/).

View file

@ -0,0 +1,23 @@
# This files lists individuals who made significant contributions to the JPEG XL
# code base, such as design, adding features, performing experiments, ...
# Small changes such as a small bugfix or fixing spelling errors are not
# included. If you'd like to be included in this file thanks to a significant
# contribution, feel free to send a pull request changing this file.
Alex Deymo
Alexander Rhatushnyak
Evgenii Kliuchnikov
Iulia-Maria Comșa
Jan Wassenberg
Jon Sneyers
Jyrki Alakuijala
Krzysztof Potempa
Lode Vandevenne
Luca Versari
Martin Bruse
Moritz Firsching
Renata Khasanova
Robert Obryk
Sami Boukortt
Sebastian Gomez-Gonzalez
Thomas Fischbacher
Zoltan Szabadka

27
media/libjxl/src/LICENSE Normal file
View file

@ -0,0 +1,27 @@
Copyright (c) the JPEG XL Project Authors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

22
media/libjxl/src/PATENTS Normal file
View file

@ -0,0 +1,22 @@
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the JPEG XL project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of JPEG XL, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of JPEG XL. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of JPEG XL or any code incorporated within this
implementation of JPEG XL constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of JPEG XL
shall terminate as of the date such litigation is filed.

View file

@ -0,0 +1,20 @@
## Disclaimer
Haiku builds are not officially supported, i.e. the build might not work at all,
some tests may fail and some sub-projects are excluded from build.
This manual outlines Haiku-specific setup. For general building and testing
instructions see "[README](README.md)" and
"[Building and Testing changes](doc/building_and_testing.md)".
## Dependencies
```shell
pkgman install llvm9_clang ninja cmake doxygen libjpeg_turbo_devel giflib_devel
```
## Building
```shell
TEST_STACK_LIMIT=none CMAKE_FLAGS="-I/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/8.3.0/include/c++ -I/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/8.3.0/include/c++/x86_64-unknown-haiku" CMAKE_SHARED_LINKER_FLAGS="-shared -Xlinker -soname=libjpegxl.so -lpthread" ./ci.sh opt
```

View file

@ -0,0 +1,41 @@
## Disclaimer
OSX builds have "best effort" support, i.e. build might not work at all, some
tests may fail and some sub-projects are excluded from build.
This manual outlines OSX specific setup. For general building and testing
instructions see "[README](README.md)" and
"[Building and Testing changes](doc/building_and_testing.md)".
[Homebrew](https://brew.sh/) is a popular package manager. JPEG XL library and
binaries could be installed using it:
```bash
brew install jpeg-xl
```
## Dependencies
Make sure that `brew doctor` does not report serious problems and up-to-date
version of XCode is installed.
Installing (actually, building) `clang` might take a couple hours.
```bash
brew install llvm
```
```bash
brew install coreutils cmake giflib jpeg-turbo libpng ninja zlib
```
Before building the project check that `which clang` is
`/usr/local/opt/llvm/bin/clang`, not the one provided by XCode. If not, update
`PATH` environment variable.
Also, setting `CMAKE_PREFIX_PATH` might be necessary for correct include paths
resolving, e.g.:
```bash
export CMAKE_PREFIX_PATH=`brew --prefix giflib`:`brew --prefix jpeg-turbo`:`brew --prefix libpng`:`brew --prefix zlib`
```

197
media/libjxl/src/README.md Normal file
View file

@ -0,0 +1,197 @@
# JPEG XL reference implementation
[![Build/Test](https://github.com/libjxl/libjxl/actions/workflows/build_test.yml/badge.svg)](
https://github.com/libjxl/libjxl/actions/workflows/build_test.yml)
[![Build/Test Cross](https://github.com/libjxl/libjxl/actions/workflows/build_test_cross.yml/badge.svg)](
https://github.com/libjxl/libjxl/actions/workflows/build_test_cross.yml)
[![Conformance](https://github.com/libjxl/libjxl/actions/workflows/conformance.yml/badge.svg)](
https://github.com/libjxl/libjxl/actions/workflows/conformance.yml)
[![CIFuzz](https://github.com/libjxl/libjxl/actions/workflows/fuzz.yml/badge.svg)](
https://github.com/libjxl/libjxl/actions/workflows/fuzz.yml)
[![Releases](https://github.com/libjxl/libjxl/actions/workflows/release.yaml/badge.svg)](
https://github.com/libjxl/libjxl/actions/workflows/release.yaml)
[![Doc](https://readthedocs.org/projects/libjxl/badge/?version=latest)](
https://libjxl.readthedocs.io/en/latest/?badge=latest)
[![codecov](https://codecov.io/gh/libjxl/libjxl/branch/main/graph/badge.svg)](
https://codecov.io/gh/libjxl/libjxl)
<img src="doc/jxl.svg" width="100" align="right" alt="JXL logo">
This repository contains a reference implementation of JPEG XL (encoder and
decoder), called `libjxl`. This software library is
[used by many applications that support JPEG XL](doc/software_support.md).
JPEG XL is in the final stages of standardization and its codestream and file format
are frozen.
The library API, command line options, and tools in this repository are subject
to change, however files encoded with `cjxl` conform to the JPEG XL format
specification and can be decoded with current and future `djxl` decoders or
`libjxl` decoding library.
## Quick start guide
For more details and other workflows see the "Advanced guide" below.
### Checking out the code
```bash
git clone https://github.com/libjxl/libjxl.git --recursive --shallow-submodules
```
This repository uses git submodules to handle some third party dependencies
under `third_party`, that's why is important to pass `--recursive`. If you
didn't check out with `--recursive`, or any submodule has changed, run:
```bash
git submodule update --init --recursive --depth 1 --recommend-shallow
```
The `--shallow-submodules` and `--depth 1 --recommend-shallow` options create
shallow clones which only downloads the commits requested, and is all that is
needed to build `libjxl`. Should full clones be necessary, you could always run:
```bash
git submodule foreach git fetch --unshallow
git submodule update --init --recursive
```
which pulls the rest of the commits in the submodules.
Important: If you downloaded a zip file or tarball from the web interface you
won't get the needed submodules and the code will not compile. You can download
these external dependencies from source running `./deps.sh`. The git workflow
described above is recommended instead.
### Installing dependencies
Required dependencies for compiling the code, in a Debian/Ubuntu based
distribution run:
```bash
sudo apt install cmake pkg-config libbrotli-dev
```
Optional dependencies for supporting other formats in the `cjxl`/`djxl` tools,
in a Debian/Ubuntu based distribution run:
```bash
sudo apt install libgif-dev libjpeg-dev libopenexr-dev libpng-dev libwebp-dev
```
We recommend using a recent Clang compiler (version 7 or newer), for that
install clang and set `CC` and `CXX` variables.
```bash
sudo apt install clang
export CC=clang CXX=clang++
```
### Building
```bash
cd libjxl
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ..
cmake --build . -- -j$(nproc)
```
The encoder/decoder tools will be available in the `build/tools` directory.
### <a name="installing"></a> Installing
```bash
sudo cmake --install .
```
### Basic encoder/decoder
To encode a source image to JPEG XL with default settings:
```bash
build/tools/cjxl input.png output.jxl
```
For more settings run `build/tools/cjxl --help` or for a full list of options
run `build/tools/cjxl -v -v --help`.
To decode a JPEG XL file run:
```bash
build/tools/djxl input.jxl output.png
```
When possible `cjxl`/`djxl` are able to read/write the following
image formats: .exr, .gif, .jpeg/.jpg, .pfm, .pgm/.ppm, .pgx, .png.
### Benchmarking
For speed benchmarks on single images in single or multi-threaded decoding
`djxl` can print decoding speed information. See `djxl --help` for details
on the decoding options and note that the output image is optional for
benchmarking purposes.
For more comprehensive benchmarking options, see the
[benchmarking guide](doc/benchmarking.md).
## Advanced guide
### Building with Docker
We build a common environment based on Debian/Ubuntu using Docker. Other
systems may have different combinations of versions and dependencies that
have not been tested and may not work. For those cases we recommend using the
Docker container as explained in the
[step by step guide](doc/developing_in_docker.md).
### Building JPEG XL for developers
For experienced developers, we provide build instructions for several other environments:
* [Building on Debian](doc/developing_in_debian.md)
* Building on Windows with [vcpkg](doc/developing_in_windows_vcpkg.md) (Visual Studio 2019)
* Building on Windows with [MSYS2](doc/developing_in_windows_msys.md)
* [Cross Compiling for Windows with Crossroad](doc/developing_with_crossroad.md)
If you encounter any difficulties, please use Docker instead.
## License
This software is available under a 3-clause BSD license which can be found in
the [LICENSE](LICENSE) file, with an "Additional IP Rights Grant" as outlined in
the [PATENTS](PATENTS) file.
Please note that the PATENTS file only mentions Google since Google is the legal
entity receiving the Contributor License Agreements (CLA) from all contributors
to the JPEG XL Project, including the initial main contributors to the JPEG XL
format: Cloudinary and Google.
## Additional documentation
### Codec description
* [JPEG XL Format Overview](doc/format_overview.md)
* [Introductory paper](https://www.spiedigitallibrary.org/proceedings/Download?fullDOI=10.1117%2F12.2529237) (open-access)
* [XL Overview](doc/xl_overview.md) - a brief introduction to the source code modules
* [JPEG XL white paper](https://ds.jpeg.org/whitepapers/jpeg-xl-whitepaper.pdf)
* [JPEG XL official website](https://jpeg.org/jpegxl)
* [JPEG XL community website](https://jpegxl.info)
### Development process
* [More information on testing/build options](doc/building_and_testing.md)
* [Git guide for JPEG XL](doc/developing_in_github.md) - for developers
* [Fuzzing](doc/fuzzing.md) - for developers
* [Building Web Assembly artifacts](doc/building_wasm.md)
* [Test coverage on Codecov.io](https://app.codecov.io/gh/libjxl/libjxl) - for
developers
* [libjxl documentation on readthedocs.io](https://libjxl.readthedocs.io/)
### Contact
If you encounter a bug or other issue with the software, please open an Issue here.
There is a [subreddit about JPEG XL](https://www.reddit.com/r/jpegxl/), and
informal chatting with developers and early adopters of `libjxl` can be done on the
[JPEG XL Discord server](https://discord.gg/DqkQgDRTFu).

View file

@ -0,0 +1,73 @@
# Security and Vulnerability Policy for libjxl
## TL;DR:
CPE prefix: `cpe:2.3:a:libjxl_project:libjxl`
To report a security issue, please email libjxl-security@google.com.
Include in your email a description of the issue, the steps you took to create
the issue, affected versions, and if known, mitigations for the issue. Our
vulnerability management team will acknowledge receiving your email within 3
working days.
This project follows a 90 day disclosure timeline.
For all other bugs, where there are no security implications about disclosing
the unpatched bug, open a [new issue](https://github.com/libjxl/libjxl/issues)
checking first for existing similar issues. If in doubt about the security
impact of a bug you discovered, email first.
## Policy overview
libjxl's Security Policy is based on the [Google Open Source program
guidelines](https://github.com/google/oss-vulnerability-guide) for coordinated
vulnerability disclosure.
Early versions of `libjxl` had a different security policy that didn't provide
security and vulnerability disclosure support. Versions up to and including
0.3.7 are not covered and won't receive any security advisory.
Only released versions, starting from version 0.5, are covered by this policy.
Development branches, arbitrary commits from `main` branch or even releases with
backported features externally patched on top are not covered. Only those
versions with a release tag in `libjxl`'s repository are covered, starting from
version 0.5.
## What's a "Security bug"
A security bug is a bug that can potentially be exploited to let an attacker
gain unauthorized access or privileges such as disclosing information or
arbitrary code execution. Not all fuzzer-found bugs and not all assert()
failures are considered security bugs in libjxl. For a detailed explanation and
examples see our [Security Vulnerabilities Playbook](doc/vuln_playbook.md).
## What to expect
To report a security issue, please email libjxl-security@google.com with all the
details about the bug you encountered.
* Include a description of the issue, steps to reproduce, etc. Compiler
versions, flags, exact version used and even CPU are often relevant given our
usage of SIMD and run-time dispatch of SIMD instructions.
* A member of our security team will reply to you within 3 business days. Note
that business days are different in different countries.
* We will evaluate the issue and we may require more input from your side to
reproduce it.
* If the issue fits in the description of a security bug, we will issue a
CVE, publish a fix and make a new minor or patch release with it. There is
a maximum of 90 day disclosure timeline, we ask you to not publish the
details before the 90 day deadline or the release date (whichever comes
first).
* In the case that we publish a CVE we will credit the external researcher who
reported the issue. When reporting security issues please let us know if you
need to include specific information while doing so, like for example a
company affiliation.
Our security team follows the [Security Vulnerabilities
Playbook](doc/vuln_playbook.md). For more details about the process and policies
please take a look at it.

View file

@ -0,0 +1,314 @@
#!/bin/bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Tests implemented in bash. These typically will run checks about the source
# code rather than the compiled one.
MYDIR=$(dirname $(realpath "$0"))
set -u
test_includes() {
local ret=0
local f
for f in $(git ls-files | grep -E '(\.cc|\.cpp|\.h)$'); do
if [ ! -e "$f" ]; then
continue
fi
# Check that the public files (in lib/include/ directory) don't use the full
# path to the public header since users of the library will include the
# library as: #include "jxl/foobar.h".
if [[ "${f#lib/include/}" != "${f}" ]]; then
if grep -i -H -n -E '#include\s*[<"]lib/include/jxl' "$f" >&2; then
echo "Don't add \"include/\" to the include path of public headers." >&2
ret=1
fi
fi
if [[ "${f#third_party/}" == "$f" ]]; then
# $f is not in third_party/
# Check that local files don't use the full path to third_party/
# directory since the installed versions will not have that path.
# Add an exception for third_party/dirent.h.
if grep -v -F 'third_party/dirent.h' "$f" | \
grep -i -H -n -E '#include\s*[<"]third_party/' >&2 &&
[[ $ret -eq 0 ]]; then
cat >&2 <<EOF
$f: Don't add third_party/ to the include path of third_party projects. This \
makes it harder to use installed system libraries instead of the third_party/ \
ones.
EOF
ret=1
fi
fi
done
return ${ret}
}
test_include_collision() {
local ret=0
local f
for f in $(git ls-files | grep -E '^lib/include/'); do
if [ ! -e "$f" ]; then
continue
fi
local base=${f#lib/include/}
if [[ -e "lib/${base}" ]]; then
echo "$f: Name collision, both $f and lib/${base} exist." >&2
ret=1
fi
done
return ${ret}
}
test_copyright() {
local ret=0
local f
for f in $(
git ls-files | grep -E \
'(Dockerfile.*|\.c|\.cc|\.cpp|\.gni|\.h|\.java|\.sh|\.m|\.py|\.ui|\.yml)$'); do
if [ ! -e "$f" ]; then
continue
fi
if [[ "${f#third_party/}" == "$f" ]]; then
# $f is not in third_party/
if ! head -n 10 "$f" |
grep -F 'Copyright (c) the JPEG XL Project Authors.' >/dev/null ; then
echo "$f: Missing Copyright blob near the top of the file." >&2
ret=1
fi
if ! head -n 10 "$f" |
grep -F 'Use of this source code is governed by a BSD-style' \
>/dev/null ; then
echo "$f: Missing License blob near the top of the file." >&2
ret=1
fi
fi
done
return ${ret}
}
# Check that we don't use "%zu" or "%zd" in format string for size_t.
test_printf_size_t() {
local ret=0
if grep -n -E '%[0-9]*z[udx]' \
$(git ls-files | grep -E '(\.c|\.cc|\.cpp|\.h)$'); then
echo "Don't use '%zu' or '%zd' in a format string, instead use " \
"'%\" PRIuS \"' or '%\" PRIdS \"'." >&2
ret=1
fi
if grep -n -E 'gmock\.h' \
$(git ls-files | grep -E '(\.c|\.cc|\.cpp|\.h)$' | grep -v -F /test_utils.h); then
echo "Don't include gmock directly, instead include 'test_utils.h'. " >&2
ret=1
fi
local f
for f in $(git ls-files | grep -E "\.cc$" | xargs grep 'PRI[udx]S' |
cut -f 1 -d : | uniq); do
if [ ! -e "$f" ]; then
continue
fi
if ! grep -F printf_macros.h "$f" >/dev/null; then
echo "$f: Add lib/jxl/base/printf_macros.h for PRI.S, or use other " \
"types for code outside lib/jxl library." >&2
ret=1
fi
done
for f in $(git ls-files | grep -E "\.h$" | grep -v -E '(printf_macros\.h|test_utils\.h)' |
xargs grep -n 'PRI[udx]S'); do
# Having PRIuS / PRIdS in a header file means that printf_macros.h may
# be included before a system header, in particular before gtest headers.
# those may re-define PRIuS unconditionally causing a compile error.
echo "$f: Don't use PRI.S in header files. Sorry."
ret=1
done
return ${ret}
}
# Check that "dec_" code doesn't depend on "enc_" headers.
test_dec_enc_deps() {
local ret=0
local f
for f in $(git ls-files | grep -E '/dec_'); do
if [ ! -e "$f" ]; then
continue
fi
if [[ "${f#third_party/}" == "$f" ]]; then
# $f is not in third_party/
if grep -n -H -E "#include.*/enc_" "$f" >&2; then
echo "$f: Don't include \"enc_*\" files from \"dec_*\" files." >&2
ret=1
fi
fi
done
return ${ret}
}
# Check for git merge conflict markers.
test_merge_conflict() {
local ret=0
TEXT_FILES='(\.cc|\.cpp|\.h|\.sh|\.m|\.py|\.md|\.txt|\.cmake)$'
for f in $(git ls-files | grep -E "${TEXT_FILES}"); do
if [ ! -e "$f" ]; then
continue
fi
if grep -E '^<<<<<<< ' "$f"; then
echo "$f: Found git merge conflict marker. Please resolve." >&2
ret=1
fi
done
return ${ret}
}
# Check that the library and the package have the same version. This prevents
# accidentally having them out of sync.
get_version() {
local varname=$1
local line=$(grep -F "set(${varname} " lib/CMakeLists.txt | head -n 1)
[[ -n "${line}" ]]
line="${line#set(${varname} }"
line="${line%)}"
echo "${line}"
}
test_version() {
local major=$(get_version JPEGXL_MAJOR_VERSION)
local minor=$(get_version JPEGXL_MINOR_VERSION)
local patch=$(get_version JPEGXL_PATCH_VERSION)
# Check that the version is not empty
if [[ -z "${major}${minor}${patch}" ]]; then
echo "Couldn't parse version from CMakeLists.txt" >&2
return 1
fi
local pkg_version=$(head -n 1 debian/changelog)
# Get only the part between the first "jpeg-xl (" and the following ")".
pkg_version="${pkg_version#jpeg-xl (}"
pkg_version="${pkg_version%%)*}"
if [[ -z "${pkg_version}" ]]; then
echo "Couldn't parse version from debian package" >&2
return 1
fi
local lib_version="${major}.${minor}.${patch}"
lib_version="${lib_version%.0}"
if [[ "${pkg_version}" != "${lib_version}"* ]]; then
echo "Debian package version (${pkg_version}) doesn't match library" \
"version (${lib_version})." >&2
return 1
fi
return 0
}
# Check that the SHA versions in deps.sh matches the git submodules.
test_deps_version() {
while IFS= read -r line; do
if [[ "${line:0:10}" != "[submodule" ]]; then
continue
fi
line="${line#[submodule \"}"
line="${line%\"]}"
local varname=$(tr '[:lower:]' '[:upper:]' <<< "${line}")
varname="${varname/\//_}"
if ! grep -F "${varname}=" deps.sh >/dev/null; then
# Ignoring submodule not in deps.sh
continue
fi
local deps_sha=$(grep -F "${varname}=" deps.sh | cut -f 2 -d '"')
[[ -n "${deps_sha}" ]]
local git_sha=$(git ls-tree -r HEAD "${line}" | cut -f 1 | cut -f 3 -d ' ')
if [[ "${deps_sha}" != "${git_sha}" ]]; then
cat >&2 <<EOF
deps.sh: SHA for project ${line} is at ${deps_sha} but the git submodule is at
${git_sha}. Please update deps.sh
If you did not intend to change the submodule's SHA value, it is possible that
you accidentally included this change in your commit after a rebase or checkout
without running "git submodule --init". To revert the submodule change run from
the top checkout directory:
git -C ${line} checkout ${deps_sha}
git commit --amend ${line}
EOF
return 1
fi
done < .gitmodules
}
# Make sure that all the Fields objects are fuzzed directly.
test_fuzz_fields() {
local ret=0
# List all the classes of the form "ClassName : public Fields".
# This doesn't catch class names that are too long to fit.
local field_classes=$( git ls-files |
grep -E '\.(cc|h)' | grep -v 'test\.cc$' |
xargs grep -h -o -E '\b[^ ]+ : public Fields' | cut -f 1 -d ' ')
local classname
for classname in ${field_classes}; do
if [ ! -e "$classname" ]; then
continue
fi
if ! grep -E "\\b${classname}\\b" tools/fields_fuzzer.cc >/dev/null; then
cat >&2 <<EOF
tools/fields_fuzzer.cc: Class ${classname} not found in the fields_fuzzer.
EOF
ret=1
fi
done
return $ret
}
# Test that we don't use %n in C++ code to avoid using it in printf and scanf.
# This test is not very precise but in cases where "module n" is needed we would
# normally have "% n" instead of "%n". Using %n is not allowed in Android 10+.
test_percent_n() {
local ret=0
local f
for f in $(git ls-files | grep -E '(\.cc|\.cpp|\.h)$'); do
if [ ! -e "$f" ]; then
continue
fi
if grep -i -H -n -E '%h*n' "$f" >&2; then
echo "Don't use \"%n\"." >&2
ret=1
fi
done
return ${ret}
}
main() {
local ret=0
cd "${MYDIR}"
if ! git rev-parse >/dev/null 2>/dev/null; then
echo "Not a git checkout, skipping bash_test"
return 0
fi
IFS=$'\n'
for f in $(declare -F); do
local test_name=$(echo "$f" | cut -f 3 -d ' ')
# Runs all the local bash functions that start with "test_".
if [[ "${test_name}" == test_* ]]; then
echo "Test ${test_name}: Start"
if ${test_name}; then
echo "Test ${test_name}: PASS"
else
echo "Test ${test_name}: FAIL"
ret=1
fi
fi
done
return ${ret}
}
main "$@"

1519
media/libjxl/src/ci.sh Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
# Original issue:
# * https://gitlab.kitware.com/cmake/cmake/-/issues/23021#note_1098733
#
# For reference:
# * https://gcc.gnu.org/wiki/Atomic/GCCMM
#
# riscv64 specific:
# * https://lists.debian.org/debian-riscv/2022/01/msg00009.html
#
# ATOMICS_FOUND - system has c++ atomics
# ATOMICS_LIBRARIES - libraries needed to use c++ atomics
include(CheckCXXSourceCompiles)
# RISC-V only has 32-bit and 64-bit atomic instructions. GCC is supposed
# to convert smaller atomics to those larger ones via masking and
# shifting like LLVM, but its a known bug that it does not. This means
# anything that wants to use atomics on 1-byte or 2-byte types needs
# -latomic, but not 4-byte or 8-byte (though it does no harm).
set(atomic_code
"
#include <atomic>
#include <cstdint>
std::atomic<uint8_t> n8 (0); // riscv64
std::atomic<uint64_t> n64 (0); // armel, mipsel, powerpc
int main() {
++n8;
++n64;
return 0;
}")
check_cxx_source_compiles("${atomic_code}" ATOMICS_LOCK_FREE_INSTRUCTIONS)
if(ATOMICS_LOCK_FREE_INSTRUCTIONS)
set(ATOMICS_FOUND TRUE)
set(ATOMICS_LIBRARIES)
else()
set(CMAKE_REQUIRED_LIBRARIES "-latomic")
check_cxx_source_compiles("${atomic_code}" ATOMICS_IN_LIBRARY)
set(CMAKE_REQUIRED_LIBRARIES)
if(ATOMICS_IN_LIBRARY)
set(ATOMICS_LIBRARY atomic)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Atomics DEFAULT_MSG ATOMICS_LIBRARY)
set(ATOMICS_LIBRARIES ${ATOMICS_LIBRARY})
unset(ATOMICS_LIBRARY)
else()
if(Atomics_FIND_REQUIRED)
message(FATAL_ERROR "Neither lock free instructions nor -latomic found.")
endif()
endif()
endif()
unset(atomic_code)

View file

@ -0,0 +1,85 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
set(brlibs brotlicommon brotlienc brotlidec)
find_package(PkgConfig QUIET)
if (PkgConfig_FOUND)
foreach(brlib IN ITEMS ${brlibs})
string(TOUPPER "${brlib}" BRPREFIX)
pkg_check_modules("PC_${BRPREFIX}" lib${brlib})
endforeach()
endif()
find_path(BROTLI_INCLUDE_DIR
NAMES brotli/decode.h
HINTS ${PC_BROTLICOMMON_INCLUDEDIR} ${PC_BROTLICOMMON_INCLUDE_DIRS}
)
foreach(brlib IN ITEMS ${brlibs})
string(TOUPPER "${brlib}" BRPREFIX)
find_library(${BRPREFIX}_LIBRARY
NAMES ${${BRPREFIX}_NAMES} ${brlib}
HINTS ${PC_${BRPREFIX}_LIBDIR} ${PC_${BRPREFIX}_LIBRARY_DIRS}
)
if (${BRPREFIX}_LIBRARY AND NOT TARGET ${brlib})
if(CMAKE_VERSION VERSION_LESS "3.13.5")
add_library(${brlib} INTERFACE IMPORTED GLOBAL)
set_property(TARGET ${brlib} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BROTLI_INCLUDE_DIR})
target_link_libraries(${brlib} INTERFACE ${${BRPREFIX}_LIBRARY})
set_property(TARGET ${brlib} PROPERTY INTERFACE_COMPILE_OPTIONS ${PC_${BRPREFIX}_CFLAGS_OTHER})
add_library(${brlib}-static INTERFACE IMPORTED GLOBAL)
set_property(TARGET ${brlib}-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${BROTLI_INCLUDE_DIR})
target_link_libraries(${brlib}-static INTERFACE ${${BRPREFIX}_LIBRARY})
set_property(TARGET ${brlib}-static PROPERTY INTERFACE_COMPILE_OPTIONS ${PC_${BRPREFIX}_CFLAGS_OTHER})
else()
add_library(${brlib} INTERFACE IMPORTED GLOBAL)
target_include_directories(${brlib}
INTERFACE ${BROTLI_INCLUDE_DIR})
target_link_libraries(${brlib}
INTERFACE ${${BRPREFIX}_LIBRARY})
target_link_options(${brlib}
INTERFACE ${PC_${BRPREFIX}_LDFLAGS_OTHER})
target_compile_options(${brlib}
INTERFACE ${PC_${BRPREFIX}_CFLAGS_OTHER})
# TODO(deymo): Remove the -static library versions, this target is
# currently needed by brunsli.cmake. When importing it this way, the
# brotli*-static target is just an alias.
add_library(${brlib}-static ALIAS ${brlib})
endif()
endif()
endforeach()
if (BROTLICOMMON_FOUND AND BROTLIENC_FOUND AND BROTLIDEC_FOUND)
set(Brotli_FOUND ON)
else ()
set(Brotli_FOUND OFF)
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Brotli
FOUND_VAR Brotli_FOUND
REQUIRED_VARS
BROTLI_INCLUDE_DIR
BROTLICOMMON_LIBRARY
BROTLIENC_LIBRARY
BROTLIDEC_LIBRARY
VERSION_VAR Brotli_VERSION
)
mark_as_advanced(
BROTLI_INCLUDE_DIR
BROTLICOMMON_LIBRARY
BROTLIENC_LIBRARY
BROTLIDEC_LIBRARY
)
if (Brotli_FOUND)
set(Brotli_LIBRARIES ${BROTLICOMMON_LIBRARY} ${BROTLIENC_LIBRARY} ${BROTLIDEC_LIBRARY})
set(Brotli_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR})
endif()

View file

@ -0,0 +1,66 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
find_package(PkgConfig QUIET)
if (PkgConfig_FOUND)
pkg_check_modules(PC_HWY QUIET libhwy)
set(HWY_VERSION ${PC_HWY_VERSION})
endif ()
find_path(HWY_INCLUDE_DIR
NAMES hwy/highway.h
HINTS ${PC_HWY_INCLUDEDIR} ${PC_HWY_INCLUDE_DIRS}
)
find_library(HWY_LIBRARY
NAMES ${HWY_NAMES} hwy
HINTS ${PC_HWY_LIBDIR} ${PC_HWY_LIBRARY_DIRS}
)
if (HWY_INCLUDE_DIR AND NOT HWY_VERSION)
if (EXISTS "${HWY_INCLUDE_DIR}/hwy/highway.h")
file(READ "${HWY_INCLUDE_DIR}/hwy/highway.h" HWY_VERSION_CONTENT)
string(REGEX MATCH "#define HWY_MAJOR +([0-9]+)" _dummy "${HWY_VERSION_CONTENT}")
set(HWY_VERSION_MAJOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define +HWY_MINOR +([0-9]+)" _dummy "${HWY_VERSION_CONTENT}")
set(HWY_VERSION_MINOR "${CMAKE_MATCH_1}")
string(REGEX MATCH "#define +HWY_PATCH +([0-9]+)" _dummy "${HWY_VERSION_CONTENT}")
set(HWY_VERSION_PATCH "${CMAKE_MATCH_1}")
set(HWY_VERSION "${HWY_VERSION_MAJOR}.${HWY_VERSION_MINOR}.${HWY_VERSION_PATCH}")
endif ()
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(HWY
FOUND_VAR HWY_FOUND
REQUIRED_VARS HWY_LIBRARY HWY_INCLUDE_DIR
VERSION_VAR HWY_VERSION
)
if (HWY_LIBRARY AND NOT TARGET hwy)
add_library(hwy INTERFACE IMPORTED GLOBAL)
if(CMAKE_VERSION VERSION_LESS "3.13.5")
set_property(TARGET hwy PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${HWY_INCLUDE_DIR})
target_link_libraries(hwy INTERFACE ${HWY_LIBRARY})
set_property(TARGET hwy PROPERTY INTERFACE_COMPILE_OPTIONS ${PC_HWY_CFLAGS_OTHER})
else()
target_include_directories(hwy INTERFACE ${HWY_INCLUDE_DIR})
target_link_libraries(hwy INTERFACE ${HWY_LIBRARY})
target_link_options(hwy INTERFACE ${PC_HWY_LDFLAGS_OTHER})
target_compile_options(hwy INTERFACE ${PC_HWY_CFLAGS_OTHER})
endif()
endif()
mark_as_advanced(HWY_INCLUDE_DIR HWY_LIBRARY)
if (HWY_FOUND)
set(HWY_LIBRARIES ${HWY_LIBRARY})
set(HWY_INCLUDE_DIRS ${HWY_INCLUDE_DIR})
endif ()

View file

@ -0,0 +1,59 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
find_package(PkgConfig QUIET)
if (PkgConfig_FOUND)
pkg_check_modules(PC_LCMS2 QUIET libLCMS2)
set(LCMS2_VERSION ${PC_LCMS2_VERSION})
endif ()
find_path(LCMS2_INCLUDE_DIR
NAMES lcms2.h
HINTS ${PC_LCMS2_INCLUDEDIR} ${PC_LCMS2_INCLUDE_DIRS}
)
find_library(LCMS2_LIBRARY
NAMES ${LCMS2_NAMES} lcms2 liblcms2 lcms-2 liblcms-2
HINTS ${PC_LCMS2_LIBDIR} ${PC_LCMS2_LIBRARY_DIRS}
)
if (LCMS2_INCLUDE_DIR AND NOT LCMS_VERSION)
file(READ ${LCMS2_INCLUDE_DIR}/lcms2.h LCMS2_VERSION_CONTENT)
string(REGEX MATCH "#define[ \t]+LCMS_VERSION[ \t]+([0-9]+)[ \t]*\n" LCMS2_VERSION_MATCH ${LCMS2_VERSION_CONTENT})
if (LCMS2_VERSION_MATCH)
string(SUBSTRING ${CMAKE_MATCH_1} 0 1 LCMS2_VERSION_MAJOR)
string(SUBSTRING ${CMAKE_MATCH_1} 1 2 LCMS2_VERSION_MINOR)
set(LCMS2_VERSION "${LCMS2_VERSION_MAJOR}.${LCMS2_VERSION_MINOR}")
endif ()
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LCMS2
FOUND_VAR LCMS2_FOUND
REQUIRED_VARS LCMS2_LIBRARY LCMS2_INCLUDE_DIR
VERSION_VAR LCMS2_VERSION
)
if (LCMS2_LIBRARY AND NOT TARGET lcms2)
add_library(lcms2 INTERFACE IMPORTED GLOBAL)
if(CMAKE_VERSION VERSION_LESS "3.13.5")
set_property(TARGET lcms2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${LCMS2_INCLUDE_DIR})
target_link_libraries(lcms2 INTERFACE ${LCMS2_LIBRARY})
set_property(TARGET lcms2 PROPERTY INTERFACE_COMPILE_OPTIONS ${PC_LCMS2_CFLAGS_OTHER})
else()
target_include_directories(lcms2 INTERFACE ${LCMS2_INCLUDE_DIR})
target_link_libraries(lcms2 INTERFACE ${LCMS2_LIBRARY})
target_link_options(lcms2 INTERFACE ${PC_LCMS2_LDFLAGS_OTHER})
target_compile_options(lcms2 INTERFACE ${PC_LCMS2_CFLAGS_OTHER})
endif()
endif()
mark_as_advanced(LCMS2_INCLUDE_DIR LCMS2_LIBRARY)
if (LCMS2_FOUND)
set(LCMS2_LIBRARIES ${LCMS2_LIBRARY})
set(LCMS2_INCLUDE_DIRS ${LCMS2_INCLUDE_DIR})
endif ()

View file

@ -0,0 +1,83 @@
jpeg-xl (0.7) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.7.
-- JPEG XL Maintainers <jpegxl@google.com> Mon, 08 Aug 2022 14:43:58 +0000
jpeg-xl (0.6) unstable; urgency=medium
* Bump JPEG XL version to 0.6.
-- JPEG XL Maintainers <jpegxl@google.com> Fri, 10 Sep 2021 16:08:17 +0200
jpeg-xl (0.5.0) unstable; urgency=medium
* Bump JPEG XL version to 0.5.0.
-- JPEG XL Maintainers <jpegxl@google.com> Thu, 12 Aug 2021 23:49:40 +0200
jpeg-xl (0.3.7) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.7.
-- Sami Boukortt <sboukortt@google.com> Mon, 29 Mar 2021 12:14:20 +0200
jpeg-xl (0.3.6) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.6.
-- Sami Boukortt <sboukortt@google.com> Thu, 25 Mar 2021 17:40:58 +0100
jpeg-xl (0.3.5) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.5.
-- Sami Boukortt <sboukortt@google.com> Tue, 23 Mar 2021 15:20:44 +0100
jpeg-xl (0.3.4) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.4.
-- Sami Boukortt <sboukortt@google.com> Tue, 16 Mar 2021 12:13:59 +0100
jpeg-xl (0.3.3) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.3.
-- Sami Boukortt <sboukortt@google.com> Fri, 5 Mar 2021 19:15:26 +0100
jpeg-xl (0.3.2) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.2.
-- Alex Deymo <deymo@google.com> Fri, 12 Feb 2021 21:00:12 +0100
jpeg-xl (0.3.1) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.1.
-- Alex Deymo <deymo@google.com> Tue, 09 Feb 2021 09:48:43 +0100
jpeg-xl (0.3) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.3.
-- Alex Deymo <deymo@google.com> Wed, 27 Jan 2021 22:36:32 +0100
jpeg-xl (0.2) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.2.
-- Alex Deymo <deymo@google.com> Wed, 23 Nov 2020 20:42:10 +0100
jpeg-xl (0.1) UNRELEASED; urgency=medium
* JPEG XL format release candidate.
-- Alex Deymo <deymo@google.com> Fri, 13 Nov 2020 17:42:24 +0100
jpeg-xl (0.0.2-1) UNRELEASED; urgency=medium
* Initial debian package.
-- Alex Deymo <deymo@google.com> Tue, 27 Oct 2020 15:27:59 +0100

View file

@ -0,0 +1 @@
10

View file

@ -0,0 +1,88 @@
Source: jpeg-xl
Maintainer: JPEG XL Maintainers <jpegxl@google.com>
Section: misc
Priority: optional
Standards-Version: 3.9.8
Build-Depends:
asciidoc,
cmake,
debhelper (>= 9),
libbrotli-dev,
libgdk-pixbuf-2.0-dev | libgdk-pixbuf2.0-dev,
libgif-dev,
libgimp2.0-dev,
libgmock-dev,
libgoogle-perftools-dev,
libgtest-dev,
libhwy-dev (>= 0.15.0),
libjpeg-dev,
libopenexr-dev,
libpng-dev,
libwebp-dev,
pkg-config,
xdg-utils,
xmlto,
Homepage: https://github.com/libjxl/libjxl
Rules-Requires-Root: no
Package: jxl
Architecture: any
Section: utils
Depends: ${misc:Depends}, ${shlibs:Depends}
Description: JPEG XL Image Coding System - "JXL" (command line utility)
The JPEG XL Image Coding System (ISO/IEC 18181) is a lossy and
lossless image compression format. It has a rich feature set and is
particularly optimized for responsive web environments, so that
content renders well on a wide range of devices. Moreover, it includes
several features that help transition from the legacy JPEG format.
.
This package installs the command line utilities.
Package: libjxl-dev
Architecture: any
Section: libdevel
Depends: libjxl (= ${binary:Version}), ${misc:Depends}
libhwy-dev,
Description: JPEG XL Image Coding System - "JXL" (development files)
The JPEG XL Image Coding System (ISO/IEC 18181) is a lossy and
lossless image compression format. It has a rich feature set and is
particularly optimized for responsive web environments, so that
content renders well on a wide range of devices. Moreover, it includes
several features that help transition from the legacy JPEG format.
.
This package installs development files.
Package: libjxl
Architecture: any
Multi-Arch: same
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Pre-Depends: ${misc:Pre-Depends}
Description: JPEG XL Image Coding System - "JXL" (shared libraries)
The JPEG XL Image Coding System (ISO/IEC 18181) is a lossy and
lossless image compression format. It has a rich feature set and is
particularly optimized for responsive web environments, so that
content renders well on a wide range of devices. Moreover, it includes
several features that help transition from the legacy JPEG format.
.
This package installs shared libraries.
Package: libjxl-gdk-pixbuf
Architecture: any
Multi-Arch: same
Section: libs
Depends: ${shlibs:Depends}, ${misc:Depends}
Pre-Depends: ${misc:Pre-Depends}
Description: JPEG XL Plugin for gdk-pixbuf
This package installs the required files for reading JPEG XL files in
GTK applications.
Package: libjxl-gimp-plugin
Architecture: any
Multi-Arch: same
Section: graphics
Depends: ${shlibs:Depends}, ${misc:Depends}
Pre-Depends: ${misc:Pre-Depends}
Enhances: gimp
Description: JPEG XL Import and Export Plugin for GIMP
This is a plugin for GIMP version 2.10.x to import and export JPEG XL images.

View file

@ -0,0 +1,194 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: jpeg-xl
Files: *
Copyright: 2020 the JPEG XL Project
License: BSD-3-clause
Files: third_party/sjpeg/*
Copyright: 2017 Google, Inc
License: Apache-2.0
Files: third_party/skcms/*
Copyright: 2018 Google Inc.
License: BSD-3-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
.
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Files: testdata/external/pngsuite/*
Copyright: Willem van Schaik, 1996, 2011
License: PngSuite License
See http://www.schaik.com/pngsuite/ for details.
.
Permission to use, copy, modify and distribute these images for any
purpose and without fee is hereby granted.
Files: testdata/external/raw.pixls/*
Copyright: their respective owners listed in https://raw.pixls.us/
License: CC0-1.0
Files: testdata/external/wesaturate/*
Copyright: their respective owners listed in https://www.wesaturate.com/
License: CC0-1.0
Files: testdata/external/wide-gamut-tests/
Copyright: github.com/codelogic/wide-gamut-tests authors.
License: Apache-2.0
License: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
.
On Debian systems, the complete text of the Apache License, Version 2
can be found in "/usr/share/common-licenses/Apache-2.0".
License: CC0
Creative Commons Zero v1.0 Universal
.
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL
SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT
RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS"
BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS
DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS
LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE
INFORMATION OR WORKS PROVIDED HEREUNDER.
.
Statement of Purpose
.
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
.
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use
and efforts of others.
.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with
a Work (the "Affirmer"), to the extent that he or she is an owner of
Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to
the Work and publicly distribute the Work under its terms, with knowledge of
his or her Copyright and Related Rights in the Work and the meaning and
intended legal effect of CC0 on those rights.
.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national implementations
thereof.
.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer
makes the Waiver for the benefit of each member of the public at large and
to the detriment of Affirmer's heirs and successors, fully intending that
such Waiver shall not be subject to revocation, rescission, cancellation,
termination, or any other legal or equitable action to disrupt the quiet
enjoyment of the Work by the public as contemplated by Affirmer's express
Statement of Purpose.
.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the
Waiver is so judged Affirmer hereby grants to each affected person a
royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "License"). The License
shall be deemed effective as of the date CC0 was applied by Affirmer to the
Work. Should any part of the License for any reason be judged legally
invalid or ineffective under applicable law, such partial invalidity or
ineffectiveness shall not invalidate the remainder of the License, and in
such case Affirmer hereby affirms that he or she will not (i) exercise any
of his or her remaining Copyright and Related Rights in the Work or (ii)
assert any associated claims and causes of action with respect to the Work,
in either case contrary to Affirmer's express Statement of Purpose.
.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied, statutory or
otherwise, including without limitation warranties of title,
merchantability, fitness for a particular purpose, non infringement, or the
absence of latent or other defects, accuracy, or the present or absence of
errors, whether or not discoverable, all to the greatest extent permissible
under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
.
For more information, please see:
http://creativecommons.org/publicdomain/zero/1.0/>

View file

@ -0,0 +1,3 @@
usr/bin/*
usr/share/man/man1/cjxl.1
usr/share/man/man1/djxl.1

View file

@ -0,0 +1,4 @@
usr/include/jxl/*.h
usr/lib/*/*.a
usr/lib/*/*.so
usr/lib/*/pkgconfig/*.pc

View file

@ -0,0 +1,3 @@
usr/lib/*/gdk-pixbuf-*/*/loaders/*
usr/share/mime/packages/image-jxl.xml
usr/share/thumbnailers/jxl.thumbnailer

View file

@ -0,0 +1 @@
usr/lib/gimp

View file

@ -0,0 +1 @@
usr/lib/*/libjxl*.so.*

View file

@ -0,0 +1,17 @@
#!/usr/bin/make -f
include /usr/share/dpkg/pkg-info.mk
%:
dh $@ --buildsystem=cmake
override_dh_auto_configure:
# TODO(deymo): Remove the DCMAKE_BUILD_TYPE once builds without NDEBUG
# are as useful as Release builds.
dh_auto_configure -- \
-DJPEGXL_VERSION=$(DEB_VERSION) \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DJPEGXL_FORCE_SYSTEM_GTEST=ON \
-DJPEGXL_FORCE_SYSTEM_BROTLI=ON \
-DJPEGXL_FORCE_SYSTEM_HWY=ON \
-DJPEGXL_ENABLE_PLUGINS=ON

View file

@ -0,0 +1 @@
3.0 (quilt)

84
media/libjxl/src/deps.sh Normal file
View file

@ -0,0 +1,84 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# This file downloads the dependencies needed to build JPEG XL into third_party.
# These dependencies are normally pulled by gtest.
set -eu
MYDIR=$(dirname $(realpath "$0"))
# Git revisions we use for the given submodules. Update these whenever you
# update a git submodule.
THIRD_PARTY_BROTLI="35ef5c554d888bef217d449346067de05e269b30"
THIRD_PARTY_HIGHWAY="22e3d7276f4157d4a47586ba9fd91dd6303f441a"
THIRD_PARTY_SKCMS="64374756e03700d649f897dbd98c95e78c30c7da"
THIRD_PARTY_SJPEG="868ab558fad70fcbe8863ba4e85179eeb81cc840"
THIRD_PARTY_ZLIB="cacf7f1d4e3d44d871b605da3b647f07d718623f"
THIRD_PARTY_LIBPNG="a40189cf881e9f0db80511c382292a5604c3c3d1"
# Download the target revision from GitHub.
download_github() {
local path="$1"
local project="$2"
local varname=`echo "$path" | tr '[:lower:]' '[:upper:]'`
varname="${varname/\//_}"
local sha
eval "sha=\${${varname}}"
local down_dir="${MYDIR}/downloads"
local local_fn="${down_dir}/${sha}.tar.gz"
if [[ -e "${local_fn}" && -d "${MYDIR}/${path}" ]]; then
echo "${path} already up to date." >&2
return 0
fi
local url
local strip_components=0
if [[ "${project:0:4}" == "http" ]]; then
# "project" is a googlesource.com base url.
url="${project}${sha}.tar.gz"
else
# GitHub files have a top-level directory
strip_components=1
url="https://github.com/${project}/tarball/${sha}"
fi
echo "Downloading ${path} version ${sha}..." >&2
mkdir -p "${down_dir}"
curl -L --show-error -o "${local_fn}.tmp" "${url}"
mkdir -p "${MYDIR}/${path}"
tar -zxf "${local_fn}.tmp" -C "${MYDIR}/${path}" \
--strip-components="${strip_components}"
mv "${local_fn}.tmp" "${local_fn}"
}
main() {
if git -C "${MYDIR}" rev-parse; then
cat >&2 <<EOF
Current directory is a git repository, downloading dependencies via git:
git submodule update --init --recursive
EOF
git -C "${MYDIR}" submodule update --init --recursive --depth 1 --recommend-shallow
return 0
fi
# Sources downloaded from a tarball.
download_github third_party/brotli google/brotli
download_github third_party/highway google/highway
download_github third_party/sjpeg webmproject/sjpeg
download_github third_party/skcms \
"https://skia.googlesource.com/skcms/+archive/"
download_github third_party/zlib madler/zlib
download_github third_party/libpng glennrp/libpng
echo "Done."
}
main "$@"

View file

@ -0,0 +1,29 @@
/* This document is meant for Doxygen use only. If you are looking for the API
* documentation generate it with `./ci.sh release` and look under the
* build/html directory.
*
* This file documents all the groups and defines the order in which they appear
* in Doxygen. Define the @defgroup commands here and use @addtogroup anywhere
* else.
*/
/**
@defgroup libjxl JPEG XL library (libjxl)
@brief The main JPEG XL decoder / encoder library.
@addtogroup libjxl
@{
@defgroup libjxl_decoder JPEG XL Decoder
@defgroup libjxl_encoder JPEG XL Encoder
@defgroup libjxl_common JPEG XL common definitions
@defgroup libjxl_butteraugli Butteraugli metric
@}
@defgroup libjxl_threads JPEG XL Multi-thread library (libjxl_threads)
@brief Additional multi-threaded implementations for the parallel runner.
*/

View file

@ -0,0 +1,82 @@
# Benchmarking
For speed benchmarks on single images in single or multi-threaded decoding
`djxl` can print decoding speed information. See `djxl --help` for details
on the decoding options and note that the output image is optional for
benchmarking purposes.
For a more comprehensive comparison of compression density between multiple
options, the tool `benchmark_xl` can be used (see below).
## Benchmarking with benchmark_xl
We recommend `build/tools/benchmark_xl` as a convenient method for reading
images or image sequences, encoding them using various codecs (jpeg jxl png
webp), decoding the result, and computing objective quality metrics. An example
invocation is:
```bash
build/tools/benchmark_xl --input "/path/*.png" --codec jxl:wombat:d1,jxl:cheetah:d2
```
Multiple comma-separated codecs are allowed. The characters after : are
parameters for the codec, separated by colons, in this case specifying maximum
target psychovisual distances of 1 and 2 (higher implies lower quality) and
the encoder effort (see below). Other common parameters are `r0.5` (target
bitrate 0.5 bits per pixel) and `q92` (quality 92, on a scale of 0-100, where
higher is better). The `jxl` codec supports the following additional parameters:
Speed: `lightning`, `thunder`, `falcon`, `cheetah`, `hare`, `wombat`, `squirrel`,
`kitten`, `tortoise` control the encoder effort in ascending order. This also
affects memory usage: using lower effort will typically reduce memory consumption
during encoding.
* `lightning` and `thunder` are fast modes useful for lossless mode (modular).
* `falcon` disables all of the following tools.
* `cheetah` enables coefficient reordering, context clustering, and heuristics
for selecting DCT sizes and quantization steps.
* `hare` enables Gaborish filtering, chroma from luma, and an initial estimate
of quantization steps.
* `wombat` enables error diffusion quantization and full DCT size selection
heuristics.
* `squirrel` (default) enables dots, patches, and spline detection, and full
context clustering.
* `kitten` optimizes the adaptive quantization for a psychovisual metric.
* `tortoise` enables a more thorough adaptive quantization search.
Mode: JPEG XL has two modes. The default is Var-DCT mode, which is suitable for
lossy compression. The other mode is Modular mode, which is suitable for lossless
compression. Modular mode can also do lossy compression (e.g. `jxl:m:q50`).
* `m` activates modular mode.
Other arguments to benchmark_xl include:
* `--save_compressed`: save codestreams to `output_dir`.
* `--save_decompressed`: save decompressed outputs to `output_dir`.
* `--output_extension`: selects the format used to output decoded images.
* `--num_threads`: number of codec instances that will independently
encode/decode images, or 0.
* `--inner_threads`: how many threads each instance should use for parallel
encoding/decoding, or 0.
* `--encode_reps`/`--decode_reps`: how many times to repeat encoding/decoding
each image, for more consistent measurements (we recommend 10).
The benchmark output begins with a header:
```
Compr Input Compr Compr Compr Decomp Butteraugli
Method Pixels Size BPP # MP/s MP/s Distance Error p norm BPP*pnorm Errors
```
`ComprMethod` lists each each comma-separated codec. `InputPixels` is the number
of pixels in the input image. `ComprSize` is the codestream size in bytes and
`ComprBPP` the bitrate. `Compr MP/s` and `Decomp MP/s` are the
compress/decompress throughput, in units of Megapixels/second.
`Butteraugli Distance` indicates the maximum psychovisual error in the decoded
image (larger is worse). `Error p norm` is a similar summary of the psychovisual
error, but closer to an average, giving less weight to small low-quality
regions. `BPP*pnorm` is the product of `ComprBPP` and `Error p norm`, which is a
figure of merit for the codec (lower is better). `Errors` is nonzero if errors
occurred while loading or encoding/decoding the image.

View file

@ -0,0 +1,171 @@
# Building and Testing
This file describes the building and testing facilities provided by the `ci.sh`
script. It assumes you already have the build environment set up, preferably
Docker (see [instructions](developing_in_docker.md)).
## Basic building
To build the JPEG XL software and run its unit tests, run:
```bash
./ci.sh release
```
## Testing
`./ci.sh` build commands including `release`, `opt`, etc. will also run tests.
You can set the environment variable `SKIP_TEST=1` to skip this.
It is possible to manually run all the tests in parallel in all your CPUs with
the command:
```bash
./ci.sh test
```
It is also possible for faster iteration to run a specific test binary directly.
Tests are run with the `ctest` command and arguments passed to `ci.sh test` are
forwarded to `ctest` with the appropriate environment variables set. For
example, to list all the available tests you can run:
```bash
./ci.sh test -N
```
To run a specific test from the list or actually a set of tests matching a
regular expression you can use `ctest`'s parameter `-R`:
```bash
./ci.sh test -R ^MyPrefixTe
```
That command would run any test whose name that starts with `MyPrefixTe`. For
more options run `ctest --help`, for example, you can pass `-j1` if you want
to run only one test at a time instead of our default of multiple tests in
parallel.
## Other commands
Running `./ci.sh` with no parameters shows a list of available commands. For
example, you can run `opt` for optimized developer builds with symbols or
`debug` for debug builds which do not have NDEBUG defined and therefore include
more runtime debug information.
### Cross-compiling
To compile the code for an architecture different than the one you are running
you can pass a
[toolchain file](https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html)
to cmake if you have one for your target, or you can use the `BUILD_TARGET`
environment variable in `./ci.sh`. For some targets such the Windows targets
`ci.sh` sets up extra environment variables that are needed for testing.
This assumes that you already have a cross-compiling environment set up and the
library dependencies are already installed for the target architecture as well
which is tricky to do in some cases. For this reason we provide a [jpegxl docker
container](developing_in_docker.md) already configured to cross-compile and run
for other architectures which is also used in our continuous integration
pipeline.
For example, to compile for the `aarch64-linux-gnu` target triplet you can run:
```bash
BUILD_TARGET=aarch64-linux-gnu ./ci.sh release
```
Whenever using a `BUILD_TARGET` or even a custom `BUILD_DIR` these variables
must be set for **every call** to `ci.sh` even calls to `ci.sh test`, for which
we recommend exporting them in your shell session, for example:
```bash
export BUILD_TARGET=x86_64-w64-mingw32 BUILD_DIR=build-foobar
```
### Format checks (lint)
```bash
./ci.sh lint
```
Linter checks will verify that the format of your patch conforms to the project
style. For this, we run clang-format only on the lines that were changed by
your commits.
If your local git branch is tracking `origin/master` and you landed a few
commits in your branch, running this lint command will check all the changes
made from the common ancestor with `origin/master` to the latest changes,
including uncommitted changes. The output of the program will show the patch
that should be applied to fix your commits. You can apply these changes with the
following command from the base directory of the git checkout:
```bash
./ci.sh lint | patch -p1
```
### Programming errors (tidy)
```bash
./ci.sh tidy
```
clang-tidy is a tool to check common programming errors in C++, and other valid
C++ constructions that are discouraged by the style guide or otherwise dangerous
and may constitute a bug.
To run clang-tidy on the files changed by your changes you can run `./ci.sh
tidy`. Note that this will report all the problems encountered in any file that
was modified by one of your commits, not just on the lines that your commits
modified.
### Address Sanitizer (asan)
```bash
./ci.sh asan
```
ASan builds allow to check for invalid address usages, such as use-after-free.
To perform these checks, as well as other undefined behavior checks we only need
to build and run the unittests with ASan enabled which can be easily achieved
with the command above. If you want to have the ASan build files separated from
your regular `build/` directory to quickly switch between asan and regular
builds, you can pass the build directory target as follows:
```bash
BUILD_DIR=build-asan ./ci.sh asan
```
### Memory Sanitizer (msan)
MSan allows to check for invalid memory accesses at runtime, such as using an
uninitialized value which likely means that there is a bug. To run these checks,
a specially compiled version of the project and tests is needed.
For building with MSan, you need to build a version of libc++ with
`-fsanitize=memory` so we can link against it from the MSan build. Also, having
an `llvm-symbolizer` installed is very helpful to obtain stack traces that
include the symbols (functions and line numbers). To install `llvm-symbolizer`
on a Debian-based system run:
```bash
sudo apt install llvm # or llvm-7, etc for a specific version.
```
To install a version of libc++ compiled with `-fsanitize=memory` you can use the
`./ci.sh msan_install` command helper. This will download, compile and install
libc++ and libc++abi in the `${HOME}/.msan` directory to be used later.
After this is set up, you can build the project using the following command:
```bash
./ci.sh msan
```
This command by default uses the `build` directory to store the cmake and object
files. If you want to have a separate build directory configured with msan you
can for example call:
```bash
BUILD_DIR=build-msan ./ci.sh msan
```

View file

@ -0,0 +1,83 @@
# Building WASM artifacts
This file describes the building and testing of JPEG XL
[Web Assembly](https://webassembly.org/) bundles and wrappers.
These instructions assume an up-to-date Debian/Ubuntu system.
For other platforms, or if you encounter any difficulties,
please instead use the [Docker container](developing_in_docker.md).
For the sake of simplicity, it is considered, that the following environment
variables are set:
* `OPT` - path to the directory containing additional software;
the `emsdk` directory with the Emscripten SDK should reside there;
in the Docker container (mentioned above) this should be `/opt`
## Requirements
[CMake](https://cmake.org/) is used as a build system. To install it, follow
[Debian build instructions](developing_in_debian.md).
[Emscripten SDK](https://emscripten.org/) is required for building
WebAssembly artifacts. To install it, follow the
[Download and Install](https://emscripten.org/docs/getting_started/downloads.html)
guide:
```bash
cd $OPT
# Get the emsdk repo.
git clone https://github.com/emscripten-core/emsdk.git
# Enter that directory.
cd emsdk
# Download and install the latest SDK tools.
./emsdk install latest
# Make the "latest" SDK "active" for the current user. (writes ~/.emscripten file)
./emsdk activate latest
```
[v8](https://v8.dev/) is a JavaScript engine used for running tests.
v8 has better WASM SIMD support than NodeJS 14.
To install it use [JSVU](https://github.com/GoogleChromeLabs/jsvu):
```bash
# Fix some v8 version know to work well.
export v8_version="8.5.133"
# Install JSVU
npm install jsvu -g
# Trick JSVU to install to specific location instead of user "home".
# Note: "os" flag should match the host OS.
HOME=$OPT jsvu --os=linux64 "v8@${v8_version}"
# Link v8 binary to version-indepentent path.
ln -s "$OPT/.jsvu/v8-${v8_version}" "$OPT/.jsvu/v8"
```
In [Docker container](developing_in_docker.md)
CMake, Emscripten SDK and V8 are pre-installed.
## Building and testing the project
```bash
# Setup EMSDK and other environment variables. In practice EMSDK is set to be
# $OPT/emsdk.
source $OPT/emsdk/emsdk_env.sh
# Specify JS engine binary
export V8=$OPT/.jsvu/v8
# If building using the jpegxl-builder docker container prefix the following commands with:
# CMAKE_FLAGS=-I/usr/wasm32/include
# ex. CMAKE_FLAGS=-I/usr/wasm32/include BUILD_TARGET=wasm32 emconfigure ./ci.sh release
# Either build with regular WASM:
BUILD_TARGET=wasm32 emconfigure ./ci.sh release
# or with SIMD WASM:
BUILD_TARGET=wasm32 ENABLE_WASM_SIMD=1 emconfigure ./ci.sh release
```

View file

@ -0,0 +1,68 @@
# Color Management
[TOC]
<!--*
# Document freshness: For more information, see go/fresh-source.
freshness: { owner: 'janwas' reviewed: '2019-02-01' }
*-->
## Why
The vast majority of web images are still sRGB. However, wide-gamut material is
increasingly being produced (photography, cinema, 4K). Screens covering most of
the Adobe RGB gamut are readily available and some also cover most of DCI P3
(iPhone, Pixel2) or even BT.2020.
Currently, after a camera records a very saturated red pixel, most raw
processors would clip it to the rather small sRGB gamut before saving as JPEG.
In keeping with our high-quality goal, we prevent such loss by allowing wider
input color spaces.
## Which color space
Even wide gamuts could be expressed relative to the sRGB primaries, but the
resulting coordinates may be outside the valid 0..1 range. Surprisingly, such
'unbounded' coordinates can be passed through color transforms provided the
transfer functions are expressed as parametric functions (not lookup tables).
However, most image file formats (including PNG and PNM) lack min/max metadata
and thus do not support unbounded coordinates.
Instead, we need a larger working gamut to ensure most pixel coordinates are
within bounds and thus not clipped. However, larger gamuts result in lower
precision/resolution when using <= 16 bit encodings (as opposed to 32-bit float
in PFM). BT.2100 or P3 DCI appear to be good compromises.
## CMS library
Transforms with unbounded pixels are desirable because they reduce round-trip
error in tests. This requires parametric curves, which are only supported for
the common sRGB case in ICC v4 profiles. ArgyllCMS does not support v4. The
other popular open-source CMS is LittleCMS. It is also used by color-managed
editors (Krita/darktable), which increases the chances of interoperability.
However, LCMS has race conditions and overflow issues that prevent fuzzing. We
will later switch to the newer skcms. Note that this library does not intend to
support multiProcessElements, so HDR transfer functions cannot be represented
accurately. Thus in the long term, we will probably migrate away from ICC
profiles entirely.
## Which viewer
On Linux, Krita and darktable support loading our PNG output images and their
ICC profile.
## How to compress/decompress
### Embedded ICC profile
- Create an 8-bit or 16-bit PNG with an iCCP chunk, e.g. using darktable.
- Pass it to `cjxl`, then `djxl` with no special arguments. The decoded output
will have the same bit depth (can override with `--output_bit_depth`) and
color space.
### Images without metadata (e.g. HDR)
- Create a PGM/PPM/PFM file in a known color space.
- Invoke `cjxl` with `-x color_space=RGB_D65_202_Rel_Lin` (linear 2020). For
details/possible values, see color_encoding.cc `Description`.
- Invoke `djxl` as above with no special arguments.

View file

@ -0,0 +1,57 @@
# Developing in Debian
These instructions assume an up-to-date Debian/Ubuntu system.
For other platforms, please instead use the following:
* [Developing in Docker](developing_in_docker.md).
* [Cross Compiling for Windows with Crossroad](developing_with_crossroad.md).
## Minimum build dependencies
Apart from the dependencies in `third_party`, some of the tools use external
dependencies that need to be installed on your system first:
```bash
sudo apt install cmake clang doxygen g++ extra-cmake-modules \
libgif-dev libjpeg-dev ninja-build libgoogle-perftools-dev
```
Make sure your default `clang` compiler is at least version 6 by running
```bash
clang --version
```
If it still shows an old version despite having, for example, `clang-7` installed, you need
to update the default `clang` compiler. On Debian-based systems run:
```bash
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
```
Optionally, to compile some of the extra tool support and tests you can install
the following packages:
```bash
sudo apt install qtbase5-dev libqt5x11extras5-dev libwebp-dev libgimp2.0-dev \
libopenexr-dev libgtest-dev libgmock-dev libbenchmark-dev libbenchmark-tools
```
For the lint/coverage commands, you will also need additional packages:
```bash
sudo apt install clang-format clang-tidy curl parallel gcovr
```
## Building
The `libjxl` project uses CMake to build. We provide a script that simplifies the
invocation. To build and test the project, run
```bash
./ci.sh opt
```
This writes binaries to `build/tools` and runs unit tests. More information
on [build modes and testing](building_and_testing.md) is available.

View file

@ -0,0 +1,114 @@
# Developing in Docker
Docker allows software to be run in a packaged container, isolated from the
host system. This allows code to be run in a standard environment instead
of dealing with different build environments during development. It also
simplifies resolving external dependencies by including them in the automated
setup of the container environment.
## Set up the container
You can read installation instructions and download Docker for your
operating system at [Get Docker](https://docs.docker.com/get-docker/).
The image used by our builders is an Ubuntu Bionic image with all the
required dependencies and build tools installed. You can pull this image
from `gcr.io/jpegxl/jpegxl-builder` using the following command:
```bash
sudo docker pull gcr.io/jpegxl/jpegxl-builder
```
To use the Docker image you can run the following command:
```bash
sudo docker run -it --rm \
--user $(id -u):$(id -g) \
-v $HOME/jpeg-xl:/jpeg-xl -w /jpeg-xl \
gcr.io/jpegxl/jpegxl-builder bash
```
This creates and runs a container that will be deleted after you exit the
terminal (`--rm` flag).
The `-v` flag is to map the directory containing your jpeg-xl checkout in your
host (assumed to be at `$HOME/jpeg-xl`) to a directory inside the container at
/jpeg-xl. Since the container is accessing the host folder directly,
changes made on the host will will be seen immediately in the container,
and vice versa.
On OSX, the path must be one of those shared and whitelisted with Docker. $HOME
(which is a subdirectory of /Users/) is known to work with the factory-default
settings of Docker.
On OSX, you may ignore the warning that Docker "cannot find name for group ID".
This warning may also appear on some Linux computers.
On Windows, you can run the following from the jpeg-xl directory obtained from
Gitlab:
```bash
docker run -u root:root -it --rm -v %cd%:/jpeg-xl -w /jpeg-xl \
gcr.io/jpegxl/jpegxl-builder
```
## Basic building
Inside the Docker container, you can compile everything and run unit tests.
We need to specify `clang-7` because the default `clang` compiler is
not installed on the image.
```bash
CC=clang-7 CXX=clang++-7 ./ci.sh opt
```
This writes binaries to `/jpeg-xl/build/tools` and runs unit tests.
More information on [build modes and testing](building_and_testing.md) is
available.
If a `build` directory already exists and was configured for a different
compiler, `cmake` will complain. This can be avoided by renaming or removing
the existing `build` directory or setting the `BUILD_DIR` environment variable.
## Cross-compiling environments (optional)
We have installed the required cross-compiling tools in the main Docker image
`jpegxl-builder`. This allows compiling for other architectures, such as arm.
Tests will be emulated under `qemu`.
The Docker container has several `qemu-*-static` binaries (such as
`qemu-aarch64-static`) that emulate other architectures on x86_64. These
binaries are automatically used when running foreign architecture programs
in the container only if `binfmt` is installed and configured on the *host*
to use binaries from `/usr/bin` . This is the default location on Ubuntu/Debian.
You need to install both `binfmt-support` and `qemu-user-static` on the host,
since `binfmt-support` configures only `binfmt` signatures of architectures
that are installed. If these are configured elsewhere on other distributions,
you can symlink them to `/usr/bin/qemu-*-static` inside the Docker container.
To install binfmt support in your Ubuntu host run *outside* the container:
```bash
sudo apt install binfmt-support qemu-user-static
```
Then to cross-compile and run unit tests execute the following commands:
```bash
export BUILD_TARGET=aarch64-linux-gnu CC=clang-7 CXX=clang++-7
./ci.sh release
```
The `BUILD_TARGET=aarch64-linux-gnu` environment variable tells the `ci.sh`
script to cross-compile for that target. This also changes the default
`BUILD_DIR` to `build-aarch64` since you never want to mix them with the `build`
of your host. You can also explicitly set a `BUILD_DIR` environment variable
that will be used instead. The list of supported `BUILD_TARGET` values for this
container is:
* *the empty string* (for native x86_64 support)
* aarch64-linux-gnu
* arm-linux-gnueabihf
* i686-linux-gnu
* x86_64-w64-mingw32 (for Windows builds)

View file

@ -0,0 +1,357 @@
# Developing in GitHub
This document describes the development steps related to handling the git
repository.
If you are new to GitHub, there's a nice [quickstart
guide](https://docs.github.com/en/github/getting-started-with-github/quickstart)
on GitHub explaining the basics.
## Initial setup
You need to perform this set up at least once if you haven't use GitHub before.
Read through the quickstart guide [Set up
Git](https://docs.github.com/en/github/getting-started-with-github/set-up-git)
page to get your git up and running. You will need to Fork a repository next.
After that "Life of a Pull Request" describes the common everyday workflows.
### Configure your SSH access
The easiest way to configure access to your Github repository is to use SSH
keys. For that you need an SSH private and public key, ideally a strong one. You
can use different keys for different sites if you want. In this example, we will
create one for using in GitHub only.
Create the `~/.ssh/id_rsa_github` file executing the following. (Here and
elsewhere, {{X}} are placeholders for your email/username)
```bash
ssh-keygen -t rsa -b 4096 -C "{{EMAIL}}" -f ~/.ssh/id_rsa_github
```
Go to your [SSH and GPG keys](https://github.com/settings/keys) settings and
paste the contents of your *public key* (the one ending in `.pub`), that would
be the output of this command:
```bash
cat ~/.ssh/id_rsa_github.pub
```
To use a specific key when SSHing to the github.com domain, you can add this
snippet of config to your .ssh/config file executing the following.
```bash
cat >> ~/.ssh/config <<EOF
Host github.com
Hostname github.com
IdentityFile ~/.ssh/id_rsa_github
IdentitiesOnly yes
EOF
```
The `IdentitiesOnly yes` part forces to only use the provided IdentityFile when
talking to GitHub.
### Fork your private copy
The JPEG XL code is located in [this repo](https://github.com/libjxl/libjxl).
The normal developer workflow in GitHub involves creating your own fork of a
repository and uploading your own changes there. From your own copy you can
request merges *to* the upstream repository directly, there's no need to create
a branch in the upstream repository.
[Fork the
repository](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo)
in GitHub to create your own copy of the repository in GitHub. You can then
propose to include changes in the main repository via a Pull Request.
Once you are done you should have your repository at
https://<!-- not a link -->github.com<!-- not a link -->/*{{USERNAME}}*/libjxl
where {{USERNAME}} denotes your GitHub username.
### Checkout the JPEG XL code from GitHub
To get the source code on your computer you need to "clone" it. There are two
repositories at play here, the upstream repository (`libjxl/lbjxl`) and your
fork (`{{USERNAME}}/libjxl`). You will be normally fetching new changes from
the upstream repository and push changes to your fork. Getting your changes from
your fork to the upstream repository is done through the Web interface, via Pull
Requests.
The [Fork a
repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo)
goes in great detail, but uses the git remote names `upstream` for the shared
upstream repository and `origin` for your work. This guide proposes an
alternative naming scheme, used in the examples below.
In this guide `origin` is the upstream shared repository and `myfork` is your
fork. You can use any other name for your fork if you want. Use the following
commands to set things up, replacing `{{USERNAME}}` with your GitHub username:
```bash
git clone git https://github.com/libjxl/libjxl --recursive
cd libjxl
git remote set-url --push origin git@github.com:{{USERNAME}}/libjxl.git
git remote add myfork git@github.com:{{USERNAME}}/libjxl.git
git remote -vv
```
These commands did three things:
* Created the repository with `origin` as the upstream remote,
* Changed the "push" URL to point to your fork, and
* Create a new remote pointing to your fork.
The last step is optional. Since the "fetch" URL of `origin` points to the
shared repository and the "push" URL points to your fork, fetching from `origin`
always gets the latest changes from the upstream repository regardless of the
contents of your fork.
Having a second origin called `myfork` is only useful if you need to download
pending changes from your fork from a different computer. For example, if you
work on multiple computers, each one with this setup, you can push to your
fork from one, and then fetch from `myfork` from another computer to get those.
# Life of a Pull Request
The general [GitHub flow
guide](https://docs.github.com/en/github/getting-started-with-github/github-flow)
applies to sending Pull Requests to this project.
All the commands here assume you are in a git checkout as setup here.
### Sync to the latest version
```bash
git fetch origin
```
The last upstream version is now on `origin/main` and none of your local
branches have been modified by this command.
### Start a new branch
To start a new change you need a local branch. Each branch will represent a list
of individual commits which can then be requested to be merged as a single merge
request. So in general one branch is one code review, but each branch can have
multiple individual commits in it.
```bash
git checkout origin/main -b mybranch
```
This will create a new branch `mybranch` tracking `origin/main`. A branch can
track any remove or local branch, which is used by some tools. Running `git
branch -vv` will show all the branches you have have, what are they tracking and
how many commits are ahead or behind. If you create a branch without tracking
any other, you can add or change the tracking branch of the current branch
running `git branch --set-upstream-to=...`.
### Add changes to your branch
Follow any of the many online tutorials, for example
[The basics](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository)
chapter from the https://git-scm.com/doc website is a good starting guide.
Create, change or delete files and do a git commit with a message.
The commit message is required. A commit message should follow the 50/72 rule:
* First line is 50 characters or less.
* Then a blank line.
* Remaining text should be wrapped at 72 characters.
The first line should identify your commit, since that's what most tools will
show to the user. First lines like "Some fixes" are not useful. Explain what the
commit contains and why.
We follow the [Google C++ Coding
Style](https://google.github.io/styleguide/cppguide.html). A
[clang-format](https://clang.llvm.org/docs/ClangFormat.html) configuration
file is available to automatically format your code, you can invoke it with
the `./ci.sh lint` helper tool.
Read the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information about
contributing to libjxl.
### Upload your changes for review
The first step is a local review of your changes to see what will you be sending
for review. `gitg` is a nice Gtk UI for reviewing your local changes, or `tig`
for similar ncurses console-based interface. Otherwise, from the terminal you
can run:
```bash
git branch -vv
```
To show the current status of your local branches. In particular, since your
branch is tracking origin/main (as seen in the output) git will tell you that
you are one commit ahead of the tracking branch.
```
* mybranch e74ae1a [origin/main: ahead 1] Improved decoding speed by 40%
```
It is a good idea before uploading to sync again with upstream (`git fetch
origin`) and then run `git branch -vv` to check whether there are new changes
upstream. If that is the case, you will see a "behind" flag in the output:
```
* mybranch e74ae1a [origin/main: ahead 1, behind 2] Improved decoding speed by 40%
```
To sync your changes on top of the latest changes in upstream you need to
rebase:
```bash
git rebase
```
This will by default rebase your current branch changes on top of the tracking
branch. In this case, this will try to apply the current commit on top of the
latest origin/main (which has 2 more commits than the ones we have in our
branch) and your branch will now include that. There could be conflicts that you
have to deal with. A shortcut to do both fetch and rebase is to run `git pull
-r`, where the `-r` stands for "rebase" and will rebase the local commits on top
of the remote ones.
Before uploading a patch, make sure your patch conforms to the
[contributing guidelines](../CONTRIBUTING.md) and it
[builds and passes tests](building_and_testing.md).
Once you are ready to send your branch for review, upload it to *your* fork:
```bash
git push origin mybranch
```
This will push your local branch "mybranch" to a remote in your fork called
"mybranch". The name can be anything, but keep in mind that it is public. A link
to the URL to create a merge request will be displayed.
```
Enumerating objects: 627, done.
Counting objects: 100% (627/627), done.
Delta compression using up to 56 threads
Compressing objects: 100% (388/388), done.
Writing objects: 100% (389/389), 10.71 MiB | 8.34 MiB/s, done.
Total 389 (delta 236), reused 0 (delta 0)
emote:
remote: Create a pull request for 'mybranch' on GitHub by visiting:
remote: https://github.com/{{USERNAME}}/libjxl/pull/new/mybranch
remote:
To github.com:{{USERNAME}}/libjxl.git
* [new branch] mybranch -> mybranch
```
### Updating submodules
The repository uses submodules for external library dependencies in
third_party. Each submodule points to a particular external commit of the
external repository by the hash code of that external commit. Just like
regular source code files, this hash code is part of the current branch and
jpeg xl commit you have checked out.
When changing branches or when doing `git rebase`, git will unfortunately
*not* automatically set those hashes to the ones of the branch or jpeg xl
commit you changed to nor set the source files of the third_party submodules
to the new state. That is, even though git will have updated the jpeg xl
source code files on your disk to the new ones, it will leave the submodule
hashes and the files in third_party in your workspace to the ones they were
before you changed branches. This will show up in a git diff because this
is seen as a change compared to the branch you switched to. The git diff shows
the difference in hash codes (as if you are changing to the old ones), it does
not show changes in files inside the third_party directory.
This mismatch can cause at least two problems:
*) the jpeg xl codebase may not compile due to third_party library version
mismatch if e.g. API changed or a submodule was added/removed.
*) when using `commit -a` your commit, which may be a technical change
unrelated to submodule changes, will unintentionally contain a change to the
submodules hash code, which is undesired unless you actually want to change
the version of third_party libraries.
To resolve this, the submodules must be updated manually with
the following command after those actions (at least when the submodules
changed):
```
git submodule update --init --recursive
```
Here, the init flag ensures new modules get added when encessary and the
recursive flag is required for the submodules depending on other submodules.
If you checkout a different branch, you can spot that submodules changed
when it shows a message similar to this:
```
M third_party/brotli
M third_party/lcms
```
If you do a rebase you may end up in a harder to solve situation, where
`git submodule update --init --recursive` itself fails with errors such as:
```
Unable to checkout '35ef5c554d888bef217d449346067de05e269b30' in submodule path 'third_party/brotli'
```
In that case, you can use the force flag:
```
git submodule update --init --recursive --force
```
### Iterating changes in your merge request
To address reviewer changes you need to amend the local changes in your branch
first. Make the changes you need in your commit locally by running `git commit
--amend file1 file2 file3 ...` or `git commit --amend -a` to amend all the
changes from all the staged files.
Once you have the new version of the "mybranch" branch to re-upload, you need to
force push it to the same branch in your fork. Since you are pushing a different
version of the same commit (as opposed to another commit on top of the existing
ones), you need to force the operation to replace the old version.
```bash
git push origin mybranch --force
```
The merge request should now be updated with the new changes.
### Merging your changes
We use "rebase" as a merge policy, which means that there a no "merge" commits
(commits with more than one parent) but instead only a linear history of
changes.
It is possible that other changes where added to the main branch since the last
time you rebased your changes. These changes could create a conflict with your
Pull Request, if so you need to `git fetch`, `git rebase` and push again your
changes which need to go through the continuous integration workflow again to
verify that all the tests pass again after including the latest changes.
### Trying locally a pending Pull Request
If you want to review in your computer a pending pull request proposed by
another user you can fetch the merge request commit with the following command,
replacing `NNNN` with the pull request number:
```bash
git fetch origin refs/pull/NNNN/head
git checkout FETCH_HEAD
```
The first command will add to your local git repository the remote commit for
the pending pull request and store a temporary reference called `FETCH_HEAD`.
The second command then checks out that reference. From this point you can
review the files in your computer, create a local branch for this FETCH_HEAD or
build on top of it.

View file

@ -0,0 +1,168 @@
# Developing for Windows with MSYS2
[MSYS2](https://www.msys2.org/) ("minimal system 2") is a software distribution and a development platform based on MinGW and Cygwin. It provides a Unix-like environment to build code on Windows. These instructions were written with a 64-bit instance of Windows 10 running on a VM. They may also work on native instances of Windows and other versions of Windows.
## Build Environments
MSYS2 provides multiple development [environments](https://www.msys2.org/docs/environments/). By convention, they are referred to in uppercase. They target slightly different platforms, runtime libraries, and compiler toolchains. For example, to build for 32-bit Windows, use the MINGW32 environment. For interoperability with Visual Studio projects, use the UCRT64 environment.
Since all of the build environments are built on top of the MSYS environment, **all updates and package installation must be done from within the MSYS environment**. After making any package changes, `exit` all MSYS2 terminals and restart the desired build-environment. This reminder is repeated multiple times throughout this guide.
* **MINGW32:** To compile for 32-bit Windows (on 64-bit Windows), use packages from the `mingw32` group. Package names are prefixed with `mingw-w64-i686`. The naming scheme may be different on the 32-bit version of MSYS2.
* **MINGW64:** This is the primary environment to building for 64-bit Windows. It uses the older MSVCRT runtime, which is widely available across Windows systems. Package names are prefixed with `mingw-w64-x86_64`.
* **UCRT64:** The Universal C Runtime (UCRT) is used by recent versions of Microsoft Visual Studio. It ships by default with Windows 10. For older versions of Windows, it must be provided with the application or installed by the user. Package names are prefixed with `mingw-w64-ucrt-x86_64`.
* **CLANG64:** Unfortunately, the `gimp` packages are not available for the CLANG64 environment. However, `libjxl` will otherwise build in this environment if the appropriate packages are installed. Packages are prefixed with `mingw-w64-clang-x86_64`.
## Install and Upgrade MSYS2
Download MSYS2 from the homepage. Install at a location without any spaces on a drive with ample free space. After installing the packages used in this guide, MSYS2 used about 15GB of space.
Toward the end of installation, select the option to run MSYS2 now. A command-line window will open. Run the following command, and answer the prompts to update the repository and close the terminal.
```bash
pacman -Syu
```
Now restart the MSYS environment and run the following command to complete updates:
```bash
pacman -Su
```
## Package Management
Packages are organized in groups, which share the build environment name, but in lower case. Then they have name prefixes that indicate which group they belong to. Consider this package search: `pacman -Ss cmake`
```
mingw32/mingw-w64-i686-cmake
mingw64/mingw-w64-x86_64-cmake
ucrt64/mingw-w64-ucrt-x86_64-cmake
clang64/mingw-w64-clang-x86_64-cmake
msys/cmake
```
We can see the organization `group/prefix-name`. When installing packages, the group name is optional.
```bash
pacman -S mingw-w64-x86_64-cmake
```
For tools that need to be aware of the compiler to function, install the package that corresponds with the specific build-environment you plan to use. For `cmake`, install the `mingw64` version. The generic `msys/cmake` will not function correctly because it will not find the compiler. For other tools, the generic `msys` version is adequate, like `msys/git`.
To remove packages, use:
```bash
pacman -Rsc [package-name]
```
## Worst-Case Scenario...
If packages management is done within a build environment other than MSYS, the environment structure will be disrupted and compilation will likely fail. If this happens, it may be necessary to reinstall MSYS2.
1. Rename the `msys64` folder to `msys64.bak`.
2. Use the installer to reinstall MSYS2 to `msys64`.
3. Copy packages from `msys64.bak/var/cache/pacman/pkg/` to the new installation to save download time and bandwidth.
4. Use `pacman` from within the MSYS environment to install and update packages.
5. After successfully building a project, it is safe to delete `msys64.bak`
## The MING64 Environment
Next set up the MING64 environment. The following commands should be run within the MSYS environment. `pacman -S` is used to install packages. The `--needed` argument prevents packages from being reinstalled.
```bash
pacman -S --needed base-devel mingw-w64-x86_64-toolchain
pacman -S git mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja \
mingw-w64-x86_64-gtest mingw-w64-x86_64-giflib \
mingw-w64-x86_64-libpng mingw-w64-x86_64-libjpeg-turbo
```
## Build `libjxl`
Download the source from the libjxl [releases](https://github.com/libjxl/libjxl/releases) page. Alternatively, you may obtain the latest development version with `git`. Run `./deps.sh` to ensure additional third-party dependencies are downloaded.
Start the MINGW64 environment, create a build directory within the source directory, and configure with `cmake`.
```bash
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF \
-DJPEGXL_ENABLE_BENCHMARK=OFF -DJPEGXL_ENABLE_PLUGINS=ON \
-DJPEGXL_ENABLE_MANPAGES=OFF -DJPEGXL_FORCE_SYSTEM_BROTLI=ON \
-DJPEGXL_FORCE_SYSTEM_GTEST=ON ..
```
Check the output to see if any dependencies were missed and need to be installed. Adding `-G Ninja` may be helpful, but on my computer, Ninja was selected by default. Remember that package changes must be done from the MSYS environment. Then exit all MSYS2 terminals and restart the build environment.
If all went well, you may now run `cmake` to build `libjxl`:
```bash
cmake --build .
```
Do not be alarmed by the compiler warnings. They are a caused by differences between gcc/g++ and clang. The build should complete successfully. Then `cjxl`, `djxl`, `jxlinfo`, and others can be run from within the build environment. Moving them into the native Windows environment requires resolving `dll` issues that are beyond the scope of this document.
## The `clang` Compiler
To use the `clang` compiler, install the packages that correspond with the environment you wish to use. Remember to make package changes from within the MSYS environment.
```
mingw-w64-i686-clang
mingw-w64-i686-clang-tools-extra
mingw-w64-i686-clang-compiler-rt
mingw-w64-x86_64-clang
mingw-w64-x86_64-clang-tools-extra
mingw-w64-x86_64-clang-compiler-rt
mingw-w64-ucrt64-x86_64-clang
mingw-w64-ucrt64-x86_64-clang-tools-extra
mingw-w64-ucrt64-x86_64-clang-compiler-rt
```
After the `clang` compiler is installed, 'libjxl' can be built with the `./ci.sh` script.
```bash
./ci.sh opt -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF \
-DJPEGXL_ENABLE_BENCHMARK=OFF -DJPEGXL_ENABLE_MANPAGES=OFF \
-DJPEGXL_FORCE_SYSTEM_BROTLI=ON -DJPEGXL_FORCE_SYSTEM_GTEST=ON
```
On my computer, `doxygen` packages needed to be installed to proceed with building. Use `pacman -Ss doxygen` to find the packages to install.
## The GIMP Plugin
To build the GIMP plugin, install the relevant `gimp` package. This will also install dependencies. Again, perform package management tasks from only the MSYS environment. Then restart the build environment.
```bash
pacman -S mingw-w64-i686-gimp
pacman -S mingw-w64-x86_64-gimp
pacman -S mingw-w64-ucrt-x86_64-gimp
```
If `clang` is installed, you can use the `./ci.sh` script to build. Otherwise, navigate to the build directory to reconfigure and build with `cmake`.
```bash
cd build
rm -r CM*
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF \
-DJPEGXL_ENABLE_BENCHMARK=OFF -DJPEGXL_ENABLE_MANPAGES=OFF \
-DJPEGXL_ENABLE_PLUGINS=ON -DJPEGXL_FORCE_SYSTEM_BROTLI=ON \
-DJPEGXL_FORCE_SYSTEM_GTEST=ON ..
```
The plugin is built statically, so there should be no need to install `dll` files. To try out the plugin:
1. [Download](https://www.gimp.org/downloads/) and install the stable version of GIMP (currently 2.10.24).
2. Create a new folder: `C:\Program Files\GIMP 2\lib\gimp\2.0\plug-ins\file-jxl`
3. Copy `build/plugins/gimp/file-jxl.exe` to the new folder.

View file

@ -0,0 +1,91 @@
# Developing on Windows with Visual Studio 2019
These instructions assume an up-to-date Windows 10 (e.g. build 19041.928) with
**Microsoft Visual Studio 2019** (e.g. Version 16.9.0 Preview 4.0) installed. If
unavailable, please use another build environment:
* [Docker container](developing_in_docker.md)
* [MSYS2 on Windows](developing_in_windows_msys.md)
* [Crossroad on Linux](developing_with_crossroad.md) (cross compilation for Windows)
## Minimum build dependencies
Apart from the dependencies in third_party, some of the tools use external
dependencies that need to be installed in your system first.
Please install [vcpkg](https://vcpkg.readthedocs.io/en/latest/examples/installing-and-using-packages/)
(tested with version 2019.07.18), and use it to install the following libraries:
```
vcpkg install gtest:x64-windows
vcpkg install giflib:x64-windows
vcpkg install libjpeg-turbo:x64-windows
vcpkg install libpng:x64-windows
vcpkg install zlib:x64-windows
```
## Building
From Visual Studio, open the CMakeLists.txt in the JPEG XL root directory.
Right-click the CMakeLists.txt entry in the Folder View of the Solution
Explorer. In the context menu, select CMake Settings. Click on the green plus
to add an x64-Clang configuration and the red minus to remove any non-Clang
configuration (the MSVC compiler is currently not supported). Click on the blue
hyperlink marked "CMakeSettings.json" and an editor will open. Insert the
following text after replacing $VCPKG with the directory where you installed
vcpkg above.
```
{
"configurations": [
{
"name": "x64-Clang-Release",
"generator": "Ninja",
"configurationType": "MinSizeRel",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "-DCMAKE_TOOLCHAIN_FILE=$VCPKG/scripts/buildsystems/vcpkg.cmake",
"buildCommandArgs": "-v",
"ctestCommandArgs": "",
"inheritEnvironments": [ "clang_cl_x64" ],
"variables": [
{
"name": "VCPKG_TARGET_TRIPLET",
"value": "x64-windows",
"type": "STRING"
},
{
"name": "JPEGXL_ENABLE_TCMALLOC",
"value": "False",
"type": "BOOL"
},
{
"name": "BUILD_GMOCK",
"value": "True",
"type": "BOOL"
},
{
"name": "gtest_force_shared_crt",
"value": "True",
"type": "BOOL"
},
{
"name": "JPEGXL_ENABLE_FUZZERS",
"value": "False",
"type": "BOOL"
},
{
"name": "JPEGXL_ENABLE_VIEWERS",
"value": "False",
"type": "BOOL"
}
]
}
]
}
```
The project is now ready for use. To build, simply press F7 (or choose
Build All from the Build menu). This writes binaries to
`out/build/x64-Clang-Release/tools`. The main [README.md](../README.md) explains
how to use the encoder/decoder and benchmark binaries.

View file

@ -0,0 +1,116 @@
# Cross Compiling for Windows with Crossroad
[Crossroad](https://pypi.org/project/crossroad/) is a tool to set up cross-compilation environments on GNU/Linux distributions. These instructions assume a Debian/Ubuntu system. However, they can likely be adapted to other Linux environments. Since Ubuntu can be run on Windows through WSL, these instruction may be useful for developing directly on Windows.
## Install Crossroad
Crossroad requires tools included with `python3-docutils` and `mingw-w64`. They may be installed using:
```bash
sudo aptitude install python3-docutils mingw-w64
```
The `zstandard` python package is also required, but is not available in the repositories. It may be installed using `pip`.
```bash
pip3 install zstandard
```
After the dependencies are installed, crossroad itself maybe installed with `pip`.
```bash
pip3 install crossroad
```
If there are errors while running crossroad, it may need to be downloaded and installed directly using `setup.py`. Instructions are on the crossroad homepage.
## Update Debian Alternatives
Since `libjxl` uses C++ features that require posix threads, the symlinks used by the Debian alternative system need to be updated:
```bash
sudo update-alternatives --config x86_64-w64-mingw32-g++
```
Select the option that indicates `posix` usage. Repeat for `gcc` and `i686`:
```bash
sudo update-alternatives --config x86_64-w64-mingw32-gcc
sudo update-alternatives --config i686-w64-mingw32-gcc
sudo update-alternatives --config i686-w64-mingw32-g++
```
## Create a New Crossroad Project
Crossroad supports the following platforms:
```
native Native platform (x86_64 GNU/Linux)
android-x86 Generic Android/Bionic on x86
android-mips64 Generic Android/Bionic on MIPS64
android-x86-64 Generic Android/Bionic on x86-64
w64 Windows 64-bit
w32 Windows 32-bit
android-arm64 Generic Android/Bionic on ARM64
android-mips Generic Android/Bionic on MIPS
android-arm Generic Android/Bionic on ARM
```
To begin cross compiling for Windows, a new project needs to be created:
```bash
crossroad w64 [project-name]
```
## Install Dependencies
Since the `gimp` development package is required to build the GIMP plugin and also includes most of the packages required by `libjxl`, install it first.
```bash
crossroad install gimp
```
`gtest` and `brotli` are also required.
```bash
crossroad install gtest brotli
```
If any packages are later found to be missing, you may search for them using:
```bash
crossroad search [...]
```
## Build `libjxl`
Download the source from the libjxl [releases](https://github.com/libjxl/libjxl/releases) page. Alternatively, you may obtain the latest development version with `git`. Run `./deps.sh` to ensure additional third-party dependencies are downloaded. Unfortunately, the script `./ci.sh` does not work with Crossroad, so `cmake` will need to be called directly.
Create a build directory within the source directory. If you haven't already, start your crossroad project and run `cmake`:
```bash
mkdir build
cd build
crossroad w64 libjxl
crossroad cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF \
-DJPEGXL_ENABLE_BENCHMARK=OFF -DJPEGXL_ENABLE_MANPAGES=OFF \
-DJPEGXL_ENABLE_PLUGINS=ON -DJPEGXL_FORCE_SYSTEM_BROTLI=ON \
-DJPEGXL_FORCE_SYSTEM_GTEST=ON ..
```
Check the output to see if any dependencies were missed and need to be installed. If all went well, you may now run `cmake` to build `libjxl`:
```bash
cmake --build .
```
## Try out the GIMP Plugin
The plugin is built statically, so there should be no need to install `dll` files. To try out the plugin:
1. [Download](https://www.gimp.org/downloads/) and install the stable version of GIMP (currently 2.10.24).
2. Create a new folder: `C:\Program Files\GIMP 2\lib\gimp\2.0\plug-ins\file-jxl`
3. Copy `build/plugins/gimp/file-jxl.exe` to the new folder.

View file

@ -0,0 +1,284 @@
# JPEG XL Format Overview
This document gives an overview of the JPEG XL file format and codestream,
its features, and the underlying design rationale.
The aim of this document is to provide general insight into the
format capabilities and design, thus helping developers
better understand how to use the `libjxl` API.
## Codestream and File Format
The JPEG XL format is defined in ISO/IEC 18181. This standard consists of
four parts:
* 18181-1: Core codestream
* 18181-2: File format
* 18181-3: Conformance testing
* 18181-4: Reference implementation
### Core codestream
The core codestream contains all the data necessary to decode and display
still image or animation data. This includes basic metadata like image dimensions,
the pixel data itself, colorspace information, orientation, upsampling, etc.
### File format
The JPEG XL file format can take two forms:
* A 'naked' codestream. In this case, only the image/animation data itself is
stored, and no additional metadata can be included. Such a file starts with the
bytes `0xFF0A` (the JPEG marker for "start of JPEG XL codestream").
* An ISOBMFF-based container. This is a box-based container that includes a
JPEG XL codestream box (`jxlc`), and can optionally include other boxes with
additional information, such as Exif metadata. In this case, the file starts with
the bytes `0x0000000C 4A584C20 0D0A870A`.
### Conformance testing
This part of the standard defines precision bounds and test cases for conforming
decoders, to verify that they implement all coding tools correctly and accurately.
### Reference implementation
The `libjxl` software is the reference implementation of JPEG XL.
## Metadata versus Image Data
JPEG XL makes a clear separation between metadata and image data.
Everything that is needed to correctly display an image is
considered to be image data, and is part of the core codestream. This includes
elements that have traditionally been considered 'metadata', such as ICC profiles
and Exif orientation. The goal is to reduce the ambiguity and potential for
incorrect implementations that can be caused by having a 'black box' codestream
that only contains numerical pixel data, requiring applications to figure out how
to correctly interpret the data (i.e. apply color transforms, upsampling,
orientation, blending, cropping, etc.). By including this functionality in the
codestream itself, the decoder can provide output in a normalized way
(e.g. in RGBA, orientation already applied, frames blended and coalesced),
simplifying things and making it less error-prone for applications.
The remaining metadata, e.g. Exif or XMP, can be stored in the container format,
but it does not influence image rendering. In the case of Exif orientation,
this field has to be ignored by applications, since the orientation in the
codestream always takes precedence (and will already have been applied
transparently by the decoder). This means that stripping metadata can be done
without affecting the displayed image.
## Codestream Features
### Color Management
In JPEG XL, images always have a fully defined colorspace, i.e. it is always
unambiguous how to interpret the pixel values. There are two options:
* Pixel data is in a specified (non-XYB) colorspace, and the decoder will produce
a pixel buffer in this colorspace plus an ICC profile that describes that
colorspace. Mathematically lossless encoding can only use this option.
* Pixel data is in the XYB colorspace, which is an absolute colorspace.
In this case, the decoder can produce a pixel buffer directly in a desired
display space like sRGB, Display-P3 or Rec.2100 PQ.
The image header always contains a colorspace; however, its meaning depends on
which of the above two options were used:
* In the first case (non-XYB), the signaled colorspace defines the
interpretation of the pixel data.
* In the second case (XYB), the signaled colorspace is merely a _suggestion_
of a target colorspace to represent the image in, i.e. it is the colorspace
the original image was in, that has a sufficiently wide gamut and a
suitable transfer curve to represent the image data with high fidelity
using a limited bit depth representation.
Colorspaces can be signaled in two ways in JPEG XL:
* CICP-style Enum values: This is a very compact representation that
covers most or all of the common colorspaces. The decoder can convert
XYB to any of these colorspaces without requiring an external color management
library.
* ICC profiles: Arbitrary ICC profiles can also be used, including
CMYK ones. The ICC profile data gets compressed. In this case, external
color management software (e.g. lcms2 or skcms) has to be used for color
conversions.
### Frames
A JPEG XL codestream contains one or more frames. In the case of animation,
these frames have a duration and can be looped (infinitely or a number of times).
Zero-duration frames are possible and represent different layers of the image.
Frames can have a blendmode (Replace, Add, Alpha-blend, Multiply, etc.) and
they can use any previous frame as a base.
They can be smaller than the image canvas, in which case the pixels outside the
crop are copied from the base frame. They can be positioned at an arbitrary
offset from the image canvas; this offset can also be negative and frames can
also be larger than the image canvas, in which case parts of the frame will
be invisible and only the intersection with the image canvas will be shown.
By default, the decoder will blend and coalesce frames, producing only a single
output frame when there are subsequent zero-duration frames, and all output frames
are of the same size (the size of the image canvas) and have either no duration
(in case of a still image) or a non-zero duration (in case of animation).
### Pixel Data
Every frame contains pixel data encoded in one of two modes:
* VarDCT mode: In this mode, variable-sized DCT transforms are applied
and the image data is encoded in the form of DCT coefficients. This mode is
always lossy, but it can also be used to losslessly represent an existing
(already lossy) JPEG image, in which case only the DCT8x8 is used.
* Modular mode: In this mode, only integer arithmetic is used, which
enables lossless compression. However, this mode can also be used for lossy
compression. Multiple transformations can be used to improve compression or to
obtain other desirable effects: reversible color transforms (RCTs),
(delta) palette transforms, and a modified non-linear Haar transform
called Squeeze, which facilitates (but does not require) lossy compression
and enables progressive decoding.
Internally, the VarDCT mode uses Modular sub-bitstreams to encode
various auxiliary images, such as the "LF image" (a 1:8 downscaled version
of the image that contains the DC coefficients of DCT8x8 and low-frequency
coefficients of the larger DCT transforms), extra channels besides the
three color channels (e.g. alpha), and weights for adaptive quantization.
In addition, both modes can separately encode additional 'image features' that
are rendered on top of the decoded image:
* Patches: rectangles from a previously decoded frame (which can be a
'hidden' frame that is not displayed but only stored to be referenced later)
can be blended using one of the blendmodes on top of the current frame.
This allows the encoder to identify repeating patterns (such as letters of
text) and encode them only once, using patches to insert the pattern in
multiple spots. These patterns are encoded in a previous frame, making
it possible to add Modular-encoded pixels to a VarDCT-encoded frame or
vice versa.
* Splines: centripetal Catmull-Rom splines can be encoded, with a color
and a thickness that can vary along the arclength of the curve.
Although the current encoder does not use this bitstream feature yet, we
anticipate that it can be useful to complement DCT-encoded data, since
thin lines are hard to represent faithfully using the DCT.
* Noise: luma-modulated synthetic noise can be added to an image, e.g.
to emulate photon noise, in a way that avoids poor compression due to
high frequency DCT coefficients.
Finally, both modes can also optionally apply two filtering methods to
the decoded image, which both have the goal of reducing block artifacts
and ringing:
* Gabor-like transform ('Gaborish'): a small (3x3) blur that gets
applied across block and group boundaries, reducing blockiness. The
encoder applies the inverse sharpening transform before encoding,
effectively getting the benefits of lapped transforms without the
disadvantages.
* Edge-preserving filter ('EPF'): similar to a bilateral filter,
this smoothing filter avoids blurring edges while reducing ringing.
The strength of this filter is signaled and can locally be adapted.
### Groups
In both modes (Modular and VarDCT), the frame data is signaled as
a sequence of groups. These groups can be decoded independently,
and the frame header contains a table of contents (TOC) with bitstream
offsets for the start of each group. This enables parallel decoding,
and also partial decoding of a region of interest or a progressive preview.
In VarDCT mode, all groups have dimensions 256x256 (or smaller at the
right and bottom borders). First the LF image is encoded, also in
256x256 groups (corresponding to 2048x2048 pixels, since this data
corresponds to the 1:8 image). This means there is always a basic
progressive preview available in VarDCT mode.
Optionally, the LF image can be encoded separately in a (hidden)
LF frame, which can itself recursively be encoded in VarDCT mode
and have its own LF frame. This makes it possible to represent huge
images while still having an overall preview that can be efficiently
decoded.
Then the HF groups are encoded, corresponding to the remaining AC
coefficients. The HF groups can be encoded in multiple passes for
more progressive refinement steps; the coefficients of all passes
are added. Unlike JPEG progressive scan scripts, JPEG XL allows
signaling any amount of detail in any part of the image in any pass.
In Modular mode, groups can have dimensions 128x128, 256x256, 512x512
or 1024x1024. If the Squeeze transform was used, the data will
be split in three parts: the Global groups (the top of the Laplacian
pyramid that fits in a single group), the LF groups (the middle part
of the Laplacian pyramid that corresponds to the data needed to
reconstruct the 1:8 image) and the HF groups (the base of the Laplacian
pyramid), where the HF groups are again possibly encoded in multiple
passes (up to three: one for the 1:4 image, one for the 1:2 image,
and one for the 1:1 image).
In case of a VarDCT image with extra channels (e.g. alpha), the
VarDCT groups and the Modular groups are interleaved in order to
allow progressive previews of all the channels.
The default group order is to encode the LF and HF groups in
scanline order (top to bottom, left to right), but this order
can be permuted arbitrarily. This allows, for example, a center-first
ordering or a saliency-based ordering, causing the bitstream
to prioritize progressive refinements in a different way.
## File Format Features
Besides the image data itself (stored in the `jxlc` codestream box),
the optional container format allows storing additional information.
## Metadata
Three types of metadata can be included in a JPEG XL container:
* Exif (`Exif`)
* XMP (`xml `)
* JUMBF (`jumb`)
This metadata can contain information about the image, such as copyright
notices, GPS coordinates, camera settings, etc.
If it contains rendering-impacting information (such as Exif orientation),
the information in the codestream takes precedence.
## Compressed Metadata
The container allows the above metadata to be stored either uncompressed
(e.g. plaintext XML in the case of XMP) or by Brotli-compression.
In the latter case, the box type is `brob` (Brotli-compressed Box) and
the first four bytes of the box contents define the actual box type
(e.g. `xml `) it represents.
## JPEG Bitstream Reconstruction Data
JPEG XL can losslessly recompress existing JPEG files.
The general design philosophy still applies in this case:
all the image data is stored in the codestream box, including the DCT
coefficients of the original JPEG image and possibly an ICC profile or
Exif orientation.
In order to allow bit-identical reconstruction of the original JPEG file
(not just the image but the actual file), additional information is needed,
since the same image data can be encoded in multiple ways as a JPEG file.
The `jbrd` box (JPEG Bitstream Reconstruction Data) contains this information.
Typically it is relatively small. Using the image data from the codestream,
the JPEG bitstream reconstruction data, and possibly other metadata boxes
that were present in the JPEG file (Exif/XMP/JUMBF), the exact original
JPEG file can be reconstructed.
This box is not needed to display a recompressed JPEG image; it is only
needed to reconstruct the original JPEG file.
## Frame Index
The container can optionally store a `jxli` box, which contains an index
of offsets to keyframes of a JPEG XL animation. It is not needed to display
the animation, but it does facilitate efficient seeking.
## Partial Codestream
The codestream can optionally be split into multiple `jxlp` boxes;
conceptually, this is equivalent to a single `jxlc` box that contains the
concatenation of all partial codestream boxes.
This makes it possible to create a file that starts with
the data needed for a progressive preview of the image, followed by
metadata, followed by the remaining image data.

View file

@ -0,0 +1,184 @@
# Fuzzing
Fuzzing is a technique to find potential bugs by providing randomly generated
invalid inputs. To detect potential bugs such as programming errors we use
fuzzing in combination with ASan (Address Sanitizer), MSan (Memory Sanitizer),
UBSan (Undefined Behavior Sanitizer) and asserts in the code. An invalid input
will likely produce a decoding error (some API function returning error), which
is absolutely not a problem, but what it should not do is access memory out of
bounds, use uninitialized memory or hit a false assert condition.
## Automated Fuzzing with oss-fuzz
libjxl fuzzing is integrated into [oss-fuzz](https://github.com/google/oss-fuzz)
as the project `libjxl`. oss-fuzz regularly runs the fuzzers on the `main`
branch and reports bugs into their bug tracker which remains private until the
bugs are fixed in main.
## Fuzzer targets
There are several fuzzer executable targets defined in the `tools/` directory
to fuzz different parts of the code. The main one is `djxl_fuzzer`, which uses
the public C decoder API to attempt to decode an image. The fuzzer input is not
directly the .jxl file, the last few bytes of the fuzzer input are used to
decide *how* will the API be used (if preview is requested, the pixel format
requested, if the .jxl input data is provided altogether, etc) and the rest of
the fuzzer input is provided as the .jxl file to the decoder. Some bugs might
reproduce only if the .jxl input is decoded in certain way.
The remaining fuzzer targets execute a specific portion the codec that might be
easier to fuzz independently from the whole codec.
## Reproducing fuzzer bugs
A fuzzer target, like `djxl_fuzzer` accepts as a parameter one or more files
that will be used as inputs. This runs the fuzzer program in test-only mode
where no new inputs are generated and only the provided files are tested. This
is the easiest way to reproduce a bug found by the fuzzer using the generated
test case from the bug report.
oss-fuzz uses a specific compiler version and flags, and it is built using
Docker. Different compiler versions will have different support for detecting
certain actions as errors, so we want to reproduce the build from oss-fuzz as
close as possible. To reproduce the build as generated by oss-fuzz there are a
few helper commands in `ci.sh` as explained below.
### Generate the gcr.io/oss-fuzz/libjxl image
First you need the ossfuzz libjxl builder image. This is the base oss-fuzz
builder image with a few dependencies installed. To generate it you need to
check out the oss-fuzz project and build it:
```bash
git clone https://github.com/google/oss-fuzz.git ~/oss-fuzz
cd ~/oss-fuzz
sudo infra/helper.py build_image libjxl
```
This will create the `gcr.io/oss-fuzz/libjxl` docker image. You can check if it
was created verifying that it is listed in the output of the `sudo docker image
ls` command.
### Build the fuzzer targets with oss-fuzz
To build the fuzzer targets from the current libjxl source checkout, use the
`./ci.sh ossfuzz_msan` command for MSan, `./ci.sh ossfuzz_asan` command for ASan
or `./ci.sh ossfuzz_ubsan` command for UBSan. All the `JXL_ASSERT` and
`JXL_DASSERT` calls are enabled in all the three modes. These ci.sh helpers will
reproduce the oss-fuzz docker call to build libjxl mounting the current source
directory into the Docker container. Ideally you will run this command in a
different build directory separated from your regular builds.
For example, for MSan builds run:
```bash
BUILD_DIR=build-fuzzmsan ./ci.sh ossfuzz_msan
```
After this, the fuzzer program will be generated in the build directory like
for other build modes: `build-fuzzmsan/tools/djxl_fuzzer`.
### Iterating changes with oss-fuzz builds
After modifying the source code to fix the fuzzer-found bug, or to include more
debug information, you can rebuild only a specific fuzzer target to save on
rebuilding time and immediately run the test case again. For example, for
rebuilding and testing only `djxl_fuzzer` in MSan mode we can run:
```bash
BUILD_DIR=build-fuzzmsan ./ci.sh ossfuzz_msan djxl_fuzzer && build-fuzzmsan/tools/djxl_fuzzer path/to/testcase.bin
```
When MSan and ASan fuzzers fail they will print a stack trace at the point where
the error occurred, and some related information. To make these these stack
traces useful we need to convert the addresses to function names and source file
names and lines, which is done with the "symbolizer". For UBSan to print a stack
trace we need to set the `UBSAN_OPTIONS` environment variables when running the
fuzzer.
Set the following environment variables when testing the fuzzer binaries. Here
`clang` should match the compiler version used by the container, you can pass a
different compiler version in the following example by first installing the
clang package for that version outside the container and using `clang-NN`
(for example `clang-11`) instead of `clang` in the following commands:
```bash
symbolizer=$($(realpath $(which clang)) -print-prog-name=llvm-symbolizer)
export MSAN_SYMBOLIZER_PATH="${symbolizer}"
export UBSAN_SYMBOLIZER_PATH="${symbolizer}"
export ASAN_SYMBOLIZER_PATH="${symbolizer}"
export ASAN_OPTIONS=detect_leaks=1
export UBSAN_OPTIONS=print_stacktrace=1
```
Note: The symbolizer binary must be a program called `llvm-symbolizer`, any
other file name will fail. There are normally symlinks already installed with
the right name which the `-print-prog-name` would print.
## Running the fuzzers locally
Running the fuzzer targets in fuzzing mode can be achieved by running them with
no parameters, or better with a parameter with the path to a *directory*
containing a seed of files to use as a starting point. Note that passing a
directory is considered a corpus to use for fuzzing while passing a file is
considered an input to evaluate. Multi-process fuzzing is also supported. For
details about all the fuzzing options run:
```bash
build-fuzzmsan/tools/djxl_fuzzer -help=1
```
## Writing fuzzer-friendly code
Fuzzing on itself can't find programming bugs unless an input makes the program
perform an invalid operation (read/write out of bounds, perform an undefined
behavior operation, etc). You can help the fuzzer find invalid situations by
adding asserts:
* `JXL_ASSERT()` is enabled in Release mode by default. It can be disabled
with `-DJXL_ENABLE_ASSERT=0` but the intention is that it will run for all
the users in released code. If performance of the check is not an issue (like
checks done once per image, once per channel, once per group, etc) a
JXL_ASSERT is appropriate. A failed assert is preferable to an out of bounds
write.
* `JXL_DASSERT()` is only enabled in Debug builds, which includes all the ASan,
MSan and UBSan builds. Performance of these checks is not an issue if kept
within reasonable limits (automated msan/asan test should finish withing 1
hour for example). Fuzzing is more effective when the given input runs
faster, so keep that in mind when adding a complex DASSERT that runs multiple
times per output pixel.
* For MSan builds it is also possible to specify that certain values must be
initialized. This is automatic for values that are used to make decisions
(like when used in an `if` statement or in the ternary operator condition)
but those checks can be made explicit for image data using the
`JXL_CHECK_IMAGE_INITIALIZED(image, rect)` macro. This helps document and
check (only in MSan builds) that a given portion of the image is expected to
be initialized, allowing to catch errors earlier in the process.
## Dealing with use-of-uninitialized memory
In MSan builds it is considered an error to *use* uninitialized memory. Using
the memory normally requires something like a decision / branch based on the
uninitialized value, just running `memcpy()` or simple arithmetic over
uninitialized memory is not a problem. Notably, computing `DemoteTo()`,
`NearestInt()` or similar expressions that create a branch based on the value of
the uninitialized memory will trigger an MSan error.
In libjxl we often run vectorized operations over a series of values, rounding
up to the next multiple of a vector size, thus operating over uninitialized
values past the end of the requested region. These values are part of the image
padding but are not initialized. This behavior would not create an MSan error
unless the processing includes operations like `NearestInt()`. For such cases
the preferred solution is to use `msan::UnpoisonMemory` over the portion of
memory of the last SIMD vector before processing, and then running
`msan::PoisonMemory` over the corresponding value in the output side. A note
including why this is safe to do must be added, for example if the processing
doesn't involve any cross-lane computation.
Initializing padding memory in MSan builds is discouraged because it may hide
bugs in functions that weren't supposed to read from the padding. Initializing
padding memory in all builds, including Release builds, would mitigate the
MSan potential security issue but it would hide the logic bug for a longer time
and potentially incur in a performance hit.

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="891.6" height="836.9" viewBox="0 0 891.6 836.9" overflow="visible"><style>.st0{fill:#5fb4b1}</style><path class="st0" d="M495.7 420.6C533 348.3 570.2 276 607.4 203.7H503.8c-24 46.6-48.1 93.3-72.1 139.9-38.8-46.6-77.6-93.3-116.4-139.9H211.7L392 420.6c-36.5 70.8-73 141.7-109.5 212.5h103.6c23.3-45.2 46.6-90.4 69.8-135.5 37.6 45.2 75.1 90.4 112.7 135.5h103.6c-58.7-70.8-117.6-141.6-176.5-212.5zM153 625.6l.3 2.3.7 2.6c3.8 15.1 8.9 59.5-12 86.3-6.2 8-14.8 14.5-25.6 19.3L53.9 836.9c36.9 0 69.4-5.8 96.5-17.4 25.9-11 47.2-27.2 63.2-48.1 22.2-28.9 33.9-66.6 33.8-109.1 0-24.8-4-44.6-5.7-52L200.8 337h.1v-90.2H0V337h109.8L153 625.6zM738.5 211.2l-.3-2.3-.7-2.6c-3.8-15.1-8.9-59.5 12-86.3 6.2-8 14.8-14.5 25.6-19.3L837.6 0c-36.9 0-69.4 5.8-96.5 17.4-25.9 11-47.2 27.2-63.2 48.1-22.2 28.9-33.9 66.6-33.8 109.1 0 24.8 4 44.6 5.7 52l40.9 273.3h-.1v90.2h200.9v-90.2H781.7l-43.2-288.7z"/><path class="st0" d="M153 625.6l.3 2.3.7 2.6c3.8 15.1 8.9 59.5-12 86.3-6.2 8-14.8 14.5-25.6 19.3L53.9 836.9c36.9 0 69.4-5.8 96.5-17.4 25.9-11 47.2-27.2 63.2-48.1 22.2-28.9 33.9-66.6 33.8-109.1 0-24.8-4-44.6-5.7-52L200.8 337h.1v-90.2H0V337h109.8L153 625.6z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1,102 @@
cjxl(1)
=======
:doctype: manpage
Name
----
cjxl - compress images to JPEG XL
Synopsis
--------
*cjxl* ['options'...] 'input' ['output.jxl']
Description
-----------
`cjxl` compresses an image or animation to the JPEG XL format. It is intended to
spare users the trouble of determining a set of optimal parameters for each
individual image. Instead, for a given target quality, it should provide
consistent visual results across various kinds of images. The defaults have been
chosen to be sensible, so that the following commands should give satisfactory
results in most cases:
----
cjxl input.png output.jxl
cjxl input.jpg output.jxl
cjxl input.gif output.jxl
----
Options
-------
-h::
--help::
Displays the options that `cjxl` supports. On its own, it will only show
basic options. It can be combined with `-v` or `-v -v` to show increasingly
advanced options as well.
-v::
--verbose::
Increases verbosity. Can be repeated to increase it further, and also
applies to `--help`.
-d 'distance'::
--distance='distance'::
The preferred way to specify quality. It is specified in multiples of a
just-noticeable difference. That is, `-d 0` is mathematically lossless,
`-d 1` should be visually lossless, and higher distances yield denser and
denser files with lower and lower fidelity. Lossy sources such as JPEG and
GIF files are compressed losslessly by default, and in the case of JPEG
files specifically, the original JPEG can then be reconstructed bit-for-bit.
For lossless sources, `-d 1` is the default.
-q 'quality'::
--quality='quality'::
Alternative way to indicate the desired quality. 100 is lossless and lower
values yield smaller files. There is no lower bound to this quality
parameter, but positive values should approximately match the quality
setting of libjpeg.
-e 'effort'::
--effort='effort'::
Controls the amount of effort that goes into producing an ``optimal'' file
in terms of quality/size. That is to say, all other parameters being equal,
a higher effort should yield a file that is at least as dense and possibly
denser, and with at least as high and possibly higher quality.
+
Recognized effort settings, from fastest to slowest, are:
+
- 1 or ``lightning''
- 2 or ``thunder''
- 3 or ``falcon''
- 4 or ``cheetah''
- 5 or ``hare''
- 6 or ``wombat''
- 7 or ``squirrel'' (default)
- 8 or ``kitten''
- 9 or ``tortoise''
Examples
--------
----
# Compress a PNG file to a high-quality JPEG XL version.
$ cjxl input.png output.jxl
# Compress it at a slightly lower quality, appropriate for web use.
$ cjxl -d 2 input.png output.jxl
# Compress it losslessly. These are equivalent.
$ cjxl -d 0 input.png lossless.jxl
$ cjxl -q 100 input.png lossless.jxl
# Compress a JPEG file losslessly.
$ cjxl input.jpeg lossless-jpeg.jxl
----
See also
--------
*djxl*(1)

View file

@ -0,0 +1,61 @@
djxl(1)
=======
:doctype: manpage
Name
----
djxl - decompress JPEG XL images
Synopsis
--------
*djxl* ['options'...] 'input.jxl' ['output']
Description
-----------
`djxl` decompresses a JPEG XL image or animation. The output format is determined
by the extension of the output file, which can be `.png`, `.jpg`, `.ppm`, `.pfm`.
If the JPEG XL input file contains an animation, multiple output files will be
produced, with names of the form "'output'-*framenumber*.ext".
Options
-------
-h::
--help::
Displays the options that `djxl` supports.
-j::
--pixels_to_jpeg::
By default, if the input JPEG XL contains a recompressed JPEG file,
djxl reconstructs the exact original JPEG file if the output file has the
`.jpg` (or `.jpeg`) filename extension.
This flag causes the decoder to instead decode the image to pixels and
encode a new (lossy) JPEG in this case.
-q 'quality'::
--jpeg_quality='quality'::
When decoding to `.jpg`, use this output quality. This option implicitly
enables the --pixels_to_jpeg option.
Examples
--------
----
# Decompress a JPEG XL file to PNG
$ djxl input.jxl output.png
# Reconstruct a losslessly-recompressed JPEG file
$ djxl lossless-jpeg.jxl reconstructed.jpeg
----
See also
--------
*cjxl*(1)

View file

@ -0,0 +1,267 @@
# libjxl release process
This guide documents the release process for the libjxl project.
libjxl follows the [semantic versioning](https://semver.org/spec/v2.0.0.html)
specification for released versions. Releases are distributed as tags in the git
repository with the semantic version prefixed by the letter "v". For example,
release version "0.3.7" will have a git tag "v0.3.7".
The public API is explicitly defined as C headers in the `lib/include`
directory, normally installed in your include path. All other headers are
internal API and are not covered by the versioning rules.
## Development and release workflow
New code development is performed on the `main` branch of the git repository.
Pre-submit checks enforce minimum build and test requirements for new patches
that balance impact and test latency, but not all checks are performed before
pull requests are merged. Several slower checks only run *after* the code has
been merged to `main`, resulting in some errors being detected hours after the
code is merged or even days after in the case of fuzzer-detected bugs.
Release tags are cut from *release branches*. Each MAJOR.MINOR version has its
own release branch, for example releases `0.7.0`, `0.7.1`, `0.7.2`, ... would
have tags `v0.7.0`, `v0.7.1`, `v0.7.2`, ... on commits from the `v0.7.x` branch.
`v0.7.x` is a branch name, not a tag name, and doesn't represent a released
version since semantic versioning requires that the PATCH is a non-negative
number. Released tags don't each one have their own release branch, all releases
from the same MAJOR.MINOR version will share the same branch. The first commit
after the branch-off points between the main branch and the release branch
should be tagged with the suffix `-snapshot` and the name of the next
MAJOR.MINOR version, in order to get meaningful ouput for `git --describe`.
The main purpose of the release branch is to stabilize the code before a
release. This involves including fixes to existing bugs but **not** including
new features. New features often come with new bugs which take time to fix, so
having a release branch allows us to cherry-pick *bug fixes* from the `main`
branch into the release branch without including the new *features* from `main`.
For this reason it is important to make small commits in `main` and separate bug
fixes from new features.
After the initial minor release (`MAJOR.MINOR.PATCH`, for example `0.5.0`) the
release branch is used to continue to cherry-pick fixes to be included in a
patch release, for example a version `0.5.1` release. Patch fixes are only meant
to fix security bugs or other critical bugs that can't wait until the next major
or minor release.
Release branches *may* continue to be maintained even after the next minor or
major version has been released to support users that can't update to a newer
minor release. In that case, the same process applies to all the maintained
release branches.
A release branch with specific cherry-picks from `main` means that the release
code is actually a version of the code that never existed in the `main` branch,
so it needs to be tested independently. Pre-submit and post-submit tests run on
release branches (branches matching `v*.*.x`) but extra manual checks should be
performed before a release, specially if multiple bug fixes interact with each
other. Take this into account when selecting which commits to include in a
release. The objective is to have a stable version that can be used without
problems for months. Having the latest improvements at the time the release tag
is created is a non-goal.
## Creating a release branch
A new release branch is needed before creating a new major or minor release,
that is, a new release where the MAJOR or MINOR numbers are increased. Patch
releases, where only the PATCH number is increased, reuse the branch from the
previous release of the same MAJOR and MINOR numbers.
The following instructions assume that you followed the recommended [libjxl git
setup](developing_in_github.md) where `origin` points to the upstream
libjxl/libjxl project, otherwise use the name of your upstream remote repository
instead of `origin`.
The release branch is normally created from the latest work in `main` at the
time the branch is created, but it is possible to create the branch from an
older commit if the current `main` is particularly unstable or includes commits
that were not intended to be included in the release. The following example
creates the branch `v0.5.x` from the latest commit in main (`origin/main`), if a
different commit is to be used then replace `origin/main` with the SHA of that
commit. Change the `v0.5.x` branch name to the one you are creating.
```bash
git fetch origin main
git push git@github.com:libjxl/libjxl.git origin/main:refs/heads/v0.5.x
```
Here we use the SSH URL explicitly since you are pushing to the `libjxl/libjxl`
project directly to a branch there. If you followed the guide `origin` will have
the HTTPS URL which wouldn't normally let you push since you wouldn't be
authenticated. The `v*.*.x` branches are [GitHub protected
branches](https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches)
in our repository, however you can push to a protected branch when *creating* it
but you can't directly push to it after it is created. To include more changes
in the release branch see the "Cherry-picking fixes to a release" section below.
## Creating a merge label
We use GitHub labels in Pull Requests to keep track of the changes that should
be merged into a given release branch. For this purpose create a new label for
each new MAJOR.MINOR release branch called `merge-MAJOR.MINOR`, for example,
`merge-0.5`.
In the [edit labels](https://github.com/libjxl/libjxl/issues/labels) page, click
on "New label" and create the label. Pick your favorite color.
Labels are a GitHub-only concept and are not represented in git. You can add the
label to a Pull Request even after it was merged, whenever it is decided that
the Pull Request should be included in the given release branch. Adding the
label doesn't automatically merge it to the release branch.
## Update the versioning number
The version number (as returned by `JxlDecoderVersion`) in the source code in
`main` must match the semantic versioning of a release. After the release
branch is created the code in `main` will only be included in the next major
or minor release. Right after a release branch update the version targeting the
next release. Artifacts from `main` should include the new (unreleased) version,
so it is important to update it. For example, after the `v0.5.x` branch is
created from main, you should update the version on `main` to `0.6.0`.
To help update it, run this helper command (in a Debian-based system):
```bash
./ci.sh bump_version 0.6.0
```
This will update the version in the following files:
* `lib/CMakeLists.txt`
* `lib/lib.gni`, automatically updated with `tools/build_cleaner.py --update`.
* `debian/changelog` to create the Debian package release with the new version.
Debian changelog shouldn't repeat the library changelog, instead it should
include changes to the packaging scripts.
If there were incompatible API/ABI changes, make sure to also adapt the
corresponding section in
[CMakeLists.txt](https://github.com/libjxl/libjxl/blob/main/lib/CMakeLists.txt#L12).
## Cherry-pick fixes to a release
After a Pull Request that should be included in a release branch has been merged
to `main` it can be cherry-picked to the release branch. Before cherry-picking a
change to a release branch it is important to check that it doesn't introduce
more problems, in particular it should run for some time in `main` to make sure
post-submit tests and the fuzzers run on it. Waiting for a day is a good idea.
Most of the testing is done on the `main` branch, so be careful with what
commits are cherry-picked to a branch. Refactoring code is often not a good
candidate to cherry-pick.
To cherry-pick a single commit to a release branch (in this example to `v0.5.x`)
you can run:
```bash
git fetch origin
git checkout origin/v0.5.x -b merge_to_release
git cherry-pick -x SHA_OF_MAIN_COMMIT
# -x will annotate the cherry-pick with the original SHA_OF_MAIN_COMMIT value.
# If not already mentioned in the original commit, add the original PR number to
# the commit, for example add "(cherry picked from PR #NNNN)".
git commit --amend
```
The `SHA_OF_MAIN_COMMIT` is the hash of the commit as it landed in main. Use
`git log origin/main` to list the recent main commits and their hashes.
Making sure that the commit message on the cherry-picked commit contains a
reference to the original pull request (like `#NNNN`) is important. It creates
an automatic comment in the original pull request notifying that it was
mentioned in another commit, helping keep track of the merged pull requests. If
the original commit was merged with the "Squash and merge" policy it will
automatically contain the pull request number on the first line, if this is not
the case you can amend the commit message of the cherry-pick to include a
reference.
Multiple commits can be cherry-picked and tested at once to save time. Continue
running `git cherry-pick` and `git commit --amend` multiple times for all the
commits you need to cherry-pick, ideally in the same order they were merged on
the `main` branch. At the end you will have a local branch with multiple commits
on top of the release branch.
Finally, upload your changes to *your fork* like normal, except that when
creating a pull request select the desired release branch as a target:
```bash
git push myfork merge_to_release
```
If you used the [guide](developing_in_github.md) `myfork` would be `origin` in
that example. Click on the URL displayed, which will be something like
`https://github.com/mygithubusername/libjxl/pull/new/merge_to_release`
In the "Open a pull request" page, change the drop-down base branch from
"base: main" (the default) to the release branch you are targeting.
The pull request approval and pre-submit rules apply as with normal pull
requests to the `main` branch.
**Important:** When merging multiple cherry-picks use "Rebase and merge" policy,
not the squash one since otherwise you would discard the individual commit
message references from the git history in the release branch.
## Publishing a release
Once a release tag is created it must not be modified, so you need to prepare
the changes before creating the release. Make sure you checked the following:
* The semantic version number in the release branch (see `lib/CMakeLists.txt`)
matches the number you intend to release, all three MAJOR, MINOR and PATCH
should match. Otherwise send a pull request to the release branch to
update them.
* The GitHub Actions checks pass on the release branch. Look for the green
tick next to the last commit on the release branch. This should be visible
on the branch page, for example: https://github.com/libjxl/libjxl/tree/v0.5.x
* There no open fuzzer-found bugs for the release branch. The most effective
way is to [run the fuzzer](fuzzing.md) on the release branch for a while. You
can seed the fuzzer with corpus generated by oss-fuzz by [downloading
it](https://google.github.io/oss-fuzz/advanced-topics/corpora/#downloading-the-corpus),
for example `djxl_fuzzer` with libFuzzer will use:
gs://libjxl-corpus.clusterfuzz-external.appspot.com/libFuzzer/libjxl_djxl_fuzzer
* Manually check that images encode/decode ok.
* Manually check that downstream projects compile with our code. Sometimes
bugs on build scripts are only detected when other projects try to use our
library. For example, test compiling
[imagemagick](https://github.com/ImageMagick/ImageMagick) and Chrome.
A [GitHub
"release"](https://docs.github.com/en/github/administering-a-repository/releasing-projects-on-github/about-releases)
consists of two different concepts:
* a git "tag": this is a name (`v` plus the semantic version number) with a
commit hash associated, defined in the git repository. Most external projects
will use git tags or HTTP URLs to these tags to fetch the code.
* a GitHub "release": this is a GitHub-only concept and is not represented in
git other than by having a git tag associated with the release. A GitHub
release has a given source code commit SHA associated (through the tag) but
it *also* contains release notes and optional binary files attached to the
release.
Releases from the older GitLab repository only have a git tag in GitHub, while
newer releases have both a git tag and a release entry in GitHub.
To publish a release open the [New Release
page](https://github.com/libjxl/libjxl/releases/new) and follow these
instructions:
* Set the "Tag version" as "v" plus the semantic version number.
* Select the "Target" as your release branch. For example for a "v0.7.1"
release tag you should use the "v0.7.x" branch.
* Use the version number as the release title.
* Copy-paste the relevant section of the [CHANGELOG.md](../CHANGELOG.md) to the
release notes into the release notes. Add any other information pertaining
the release itself that are not included in the CHANGELOG.md, although prefer
to include those in the CHANGELOG.md file. You can switch to the Preview tab
to see the results.
* Finally click "Publish release" and go celebrate with the team. 🎉

View file

@ -0,0 +1,65 @@
# JPEG XL software support
This document attempts to keep track of software that is using libjxl to support JPEG XL.
This list serves several purposes:
- thank/acknowledge other projects for integrating jxl support
- point end-users to software that can read/write jxl
- keep track of the adoption status of jxl
- in case of a (security) bug in libjxl, it's easier to see who might be affected and check if they are updated (in case they use static linking)
Please add missing software to this list.
## Browsers
- Chromium: behind a flag since version 91, [tracking bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1178058)
- Firefox: behind a flag since version 90, [tracking bug](https://bugzilla.mozilla.org/show_bug.cgi?id=1539075)
- Safari: not supported, [tracking bug](https://bugs.webkit.org/show_bug.cgi?id=208235)
- Edge: behind a flag since version 91, start with `.\msedge.exe --enable-features=JXL`
- Opera: behind a flag since version 77.
- For all browsers and to track browsers progress see [Can I Use](https://caniuse.com/jpegxl).
## Image libraries
- [ImageMagick](https://imagemagick.org/): supported since 7.0.10-54
- [libvips](https://libvips.github.io/libvips/): supported since 8.11
- [Imlib2](https://github.com/alistair7/imlib2-jxl)
- [FFmpeg](https://github.com/FFmpeg/FFmpeg/search?q=jpeg-xl&type=commits)
- [GDAL](https://gdal.org/drivers/raster/jpegxl.html): supported since 3.4.0 as a TIFF codec, and 3.6.0 as standalone format
## OS-level support / UI frameworks / file browser plugins
- Qt / KDE: [plugin available](https://github.com/novomesk/qt-jpegxl-image-plugin)
- GDK-pixbuf: plugin available in libjxl repo
- [gThumb](https://ubuntuhandbook.org/index.php/2021/04/gthumb-3-11-3-adds-jpeg-xl-support/)
- [MacOS viewer/QuickLook plugin](https://github.com/yllan/JXLook)
- [Windows Imaging Component](https://github.com/mirillis/jpegxl-wic)
- [Windows thumbnail handler](https://github.com/saschanaz/jxl-winthumb)
- [OpenMandriva Lx (since 4.3 RC)](https://www.openmandriva.org/en/news/article/openmandriva-lx-4-3-rc-available-for-testing)
- [KaOS (since 2021.06)](https://news.itsfoss.com/kaos-2021-06-release/)
- [EFL (since 1.27, no external plugin needed)](https://www.enlightenment.org)
## Image editors
- [GIMP (since 2.99.8)](https://www.gimp.org/news/2021/10/20/gimp-2-99-8-released/); plugin for older versions available in libjxl repo
- [Krita](https://invent.kde.org/graphics/krita/-/commit/13e5d2e5b9f0eac5c8064b7767f0b62264a0797b)
- Photoshop: no plugin available yet, no official support yet
## Image viewers
- [XnView](https://www.xnview.com/en/)
- [ImageGlass](https://imageglass.org/)
- [IrfanView](https://www.irfanview.com/); supported since 4.59 - requires a [plugin](https://www.irfanview.com/plugins.htm) to be downloaded and enabled.
- [Tachiyomi](https://github.com/tachiyomiorg/tachiyomi/releases/tag/v0.12.1)
- Any viewer based on Qt, KDE, GDK-pixbuf, EFL, ImageMagick, libvips or imlib2 (see above)
- Qt viewers: gwenview, digiKam, KolourPaint, KPhotoAlbum, LXImage-Qt, qimgv, qView, nomacs, VookiImageViewer, PhotoQt
- GTK viewers: Eye of Gnome (eog), gThumb, Geeqie
- EFL viewers: entice, ephoto
- [Swayimg](https://github.com/artemsen/swayimg)
## Online tools
- [Squoosh](https://squoosh.app/)
- [Cloudinary](https://cloudinary.com/blog/cloudinary_supports_jpeg_xl)
- [MConverter](https://mconverter.eu/)
- [jpegxl.io](https://jpegxl.io/)

View file

@ -0,0 +1,15 @@
API reference
=============
``libjxl`` exposes a C API for encoding and decoding JPEG XL files with some
C++ header-only helpers for C++ users.
.. toctree::
:caption: API REFERENCE
:maxdepth: 2
api_decoder
api_encoder
api_common
api_butteraugli
api_threads

View file

@ -0,0 +1,6 @@
Butteraugli API - ``jxl/butteraugli.h``
=======================================
.. doxygengroup:: libjxl_butteraugli
:members:
:private-members:

View file

@ -0,0 +1,6 @@
Common API concepts
===================
.. doxygengroup:: libjxl_common
:members:
:private-members:

View file

@ -0,0 +1,6 @@
Decoder API - ``jxl/decode.h``
==============================
.. doxygengroup:: libjxl_decoder
:members:
:private-members:

View file

@ -0,0 +1,6 @@
Encoder API - ``jxl/encode.h``
==============================
.. doxygengroup:: libjxl_encoder
:members:
:private-members:

View file

@ -0,0 +1,6 @@
Multi-threaded Encoder/Decoder
==============================
.. doxygengroup:: libjxl_threads
:members:
:private-members:

View file

@ -0,0 +1,110 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Configuration file for the Sphinx documentation builder.
#
# See https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
import re
import subprocess
def GetVersion():
"""Function to get the version of the current code."""
with open(os.path.join(
os.path.dirname(__file__), '../../lib/CMakeLists.txt'), 'r') as f:
cmakevars = {}
for line in f:
m = re.match(r'set\(JPEGXL_([A-Z]+)_VERSION ([^\)]+)\)', line)
if m:
cmakevars[m.group(1)] = m.group(2)
return '%s.%s.%s' % (cmakevars['MAJOR'], cmakevars['MINOR'], cmakevars['PATCH'])
def ConfigProject(app, config):
# Configure the doxygen xml directory as the "xml" directory next to the
# sphinx output directory. Doxygen generates by default the xml files in a
# "xml" sub-directory of the OUTPUT_DIRECTORY.
build_dir = os.path.dirname(app.outdir)
xml_dir = os.path.join(build_dir, 'xml')
config.breathe_projects['libjxl'] = xml_dir
# Read the docs build environment doesn't run our cmake script so instead we
# need to run doxygen manually here.
if os.environ.get('READTHEDOCS', None) != 'True':
return
root_dir = os.path.realpath(os.path.join(app.srcdir, '../../'))
doxyfile = os.path.join(build_dir, 'Doxyfile-rtd.doc')
with open(doxyfile, 'w') as f:
f.write(f"""
FILE_PATTERNS = *.c *.h
GENERATE_HTML = NO
GENERATE_LATEX = NO
GENERATE_XML = YES
INPUT = lib/include doc/api.txt
OUTPUT_DIRECTORY = {build_dir}
PROJECT_NAME = LIBJXL
QUIET = YES
RECURSIVE = YES
STRIP_FROM_PATH = lib/include
WARN_AS_ERROR = YES
""")
subprocess.check_call(['doxygen', doxyfile], cwd=root_dir)
def setup(app):
# Generate doxygen XML on init when running from Read the docs.
app.connect("config-inited", ConfigProject)
### Project information
project = 'libjxl'
project_copyright = 'JPEG XL Project Authors'
author = 'JPEG XL Project Authors'
version = GetVersion()
### General configuration
extensions = [
# For integration with doxygen documentation.
'breathe',
# sphinx readthedocs theme.
'sphinx_rtd_theme',
# Do we use it?
'sphinx.ext.graphviz',
]
breathe_default_project = 'libjxl'
breathe_projects = {}
# All the API is in C, except those files that end with cxx.h.
breathe_domain_by_extension = {'h': 'cpp'}
breathe_domain_by_file_pattern = {
'*cxx.h': 'cpp',
}
breathe_implementation_filename_extensions = ['.cc']
# These are defined at build time by cmake.
c_id_attributes = [
'JXL_EXPORT',
'JXL_DEPRECATED',
'JXL_THREADS_EXPORT',
]
cpp_id_attributes = c_id_attributes
breathe_projects_source = {
'libjxl' : ('../../', [
'doc/api.txt',
'lib/include/jxl',
])
}
# Recognized suffixes.
source_suffix = ['.rst', '.md']
### Options for HTML output
# Use the readthedocs.io theme when generating the HTML output.
html_theme = 'sphinx_rtd_theme'

View file

@ -0,0 +1,18 @@
.. libjxl sphinx documentation entrypoint
JPEG XL image format reference implementation
=============================================
.. toctree::
:maxdepth: 3
:caption: Contents:
api
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`

View file

@ -0,0 +1,3 @@
breathe
sphinx
sphinx-rtd-theme

View file

@ -0,0 +1,6 @@
#### Table M.8 "Adobe" marker template
```
0xEE, 0x00, 0x0E, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x01
```

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
cat dct_gen.md \
is_zero_base.md num_nonzeros_base.md brn_proto.md app0.md icc.md ducky.md \
adobe.md stock_counts.md stock_values.md symbol_order.md stock_quant.md \
quant.md freq_context.md num_nonzero_context.md nonzero_buckets.md \
context_modes.md > all_tables.md

View file

@ -0,0 +1,6 @@
#### Table M.4 APP0 template
```
0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00
```

View file

@ -0,0 +1,23 @@
#### Table M.3 Protocol Buffer descriptor of top-level structure of losslessly compressed JPEG stream
```protobuf
message Header {
optional uint64 width = 1;
optional uint64 height = 2;
required uint64 version_and_component_count_code = 3;
optional uint64 subsampling_code = 4;
}
message Jpeg {
required bytes signature = 1;
required Header header = 2;
optional bytes meta_data = 3;
optional bytes jpeg1_internals = 4;
optional bytes quant_data = 5;
optional bytes histogram_data = 6;
optional bytes dc_data = 7;
optional bytes ac_data = 8;
optional bytes original_jpg = 9;
}
```

View file

@ -0,0 +1,13 @@
#### Table M.29 context_modes table
```
0, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
```
```
0, 1, 1, 1, 1, 0, 0, 0, 2, 3, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0,
0, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
```

View file

@ -0,0 +1,241 @@
#### Electronic Insert I.1 DCT-II / DCT-III code generator
```python
#######################################################################
# DCT-II / DCT-III generator
#
# Based on:
# "A low multiplicative complexity fast recursive DCT-2 algorithm"
# by Maxim Vashkevich and Alexander Petrovsky / arXiv / 20 Jul 2012
#######################################################################
import math
import sys
N = 8
#######################################################################
# Base transforms / generators
#######################################################################
CNTR = 0
def makeTmp():
global CNTR
result = "t{:02d}".format(CNTR)
CNTR = CNTR + 1
return result
def makeVar(i):
return "i{:02d}".format(i)
def add(x, y):
tmp = makeTmp()
print(tmp + " = " + x + " + " + y + ";")
return tmp
def sub(x, y):
tmp = makeTmp()
print(tmp + " = " + x + " - " + y + ";")
return tmp
def mul(x, c):
tmp = makeTmp()
print(tmp + " = " + x + " * " + c + ";")
return tmp
# 2.0 * math.cos((a + 0.0) / (b + 0.0) * math.pi)
def C2(a, b):
return "c_c2_" + str(a) + "_" + str(b)
# 1.0 / C2(a, b)
def iC2(a, b):
return "c_ic2_" + str(a) + "_" + str(b)
#######################################################################
# Utilities
#######################################################################
# Generate identity matrix. Usually this matrix is passed to
# DCT algorithm to generate "basis" vectors of the transform.
def makeVars():
return [makeVar(i) for i in range(N)]
# Split list of variables info halves.
def split(x):
m = len(x)
m2 = m // 2
return (x[0 : m2], x[m2 : m])
# Make a list of variables in a reverse order.
def reverse(varz):
m = len(varz)
result = [0] * m
for i in range(m):
result[i] = varz[m - 1 - i]
return result
# Apply permutation
def permute(x, p):
return [x[p[i]] for i in range(len(p))]
def transposePermutation(p):
n = len(p)
result = [0] * n
for i in range(n):
result[p[i]] = i
return result
# See paper. Split even-odd elements.
def P(n):
if n == 1:
return [0]
n2 = n // 2
return [2 * i for i in range(n2)] + [2 * i + 1 for i in range(n2)]
# See paper. Interleave first and second half.
def Pt(n):
return transposePermutation(P(n))
#######################################################################
# Scheme
#######################################################################
def B2(x):
n = len(x)
n2 = n // 2
if n == 1:
raise "ooops"
(top, bottom) = split(x)
bottom = reverse(bottom)
t = [add(top[i], bottom[i]) for i in range(n2)]
b = [sub(top[i], bottom[i]) for i in range(n2)]
return t + b
def iB2(x):
n = len(x)
n2 = n // 2
if n == 1:
raise "ooops"
(top, bottom) = split(x)
t = [add(top[i], bottom[i]) for i in range(n2)]
b = [sub(top[i], bottom[i]) for i in range(n2)]
return t + reverse(b)
def B4(x, rn):
n = len(x)
n2 = n // 2
if n == 1:
raise "ooops"
(top, bottom) = split(x)
rbottom = reverse(bottom)
t = [sub(top[i], rbottom[i]) for i in range(n2)]
b = [mul(bottom[i], C2(rn, 2 * N)) for i in range(n2)]
top = [add(t[i], b[i]) for i in range(n2)]
bottom = [sub(t[i], b[i]) for i in range(n2)]
return top + bottom
def iB4(x, rn):
n = len(x)
n2 = n // 2
if n == 1:
raise "ooops"
(top, bottom) = split(x)
t = [add(top[i], bottom[i]) for i in range(n2)]
b = [sub(top[i], bottom[i]) for i in range(n2)]
bottom = [mul(b[i], iC2(rn, 2 * N)) for i in range(n2)]
rbottom = reverse(bottom)
top = [add(t[i], rbottom[i]) for i in range(n2)]
return top + bottom
def P4(n):
if n == 1:
return [0]
if n == 2:
return [0, 1]
n2 = n // 2
result = [0] * n
tc = 0
bc = 0
i = 0
result[i] = tc; tc = tc + 1; i = i + 1
turn = True
while i < n - 1:
if turn:
result[i] = n2 + bc; bc = bc + 1; i = i + 1
result[i] = n2 + bc; bc = bc + 1; i = i + 1
else:
result[i] = tc; tc = tc + 1; i = i + 1
result[i] = tc; tc = tc + 1; i = i + 1
turn = not turn
result[i] = tc; tc = tc + 1; i = i + 1
return result
def iP4(n):
return transposePermutation(P4(n))
def d2n(x):
n = len(x)
if n == 1:
return x
y = B2(x)
(top, bottom) = split(y)
return permute(d2n(top) + d4n(bottom, N // 2), Pt(n))
def id2n(x):
n = len(x)
if n == 1:
return x
(top, bottom) = split(permute(x, P(n)))
return iB2(id2n(top) + id4n(bottom, N // 2))
def d4n(x, rn):
n = len(x)
if n == 1:
return x
y = B4(x, rn)
(top, bottom) = split(y)
rn2 = rn // 2
return permute(d4n(top, rn2) + d4n(bottom, N - rn2), P4(n))
def id4n(x, rn):
n = len(x)
if n == 1:
return x
(top, bottom) = split(permute(x, iP4(n)))
rn2 = rn // 2
y = id4n(top, rn2) + id4n(bottom, N -rn2)
return iB4(y, rn)
#######################################################################
# Main.
#######################################################################
def help():
print("Usage: %s [N [T]]" % sys.argv[0])
print(" N should be the power of 2, default is 8")
print(" T is one of {2, 3}, default is 2")
sys.exit()
def parseInt(s):
try:
return int(s)
except ValueError:
help()
if __name__ == "__main__":
if len(sys.argv) < 1 or len(sys.argv) > 3: help()
if len(sys.argv) >= 2:
N = parseInt(sys.argv[1])
if (N & (N - 1)) != 0: help()
type = 0
if len(sys.argv) >= 3:
typeOption = sys.argv[2]
if len(typeOption) != 1: help()
type = "23".index(typeOption)
if type == -1: help()
if type == 0:
vars = d2n(makeVars())
else: # type == 1
vars = id2n(makeVars())
print("Output vector: " + str(vars))
```

View file

@ -0,0 +1,6 @@
#### Table M.7 "Ducky" marker template
```
0xEC, 0x00, 0x11, 0x44, 0x75, 0x63, 0x6B, 0x79, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00
```

View file

@ -0,0 +1,54 @@
#### Table M.15 freq_context
`scheme == 0`:
```
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
```
`scheme == 1`:
```
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0
```
`scheme == 2`:
```
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1
```
`scheme == 3`:
```
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2
```
`scheme == 4`:
```
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9,
9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13,
13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15,
15, 15, 15, 15, 15, 15, 15, 15, 15, 15
```
`scheme == 5`:
```
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 24, 24,
25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29,
29, 29, 30, 30, 30, 30, 31, 31, 31, 31
```
`scheme == 6`:
```
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63
```

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,9 @@
#### Table M.1 is_zero_base table
```
228, 216, 216, 195, 192, 189, 182, 184, 179, 176, 171, 168, 166, 159,
156, 151, 151, 150, 150, 146, 144, 138, 138, 137, 135, 131, 127, 126,
124, 123, 124, 123, 122, 121, 118, 117, 114, 115, 116, 116, 115, 115,
114, 111, 111, 111, 112, 111, 110, 110, 110, 111, 111, 114, 110, 111,
112, 113, 116, 120, 126, 131, 147, 160
```

View file

@ -0,0 +1,36 @@
/*
settings.json:
"markdown-pdf.styles": ["markdown-pdf.css",],
"markdown-pdf.format": "Letter",
"markdown-pdf.margin.top": "1in",
"markdown-pdf.margin.bottom": "1in",
"markdown-pdf.margin.left": "1in",
"markdown-pdf.margin.right": "1in",
"markdown-pdf.stylesRelativePathFile" : true,
"markdown-pdf.displayHeaderFooter": false,
*/
body {
font-family: "Times";
font-size: 10pt;
padding: 0;
}
h4 {
font-family: "Times New Roman";
font-size: 10pt;
font-weight: bold;
}
code {
font-family: Consolas, "Source Code Pro";
font-size: 10pt;
}
pre.hljs code > div {
padding: 0px;
}
:not(pre):not(.hljs) > code {
color: #4d4d4c;
}

View file

@ -0,0 +1,9 @@
#### Table M.17 nonzero_buckets
```
0, 1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10
```

View file

@ -0,0 +1,60 @@
#### Table M.16 num_nonzero_context
`scheme == 0`:
```
0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
```
`scheme == 1`:
```
0, 2, 2, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10,
10, 10, 10, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
12, 12, 12, 12, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 14
```
`scheme == 2`:
```
0, 4, 4, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 16, 16, 16, 20, 20,
20, 20, 20, 20, 20, 20, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
24, 24, 24, 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
28, 28, 28, 28, 28, 28, 28, 28, 28, 28
```
`scheme == 3`:
```
0, 8, 8, 16, 16, 16, 24, 24, 24, 24, 32, 32, 32, 32, 32, 32, 40, 40,
40, 40, 40, 40, 40, 40, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
48, 48, 48, 48, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
55, 55, 55, 55, 55, 55, 55, 55, 55, 55
```
`scheme == 4`:
```
0, 16, 16, 32, 32, 32, 48, 48, 48, 48, 64, 64, 64, 64,
64, 64, 80, 80, 80, 80, 80, 80, 80, 80, 95, 95, 95, 95,
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 109, 109,
109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, 109,
109, 109, 109, 109, 109, 109, 109, 109
```
`scheme == 5`:
```
0, 32, 32, 64, 64, 64, 96, 96, 96, 96, 127, 127, 127, 127,
127, 127, 157, 157, 157, 157, 157, 157, 157, 157, 185, 185, 185, 185,
185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 211, 211,
211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
211, 211, 211, 211, 211, 211, 211, 211
```
`scheme == 6`:
```
0, 64, 64, 127, 127, 127, 188, 188, 188, 188, 246, 246, 246, 246,
246, 246, 300, 300, 300, 300, 300, 300, 300, 300, 348, 348, 348, 348,
348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 348, 388, 388,
388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
388, 388, 388, 388, 388, 388, 388, 388
```

View file

@ -0,0 +1,258 @@
#### Table M.2 num_nonzeros_base table
```
251, 252, 117, 249, 161, 136, 83, 238, 184, 126, 137, 129, 140, 119,
70, 213, 160, 175, 174, 130, 166, 134, 122, 125, 131, 144, 136, 133,
139, 123, 79, 216, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
254, 252, 174, 232, 189, 155, 122, 177, 204, 173, 146, 149, 141, 133,
103, 109, 167, 187, 168, 142, 154, 147, 125, 139, 144, 138, 138, 153,
141, 133, 90, 121, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
251, 240, 197, 176, 184, 177, 114, 89, 194, 165, 153, 161, 158, 136,
92, 95, 123, 171, 160, 140, 148, 136, 129, 139, 145, 136, 143, 134,
138, 124, 92, 154, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
247, 220, 201, 110, 194, 176, 147, 59, 175, 171, 156, 157, 152, 146,
115, 114, 88, 151, 164, 141, 153, 135, 141, 131, 146, 139, 140, 145,
138, 137, 112, 184, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
238, 179, 203, 63, 194, 173, 149, 71, 139, 169, 154, 159, 150, 146,
117, 143, 78, 122, 152, 137, 149, 138, 138, 133, 134, 142, 142, 142,
148, 128, 118, 199, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
227, 127, 200, 44, 192, 170, 148, 100, 102, 161, 156, 153, 148, 149,
124, 160, 88, 101, 134, 132, 149, 145, 134, 134, 136, 141, 138, 142,
144, 137, 116, 208, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
214, 86, 195, 44, 187, 163, 148, 126, 81, 147, 156, 152, 150, 144,
121, 172, 96, 95, 117, 122, 145, 152, 136, 133, 135, 135, 131, 142,
141, 135, 114, 217, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
198, 56, 191, 54, 171, 162, 147, 144, 74, 128, 152, 149, 150, 142,
119, 177, 101, 100, 106, 111, 135, 154, 136, 137, 136, 132, 133, 142,
144, 130, 117, 222, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
176, 40, 189, 73, 147, 159, 148, 152, 79, 106, 147, 149, 151, 139,
123, 188, 108, 110, 106, 97, 125, 151, 137, 138, 135, 135, 134, 136,
140, 131, 116, 221, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
148, 33, 185, 88, 117, 158, 145, 163, 95, 91, 137, 146, 150, 140,
120, 197, 115, 116, 114, 92, 114, 144, 130, 133, 132, 133, 129, 140,
138, 130, 111, 224, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
117, 31, 180, 104, 93, 150, 143, 166, 99, 85, 124, 139, 148, 142,
118, 201, 105, 120, 120, 90, 107, 135, 127, 130, 131, 131, 132, 140,
142, 133, 114, 229, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
87, 35, 170, 110, 78, 141, 144, 176, 106, 90, 112, 132, 143, 138,
119, 204, 111, 121, 125, 90, 105, 131, 124, 122, 129, 128, 129, 137,
138, 133, 114, 227, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
63, 42, 159, 123, 73, 127, 142, 191, 105, 91, 105, 123, 139, 137,
120, 209, 117, 110, 122, 98, 110, 125, 115, 123, 122, 126, 128, 134,
141, 129, 113, 229, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
45, 53, 146, 135, 71, 114, 138, 193, 100, 98, 98, 113, 133, 135,
118, 222, 113, 111, 139, 103, 107, 126, 111, 119, 121, 122, 127, 135,
141, 128, 114, 242, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
33, 60, 132, 138, 75, 100, 134, 203, 112, 99, 98, 105, 126, 131,
115, 229, 107, 93, 121, 106, 108, 122, 106, 109, 114, 116, 127, 133,
143, 128, 110, 242, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
24, 70, 118, 134, 76, 87, 130, 201, 110, 96, 99, 97, 119, 130,
111, 229, 97, 104, 125, 102, 112, 125, 101, 109, 113, 114, 125, 129,
142, 127, 112, 241, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
17, 65, 100, 121, 80, 75, 124, 174, 117, 100, 94, 93, 114, 128,
110, 216, 103, 94, 113, 122, 118, 126, 113, 108, 105, 108, 122, 128,
141, 125, 113, 238, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
12, 70, 82, 132, 78, 65, 118, 155, 136, 103, 97, 89, 106, 124,
111, 215, 115, 123, 129, 99, 104, 127, 110, 108, 101, 109, 118, 126,
136, 123, 110, 233, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
8, 66, 61, 117, 91, 59, 108, 195, 101, 112, 99, 99, 99, 116,
106, 230, 127, 99, 144, 101, 118, 137, 117, 111, 106, 104, 116, 121,
134, 122, 110, 223, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
6, 78, 42, 146, 101, 54, 94, 201, 116, 102, 110, 94, 92, 108,
103, 214, 108, 111, 127, 102, 121, 132, 120, 121, 95, 98, 110, 121,
129, 117, 107, 235, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
5, 93, 29, 145, 102, 52, 77, 216, 108, 115, 108, 102, 89, 97,
94, 229, 89, 103, 139, 120, 103, 151, 102, 100, 97, 96, 99, 111,
125, 116, 104, 242, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
4, 105, 21, 145, 100, 54, 64, 217, 100, 122, 128, 87, 88, 91,
87, 230, 112, 80, 148, 95, 146, 123, 96, 140, 90, 91, 98, 106,
122, 111, 100, 249, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
4, 130, 14, 142, 104, 56, 51, 208, 116, 135, 100, 89, 82, 84,
75, 239, 85, 85, 122, 125, 94, 144, 151, 136, 92, 97, 104, 109,
113, 110, 91, 246, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
3, 126, 9, 172, 105, 57, 39, 219, 95, 120, 118, 96, 93, 75,
66, 241, 102, 134, 96, 156, 146, 162, 130, 112, 82, 89, 97, 101,
116, 103, 82, 254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
3, 149, 7, 182, 122, 54, 29, 224, 103, 100, 113, 96, 90, 74,
55, 250, 127, 94, 118, 93, 135, 160, 113, 130, 95, 117, 106, 96,
111, 97, 77, 242, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
3, 150, 4, 170, 138, 59, 20, 229, 91, 150, 107, 98, 92, 68,
48, 245, 113, 64, 114, 111, 134, 127, 102, 104, 85, 118, 103, 107,
102, 91, 72, 245, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
3, 171, 3, 165, 137, 62, 14, 211, 96, 127, 132, 121, 95, 62,
37, 248, 102, 57, 144, 85, 127, 191, 102, 97, 127, 104, 91, 102,
107, 81, 64, 254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
2, 166, 2, 196, 122, 65, 10, 243, 102, 93, 117, 92, 96, 63,
29, 251, 169, 159, 149, 96, 91, 139, 157, 40, 100, 89, 120, 92,
109, 79, 58, 247, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
2, 176, 2, 189, 118, 48, 7, 219, 68, 43, 109, 96, 129, 75,
19, 254, 2, 3, 185, 6, 102, 127, 127, 127, 1, 131, 83, 99,
107, 80, 45, 254, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
1, 205, 2, 208, 64, 89, 4, 223, 29, 169, 29, 123, 118, 76,
11, 240, 202, 243, 65, 6, 12, 243, 96, 55, 102, 102, 114, 102,
107, 74, 31, 247, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
1, 216, 1, 214, 127, 94, 2, 234, 145, 3, 127, 106, 155, 80,
4, 247, 4, 65, 86, 127, 127, 127, 127, 102, 127, 143, 143, 108,
113, 80, 16, 216, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```
```
2, 199, 1, 222, 93, 94, 1, 232, 2, 65, 74, 139, 201, 48,
2, 254, 169, 127, 52, 243, 251, 249, 102, 86, 202, 153, 65, 65,
146, 69, 8, 238, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128
```

View file

@ -0,0 +1,19 @@
#### Table M.13 template quant tables
`is_luma == true`:
```
16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60,
55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87,
80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81,
104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98,
112, 100, 103, 99
```
`is_luma == false`:
```
17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26,
56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99, 99, 99
```

View file

@ -0,0 +1,22 @@
#### Table M.9 stock counts arrays
`is_ac == 0`, `stock_index == 0`:
```
0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0
```
`is_ac == 0`, `stock_index == 1`:
```
0, 0, 1, 5, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0
```
`is_ac == 1`, `stock_index == 0`:
```
0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 126
```
`is_ac == 1`, `stock_index == 1`:
```
0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 120
```

View file

@ -0,0 +1,130 @@
#### Table M.12 stock quant tables
`is_luma == true`, `stock_index == 0`:
```
3, 2, 2, 3, 5, 8, 10, 12, 2, 2, 3, 4, 5, 12, 12, 11, 3, 3,
3, 5, 8, 11, 14, 11, 3, 3, 4, 6, 10, 17, 16, 12, 4, 4, 7, 11,
14, 22, 21, 15, 5, 7, 11, 13, 16, 21, 23, 18, 10, 13, 16, 17, 21, 24,
24, 20, 14, 18, 19, 20, 22, 20, 21, 20
```
`is_luma == true`, `stock_index == 1`:
```
8, 6, 5, 8, 12, 20, 26, 31, 6, 6, 7, 10, 13, 29, 30, 28, 7, 7,
8, 12, 20, 29, 35, 28, 7, 9, 11, 15, 26, 44, 40, 31, 9, 11, 19, 28,
34, 55, 52, 39, 12, 18, 28, 32, 41, 52, 57, 46, 25, 32, 39, 44, 52, 61,
60, 51, 36, 46, 48, 49, 56, 50, 52, 50
```
`is_luma == true`, `stock_index == 2`:
```
6, 4, 4, 6, 10, 16, 20, 24, 5, 5, 6, 8, 10, 23, 24, 22, 6, 5,
6, 10, 16, 23, 28, 22, 6, 7, 9, 12, 20, 35, 32, 25, 7, 9, 15, 22,
27, 44, 41, 31, 10, 14, 22, 26, 32, 42, 45, 37, 20, 26, 31, 35, 41, 48,
48, 40, 29, 37, 38, 39, 45, 40, 41, 40
```
`is_luma == true`, `stock_index == 3`:
```
5, 3, 3, 5, 7, 12, 15, 18, 4, 4, 4, 6, 8, 17, 18, 17, 4, 4,
5, 7, 12, 17, 21, 17, 4, 5, 7, 9, 15, 26, 24, 19, 5, 7, 11, 17,
20, 33, 31, 23, 7, 11, 17, 19, 24, 31, 34, 28, 15, 19, 23, 26, 31, 36,
36, 30, 22, 28, 29, 29, 34, 30, 31, 30
```
`is_luma == true`, `stock_index == 4`:
```
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1
```
`is_luma == true`, `stock_index == 5`:
```
2, 1, 1, 2, 2, 4, 5, 6, 1, 1, 1, 2, 3, 6, 6, 6, 1, 1,
2, 2, 4, 6, 7, 6, 1, 2, 2, 3, 5, 9, 8, 6, 2, 2, 4, 6,
7, 11, 10, 8, 2, 4, 6, 6, 8, 10, 11, 9, 5, 6, 8, 9, 10, 12,
12, 10, 7, 9, 10, 10, 11, 10, 10, 10
```
`is_luma == true`, `stock_index == 6`:
```
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
1, 2, 2, 3, 1, 1, 1, 1, 2, 2, 3, 3, 1, 1, 1, 2, 2, 3,
3, 3, 1, 1, 2, 2, 3, 3, 3, 3
```
`is_luma == true`, `stock_index == 7`:
```
10, 7, 6, 10, 14, 24, 31, 37, 7, 7, 8, 11, 16, 35, 36, 33, 8, 8,
10, 14, 24, 34, 41, 34, 8, 10, 13, 17, 31, 52, 48, 37, 11, 13, 22, 34,
41, 65, 62, 46, 14, 21, 33, 38, 49, 62, 68, 55, 29, 38, 47, 52, 62, 73,
72, 61, 43, 55, 57, 59, 67, 60, 62, 59
```
`is_luma == false`, `stock_index == 0`:
```
9, 9, 9, 12, 11, 12, 24, 13, 13, 24, 50, 33, 28, 33, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50
```
`is_luma == false`, `stock_index == 1`:
```
3, 4, 5, 9, 20, 20, 20, 20, 4, 4, 5, 13, 20, 20, 20, 20, 5, 5,
11, 20, 20, 20, 20, 20, 9, 13, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 20, 20, 20
```
`is_luma == false`, `stock_index == 2`:
```
9, 9, 12, 24, 50, 50, 50, 50, 9, 11, 13, 33, 50, 50, 50, 50, 12, 13,
28, 50, 50, 50, 50, 50, 24, 33, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
50, 50, 50, 50, 50, 50, 50, 50, 50, 50
```
`is_luma == false`, `stock_index == 3`:
```
5, 5, 7, 14, 30, 30, 30, 30, 5, 6, 8, 20, 30, 30, 30, 30, 7, 8,
17, 30, 30, 30, 30, 30, 14, 20, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
30, 30, 30, 30, 30, 30, 30, 30, 30, 30
```
`is_luma == false`, `stock_index == 4`:
```
7, 7, 10, 19, 40, 40, 40, 40, 7, 8, 10, 26, 40, 40, 40, 40, 10, 10,
22, 40, 40, 40, 40, 40, 19, 26, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
40, 40, 40, 40, 40, 40, 40, 40, 40, 40
```
`is_luma == false`, `stock_index == 5`:
```
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1
```
`is_luma == false`, `stock_index == 6`:
```
2, 2, 2, 5, 10, 10, 10, 10, 2, 2, 3, 7, 10, 10, 10, 10, 2, 3,
6, 10, 10, 10, 10, 10, 5, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 10, 10
```
`is_luma == false`, `stock_index == 7`:
```
10, 11, 14, 28, 59, 59, 59, 59, 11, 13, 16, 40, 59, 59, 59, 59, 14, 16,
34, 59, 59, 59, 59, 59, 28, 40, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59, 59, 59
```

View file

@ -0,0 +1,44 @@
#### Table M.10 stock values arrays
`is_ac == 0`, `stock_index == 0`:
```
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 256
```
`is_ac == 0`, `stock_index == 1`:
```
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 256
```
`is_ac == 1`, `stock_index == 0`:
```
1, 2, 3, 0, 4, 17, 5, 18, 33, 49, 65, 6, 19, 81,
97, 7, 34, 113, 20, 50, 129, 145, 161, 8, 35, 66, 177, 193,
21, 82, 209, 240, 36, 51, 98, 114, 130, 9, 10, 22, 23, 24,
25, 26, 37, 38, 39, 40, 41, 42, 52, 53, 54, 55, 56, 57,
58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86, 87,
88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116, 117,
118, 119, 120, 121, 122, 131, 132, 133, 134, 135, 136, 137, 138, 146,
147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165, 166, 167,
168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186, 194, 195,
196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214, 215, 216,
217, 218, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 241, 242,
243, 244, 245, 246, 247, 248, 249, 250, 256
```
`is_ac == 1`, `stock_index == 1`:
```
0, 1, 2, 3, 17, 4, 5, 33, 49, 6, 18, 65, 81, 7,
97, 113, 19, 34, 50, 129, 8, 20, 66, 145, 161, 177, 193, 9,
35, 51, 82, 240, 21, 98, 114, 209, 10, 22, 36, 52, 225, 37,
241, 23, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55, 56,
57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85, 86,
87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115, 116,
117, 118, 119, 120, 121, 122, 130, 131, 132, 133, 134, 135, 136, 137,
138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165,
166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186,
194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214,
215, 216, 217, 218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242,
243, 244, 245, 246, 247, 248, 249, 250, 256
```

View file

@ -0,0 +1,30 @@
#### Table M.11 predefined symbol order
`is_ac == 0`:
```
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
```
`is_ac == 1`:
```
1, 0, 2, 3, 17, 4, 5, 33, 18, 49, 65, 6, 81, 19,
97, 7, 34, 113, 50, 129, 20, 145, 161, 8, 35, 66, 177, 193,
21, 82, 209, 240, 36, 51, 98, 114, 9, 130, 10, 22, 52, 225,
23, 37, 241, 24, 25, 26, 38, 39, 40, 41, 42, 53, 54, 55,
56, 57, 58, 67, 68, 69, 70, 71, 72, 73, 74, 83, 84, 85,
86, 87, 88, 89, 90, 99, 100, 101, 102, 103, 104, 105, 106, 115,
116, 117, 118, 119, 120, 121, 122, 131, 132, 133, 134, 135, 136, 137,
138, 146, 147, 148, 149, 150, 151, 152, 153, 154, 162, 163, 164, 165,
166, 167, 168, 169, 170, 178, 179, 180, 181, 182, 183, 184, 185, 186,
194, 195, 196, 197, 198, 199, 200, 201, 202, 210, 211, 212, 213, 214,
215, 216, 217, 218, 226, 227, 228, 229, 230, 231, 232, 233, 234, 242,
243, 244, 245, 246, 247, 248, 249, 250, 16, 32, 48, 64, 80, 96,
112, 128, 144, 160, 176, 192, 208, 11, 12, 13, 14, 15, 27, 28,
29, 30, 31, 43, 44, 45, 46, 47, 59, 60, 61, 62, 63, 75,
76, 77, 78, 79, 91, 92, 93, 94, 95, 107, 108, 109, 110, 111,
123, 124, 125, 126, 127, 139, 140, 141, 142, 143, 155, 156, 157, 158,
159, 171, 172, 173, 174, 175, 187, 188, 189, 190, 191, 203, 204, 205,
206, 207, 219, 220, 221, 222, 223, 224, 235, 236, 237, 238, 239, 251,
252, 253, 254, 255
```

View file

@ -0,0 +1,245 @@
# Security Vulnerabilities Playbook
## Reporting security bugs
Report security bugs by emailing libjxl-security@google.com.
Don't open a GitHub issue, don't discuss it public forums like Discord and don't
send a Pull Request if you think you have found a security bug.
## Overview
This document outlines the guidelines followed by the project when handling
security bugs, their fixes, disclosure and coordination with security
researchers. For more context about this guide, read the [coordinated
vulnerability disclosure
guidelines](https://github.com/google/oss-vulnerability-guide/blob/main/guide.md)
from Google Open Source Programs Office.
The main target audience of this guide is the coordinator from the libjxl
Vulnerability Management Team (VMT) handling the requests, however it is useful
for other people to understand what to expect from this process.
Members of the VMT monitor the reports received by email and will coordinate
for these to be addressed. This doesn't mean that said member would fix the bug,
but their responsibility is to make sure it is handled properly according to
this guide.
## Life of security bug
The Coordinator from VMT will make sure that the following steps are taken.
1. Acknowledge the bug report.
Our policy mandates a maximum of **3 business days** to respond to bug reports
in the given email, but you should respond as soon as possible and keep a fluid
communication with the reporter, who has spent some time looking at the issue.
2. Determine if the bug is a security bug covered by our policy.
Not all bugs are security bugs, and not all security bugs are covered by this
vulnerability disclosure policy. See the [What's a Security bug] section below.
3. Determine the affected versions.
Often new bugs on stable projects are found on new features or because of those
new features, so only the most recent versions are affected. It is important to
determine both what older versions are affected, so users running those older
versions can patch or update the software, and also what older versions are
*not* affected. It is possible that stable distributions ship older versions
that didn't contain the bug and therefore don't need to patch the code. Often
maintainers of package distributions need to patch older versions instead of
updating due to incompatibilities with newer ones and they need to understand
what's the vulnerable code.
Security bugs that have already been fixed in `main` or in already released code
but not disclosed as a vulnerability, for example if fixed as a result of a
refactor, should be treated like any other security bug in this policy and
disclosed indicating the range of older affected versions (expect for versions
before 0.5, see below). In such case a new release would likely not be needed if
one already exists, but stable distributions may be still using those version
and need to be aware of the issue and fix.
If no released version is affected by the bug, for example because it was only
introduced in the `main` branch but not yet released, then no vulnerability
disclosure is needed.
Note: Versions before 0.5 are not covered by the security policy. Those versions
have multiple security issues and should not be used anyway.
4. Communicate with the reporter
Communicate the decision to the reporter.
If the bug was not considered a security bug or not covered by this policy,
explain why and direct the reporter to open a public [issue in
GitHub](https://github.com/libjxl/libjxl/issues) or open one on their behalf.
You don't need to follow the rest of the guide in this case.
If the bug *is* a covered security bug then follow the rest of this guide.
Ask the reporter how they want to be credited in the disclosure: name and
company affiliation if any. Security researchers often value this recognition
and helps them dedicate their time to finding security bugs in our project.
There's no bug bounty (monetary compensation for security bugs) available for
libjxl.
5. Create a Security Advisory draft in GitHub
At this point it was established that the bug is a security issue that requires
a vulnerability disclosure. Start by creating a Security Advisory draft in the
[Security Advisories](https://github.com/libjxl/libjxl/security/advisories) page
in GitHub.
Add a short description of the bug explaining what's the issue and what's the
impact of the issue. Being 'hard' or 'complex' to exploit is not a reason to
discard the potential impact. You can update this description later, save it as
a draft in GitHub.
Add the reporter to the security advisory draft if they have a GitHub account,
and add the project members that will be working on a fix for the bug.
Establish the severity of the issue according to the impact and tag the
appropriate Common Weakness Enumeration (CWE) values. This helps classify the
security issues according to their nature.
6. Work on a fix in a private branch
Coordinators can work on the fix themselves, use a proposed fix from the
reporter if there is one, or work with other project members to create one.
Work on a fix for the bug in *private*. Don't publish a Pull Request with the
fix like you normally do, and don't upload the fix to your libjxl fork. If you
ask another project member to work on it, explain them that they should follow
this guide.
7. Request a CVE number
The Common Vulnerabilities and Exposures (CVE) is the system used to disclose
vulnerabilities in software. A CVE number, like CVE-2021-NNNNNN, is a unique
identifier for a given vulnerability. These numbers are assigned by a CVE
Numbering Authority (CNA) with scope on the given project that has the
vulnerability. For libjxl, we use Google's Generic CNA.
For VMT coordinators at Google, file a bug at
[go/cve-request](https://goto.google.com/cve-request) to request a CVE. See
go/vcp-cna for context.
When requesting the CVE include:
* A description of the problem (example: bug when parsing this field)
* A description of the impact of the bug (example: OOB read, remote code
execution, etc)
* The proposed CWE id(s) determined earlier.
* List of affected versions.
* Reporter of the bug and their preferred name/company to include in the
disclosure.
* Links to the issues/fixes (if already public), these can be added later, even
after the CVE is public.
* The CPE prefix of the affected project (`cpe:2.3:a:libjxl_project:libjxl`)
When in doubt, you can discuss these with the security team while requesting it.
8. File a Security bug in Chromium (if affected).
libjxl project is in charge of updating and maintaining Chromium's libjxl
integration code, this includes updating the libjxl library when needed. While
the regular CVE disclosure process will eventually create a bug to update
Chromium, filing one at this stage speeds up the process.
[go/crbug](https://goto.google.com/crbug), select the "Security Bug" template
and complete the details. This bug will be used to keep track of what versions
of Chromium need backporting. The new bug in Chromium will not be public
initially, but will be made public some time after the issue is fixed.
9. Test the fixes on the intended releases
When disclosing a vulnerability normally two ways to fix it are offered:
* A patch or set of patches that fix the issue on `main` branch, and
* A new release that contains the security fix for the user to update to.
New releases that fix the vulnerability should be PATCH releases, that is, a
previous release (like 1.2.3) plus the patches that fix the vulnerability,
becoming a new version (like 1.2.4). See the [release process](release.md) for
details. At least the latest MINOR release branch should have a PATCH release
with the fix, however it might make sense to also backport the fix to older
minor branch releases, depending on long-term support schedule for certain
releases. For example, if many users are still using a particular older version
of the library and updating to a new version requires significant changes (due
to a redesigned API or new unavailable dependencies) it is helpful to provide a
PATCH release there too.
In either case, make sure that you test the fix in all the branches that you
intend to release it to.
The Continuous Integration pipelines don't work on the private forks created by
the Security Advisory, so manual testing of the fix is needed there before
making it public. Don't upload it to your public fork for testing.
10. Coordinate a date for release of the vulnerability disclosure.
Agree with the reporter and security folks from the CNA on a release date. There
is a maximum of 90 day disclosure timeline from the day the bug was reported.
On the disclosure date publish the fixes and tag the new PATCH release with the
fix. You can prepare private drafts of the release for review beforehand to
reduce the workload.
Update Chromium to the new release version (if affected) and work with Chrome
engineers on the required backports.
## What's a Security bug
A security bug is a bug that can potentially be exploited to let an attacker
gain unauthorized access or privileges. For example, gaining code execution in
libjxl decoder by decoding a malicious .jxl file is a security but hitting a
`JXL_ASSERT()` is not necessarily one.
The supported use cases to consider in the context of security bugs that require
a vulnerability disclosure are "release" builds. The disclosure is intended for
users of the project, to let them know that there is a security issue and that
they should update or patch it.
Unreleased versions are not relevant in this context. A bug introduced in the
`main` branch that is not yet in any release is not covered by this guide even
if the bug allows a remote code execution. CVEs should have a non-empty list of
affected released versions.
"Developer only" code is also not covered by this policy. In particular, tools
that are not installed by the build, or not installed when packaging `libjxl`
are not covered. For example, a bug in `tone_map` would not affect users since
is a developer-only tool. The rationale behind this is that users of the
released software will not have the developer code. This developer code is in
the same libjxl repository for convenience.
When considering the impact of a bug, "release" mode should be assumed. In
release mode `JXL_ASSERT()` and `JXL_CHECK()` are enabled, but `JXL_DASSERT()`
are not. This means that if a `JXL_DASSERT()` protects an out-of-bounds (OOB)
write, then the impact of a bug hitting the `JXL_DASSERT()` is at least an
OOB write. On the other hand, if a bug ends up hitting a `JXL_CHECK()` instead
of continuing, the only impact is the process abort instead of whatever else is
possible after the `JXL_CHECK()`.
Asserts in `libjxl` *tools* cause the tool process to abort, but don't affect
the caller. Either crashing or returning an error (non-zero exit code) would
have the same effect, so `JXL_ASSERT()` failures in the tools have no security
or functional impact.
Asserts in `libjxl` libraries, meant to be linked into other processes, cause
the caller process to abort, potentially causing a Denial of Service, however,
Denial of Service issues are *not* considered security bugs by this policy.
These are still issues and should be fixed, but they are not security issues.
Out-of-bounds (OOB) reads in process memory are considered security
vulnerabilities. OOB reads may allow an attacker to read other buffers from the
same process that it shouldn't have access to, even a small OOB read can
allow the attacker to read an address in the stack or in the heap, defeating
address space randomization techniques. In combination with other bugs these
can enable or simplify attacks to the process using libjxl. OOB reads don't need
to require a segmentation fault to be a problem, leaking process information in
decoded RGB pixels could be used as part of an exploit in some scenarios.
OOB writes and remote code execution (RCE) are security bugs of at least high
security impact.

View file

@ -0,0 +1,181 @@
# XL Overview
## Requirements
JPEG XL was designed for two main requirements:
* high quality: visually lossless at reasonable bitrates;
* decoding speed: multithreaded decoding should be able to reach around
400 Megapixel/s on large images.
These goals apply to various types of images, including HDR content, whose
support is made possible by full-precision (float32) computations and extensive
support of color spaces and transfer functions.
High performance is achieved by designing the format with careful consideration
of memory bandwidth usage and ease of SIMD/GPU implementation.
The full requirements for JPEG XL are listed in document wg1m82079.
## General architecture
The architecture follows the traditional block transform model with improvements
in the individual components. For a quick overview, we sketch a "block diagram"
of the lossy format decoder in the form of module names in **bold** followed by
a brief description. Note that post-processing modules in [brackets] are
optional - they are unnecessary or even counterproductive at very high quality
settings.
**Header**: decode metadata (e.g. image dimensions) from compressed fields
(smaller than Exp-Golomb thanks to per-field encodings). The compression and
small number of required fields enables very compact headers - much smaller than
JFIF and HEVC. The container supports multiple images (e.g. animations/bursts)
and passes (progressive).
**Bitstream**: decode transform coefficient residuals using rANS-encoded
<#bits,bits> symbols
**Dequantize**: from adaptive quant map side information, plus chroma from luma
**DC prediction**: expand DC residuals using adaptive (history-based) predictors
**Chroma from luma**: restore predicted X from B and Y from B
**IDCT:** 2x2..32x32, floating-point
**[Gaborish]**: additional deblocking convolution with 3x3 kernel
**[Edge preserving filter]**: nonlinear adaptive smoothing controlled by side
information
**[Noise injection]**: add perceptually pleasing noise according to a per-image
noise model
**Color space conversion**: from perceptual opsin XYB to linear RGB
**[Converting to other color spaces via ICC]**
The encoder is basically the reverse:
**Color space conversion**: from linear RGB to perceptual opsin XYB
**[Noise estimation]**: compute a noise model for the image
**[Gaborish]**: sharpening to counteract the blurring on the decoder side
**DCT**: transform sizes communicated via per-block side information
**Chroma from luma**: find the best multipliers of Y for X and B channels of
entire image
**Adaptive quantization**: iterative search for quant map that yields the best
perceived restoration
**Quantize**: store 16-bit prediction residuals
**DC prediction**: store residuals (prediction happens in quantized space)
**Entropy coding**: rANS and context modeling with clustering
# File Structure
A codestream begins with a `FileHeader` followed by one or more "passes"
(= scans: e.g. DC or AC_LF) which are then added together (summing the
respective color components in Opsin space) to form the final image. There is no
limit to the number of passes, so an encoder could choose to send salient parts
first, followed by arbitrary decompositions of the final image (in terms of
resolution, bit depth, quality or spatial location).
Each pass contains groups of AC and DC data. A group is a subset of pixels that
can be decoded in parallel. DC groups contain 256x256 DCs (from 2048x2048 input
pixels), AC groups cover 256x256 input pixels.
Each pass starts with a table of contents (sizes of each of their DC+AC
groups), which enables parallel decoding and/or the decoding of a subset.
However, there is no higher-level TOC of passes, as that would prevent
appending additional images and could be too constraining for the encoder.
## Lossless
JPEG XL supports tools for lossless coding designed by Alexander Rhatushnyak and
Jon Sneyers. They are about 60-75% of size of PNG, and smaller than WebP
lossless for photos.
An adaptive predictor computes 4 from the NW, N, NE and W pixels and combines
them with weights based on previous errors. The error value is encoded in a
bucket chosen based on a heuristic max error. The result is entropy-coded using
the ANS encoder.
## Current Reference Implementation
### Conventions
The software is written in C++ and built using CMake 3.6 or later.
Error handling is done by having functions return values of type `jxl::Status`
(a thin wrapper around bool which checks that it is not ignored). A convenience
macro named `JXL_RETURN_IF_ERROR` makes this more convenient by automatically
forwarding errors, and another macro named `JXL_FAILURE` exits with an error
message if reached, with no effect in optimized builds.
To diagnose the cause of encoder/decoder failures (which often only result in a
generic "decode failed" message), build using the following command:
```bash
CMAKE_FLAGS="-DJXL_CRASH_ON_ERROR" ./ci.sh opt
```
In such builds, the first JXL_FAILURE will print a message identifying where the
problem is and the program will exit immediately afterwards.
### Architecture
Getting back to the earlier block diagram:
**Header** handling is implemented in `headers.h` and `field*`.
**Bitstream**: `entropy_coder.h`, `dec_ans_*`.
**(De)quantize**: `quantizer.h`.
**DC prediction**: `predictor.h`.
**Chroma from luma**: `chroma_from_luma.h`
**(I)DCT**: `dct*.h`. Instead of operating directly on blocks of memory, the
functions operate on thin wrappers which can handle blocks spread across
multiple image lines.
**DCT size selection**: `ac_strategy.cc`
**[Gaborish]**: `gaborish.h`.
**[Edge preserving filter]**: `epf.h`
**[Noise injection]**: `noise*` (currently disabled)
**Color space conversion**: `color_*`, `dec_xyb.h`.
## Decoder overview
After decoding headers, the decoder begins processing frames (`dec_frame.cc`).
For each pass, it will read the DC group table of contents (TOC) and start
decoding, dequantizing and restoring color correlation of each DC group
(covering 2048x2048 pixels in the input image) in parallel
(`compressed_dc.cc`). The DC is split into parts corresponding to each AC group
(with 1px of extra border); the AC group TOC is read and each AC group (256x256
pixels) is processed in parallel (`dec_group.cc`).
In each AC group, the decoder reads per-block side information indicating the
kind of DCT transform; this is followed by the quantization field. Then, AC
coefficients are read, dequantized and have color correlation restored on a
tile per tile basis for better locality.
After all the groups are read, postprocessing is applied: Gaborish smoothing
and edge preserving filter, to reduce blocking and other artifacts.
Finally, the image is converted back from the XYB color space
(`dec_xyb.cc`) and saved to the output image (`codec_*.cc`).

View file

@ -0,0 +1,21 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Build an Ubuntu-based docker image with the installed software needed to
# develop and test JPEG XL.
FROM ubuntu:bionic
# Set a prompt for when using it locally.
ENV PS1="\[\033[01;33m\]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "
COPY scripts/99_norecommends /etc/apt/apt.conf.d/99_norecommends
COPY scripts /jpegxl_scripts
ARG DEBIAN_FRONTEND=noninteractive
RUN /jpegxl_scripts/jpegxl_builder.sh && \
rm -rf /jpegxl_scripts

View file

@ -0,0 +1,37 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Build an Ubuntu-based docker image for aarch64 with the installed software
# needed to run JPEG XL. This is only useful when running on actual aarch64
# hardware.
FROM arm64v8/ubuntu:bionic
COPY scripts/99_norecommends /etc/apt/apt.conf.d/99_norecommends
# Set a prompt for when using it locally.
ENV PS1="\[\033[01;33m\]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "
ARG DEBIAN_FRONTEND=noninteractive
RUN set -ex; \
apt-get update -y; \
apt-get install -y \
bsdmainutils \
cmake \
curl \
ca-certificates \
extra-cmake-modules \
git \
imagemagick \
libjpeg8 \
libgif7 \
libgoogle-perftools4 \
libopenexr22 \
libpng16-16 \
libqt5x11extras5 \
libsdl2-2.0-0 \
parallel; \
rm -rf /var/lib/apt/lists/*;

View file

@ -0,0 +1,7 @@
### Docker container infrastructure for JPEG XL
This directory contains the requirements to build a docker image for the
JPEG XL project builder.
Docker images need to be created and upload manually. See ./build.sh for
details.

View file

@ -0,0 +1,83 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
set -eu
MYDIR=$(dirname $(realpath "$0"))
declare -a TARGETS
load_targets() {
# Built-in OSX "find" does not support "-m".
FIND=$(which "gfind" || which "find")
for f in $(${FIND} -maxdepth 1 -name 'Dockerfile.*' | sort); do
local target="${f#*Dockerfile.}"
TARGETS+=("${target}")
done
}
usage() {
cat >&2 <<EOF
Use: $1 [targets]
Available targets:
* all
EOF
for target in "${TARGETS[@]}"; do
echo " * ${target}" >&2
done
}
build_target() {
local target="$1"
local dockerfile="${MYDIR}/Dockerfile.${target}"
# JPEG XL builder images are stored in the gcr.io/jpegxl project.
local tag="gcr.io/jpegxl/${target}"
echo "Building ${target}"
if ! sudo docker build --no-cache -t "${tag}" -f "${dockerfile}" "${MYDIR}" \
>"${target}.log" 2>&1; then
echo "${target} failed. See ${target}.log" >&2
else
echo "Done, to upload image run:" >&2
echo " sudo docker push ${tag}"
if [[ "${JPEGXL_PUSH:-}" == "1" ]]; then
echo "sudo docker push ${tag}" >&2
sudo docker push "${tag}"
# The RepoDigest is only created after it is pushed.
local fulltag=$(sudo docker inspect --format="{{.RepoDigests}}" "${tag}")
fulltag="${fulltag#[}"
fulltag="${fulltag%]}"
echo "Updating .gitlab-ci.yml to ${fulltag}" >&2
sed -E "s;${tag}@sha256:[0-9a-f]+;${fulltag};" \
-i "${MYDIR}/../.gitlab-ci.yml"
fi
fi
}
main() {
cd "${MYDIR}"
local target="${1:-}"
load_targets
if [[ -z "${target}" ]]; then
usage $0
exit 1
fi
if [[ "${target}" == "all" ]]; then
for target in "${TARGETS[@]}"; do
build_target "${target}"
done
else
for target in "$@"; do
build_target "${target}"
done
fi
}
main "$@"

View file

@ -0,0 +1 @@
APT::Install-Recommends "false";

View file

@ -0,0 +1,28 @@
Description: fix lack of alignment in relocations (crashes on mingw)
See https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=73af69e74974eaa155eec89867e3ccc77ab39f6d
From: Marc <marc@groundctl.com>
Date: Fri, 9 Nov 2018 11:13:50 +0000
Subject: [PATCH] Allow for compilers that do not produce aligned .rdat
sections in PE format files.
--- a/upstream/ld/scripttempl/pe.sc 2020-05-12 18:45:12.000000000 +0200
+++ b/upstream/ld/scripttempl/pe.sc 2020-05-12 18:47:12.000000000 +0200
@@ -143,6 +143,7 @@
.rdata ${RELOCATING+BLOCK(__section_alignment__)} :
{
${R_RDATA}
+ . = ALIGN(4);
${RELOCATING+__rt_psrelocs_start = .;}
${RELOCATING+KEEP(*(.rdata_runtime_pseudo_reloc))}
${RELOCATING+__rt_psrelocs_end = .;}
--- a/upstream/ld/scripttempl/pep.sc 2020-05-12 18:45:19.000000000 +0200
+++ b/upstream/ld/scripttempl/pep.sc 2020-05-12 18:47:18.000000000 +0200
@@ -143,6 +143,7 @@
.rdata ${RELOCATING+BLOCK(__section_alignment__)} :
{
${R_RDATA}
+ . = ALIGN(4);
${RELOCATING+__rt_psrelocs_start = .;}
${RELOCATING+KEEP(*(.rdata_runtime_pseudo_reloc))}
${RELOCATING+__rt_psrelocs_end = .;}

View file

@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
EMSDK_URL="https://github.com/emscripten-core/emsdk/archive/main.tar.gz"
EMSDK_DIR="/opt/emsdk"
EMSDK_RELEASE="2.0.23"
set -eu -x
# Temporary files cleanup hooks.
CLEANUP_FILES=()
cleanup() {
if [[ ${#CLEANUP_FILES[@]} -ne 0 ]]; then
rm -fr "${CLEANUP_FILES[@]}"
fi
}
trap "{ set +x; } 2>/dev/null; cleanup" INT TERM EXIT
main() {
local workdir=$(mktemp -d --suffix=emsdk)
CLEANUP_FILES+=("${workdir}")
local emsdktar="${workdir}/emsdk.tar.gz"
curl --output "${emsdktar}" "${EMSDK_URL}" --location
mkdir -p "${EMSDK_DIR}"
tar -zxf "${emsdktar}" -C "${EMSDK_DIR}" --strip-components=1
cd "${EMSDK_DIR}"
./emsdk install --shallow "${EMSDK_RELEASE}"
./emsdk activate --embedded "${EMSDK_RELEASE}"
}
main "$@"

View file

@ -0,0 +1,518 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Main entry point for all the Dockerfile for jpegxl-builder. This centralized
# file helps sharing code and configuration between Dockerfiles.
set -eux
MYDIR=$(dirname $(realpath "$0"))
# libjpeg-turbo.
JPEG_TURBO_RELEASE="2.0.4"
JPEG_TURBO_URL="https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_TURBO_RELEASE}.tar.gz"
JPEG_TURBO_SHA256="7777c3c19762940cff42b3ba4d7cd5c52d1671b39a79532050c85efb99079064"
# zlib (dependency of libpng)
ZLIB_RELEASE="1.2.11"
ZLIB_URL="https://www.zlib.net/zlib-${ZLIB_RELEASE}.tar.gz"
ZLIB_SHA256="c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1"
# The name in the .pc and the .dll generated don't match in zlib for Windows
# because they use different .dll names in Windows. We avoid that by defining
# UNIX=1. We also install all the .dll files to ${prefix}/lib instead of the
# default ${prefix}/bin.
ZLIB_FLAGS='-DUNIX=1 -DINSTALL_PKGCONFIG_DIR=/${CMAKE_INSTALL_PREFIX}/lib/pkgconfig -DINSTALL_BIN_DIR=/${CMAKE_INSTALL_PREFIX}/lib'
# libpng
LIBPNG_RELEASE="1.6.37"
LIBPNG_URL="https://github.com/glennrp/libpng/archive/v${LIBPNG_RELEASE}.tar.gz"
LIBPNG_SHA256="ca74a0dace179a8422187671aee97dd3892b53e168627145271cad5b5ac81307"
# giflib
GIFLIB_RELEASE="5.2.1"
GIFLIB_URL="https://netcologne.dl.sourceforge.net/project/giflib/giflib-${GIFLIB_RELEASE}.tar.gz"
GIFLIB_SHA256="31da5562f44c5f15d63340a09a4fd62b48c45620cd302f77a6d9acf0077879bd"
# A patch needed to compile GIFLIB in mingw.
GIFLIB_PATCH_URL="https://github.com/msys2/MINGW-packages/raw/3afde38fcee7b3ba2cafd97d76cca8f06934504f/mingw-w64-giflib/001-mingw-build.patch"
GIFLIB_PATCH_SHA256="2b2262ddea87fc07be82e10aeb39eb699239f883c899aa18a16e4d4e40af8ec8"
# webp
WEBP_RELEASE="1.0.2"
WEBP_URL="https://codeload.github.com/webmproject/libwebp/tar.gz/v${WEBP_RELEASE}"
WEBP_SHA256="347cf85ddc3497832b5fa9eee62164a37b249c83adae0ba583093e039bf4881f"
# Google benchmark
BENCHMARK_RELEASE="1.5.2"
BENCHMARK_URL="https://github.com/google/benchmark/archive/v${BENCHMARK_RELEASE}.tar.gz"
BENCHMARK_SHA256="dccbdab796baa1043f04982147e67bb6e118fe610da2c65f88912d73987e700c"
BENCHMARK_FLAGS="-DGOOGLETEST_PATH=${MYDIR}/../../third_party/googletest"
# attribute(format(__MINGW_PRINTF_FORMAT, ...)) doesn't work in our
# environment, so we disable the warning.
BENCHMARK_FLAGS="-DCMAKE_BUILD_TYPE=Release -DBENCHMARK_ENABLE_TESTING=OFF \
-DCMAKE_CXX_FLAGS=-Wno-ignored-attributes \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
# V8
V8_VERSION="9.3.22"
# Temporary files cleanup hooks.
CLEANUP_FILES=()
cleanup() {
if [[ ${#CLEANUP_FILES[@]} -ne 0 ]]; then
rm -fr "${CLEANUP_FILES[@]}"
fi
}
trap "{ set +x; } 2>/dev/null; cleanup" INT TERM EXIT
# List of Ubuntu arch names supported by the builder (such as "i386").
LIST_ARCHS=(
amd64
i386
arm64
armhf
)
# List of target triplets supported by the builder.
LIST_TARGETS=(
x86_64-linux-gnu
i686-linux-gnu
arm-linux-gnueabihf
aarch64-linux-gnu
)
LIST_MINGW_TARGETS=(
i686-w64-mingw32
x86_64-w64-mingw32
)
LIST_WASM_TARGETS=(
wasm32
)
# Setup the apt repositories and supported architectures.
setup_apt() {
apt-get update -y
apt-get install -y curl gnupg ca-certificates
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1E9377A2BA9EF27F
# node sources.
cat >/etc/apt/sources.list.d/nodesource.list <<EOF
deb https://deb.nodesource.com/node_14.x bionic main
deb-src https://deb.nodesource.com/node_14.x bionic main
EOF
curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -
local port_list=()
local main_list=()
local ubarch
for ubarch in "${LIST_ARCHS[@]}"; do
if [[ "${ubarch}" != "amd64" && "${ubarch}" != "i386" ]]; then
# other archs are not part of the main mirrors, but available in
# ports.ubuntu.com.
port_list+=("${ubarch}")
else
main_list+=("${ubarch}")
fi
# Add the arch to the system.
if [[ "${ubarch}" != "amd64" ]]; then
dpkg --add-architecture "${ubarch}"
fi
done
# Update the sources.list with the split of supported architectures.
local bkplist="/etc/apt/sources.list.bkp"
[[ -e "${bkplist}" ]] || \
mv /etc/apt/sources.list "${bkplist}"
local newlist="/etc/apt/sources.list.tmp"
rm -f "${newlist}"
port_list=$(echo "${port_list[@]}" | tr ' ' ,)
if [[ -n "${port_list}" ]]; then
local port_url="http://ports.ubuntu.com/ubuntu-ports/"
grep -v -E '^#' "${bkplist}" |
sed -E "s;^deb (http[^ ]+) (.*)\$;deb [arch=${port_list}] ${port_url} \\2;" \
>>"${newlist}"
fi
main_list=$(echo "${main_list[@]}" | tr ' ' ,)
grep -v -E '^#' "${bkplist}" |
sed -E "s;^deb (http[^ ]+) (.*)\$;deb [arch=${main_list}] \\1 \\2\ndeb-src [arch=${main_list}] \\1 \\2;" \
>>"${newlist}"
mv "${newlist}" /etc/apt/sources.list
}
install_pkgs() {
packages=(
# Native compilers (minimum for SIMD is clang-7)
clang-7 clang-format-7 clang-tidy-7
# TODO: Consider adding clang-8 to every builder:
# clang-8 clang-format-8 clang-tidy-8
# For cross-compiling to Windows with mingw.
mingw-w64
wine64
wine-binfmt
# Native tools.
bsdmainutils
cmake
extra-cmake-modules
git
llvm
nasm
ninja-build
parallel
pkg-config
# For compiling / testing JNI wrapper. JDK8 is almost 2x smaller than JDK11
# openjdk-8-jdk-headless would be 50MB smaller, unfortunately, CMake
# does mistakenly thinks it does not contain JNI feature.
openjdk-8-jdk
# These are used by the ./ci.sh lint in the native builder.
clang-format-7
clang-format-8
# For coverage builds
gcovr
# For compiling giflib documentation.
xmlto
# Common libraries.
libstdc++-8-dev
# We don't use tcmalloc on archs other than amd64. This installs
# libgoogle-perftools4:amd64.
google-perftools
# NodeJS for running WASM tests
nodejs
# To generate API documentation.
doxygen
# Freezes version that builds (passes tests). Newer version
# (2.30-21ubuntu1~18.04.4) claims to fix "On Intel Skylake
# (-march=native) generated avx512 instruction can be wrong",
# but newly added tests does not pass. Perhaps the problem is
# that mingw package is not updated.
binutils-source=2.30-15ubuntu1
)
# Install packages that are arch-dependent.
local ubarch
for ubarch in "${LIST_ARCHS[@]}"; do
packages+=(
# Library dependencies. These normally depend on the target architecture
# we are compiling for and can't usually be installed for multiple
# architectures at the same time.
libgif7:"${ubarch}"
libjpeg-dev:"${ubarch}"
libpng-dev:"${ubarch}"
libqt5x11extras5-dev:"${ubarch}"
libstdc++-8-dev:"${ubarch}"
qtbase5-dev:"${ubarch}"
# For OpenEXR:
libilmbase12:"${ubarch}"
libopenexr22:"${ubarch}"
# TCMalloc dependency
libunwind-dev:"${ubarch}"
# Cross-compiling tools per arch.
libc6-dev-"${ubarch}"-cross
libstdc++-8-dev-"${ubarch}"-cross
)
done
local target
for target in "${LIST_TARGETS[@]}"; do
# Per target cross-compiling tools.
if [[ "${target}" != "x86_64-linux-gnu" ]]; then
packages+=(
binutils-"${target}"
gcc-"${target}"
)
fi
done
# Install all the manual packages via "apt install" for the main arch. These
# will be installed for other archs via manual download and unpack.
apt install -y "${packages[@]}" "${UNPACK_PKGS[@]}"
}
# binutils <2.32 need a patch.
install_binutils() {
local workdir=$(mktemp -d --suffix=_install)
CLEANUP_FILES+=("${workdir}")
pushd "${workdir}"
apt source binutils-mingw-w64
apt -y build-dep binutils-mingw-w64
cd binutils-mingw-w64-8ubuntu1
cp "${MYDIR}/binutils_align_fix.patch" debian/patches
echo binutils_align_fix.patch >> debian/patches/series
dpkg-buildpackage -b
cd ..
dpkg -i *deb
popd
}
# Install a library from the source code for multiple targets.
# Usage: install_from_source <tar_url> <sha256> <target> [<target...>]
install_from_source() {
local package="$1"
shift
local url
eval "url=\${${package}_URL}"
local sha256
eval "sha256=\${${package}_SHA256}"
# Optional package flags
local pkgflags
eval "pkgflags=\${${package}_FLAGS:-}"
local workdir=$(mktemp -d --suffix=_install)
CLEANUP_FILES+=("${workdir}")
local tarfile="${workdir}"/$(basename "${url}")
curl -L --output "${tarfile}" "${url}"
if ! echo "${sha256} ${tarfile}" | sha256sum -c --status -; then
echo "SHA256 mismatch for ${url}: expected ${sha256} but found:"
sha256sum "${tarfile}"
exit 1
fi
local target
for target in "$@"; do
echo "Installing ${package} for target ${target} from ${url}"
local srcdir="${workdir}/source-${target}"
mkdir -p "${srcdir}"
tar -zxf "${tarfile}" -C "${srcdir}" --strip-components=1
local prefix="/usr"
if [[ "${target}" != "x86_64-linux-gnu" ]]; then
prefix="/usr/${target}"
fi
# Apply patches to buildfiles.
if [[ "${package}" == "GIFLIB" && "${target}" == *mingw32 ]]; then
# GIFLIB Makefile has several problems so we need to fix them here. We are
# using a patch from MSYS2 that already fixes the compilation for mingw.
local make_patch="${srcdir}/libgif.patch"
curl -L "${GIFLIB_PATCH_URL}" -o "${make_patch}"
echo "${GIFLIB_PATCH_SHA256} ${make_patch}" | sha256sum -c --status -
patch "${srcdir}/Makefile" < "${make_patch}"
elif [[ "${package}" == "LIBPNG" && "${target}" == wasm* ]]; then
# Cut the dependency to libm; there is pull request to fix it, so this
# might not be needed in the future.
sed -i 's/APPLE/EMSCRIPTEN/g' "${srcdir}/CMakeLists.txt"
fi
local cmake_args=()
local export_args=("CC=clang-7" "CXX=clang++-7")
local cmake="cmake"
local make="make"
local system_name="Linux"
if [[ "${target}" == *mingw32 ]]; then
system_name="Windows"
# When compiling with clang, CMake doesn't detect that we are using mingw.
cmake_args+=(
-DMINGW=1
# Googletest needs this when cross-compiling to windows
-DCMAKE_CROSSCOMPILING=1
-DHAVE_STD_REGEX=0
-DHAVE_POSIX_REGEX=0
-DHAVE_GNU_POSIX_REGEX=0
)
local windres=$(which ${target}-windres || true)
if [[ -n "${windres}" ]]; then
cmake_args+=(-DCMAKE_RC_COMPILER="${windres}")
fi
fi
if [[ "${target}" == wasm* ]]; then
system_name="WASM"
cmake="emcmake cmake"
make="emmake make"
export_args=()
cmake_args+=(
-DCMAKE_FIND_ROOT_PATH="${prefix}"
-DCMAKE_PREFIX_PATH="${prefix}"
)
# Static and shared library link to the same file -> race condition.
nproc=1
else
nproc=`nproc --all`
fi
cmake_args+=(-DCMAKE_SYSTEM_NAME="${system_name}")
if [[ "${target}" != "x86_64-linux-gnu" ]]; then
# Cross-compiling.
cmake_args+=(
-DCMAKE_C_COMPILER_TARGET="${target}"
-DCMAKE_CXX_COMPILER_TARGET="${target}"
-DCMAKE_SYSTEM_PROCESSOR="${target%%-*}"
)
fi
if [[ -e "${srcdir}/CMakeLists.txt" ]]; then
# Most packages use cmake for building which is easier to configure for
# cross-compiling.
if [[ "${package}" == "JPEG_TURBO" && "${target}" == wasm* ]]; then
# JT erroneously detects WASM CPU as i386 and tries to use asm.
# Wasm/Emscripten support for dynamic linking is incomplete; disable
# to avoid CMake warning.
cmake_args+=(-DWITH_SIMD=0 -DENABLE_SHARED=OFF)
fi
(
cd "${srcdir}"
export ${export_args[@]}
${cmake} \
-DCMAKE_INSTALL_PREFIX="${prefix}" \
"${cmake_args[@]}" ${pkgflags}
${make} -j${nproc}
${make} install
)
elif [[ "${package}" == "GIFLIB" ]]; then
# GIFLIB doesn't yet have a cmake build system. There is a pull
# request in giflib for adding CMakeLists.txt so this might not be
# needed in the future.
(
cd "${srcdir}"
local giflib_make_flags=(
CFLAGS="-O2 --target=${target} -std=gnu99"
PREFIX="${prefix}"
)
if [[ "${target}" != wasm* ]]; then
giflib_make_flags+=(CC=clang-7)
fi
# giflib make dependencies are not properly set up so parallel building
# doesn't work for everything.
${make} -j${nproc} libgif.a "${giflib_make_flags[@]}"
${make} -j${nproc} all "${giflib_make_flags[@]}"
${make} install "${giflib_make_flags[@]}"
)
else
echo "Don't know how to install ${package}"
exit 1
fi
# CMake mistakenly uses ".so" libraries and EMCC fails to link properly.
if [[ "${target}" == wasm* ]]; then
rm -f "${prefix}/lib"/*.so*
fi
done
}
# Packages that are manually unpacked for each architecture.
UNPACK_PKGS=(
libgif-dev
libclang-common-7-dev
# For OpenEXR:
libilmbase-dev
libopenexr-dev
# TCMalloc
libgoogle-perftools-dev
libtcmalloc-minimal4
libgoogle-perftools4
)
# Main script entry point.
main() {
cd "${MYDIR}"
# Configure the repositories with the sources for multi-arch cross
# compilation.
setup_apt
apt-get update -y
apt-get dist-upgrade -y
install_pkgs
install_binutils
apt clean
# Remove prebuilt Java classes cache.
rm /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/classes.jsa
# Manually extract packages for the target arch that can't install it directly
# at the same time as the native ones.
local ubarch
for ubarch in "${LIST_ARCHS[@]}"; do
if [[ "${ubarch}" != "amd64" ]]; then
local pkg
for pkg in "${UNPACK_PKGS[@]}"; do
apt download "${pkg}":"${ubarch}"
dpkg -x "${pkg}"_*_"${ubarch}".deb /
done
fi
done
# TODO: Add clang from the llvm repos. This is problematic since we are
# installing libclang-common-7-dev:"${ubarch}" from the ubuntu ports repos
# which is not available in the llvm repos so it might have a different
# version than the ubuntu ones.
# Remove the win32 libgcc version. The gcc-mingw-w64-x86-64 (and i686)
# packages install two libgcc versions:
# /usr/lib/gcc/x86_64-w64-mingw32/7.3-posix
# /usr/lib/gcc/x86_64-w64-mingw32/7.3-win32
# (exact libgcc version number depends on the package version).
#
# Clang will pick the best libgcc, sorting by version, but it doesn't
# seem to be a way to specify one or the other one, except by passing
# -nostdlib and setting all the include paths from the command line.
# To check which one is being used you can run:
# clang++-7 --target=x86_64-w64-mingw32 -v -print-libgcc-file-name
# We need to use the "posix" versions for thread support, so here we
# just remove the other one.
local target
for target in "${LIST_MINGW_TARGETS[@]}"; do
update-alternatives --set "${target}-gcc" $(which "${target}-gcc-posix")
local gcc_win32_path=$("${target}-cpp-win32" -print-libgcc-file-name)
rm -rf $(dirname "${gcc_win32_path}")
done
# TODO: Add msan for the target when cross-compiling. This only installs it
# for amd64.
./msan_install.sh
# Build and install qemu user-linux targets.
./qemu_install.sh
# Install emscripten SDK.
./emsdk_install.sh
# Setup environment for building WASM libraries from sources.
source /opt/emsdk/emsdk_env.sh
# Install some dependency libraries manually for the different targets.
install_from_source JPEG_TURBO "${LIST_MINGW_TARGETS[@]}" "${LIST_WASM_TARGETS[@]}"
install_from_source ZLIB "${LIST_MINGW_TARGETS[@]}" "${LIST_WASM_TARGETS[@]}"
install_from_source LIBPNG "${LIST_MINGW_TARGETS[@]}" "${LIST_WASM_TARGETS[@]}"
install_from_source GIFLIB "${LIST_MINGW_TARGETS[@]}" "${LIST_WASM_TARGETS[@]}"
# webp in Ubuntu is relatively old so we install it from source for everybody.
install_from_source WEBP "${LIST_TARGETS[@]}" "${LIST_MINGW_TARGETS[@]}"
install_from_source BENCHMARK "${LIST_TARGETS[@]}" "${LIST_MINGW_TARGETS[@]}"
# Install v8. v8 has better WASM SIMD support than NodeJS 14 (LTS).
# First we need the installer to install v8.
npm install jsvu -g
# install specific version;
HOME=/opt jsvu --os=linux64 "v8@${V8_VERSION}"
ln -s "/opt/.jsvu/v8-${V8_VERSION}" "/opt/.jsvu/v8"
# Cleanup.
find /var/lib/apt/lists/ -mindepth 1 -delete
}
main "$@"

View file

@ -0,0 +1,131 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
set -eu
MYDIR=$(dirname $(realpath "$0"))
# Convenience flag to pass both CMAKE_C_FLAGS and CMAKE_CXX_FLAGS
CMAKE_FLAGS=${CMAKE_FLAGS:-}
CMAKE_C_FLAGS=${CMAKE_C_FLAGS:-${CMAKE_FLAGS}}
CMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS:-${CMAKE_FLAGS}}
CMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS:-}
CLANG_VERSION="${CLANG_VERSION:-}"
# Detect the clang version suffix and store it in CLANG_VERSION. For example,
# "6.0" for clang 6 or "7" for clang 7.
detect_clang_version() {
if [[ -n "${CLANG_VERSION}" ]]; then
return 0
fi
local clang_version=$("${CC:-clang}" --version | head -n1)
local llvm_tag
case "${clang_version}" in
"clang version 6."*)
CLANG_VERSION="6.0"
;;
"clang version 7."*)
CLANG_VERSION="7"
;;
"clang version 8."*)
CLANG_VERSION="8"
;;
"clang version 9."*)
CLANG_VERSION="9"
;;
*)
echo "Unknown clang version: ${clang_version}" >&2
return 1
esac
}
# Temporary files cleanup hooks.
CLEANUP_FILES=()
cleanup() {
if [[ ${#CLEANUP_FILES[@]} -ne 0 ]]; then
rm -fr "${CLEANUP_FILES[@]}"
fi
}
trap "{ set +x; } 2>/dev/null; cleanup" INT TERM EXIT
# Install libc++ libraries compiled with msan in the msan_prefix for the current
# compiler version.
cmd_msan_install() {
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
# Detect the llvm to install:
export CC="${CC:-clang}"
export CXX="${CXX:-clang++}"
detect_clang_version
local llvm_tag
case "${CLANG_VERSION}" in
"6.0")
llvm_tag="llvmorg-6.0.1"
;;
"7")
llvm_tag="llvmorg-7.0.1"
;;
"8")
llvm_tag="llvmorg-8.0.0"
;;
*)
echo "Unknown clang version: ${clang_version}" >&2
return 1
esac
local llvm_targz="${tmpdir}/${llvm_tag}.tar.gz"
curl -L --show-error -o "${llvm_targz}" \
"https://github.com/llvm/llvm-project/archive/${llvm_tag}.tar.gz"
tar -C "${tmpdir}" -zxf "${llvm_targz}"
local llvm_root="${tmpdir}/llvm-project-${llvm_tag}"
local msan_prefix="${HOME}/.msan/${CLANG_VERSION}"
rm -rf "${msan_prefix}"
declare -A CMAKE_EXTRAS
CMAKE_EXTRAS[libcxx]="\
-DLIBCXX_CXX_ABI=libstdc++ \
-DLIBCXX_INSTALL_EXPERIMENTAL_LIBRARY=ON"
for project in libcxx; do
local proj_build="${tmpdir}/build-${project}"
local proj_dir="${llvm_root}/${project}"
mkdir -p "${proj_build}"
cmake -B"${proj_build}" -H"${proj_dir}" \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_USE_SANITIZER=Memory \
-DLLVM_PATH="${llvm_root}/llvm" \
-DLLVM_CONFIG_PATH="$(which llvm-config llvm-config-7 llvm-config-6.0 | \
head -n1)" \
-DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}" \
-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS}" \
-DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS}" \
-DCMAKE_INSTALL_PREFIX="${msan_prefix}" \
${CMAKE_EXTRAS[${project}]}
cmake --build "${proj_build}"
ninja -C "${proj_build}" install
done
}
main() {
set -x
for version in 6.0 7 8; do
if ! which "clang-${version}" >/dev/null; then
echo "Skipping msan install for clang version ${version}"
continue
fi
(
trap "{ set +x; } 2>/dev/null; cleanup" INT TERM EXIT
export CLANG_VERSION=${version}
export CC=clang-${version}
export CXX=clang++-${version}
cmd_msan_install
) &
done
wait
}
main "$@"

View file

@ -0,0 +1,83 @@
#!/usr/bin/env bash
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
QEMU_RELEASE="4.1.0"
QEMU_URL="https://download.qemu.org/qemu-${QEMU_RELEASE}.tar.xz"
QEMU_ARCHS=(
aarch64
arm
i386
# TODO: Consider adding these:
# aarch64_be
# mips64el
# mips64
# mips
# ppc64
# ppc
)
# Ubuntu packages not installed that are needed to build qemu.
QEMU_BUILD_DEPS=(
libglib2.0-dev
libpixman-1-dev
flex
bison
)
set -eu -x
# Temporary files cleanup hooks.
CLEANUP_FILES=()
cleanup() {
if [[ ${#CLEANUP_FILES[@]} -ne 0 ]]; then
rm -fr "${CLEANUP_FILES[@]}"
fi
}
trap "{ set +x; } 2>/dev/null; cleanup" INT TERM EXIT
main() {
local workdir=$(mktemp -d --suffix=qemu)
CLEANUP_FILES+=("${workdir}")
apt install -y "${QEMU_BUILD_DEPS[@]}"
local qemutar="${workdir}/qemu.tar.gz"
curl --output "${qemutar}" "${QEMU_URL}"
tar -Jxf "${qemutar}" -C "${workdir}"
local srcdir="${workdir}/qemu-${QEMU_RELEASE}"
local builddir="${workdir}/build"
local prefixdir="${workdir}/prefix"
mkdir -p "${builddir}"
# List of targets to build.
local targets=""
local make_targets=()
local target
for target in "${QEMU_ARCHS[@]}"; do
targets="${targets} ${target}-linux-user"
# Build just the linux-user targets.
make_targets+=("${target}-linux-user/all")
done
cd "${builddir}"
"${srcdir}/configure" \
--prefix="${prefixdir}" \
--static --disable-system --enable-linux-user \
--target-list="${targets}"
make -j $(nproc --all || echo 1) "${make_targets[@]}"
# Manually install these into the non-standard location. This script runs as
# root anyway.
for target in "${QEMU_ARCHS[@]}"; do
cp "${target}-linux-user/qemu-${target}" "/usr/bin/qemu-${target}-static"
done
apt autoremove -y --purge "${QEMU_BUILD_DEPS[@]}"
}
main "$@"

View file

@ -0,0 +1,56 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
# Example project using libjxl.
cmake_minimum_required(VERSION 3.10)
project(SAMPLE_LIBJXL LANGUAGES C CXX)
# Use pkg-config to find libjxl.
find_package(PkgConfig)
pkg_check_modules(Jxl REQUIRED IMPORTED_TARGET libjxl)
pkg_check_modules(JxlThreads REQUIRED IMPORTED_TARGET libjxl_threads)
# Build the example encoder/decoder binaries using the default shared libraries
# installed.
add_executable(decode_oneshot decode_oneshot.cc)
target_link_libraries(decode_oneshot PkgConfig::Jxl PkgConfig::JxlThreads)
add_executable(decode_progressive decode_progressive.cc)
target_link_libraries(decode_progressive PkgConfig::Jxl PkgConfig::JxlThreads)
add_executable(encode_oneshot encode_oneshot.cc)
target_link_libraries(encode_oneshot PkgConfig::Jxl PkgConfig::JxlThreads)
# Building a static binary with the static libjxl dependencies. How to load
# static library configs from pkg-config and how to build static binaries
# depends on the platform, and building static binaries in general has problems.
# If you don't need static binaries you can remove this section.
add_library(StaticJxl INTERFACE IMPORTED GLOBAL)
set_target_properties(StaticJxl PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Jxl_STATIC_INCLUDE_DIR}"
INTERFACE_COMPILE_OPTIONS "${Jxl_STATIC_CFLAGS_OTHER}"
INTERFACE_LINK_LIBRARIES "${Jxl_STATIC_LDFLAGS}"
)
add_library(StaticJxlThreads INTERFACE IMPORTED GLOBAL)
set_target_properties(StaticJxlThreads PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${JxlThreads_STATIC_INCLUDE_DIR}"
INTERFACE_COMPILE_OPTIONS "${JxlThreads_STATIC_CFLAGS_OTHER}"
# libgcc uses weak symbols for pthread which means that -lpthread is not
# linked when compiling a static binary. This is a platform-specific fix for
# that.
INTERFACE_LINK_LIBRARIES
"${JxlThreads_STATIC_LDFLAGS} -Wl,--whole-archive -lpthread -Wl,--no-whole-archive"
)
add_executable(decode_oneshot_static decode_oneshot.cc)
target_link_libraries(decode_oneshot_static
-static StaticJxl StaticJxlThreads)
add_executable(encode_oneshot_static encode_oneshot.cc)
target_link_libraries(encode_oneshot_static
-static StaticJxl StaticJxlThreads)

View file

@ -0,0 +1,173 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This C++ example decodes a JPEG XL image in one shot (all input bytes
// available at once). The example outputs the pixels and color information to a
// floating point image and an ICC profile on disk.
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include "jxl/decode.h"
#include "jxl/decode_cxx.h"
bool DecodeJpegXlExif(const uint8_t* jxl, size_t size,
std::vector<uint8_t>* exif) {
auto dec = JxlDecoderMake(nullptr);
// We're only interested in the Exif boxes in this example, so don't
// subscribe to events related to pixel data.
if (JXL_DEC_SUCCESS != JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BOX)) {
fprintf(stderr, "JxlDecoderSubscribeEvents failed\n");
return false;
}
bool support_decompression = true;
if (JXL_DEC_SUCCESS != JxlDecoderSetDecompressBoxes(dec.get(), JXL_TRUE)) {
fprintf(stderr,
"NOTE: decompressing brob boxes not supported with the currently "
"used jxl library.\n");
support_decompression = false;
}
JxlDecoderSetInput(dec.get(), jxl, size);
JxlDecoderCloseInput(dec.get());
const constexpr size_t kChunkSize = 65536;
size_t output_pos = 0;
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
if (status == JXL_DEC_ERROR) {
fprintf(stderr, "Decoder error\n");
return false;
} else if (status == JXL_DEC_NEED_MORE_INPUT) {
fprintf(stderr, "Error, already provided all input\n");
return false;
} else if (status == JXL_DEC_BOX) {
if (!exif->empty()) {
size_t remaining = JxlDecoderReleaseBoxBuffer(dec.get());
exif->resize(exif->size() - remaining);
// No need to wait for JXL_DEC_SUCCESS or decode other boxes.
return true;
}
JxlBoxType type;
if (JXL_DEC_SUCCESS !=
JxlDecoderGetBoxType(dec.get(), type, support_decompression)) {
fprintf(stderr, "Error, failed to get box type\n");
return false;
}
if (!memcmp(type, "Exif", 4)) {
exif->resize(kChunkSize);
JxlDecoderSetBoxBuffer(dec.get(), exif->data(), exif->size());
}
} else if (status == JXL_DEC_BOX_NEED_MORE_OUTPUT) {
size_t remaining = JxlDecoderReleaseBoxBuffer(dec.get());
output_pos += kChunkSize - remaining;
exif->resize(exif->size() + kChunkSize);
JxlDecoderSetBoxBuffer(dec.get(), exif->data() + output_pos,
exif->size() - output_pos);
} else if (status == JXL_DEC_SUCCESS) {
if (!exif->empty()) {
size_t remaining = JxlDecoderReleaseBoxBuffer(dec.get());
exif->resize(exif->size() - remaining);
return true;
}
return true;
} else {
fprintf(stderr, "Unknown decoder status\n");
return false;
}
}
}
bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
FILE* file = fopen(filename, "rb");
if (!file) {
return false;
}
if (fseek(file, 0, SEEK_END) != 0) {
fclose(file);
return false;
}
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
return false;
}
if (fseek(file, 0, SEEK_SET) != 0) {
fclose(file);
return false;
}
out->resize(size);
size_t readsize = fread(out->data(), 1, size, file);
if (fclose(file) != 0) {
return false;
}
return readsize == static_cast<size_t>(size);
}
bool WriteFile(const char* filename, const uint8_t* data, size_t size) {
FILE* file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Could not open %s for writing", filename);
return false;
}
fwrite(data, 1, size, file);
if (fclose(file) != 0) {
return false;
}
return true;
}
int main(int argc, char* argv[]) {
if (argc != 3) {
fprintf(stderr,
"Usage: %s <jxl> <exif>\n"
"Where:\n"
" jxl = input JPEG XL image filename\n"
" exif = output exif filename\n"
"Output files will be overwritten.\n",
argv[0]);
return 1;
}
const char* jxl_filename = argv[1];
const char* exif_filename = argv[2];
std::vector<uint8_t> jxl;
if (!LoadFile(jxl_filename, &jxl)) {
fprintf(stderr, "couldn't load %s\n", jxl_filename);
return 1;
}
std::vector<uint8_t> exif;
if (!DecodeJpegXlExif(jxl.data(), jxl.size(), &exif)) {
fprintf(stderr, "Error while decoding the jxl file\n");
return 1;
}
if (exif.empty()) {
printf("No exif data present in this image\n");
} else {
// TODO(lode): the exif box data contains the 4-byte TIFF header at the
// beginning, check whether this is desired to be part of the output, or
// should be removed.
if (!WriteFile(exif_filename, exif.data(), exif.size())) {
fprintf(stderr, "Error while writing the exif file\n");
return 1;
}
printf("Successfully wrote %s\n", exif_filename);
}
return 0;
}

View file

@ -0,0 +1,248 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This C++ example decodes a JPEG XL image in one shot (all input bytes
// available at once). The example outputs the pixels and color information to a
// floating point image and an ICC profile on disk.
#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include "jxl/decode.h"
#include "jxl/decode_cxx.h"
#include "jxl/resizable_parallel_runner.h"
#include "jxl/resizable_parallel_runner_cxx.h"
/** Decodes JPEG XL image to floating point pixels and ICC Profile. Pixel are
* stored as floating point, as interleaved RGBA (4 floating point values per
* pixel), line per line from top to bottom. Pixel values have nominal range
* 0..1 but may go beyond this range for HDR or wide gamut. The ICC profile
* describes the color format of the pixel data.
*/
bool DecodeJpegXlOneShot(const uint8_t* jxl, size_t size,
std::vector<float>* pixels, size_t* xsize,
size_t* ysize, std::vector<uint8_t>* icc_profile) {
// Multi-threaded parallel runner.
auto runner = JxlResizableParallelRunnerMake(nullptr);
auto dec = JxlDecoderMake(nullptr);
if (JXL_DEC_SUCCESS !=
JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO |
JXL_DEC_COLOR_ENCODING |
JXL_DEC_FULL_IMAGE)) {
fprintf(stderr, "JxlDecoderSubscribeEvents failed\n");
return false;
}
if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(dec.get(),
JxlResizableParallelRunner,
runner.get())) {
fprintf(stderr, "JxlDecoderSetParallelRunner failed\n");
return false;
}
JxlBasicInfo info;
JxlPixelFormat format = {4, JXL_TYPE_FLOAT, JXL_NATIVE_ENDIAN, 0};
JxlDecoderSetInput(dec.get(), jxl, size);
JxlDecoderCloseInput(dec.get());
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
if (status == JXL_DEC_ERROR) {
fprintf(stderr, "Decoder error\n");
return false;
} else if (status == JXL_DEC_NEED_MORE_INPUT) {
fprintf(stderr, "Error, already provided all input\n");
return false;
} else if (status == JXL_DEC_BASIC_INFO) {
if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &info)) {
fprintf(stderr, "JxlDecoderGetBasicInfo failed\n");
return false;
}
*xsize = info.xsize;
*ysize = info.ysize;
JxlResizableParallelRunnerSetThreads(
runner.get(),
JxlResizableParallelRunnerSuggestThreads(info.xsize, info.ysize));
} else if (status == JXL_DEC_COLOR_ENCODING) {
// Get the ICC color profile of the pixel data
size_t icc_size;
if (JXL_DEC_SUCCESS !=
JxlDecoderGetICCProfileSize(
dec.get(), &format, JXL_COLOR_PROFILE_TARGET_DATA, &icc_size)) {
fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n");
return false;
}
icc_profile->resize(icc_size);
if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
dec.get(), &format,
JXL_COLOR_PROFILE_TARGET_DATA,
icc_profile->data(), icc_profile->size())) {
fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
return false;
}
} else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
size_t buffer_size;
if (JXL_DEC_SUCCESS !=
JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size)) {
fprintf(stderr, "JxlDecoderImageOutBufferSize failed\n");
return false;
}
if (buffer_size != *xsize * *ysize * 16) {
fprintf(stderr, "Invalid out buffer size %" PRIu64 " %" PRIu64 "\n",
static_cast<uint64_t>(buffer_size),
static_cast<uint64_t>(*xsize * *ysize * 16));
return false;
}
pixels->resize(*xsize * *ysize * 4);
void* pixels_buffer = (void*)pixels->data();
size_t pixels_buffer_size = pixels->size() * sizeof(float);
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format,
pixels_buffer,
pixels_buffer_size)) {
fprintf(stderr, "JxlDecoderSetImageOutBuffer failed\n");
return false;
}
} else if (status == JXL_DEC_FULL_IMAGE) {
// Nothing to do. Do not yet return. If the image is an animation, more
// full frames may be decoded. This example only keeps the last one.
} else if (status == JXL_DEC_SUCCESS) {
// All decoding successfully finished.
// It's not required to call JxlDecoderReleaseInput(dec.get()) here since
// the decoder will be destroyed.
return true;
} else {
fprintf(stderr, "Unknown decoder status\n");
return false;
}
}
}
/** Writes to .pfm file (Portable FloatMap). Gimp, tev viewer and ImageMagick
* support viewing this format.
* The input pixels are given as 32-bit floating point with 4-channel RGBA.
* The alpha channel will not be written since .pfm does not support it.
*/
bool WritePFM(const char* filename, const float* pixels, size_t xsize,
size_t ysize) {
FILE* file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Could not open %s for writing", filename);
return false;
}
uint32_t endian_test = 1;
uint8_t little_endian[4];
memcpy(little_endian, &endian_test, 4);
fprintf(file, "PF\n%d %d\n%s\n", (int)xsize, (int)ysize,
little_endian[0] ? "-1.0" : "1.0");
for (int y = ysize - 1; y >= 0; y--) {
for (size_t x = 0; x < xsize; x++) {
for (size_t c = 0; c < 3; c++) {
const float* f = &pixels[(y * xsize + x) * 4 + c];
fwrite(f, 4, 1, file);
}
}
}
if (fclose(file) != 0) {
return false;
}
return true;
}
bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
FILE* file = fopen(filename, "rb");
if (!file) {
return false;
}
if (fseek(file, 0, SEEK_END) != 0) {
fclose(file);
return false;
}
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
return false;
}
if (fseek(file, 0, SEEK_SET) != 0) {
fclose(file);
return false;
}
out->resize(size);
size_t readsize = fread(out->data(), 1, size, file);
if (fclose(file) != 0) {
return false;
}
return readsize == static_cast<size_t>(size);
}
bool WriteFile(const char* filename, const uint8_t* data, size_t size) {
FILE* file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Could not open %s for writing", filename);
return false;
}
fwrite(data, 1, size, file);
if (fclose(file) != 0) {
return false;
}
return true;
}
int main(int argc, char* argv[]) {
if (argc != 4) {
fprintf(stderr,
"Usage: %s <jxl> <pfm> <icc>\n"
"Where:\n"
" jxl = input JPEG XL image filename\n"
" pfm = output Portable FloatMap image filename\n"
" icc = output ICC color profile filename\n"
"Output files will be overwritten.\n",
argv[0]);
return 1;
}
const char* jxl_filename = argv[1];
const char* pfm_filename = argv[2];
const char* icc_filename = argv[3];
std::vector<uint8_t> jxl;
if (!LoadFile(jxl_filename, &jxl)) {
fprintf(stderr, "couldn't load %s\n", jxl_filename);
return 1;
}
std::vector<float> pixels;
std::vector<uint8_t> icc_profile;
size_t xsize = 0, ysize = 0;
if (!DecodeJpegXlOneShot(jxl.data(), jxl.size(), &pixels, &xsize, &ysize,
&icc_profile)) {
fprintf(stderr, "Error while decoding the jxl file\n");
return 1;
}
if (!WritePFM(pfm_filename, pixels.data(), xsize, ysize)) {
fprintf(stderr, "Error while writing the PFM image file\n");
return 1;
}
if (!WriteFile(icc_filename, icc_profile.data(), icc_profile.size())) {
fprintf(stderr, "Error while writing the ICC profile file\n");
return 1;
}
printf("Successfully wrote %s and %s\n", pfm_filename, icc_filename);
return 0;
}

View file

@ -0,0 +1,238 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This C++ example decodes a JPEG XL image progressively (input bytes are
// passed in chunks). The example outputs the intermediate steps to PAM files.
#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include "jxl/decode.h"
#include "jxl/decode_cxx.h"
#include "jxl/resizable_parallel_runner.h"
#include "jxl/resizable_parallel_runner_cxx.h"
bool WritePAM(const char* filename, const uint8_t* buffer, size_t w, size_t h) {
FILE* fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Could not open %s for writing", filename);
return false;
}
fprintf(fp,
"P7\nWIDTH %" PRIu64 "\nHEIGHT %" PRIu64
"\nDEPTH 4\nMAXVAL 255\nTUPLTYPE "
"RGB_ALPHA\nENDHDR\n",
static_cast<uint64_t>(w), static_cast<uint64_t>(h));
fwrite(buffer, 1, w * h * 4, fp);
if (fclose(fp) != 0) {
return false;
}
return true;
}
/** Decodes JPEG XL image to 8-bit integer RGBA pixels and an ICC Profile, in a
* progressive way, saving the intermediate steps.
*/
bool DecodeJpegXlProgressive(const uint8_t* jxl, size_t size,
const char* filename, size_t chunksize) {
std::vector<uint8_t> pixels;
std::vector<uint8_t> icc_profile;
size_t xsize = 0, ysize = 0;
// Multi-threaded parallel runner.
auto runner = JxlResizableParallelRunnerMake(nullptr);
auto dec = JxlDecoderMake(nullptr);
if (JXL_DEC_SUCCESS !=
JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO |
JXL_DEC_COLOR_ENCODING |
JXL_DEC_FULL_IMAGE)) {
fprintf(stderr, "JxlDecoderSubscribeEvents failed\n");
return false;
}
if (JXL_DEC_SUCCESS != JxlDecoderSetParallelRunner(dec.get(),
JxlResizableParallelRunner,
runner.get())) {
fprintf(stderr, "JxlDecoderSetParallelRunner failed\n");
return false;
}
JxlBasicInfo info;
JxlPixelFormat format = {4, JXL_TYPE_UINT8, JXL_NATIVE_ENDIAN, 0};
size_t seen = 0;
JxlDecoderSetInput(dec.get(), jxl, chunksize);
size_t remaining = chunksize;
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
if (status == JXL_DEC_ERROR) {
fprintf(stderr, "Decoder error\n");
return false;
} else if (status == JXL_DEC_NEED_MORE_INPUT || status == JXL_DEC_SUCCESS ||
status == JXL_DEC_FULL_IMAGE) {
seen += remaining - JxlDecoderReleaseInput(dec.get());
printf("Flushing after %" PRIu64 " bytes\n", static_cast<uint64_t>(seen));
if (status == JXL_DEC_NEED_MORE_INPUT &&
JXL_DEC_SUCCESS != JxlDecoderFlushImage(dec.get())) {
printf("flush error (no preview yet)\n");
} else {
char fname[1024];
if (snprintf(fname, 1024, "%s-%" PRIu64 ".pam", filename,
static_cast<uint64_t>(seen)) >= 1024) {
fprintf(stderr, "Filename too long\n");
return false;
};
if (!WritePAM(fname, pixels.data(), xsize, ysize)) {
fprintf(stderr, "Error writing progressive output\n");
}
}
remaining = size - seen;
if (remaining > chunksize) remaining = chunksize;
if (remaining == 0) {
if (status == JXL_DEC_NEED_MORE_INPUT) {
fprintf(stderr, "Error, already provided all input\n");
return false;
} else {
return true;
}
}
JxlDecoderSetInput(dec.get(), jxl + seen, remaining);
} else if (status == JXL_DEC_BASIC_INFO) {
if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &info)) {
fprintf(stderr, "JxlDecoderGetBasicInfo failed\n");
return false;
}
xsize = info.xsize;
ysize = info.ysize;
JxlResizableParallelRunnerSetThreads(
runner.get(),
JxlResizableParallelRunnerSuggestThreads(info.xsize, info.ysize));
} else if (status == JXL_DEC_COLOR_ENCODING) {
// Get the ICC color profile of the pixel data
size_t icc_size;
if (JXL_DEC_SUCCESS !=
JxlDecoderGetICCProfileSize(dec.get(), &format,
JXL_COLOR_PROFILE_TARGET_ORIGINAL,
&icc_size)) {
fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n");
return false;
}
icc_profile.resize(icc_size);
if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
dec.get(), &format,
JXL_COLOR_PROFILE_TARGET_ORIGINAL,
icc_profile.data(), icc_profile.size())) {
fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
return false;
}
} else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER) {
size_t buffer_size;
if (JXL_DEC_SUCCESS !=
JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size)) {
fprintf(stderr, "JxlDecoderImageOutBufferSize failed\n");
return false;
}
if (buffer_size != xsize * ysize * 4) {
fprintf(stderr, "Invalid out buffer size %" PRIu64 " != %" PRIu64 "\n",
static_cast<uint64_t>(buffer_size),
static_cast<uint64_t>(xsize * ysize * 4));
return false;
}
pixels.resize(xsize * ysize * 4);
void* pixels_buffer = (void*)pixels.data();
size_t pixels_buffer_size = pixels.size() * sizeof(float);
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format,
pixels_buffer,
pixels_buffer_size)) {
fprintf(stderr, "JxlDecoderSetImageOutBuffer failed\n");
return false;
}
} else {
fprintf(stderr, "Unknown decoder status\n");
return false;
}
}
}
bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
FILE* file = fopen(filename, "rb");
if (!file) {
return false;
}
if (fseek(file, 0, SEEK_END) != 0) {
fclose(file);
return false;
}
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
return false;
}
if (fseek(file, 0, SEEK_SET) != 0) {
fclose(file);
return false;
}
out->resize(size);
size_t readsize = fread(out->data(), 1, size, file);
if (fclose(file) != 0) {
return false;
}
return readsize == static_cast<size_t>(size);
}
int main(int argc, char* argv[]) {
if (argc < 3) {
fprintf(
stderr,
"Usage: %s <jxl> <basename> [chunksize]\n"
"Where:\n"
" jxl = input JPEG XL image filename\n"
" basename = prefix of output filenames\n"
" chunksize = loads chunksize bytes at a time and writes\n"
" intermediate results to basename-[bytes loaded].pam\n"
"Output files will be overwritten.\n",
argv[0]);
return 1;
}
const char* jxl_filename = argv[1];
const char* png_filename = argv[2];
std::vector<uint8_t> jxl;
if (!LoadFile(jxl_filename, &jxl)) {
fprintf(stderr, "couldn't load %s\n", jxl_filename);
return 1;
}
size_t chunksize = jxl.size();
if (argc > 3) {
long cs = atol(argv[3]);
if (cs < 100) {
fprintf(stderr, "Chunk size is too low, try at least 100 bytes\n");
return 1;
}
chunksize = cs;
}
if (!DecodeJpegXlProgressive(jxl.data(), jxl.size(), png_filename,
chunksize)) {
fprintf(stderr, "Error while decoding the jxl file\n");
return 1;
}
return 0;
}

View file

@ -0,0 +1,276 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This example encodes a file containing a floating point image to another
// file containing JPEG XL image with a single frame.
#include <limits.h>
#include <string.h>
#include <sstream>
#include <string>
#include <vector>
#include "jxl/encode.h"
#include "jxl/encode_cxx.h"
#include "jxl/thread_parallel_runner.h"
#include "jxl/thread_parallel_runner_cxx.h"
/**
* Reads from .pfm file (Portable FloatMap)
*
* @param filename name of the file to read
* @param pixels vector to fill with loaded pixels as 32-bit floating point with
* 3-channel RGB
* @param xsize set to width of loaded image
* @param ysize set to height of loaded image
*/
bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
uint32_t* ysize) {
FILE* file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "Could not open %s for reading.\n", filename);
return false;
}
uint32_t endian_test = 1;
uint8_t little_endian[4];
memcpy(little_endian, &endian_test, 4);
if (fseek(file, 0, SEEK_END) != 0) {
fclose(file);
return false;
}
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
return false;
}
if (fseek(file, 0, SEEK_SET) != 0) {
fclose(file);
return false;
}
std::vector<char> data;
data.resize(size);
size_t readsize = fread(data.data(), 1, size, file);
if ((long)readsize != size) {
return false;
}
if (fclose(file) != 0) {
return false;
}
std::stringstream datastream;
std::string datastream_content(data.data(), data.size());
datastream.str(datastream_content);
std::string pf_token;
getline(datastream, pf_token, '\n');
if (pf_token != "PF") {
fprintf(stderr,
"%s doesn't seem to be a 3 channel Portable FloatMap file (missing "
"'PF\\n' "
"bytes).\n",
filename);
return false;
}
std::string xsize_token;
getline(datastream, xsize_token, ' ');
*xsize = std::stoi(xsize_token);
std::string ysize_token;
getline(datastream, ysize_token, '\n');
*ysize = std::stoi(ysize_token);
std::string endianness_token;
getline(datastream, endianness_token, '\n');
bool input_little_endian;
if (endianness_token == "1.0") {
input_little_endian = false;
} else if (endianness_token == "-1.0") {
input_little_endian = true;
} else {
fprintf(stderr,
"%s doesn't seem to be a Portable FloatMap file (endianness token "
"isn't '1.0' or '-1.0').\n",
filename);
return false;
}
size_t offset = pf_token.size() + 1 + xsize_token.size() + 1 +
ysize_token.size() + 1 + endianness_token.size() + 1;
if (data.size() != *ysize * *xsize * 3 * 4 + offset) {
fprintf(stderr,
"%s doesn't seem to be a Portable FloatMap file (pixel data bytes "
"are %d, but expected %d * %d * 3 * 4 + %d (%d).\n",
filename, (int)data.size(), (int)*ysize, (int)*xsize, (int)offset,
(int)(*ysize * *xsize * 3 * 4 + offset));
return false;
}
if (!!little_endian[0] != input_little_endian) {
fprintf(stderr,
"%s has a different endianness than we do, conversion is not "
"supported.\n",
filename);
return false;
}
pixels->resize(*ysize * *xsize * 3);
for (int y = *ysize - 1; y >= 0; y--) {
for (int x = 0; x < (int)*xsize; x++) {
for (int c = 0; c < 3; c++) {
memcpy(pixels->data() + (y * *xsize + x) * 3 + c, data.data() + offset,
sizeof(float));
offset += sizeof(float);
}
}
}
return true;
}
/**
* Compresses the provided pixels.
*
* @param pixels input pixels
* @param xsize width of the input image
* @param ysize height of the input image
* @param compressed will be populated with the compressed bytes
*/
bool EncodeJxlOneshot(const std::vector<float>& pixels, const uint32_t xsize,
const uint32_t ysize, std::vector<uint8_t>* compressed) {
auto enc = JxlEncoderMake(/*memory_manager=*/nullptr);
auto runner = JxlThreadParallelRunnerMake(
/*memory_manager=*/nullptr,
JxlThreadParallelRunnerDefaultNumWorkerThreads());
if (JXL_ENC_SUCCESS != JxlEncoderSetParallelRunner(enc.get(),
JxlThreadParallelRunner,
runner.get())) {
fprintf(stderr, "JxlEncoderSetParallelRunner failed\n");
return false;
}
JxlPixelFormat pixel_format = {3, JXL_TYPE_FLOAT, JXL_NATIVE_ENDIAN, 0};
JxlBasicInfo basic_info;
JxlEncoderInitBasicInfo(&basic_info);
basic_info.xsize = xsize;
basic_info.ysize = ysize;
basic_info.bits_per_sample = 32;
basic_info.exponent_bits_per_sample = 8;
basic_info.uses_original_profile = JXL_FALSE;
if (JXL_ENC_SUCCESS != JxlEncoderSetBasicInfo(enc.get(), &basic_info)) {
fprintf(stderr, "JxlEncoderSetBasicInfo failed\n");
return false;
}
JxlColorEncoding color_encoding = {};
JxlColorEncodingSetToSRGB(&color_encoding,
/*is_gray=*/pixel_format.num_channels < 3);
if (JXL_ENC_SUCCESS !=
JxlEncoderSetColorEncoding(enc.get(), &color_encoding)) {
fprintf(stderr, "JxlEncoderSetColorEncoding failed\n");
return false;
}
JxlEncoderFrameSettings* frame_settings =
JxlEncoderFrameSettingsCreate(enc.get(), nullptr);
if (JXL_ENC_SUCCESS !=
JxlEncoderAddImageFrame(frame_settings, &pixel_format,
(void*)pixels.data(),
sizeof(float) * pixels.size())) {
fprintf(stderr, "JxlEncoderAddImageFrame failed\n");
return false;
}
JxlEncoderCloseInput(enc.get());
compressed->resize(64);
uint8_t* next_out = compressed->data();
size_t avail_out = compressed->size() - (next_out - compressed->data());
JxlEncoderStatus process_result = JXL_ENC_NEED_MORE_OUTPUT;
while (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
process_result = JxlEncoderProcessOutput(enc.get(), &next_out, &avail_out);
if (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
size_t offset = next_out - compressed->data();
compressed->resize(compressed->size() * 2);
next_out = compressed->data() + offset;
avail_out = compressed->size() - offset;
}
}
compressed->resize(next_out - compressed->data());
if (JXL_ENC_SUCCESS != process_result) {
fprintf(stderr, "JxlEncoderProcessOutput failed\n");
return false;
}
return true;
}
/**
* Writes bytes to file.
*/
bool WriteFile(const std::vector<uint8_t>& bytes, const char* filename) {
FILE* file = fopen(filename, "wb");
if (!file) {
fprintf(stderr, "Could not open %s for writing\n", filename);
return false;
}
if (fwrite(bytes.data(), sizeof(uint8_t), bytes.size(), file) !=
bytes.size()) {
fprintf(stderr, "Could not write bytes to %s\n", filename);
return false;
}
if (fclose(file) != 0) {
fprintf(stderr, "Could not close %s\n", filename);
return false;
}
return true;
}
int main(int argc, char* argv[]) {
if (argc != 3) {
fprintf(stderr,
"Usage: %s <pfm> <jxl>\n"
"Where:\n"
" pfm = input Portable FloatMap image filename\n"
" jxl = output JPEG XL image filename\n"
"Output files will be overwritten.\n",
argv[0]);
return 1;
}
const char* pfm_filename = argv[1];
const char* jxl_filename = argv[2];
std::vector<float> pixels;
uint32_t xsize;
uint32_t ysize;
if (!ReadPFM(pfm_filename, &pixels, &xsize, &ysize)) {
fprintf(stderr, "Couldn't load %s\n", pfm_filename);
return 2;
}
std::vector<uint8_t> compressed;
if (!EncodeJxlOneshot(pixels, xsize, ysize, &compressed)) {
fprintf(stderr, "Couldn't encode jxl\n");
return 3;
}
if (!WriteFile(compressed, jxl_filename)) {
fprintf(stderr, "Couldn't write jxl file\n");
return 4;
}
return 0;
}

View file

@ -0,0 +1,11 @@
# Copyright (c) the JPEG XL Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
add_executable(decode_oneshot ${CMAKE_CURRENT_LIST_DIR}/decode_oneshot.cc)
target_link_libraries(decode_oneshot jxl_dec jxl_threads)
add_executable(decode_progressive ${CMAKE_CURRENT_LIST_DIR}/decode_progressive.cc)
target_link_libraries(decode_progressive jxl_dec jxl_threads)
add_executable(encode_oneshot ${CMAKE_CURRENT_LIST_DIR}/encode_oneshot.cc)
target_link_libraries(encode_oneshot jxl jxl_threads)

Some files were not shown because too many files have changed in this diff Show more