Issue #2697 - Part 1: Import libjxl 0.11.1 files to the tree.

This commit is contained in:
Moonchild 2025-03-10 23:05:20 +01:00 committed by roytam1
commit 845db2526f
910 changed files with 84393 additions and 51559 deletions

View file

@ -0,0 +1 @@
third_party

View file

@ -1,6 +1,4 @@
# 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>.
@ -27,17 +25,34 @@ Checks: >-
modernize-*,
performance-*,
readability-*,
-google-readability-todo,
-bugprone-branch-clone,
-bugprone-easily-swappable-parameters,
-bugprone-implicit-widening-of-multiplication-result,
-bugprone-infinite-loop,
-bugprone-narrowing-conversions,
-bugprone-unused-local-non-trivial-variable,
-modernize-avoid-c-arrays,
-modernize-concat-nested-namespaces,
-modernize-deprecated-headers,
-modernize-return-braced-init-list,
-modernize-type-traits,
-modernize-use-auto,
-modernize-use-default-member-init,
-modernize-use-nodiscard,
-modernize-use-trailing-return-type,
-modernize-use-using,
-performance-enum-size,
-readability-avoid-nested-conditional-operator,
-readability-else-after-return,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-magic-numbers,
-readability-redundant-access-specifiers,
-readability-simplify-boolean-expr,
-readability-static-accessed-through-instance,
-readability-suspicious-call-argument,
-readability-uppercase-literal-suffix,
-readability-use-anyofallof,
WarningsAsErrors: >-
@ -60,11 +75,13 @@ WarningsAsErrors: >-
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'
- 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'
- key: bugprone-signed-char-misuse.CharTypdefsToIgnore
value: 'int8_t'

View file

@ -1,7 +1,10 @@
# Build output directories
/build
/build*
/docker/*.log
/bazel*
# clangd
.cache
# The downloaded corpora files for benchmark.
/third_party/corpora

View file

@ -25,3 +25,6 @@
[submodule "third_party/testdata"]
path = testdata
url = https://github.com/libjxl/testdata
[submodule "third_party/libjpeg-turbo"]
path = third_party/libjpeg-turbo
url = https://github.com/libjpeg-turbo/libjpeg-turbo.git

View file

@ -0,0 +1,30 @@
repos:
- repo: https://github.com/gherynos/pre-commit-java
rev: v0.2.4
hooks:
- id: Checkstyle
- repo: https://github.com/gitleaks/gitleaks
rev: v8.16.3
hooks:
- id: gitleaks
- repo: https://github.com/jumanjihouse/pre-commit-hooks
rev: 3.0.0
hooks:
- id: shellcheck
- repo: https://github.com/pocc/pre-commit-hooks
rev: v1.3.5
hooks:
- id: cpplint
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.38.0
hooks:
- id: eslint
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pylint-dev/pylint
rev: v2.17.2
hooks:
- id: pylint

View file

@ -11,7 +11,14 @@ version: 2
sphinx:
configuration: doc/sphinx/conf.py
build:
os: ubuntu-22.04
tools:
python: "3"
apt_packages:
- doxygen
- graphviz
python:
version: "3.7"
install:
- requirements: doc/sphinx/requirements.txt

View file

@ -1,38 +1,75 @@
# 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.
# List of the project authors.
# When contributing you can add your name to this list.
# For a complete list of contributions made after the move
# from gitlab to github, see
# https://github.com/libjxl/libjxl/graphs/contributors.
# 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>
# - Cloudinary Ltd.:
Jon Sneyers <jon@cloudinary.com>
# - Google:
Evgenii Kliuchnikov <eustas@google.com>
Iulia Comșa <iuliacomsa@google.com>
Jan Wassenberg <janwas@google.com>
Jyrki Alakuijala <jyrki@google.com>
Lode Vandevenne <lode@google.com>
Luca Versari <veluca@google.com>
Marcin Kowalczyk <qrczak@google.com>
Martin Bruse <zond@google.com>
Moritz Firsching <firsching@google.com>
Sami Boukortt <sboukortt@google.com>
Sebastian Gomez <sggonzalez@google.com>
Thomas Fischbacher <tfish@google.com>
Zoltan Szabadka <szabadka@google.com>
# Individuals:
a-shvedov
Aditya Patadia <adityapatadia@users.noreply.github.com>
Ahmad Amsyar Asyadiq Bin Syaiful Bahri <27284123+Ahmad-Amsyar@users.noreply.github.com>
Alex Xu (Hello71) <alex_y_xu@yahoo.ca>
Alexander Sago <cagelight@gmail.com>
Alifian Caesar Khalid <alifiancaesar@gmail.com>
Alistair Barrow
Andrius Lukas Narbutas <andrius4669@gmail.com>
Aous Naman <aous@unsw.edu.au>
Artem Selishchev
Aryan Pingle <realaryanpingle@gmail.com>
Biswapriyo Nath <nathbappai@gmail.com>
CanadianBaconBoi <beamconnor@gmail.com>
Damiano Albani <damiano.albani@gmail.com>
Damon Townsend
Daniel Novomeský <dnovomesky@gmail.com>
David Burnett <vargolsoft@gmail.com>
dependabot[bot]
Diego Pino <dpino@igalia.com>
Dirk Lemstra <dirk@lemstra.org>
Dmitry Baryshev <dima8w@gmail.com>
Don Olmstead <don.j.olmstead@gmail.com>
Dong Xu <xdong181@gmail.com>
estrogently <41487185+estrogently@users.noreply.github.com>
Even Rouault <even.rouault@spatialys.com>
Fred Brennan <copypaste@kittens.ph>
Gerhard Huber <support@pl32.com>
gi-man
Gilles Devillers (GilDev) <gildev@gmail.com>
Heiko Becker <heirecka@exherbo.org>
Jon Sneyers <jon@cloudinary.com>
Ivan Kokorev
Jim Robinson <jimbo2150@gmail.com>
John Platts <john_platts@hotmail.com>
Jonathan Brown (Jonnyawsom3) <jonathanbr30@gmail.com>
Joshua Root <jmr@macports.org>
Kai Hollberg <Schweinepriester@users.noreply.github.com>
Kerry Su <me@sshockwave.net>
Kleis Auke Wolthuizen <github@kleisauke.nl>
L. E. Segovia
ledoge
Leo Izen <leo.izen@gmail.com>
Lovell Fuller
Maarten DB <anonymous.maarten@gmail.com>
@ -41,14 +78,26 @@ Martin Strunz
Mathieu Malaterre <mathieu.malaterre@gmail.com>
Mikk Leini <mikk.leini@krakul.eu>
Misaki Kasumi <misakikasumi@outlook.com>
Moonchild Straver <moonchild@palemoon.org>
Nicholas Hayes <0xC0000054@users.noreply.github.com>
Nigel Tao <nigeltao@golang.org>
oupson <oupson1er@gmail.com>
Petr Diblík
Pieter Wuille
roland-rollo
Samuel Leong <wvvwvvvvwvvw@gmail.com>
Sandro <sandro.jaeckel@gmail.com>
sandstrom
Sergey Fedorov <vital.had@gmail.com>
Stephan T. Lavavej <stl@nuwen.net>
StepSecurity Bot <bot@stepsecurity.io>
Sylvestre Ledru <sylvestre@debian.org>
Thomas Bonfort <thomas.bonfort@airbus.com>
Timo Rothenpieler <timo@rothenpieler.org>
tmkk <tmkkmac@gmail.com>
Vincent Torri <vincent.torri@gmail.com>
Wonwoo Choi <chwo9843@gmail.com>
xiota
Yonatan Nebenzhal <yonatan.nebenzhl@gmail.com>
Ziemowit Zabawa <ziemek.zabawa@outlook.com>
源文雨 <41315874+fumiama@users.noreply.github.com>

View file

@ -5,7 +5,149 @@ 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.11.1] - 2024-26-11
### Fixed
- Huffman lookup table size fix (#3871 -
[CVE-2024-11403](https://www.cve.org/cverecord?id=CVE-2024-11403))
- Check height limit in modular trees. (#3943 -
[CVE-2024-11498](https://www.cve.org/cverecord?id=CVE-2024-11498))
## [0.11.0] - 2024-09-13
### Added
- Gain Map API (#3552 and #3628): `JxlGainMapBundle` struct and API functions
to read and write gain map bundles`JxlGainMapWriteBundle` and
`JxlGainMapReadBundle` as well as handling compressed ICC profiles:
`JxlICCProfileEncode` and `JxlICCProfileDecode`.
- decoder API: added `JXL_DEC_BOX_COMPLETE` event to signal that the output
buffer for the current box has received all contents. Previously, this was
to be determined from the fact that the decoder had moved on either to
`JXL_DEC_SUCCESS` or to another subsequent `JXL_DEC_BOX`. This change is
made backward-compatible by the fact that the new event must be explicitly
subscribed to, and that `JXL_DEC_SUCCESS` / `JXL_DEC_BOX` still occur
afterwards and still imply that the previous box must be complete.
### Changed / clarified
- avoiding abort in release build (#3631 and #3639)
## [0.10.2] - 2024-03-08
### Fixed
- bugs in (lossless) encoding (#3367, #3359 and #3386)
- re-enable installation of MIME file (#3375)
- bugs in streaming mode (#3379 and #3380)
## [0.10.1] - 2024-02-28
### Fixed
- reduce allocations (#3336 and #3339),
fixing a significant speed regression present since 0.9.0
- bug in streaming encoding (#3331)
## [0.10.0] - 2024-02-21
### Added
- decoder API: added `JxlDecoderGetBoxSizeContents` for getting the size of the
content of a box without the headers.
- encoder API: implemented new api functions for streaming encoding.
### Changed / clarified
- decoder/encoder API: return failure when surface allocation fail
- encoder API / cjxl: updated modular effort levels to faster settings; the
effort range is now 1-10, with 11 available in advanced mode.
## [0.9.2] - 2024-02-07
### Fixed
- bugs in the gdk-pixbuf plugin
- some build issues
## [0.9.1] - 2024-01-08
### Fixed
- multiple build issues
## [0.9.0] - 2023-12-22
### Added
- encoder API: add `JxlEncoderSetExtraChannelDistance` to adjust the quality
of extra channels (like alpha) separately.
- encoder API: new api functions for streaming encoding:
- `JxlEncoderSetOutputProcessor`
- `JxlEncoderFlushInput`
- `JxlEncoderOutputProcessor` struct
- `JxlEncoderSetOutputCallback`
- `JxlChunkedFrameInputSource` struct
- `JxlEncoderAddChunkedFrame`
- encoder API: new options for more fine-grained control over metadata
preservation when using `JxlEncoderAddJPEGFrame`:
- `JXL_ENC_FRAME_SETTING_JPEG_KEEP_EXIF`
- `JXL_ENC_FRAME_SETTING_JPEG_KEEP_XMP`
- `JXL_ENC_FRAME_SETTING_JPEG_KEEP_JUMBF`
- encoder API: new function `JxlEncoderSetUpsamplingMode` to change the upsampling
method, e.g. to use nearest-neighbor upsampling for pixel art
- decoder API: implemented `JxlDecoderSetOutputColorProfile` and
`JxlDecoderSetCms` to enable decoding to desired colorspace.
- cjxl can now be used to explicitly add/update/strip Exif/XMP/JUMBF metadata using
the decoder-hints syntax, e.g. `cjxl input.ppm -x exif=input.exif output.jxl`
- djxl can now be used to extract Exif/XMP/JUMBF metadata
- encoder API: new function `JxlEncoderDistanceFromQuality` for convenience to
calculate a `distance` given a `quality`
### Removed
- API: the Butteraugli API (`jxl/butteraugli.h`) was removed.
- encoder and decoder API: all deprecated functions were removed:
`JxlDecoderDefaultPixelFormat`, `JxlEncoderOptionsSetLossless`,
`JxlEncoderOptionsSetEffort`, `JxlEncoderOptionsSetDecodingSpeed`,
`JxlEncoderOptionsSetDistance`, `JxlEncoderOptionsCreate`, as well as
the deprecated enumerator values `JXL_DEC_EXTENSIONS`, `JXL_ENC_NOT_SUPPORTED`,
`JXL_TYPE_BOOLEAN`, `JXL_TYPE_UINT32`, and deprecated type `JxlEncoderOptions`.
- decoder API: the signature of `JxlDecoderGetColorAsEncodedProfile`,
`JxlDecoderGetICCProfileSize`, and `JxlDecoderGetColorAsICCProfile`
changed: a deprecated unused argument was removed.
### Changed / clarified
- changed the name of the cjxl flag `photon_noise` to `photon_noise_iso`
- fixed how large boxes are decoded (#2958)
- fixed encoding files with unreadable patches (#3042, #3046)
## [0.8.2] - 2023-06-14
### Changed
- Security: Fix an integer underflow bug in patch decoding (#2551- CVE-2023-35790).
## [0.8.1] - 2023-02-03
### Changed
- Allow fast-lossless for 16-bit float input (#2093)
- Fix bug in palette (#2120)
- Security: Fix OOB read in exif.h (#2101 - [CVE-2023-0645](https://www.cve.org/cverecord?id=CVE-2023-0645))
## [0.8.0] - 2023-01-18
### Added
- decoder API: new function `JxlDecoderSetImageBitDepth` to set the bit depth
of the output buffer.
- decoder API proposal: add `JxlDecoderSetOutputColorProfile` and
`JxlDecoderSetCms` to enable decoding to desired colorspace; NB: not
implemented yet.
- encoder API: new function `JxlEncoderSetFrameBitDepth` to set the bit depth
of the input buffer.
- encoder API: add an effort 10 option for lossless compression; using this
setting requires calling `JxlEncoderAllowExpertOptions`.
- encoder API: new `JXL_ENC_FRAME_SETTING_JPEG_COMPRESS_BOXES` enum value to
allow explicit control of metadata compression
### Removed
- common API: removed `JxlIntrinsicSizeHeader`
- decoder API: removed deprecated `JXL_DEC_NEED_DC_OUT_BUFFER` and
`JXL_DEC_DC_IMAGE` events, `JxlDecoderDCOutBufferSize` and
`JxlDecoderSetDCOutBuffer` functions
### Changed / clarified
- encoder API: `JxlEncoderProcessOutput` requires at least 32 bytes of output
space to proceed and guarantees that at least one byte will be written
## [0.7] - 2022-07-21

View file

@ -3,44 +3,28 @@
# 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)
# Ubuntu focal ships with cmake 3.16.
cmake_minimum_required(VERSION 3.16...3.27)
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
)
# TODO(sboukortt): remove once oss-fuzz passes -DBUILD_SHARED_LIBS=OFF
if(JPEGXL_ENABLE_FUZZERS)
message(STATUS "Fuzzer build detected, building static libs")
set(BUILD_SHARED_LIBS OFF)
endif()
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)
# Add "DebugOpt" CMake build type. Unlike builtin DEBUG it is optimized.
string(REGEX REPLACE "-DNDEBUG " "" CMAKE_CXX_FLAGS_DEBUGOPT "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDEBUG" )
string(REGEX REPLACE "-DNDEBUG " "" CMAKE_C_FLAGS_DEBUGOPT "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DDEBUG" )
# Enabled PIE binaries by default if supported.
include(CheckPIESupported OPTIONAL RESULT_VARIABLE CHECK_PIE_SUPPORTED)
if(CHECK_PIE_SUPPORTED)
@ -50,6 +34,19 @@ if(CHECK_PIE_SUPPORTED)
endif()
endif()
if(PROVISION_DEPENDENCIES)
# Run script to provision dependencies.
find_program (BASH_PROGRAM bash)
if(BASH_PROGRAM)
execute_process(
COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/deps.sh
RESULT_VARIABLE PROVISION_DEPENDENCIES_RESULT)
endif()
if(NOT PROVISION_DEPENDENCIES_RESULT EQUAL "0")
message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/deps.sh failed with ${PROVISION_DEPENDENCIES_RESULT}")
endif()
endif()
### Project build options:
if(CXX_FUZZERS_SUPPORTED)
# Enabled by default except on arm64, Windows and Apple builds.
@ -82,14 +79,29 @@ check_cxx_source_compiles(
JXL_HWY_DISABLED_TARGETS_FORCED
)
set(WARNINGS_AS_ERRORS_DEFAULT false)
if((SANITIZER STREQUAL "msan") OR JPEGXL_EMSCRIPTEN)
if((SANITIZER STREQUAL "msan") OR EMSCRIPTEN)
set(BUNDLE_LIBPNG_DEFAULT YES)
else()
set(BUNDLE_LIBPNG_DEFAULT NO)
endif()
if(EXISTS "${PROJECT_SOURCE_DIR}/third_party/libjpeg-turbo/jconfig.h.in")
set(ENABLE_JPEGLI_DEFAULT YES)
else()
set(ENABLE_JPEGLI_DEFAULT NO)
message(STATUS "libjpeg-turbo submodule is absent; not enabling jpegli")
endif()
include(TestBigEndian)
test_big_endian(ARCH_IS_BIG_ENDIAN)
if(ARCH_IS_BIG_ENDIAN)
set(ENABLE_SKCMS_DEFAULT NO)
message(STATUS "Big-endian architecture detected; defaulting to lcms2 instead of skcms")
else()
set(ENABLE_SKCMS_DEFAULT YES)
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})
@ -100,6 +112,16 @@ 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_JPEGLI ${ENABLE_JPEGLI_DEFAULT} CACHE BOOL
"Build jpegli library.")
set(JPEGXL_ENABLE_JPEGLI_LIBJPEG true CACHE BOOL
"Build libjpeg.so shared library based on jpegli.")
set(JPEGXL_INSTALL_JPEGLI_LIBJPEG false CACHE BOOL
"Install jpegli version of libjpeg.so system-wide.")
set(JPEGLI_LIBJPEG_LIBRARY_VERSION "62.3.0" CACHE STRING
"Library version of the libjpeg.so shared library that we build.")
set(JPEGLI_LIBJPEG_LIBRARY_SOVERSION "62" CACHE STRING
"Library so-version of the libjpeg.so shared library that we build.")
set(JPEGXL_ENABLE_DOXYGEN true CACHE BOOL
"Generate C API documentation using Doxygen.")
set(JPEGXL_ENABLE_MANPAGES true CACHE BOOL
@ -116,10 +138,8 @@ 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
set(JPEGXL_ENABLE_SKCMS ${ENABLE_SKCMS_DEFAULT} 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
@ -128,29 +148,40 @@ 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_ENABLE_BOXES true CACHE BOOL
"Builds in support for decoding boxes in JXL files,\
disabling it makes the decoder reject JXL_DEC_BOX 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
set(JPEGXL_WARNINGS_AS_ERRORS false 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.")
set(JPEGXL_TEST_TOOLS false CACHE BOOL
"Run scripts that test the encoding / decoding tools.")
set(JPEGXL_ENABLE_AVX512 false CACHE BOOL
"Build with AVX512 support (faster on CPUs that support it, but larger binary size).")
set(JPEGXL_ENABLE_AVX512_SPR false CACHE BOOL
"Build with AVX-512FP16 support (faster on CPUs that support it, but larger binary size).")
set(JPEGXL_ENABLE_AVX512_ZEN4 false CACHE BOOL
"Build with Zen4-optimized AVX512 support (faster on CPUs that support it, but larger binary size).")
set(JPEGXL_ENABLE_WASM_THREADS true CACHE BOOL
"Builds WASM modules with threads support")
# 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.")
"Force using system installed googletest (gtest) 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
@ -162,37 +193,49 @@ 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}")
set(JXL_HWY_INCLUDE_DIRS "$<BUILD_INTERFACE:$<TARGET_PROPERTY:$<IF:$<TARGET_EXISTS:hwy::hwy>,hwy::hwy,hwy>,INTERFACE_INCLUDE_DIRECTORIES>>")
# Always disable SSSE3 since it is rare to have SSSE3 but not SSE4
set(HWY_DISABLED_TARGETS "HWY_SSSE3")
if (NOT JPEGXL_ENABLE_AVX512)
message(STATUS "Disabled AVX512 (set JPEGXL_ENABLE_AVX512 to enable it)")
set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_AVX3")
add_definitions(-DFJXL_ENABLE_AVX512=0)
endif()
if (NOT JPEGXL_ENABLE_AVX512_SPR)
message(STATUS "Disabled AVX512_SPR (set JPEGXL_ENABLE_AVX512_SPR to enable it)")
set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_AVX3_SPR")
endif()
if (NOT JPEGXL_ENABLE_AVX512_ZEN4)
message(STATUS "Disabled AVX512_ZEN4 (set JPEGXL_ENABLE_AVX512_ZEN4 to enable it)")
set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_AVX3_ZEN4")
endif()
# 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)
# https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-170
# https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html
set(CMAKE_MSVC_RUNTIME_LIBRARY "$<$<NOT:$<CONFIG:Debug>>:MultiThreaded>" CACHE STRING "")
# 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)
if (NOT MSVC)
string(APPEND CMAKE_EXE_LINKER_FLAGS " -static")
endif()
if ((NOT WIN32 AND NOT APPLE) OR CYGWIN OR MINGW)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -static-libgcc -static-libstdc++")
endif()
endif() # JPEGXL_STATIC
@ -202,7 +245,16 @@ 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)
if ("cxx_std_17" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
set(CMAKE_CXX_STANDARD 17)
else()
if ("cxx_std_14" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
set(CMAKE_CXX_STANDARD 14)
else()
set(CMAKE_CXX_STANDARD 11)
endif()
endif()
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
@ -243,7 +295,7 @@ if(JPEGXL_STATIC)
endif()
endif() # JPEGXL_STATIC
if (JPEGXL_EMSCRIPTEN)
if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_THREADS)
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")
@ -257,73 +309,75 @@ if (CXX_NO_RTTI_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif()
# Internal flags for coverage builds:
set(JPEGXL_COVERAGE_FLAGS)
set(JPEGXL_COVERAGE_LINK_FLAGS)
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)
# TODO(janwas): add flags
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
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"
)
# 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()
# TODO(eustas): JXL currently compiles, but does not pass tests...
if (NOT JXL_HWY_DISABLED_TARGETS_FORCED)
if (NOT JPEGXL_ENABLE_SIZELESS_VECTORS)
set(HWY_DISABLED_TARGETS "${HWY_DISABLED_TARGETS}|HWY_SVE|HWY_SVE2|HWY_SVE_256|HWY_SVE2_128|HWY_RVV")
endif()
add_compile_options($<$<NOT:$<COMPILE_LANGUAGE:RC>>:-DHWY_DISABLED_TARGETS=\(${HWY_DISABLED_TARGETS}\)>)
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.
add_compile_options(-funwind-tables)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options("SHELL:-Xclang -mrelax-all")
endif()
if (CXX_CONSTRUCTOR_ALIASES_SUPPORTED)
add_compile_options("SHELL:-Xclang -mconstructor-aliases")
endif()
# 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()
add_compile_options(-fno-omit-frame-pointer)
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
# 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.
add_compile_options(-mfpu=neon-vfpv4 -mfloat-abi=hard)
endif()
endif()
# 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()
add_compile_options(
# Ignore this to allow redefining __DATE__ and others.
-Wno-builtin-macro-redefined
# Force build with optimizations in release mode.
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
# Global warning settings.
-Wall
)
add_compile_options(
# Ignore this to allow redefining __DATE__ and others.
-Wno-builtin-macro-redefined
if (JPEGXL_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif ()
# Global warning settings.
-Wall
)
if (JPEGXL_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif ()
if(JPEGXL_ENABLE_COVERAGE)
set(JPEGXL_COVERAGE_FLAGS
-g -O0 -fprofile-arcs -ftest-coverage
)
set(JPEGXL_COVERAGE_LINK_FLAGS
--coverage
)
endif() # JPEGXL_ENABLE_COVERAGE
endif () # !MSVC
include(GNUInstallDirs)
@ -348,125 +402,146 @@ endif()
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()
# 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")
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")
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
# 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
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)
find_program(ASCIIDOC a2x)
if(ASCIIDOC)
file(STRINGS "${ASCIIDOC}" ASCIIDOC_SHEBANG LIMIT_COUNT 1)
if(ASCIIDOC_SHEBANG MATCHES "sh$" OR ASCIIDOC_SHEBANG MATCHES "libexec/bin/python$" OR MINGW)
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()
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
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)
include(examples/examples.cmake)
endif ()
# Plugins for third-party software
if (JPEGXL_ENABLE_PLUGINS)
add_subdirectory(plugins)
add_subdirectory(plugins)
endif ()
# Binary tools
add_subdirectory(tools)
macro(list_test_targets out dir)
get_property(dir_targets DIRECTORY ${dir} PROPERTY BUILDSYSTEM_TARGETS)
foreach(target ${dir_targets})
if (target MATCHES ".*_test")
list(APPEND ${out} ${target})
endif()
endforeach()
get_property(subdirectories DIRECTORY ${dir} PROPERTY SUBDIRECTORIES)
foreach(subdir ${subdirectories})
list_test_targets(${out} ${subdir})
endforeach()
endmacro()
set(all_tests_list)
list_test_targets(all_tests_list ${CMAKE_CURRENT_SOURCE_DIR})
if(all_tests_list)
add_custom_target(all_tests)
add_dependencies(all_tests ${all_tests_list})
endif()

View file

@ -75,7 +75,9 @@ information on using pull requests.
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
* 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
@ -113,8 +115,7 @@ information on using pull requests.
* 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.
* AUTHORS: You can add your name to the [AUTHORS](AUTHORS) file.
* Style guide. Check `./ci.sh lint`.

View file

@ -0,0 +1,12 @@
# 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.
bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "giflib", version = "5.2.1")
bazel_dep(name = "googletest", version = "1.14.0")
bazel_dep(name = "libjpeg_turbo", version = "2.1.91")
bazel_dep(name = "libpng", version = "1.6.40")
bazel_dep(name = "libwebp", version = "1.3.2")
bazel_dep(name = "openexr", version = "3.2.1")

132
media/libjxl/src/MODULE.bazel.lock generated Normal file
View file

@ -0,0 +1,132 @@
{
"lockFileVersion": 11,
"registryFileHashes": {
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/source.json": "06cc0842d241da0c5edc755edb3c7d0d008d304330e57ecf2d6449fb0b633a82",
"https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef",
"https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
"https://bcr.bazel.build/modules/giflib/5.2.1/MODULE.bazel": "810dbc4275425c89ffe648dd78c537fe2eb1d2a9704d10e950b295263af03366",
"https://bcr.bazel.build/modules/giflib/5.2.1/source.json": "94215af981976c329eaec0083727b155ea89607e61debea50ed508e7963ef9a6",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/googletest/1.14.0/source.json": "2478949479000fdd7de9a3d0107ba2c85bb5f961c3ecb1aa448f52549ce310b5",
"https://bcr.bazel.build/modules/imath/3.1.9/MODULE.bazel": "26fe47ee8137a4c605667fb0d26a5c12b8fb2e758824a376789b287b2f9d424d",
"https://bcr.bazel.build/modules/imath/3.1.9/source.json": "22b7d9e617d4d26626f5ac8fba3cd2bd7a87f7501c99fa847f8d9e2980416e8f",
"https://bcr.bazel.build/modules/libdeflate/1.19/MODULE.bazel": "b7396a2edfd5ce6669509fbdd10db5e8731d60954063699c546c3126c8156824",
"https://bcr.bazel.build/modules/libdeflate/1.19/source.json": "d4604a526efba9b5347309de49673bbe152da465f7c80c7f7ffe6800d8b504d1",
"https://bcr.bazel.build/modules/libjpeg_turbo/2.1.91/MODULE.bazel": "bcc23b7c4866af2d7777ee49db435603ca1e35b90ea0689f8051900fa8c73c6b",
"https://bcr.bazel.build/modules/libjpeg_turbo/2.1.91/source.json": "42ea85708058e2408f229075e1cbeaad13fa2719918ff9c505be5e22b57ef17b",
"https://bcr.bazel.build/modules/libpng/1.6.40/MODULE.bazel": "cc1952a9b5efd4df3dfdb9f9ba2b1c8d88b4fd9b0e474185cb81d90a31c7c453",
"https://bcr.bazel.build/modules/libpng/1.6.40/source.json": "2fe294bf161c2d3f1e04e7cecb6eb2e6c0c198698b23cabc1c4e6ff77d82a86a",
"https://bcr.bazel.build/modules/libwebp/1.3.2/MODULE.bazel": "c60edf34a913daebac9bd2cbe17b84048e4a7a5d3571f70be93c1b1227a69659",
"https://bcr.bazel.build/modules/libwebp/1.3.2/source.json": "e7b8d3047ad9758fda22fcf46bd8b57414b0eb5e7903f4ce888683d778633cf7",
"https://bcr.bazel.build/modules/openexr/3.2.1/MODULE.bazel": "5665fa95490825760943601d618e2d70eb45378ea3f2961c5ec18f23ae8a2106",
"https://bcr.bazel.build/modules/openexr/3.2.1/source.json": "afc17dda6614ff723cc1def634fa4f33534d3d29514b089fa4aa5eb47ba1c65b",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
"https://bcr.bazel.build/modules/platforms/0.0.9/source.json": "cd74d854bf16a9e002fb2ca7b1a421f4403cda29f824a765acd3a8c56f8d43e6",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/21.7/source.json": "bbe500720421e582ff2d18b0802464205138c06056f443184de39fbb8187b09b",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/7.6.1/source.json": "8f3f3076554e1558e8e468b2232991c510ecbcbed9e6f8c06ac31c93bcf38362",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/source.json": "a075731e1b46bc8425098512d038d416e966ab19684a10a34f4741295642fc35",
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/0.0.7/source.json": "355cc5737a0f294e560d52b1b7a6492d4fff2caf0bef1a315df5a298fca2d34a",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c",
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json": "d57902c052424dfda0e71646cb12668d39c4620ee0544294d9d941e7d12bc3a9",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7",
"https://bcr.bazel.build/modules/rules_python/0.22.1/source.json": "57226905e783bae7c37c2dd662be078728e48fa28ee4324a7eabcafb5a43d014",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.1/source.json": "a96f95e02123320aa015b956f29c00cb818fa891ef823d55148e1a362caacf29",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json": "f1ef7d3f9e0e26d4b23d1c39b5f5de71f584dd7d1b4ef83d9bbba6ec7a6a6459",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
"https://bcr.bazel.build/modules/zlib/1.3/MODULE.bazel": "6a9c02f19a24dcedb05572b2381446e27c272cd383aed11d41d99da9e3167a72",
"https://bcr.bazel.build/modules/zlib/1.3/source.json": "b6b43d0737af846022636e6e255fd4a96fee0d34f08f3830e6e0bac51465c37c"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
"general": {
"bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=",
"usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"local_config_apple_cc": {
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
"ruleClassName": "_apple_cc_autoconf",
"attributes": {}
},
"local_config_apple_cc_toolchains": {
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
"ruleClassName": "_apple_cc_autoconf_toolchains",
"attributes": {}
}
},
"recordedRepoMappingEntries": [
[
"apple_support~",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@platforms//host:extension.bzl%host_platform": {
"general": {
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
"usagesDigest": "meSzxn3DUCcYEhq4HQwExWkWtU4EjriRBQLsZN+Q0SU=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"host_platform": {
"bzlFile": "@@platforms//host:extension.bzl",
"ruleClassName": "host_platform_repo",
"attributes": {}
}
},
"recordedRepoMappingEntries": []
}
}
}
}

View file

@ -1,20 +0,0 @@
## 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

@ -1,41 +0,0 @@
## 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`
```

View file

@ -12,6 +12,10 @@ https://github.com/libjxl/libjxl/actions/workflows/fuzz.yml)
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)
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7845/badge)](
https://www.bestpractices.dev/projects/7845)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/libjxl/libjxl/badge)](
https://securityscorecards.dev/viewer/?uri=github.com/libjxl/libjxl)
[![codecov](https://codecov.io/gh/libjxl/libjxl/branch/main/graph/badge.svg)](
https://codecov.io/gh/libjxl/libjxl)
@ -21,109 +25,62 @@ 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.
JPEG XL was standardized in 2022 as [ISO/IEC 18181](https://jpeg.org/jpegxl/workplan.html).
The [core codestream](doc/format_overview.md#codestream-features) is specified in 18181-1,
the [file format](doc/format_overview.md#file-format-features) in 18181-2.
[Decoder conformance](https://github.com/libjxl/conformance) is defined in 18181-3,
and 18181-4 is the [reference software](https://github.com/libjxl/libjxl).
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.
to change, however files encoded with `cjxl` conform to the JPEG XL specification
and can be decoded with current and future `djxl` decoders or the `libjxl` decoding library.
## Quick start guide
## Installation
For more details and other workflows see the "Advanced guide" below.
In most Linux distributions, installing `libjxl` is just a matter of using the package management system.
For example in Debian-based distributions: `apt install libjxl-tools` will install `cjxl` and `djxl`
and other tools like `benchmark_xl` are available in the package `libjxl-devtools`.
On MacOS, you can use [Homebrew](https://brew.sh/): `brew install jpeg-xl`.
### Checking out the code
[![libjxl packaging status](https://repology.org/badge/vertical-allrepos/libjxl.svg?exclude_unsupported=1&columns=3&exclude_sources=modules,site&header=libjxl%20packaging%20status)](https://repology.org/project/libjxl/versions)
```bash
git clone https://github.com/libjxl/libjxl.git --recursive --shallow-submodules
```
From the [releases page](https://github.com/libjxl/libjxl/releases/) the following can be downloaded:
- Windows binaries
- Debian and Ubuntu .deb packages
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:
Of course you can also [build libjxl from sources](BUILDING.md).
```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
## Usage
To encode a source image to JPEG XL with default settings:
```bash
build/tools/cjxl input.png output.jxl
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`.
The desired visual fidelity can be selected using the `--distance` parameter
(in units of just-noticeable difference, where 0 is lossless and the most useful lossy range is 0.5 .. 3.0),
or using `--quality` (on a scale from 0 to 100, roughly matching libjpeg).
The [encode effort](doc/encode_effort.md) can be selected using the `--effort` parameter.
For more settings run `cjxl --help` or for a full list of options
run `cjxl -v -v --help`.
To decode a JPEG XL file run:
```bash
build/tools/djxl input.jxl output.png
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.
When possible, `cjxl`/`djxl` are able to read/write the following image formats:
OpenEXR (`.exr`), GIF (`.gif`), JPEG (`.jpg`/`.jpeg`), NetPBM (`.pam`/`.pgm`/`.ppm`),
Portable FloatMap (`.pfm`), PGX Test Format (`.pgx`), Portable Network Graphics (`.png`),
Animated PNG (`.png`/`.apng`), and JPEG XL itself (`.jxl`).
Specifically for JPEG files, the default `cjxl` behavior is to apply lossless
recompression and the default `djxl` behavior is to reconstruct the original
JPEG file (when the extension of the output file is `.jpg`).
### Benchmarking
@ -135,26 +92,12 @@ benchmarking purposes.
For more comprehensive benchmarking options, see the
[benchmarking guide](doc/benchmarking.md).
## Advanced guide
### Library API
### Building with Docker
Besides the `libjxl` library [API documentation](https://libjxl.readthedocs.io/en/latest/),
there are [example applications](examples/) and [plugins](plugins/) that can be used as a reference or
starting point for developers who wish to integrate `libjxl` in their project.
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
@ -187,6 +130,7 @@ format: Cloudinary and Google.
* [Test coverage on Codecov.io](https://app.codecov.io/gh/libjxl/libjxl) - for
developers
* [libjxl documentation on readthedocs.io](https://libjxl.readthedocs.io/)
* The development of jpegli, the improved JPEG encoder and decoder, will continue at https://github.com/google/jpegli
### Contact

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.
workspace(name = "libjxl")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
local_repository(
name = "highway",
path = "third_party/highway",
)
local_repository(
name = "brotli",
path = "third_party/brotli",
)
new_local_repository(
name = "skcms",
build_file_content = """
cc_library(
name = "skcms",
srcs = [
"skcms.cc",
"src/skcms_internals.h",
"src/skcms_Transform.h",
"src/Transform_inl.h",
],
hdrs = ["skcms.h"],
visibility = ["//visibility:public"],
)
""",
path = "third_party/skcms",
)

View file

@ -7,7 +7,8 @@
# Tests implemented in bash. These typically will run checks about the source
# code rather than the compiled one.
MYDIR=$(dirname $(realpath "$0"))
SELF=$(realpath "$0")
MYDIR=$(dirname "${SELF}")
set -u
@ -18,14 +19,11 @@ test_includes() {
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
# Check that the full paths to the public headers are not used, since users
# of the library will include the library as: #include "jxl/foobar.h".
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
if [[ "${f#third_party/}" == "$f" ]]; then
@ -103,9 +101,9 @@ test_printf_size_t() {
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
if grep -n -E '[^_]gtest\.h' \
$(git ls-files | grep -E '(\.c|\.cc|\.cpp|\.h)$' | grep -v -F /testing.h); then
echo "Don't include gtest directly, instead include 'testing.h'. " >&2
ret=1
fi
@ -122,7 +120,7 @@ test_printf_size_t() {
fi
done
for f in $(git ls-files | grep -E "\.h$" | grep -v -E '(printf_macros\.h|test_utils\.h)' |
for f in $(git ls-files | grep -E "\.h$" | grep -v -E '(printf_macros\.h|testing\.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.

View file

@ -5,23 +5,29 @@
# license that can be found in the LICENSE file.
# Continuous integration helper module. This module is meant to be called from
# the .gitlab-ci.yml file during the continuous integration build, as well as
# from the command line for developers.
# workflows during the continuous integration build, as well as from the
# command line for developers.
set -eu
OS=`uname -s`
MYDIR=$(dirname $(realpath "$0"))
SELF=$(realpath "$0")
MYDIR=$(dirname "${SELF}")
### Environment parameters:
TEST_STACK_LIMIT="${TEST_STACK_LIMIT:-256}"
BENCHMARK_NUM_THREADS="${BENCHMARK_NUM_THREADS:-0}"
BUILD_CONFIG=${BUILD_CONFIG:-}
CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE:-RelWithDebInfo}
CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH:-}
CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER:-}
CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER:-}
CMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM:-}
SKIP_BUILD="${SKIP_BUILD:-0}"
SKIP_TEST="${SKIP_TEST:-0}"
FASTER_MSAN_BUILD="${FASTER_MSAN_BUILD:-0}"
TARGETS="${TARGETS:-all doc}"
TEST_SELECTOR="${TEST_SELECTOR:-}"
BUILD_TARGET="${BUILD_TARGET:-}"
ENABLE_WASM_SIMD="${ENABLE_WASM_SIMD:-0}"
@ -32,6 +38,8 @@ else
fi
# Whether we should post a message in the MR when the build fails.
POST_MESSAGE_ON_ERROR="${POST_MESSAGE_ON_ERROR:-1}"
# By default, do a lightweight debian HWY package build.
HWY_PKG_OPTIONS="${HWY_PKG_OPTIONS:---set-envvar=HWY_EXTRA_CONFIG=-DBUILD_TESTING=OFF -DHWY_ENABLE_EXAMPLES=OFF -DHWY_ENABLE_CONTRIB=OFF}"
# Set default compilers to clang if not already set
export CC=${CC:-clang}
@ -69,13 +77,24 @@ if [[ "${ENABLE_WASM_SIMD}" -ne "0" ]]; then
CMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS} -msimd128"
fi
if [[ "${ENABLE_WASM_SIMD}" -eq "2" ]]; then
CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -DHWY_WANT_WASM2"
CMAKE_C_FLAGS="${CMAKE_C_FLAGS} -DHWY_WANT_WASM2"
fi
if [[ -z "${BUILD_CONFIG}" ]]; then
TOOLS_DIR="${BUILD_DIR}/tools"
else
TOOLS_DIR="${BUILD_DIR}/tools/${BUILD_CONFIG}"
fi
if [[ ! -z "${HWY_BASELINE_TARGETS}" ]]; then
CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -DHWY_BASELINE_TARGETS=${HWY_BASELINE_TARGETS}"
fi
# Version inferred from the CI variables.
CI_COMMIT_SHA=${CI_COMMIT_SHA:-${GITHUB_SHA:-}}
JPEGXL_VERSION=${JPEGXL_VERSION:-${CI_COMMIT_SHA:0:8}}
CI_COMMIT_SHA=${GITHUB_SHA:-}
JPEGXL_VERSION=${JPEGXL_VERSION:-}
# Benchmark parameters
STORE_IMAGES=${STORE_IMAGES:-1}
@ -118,17 +137,34 @@ if [[ "${BUILD_TARGET%%-*}" != "arm" ]]; then
)
fi
CLANG_TIDY_BIN=$(which clang-tidy-6.0 clang-tidy-7 clang-tidy-8 clang-tidy | head -n 1)
CLANG_TIDY_BIN_CANDIDATES=(
clang-tidy
clang-tidy-6.0
clang-tidy-7
clang-tidy-8
clang-tidy-9
clang-tidy-10
clang-tidy-11
clang-tidy-12
clang-tidy-13
clang-tidy-14
clang-tidy-15
clang-tidy-16
clang-tidy-17
clang-tidy-18
)
CLANG_TIDY_BIN=${CLANG_TIDY_BIN:-$(which ${CLANG_TIDY_BIN_CANDIDATES[@]} 2>/dev/null | tail -n 1)}
# Default to "cat" if "colordiff" is not installed or if stdout is not a tty.
if [[ -t 1 ]]; then
COLORDIFF_BIN=$(which colordiff cat | head -n 1)
COLORDIFF_BIN=$(which colordiff cat 2>/dev/null | head -n 1)
else
COLORDIFF_BIN="cat"
fi
FIND_BIN=$(which gfind find | head -n 1)
FIND_BIN=$(which gfind find 2>/dev/null | head -n 1)
# "false" will disable wine64 when not installed. This won't allow
# cross-compiling.
WINE_BIN=$(which wine64 false | head -n 1)
WINE_BIN=$(which wine64 false 2>/dev/null | head -n 1)
CLANG_VERSION="${CLANG_VERSION:-}"
# Detect the clang version suffix and store it in CLANG_VERSION. For example,
@ -139,6 +175,7 @@ detect_clang_version() {
fi
local clang_version=$("${CC:-clang}" --version | head -n1)
clang_version=${clang_version#"Debian "}
clang_version=${clang_version#"Ubuntu "}
local llvm_tag
case "${clang_version}" in
"clang version 6."*)
@ -171,27 +208,6 @@ on_exit() {
local retcode="$1"
# Always cleanup the CLEANUP_FILES.
cleanup
# Post a message in the MR when requested with POST_MESSAGE_ON_ERROR but only
# if the run failed and we are not running from a MR pipeline.
if [[ ${retcode} -ne 0 && -n "${CI_BUILD_NAME:-}" &&
-n "${POST_MESSAGE_ON_ERROR}" && -z "${CI_MERGE_REQUEST_ID:-}" &&
"${CI_BUILD_REF_NAME}" = "master" ]]; then
load_mr_vars_from_commit
{ set +xeu; } 2>/dev/null
local message="**Run ${CI_BUILD_NAME} @ ${CI_COMMIT_SHORT_SHA} failed.**
Check the output of the job at ${CI_JOB_URL:-} to see if this was your problem.
If it was, please rollback this change or fix the problem ASAP, broken builds
slow down development. Check if the error already existed in the previous build
as well.
Pipeline: ${CI_PIPELINE_URL}
Previous build commit: ${CI_COMMIT_BEFORE_SHA}
"
cmd_post_mr_comment "${message}"
fi
}
trap 'retcode=$?; { set +x; } 2>/dev/null; on_exit ${retcode}' INT TERM EXIT
@ -203,7 +219,7 @@ trap 'retcode=$?; { set +x; } 2>/dev/null; on_exit ${retcode}' INT TERM EXIT
# running from a merge request pipeline).
MR_HEAD_SHA=""
# The common ancestor between the current commit and the tracked branch, such
# as master. This includes a list
# as main. This includes a list
MR_ANCESTOR_SHA=""
# Populate MR_HEAD_SHA and MR_ANCESTOR_SHA.
@ -216,30 +232,23 @@ merge_request_commits() {
# changes on the Pull Request if needed. This fetches 10 more commits which
# should be enough given that PR normally should have 1 commit.
git -C "${MYDIR}" fetch -q origin "${GITHUB_SHA}" --depth 10
MR_HEAD_SHA="$(git rev-parse "FETCH_HEAD^2" 2>/dev/null ||
if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then
MR_HEAD_SHA="$(git rev-parse "FETCH_HEAD^2" 2>/dev/null ||
echo "${GITHUB_SHA}")"
else
MR_HEAD_SHA="${GITHUB_SHA}"
fi
else
# CI_BUILD_REF is the reference currently being build in the CI workflow.
MR_HEAD_SHA=$(git -C "${MYDIR}" rev-parse -q "${CI_BUILD_REF:-HEAD}")
MR_HEAD_SHA=$(git -C "${MYDIR}" rev-parse -q "HEAD")
fi
if [[ -n "${CI_MERGE_REQUEST_IID:-}" ]]; then
# Merge request pipeline in CI. In this case the upstream is called "origin"
# but it refers to the forked project that's the source of the merge
# request. We need to get the target of the merge request, for which we need
# to query that repository using our CI_JOB_TOKEN.
echo "machine gitlab.com login gitlab-ci-token password ${CI_JOB_TOKEN}" \
>> "${HOME}/.netrc"
git -C "${MYDIR}" fetch "${CI_MERGE_REQUEST_PROJECT_URL}" \
"${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
MR_ANCESTOR_SHA=$(git -C "${MYDIR}" rev-parse -q FETCH_HEAD)
elif [[ -n "${GITHUB_BASE_REF:-}" ]]; then
if [[ -n "${GITHUB_BASE_REF:-}" ]]; then
# Pull request workflow in GitHub Actions. GitHub checkout action uses
# "origin" as the remote for the git checkout.
git -C "${MYDIR}" fetch -q origin "${GITHUB_BASE_REF}"
MR_ANCESTOR_SHA=$(git -C "${MYDIR}" rev-parse -q FETCH_HEAD)
else
# We are in a local branch, not a merge request.
# We are in a local branch, not a pull request workflow.
MR_ANCESTOR_SHA=$(git -C "${MYDIR}" rev-parse -q HEAD@{upstream} || true)
fi
@ -258,40 +267,6 @@ merge_request_commits() {
set -x
}
# Load the MR iid from the landed commit message when running not from a
# merge request workflow. This is useful to post back results at the merge
# request when running pipelines from master.
load_mr_vars_from_commit() {
{ set +x; } 2>/dev/null
if [[ -z "${CI_MERGE_REQUEST_IID:-}" ]]; then
local mr_iid=$(git rev-list --format=%B --max-count=1 HEAD |
grep -F "${CI_PROJECT_URL}" | grep -F "/merge_requests" | head -n 1)
# mr_iid contains a string like this if it matched:
# Part-of: <https://gitlab.com/wg1/jpeg-xlm/merge_requests/123456>
if [[ -n "${mr_iid}" ]]; then
mr_iid=$(echo "${mr_iid}" |
sed -E 's,^.*merge_requests/([0-9]+)>.*$,\1,')
CI_MERGE_REQUEST_IID="${mr_iid}"
CI_MERGE_REQUEST_PROJECT_ID=${CI_PROJECT_ID}
fi
fi
set -x
}
# Posts a comment to the current merge request.
cmd_post_mr_comment() {
{ set +x; } 2>/dev/null
local comment="$1"
if [[ -n "${BOT_TOKEN:-}" && -n "${CI_MERGE_REQUEST_IID:-}" ]]; then
local url="${CI_API_V4_URL}/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes"
curl -X POST -g \
-H "PRIVATE-TOKEN: ${BOT_TOKEN}" \
--data-urlencode "body=${comment}" \
--output /dev/null \
"${url}"
fi
set -x
}
# Set up and export the environment variables needed by the child processes.
export_env() {
@ -452,14 +427,17 @@ cmake_configure() {
}
cmake_build_and_test() {
if [[ "${SKIP_BUILD}" -eq "1" ]]; then
return 0
fi
# gtest_discover_tests() runs the test binaries to discover the list of tests
# at build time, which fails under qemu.
ASAN_OPTIONS=detect_leaks=0 cmake --build "${BUILD_DIR}" -- all doc
ASAN_OPTIONS=detect_leaks=0 cmake --build "${BUILD_DIR}" -- $TARGETS
# Pack test binaries if requested.
if [[ "${PACK_TEST:-}" == "1" ]]; then
(cd "${BUILD_DIR}"
${FIND_BIN} -name '*.cmake' -a '!' -path '*CMakeFiles*'
# gtest / gmock / gtest_main shared libs
# gtest / gtest_main shared libs
${FIND_BIN} lib/ -name 'libg*.so*'
${FIND_BIN} -type d -name tests -a '!' -path '*CMakeFiles*'
) | tar -C "${BUILD_DIR}" -cf "${BUILD_DIR}/tests.tar.xz" -T - \
@ -507,7 +485,7 @@ strip_dead_code() {
### Externally visible commands
cmd_debug() {
CMAKE_BUILD_TYPE="Debug"
CMAKE_BUILD_TYPE="DebugOpt"
cmake_configure "$@"
cmake_build_and_test
}
@ -521,7 +499,7 @@ cmd_release() {
cmd_opt() {
CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CXX_FLAGS+=" -DJXL_DEBUG_WARNING -DJXL_DEBUG_ON_ERROR"
CMAKE_CXX_FLAGS+=" -DJXL_IS_DEBUG_BUILD"
cmake_configure "$@"
cmake_build_and_test
}
@ -547,6 +525,7 @@ cmd_coverage_report() {
# Only print coverage information for the libjxl directories. The rest
# is not part of the code under test.
--filter '.*jxl/.*'
--exclude '.*_gbench.cc'
--exclude '.*_test.cc'
--exclude '.*_testonly..*'
--exclude '.*_debug.*'
@ -576,7 +555,7 @@ cmd_test() {
(cd "${BUILD_DIR}"
export UBSAN_OPTIONS=print_stacktrace=1
[[ "${TEST_STACK_LIMIT}" == "none" ]] || ulimit -s "${TEST_STACK_LIMIT}"
ctest -j $(nproc --all || echo 1) --output-on-failure "$@")
ctest -j $(nproc --all || echo 1) ${TEST_SELECTOR} --output-on-failure "$@")
}
cmd_gbench() {
@ -600,6 +579,7 @@ cmd_msanfuzz() {
# Install msan if needed before changing the flags.
detect_clang_version
local msan_prefix="${HOME}/.msan/${CLANG_VERSION}"
# TODO(eustas): why libc++abi.a is bad?
if [[ ! -d "${msan_prefix}" || -e "${msan_prefix}/lib/libc++abi.a" ]]; then
# Install msan libraries for this version if needed or if an older version
# with libc++abi was installed.
@ -613,9 +593,9 @@ cmd_msanfuzz() {
cmd_asan() {
SANITIZER="asan"
CMAKE_C_FLAGS+=" -DJXL_ENABLE_ASSERT=1 -g -DADDRESS_SANITIZER \
CMAKE_C_FLAGS+=" -g -DADDRESS_SANITIZER \
-fsanitize=address ${UBSAN_FLAGS[@]}"
CMAKE_CXX_FLAGS+=" -DJXL_ENABLE_ASSERT=1 -g -DADDRESS_SANITIZER \
CMAKE_CXX_FLAGS+=" -g -DADDRESS_SANITIZER \
-fsanitize=address ${UBSAN_FLAGS[@]}"
strip_dead_code
cmake_configure "$@" -DJPEGXL_ENABLE_TCMALLOC=OFF
@ -625,16 +605,13 @@ cmd_asan() {
cmd_tsan() {
SANITIZER="tsan"
local tsan_args=(
-DJXL_ENABLE_ASSERT=1
-g
-DTHREAD_SANITIZER
${UBSAN_FLAGS[@]}
-fsanitize=thread
)
CMAKE_C_FLAGS+=" ${tsan_args[@]}"
CMAKE_CXX_FLAGS+=" ${tsan_args[@]}"
CMAKE_BUILD_TYPE="RelWithDebInfo"
cmake_configure "$@" -DJPEGXL_ENABLE_TCMALLOC=OFF
cmake_build_and_test
}
@ -652,15 +629,20 @@ cmd_msan() {
local msan_c_flags=(
-fsanitize=memory
-fno-omit-frame-pointer
-fsanitize-memory-track-origins
-DJXL_ENABLE_ASSERT=1
-g
-DMEMORY_SANITIZER
# Force gtest to not use the cxxbai.
-DGTEST_HAS_CXXABI_H_=0
)
if [[ "${FASTER_MSAN_BUILD}" -ne "1" ]]; then
msan_c_flags=(
"${msan_c_flags[@]}"
-fsanitize-memory-track-origins
)
fi
local msan_cxx_flags=(
"${msan_c_flags[@]}"
@ -680,16 +662,22 @@ cmd_msan() {
-Wl,-rpath -Wl,"${msan_prefix}"/lib/
)
CMAKE_C_FLAGS+=" ${msan_c_flags[@]} ${UBSAN_FLAGS[@]}"
CMAKE_CXX_FLAGS+=" ${msan_cxx_flags[@]} ${UBSAN_FLAGS[@]}"
CMAKE_C_FLAGS+=" ${msan_c_flags[@]}"
CMAKE_CXX_FLAGS+=" ${msan_cxx_flags[@]}"
CMAKE_EXE_LINKER_FLAGS+=" ${msan_linker_flags[@]}"
CMAKE_MODULE_LINKER_FLAGS+=" ${msan_linker_flags[@]}"
CMAKE_SHARED_LINKER_FLAGS+=" ${msan_linker_flags[@]}"
strip_dead_code
# MSAN share of stack size is non-negligible.
TEST_STACK_LIMIT="none"
# TODO(eustas): investigate why fuzzers do not link when MSAN libc++ is used
cmake_configure "$@" \
-DCMAKE_CROSSCOMPILING=1 -DRUN_HAVE_STD_REGEX=0 -DRUN_HAVE_POSIX_REGEX=0 \
-DJPEGXL_ENABLE_TCMALLOC=OFF -DJPEGXL_WARNINGS_AS_ERRORS=OFF \
-DCMAKE_REQUIRED_LINK_OPTIONS="${msan_linker_flags[@]}"
-DCMAKE_REQUIRED_LINK_OPTIONS="${msan_linker_flags[@]}" \
-DJPEGXL_ENABLE_FUZZERS=OFF
cmake_build_and_test
}
@ -698,6 +686,8 @@ cmd_msan() {
cmd_msan_install() {
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
local msan_root="${HOME}/.msan"
mkdir -p "${msan_root}"
# Detect the llvm to install:
export CC="${CC:-clang}"
export CXX="${CXX:-clang++}"
@ -705,50 +695,70 @@ cmd_msan_install() {
# Allow overriding the LLVM checkout.
local llvm_root="${LLVM_ROOT:-}"
if [ -z "${llvm_root}" ]; then
local llvm_tag="llvmorg-${CLANG_VERSION}.0.0"
case "${CLANG_VERSION}" in
"6.0")
llvm_tag="llvmorg-6.0.1"
;;
"7")
llvm_tag="llvmorg-7.0.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"
declare -A llvm_tag_by_version=(
["6.0"]="6.0.1"
["7"]="7.1.0"
["8"]="8.0.1"
["9"]="9.0.2"
["10"]="10.0.1"
["11"]="11.1.0"
["12"]="12.0.1"
["13"]="13.0.1"
["14"]="14.0.6"
["15"]="15.0.7"
["16"]="16.0.6"
["17"]="17.0.6"
["18"]="18.1.6"
)
local llvm_tag="${CLANG_VERSION}.0.0"
if [[ -n "${llvm_tag_by_version["${CLANG_VERSION}"]}" ]]; then
llvm_tag=${llvm_tag_by_version["${CLANG_VERSION}"]}
fi
llvm_tag="llvmorg-${llvm_tag}"
local llvm_targz="${msan_root}/${llvm_tag}.tar.gz"
if [ ! -f "${llvm_targz}" ]; then
curl -L --show-error -o "${llvm_targz}" \
"https://github.com/llvm/llvm-project/archive/${llvm_tag}.tar.gz"
fi
tar -C "${tmpdir}" -zxf "${llvm_targz}"
llvm_root="${tmpdir}/llvm-project-${llvm_tag}"
fi
local msan_prefix="${HOME}/.msan/${CLANG_VERSION}"
local msan_prefix="${msan_root}/${CLANG_VERSION}"
rm -rf "${msan_prefix}"
declare -A CMAKE_EXTRAS
CMAKE_EXTRAS[libcxx]="\
-DLIBCXX_CXX_ABI=libstdc++ \
-DLIBCXX_INSTALL_EXPERIMENTAL_LIBRARY=ON"
local TARGET_OPTS=""
if [[ -n "${BUILD_TARGET}" ]]; then
TARGET_OPTS=" \
-DCMAKE_C_COMPILER_TARGET=\"${BUILD_TARGET}\" \
-DCMAKE_CXX_COMPILER_TARGET=\"${BUILD_TARGET}\" \
-DCMAKE_SYSTEM_PROCESSOR=\"${BUILD_TARGET%%-*}\" \
"
fi
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_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS}" \
-DCMAKE_INSTALL_PREFIX="${msan_prefix}" \
${CMAKE_EXTRAS[${project}]}
cmake --build "${proj_build}"
ninja -C "${proj_build}" install
done
local build_dir="${tmpdir}/build-llvm"
mkdir -p "${build_dir}"
cd ${llvm_root}
cmake -B"${build_dir}" \
-G Ninja \
-S runtimes \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_USE_SANITIZER=Memory \
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind;compiler-rt" \
-DLIBCXXABI_ENABLE_SHARED=ON \
-DLIBCXXABI_ENABLE_STATIC=OFF \
-DLIBCXX_ENABLE_SHARED=ON \
-DLIBCXX_ENABLE_STATIC=OFF \
-DCMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}" \
-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS}" \
-DCMAKE_EXE_LINKER_FLAGS="${CMAKE_EXE_LINKER_FLAGS}" \
-DCMAKE_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS}" \
-DCMAKE_INSTALL_PREFIX="${msan_prefix}" \
-DLLVM_PATH="${llvm_root}/llvm" \
-DLLVM_CONFIG_PATH="$(which llvm-config-${CLANG_VERSION} llvm-config | head -n1)" \
${TARGET_OPTS}
cmake --build "${build_dir}"
ninja -C "${build_dir}" install
}
# Internal build step shared between all cmd_ossfuzz_* commands.
@ -788,7 +798,7 @@ _cmd_ossfuzz() {
-e MSAN_LIBS_PATH="/work/msan" \
-e JPEGXL_EXTRA_ARGS="${jpegxl_extra_args}" \
-v "${MYDIR}":/src/libjxl \
-v "${MYDIR}/tools/ossfuzz-build.sh":/src/build.sh \
-v "${MYDIR}/tools/scripts/ossfuzz-build.sh":/src/build.sh \
-v "${real_build_dir}":/work \
gcr.io/oss-fuzz/libjxl
}
@ -822,9 +832,13 @@ cmd_ossfuzz_ninja() {
cmd_fast_benchmark() {
local small_corpus_tar="${BENCHMARK_CORPORA}/jyrki-full.tar"
local small_corpus_url="https://storage.googleapis.com/artifacts.jpegxl.appspot.com/corpora/jyrki-full.tar"
mkdir -p "${BENCHMARK_CORPORA}"
curl --show-error -o "${small_corpus_tar}" -z "${small_corpus_tar}" \
"https://storage.googleapis.com/artifacts.jpegxl.appspot.com/corpora/jyrki-full.tar"
if [ -f "${small_corpus_tar}" ]; then
curl --show-error -o "${small_corpus_tar}" -z "${small_corpus_tar}" "${small_corpus_url}"
else
curl --show-error -o "${small_corpus_tar}" "${small_corpus_url}"
fi
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
@ -862,7 +876,7 @@ cmd_benchmark() {
png_filename="${filename%.ppm}.png"
png_filename=$(echo "${png_filename}" | tr '/' '_')
sem --bg --id "${sem_id}" -j"${nprocs}" -- \
"${BUILD_DIR}/tools/decode_and_encode" \
"${TOOLS_DIR}/decode_and_encode" \
"${tmpdir}/${filename}" "${mode}" "${tmpdir}/${png_filename}"
images+=( "${png_filename}" )
done < <(cd "${tmpdir}"; ${FIND_BIN} . -name '*.ppm' -type f)
@ -875,6 +889,8 @@ cmd_benchmark() {
get_mem_available() {
if [[ "${OS}" == "Darwin" ]]; then
echo $(vm_stat | grep -F 'Pages free:' | awk '{print $3 * 4}')
elif [[ "${OS}" == MINGW* ]]; then
echo $(vmstat | tail -n 1 | awk '{print $4 * 4}')
else
echo $(grep -F MemAvailable: /proc/meminfo | awk '{print $2}')
fi
@ -887,45 +903,46 @@ run_benchmark() {
local output_dir="${BUILD_DIR}/benchmark_results"
mkdir -p "${output_dir}"
# The memory available at the beginning of the benchmark run in kB. The number
# of threads depends on the available memory, and the passed memory per
# thread. We also add a 2 GiB of constant memory.
local mem_available="$(get_mem_available)"
# Check that we actually have a MemAvailable value.
[[ -n "${mem_available}" ]]
local num_threads=$(( (${mem_available} - 1048576) / ${mem_per_thread} ))
if [[ ${num_threads} -le 0 ]]; then
num_threads=1
if [[ "${OS}" == MINGW* ]]; then
src_img_dir=`cygpath -w "${src_img_dir}"`
fi
local num_threads=1
if [[ ${BENCHMARK_NUM_THREADS} -gt 0 ]]; then
num_threads=${BENCHMARK_NUM_THREADS}
else
# The memory available at the beginning of the benchmark run in kB. The number
# of threads depends on the available memory, and the passed memory per
# thread. We also add a 2 GiB of constant memory.
local mem_available="$(get_mem_available)"
# Check that we actually have a MemAvailable value.
[[ -n "${mem_available}" ]]
num_threads=$(( (${mem_available} - 1048576) / ${mem_per_thread} ))
if [[ ${num_threads} -le 0 ]]; then
num_threads=1
fi
fi
local benchmark_args=(
--input "${src_img_dir}/*.png"
--codec=jpeg:yuv420:q85,webp:q80,jxl:d1:6,jxl:d1:6:downsampling=8,jxl:d5:6,jxl:d5:6:downsampling=8,jxl:m:d0:2,jxl:m:d0:3,jxl:m:d2:2
--output_dir "${output_dir}"
--noprofiler --show_progress
--show_progress
--num_threads="${num_threads}"
--decode_reps=11
--encode_reps=11
)
if [[ "${STORE_IMAGES}" == "1" ]]; then
benchmark_args+=(--save_decompressed --save_compressed)
fi
(
[[ "${TEST_STACK_LIMIT}" == "none" ]] || ulimit -s "${TEST_STACK_LIMIT}"
"${BUILD_DIR}/tools/benchmark_xl" "${benchmark_args[@]}" | \
"${TOOLS_DIR}/benchmark_xl" "${benchmark_args[@]}" | \
tee "${output_dir}/results.txt"
# Check error code for benckmark_xl command. This will exit if not.
# Check error code for benchmark_xl command. This will exit if not.
return ${PIPESTATUS[0]}
)
if [[ -n "${CI_BUILD_NAME:-}" ]]; then
{ set +x; } 2>/dev/null
local message="Results for ${CI_BUILD_NAME} @ ${CI_COMMIT_SHORT_SHA} (job ${CI_JOB_URL:-}):
$(cat "${output_dir}/results.txt")
"
cmd_post_mr_comment "${message}"
set -x
fi
}
# Helper function to wait for the CPU temperature to cool down on ARM.
@ -1066,7 +1083,7 @@ cmd_arm_benchmark() {
local src_img
for src_img in "${jpg_images[@]}" "${images[@]}"; do
local src_img_hash=$(sha1sum "${src_img}" | cut -f 1 -d ' ')
local enc_binaries=("${BUILD_DIR}/tools/cjxl")
local enc_binaries=("${TOOLS_DIR}/cjxl")
local src_ext="${src_img##*.}"
for enc_binary in "${enc_binaries[@]}"; do
local enc_binary_base=$(basename "${enc_binary}")
@ -1115,7 +1132,7 @@ cmd_arm_benchmark() {
local dec_output
wait_for_temp
dec_output=$("${BUILD_DIR}/tools/djxl" "${enc_file}" \
dec_output=$("${TOOLS_DIR}/djxl" "${enc_file}" \
--num_reps=5 --num_threads="${num_threads}" 2>&1 | tee /dev/stderr |
grep -E "M[BP]/s \[")
local img_size=$(echo "${dec_output}" | cut -f 1 -d ',')
@ -1131,7 +1148,7 @@ cmd_arm_benchmark() {
if [[ "${src_ext}" == "jpg" ]]; then
wait_for_temp
local dec_file="${BUILD_DIR}/arm_benchmark/${enc_file_hash}.jpg"
dec_output=$("${BUILD_DIR}/tools/djxl" "${enc_file}" \
dec_output=$("${TOOLS_DIR}/djxl" "${enc_file}" \
"${dec_file}" --num_reps=5 --num_threads="${num_threads}" 2>&1 | \
tee /dev/stderr | grep -E "M[BP]/s \[")
local jpeg_dec_mps_speed=$(_speed_from_output "${dec_output}")
@ -1153,18 +1170,6 @@ cmd_arm_benchmark() {
cmd_cpuset "${RUNNER_CPU_ALL:-}"
cat "${runs_file}"
if [[ -n "${CI_BUILD_NAME:-}" ]]; then
load_mr_vars_from_commit
{ set +x; } 2>/dev/null
local message="Results for ${CI_BUILD_NAME} @ ${CI_COMMIT_SHORT_SHA} (job ${CI_JOB_URL:-}):
\`\`\`
$(column -t -s " " "${runs_file}")
\`\`\`
"
cmd_post_mr_comment "${message}"
set -x
fi
}
# Generate a corpus and run the fuzzer on that corpus.
@ -1173,33 +1178,58 @@ cmd_fuzz() {
local fuzzer_crash_dir=$(realpath "${BUILD_DIR}/fuzzer_crash")
mkdir -p "${corpus_dir}" "${fuzzer_crash_dir}"
# Generate step.
"${BUILD_DIR}/tools/fuzzer_corpus" "${corpus_dir}"
"${TOOLS_DIR}/fuzzer_corpus" "${corpus_dir}"
# Run step:
local nprocs=$(nproc --all || echo 1)
(
cd "${BUILD_DIR}"
"tools/djxl_fuzzer" "${fuzzer_crash_dir}" "${corpus_dir}" \
cd "${TOOLS_DIR}"
djxl_fuzzer "${fuzzer_crash_dir}" "${corpus_dir}" \
-max_total_time="${FUZZER_MAX_TIME}" -jobs=${nprocs} \
-artifact_prefix="${fuzzer_crash_dir}/"
)
}
# Runs the linter (clang-format) on the pending CLs.
# Runs the linters (clang-format, build_cleaner, buildirier) on the pending CLs.
cmd_lint() {
merge_request_commits
{ set +x; } 2>/dev/null
local versions=(${1:-6.0 7 8 9 10 11})
local versions=(${1:-16 15 14 13 12 11 10 9 8 7 6.0})
local clang_format_bins=("${versions[@]/#/clang-format-}" clang-format)
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
local ret=0
local build_patch="${tmpdir}/build_cleaner.patch"
if ! "${MYDIR}/tools/build_cleaner.py" >"${build_patch}"; then
if ! "${MYDIR}/tools/scripts/build_cleaner.py" >"${build_patch}"; then
ret=1
echo "build_cleaner.py findings:" >&2
"${COLORDIFF_BIN}" <"${build_patch}"
echo "Run \`tools/build_cleaner.py --update\` to apply them" >&2
echo "Run \`tools/scripts/build_cleaner.py --update\` to apply them" >&2
fi
# It is ok, if buildifier is not installed.
if which buildifier >/dev/null; then
local buildifier_patch="${tmpdir}/buildifier.patch"
local bazel_files=`git -C "${MYDIR}" ls-files | grep -E "/BUILD$|WORKSPACE|.bzl$"`
set -x
buildifier -d ${bazel_files} >"${buildifier_patch}"|| true
{ set +x; } 2>/dev/null
if [ -s "${buildifier_patch}" ]; then
ret=1
echo 'buildifier have found some problems in Bazel build files:' >&2
"${COLORDIFF_BIN}" <"${buildifier_patch}"
echo 'To fix them run (from the base directory):' >&2
echo ' buildifier `git ls-files | grep -E "/BUILD$|WORKSPACE|.bzl$"`' >&2
fi
fi
# It is ok, if spell-checker is not installed.
if which typos >/dev/null; then
local src_ext="bazel|bzl|c|cc|cmake|gni|h|html|in|java|js|m|md|nix|py|rst|sh|ts|txt|yaml|yml"
local sources=`git -C "${MYDIR}" ls-files | grep -E "\.(${src_ext})$"`
typos -c "${MYDIR}/tools/scripts/typos.toml" ${sources}
else
echo "Consider installing https://github.com/crate-ci/typos for spell-checking"
fi
local installed=()
@ -1218,7 +1248,7 @@ cmd_lint() {
git -C "${MYDIR}" "${clang_format}" --binary "${clang_format}" \
--style=file --diff "${MR_ANCESTOR_SHA}" -- >"${tmppatch}" || true
{ set +x; } 2>/dev/null
if grep -E '^--- ' "${tmppatch}">/dev/null; then
if grep -E '^--- ' "${tmppatch}" | grep -v 'a/third_party' >/dev/null; then
if [[ -n "${LINT_OUTPUT:-}" ]]; then
cp "${tmppatch}" "${LINT_OUTPUT}"
fi
@ -1326,6 +1356,7 @@ cmd_debian_stats() {
build_debian_pkg() {
local srcdir="$1"
local srcpkg="$2"
local options="${3:-}"
local debsdir="${BUILD_DIR}/debs"
local builddir="${debsdir}/${srcpkg}"
@ -1341,7 +1372,7 @@ build_debian_pkg() {
done
(
cd "${builddir}"
debuild -b -uc -us
debuild "${options}" -b -uc -us
)
}
@ -1353,7 +1384,7 @@ cmd_debian_build() {
build_debian_pkg "${MYDIR}" "jpeg-xl"
;;
highway)
build_debian_pkg "${MYDIR}/third_party/highway" "highway"
build_debian_pkg "${MYDIR}/third_party/highway" "highway" "${HWY_PKG_OPTIONS}"
;;
*)
echo "ERROR: Must pass a valid source package name to build." >&2
@ -1374,7 +1405,7 @@ cmd_bump_version() {
local newver="${1:-}"
if ! which dch >/dev/null; then
echo "Run:\n sudo apt install debhelper"
echo "Missing dch\nTo install it run:\n sudo apt install devscripts"
exit 1
fi
@ -1402,9 +1433,13 @@ cmd_bump_version() {
-e "s/(set\\(JPEGXL_MINOR_VERSION) [0-9]+\\)/\\1 ${minor})/" \
-e "s/(set\\(JPEGXL_PATCH_VERSION) [0-9]+\\)/\\1 ${patch})/" \
-i lib/CMakeLists.txt
sed -E \
-e "s/(LIBJXL_VERSION: )\"[0-9.]+\"/\\1\"${major}.${minor}.${patch}\"/" \
-e "s/(LIBJXL_ABI_VERSION: )\"[0-9.]+\"/\\1\"${major}.${minor}\"/" \
-i .github/workflows/conformance.yml
# Update lib.gni
tools/build_cleaner.py --update
tools/scripts/build_cleaner.py --update
# Mark the previous version as "unstable".
DEBCHANGE_RELEASE_HEURISTIC=log dch -M --distribution unstable --release ''
@ -1418,11 +1453,11 @@ cmd_authors() {
merge_request_commits
local emails
local names
readarray -t emails < <(git log --format='%ae' "${MR_HEAD_SHA}...${MR_ANCESTOR_SHA}")
readarray -t names < <(git log --format='%an' "${MR_HEAD_SHA}...${MR_ANCESTOR_SHA}")
readarray -t emails < <(git log --format='%ae' "${MR_ANCESTOR_SHA}..${MR_HEAD_SHA}")
readarray -t names < <(git log --format='%an' "${MR_ANCESTOR_SHA}..${MR_HEAD_SHA}")
for i in "${!names[@]}"; do
echo "Checking name '${names[$i]}' with email '${emails[$i]}' ..."
"${MYDIR}"/tools/check_author.py "${emails[$i]}" "${names[$i]}"
"${MYDIR}"/tools/scripts/check_author.py "${emails[$i]}" "${names[$i]}"
done
}
@ -1450,7 +1485,7 @@ Where cmd is one of:
benchmark Run the benchmark over the default corpus.
fast_benchmark Run the benchmark over the small corpus.
coverage Buils and run tests with coverage support. Runs coverage_report as
coverage Build and run tests with coverage support. Runs coverage_report as
well.
coverage_report Generate HTML, XML and text coverage report after a coverage
run.
@ -1483,6 +1518,7 @@ You can pass some optional environment variables as well:
- FUZZER_MAX_TIME: "fuzz" command fuzzer running timeout in seconds.
- LINT_OUTPUT: Path to the output patch from the "lint" command.
- SKIP_CPUSET=1: Skip modifying the cpuset in the arm_benchmark.
- SKIP_BUILD=1: Skip the build stage, cmake configure only.
- SKIP_TEST=1: Skip the test stage.
- STORE_IMAGES=0: Makes the benchmark discard the computed images.
- TEST_STACK_LIMIT: Stack size limit (ulimit -s) during tests, in KiB.

View file

@ -31,11 +31,6 @@ foreach(brlib IN ITEMS ${brlibs})
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}
@ -46,11 +41,6 @@ foreach(brlib IN ITEMS ${brlibs})
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()

View file

@ -10,7 +10,7 @@ if (PkgConfig_FOUND)
endif ()
find_path(HWY_INCLUDE_DIR
NAMES hwy/highway.h
NAMES hwy/base.h hwy/highway.h
HINTS ${PC_HWY_INCLUDEDIR} ${PC_HWY_INCLUDE_DIRS}
)
@ -19,21 +19,31 @@ find_library(HWY_LIBRARY
HINTS ${PC_HWY_LIBDIR} ${PC_HWY_LIBRARY_DIRS}
)
# If version not found using pkg-config, try extracting it from header files
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)
set(HWY_VERSION "")
set(HWY_POSSIBLE_HEADERS "${HWY_INCLUDE_DIR}/hwy/base.h" "${HWY_INCLUDE_DIR}/hwy/highway.h")
foreach(HWY_HEADER_FILE IN LISTS HWY_POSSIBLE_HEADERS)
if (EXISTS "${HWY_HEADER_FILE}")
file(READ "${HWY_HEADER_FILE}" 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_MAJOR +([0-9]+)" _sink "${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_MINOR +([0-9]+)" _sink "${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 ()
string(REGEX MATCH "#define +HWY_PATCH +([0-9]+)" _sink "${HWY_VERSION_CONTENT}")
set(HWY_VERSION_PATCH "${CMAKE_MATCH_1}")
if (NOT HWY_VERSION_MAJOR STREQUAL "" AND NOT HWY_VERSION_MINOR STREQUAL "" AND NOT HWY_VERSION_PATCH STREQUAL "")
set(HWY_VERSION "${HWY_VERSION_MAJOR}.${HWY_VERSION_MINOR}.${HWY_VERSION_PATCH}")
break()
endif()
endif ()
endforeach ()
if (NOT HWY_VERSION)
message(WARNING "Highway version not found.")
endif()
endif ()
include(FindPackageHandleStandardArgs)

View file

@ -1,4 +1,46 @@
jpeg-xl (0.7) UNRELEASED; urgency=medium
jpeg-xl (0.11.1) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.11.1.
-- JPEG XL Maintainers <jpegxl@google.com> Tue, 26 Nov 2024 12:09:23 +0100
jpeg-xl (0.11.0) unstable; urgency=medium
* Bump JPEG XL version to 0.11.0.
-- JPEG XL Maintainers <jpegxl@google.com> Tue, 06 Aug 2024 14:35:34 +0200
jpeg-xl (0.10.2) unstable; urgency=medium
* Bump JPEG XL version to 0.10.2.
-- JPEG XL Maintainers <jpegxl@google.com> Thu, 07 Mar 2024 13:50:05 +0100
jpeg-xl (0.10.1) unstable; urgency=medium
* Bump JPEG XL version to 0.10.1.
-- JPEG XL Maintainers <jpegxl@google.com> Wed, 28 Feb 2024 12:52:20 +0100
jpeg-xl (0.10.0) unstable; urgency=medium
* Bump JPEG XL version to 0.10.0.
-- JPEG XL Maintainers <jpegxl@google.com> Wed, 21 Feb 2024 08:37:00 +0100
jpeg-xl (0.9.0) unstable; urgency=medium
* Bump JPEG XL version to 0.9.0.
-- JPEG XL Maintainers <jpegxl@google.com> Tue, 21 Nov 2023 10:32:59 +0100
jpeg-xl (0.8) unstable; urgency=medium
* Bump JPEG XL version to 0.8.
-- JPEG XL Maintainers <jpegxl@google.com> Wed, 11 Jan 2023 16:12:34 +0000
jpeg-xl (0.7) unstable; urgency=medium
* Bump JPEG XL version to 0.7.

View file

@ -11,10 +11,9 @@ Build-Depends:
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),
libhwy-dev (>= 1.0.0),
libjpeg-dev,
libopenexr-dev,
libpng-dev,

View file

@ -5,6 +5,11 @@ Files: *
Copyright: 2020 the JPEG XL Project
License: BSD-3-clause
Files: third_party/libjpeg-turbo/*
Copyright (C)2009-2023 D. R. Commander. All Rights Reserved.
Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
License: BSD-3-clause
Files: third_party/sjpeg/*
Copyright: 2017 Google, Inc
License: Apache-2.0

View file

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

View file

@ -8,10 +8,14 @@ include /usr/share/dpkg/pkg-info.mk
override_dh_auto_configure:
# TODO(deymo): Remove the DCMAKE_BUILD_TYPE once builds without NDEBUG
# are as useful as Release builds.
# TODO(szabadka) Re-enable jpegli after tests are fixed on Ubuntu 20.04,
# and debian:buster
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
-DJPEGXL_ENABLE_JPEGLI=OFF \
-DJPEGXL_ENABLE_JPEGLI_LIBJPEG=OFF \
-DJPEGXL_ENABLE_PLUGINS=ON

View file

@ -5,20 +5,24 @@
# 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.
# These dependencies are normally pulled by git.
set -eu
MYDIR=$(dirname $(realpath "$0"))
SELF=$(realpath "$0")
MYDIR=$(dirname "${SELF}")
# 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"
TESTDATA="873045a9c42ed60721756e26e2a6b32e17415205"
THIRD_PARTY_BROTLI="36533a866ed1ca4b75cf049f4521e4ec5fe24727"
THIRD_PARTY_GOOGLETEST="58d77fa8070e8cec2dc1ed015d66b454c8d78850"
THIRD_PARTY_HIGHWAY="457c891775a7397bdb0376bb1031e6e027af1c48"
THIRD_PARTY_SKCMS="42030a771244ba67f86b1c1c76a6493f873c5f91"
THIRD_PARTY_SJPEG="e5ab13008bb214deb66d5f3e17ca2f8dbff150bf"
THIRD_PARTY_ZLIB="51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf" # v1.3.1
THIRD_PARTY_LIBPNG="f135775ad4e5d4408d2e12ffcc71bb36e6b48551" # v1.6.40
THIRD_PARTY_LIBJPEG_TURBO="8ecba3647edb6dd940463fedf38ca33a8e2a73d1" # 2.1.5.1
# Download the target revision from GitHub.
download_github() {
@ -26,7 +30,7 @@ download_github() {
local project="$2"
local varname=`echo "$path" | tr '[:lower:]' '[:upper:]'`
varname="${varname/\//_}"
varname="${varname//[\/-]/_}"
local sha
eval "sha=\${${varname}}"
@ -57,9 +61,16 @@ download_github() {
mv "${local_fn}.tmp" "${local_fn}"
}
is_git_repository() {
local dir="$1"
local toplevel=$(git rev-parse --show-toplevel)
[[ "${dir}" == "${toplevel}" ]]
}
main() {
if git -C "${MYDIR}" rev-parse; then
if is_git_repository "${MYDIR}"; then
cat >&2 <<EOF
Current directory is a git repository, downloading dependencies via git:
@ -71,13 +82,16 @@ EOF
fi
# Sources downloaded from a tarball.
download_github testdata libjxl/testdata
download_github third_party/brotli google/brotli
download_github third_party/googletest google/googletest
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
download_github third_party/libjpeg-turbo libjpeg-turbo/libjpeg-turbo
echo "Done."
}

View file

@ -14,13 +14,17 @@
@addtogroup libjxl
@{
@defgroup libjxl_decoder JPEG XL Decoder
@defgroup libjxl_decoder JPEG XL Decoder API
@defgroup libjxl_encoder JPEG XL Encoder
@defgroup libjxl_encoder JPEG XL Encoder API
@defgroup libjxl_common JPEG XL common definitions
@defgroup libjxl_common Common API concepts
@defgroup libjxl_butteraugli Butteraugli metric
@defgroup libjxl_metadata Image and frame metadata
@defgroup libjxl_color Color encoding and conversion
@defgroup libjxl_cpp C++ helpers
@}

View file

@ -1,8 +1,7 @@
# 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)).
script. It assumes you already have the build environment set up.
## Basic building
@ -62,11 +61,7 @@ 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.
library dependencies are already installed for the target architecture as well.
For example, to compile for the `aarch64-linux-gnu` target triplet you can run:
@ -92,9 +87,9 @@ 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
If your local git branch is tracking `origin/main` 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,
made from the common ancestor with `origin/main` 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:

View file

@ -4,15 +4,12 @@ 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`
the `emsdk` directory with the Emscripten SDK should reside there.
## Requirements
@ -40,28 +37,6 @@ cd emsdk
./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
@ -69,15 +44,19 @@ CMake, Emscripten SDK and V8 are pre-installed.
# $OPT/emsdk.
source $OPT/emsdk/emsdk_env.sh
# Specify JS engine binary
export V8=$OPT/.jsvu/v8
# This should set the $EMSDK variable.
# If your node version is <16.4.0, you might need to update to a newer version or override
# the node binary with a version which supports SIMD:
echo "NODE_JS='/path/to/node_binary'" >> $EMSDK/.emscripten
# 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:
# Assuming you are in the root level of the cloned libjxl repo,
# 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
```
## Example site
Once you have build the wasm binary, you can give it a try by building a site
that decodes jxl images, see [wasm_demo](../tools/wasm_demo/README.md).

View file

@ -4,7 +4,7 @@
<!--*
# Document freshness: For more information, see go/fresh-source.
freshness: { owner: 'janwas' reviewed: '2019-02-01' }
freshness: { owner: 'sboukortt' reviewed: '2022-09-27' }
*-->
## Why

View file

@ -0,0 +1,71 @@
### Reasoning
Given the differences in compilers / environment it is not always clear why some
build / test fails in workflows. In this document we gather practices that
would help debugging workflows.
### Debugging workflows on GitHub
To connect to real workflow on GitHub one can use "tmate" plugin. To do that,
add the following snippet in workflow .yml:
```
- name: Setup tmate session
# Or other condition that pin-points a single strategy matrix item
if: failure()
uses: mxschmitt/action-tmate@a283f9441d2d96eb62436dc46d7014f5d357ac22 # v3.17
timeout-minutes: 15
```
When the plugin is executed it dumps to log a command to "ssh" to that instance.
NB: since session is wrapped in tmux, scrolling might be very inconvenient.
### Debugging build_test_cross.yml locally
"cross" workflows are executed in container, so those are easy to reproduce
locally. Here is a snippet that reflects how setup / compilation are (currently)
done in the workflow:
```
docker run -it -v`pwd`:/libjxl debian:bookworm bash
cd /libjxl
export ARCH=i386 # arm64 armhf
export MAIN_LIST="amd64,${ARCH}"
export BUILD_DIR=build
export CC=clang-14
export CXX=clang++-14
export BUILD_TARGET=i686-linux-gnu # aarch64-linux-gnu arm-linux-gnueabihf
rm -f /var/lib/man-db/auto-update
apt-get update -y
apt-get install -y ca-certificates debian-ports-archive-keyring python3
dpkg --add-architecture ${ARCH}
python3 ./tools/scripts/transform_sources_list.py "${MAIN_LIST}"
apt update
apt-get install -y \
clang-14 cmake doxygen g++-aarch64-linux-gnu graphviz libbrotli-dev:${ARCH} \
libc6-dev-${ARCH}-cross libgdk-pixbuf2.0-dev:${ARCH} libgif-dev:${ARCH} \
libgtk2.0-dev:${ARCH} libilmbase-dev:${ARCH} libjpeg-dev:${ARCH} \
libopenexr-dev:${ARCH} libpng-dev:${ARCH} libstdc++-12-dev-${ARCH}-cross \
libstdc++-12-dev:${ARCH} libwebp-dev:${ARCH} ninja-build pkg-config \
qemu-user-static unzip xdg-utils xvfb
#apt-get install -y binutils-${BUILD_TARGET} gcc-${BUILD_TARGET}
#apt-get install -y \
# libgoogle-perftools-dev:${ARCH} libgoogle-perftools4:${ARCH} \
# libtcmalloc-minimal4:${ARCH} libunwind-dev:${ARCH}
#export CMAKE_FLAGS="-march=armv8-a+sve"
SKIP_TEST=1 ./ci.sh release \
-DJPEGXL_FORCE_SYSTEM_BROTLI=ON \
-DJPEGXL_ENABLE_JNI=OFF
# -DCMAKE_CROSSCOMPILING_EMULATOR=/usr/bin/qemu-aarch64-static
# -DJPEGXL_ENABLE_OPENEXR=off
# -DJPEGXL_ENABLE_SIZELESS_VECTORS=on
# -DCMAKE_CXX_FLAGS=-DJXL_HIGH_PRECISION=0
```

View file

@ -3,7 +3,6 @@
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
@ -13,7 +12,8 @@ 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
libgif-dev libjpeg-dev ninja-build libgoogle-perftools-dev \
graphviz
```
Make sure your default `clang` compiler is at least version 6 by running
@ -34,8 +34,8 @@ 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
sudo apt install qt6-base-dev libwebp-dev libgimp2.0-dev libopenexr-dev \
libgtest-dev libbenchmark-dev libbenchmark-tools
```
For the lint/coverage commands, you will also need additional packages:

View file

@ -1,114 +0,0 @@
# 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

@ -17,7 +17,7 @@ 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
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.
@ -93,7 +93,7 @@ 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
git clone 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
@ -231,7 +231,7 @@ 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.
to the URL to create a pull request will be displayed.
```
Enumerating objects: 627, done.
@ -309,7 +309,7 @@ In that case, you can use the force flag:
git submodule update --init --recursive --force
```
### Iterating changes in your merge request
### Iterating changes in your pull 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
@ -325,7 +325,7 @@ ones), you need to force the operation to replace the old version.
git push origin mybranch --force
```
The merge request should now be updated with the new changes.
The pull request should now be updated with the new changes.
### Merging your changes
@ -342,7 +342,7 @@ 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,
another user you can fetch the pull request commit with the following command,
replacing `NNNN` with the pull request number:
```bash

View file

@ -4,7 +4,6 @@ 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)
@ -59,11 +58,6 @@ vcpkg above.
"value": "False",
"type": "BOOL"
},
{
"name": "BUILD_GMOCK",
"value": "True",
"type": "BOOL"
},
{
"name": "gtest_force_shared_crt",
"value": "True",

View file

@ -0,0 +1,32 @@
# Encode effort settings
Various trade-offs between encode speed and compression performance can be selected in libjxl. In `cjxl`, this is done via the `--effort` (`-e`) option.
Higher effort means slower encoding; generally the higher the effort, the more coding tools are used, computationally more expensive heuristics are used,
and more exhaustive search is performed.
Generally efforts range between `1` and `9`, but there is also `e10` you pass the flag `--allow_expert_options` (in combination with "lossless", i.e. `-d 0`). It is considered an expert option because it can be extremely slow.
For lossy compression, higher effort results in better visual quality at a given filesize, and also better
encoder consistency, i.e. less image-dependent variation in the actual visual quality that is achieved. This means that for lossy compression,
higher effort does not necessarily mean smaller filesizes for every image — some images may be somewhat lower quality than desired when using
lower effort heuristics, and to improve consistency, higher effort heuristics may decide to use more bytes for them.
For lossless compression, higher effort should result in smaller filesizes, although this is not guaranteed;
in particular, e2 can be better than e3 for non-photographic images, and e3 can be better than e4 for photographic images.
The following table describes what the various effort settings do:
|Effort | Modular (lossless) | VarDCT (lossy) |
|-------|--------------------|----------------|
| e1 | fast-lossless, fixed YCoCg RCT, fixed ClampedGradient predictor, simple palette detection, no MA tree (one context for everything), Huffman, simple rle-only lz77 | |
| e2 | global channel palette, fixed MA tree (context based on Gradient-error), ANS, otherwise same as e1 | |
| e3 | same as e2 but fixed Weighted predictor and fixed MA tree with context based on WP-error | only 8x8, basically XYB jpeg with ANS |
| e4 | try both ClampedGradient and Weighted predictor, learned MA tree, global palette | simple variable blocks heuristics, adaptive quantization, coefficient reordering |
| e5 | e4 + patches, local palette / local channel palette, different local RCTs | e4 + gabor-like transform, chroma from luma |
| e6 | e5 + more RCTs and MA tree properties | e5 + error diffusion, full variable blocks heuristics |
| e7 | e6 + more RCTs and MA tree properties | e6 + patches (including dots) |
| e8 | e7 + more RCTs, MA tree properties and Weighted predictor parameters | e7 + Butteraugli iterations for adaptive quantization |
| e9 | e8 + more RCTs, MA tree properties and Weighted predictor parameters, try all predictors | e8 + more Butteraugli iterations |
| e10 | e9 + previous-channel MA tree properties, different group dimensions, exhaustively try various e9 options | |
For the entropy coding (context clustering, lz77 search, hybriduint configuration): slower/more exhaustive search as effort goes up.

View file

@ -103,7 +103,7 @@ 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)
symbolizer=$($(realpath "$(which clang)") -print-prog-name=llvm-symbolizer)
export MSAN_SYMBOLIZER_PATH="${symbolizer}"
export UBSAN_SYMBOLIZER_PATH="${symbolizer}"
export ASAN_SYMBOLIZER_PATH="${symbolizer}"
@ -135,16 +135,9 @@ 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,
* `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
within reasonable limits (automated msan/asan test should finish within 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.

View file

@ -29,7 +29,7 @@ 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`.
MAJOR.MINOR version, in order to get meaningful output 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
@ -93,6 +93,15 @@ branches](https://docs.github.com/en/github/administering-a-repository/defining-
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.
Remember to tag the first commit in the `main` branch after the branch of point
with the suffix `-snapshot`, so for instances, if you just made the
branch `v0.5.x`, run
```
git checkout [hash of first commit after the branch off point]
git tag v0.5-snapshot
git push git@github.com:libjxl/libjxl.git v0.5-snapshot
```
## Creating a merge label
@ -128,13 +137,15 @@ To help update it, run this helper command (in a Debian-based system):
This will update the version in the following files:
* `lib/CMakeLists.txt`
* `lib/lib.gni`, automatically updated with `tools/build_cleaner.py --update`.
* `lib/lib.gni`, automatically updated with
`tools/scripts/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
* `.github/workflows/conformance.yml`
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
@ -180,6 +191,15 @@ 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.
To update the version number, for example from v0.8.0 to v0.8.1 run this helper
command (in a Debian-based system):
```bash
./ci.sh bump_version 0.8.1
```
as described above and commit the changes.
Finally, upload your changes to *your fork* like normal, except that when
creating a pull request select the desired release branch as a target:
@ -263,5 +283,67 @@ instructions:
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.
* Copy-paste the following note:
```markdown
**Note:** This release is for evaluation purposes and may contain bugs, including security bugs, that may not be individually documented when fixed. See the [SECURITY.md](SECURITY.md) file for details. Always prefer to use the latest release.
Please provide feedback and report bugs [here](https://github.com/libjxl/libjxl/issues).
```
* Finally click "Publish release" and go celebrate with the team. 🎉
* The branch v0.7.x will be pushed to gitlab automatically, but make sure to
manually push the *tag* of the release also to
https://gitlab.com/wg1/jpeg-xl, by doing configuring `gitlab` to be the remote `git@gitlab.com:wg1/jpeg-xl.git` and then running:
```bash
git push gitlab v0.7.1
```
and possibly also push the tag for the snapshot to gitlab, if it wasn't done yet:
```bash
git push gitlab v0.7-snapshot
```
### How to build downstream projects
```bash
docker run -it debian:bookworm /bin/bash
apt update
apt install -y clang cmake git libbrotli-dev nasm pkg-config ninja-build
export CC=clang
export CXX=clang++
mkdir -p /src
cd /src
git clone --recurse-submodules --depth 1 -b v0.9.x \
https://github.com/libjxl/libjxl.git
git clone --recurse-submodules --depth 1 \
https://github.com/ImageMagick/ImageMagick.git
git clone --recurse-submodules --depth 1 \
https://github.com/FFmpeg/FFmpeg.git
cd /src/libjxl
cmake -B build -G Ninja .
cmake --build build -j`nproc`
cmake --install build --prefix="/usr"
cd /src/ImageMagick
./configure --with-jxl=yes
# check for "JPEG XL --with-jxl=yes yes"
make -j `nproc`
./utilities/magick -version
cd /src/FFmpeg
./configure --disable-all --disable-debug --enable-avcodec --enable-avfilter \
--enable-avformat --enable-libjxl --enable-encoder=libjxl \
--enable-decoder=libjxl --enable-ffmpeg
# check for libjxl decoder/encoder support
make -j `nproc`
ldd ./ffmpeg
./ffmpeg -version
```

View file

@ -12,20 +12,34 @@ 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)
- Chromium: behind a flag from version 91 to 109, [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)
- Safari: supported since version 17 [release notes](https://developer.apple.com/documentation/safari-release-notes/safari-17-release-notes), [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).
- Basilisk: supported since version v2023.01.07, [release notes](https://www.basilisk-browser.org/releasenotes.shtml)
- Pale Moon: supported since version 31.4.0, [release notes](https://www.palemoon.org/releasenotes-archived.shtml#v31.4.0)
- Waterfox: [enabled by default](https://github.com/WaterfoxCo/Waterfox/pull/2936)
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)
- [Imlib2](https://docs.enlightenment.org/api/imlib2/html/)
- [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
- [GraphicsMagick](http://www.graphicsmagick.org/NEWS.html#march-26-2022): supported since 1.3.38
- [SAIL](https://sail.software): supported since 0.9.0
- [JPEG XL Coder](https://github.com/awxkee/jxl-coder): Supports version from Android 5.0 (API Level 21)
- [SDWebImageJPEGXLCoder](https://github.com/SDWebImage/SDWebImageJPEGXLCoder): supported since 0.1.0
## Metadata manipulation libraries
- [ExifTool by Phil Harvey](https://exiftool.org/): supported since 12.25
- [Exiv2](https://exiv2.org): supported since 0.27.4
- [Ashampoo Kim](https://github.com/ashampoo/kim): supported since 0.10
## OS-level support / UI frameworks / file browser plugins
@ -41,25 +55,43 @@ Please add missing software to this list.
## Image editors
- [Adobe Camera Raw (since version 15)](https://helpx.adobe.com/camera-raw/using/hdr-output.html)
- [Affinity (since V2)](https://affinity.serif.com/en-gb/whats-new/)
- [darktable (since 4.2)](https://github.com/darktable-org/darktable/releases/tag/release-4.2.0)
- [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
- [Graphic Converter (since 11.5)](https://www.lemkesoft.de/en/products/graphicconverter/)
- [Krita](https://invent.kde.org/graphics/krita/-/commit/13e5d2e5b9f0eac5c8064b7767f0b62264a0797b)
- [Paint.NET](https://www.getpaint.net/index.html); supported since 4.3.12 - requires a [plugin](https://github.com/0xC0000054/pdn-jpegxl) to be downloaded and installed.
- Photoshop: no plugin available yet, no official support yet
- [XL Converter](https://github.com/JacobDev1/xl-converter)
- [Image Toolbox (supported since 2.6.0)](https://github.com/T8RIN/ImageToolbox)
- [JPEG XL Toolbox by SUIKA LTD](https://apps.apple.com/app/jpeg-xl-toolbox/id6470681357)
- [RawTherapee (since 5.11)](https://github.com/Beep6581/RawTherapee); Currently only opening of JXL files is supported. [Exporting is expected for the 6.0 release](https://github.com/Beep6581/RawTherapee/pull/7097)
## Image viewers
- [XnView](https://www.xnview.com/en/)
- [Aspect](https://aspect.bildhuus.com)
- [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.
- [jpegview](https://github.com/sylikc/jpegview/releases)
- [Swayimg](https://github.com/artemsen/swayimg)
- [Tachiyomi](https://github.com/tachiyomiorg/tachiyomi/releases/tag/v0.12.1)
- [XnView](https://www.xnview.com/en/)
- 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)
## Duplicate image finders
- [AntiDupl.NET](https://github.com/ermig1979/AntiDupl/releases)
## Online tools
- [Gumlet](https://www.gumlet.com/blog/jpeg-xl/)
- [Squoosh](https://squoosh.app/)
- [Cloudinary](https://cloudinary.com/blog/cloudinary_supports_jpeg_xl)
- [MConverter](https://mconverter.eu/)
- [jpegxl.io](https://jpegxl.io/)
- [EXIF Viewer](https://stefan-oltmann.de/exif-viewer)
- [Immich](https://immich.app/), a self-hosted image gallery service

View file

@ -1,5 +1,5 @@
API reference
=============
libjxl API reference
====================
``libjxl`` exposes a C API for encoding and decoding JPEG XL files with some
C++ header-only helpers for C++ users.
@ -11,5 +11,7 @@ C++ header-only helpers for C++ users.
api_decoder
api_encoder
api_common
api_butteraugli
api_metadata
api_color
api_threads
api_cpp

View file

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

View file

@ -0,0 +1,6 @@
Color encoding and conversion
=============================
.. doxygengroup:: libjxl_color
:members:
:private-members:

View file

@ -0,0 +1,6 @@
C++ helpers
===========
.. doxygengroup:: libjxl_cpp
:members:
:private-members:

View file

@ -0,0 +1,6 @@
Image and frame metadata
========================
.. doxygengroup:: libjxl_metadata
:members:
:private-members:

View file

@ -1,6 +0,0 @@
#### 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

@ -1,11 +0,0 @@
#!/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

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

View file

@ -1,23 +0,0 @@
#### 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

@ -1,13 +0,0 @@
#### 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

@ -1,241 +0,0 @@
#### 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

@ -1,6 +0,0 @@
#### 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

@ -1,54 +0,0 @@
#### 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

@ -1,9 +0,0 @@
#### 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

@ -1,36 +0,0 @@
/*
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

@ -1,9 +0,0 @@
#### 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

@ -1,60 +0,0 @@
#### 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

@ -1,258 +0,0 @@
#### 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

@ -1,19 +0,0 @@
#### 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

@ -1,22 +0,0 @@
#### 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

@ -1,130 +0,0 @@
#### 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

@ -1,44 +0,0 @@
#### 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

@ -1,30 +0,0 @@
#### 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

@ -195,7 +195,7 @@ engineers on the required backports.
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.
`JXL_DASSERT` 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
@ -215,22 +215,9 @@ 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.
non-release mode `JXL_DASSERT` is enabled. 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.
Out-of-bounds (OOB) reads in process memory are considered security
vulnerabilities. OOB reads may allow an attacker to read other buffers from the

View file

@ -124,7 +124,7 @@ 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
CMAKE_FLAGS="-DJXL_CRASH_ON_ERROR" ./ci.sh debug
```
In such builds, the first JXL_FAILURE will print a message identifying where the
@ -150,7 +150,7 @@ multiple image lines.
**DCT size selection**: `ac_strategy.cc`
**[Gaborish]**: `gaborish.h`.
**[Gaborish]**: `enc_gaborish.h`.
**[Edge preserving filter]**: `epf.h`

View file

@ -1,21 +0,0 @@
# 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

@ -1,37 +0,0 @@
# 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

@ -1,7 +0,0 @@
### 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

@ -1,83 +0,0 @@
#!/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

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

View file

@ -1,28 +0,0 @@
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

@ -1,37 +0,0 @@
#!/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

@ -1,518 +0,0 @@
#!/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

@ -1,131 +0,0 @@
#!/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

@ -1,83 +0,0 @@
#!/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

@ -11,46 +11,18 @@ 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)
pkg_check_modules(Jxl REQUIRED IMPORTED_TARGET libjxl libjxl_cms libjxl_threads)
# Build the example encoder/decoder binaries using the default shared libraries
# installed.
add_executable(decode_exif_metadata decode_exif_metadata.cc)
target_link_libraries(decode_exif_metadata PkgConfig::Jxl)
add_executable(decode_oneshot decode_oneshot.cc)
target_link_libraries(decode_oneshot PkgConfig::Jxl PkgConfig::JxlThreads)
target_link_libraries(decode_oneshot PkgConfig::Jxl)
add_executable(decode_progressive decode_progressive.cc)
target_link_libraries(decode_progressive PkgConfig::Jxl PkgConfig::JxlThreads)
target_link_libraries(decode_progressive PkgConfig::Jxl)
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)
target_link_libraries(encode_oneshot PkgConfig::Jxl)

View file

@ -7,6 +7,8 @@
// available at once). The example outputs the pixels and color information to a
// floating point image and an ICC profile on disk.
#include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
@ -14,16 +16,14 @@
#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)) {
if (JXL_DEC_SUCCESS != JxlDecoderSubscribeEvents(
dec.get(), JXL_DEC_BOX | JXL_DEC_BOX_COMPLETE)) {
fprintf(stderr, "JxlDecoderSubscribeEvents failed\n");
return false;
}
@ -57,8 +57,9 @@ bool DecodeJpegXlExif(const uint8_t* jxl, size_t size,
return true;
}
JxlBoxType type;
if (JXL_DEC_SUCCESS !=
JxlDecoderGetBoxType(dec.get(), type, support_decompression)) {
status = JxlDecoderGetBoxType(dec.get(), type,
TO_JXL_BOOL(support_decompression));
if (JXL_DEC_SUCCESS != status) {
fprintf(stderr, "Error, failed to get box type\n");
return false;
}
@ -72,7 +73,7 @@ bool DecodeJpegXlExif(const uint8_t* jxl, size_t size,
exif->resize(exif->size() + kChunkSize);
JxlDecoderSetBoxBuffer(dec.get(), exif->data() + output_pos,
exif->size() - output_pos);
} else if (status == JXL_DEC_SUCCESS) {
} else if (status == JXL_DEC_BOX_COMPLETE) {
if (!exif->empty()) {
size_t remaining = JxlDecoderReleaseBoxBuffer(dec.get());
exif->resize(exif->size() - remaining);
@ -97,7 +98,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
return false;
}
long size = ftell(file);
long size = ftell(file); // NOLINT
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);

View file

@ -7,7 +7,12 @@
// 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 <jxl/codestream_header.h>
#include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <jxl/resizable_parallel_runner.h>
#include <jxl/resizable_parallel_runner_cxx.h>
#include <jxl/types.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
@ -15,11 +20,6 @@
#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
@ -77,15 +77,14 @@ bool DecodeJpegXlOneShot(const uint8_t* jxl, size_t size,
// 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)) {
JxlDecoderGetICCProfileSize(dec.get(), 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,
dec.get(), JXL_COLOR_PROFILE_TARGET_DATA,
icc_profile->data(), icc_profile->size())) {
fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
return false;
@ -98,13 +97,13 @@ bool DecodeJpegXlOneShot(const uint8_t* jxl, size_t size,
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));
fprintf(stderr, "Invalid out buffer size %d %d\n",
static_cast<int>(buffer_size),
static_cast<int>(*xsize * *ysize * 16));
return false;
}
pixels->resize(*xsize * *ysize * 4);
void* pixels_buffer = (void*)pixels->data();
void* pixels_buffer = static_cast<void*>(pixels->data());
size_t pixels_buffer_size = pixels->size() * sizeof(float);
if (JXL_DEC_SUCCESS != JxlDecoderSetImageOutBuffer(dec.get(), &format,
pixels_buffer,
@ -143,8 +142,8 @@ bool WritePFM(const char* filename, const float* pixels, size_t xsize,
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");
fprintf(file, "PF\n%d %d\n%s\n", static_cast<int>(xsize),
static_cast<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++) {
@ -170,7 +169,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
return false;
}
long size = ftell(file);
long size = ftell(file); // NOLINT
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
@ -229,7 +228,8 @@ int main(int argc, char* argv[]) {
std::vector<float> pixels;
std::vector<uint8_t> icc_profile;
size_t xsize = 0, ysize = 0;
size_t xsize = 0;
size_t ysize = 0;
if (!DecodeJpegXlOneShot(jxl.data(), jxl.size(), &pixels, &xsize, &ysize,
&icc_profile)) {
fprintf(stderr, "Error while decoding the jxl file\n");

View file

@ -6,19 +6,22 @@
// 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>
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <jxl/resizable_parallel_runner.h>
#include <jxl/resizable_parallel_runner_cxx.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <cinttypes> // PRIu64
#include <cstdint>
#include <cstdio>
#include <cstring>
#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) {
@ -26,11 +29,14 @@ bool WritePAM(const char* filename, const uint8_t* buffer, size_t w, size_t h) {
return false;
}
fprintf(fp,
"P7\nWIDTH %" PRIu64 "\nHEIGHT %" PRIu64
"\nDEPTH 4\nMAXVAL 255\nTUPLTYPE "
"P7\nWIDTH %d\nHEIGHT %d\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);
static_cast<int>(w), static_cast<int>(h));
size_t num_bytes = w * h * 4;
if (fwrite(buffer, 1, num_bytes, fp) != num_bytes) {
fclose(fp);
return false;
};
if (fclose(fp) != 0) {
return false;
}
@ -44,7 +50,8 @@ 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;
size_t xsize = 0;
size_t ysize = 0;
// Multi-threaded parallel runner.
auto runner = JxlResizableParallelRunnerMake(nullptr);
@ -121,16 +128,14 @@ bool DecodeJpegXlProgressive(const uint8_t* jxl, size_t size,
// 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)) {
JxlDecoderGetICCProfileSize(
dec.get(), 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,
dec.get(), JXL_COLOR_PROFILE_TARGET_ORIGINAL,
icc_profile.data(), icc_profile.size())) {
fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
return false;
@ -149,11 +154,9 @@ bool DecodeJpegXlProgressive(const uint8_t* jxl, size_t size,
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)) {
pixels.data(),
pixels.size())) {
fprintf(stderr, "JxlDecoderSetImageOutBuffer failed\n");
return false;
}
@ -175,7 +178,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
return false;
}
long size = ftell(file);
long size = ftell(file); // NOLINT
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
@ -221,7 +224,7 @@ int main(int argc, char* argv[]) {
}
size_t chunksize = jxl.size();
if (argc > 3) {
long cs = atol(argv[3]);
long cs = atol(argv[3]); // NOLINT
if (cs < 100) {
fprintf(stderr, "Chunk size is too low, try at least 100 bytes\n");
return 1;

View file

@ -6,18 +6,22 @@
// This example encodes a file containing a floating point image to another
// file containing JPEG XL image with a single frame.
#include <jxl/codestream_header.h>
#include <jxl/color_encoding.h>
#include <jxl/encode.h>
#include <jxl/encode_cxx.h>
#include <jxl/thread_parallel_runner.h>
#include <jxl/thread_parallel_runner_cxx.h>
#include <jxl/types.h>
#include <limits.h>
#include <string.h>
#include <cstdint>
#include <cstdio>
#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)
*
@ -35,15 +39,16 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
return false;
}
uint32_t endian_test = 1;
uint8_t little_endian[4];
memcpy(little_endian, &endian_test, 4);
uint8_t little_endian_check[4];
memcpy(little_endian_check, &endian_test, 4);
bool little_endian = (little_endian_check[0] == 1);
if (fseek(file, 0, SEEK_END) != 0) {
fclose(file);
return false;
}
long size = ftell(file);
long size = ftell(file); // NOLINT
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
@ -59,7 +64,8 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
data.resize(size);
size_t readsize = fread(data.data(), 1, size, file);
if ((long)readsize != size) {
if (static_cast<long>(readsize) != size) { // NOLINT
fclose(file);
return false;
}
if (fclose(file) != 0) {
@ -111,12 +117,13 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
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));
filename, static_cast<int>(data.size()), static_cast<int>(*ysize),
static_cast<int>(*xsize), static_cast<int>(offset),
static_cast<int>(*ysize * *xsize * 3 * 4 + offset));
return false;
}
if (!!little_endian[0] != input_little_endian) {
if (little_endian != input_little_endian) {
fprintf(stderr,
"%s has a different endianness than we do, conversion is not "
"supported.\n",
@ -127,7 +134,7 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
pixels->resize(*ysize * *xsize * 3);
for (int y = *ysize - 1; y >= 0; y--) {
for (int x = 0; x < (int)*xsize; x++) {
for (int x = 0; x < static_cast<int>(*xsize); x++) {
for (int c = 0; c < 3; c++) {
memcpy(pixels->data() + (y * *xsize + x) * 3 + c, data.data() + offset,
sizeof(float));
@ -175,8 +182,8 @@ bool EncodeJxlOneshot(const std::vector<float>& pixels, const uint32_t xsize,
}
JxlColorEncoding color_encoding = {};
JxlColorEncodingSetToSRGB(&color_encoding,
/*is_gray=*/pixel_format.num_channels < 3);
JXL_BOOL is_gray = TO_JXL_BOOL(pixel_format.num_channels < 3);
JxlColorEncodingSetToSRGB(&color_encoding, is_gray);
if (JXL_ENC_SUCCESS !=
JxlEncoderSetColorEncoding(enc.get(), &color_encoding)) {
fprintf(stderr, "JxlEncoderSetColorEncoding failed\n");
@ -188,7 +195,7 @@ bool EncodeJxlOneshot(const std::vector<float>& pixels, const uint32_t xsize,
if (JXL_ENC_SUCCESS !=
JxlEncoderAddImageFrame(frame_settings, &pixel_format,
(void*)pixels.data(),
static_cast<const void*>(pixels.data()),
sizeof(float) * pixels.size())) {
fprintf(stderr, "JxlEncoderAddImageFrame failed\n");
return false;
@ -229,6 +236,7 @@ bool WriteFile(const std::vector<uint8_t>& bytes, const char* filename) {
if (fwrite(bytes.data(), sizeof(uint8_t), bytes.size(), file) !=
bytes.size()) {
fprintf(stderr, "Could not write bytes to %s\n", filename);
fclose(file);
return false;
}
if (fclose(file) != 0) {

View file

@ -3,6 +3,8 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
add_executable(decode_exif_metadata ${CMAKE_CURRENT_LIST_DIR}/decode_exif_metadata.cc)
target_link_libraries(decode_exif_metadata jxl_dec jxl_threads)
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)

File diff suppressed because it is too large Load diff

View file

@ -1,14 +0,0 @@
// 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.
#ifndef FAST_LOSSLESS_H
#define FAST_LOSSLESS_H
#include <stdlib.h>
size_t FastLosslessEncode(const unsigned char* rgba, size_t width,
size_t row_stride, size_t height, size_t nb_chans,
size_t bitdepth, int effort, unsigned char** output);
#endif

61
media/libjxl/src/flake.lock generated Normal file
View file

@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1702312524,
"narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a9bf124c46ef298113270b1f84a164865987a91c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -0,0 +1,38 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem
(system:
let
pkgs = import nixpkgs {
inherit system;
};
in
with pkgs;
{
devShells.default = mkShell {
buildInputs = [
clang
cmake
pkg-config
gtest
doxygen
graphviz
python3
libclang.python
libpng
giflib
lcms2
brotli
];
shellHook = ''
export CC=clang
export CXX=clang++
'';
};
}
);
}

314
media/libjxl/src/lib/BUILD Normal file
View file

@ -0,0 +1,314 @@
# 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.
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
# Load sources/headers/tests lists.
load(
"jxl_lists.bzl",
"libjxl_base_sources",
"libjxl_cms_sources",
"libjxl_codec_apng_sources",
"libjxl_codec_exr_sources",
"libjxl_codec_gif_sources",
"libjxl_codec_jpegli_sources",
"libjxl_codec_jpg_sources",
"libjxl_codec_jxl_sources",
"libjxl_codec_npy_sources",
"libjxl_codec_pgx_sources",
"libjxl_codec_pnm_sources",
"libjxl_dec_box_sources",
"libjxl_dec_jpeg_sources",
"libjxl_dec_sources",
"libjxl_enc_sources",
"libjxl_extras_for_tools_sources",
"libjxl_extras_sources",
# "libjxl_gbench_sources",
# "libjxl_jpegli_lib_version",
"libjxl_jpegli_libjpeg_helper_files",
"libjxl_jpegli_sources",
"libjxl_jpegli_testlib_files",
"libjxl_jpegli_tests",
"libjxl_major_version",
"libjxl_minor_version",
"libjxl_patch_version",
"libjxl_public_headers",
"libjxl_testlib_files",
"libjxl_tests",
"libjxl_threads_public_headers",
"libjxl_threads_sources",
)
load(
"jxl_vars.bzl",
"libjxl_deps_brotli",
"libjxl_deps_exr",
"libjxl_deps_gif",
"libjxl_deps_gtest",
"libjxl_deps_hwy",
"libjxl_deps_hwy_nanobenchmark",
"libjxl_deps_hwy_test_util",
"libjxl_deps_jpeg",
"libjxl_deps_png",
"libjxl_deps_runfiles",
"libjxl_deps_skcms",
# "libjxl_deps_testdata",
# "libjxl_deps_webp",
"libjxl_root_package",
"libjxl_test_shards",
"libjxl_test_timeouts",
)
DEFAULT_VISIBILITY = ["//:__subpackages__"]
DEFAULT_COMPATIBILITY = []
INCLUDES_DIR = "include"
package(
default_visibility = DEFAULT_VISIBILITY,
)
licenses(["notice"])
exports_files(["LICENSE"])
EXPORT_TEMPLATE = """
#ifndef @_EXPORT_H
#define @_EXPORT_H
#define @_EXPORT
#define @_NO_EXPORT
#ifndef @_DEPRECATED
# define @_DEPRECATED __attribute__ ((__deprecated__))
#endif
#endif
"""
JXL_EXPORT_H = INCLUDES_DIR + "/jxl/jxl_export.h"
genrule(
name = "create_jxl_export",
outs = [JXL_EXPORT_H],
cmd = "echo '" + EXPORT_TEMPLATE.replace("@", "JXL") + "' > $@",
compatible_with = DEFAULT_COMPATIBILITY,
)
JXL_CMS_EXPORT_H = INCLUDES_DIR + "/jxl/jxl_cms_export.h"
genrule(
name = "create_jxl_cms_export",
outs = [JXL_CMS_EXPORT_H],
cmd = "echo '" + EXPORT_TEMPLATE.replace("@", "JXL_CMS") + "' > $@",
compatible_with = DEFAULT_COMPATIBILITY,
)
JXL_THREADS_EXPORT_H = INCLUDES_DIR + "/jxl/jxl_threads_export.h"
genrule(
name = "create_jxl_threads_export",
outs = [JXL_THREADS_EXPORT_H],
cmd = "echo '" + EXPORT_TEMPLATE.replace("@", "JXL_THREADS") + "' > $@",
compatible_with = DEFAULT_COMPATIBILITY,
)
JXL_VERSION_H = INCLUDES_DIR + "/jxl/version.h"
expand_template(
name = "expand_jxl_version",
out = JXL_VERSION_H,
compatible_with = DEFAULT_COMPATIBILITY,
substitutions = {
"@JPEGXL_MAJOR_VERSION@": str(libjxl_major_version),
"@JPEGXL_MINOR_VERSION@": str(libjxl_minor_version),
"@JPEGXL_PATCH_VERSION@": str(libjxl_patch_version),
},
template = "jxl/version.h.in",
)
cc_library(
name = "jxl_version",
hdrs = [JXL_VERSION_H],
compatible_with = DEFAULT_COMPATIBILITY,
strip_include_prefix = INCLUDES_DIR,
)
JPEGLI_JCONFIG_H = INCLUDES_DIR + "/jpegli/jconfig.h"
JPEGLI_JMORECFG_H = INCLUDES_DIR + "/jpegli/jmorecfg.h"
JPEGLI_JPEGLIB_H = INCLUDES_DIR + "/jpegli/jpeglib.h"
copy_file(
name = "expand_jconfig",
src = "@libjpeg_turbo//:jconfig.h",
out = JPEGLI_JCONFIG_H,
compatible_with = DEFAULT_COMPATIBILITY,
)
copy_file(
name = "copy_jmorecfg",
src = "@libjpeg_turbo//:jmorecfg.h",
out = JPEGLI_JMORECFG_H,
compatible_with = DEFAULT_COMPATIBILITY,
)
copy_file(
name = "copy_jpeglib",
src = "@libjpeg_turbo//:jpeglib.h",
out = JPEGLI_JPEGLIB_H,
compatible_with = DEFAULT_COMPATIBILITY,
)
cc_library(
name = "includes",
hdrs = libjxl_public_headers + [
JXL_EXPORT_H,
JXL_CMS_EXPORT_H,
],
compatible_with = DEFAULT_COMPATIBILITY,
strip_include_prefix = INCLUDES_DIR,
deps = [":jxl_version"],
)
cc_library(
name = "libjpeg_includes",
hdrs = [
JPEGLI_JCONFIG_H,
JPEGLI_JMORECFG_H,
JPEGLI_JPEGLIB_H,
],
compatible_with = DEFAULT_COMPATIBILITY,
strip_include_prefix = INCLUDES_DIR + "/jpegli",
)
cc_library(
name = "base",
srcs = [path for path in libjxl_base_sources if path.endswith(".cc")],
hdrs = [path for path in libjxl_base_sources if path.endswith(".h")],
compatible_with = DEFAULT_COMPATIBILITY,
deps = [
":includes",
] + libjxl_deps_hwy,
)
cc_library(
name = "jpegxl",
srcs = libjxl_dec_sources + libjxl_dec_box_sources + libjxl_dec_jpeg_sources + libjxl_enc_sources + libjxl_cms_sources,
compatible_with = DEFAULT_COMPATIBILITY,
defines = [
"JPEGXL_ENABLE_SKCMS=1",
],
deps = [
":base",
":includes",
] + libjxl_deps_brotli + libjxl_deps_hwy + libjxl_deps_skcms,
)
cc_library(
name = "jpegxl_private",
hdrs = [
path
for path in libjxl_dec_sources + libjxl_dec_box_sources + libjxl_dec_jpeg_sources + libjxl_enc_sources + libjxl_cms_sources
if path.endswith(".h") and not path.endswith("-inl.h")
],
compatible_with = DEFAULT_COMPATIBILITY,
deps = [":jpegxl"],
)
cc_library(
name = "jpegxl_threads",
srcs = libjxl_threads_sources,
hdrs = libjxl_threads_public_headers + [JXL_THREADS_EXPORT_H],
compatible_with = DEFAULT_COMPATIBILITY,
strip_include_prefix = INCLUDES_DIR,
deps = [
":base",
":includes",
],
)
CODEC_FILES = libjxl_codec_apng_sources + libjxl_codec_exr_sources + libjxl_codec_gif_sources + libjxl_codec_jpegli_sources + libjxl_codec_jpg_sources + libjxl_codec_jxl_sources + libjxl_codec_npy_sources + libjxl_codec_pgx_sources + libjxl_codec_pnm_sources
CODEC_SRCS = [path for path in CODEC_FILES if path.endswith(".cc")]
CODEC_HDRS = [path for path in CODEC_FILES if path.endswith(".h")]
cc_library(
name = "jpegli",
srcs = libjxl_jpegli_sources,
hdrs = [
"jpegli/common_internal.h", # TODO(eustas): should not be here
],
compatible_with = DEFAULT_COMPATIBILITY,
deps = [
":jpegxl_private",
":libjpeg_includes",
] + libjxl_deps_hwy,
)
# TODO(eustas): build codecs separately?
cc_library(
name = "jpegxl_extras",
srcs = libjxl_extras_sources + libjxl_extras_for_tools_sources + CODEC_SRCS,
hdrs = CODEC_HDRS,
compatible_with = DEFAULT_COMPATIBILITY,
defines = [
"JPEGXL_ENABLE_APNG=1",
"JPEGXL_ENABLE_EXR=1",
"JPEGXL_ENABLE_GIF=1",
"JPEGXL_ENABLE_JPEG=1",
"JPEGXL_ENABLE_JPEGLI=1",
],
deps = [
":jpegli",
":jpegxl_private",
":jpegxl_threads",
":jxl_version",
] + libjxl_deps_exr + libjxl_deps_gif + libjxl_deps_jpeg + libjxl_deps_png,
)
TESTLIB_FILES = libjxl_testlib_files + libjxl_jpegli_testlib_files + libjxl_jpegli_libjpeg_helper_files
cc_library(
name = "test_utils",
testonly = 1,
srcs = [path for path in TESTLIB_FILES if not path.endswith(".h")],
hdrs = [path for path in TESTLIB_FILES if path.endswith(".h")],
compatible_with = DEFAULT_COMPATIBILITY,
defines = [
'JPEGXL_ROOT_PACKAGE=\'"' + libjxl_root_package + '"\'',
],
deps = [
":jpegli",
":jpegxl_extras",
":jpegxl_private",
] + libjxl_deps_runfiles,
)
TESTS = [path.partition(".")[0] for path in libjxl_tests + libjxl_jpegli_tests]
[
cc_test(
name = test,
timeout = libjxl_test_timeouts.get(test, "moderate"),
srcs = [
test + ".cc",
"jpegli/testing.h",
"jxl/testing.h",
],
data = ["//:testdata"],
shard_count = libjxl_test_shards.get(test, 1),
deps = [
":jpegxl_extras",
":jpegxl_private",
":jpegxl_threads",
":test_utils",
] + libjxl_deps_gtest + libjxl_deps_hwy_test_util + libjxl_deps_hwy_nanobenchmark,
)
for test in TESTS
]

View file

@ -4,8 +4,8 @@
# license that can be found in the LICENSE file.
set(JPEGXL_MAJOR_VERSION 0)
set(JPEGXL_MINOR_VERSION 7)
set(JPEGXL_PATCH_VERSION 0)
set(JPEGXL_MINOR_VERSION 11)
set(JPEGXL_PATCH_VERSION 1)
set(JPEGXL_LIBRARY_VERSION
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_MINOR_VERSION}.${JPEGXL_PATCH_VERSION}")
@ -15,152 +15,179 @@ set(JPEGXL_LIBRARY_VERSION
# It is important to update this value when making incompatible API/ABI changes
# so that programs that depend on libjxl can update their dependencies. Semantic
# versioning allows 0.y.z to have incompatible changes in minor versions.
set(JPEGXL_SO_MINOR_VERSION 7)
set(JPEGXL_SO_MINOR_VERSION 11)
if (JPEGXL_MAJOR_VERSION EQUAL 0)
set(JPEGXL_LIBRARY_SOVERSION
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_SO_MINOR_VERSION}")
set(JPEGXL_LIBRARY_SOVERSION
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_SO_MINOR_VERSION}")
else()
set(JPEGXL_LIBRARY_SOVERSION "${JPEGXL_MAJOR_VERSION}")
set(JPEGXL_LIBRARY_SOVERSION "${JPEGXL_MAJOR_VERSION}")
endif()
# List of warning and feature flags for our library and tests.
if (MSVC)
set(JPEGXL_INTERNAL_FLAGS
# TODO(janwas): add flags
)
set(JPEGXL_INTERNAL_FLAGS
# TODO(janwas): add flags
)
else ()
set(JPEGXL_INTERNAL_FLAGS
# F_FLAGS
-fmerge-all-constants
-fno-builtin-fwrite
-fno-builtin-fread
set(JPEGXL_INTERNAL_FLAGS
# F_FLAGS
-fmerge-all-constants
-fno-builtin-fwrite
-fno-builtin-fread
# WARN_FLAGS
-Wall
-Wextra
-Wc++11-compat
-Warray-bounds
-Wformat-security
-Wimplicit-fallthrough
-Wno-register # Needed by public headers in lcms
-Wno-unused-function
-Wno-unused-parameter
-Wnon-virtual-dtor
-Woverloaded-virtual
-Wvla
)
# Warning flags supported by clang.
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND JPEGXL_INTERNAL_FLAGS
-Wdeprecated-increment-bool
# TODO(deymo): Add -Wextra-semi once we update third_party/highway.
# -Wextra-semi
-Wfloat-overflow-conversion
-Wfloat-zero-conversion
-Wfor-loop-analysis
-Wgnu-redeclared-enum
-Winfinite-recursion
-Wliteral-conversion
-Wno-c++98-compat
-Wno-unused-command-line-argument
-Wprivate-header
-Wself-assign
-Wstring-conversion
-Wtautological-overlap-compare
-Wthread-safety-analysis
-Wundefined-func-template
-Wunreachable-code
-Wunused-comparison
)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0)
list(APPEND HWY_FLAGS -Wc++2a-extensions)
endif()
endif() # Clang
if (WIN32)
list(APPEND JPEGXL_INTERNAL_FLAGS
-Wno-cast-align
-Wno-double-promotion
-Wno-float-equal
-Wno-format-nonliteral
-Wno-shadow
-Wno-sign-conversion
-Wno-zero-as-null-pointer-constant
# WARN_FLAGS
-Wall
-Wextra
-Wc++11-compat
-Warray-bounds
-Wformat-security
-Wimplicit-fallthrough
-Wno-register # Needed by public headers in lcms
-Wno-unused-function
-Wno-unused-parameter
-Wnon-virtual-dtor
-Woverloaded-virtual
-Wvla
)
# Warning flags supported by clang.
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND JPEGXL_INTERNAL_FLAGS
-Wno-used-but-marked-unused
-Wno-unused-template
-Wno-unused-member-function
-Wno-shadow-field-in-constructor
-Wno-language-extension-token
-Wno-global-constructors
-Wno-c++98-compat-pedantic
-Wdeprecated-increment-bool
# TODO(deymo): Add -Wextra-semi once we update third_party/highway.
# -Wextra-semi
-Wfloat-overflow-conversion
-Wfloat-zero-conversion
-Wfor-loop-analysis
-Wgnu-redeclared-enum
-Winfinite-recursion
-Wliteral-conversion
-Wno-c++98-compat
-Wno-unused-command-line-argument
-Wprivate-header
-Wself-assign
-Wstring-conversion
-Wtautological-overlap-compare
-Wthread-safety-analysis
-Wundefined-func-template
-Wunreachable-code
-Wunused-comparison
)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0)
list(APPEND HWY_FLAGS -Wc++2a-extensions)
endif()
endif() # Clang
else() # WIN32
list(APPEND JPEGXL_INTERNAL_FLAGS
-fsized-deallocation
-fno-exceptions
# Language flags
-fmath-errno
)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if (WIN32)
list(APPEND JPEGXL_INTERNAL_FLAGS
-fnew-alignment=8
-fno-cxx-exceptions
-fno-slp-vectorize
-fno-vectorize
-disable-free
-disable-llvm-verifier
-Wno-cast-align
-Wno-double-promotion
-Wno-float-equal
-Wno-format-nonliteral
-Wno-shadow
-Wno-sign-conversion
-Wno-zero-as-null-pointer-constant
)
endif() # Clang
endif() # WIN32
# Internal flags for coverage builds:
if(JPEGXL_ENABLE_COVERAGE)
set(JPEGXL_COVERAGE_FLAGS
-g -O0 -fprofile-arcs -ftest-coverage
-DJXL_ENABLE_ASSERT=0 -DJXL_ENABLE_CHECK=0
)
endif() # JPEGXL_ENABLE_COVERAGE
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND JPEGXL_INTERNAL_FLAGS
-Wno-used-but-marked-unused
-Wno-unused-template
-Wno-unused-member-function
-Wno-shadow-field-in-constructor
-Wno-language-extension-token
-Wno-global-constructors
-Wno-c++98-compat-pedantic
)
endif() # Clang
else() # WIN32
list(APPEND JPEGXL_INTERNAL_FLAGS
-fsized-deallocation
-fno-exceptions
# Language flags
-fmath-errno
)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND JPEGXL_INTERNAL_FLAGS
-fnew-alignment=8
-fno-cxx-exceptions
-fno-slp-vectorize
-fno-vectorize
-disable-free
-disable-llvm-verifier
)
endif() # Clang
endif() # WIN32
endif() #!MSVC
if (JPEGXL_ENABLE_SKCMS)
list(APPEND JPEGXL_INTERNAL_FLAGS -DJPEGXL_ENABLE_SKCMS=1)
endif ()
# strips the -internal suffix from all the elements in LIST
function(strip_internal OUTPUT_VAR LIB_LIST)
foreach(lib IN LISTS ${LIB_LIST})
string(REGEX REPLACE "-internal$" "" lib "${lib}")
list(APPEND out_list "${lib}")
endforeach()
set(${OUTPUT_VAR} ${out_list} PARENT_SCOPE)
endfunction()
# set variables for jxl_cms.cmake and jxl.cmake
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
set(PKGCONFIG_TARGET_INCLUDES "${CMAKE_INSTALL_INCLUDEDIR}")
else()
set(PKGCONFIG_TARGET_INCLUDES "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
endif()
if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}")
set(PKGCONFIG_TARGET_LIBS "${CMAKE_INSTALL_LIBDIR}")
else()
set(PKGCONFIG_TARGET_LIBS "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
endif()
include(CheckCXXSymbolExists)
set(PKGCONFIG_CXX_LIB "")
check_cxx_symbol_exists(__GLIBCXX__ iostream LIBSTDCXX)
check_cxx_symbol_exists(_LIBCPP_VERSION iostream LIBCXX)
if(LIBSTDCXX)
set(PKGCONFIG_CXX_LIB "-lstdc++")
elseif(LIBCXX)
set(PKGCONFIG_CXX_LIB "-lc++")
endif()
# The jxl_cms library definition.
include(jxl_cms.cmake)
# The jxl library definition.
include(jxl.cmake)
# Other libraries outside the core jxl library.
if(JPEGXL_ENABLE_TOOLS)
if(JPEGXL_ENABLE_TOOLS OR BUILD_TESTING)
include(jxl_extras.cmake)
endif()
include(jxl_threads.cmake)
if (JPEGXL_ENABLE_JPEGLI)
include(jpegli.cmake)
endif()
# Install all the library headers from the source and the generated ones. There
# is no distinction on which libraries use which header since it is expected
# that all developer libraries are available together at build time.
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/jxl
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
# For simplicity all the library headers, both source and generated ones, are
# gathered in the binary folder. There is no distinction on which libraries use
# which header since it is expected that all developer libraries are available
# together at build time.
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/jxl
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
# Profiler for libjxl
include(jxl_profiler.cmake)
if(BUILD_TESTING)
# Unittests
cmake_policy(SET CMP0057 NEW) # https://gitlab.kitware.com/cmake/cmake/issues/18198
include(GoogleTest)
include(GoogleTest)
endif()
# Tests for the jxl library.
include(jxl_tests.cmake)
# Google benchmark for the jxl library
include(jxl_benchmark.cmake)
endif() # BUILD_TESTING
if(BUILD_TESTING)
# Google benchmark for the jxl library
include(jxl_benchmark.cmake)
endif()

View file

@ -0,0 +1,67 @@
// 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.
#include "lib/extras/alpha_blend.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
namespace {
Status AlphaBlend(PackedFrame* frame, const float background[3]) {
if (!frame) return true;
const PackedImage& im = frame->color;
JxlPixelFormat format = im.format;
if (format.num_channels != 2 && format.num_channels != 4) {
return true;
}
--format.num_channels;
JXL_ASSIGN_OR_RETURN(PackedImage blended,
PackedImage::Create(im.xsize, im.ysize, format));
// TODO(szabadka) SIMDify this and make it work for float16.
for (size_t y = 0; y < im.ysize; ++y) {
for (size_t x = 0; x < im.xsize; ++x) {
if (format.num_channels == 2) {
float g = im.GetPixelValue(y, x, 0);
float a = im.GetPixelValue(y, x, 1);
float out = g * a + background[0] * (1 - a);
blended.SetPixelValue(y, x, 0, out);
} else {
float r = im.GetPixelValue(y, x, 0);
float g = im.GetPixelValue(y, x, 1);
float b = im.GetPixelValue(y, x, 2);
float a = im.GetPixelValue(y, x, 3);
float out_r = r * a + background[0] * (1 - a);
float out_g = g * a + background[1] * (1 - a);
float out_b = b * a + background[2] * (1 - a);
blended.SetPixelValue(y, x, 0, out_r);
blended.SetPixelValue(y, x, 1, out_g);
blended.SetPixelValue(y, x, 2, out_b);
}
}
}
frame->color = blended.Copy();
return true;
}
} // namespace
Status AlphaBlend(PackedPixelFile* ppf, const float background[3]) {
if (!ppf || ppf->info.alpha_bits == 0) {
return true;
}
ppf->info.alpha_bits = 0;
JXL_RETURN_IF_ERROR(AlphaBlend(ppf->preview_frame.get(), background));
for (auto& frame : ppf->frames) {
JXL_RETURN_IF_ERROR(AlphaBlend(&frame, background));
}
return true;
}
} // namespace extras
} // namespace jxl

View file

@ -0,0 +1,20 @@
// 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.
#ifndef LIB_EXTRAS_ALPHA_BLEND_H_
#define LIB_EXTRAS_ALPHA_BLEND_H_
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
Status AlphaBlend(PackedPixelFile* ppf, const float background[3]);
} // namespace extras
} // namespace jxl
#endif // LIB_EXTRAS_ALPHA_BLEND_H_

View file

@ -5,28 +5,18 @@
#include "lib/extras/codec.h"
#include "jxl/decode.h"
#include "jxl/types.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/padded_bytes.h"
#include "lib/jxl/base/status.h"
#if JPEGXL_ENABLE_APNG
#include "lib/extras/enc/apng.h"
#endif
#if JPEGXL_ENABLE_JPEG
#include "lib/extras/enc/jpg.h"
#endif
#if JPEGXL_ENABLE_EXR
#include "lib/extras/enc/exr.h"
#endif
#include <jxl/decode.h>
#include <jxl/types.h>
#include "lib/extras/dec/decode.h"
#include "lib/extras/enc/apng.h"
#include "lib/extras/enc/exr.h"
#include "lib/extras/enc/jpg.h"
#include "lib/extras/enc/pgx.h"
#include "lib/extras/enc/pnm.h"
#include "lib/extras/packed_image.h"
#include "lib/extras/packed_image_convert.h"
#include "lib/jxl/base/file_io.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/base/status.h"
namespace jxl {
namespace {
@ -38,78 +28,46 @@ constexpr size_t kMinBytes = 9;
Status SetFromBytes(const Span<const uint8_t> bytes,
const extras::ColorHints& color_hints, CodecInOut* io,
ThreadPool* pool, extras::Codec* orig_codec) {
ThreadPool* pool, const SizeConstraints* constraints,
extras::Codec* orig_codec) {
if (bytes.size() < kMinBytes) return JXL_FAILURE("Too few bytes");
extras::PackedPixelFile ppf;
if (extras::DecodeBytes(bytes, color_hints, io->constraints, &ppf,
orig_codec)) {
if (extras::DecodeBytes(bytes, color_hints, &ppf, constraints, orig_codec)) {
return ConvertPackedPixelFileToCodecInOut(ppf, pool, io);
}
return JXL_FAILURE("Codecs failed to decode");
}
Status SetFromFile(const std::string& pathname,
const extras::ColorHints& color_hints, CodecInOut* io,
ThreadPool* pool, extras::Codec* orig_codec) {
std::vector<uint8_t> encoded;
JXL_RETURN_IF_ERROR(ReadFile(pathname, &encoded));
JXL_RETURN_IF_ERROR(SetFromBytes(Span<const uint8_t>(encoded), color_hints,
io, pool, orig_codec));
return true;
}
Status Encode(const CodecInOut& io, const extras::Codec codec,
const ColorEncoding& c_desired, size_t bits_per_sample,
Status Encode(const extras::PackedPixelFile& ppf, const extras::Codec codec,
std::vector<uint8_t>* bytes, ThreadPool* pool) {
JXL_CHECK(!io.Main().c_current().ICC().empty());
JXL_CHECK(!c_desired.ICC().empty());
io.CheckMetadata();
if (io.Main().IsJPEG()) {
JXL_WARNING("Writing JPEG data as pixels");
}
JxlPixelFormat format = {
0, // num_channels is ignored by the converter
bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16, JXL_BIG_ENDIAN,
0};
const bool floating_point = bits_per_sample > 16;
bytes->clear();
std::unique_ptr<extras::Encoder> encoder;
std::ostringstream os;
switch (codec) {
case extras::Codec::kPNG:
#if JPEGXL_ENABLE_APNG
encoder = extras::GetAPNGEncoder();
break;
#else
return JXL_FAILURE("JPEG XL was built without (A)PNG support");
#endif
if (encoder) {
break;
} else {
return JXL_FAILURE("JPEG XL was built without (A)PNG support");
}
case extras::Codec::kJPG:
#if JPEGXL_ENABLE_JPEG
format.data_type = JXL_TYPE_UINT8;
encoder = extras::GetJPEGEncoder();
os << io.jpeg_quality;
encoder->SetOption("q", os.str());
break;
#else
return JXL_FAILURE("JPEG XL was built without JPEG support");
#endif
if (encoder) {
break;
} else {
return JXL_FAILURE("JPEG XL was built without JPEG support");
}
case extras::Codec::kPNM:
if (io.Main().HasAlpha()) {
if (ppf.info.alpha_bits > 0) {
encoder = extras::GetPAMEncoder();
} else if (io.Main().IsGray()) {
} else if (ppf.info.num_color_channels == 1) {
encoder = extras::GetPGMEncoder();
} else if (!floating_point) {
} else if (ppf.info.bits_per_sample <= 16) {
encoder = extras::GetPPMEncoder();
} else {
format.data_type = JXL_TYPE_FLOAT;
format.endianness = JXL_NATIVE_ENDIAN;
encoder = extras::GetPFMEncoder();
}
if (!c_desired.IsSRGB()) {
JXL_WARNING(
"PNM encoder cannot store custom ICC profile; decoder "
"will need hint key=color_space to get the same values");
}
break;
case extras::Codec::kPGX:
encoder = extras::GetPGXEncoder();
@ -117,13 +75,16 @@ Status Encode(const CodecInOut& io, const extras::Codec codec,
case extras::Codec::kGIF:
return JXL_FAILURE("Encoding to GIF is not implemented");
case extras::Codec::kEXR:
#if JPEGXL_ENABLE_EXR
format.data_type = JXL_TYPE_FLOAT;
encoder = extras::GetEXREncoder();
break;
#else
return JXL_FAILURE("JPEG XL was built without OpenEXR support");
#endif
if (encoder) {
break;
} else {
return JXL_FAILURE("JPEG XL was built without OpenEXR support");
}
case extras::Codec::kJXL:
// TODO(user): implement
return JXL_FAILURE("Codec::kJXL is not supported yet");
case extras::Codec::kUnknown:
return JXL_FAILURE("Cannot encode using Codec::kUnknown");
}
@ -131,59 +92,20 @@ Status Encode(const CodecInOut& io, const extras::Codec codec,
if (!encoder) {
return JXL_FAILURE("Invalid codec.");
}
extras::PackedPixelFile ppf;
JXL_RETURN_IF_ERROR(
ConvertCodecInOutToPackedPixelFile(io, format, c_desired, pool, &ppf));
extras::EncodedImage encoded_image;
JXL_RETURN_IF_ERROR(encoder->Encode(ppf, &encoded_image, pool));
JXL_ASSERT(encoded_image.bitstreams.size() == 1);
JXL_ENSURE(encoded_image.bitstreams.size() == 1);
*bytes = encoded_image.bitstreams[0];
return true;
}
Status EncodeToFile(const CodecInOut& io, const ColorEncoding& c_desired,
size_t bits_per_sample, const std::string& pathname,
ThreadPool* pool) {
const std::string extension = Extension(pathname);
Status Encode(const extras::PackedPixelFile& ppf, const std::string& pathname,
std::vector<uint8_t>* bytes, ThreadPool* pool) {
std::string extension;
const extras::Codec codec =
extras::CodecFromExtension(extension, &bits_per_sample);
// Warn about incorrect usage of PGM/PGX/PPM - only the latter supports
// color, but CodecFromExtension lumps them all together.
if (codec == extras::Codec::kPNM && extension != ".pfm") {
if (io.Main().HasAlpha() && extension != ".pam") {
JXL_WARNING(
"For images with alpha, the filename should end with .pam.\n");
} else if (!io.Main().IsGray() && extension == ".pgm") {
JXL_WARNING("For color images, the filename should end with .ppm.\n");
} else if (io.Main().IsGray() && extension == ".ppm") {
JXL_WARNING(
"For grayscale images, the filename should not end with .ppm.\n");
}
if (bits_per_sample > 16) {
JXL_WARNING("PPM only supports up to 16 bits per sample");
bits_per_sample = 16;
}
} else if (codec == extras::Codec::kPGX && !io.Main().IsGray()) {
JXL_WARNING("Storing color image to PGX - use .ppm extension instead.\n");
}
if (bits_per_sample > 16 && codec == extras::Codec::kPNG) {
JXL_WARNING("PNG only supports up to 16 bits per sample");
bits_per_sample = 16;
}
std::vector<uint8_t> encoded;
return Encode(io, codec, c_desired, bits_per_sample, &encoded, pool) &&
WriteFile(encoded, pathname);
}
Status EncodeToFile(const CodecInOut& io, const std::string& pathname,
ThreadPool* pool) {
// TODO(lode): need to take the floating_point_sample field into account
return EncodeToFile(io, io.metadata.m.color_encoding,
io.metadata.m.bit_depth.bits_per_sample, pathname, pool);
extras::CodecFromPath(pathname, nullptr, &extension);
return Encode(ppf, codec, bytes, pool);
}
} // namespace jxl

View file

@ -17,7 +17,6 @@
#include "lib/extras/dec/decode.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/padded_bytes.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/codec_in_out.h"
@ -26,39 +25,30 @@
namespace jxl {
struct SizeConstraints;
// Decodes "bytes" and sets io->metadata.m.
// color_space_hint may specify the color space, otherwise, defaults to sRGB.
Status SetFromBytes(Span<const uint8_t> bytes,
const extras::ColorHints& color_hints, CodecInOut* io,
ThreadPool* pool = nullptr,
const SizeConstraints* constraints = nullptr,
extras::Codec* orig_codec = nullptr);
// Helper function to use no color_space_hint.
JXL_INLINE Status SetFromBytes(const Span<const uint8_t> bytes, CodecInOut* io,
ThreadPool* pool = nullptr,
const SizeConstraints* constraints = nullptr,
extras::Codec* orig_codec = nullptr) {
return SetFromBytes(bytes, extras::ColorHints(), io, pool, orig_codec);
return SetFromBytes(bytes, extras::ColorHints(), io, pool, constraints,
orig_codec);
}
// Reads from file and calls SetFromBytes.
Status SetFromFile(const std::string& pathname,
const extras::ColorHints& color_hints, CodecInOut* io,
ThreadPool* pool = nullptr,
extras::Codec* orig_codec = nullptr);
Status Encode(const extras::PackedPixelFile& ppf, extras::Codec codec,
std::vector<uint8_t>* bytes, ThreadPool* pool);
// Replaces "bytes" with an encoding of pixels transformed from c_current
// color space to c_desired.
Status Encode(const CodecInOut& io, extras::Codec codec,
const ColorEncoding& c_desired, size_t bits_per_sample,
Status Encode(const extras::PackedPixelFile& ppf, const std::string& pathname,
std::vector<uint8_t>* bytes, ThreadPool* pool = nullptr);
// Deduces codec, calls Encode and writes to file.
Status EncodeToFile(const CodecInOut& io, const ColorEncoding& c_desired,
size_t bits_per_sample, const std::string& pathname,
ThreadPool* pool = nullptr);
// Same, but defaults to metadata.original color_encoding and bits_per_sample.
Status EncodeToFile(const CodecInOut& io, const std::string& pathname,
ThreadPool* pool = nullptr);
} // namespace jxl
#endif // LIB_EXTRAS_CODEC_H_

View file

@ -3,42 +3,52 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "lib/extras/codec.h"
#include <stddef.h>
#include <stdio.h>
#include <jxl/codestream_header.h>
#include <jxl/color_encoding.h>
#include <jxl/encode.h>
#include <jxl/types.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "lib/extras/dec/pgx.h"
#include "lib/extras/dec/pnm.h"
#include "lib/extras/common.h"
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/dec/decode.h"
#include "lib/extras/enc/encode.h"
#include "lib/extras/packed_image_convert.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/random.h"
#include "lib/jxl/base/thread_pool_internal.h"
#include "lib/jxl/color_management.h"
#include "lib/jxl/enc_color_management.h"
#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/image_test_utils.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testdata.h"
#include "lib/jxl/testing.h"
namespace jxl {
using ::jxl::test::ThreadPoolForTests;
namespace extras {
Status PnmParseSigned(Bytes str, double* v);
Status PnmParseUnsigned(Bytes str, size_t* v);
namespace {
using ::testing::AllOf;
using ::testing::Contains;
using ::testing::Field;
using ::testing::IsEmpty;
using ::testing::NotNull;
using ::testing::SizeIs;
Span<const uint8_t> MakeSpan(const char* str) {
return Bytes(reinterpret_cast<const uint8_t*>(str), strlen(str));
}
std::string ExtensionFromCodec(Codec codec, const bool is_gray,
const bool has_alpha,
@ -51,18 +61,14 @@ std::string ExtensionFromCodec(Codec codec, const bool is_gray,
case Codec::kPNG:
return ".png";
case Codec::kPNM:
if (bits_per_sample == 32) return ".pfm";
if (has_alpha) return ".pam";
if (is_gray) return ".pgm";
return (bits_per_sample == 32) ? ".pfm" : ".ppm";
case Codec::kGIF:
return ".gif";
return is_gray ? ".pgm" : ".ppm";
case Codec::kEXR:
return ".exr";
case Codec::kUnknown:
default:
return std::string();
}
JXL_UNREACHABLE;
return std::string();
}
void VerifySameImage(const PackedImage& im0, size_t bits_per_sample0,
@ -76,8 +82,8 @@ void VerifySameImage(const PackedImage& im0, size_t bits_per_sample0,
};
double factor0 = get_factor(im0.format, bits_per_sample0);
double factor1 = get_factor(im1.format, bits_per_sample1);
auto pixels0 = static_cast<const uint8_t*>(im0.pixels());
auto pixels1 = static_cast<const uint8_t*>(im1.pixels());
const auto* pixels0 = static_cast<const uint8_t*>(im0.pixels());
const auto* pixels1 = static_cast<const uint8_t*>(im1.pixels());
auto rgba0 =
test::ConvertToRGBA32(pixels0, im0.xsize, im0.ysize, im0.format, factor0);
auto rgba1 =
@ -110,17 +116,16 @@ JxlColorEncoding CreateTestColorEncoding(bool is_gray) {
// Roundtrip through internal color encoding to fill in primaries and white
// point CIE xy coordinates.
ColorEncoding c_internal;
JXL_CHECK(ConvertExternalToInternalColorEncoding(c, &c_internal));
ConvertInternalToExternalColorEncoding(c_internal, &c);
EXPECT_TRUE(c_internal.FromExternal(c));
c = c_internal.ToExternal();
return c;
}
std::vector<uint8_t> GenerateICC(JxlColorEncoding color_encoding) {
ColorEncoding c;
JXL_CHECK(ConvertExternalToInternalColorEncoding(color_encoding, &c));
JXL_CHECK(c.CreateICC());
PaddedBytes icc = c.ICC();
return std::vector<uint8_t>(icc.begin(), icc.end());
EXPECT_TRUE(c.FromExternal(color_encoding));
EXPECT_TRUE(!c.ICC().empty());
return c.ICC();
}
void StoreRandomValue(uint8_t* out, Rng* rng, JxlPixelFormat format,
@ -173,10 +178,11 @@ struct TestImageParams {
bool is_gray;
bool add_alpha;
bool big_endian;
bool add_extra_channels;
bool ShouldTestRoundtrip() const {
if (codec == Codec::kPNG) {
return true;
return bits_per_sample <= 16;
} else if (codec == Codec::kPNM) {
// TODO(szabadka) Make PNM encoder endianness-aware.
return ((bits_per_sample <= 16 && big_endian) ||
@ -213,7 +219,7 @@ struct TestImageParams {
std::string DebugString() const {
std::ostringstream os;
os << "bps:" << bits_per_sample << " gr:" << is_gray << " al:" << add_alpha
<< " be: " << big_endian;
<< " be: " << big_endian << " ec: " << add_extra_channels;
return os.str();
}
};
@ -225,14 +231,31 @@ void CreateTestImage(const TestImageParams& params, PackedPixelFile* ppf) {
ppf->info.exponent_bits_per_sample = params.bits_per_sample == 32 ? 8 : 0;
ppf->info.num_color_channels = params.is_gray ? 1 : 3;
ppf->info.alpha_bits = params.add_alpha ? params.bits_per_sample : 0;
ppf->info.alpha_premultiplied = (params.codec == Codec::kEXR);
ppf->info.alpha_premultiplied = TO_JXL_BOOL(params.codec == Codec::kEXR);
JxlColorEncoding color_encoding = CreateTestColorEncoding(params.is_gray);
ppf->icc = GenerateICC(color_encoding);
ppf->color_encoding = color_encoding;
PackedFrame frame(params.xsize, params.ysize, params.PixelFormat());
JXL_TEST_ASSIGN_OR_DIE(
PackedFrame frame,
PackedFrame::Create(params.xsize, params.ysize, params.PixelFormat()));
FillPackedImage(params.bits_per_sample, &frame.color);
if (params.add_extra_channels) {
for (size_t i = 0; i < 7; ++i) {
JxlPixelFormat ec_format = params.PixelFormat();
ec_format.num_channels = 1;
JXL_TEST_ASSIGN_OR_DIE(
PackedImage ec,
PackedImage::Create(params.xsize, params.ysize, ec_format));
FillPackedImage(params.bits_per_sample, &ec);
frame.extra_channels.emplace_back(std::move(ec));
PackedExtraChannel pec;
pec.ec_info.bits_per_sample = params.bits_per_sample;
pec.ec_info.type = static_cast<JxlExtraChannelType>(i);
ppf->extra_channels_info.emplace_back(std::move(pec));
}
}
ppf->frames.emplace_back(std::move(frame));
}
@ -249,33 +272,67 @@ void TestRoundTrip(const TestImageParams& params, ThreadPool* pool) {
EncodedImage encoded;
auto encoder = Encoder::FromExtension(extension);
ASSERT_TRUE(encoder.get());
if (!encoder) {
fprintf(stderr, "Skipping test because of missing codec support.\n");
return;
}
ASSERT_TRUE(encoder->Encode(ppf_in, &encoded, pool));
ASSERT_EQ(encoded.bitstreams.size(), 1);
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeBytes(Span<const uint8_t>(encoded.bitstreams[0]),
ColorHints(), SizeConstraints(), &ppf_out));
if (params.codec != Codec::kPNM && params.codec != Codec::kPGX &&
params.codec != Codec::kEXR) {
ColorHints color_hints;
if (params.codec == Codec::kPNM || params.codec == Codec::kPGX) {
color_hints.Add("color_space",
params.is_gray ? "Gra_D65_Rel_SRG" : "RGB_D65_SRG_Rel_SRG");
}
ASSERT_TRUE(DecodeBytes(Bytes(encoded.bitstreams[0]), color_hints, &ppf_out));
if (params.codec == Codec::kPNG && ppf_out.icc.empty()) {
// Decoding a PNG may drop the ICC profile if there's a valid cICP chunk.
// Rendering intent is not preserved in this case.
EXPECT_EQ(ppf_in.color_encoding.color_space,
ppf_out.color_encoding.color_space);
EXPECT_EQ(ppf_in.color_encoding.white_point,
ppf_out.color_encoding.white_point);
if (ppf_in.color_encoding.color_space != JXL_COLOR_SPACE_GRAY) {
EXPECT_EQ(ppf_in.color_encoding.primaries,
ppf_out.color_encoding.primaries);
}
EXPECT_EQ(ppf_in.color_encoding.transfer_function,
ppf_out.color_encoding.transfer_function);
EXPECT_EQ(ppf_out.color_encoding.rendering_intent,
JXL_RENDERING_INTENT_RELATIVE);
} else if (params.codec != Codec::kPNM && params.codec != Codec::kPGX &&
params.codec != Codec::kEXR) {
EXPECT_EQ(ppf_in.icc, ppf_out.icc);
}
ASSERT_EQ(ppf_out.frames.size(), 1);
VerifySameImage(ppf_in.frames[0].color, ppf_in.info.bits_per_sample,
ppf_out.frames[0].color, ppf_out.info.bits_per_sample,
const auto& frame_in = ppf_in.frames[0];
const auto& frame_out = ppf_out.frames[0];
VerifySameImage(frame_in.color, ppf_in.info.bits_per_sample, frame_out.color,
ppf_out.info.bits_per_sample,
/*lossless=*/params.codec != Codec::kJPG);
ASSERT_EQ(frame_in.extra_channels.size(), frame_out.extra_channels.size());
ASSERT_EQ(ppf_out.extra_channels_info.size(),
frame_out.extra_channels.size());
for (size_t i = 0; i < frame_in.extra_channels.size(); ++i) {
VerifySameImage(frame_in.extra_channels[i], ppf_in.info.bits_per_sample,
frame_out.extra_channels[i], ppf_out.info.bits_per_sample,
/*lossless=*/true);
EXPECT_EQ(ppf_out.extra_channels_info[i].ec_info.type,
ppf_in.extra_channels_info[i].ec_info.type);
}
}
TEST(CodecTest, TestRoundTrip) {
ThreadPoolInternal pool(12);
ThreadPoolForTests pool(12);
TestImageParams params;
params.xsize = 7;
params.ysize = 4;
for (Codec codec : AvailableCodecs()) {
for (Codec codec :
{Codec::kPNG, Codec::kPNM, Codec::kPGX, Codec::kEXR, Codec::kJPG}) {
for (int bits_per_sample : {4, 8, 10, 12, 16, 32}) {
for (bool is_gray : {false, true}) {
for (bool add_alpha : {false, true}) {
@ -285,7 +342,12 @@ TEST(CodecTest, TestRoundTrip) {
params.is_gray = is_gray;
params.add_alpha = add_alpha;
params.big_endian = big_endian;
TestRoundTrip(params, &pool);
params.add_extra_channels = false;
TestRoundTrip(params, pool.get());
if (codec == Codec::kPNM && add_alpha) {
params.add_extra_channels = true;
TestRoundTrip(params, pool.get());
}
}
}
}
@ -293,194 +355,74 @@ TEST(CodecTest, TestRoundTrip) {
}
}
CodecInOut DecodeRoundtrip(const std::string& pathname, ThreadPool* pool,
const ColorHints& color_hints = ColorHints()) {
CodecInOut io;
const PaddedBytes orig = ReadTestData(pathname);
JXL_CHECK(
SetFromBytes(Span<const uint8_t>(orig), color_hints, &io, pool, nullptr));
const ImageBundle& ib1 = io.Main();
TEST(CodecTest, LosslessPNMRoundtrip) {
ThreadPoolForTests pool(12);
// Encode/Decode again to make sure Encode carries through all metadata.
std::vector<uint8_t> encoded;
JXL_CHECK(Encode(io, Codec::kPNG, io.metadata.m.color_encoding,
io.metadata.m.bit_depth.bits_per_sample, &encoded, pool));
static const char* kChannels[] = {"", "g", "ga", "rgb", "rgba"};
static const char* kExtension[] = {"", ".pgm", ".pam", ".ppm", ".pam"};
for (size_t bit_depth = 1; bit_depth <= 16; ++bit_depth) {
for (size_t channels = 1; channels <= 4; ++channels) {
if (bit_depth == 1 && (channels == 2 || channels == 4)) continue;
std::string extension(kExtension[channels]);
std::string filename = "jxl/flower/flower_small." +
std::string(kChannels[channels]) + ".depth" +
std::to_string(bit_depth) + extension;
const std::vector<uint8_t> orig = jxl::test::ReadTestData(filename);
CodecInOut io2;
JXL_CHECK(SetFromBytes(Span<const uint8_t>(encoded), color_hints, &io2, pool,
nullptr));
const ImageBundle& ib2 = io2.Main();
EXPECT_EQ(Description(ib1.metadata()->color_encoding),
Description(ib2.metadata()->color_encoding));
EXPECT_EQ(Description(ib1.c_current()), Description(ib2.c_current()));
PackedPixelFile ppf;
ColorHints color_hints;
color_hints.Add("color_space",
channels < 3 ? "Gra_D65_Rel_SRG" : "RGB_D65_SRG_Rel_SRG");
ASSERT_TRUE(
DecodeBytes(Bytes(orig.data(), orig.size()), color_hints, &ppf));
size_t bits_per_sample = io2.metadata.m.bit_depth.bits_per_sample;
// "Same" pixels?
double max_l1 = bits_per_sample <= 12 ? 1.3 : 2E-3;
double max_rel = bits_per_sample <= 12 ? 6E-3 : 1E-4;
if (ib1.metadata()->color_encoding.IsGray()) {
max_rel *= 2.0;
} else if (ib1.metadata()->color_encoding.primaries != Primaries::kSRGB) {
// Need more tolerance for large gamuts (anything but sRGB)
max_l1 *= 1.5;
max_rel *= 3.0;
}
VerifyRelativeError(ib1.color(), ib2.color(), max_l1, max_rel);
// Simulate the encoder removing profile and decoder restoring it.
if (!ib2.metadata()->color_encoding.WantICC()) {
io2.metadata.m.color_encoding.InternalRemoveICC();
EXPECT_TRUE(io2.metadata.m.color_encoding.CreateICC());
}
return io2;
}
#if 0
TEST(CodecTest, TestMetadataSRGB) {
ThreadPoolInternal pool(12);
const char* paths[] = {"external/raw.pixls/DJI-FC6310-16bit_srgb8_v4_krita.png",
"external/raw.pixls/Google-Pixel2XL-16bit_srgb8_v4_krita.png",
"external/raw.pixls/HUAWEI-EVA-L09-16bit_srgb8_dt.png",
"external/raw.pixls/Nikon-D300-12bit_srgb8_dt.png",
"external/raw.pixls/Sony-DSC-RX1RM2-14bit_srgb8_v4_krita.png"};
for (const char* relative_pathname : paths) {
const CodecInOut io =
DecodeRoundtrip(relative_pathname, Codec::kPNG, &pool);
EXPECT_EQ(8, io.metadata.m.bit_depth.bits_per_sample);
EXPECT_FALSE(io.metadata.m.bit_depth.floating_point_sample);
EXPECT_EQ(0, io.metadata.m.bit_depth.exponent_bits_per_sample);
EXPECT_EQ(64, io.xsize());
EXPECT_EQ(64, io.ysize());
EXPECT_FALSE(io.metadata.m.HasAlpha());
const ColorEncoding& c_original = io.metadata.m.color_encoding;
EXPECT_FALSE(c_original.ICC().empty());
EXPECT_EQ(ColorSpace::kRGB, c_original.GetColorSpace());
EXPECT_EQ(WhitePoint::kD65, c_original.white_point);
EXPECT_EQ(Primaries::kSRGB, c_original.primaries);
EXPECT_TRUE(c_original.tf.IsSRGB());
EncodedImage encoded;
auto encoder = Encoder::FromExtension(extension);
ASSERT_TRUE(encoder.get());
ASSERT_TRUE(encoder->Encode(ppf, &encoded, pool.get()));
ASSERT_EQ(encoded.bitstreams.size(), 1);
ASSERT_EQ(orig.size(), encoded.bitstreams[0].size());
EXPECT_EQ(0,
memcmp(orig.data(), encoded.bitstreams[0].data(), orig.size()));
}
}
}
TEST(CodecTest, TestMetadataLinear) {
ThreadPoolInternal pool(12);
TEST(CodecTest, TestPNM) {
size_t u = 77777; // Initialized to wrong value.
double d = 77.77;
// Failing to parse invalid strings results in a crash if `JXL_CRASH_ON_ERROR`
// is defined and hence the tests fail. Therefore we only run these tests if
// `JXL_CRASH_ON_ERROR` is not defined.
#if (!JXL_CRASH_ON_ERROR)
ASSERT_FALSE(PnmParseUnsigned(MakeSpan(""), &u));
ASSERT_FALSE(PnmParseUnsigned(MakeSpan("+"), &u));
ASSERT_FALSE(PnmParseUnsigned(MakeSpan("-"), &u));
ASSERT_FALSE(PnmParseUnsigned(MakeSpan("A"), &u));
const char* paths[3] = {
"external/raw.pixls/Google-Pixel2XL-16bit_acescg_g1_v4_krita.png",
"external/raw.pixls/HUAWEI-EVA-L09-16bit_709_g1_dt.png",
"external/raw.pixls/Nikon-D300-12bit_2020_g1_dt.png",
};
const WhitePoint white_points[3] = {WhitePoint::kCustom, WhitePoint::kD65,
WhitePoint::kD65};
const Primaries primaries[3] = {Primaries::kCustom, Primaries::kSRGB,
Primaries::k2100};
for (size_t i = 0; i < 3; ++i) {
const CodecInOut io = DecodeRoundtrip(paths[i], Codec::kPNG, &pool);
EXPECT_EQ(16, io.metadata.m.bit_depth.bits_per_sample);
EXPECT_FALSE(io.metadata.m.bit_depth.floating_point_sample);
EXPECT_EQ(0, io.metadata.m.bit_depth.exponent_bits_per_sample);
EXPECT_EQ(64, io.xsize());
EXPECT_EQ(64, io.ysize());
EXPECT_FALSE(io.metadata.m.HasAlpha());
const ColorEncoding& c_original = io.metadata.m.color_encoding;
EXPECT_FALSE(c_original.ICC().empty());
EXPECT_EQ(ColorSpace::kRGB, c_original.GetColorSpace());
EXPECT_EQ(white_points[i], c_original.white_point);
EXPECT_EQ(primaries[i], c_original.primaries);
EXPECT_TRUE(c_original.tf.IsLinear());
}
}
TEST(CodecTest, TestMetadataICC) {
ThreadPoolInternal pool(12);
const char* paths[] = {
"external/raw.pixls/DJI-FC6310-16bit_709_v4_krita.png",
"external/raw.pixls/Sony-DSC-RX1RM2-14bit_709_v4_krita.png",
};
for (const char* relative_pathname : paths) {
const CodecInOut io =
DecodeRoundtrip(relative_pathname, Codec::kPNG, &pool);
EXPECT_GE(16, io.metadata.m.bit_depth.bits_per_sample);
EXPECT_LE(14, io.metadata.m.bit_depth.bits_per_sample);
EXPECT_EQ(64, io.xsize());
EXPECT_EQ(64, io.ysize());
EXPECT_FALSE(io.metadata.m.HasAlpha());
const ColorEncoding& c_original = io.metadata.m.color_encoding;
EXPECT_FALSE(c_original.ICC().empty());
EXPECT_EQ(RenderingIntent::kPerceptual, c_original.rendering_intent);
EXPECT_EQ(ColorSpace::kRGB, c_original.GetColorSpace());
EXPECT_EQ(WhitePoint::kD65, c_original.white_point);
EXPECT_EQ(Primaries::kSRGB, c_original.primaries);
EXPECT_EQ(TransferFunction::k709, c_original.tf.GetTransferFunction());
}
}
TEST(CodecTest, Testexternal/pngsuite) {
ThreadPoolInternal pool(12);
// Ensure we can load PNG with text, japanese UTF-8, compressed text.
(void)DecodeRoundtrip("external/pngsuite/ct1n0g04.png", Codec::kPNG, &pool);
(void)DecodeRoundtrip("external/pngsuite/ctjn0g04.png", Codec::kPNG, &pool);
(void)DecodeRoundtrip("external/pngsuite/ctzn0g04.png", Codec::kPNG, &pool);
// Extract gAMA
const CodecInOut b1 =
DecodeRoundtrip("external/pngsuite/g10n3p04.png", Codec::kPNG, &pool);
EXPECT_TRUE(b1.metadata.color_encoding.tf.IsLinear());
// Extract cHRM
const CodecInOut b_p =
DecodeRoundtrip("external/pngsuite/ccwn2c08.png", Codec::kPNG, &pool);
EXPECT_EQ(Primaries::kSRGB, b_p.metadata.color_encoding.primaries);
EXPECT_EQ(WhitePoint::kD65, b_p.metadata.color_encoding.white_point);
// Extract EXIF from (new-style) dedicated chunk
const CodecInOut b_exif =
DecodeRoundtrip("external/pngsuite/exif2c08.png", Codec::kPNG, &pool);
EXPECT_EQ(978, b_exif.blobs.exif.size());
}
ASSERT_FALSE(PnmParseSigned(MakeSpan(""), &d));
ASSERT_FALSE(PnmParseSigned(MakeSpan("+"), &d));
ASSERT_FALSE(PnmParseSigned(MakeSpan("-"), &d));
ASSERT_FALSE(PnmParseSigned(MakeSpan("A"), &d));
#endif
ASSERT_TRUE(PnmParseUnsigned(MakeSpan("1"), &u));
ASSERT_TRUE(u == 1);
void VerifyWideGamutMetadata(const std::string& relative_pathname,
const Primaries primaries, ThreadPool* pool) {
const CodecInOut io = DecodeRoundtrip(relative_pathname, pool);
ASSERT_TRUE(PnmParseUnsigned(MakeSpan("32"), &u));
ASSERT_TRUE(u == 32);
EXPECT_EQ(8u, io.metadata.m.bit_depth.bits_per_sample);
EXPECT_FALSE(io.metadata.m.bit_depth.floating_point_sample);
EXPECT_EQ(0u, io.metadata.m.bit_depth.exponent_bits_per_sample);
const ColorEncoding& c_original = io.metadata.m.color_encoding;
EXPECT_FALSE(c_original.ICC().empty());
EXPECT_EQ(RenderingIntent::kAbsolute, c_original.rendering_intent);
EXPECT_EQ(ColorSpace::kRGB, c_original.GetColorSpace());
EXPECT_EQ(WhitePoint::kD65, c_original.white_point);
EXPECT_EQ(primaries, c_original.primaries);
ASSERT_TRUE(PnmParseSigned(MakeSpan("1"), &d));
ASSERT_TRUE(d == 1.0);
ASSERT_TRUE(PnmParseSigned(MakeSpan("+2"), &d));
ASSERT_TRUE(d == 2.0);
ASSERT_TRUE(PnmParseSigned(MakeSpan("-3"), &d));
ASSERT_TRUE(std::abs(d - -3.0) < 1E-15);
ASSERT_TRUE(PnmParseSigned(MakeSpan("3.141592"), &d));
ASSERT_TRUE(std::abs(d - 3.141592) < 1E-15);
ASSERT_TRUE(PnmParseSigned(MakeSpan("-3.141592"), &d));
ASSERT_TRUE(std::abs(d - -3.141592) < 1E-15);
}
TEST(CodecTest, TestWideGamut) {
ThreadPoolInternal pool(12);
// VerifyWideGamutMetadata("external/wide-gamut-tests/P3-sRGB-color-bars.png",
// Primaries::kP3, &pool);
VerifyWideGamutMetadata("external/wide-gamut-tests/P3-sRGB-color-ring.png",
Primaries::kP3, &pool);
// VerifyWideGamutMetadata("external/wide-gamut-tests/R2020-sRGB-color-bars.png",
// Primaries::k2100, &pool);
// VerifyWideGamutMetadata("external/wide-gamut-tests/R2020-sRGB-color-ring.png",
// Primaries::k2100, &pool);
}
TEST(CodecTest, TestPNM) { TestCodecPNM(); }
TEST(CodecTest, FormatNegotiation) {
const std::vector<JxlPixelFormat> accepted_formats = {
{/*num_channels=*/4,
@ -520,29 +462,32 @@ TEST(CodecTest, EncodeToPNG) {
ThreadPool* const pool = nullptr;
std::unique_ptr<Encoder> png_encoder = Encoder::FromExtension(".png");
ASSERT_THAT(png_encoder, NotNull());
if (!png_encoder) {
fprintf(stderr, "Skipping test because of missing codec support.\n");
return;
}
const PaddedBytes original_png =
ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_srgb8.png");
const std::vector<uint8_t> original_png = jxl::test::ReadTestData(
"external/wesaturate/500px/tmshre_riaphotographs_srgb8.png");
PackedPixelFile ppf;
ASSERT_TRUE(extras::DecodeBytes(Span<const uint8_t>(original_png),
ColorHints(), SizeConstraints(), &ppf));
ASSERT_TRUE(extras::DecodeBytes(Bytes(original_png), ColorHints(), &ppf));
const JxlPixelFormat& format = ppf.frames.front().color.format;
ASSERT_THAT(
png_encoder->AcceptedFormats(),
Contains(AllOf(Field(&JxlPixelFormat::num_channels, format.num_channels),
Field(&JxlPixelFormat::data_type, format.data_type),
Field(&JxlPixelFormat::endianness, format.endianness))));
const auto& format_matcher = [&format](const JxlPixelFormat& candidate) {
return (candidate.num_channels == format.num_channels) &&
(candidate.data_type == format.data_type) &&
(candidate.endianness == format.endianness);
};
const auto formats = png_encoder->AcceptedFormats();
ASSERT_TRUE(std::any_of(formats.begin(), formats.end(), format_matcher));
EncodedImage encoded_png;
ASSERT_TRUE(png_encoder->Encode(ppf, &encoded_png, pool));
EXPECT_THAT(encoded_png.icc, IsEmpty());
ASSERT_THAT(encoded_png.bitstreams, SizeIs(1));
EXPECT_TRUE(encoded_png.icc.empty());
ASSERT_EQ(encoded_png.bitstreams.size(), 1);
PackedPixelFile decoded_ppf;
ASSERT_TRUE(
extras::DecodeBytes(Span<const uint8_t>(encoded_png.bitstreams.front()),
ColorHints(), SizeConstraints(), &decoded_ppf));
ASSERT_TRUE(extras::DecodeBytes(Bytes(encoded_png.bitstreams.front()),
ColorHints(), &decoded_ppf));
ASSERT_EQ(decoded_ppf.info.bits_per_sample, ppf.info.bits_per_sample);
ASSERT_EQ(decoded_ppf.frames.size(), 1);

View file

@ -0,0 +1,62 @@
// 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.
#include "lib/extras/common.h"
#include <jxl/codestream_header.h>
#include <jxl/types.h>
#include <cstddef>
#include <vector>
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
Status SelectFormat(const std::vector<JxlPixelFormat>& accepted_formats,
const JxlBasicInfo& basic_info, JxlPixelFormat* format) {
const size_t original_bit_depth = basic_info.bits_per_sample;
size_t current_bit_depth = 0;
size_t num_alpha_channels = (basic_info.alpha_bits != 0 ? 1 : 0);
size_t num_channels = basic_info.num_color_channels + num_alpha_channels;
for (;;) {
for (const JxlPixelFormat& candidate : accepted_formats) {
if (candidate.num_channels != num_channels) continue;
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(candidate.data_type));
const size_t candidate_bit_depth =
PackedImage::BitsPerChannel(candidate.data_type);
if (
// Candidate bit depth is less than what we have and still enough
(original_bit_depth <= candidate_bit_depth &&
candidate_bit_depth < current_bit_depth) ||
// Or larger than the too-small bit depth we currently have
(current_bit_depth < candidate_bit_depth &&
current_bit_depth < original_bit_depth)) {
*format = candidate;
current_bit_depth = candidate_bit_depth;
}
}
if (current_bit_depth == 0) {
if (num_channels > basic_info.num_color_channels) {
// Try dropping the alpha channel.
--num_channels;
continue;
}
return JXL_FAILURE("no appropriate format found");
}
break;
}
if (current_bit_depth < original_bit_depth) {
JXL_WARNING("encoding %" PRIuS "-bit original to %" PRIuS " bits",
original_bit_depth, current_bit_depth);
}
return true;
}
} // namespace extras
} // namespace jxl

View file

@ -0,0 +1,26 @@
// 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.
#ifndef LIB_EXTRAS_COMMON_H_
#define LIB_EXTRAS_COMMON_H_
#include <jxl/codestream_header.h>
#include <jxl/types.h>
#include <vector>
#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
// TODO(sboukortt): consider exposing this as part of the C API.
Status SelectFormat(const std::vector<JxlPixelFormat>& accepted_formats,
const JxlBasicInfo& basic_info, JxlPixelFormat* format);
} // namespace extras
} // namespace jxl
#endif // LIB_EXTRAS_COMMON_H_

View file

@ -0,0 +1,53 @@
// 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.
#include <jxl/compressed_icc.h>
#include "lib/jxl/base/span.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_icc_codec.h"
#include "lib/jxl/icc_codec.h"
JXL_BOOL JxlICCProfileEncode(const JxlMemoryManager* memory_manager,
const uint8_t* icc, size_t icc_size,
uint8_t** compressed_icc,
size_t* compressed_icc_size) {
JxlMemoryManager local_memory_manager;
if (!jxl::MemoryManagerInit(&local_memory_manager, memory_manager)) {
return JXL_FALSE;
}
jxl::BitWriter writer(&local_memory_manager);
JXL_RETURN_IF_ERROR(jxl::WriteICC(jxl::Span<const uint8_t>(icc, icc_size),
&writer, jxl::LayerType::Header, nullptr));
writer.ZeroPadToByte();
jxl::Bytes bytes = writer.GetSpan();
*compressed_icc_size = bytes.size();
*compressed_icc = static_cast<uint8_t*>(
jxl::MemoryManagerAlloc(&local_memory_manager, *compressed_icc_size));
memcpy(*compressed_icc, bytes.data(), bytes.size());
return JXL_TRUE;
}
JXL_BOOL JxlICCProfileDecode(const JxlMemoryManager* memory_manager,
const uint8_t* compressed_icc,
size_t compressed_icc_size, uint8_t** icc,
size_t* icc_size) {
JxlMemoryManager local_memory_manager;
if (!jxl::MemoryManagerInit(&local_memory_manager, memory_manager)) {
return JXL_FALSE;
}
jxl::ICCReader icc_reader(&local_memory_manager);
jxl::PaddedBytes decompressed(&local_memory_manager);
jxl::BitReader bit_reader(
jxl::Span<const uint8_t>(compressed_icc, compressed_icc_size));
JXL_RETURN_IF_ERROR(icc_reader.Init(&bit_reader));
JXL_RETURN_IF_ERROR(icc_reader.Process(&bit_reader, &decompressed));
JXL_RETURN_IF_ERROR(bit_reader.Close());
*icc_size = decompressed.size();
*icc = static_cast<uint8_t*>(
jxl::MemoryManagerAlloc(&local_memory_manager, *icc_size));
memcpy(*icc, decompressed.data(), *icc_size);
return JXL_TRUE;
}

View file

@ -0,0 +1,47 @@
// 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.
#include "jxl/compressed_icc.h"
#include <jxl/memory_manager.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/test_memory_manager.h"
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testing.h"
namespace jxl {
namespace {
TEST(CompressedIccTest, Roundtrip) {
JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
uint8_t* compressed_icc;
size_t compressed_icc_size;
const IccBytes icc = jxl::test::GetIccTestProfile();
ASSERT_TRUE(JxlICCProfileEncode(memory_manager, icc.data(), icc.size(),
&compressed_icc, &compressed_icc_size));
EXPECT_LT(compressed_icc_size, icc.size());
uint8_t* decompressed_icc;
size_t decompressed_icc_size;
ASSERT_TRUE(JxlICCProfileDecode(memory_manager, compressed_icc,
compressed_icc_size, &decompressed_icc,
&decompressed_icc_size));
ASSERT_EQ(decompressed_icc_size, icc.size());
EXPECT_EQ(0, memcmp(decompressed_icc, icc.data(), decompressed_icc_size));
memory_manager->free(memory_manager->opaque, compressed_icc);
memory_manager->free(memory_manager->opaque, decompressed_icc);
}
} // namespace
} // namespace jxl

File diff suppressed because it is too large Load diff

View file

@ -8,23 +8,25 @@
// Decodes APNG images in memory.
#include <stdint.h>
#include <cstdint>
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/padded_bytes.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/codec_in_out.h"
namespace jxl {
struct SizeConstraints;
namespace extras {
bool CanDecodeAPNG();
// Decodes `bytes` into `ppf`.
Status DecodeImageAPNG(Span<const uint8_t> bytes, const ColorHints& color_hints,
const SizeConstraints& constraints,
PackedPixelFile* ppf);
PackedPixelFile* ppf,
const SizeConstraints* constraints = nullptr);
} // namespace extras
} // namespace jxl

View file

@ -9,6 +9,8 @@
#include <cmath>
#include "lib/jxl/base/common.h"
namespace jxl {
namespace {
@ -19,49 +21,46 @@ struct EnumName {
T value;
};
const EnumName<JxlColorSpace> kJxlColorSpaceNames[] = {
{"RGB", JXL_COLOR_SPACE_RGB},
{"Gra", JXL_COLOR_SPACE_GRAY},
{"XYB", JXL_COLOR_SPACE_XYB},
{"CS?", JXL_COLOR_SPACE_UNKNOWN},
};
constexpr auto kJxlColorSpaceNames =
to_array<EnumName<JxlColorSpace>>({{"RGB", JXL_COLOR_SPACE_RGB},
{"Gra", JXL_COLOR_SPACE_GRAY},
{"XYB", JXL_COLOR_SPACE_XYB},
{"CS?", JXL_COLOR_SPACE_UNKNOWN}});
const EnumName<JxlWhitePoint> kJxlWhitePointNames[] = {
{"D65", JXL_WHITE_POINT_D65},
{"Cst", JXL_WHITE_POINT_CUSTOM},
{"EER", JXL_WHITE_POINT_E},
{"DCI", JXL_WHITE_POINT_DCI},
};
constexpr auto kJxlWhitePointNames =
to_array<EnumName<JxlWhitePoint>>({{"D65", JXL_WHITE_POINT_D65},
{"Cst", JXL_WHITE_POINT_CUSTOM},
{"EER", JXL_WHITE_POINT_E},
{"DCI", JXL_WHITE_POINT_DCI}});
const EnumName<JxlPrimaries> kJxlPrimariesNames[] = {
{"SRG", JXL_PRIMARIES_SRGB},
{"Cst", JXL_PRIMARIES_CUSTOM},
{"202", JXL_PRIMARIES_2100},
{"DCI", JXL_PRIMARIES_P3},
};
constexpr auto kJxlPrimariesNames =
to_array<EnumName<JxlPrimaries>>({{"SRG", JXL_PRIMARIES_SRGB},
{"Cst", JXL_PRIMARIES_CUSTOM},
{"202", JXL_PRIMARIES_2100},
{"DCI", JXL_PRIMARIES_P3}});
const EnumName<JxlTransferFunction> kJxlTransferFunctionNames[] = {
{"709", JXL_TRANSFER_FUNCTION_709},
{"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN},
{"Lin", JXL_TRANSFER_FUNCTION_LINEAR},
{"SRG", JXL_TRANSFER_FUNCTION_SRGB},
{"PeQ", JXL_TRANSFER_FUNCTION_PQ},
{"DCI", JXL_TRANSFER_FUNCTION_DCI},
{"HLG", JXL_TRANSFER_FUNCTION_HLG},
{"", JXL_TRANSFER_FUNCTION_GAMMA},
};
constexpr auto kJxlRenderingIntentNames =
to_array<EnumName<JxlRenderingIntent>>(
{{"Per", JXL_RENDERING_INTENT_PERCEPTUAL},
{"Rel", JXL_RENDERING_INTENT_RELATIVE},
{"Sat", JXL_RENDERING_INTENT_SATURATION},
{"Abs", JXL_RENDERING_INTENT_ABSOLUTE}});
const EnumName<JxlRenderingIntent> kJxlRenderingIntentNames[] = {
{"Per", JXL_RENDERING_INTENT_PERCEPTUAL},
{"Rel", JXL_RENDERING_INTENT_RELATIVE},
{"Sat", JXL_RENDERING_INTENT_SATURATION},
{"Abs", JXL_RENDERING_INTENT_ABSOLUTE},
};
constexpr auto kJxlTransferFunctionNames =
to_array<EnumName<JxlTransferFunction>>(
{{"709", JXL_TRANSFER_FUNCTION_709},
{"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN},
{"Lin", JXL_TRANSFER_FUNCTION_LINEAR},
{"SRG", JXL_TRANSFER_FUNCTION_SRGB},
{"PeQ", JXL_TRANSFER_FUNCTION_PQ},
{"DCI", JXL_TRANSFER_FUNCTION_DCI},
{"HLG", JXL_TRANSFER_FUNCTION_HLG},
{"", JXL_TRANSFER_FUNCTION_GAMMA}});
template <typename T>
Status ParseEnum(const std::string& token, const EnumName<T>* enum_values,
size_t enum_len, T* value) {
for (size_t i = 0; i < enum_len; i++) {
template <typename T, size_t N>
Status ParseEnum(const std::string& token,
const std::array<EnumName<T>, N>& enum_values, T* value) {
for (size_t i = 0; i < enum_values.size(); i++) {
if (enum_values[i].name == token) {
*value = enum_values[i].value;
return true;
@ -69,9 +68,6 @@ Status ParseEnum(const std::string& token, const EnumName<T>* enum_values,
}
return false;
}
#define ARRAYSIZE(X) (sizeof(X) / sizeof((X)[0]))
#define PARSE_ENUM(type, token, value) \
ParseEnum<type>(token, k##type##Names, ARRAYSIZE(k##type##Names), value)
class Tokenizer {
public:
@ -122,7 +118,7 @@ Status ParseColorSpace(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
JxlColorSpace cs;
if (PARSE_ENUM(JxlColorSpace, str, &cs)) {
if (ParseEnum(str, kJxlColorSpaceNames, &cs)) {
c->color_space = cs;
return true;
}
@ -139,7 +135,7 @@ Status ParseWhitePoint(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
if (PARSE_ENUM(JxlWhitePoint, str, &c->white_point)) return true;
if (ParseEnum(str, kJxlWhitePointNames, &c->white_point)) return true;
Tokenizer xy_tokenizer(&str, ';');
c->white_point = JXL_WHITE_POINT_CUSTOM;
@ -157,7 +153,7 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
if (PARSE_ENUM(JxlPrimaries, str, &c->primaries)) return true;
if (ParseEnum(str, kJxlPrimariesNames, &c->primaries)) return true;
Tokenizer xy_tokenizer(&str, ';');
JXL_RETURN_IF_ERROR(ParseDouble(&xy_tokenizer, c->primaries_red_xy + 0));
@ -168,13 +164,14 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) {
JXL_RETURN_IF_ERROR(ParseDouble(&xy_tokenizer, c->primaries_blue_xy + 1));
c->primaries = JXL_PRIMARIES_CUSTOM;
return JXL_FAILURE("Invalid primaries %s", str.c_str());
return true;
}
Status ParseRenderingIntent(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
if (PARSE_ENUM(JxlRenderingIntent, str, &c->rendering_intent)) return true;
if (ParseEnum(str, kJxlRenderingIntentNames, &c->rendering_intent))
return true;
return JXL_FAILURE("Invalid RenderingIntent %s\n", str.c_str());
}
@ -189,7 +186,7 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
if (PARSE_ENUM(JxlTransferFunction, str, &c->transfer_function)) {
if (ParseEnum(str, kJxlTransferFunctionNames, &c->transfer_function)) {
return true;
}
@ -206,12 +203,38 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) {
Status ParseDescription(const std::string& description, JxlColorEncoding* c) {
*c = {};
Tokenizer tokenizer(&description, '_');
JXL_RETURN_IF_ERROR(ParseColorSpace(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParseWhitePoint(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParsePrimaries(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParseRenderingIntent(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParseTransferFunction(&tokenizer, c));
if (description == "sRGB") {
c->color_space = JXL_COLOR_SPACE_RGB;
c->white_point = JXL_WHITE_POINT_D65;
c->primaries = JXL_PRIMARIES_SRGB;
c->transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
c->rendering_intent = JXL_RENDERING_INTENT_PERCEPTUAL;
} else if (description == "DisplayP3") {
c->color_space = JXL_COLOR_SPACE_RGB;
c->white_point = JXL_WHITE_POINT_D65;
c->primaries = JXL_PRIMARIES_P3;
c->transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
c->rendering_intent = JXL_RENDERING_INTENT_PERCEPTUAL;
} else if (description == "Rec2100PQ") {
c->color_space = JXL_COLOR_SPACE_RGB;
c->white_point = JXL_WHITE_POINT_D65;
c->primaries = JXL_PRIMARIES_2100;
c->transfer_function = JXL_TRANSFER_FUNCTION_PQ;
c->rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
} else if (description == "Rec2100HLG") {
c->color_space = JXL_COLOR_SPACE_RGB;
c->white_point = JXL_WHITE_POINT_D65;
c->primaries = JXL_PRIMARIES_2100;
c->transfer_function = JXL_TRANSFER_FUNCTION_HLG;
c->rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
} else {
Tokenizer tokenizer(&description, '_');
JXL_RETURN_IF_ERROR(ParseColorSpace(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParseWhitePoint(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParsePrimaries(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParseRenderingIntent(&tokenizer, c));
JXL_RETURN_IF_ERROR(ParseTransferFunction(&tokenizer, c));
}
return true;
}

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