Bug 1918647 - Update libjxl to v0.11.0 r=saschanaz

Differential Revision: https://phabricator.services.mozilla.com/D222104
This commit is contained in:
Updatebot 2024-09-17 10:19:32 +00:00
Родитель 6cc15139bc
Коммит 5bd52a5b9c
479 изменённых файлов: 16801 добавлений и 23124 удалений

Просмотреть файл

@ -15,7 +15,6 @@ SOURCES += [
"/third_party/jpeg-xl/lib/jxl/alpha.cc",
"/third_party/jpeg-xl/lib/jxl/ans_common.cc",
"/third_party/jpeg-xl/lib/jxl/blending.cc",
"/third_party/jpeg-xl/lib/jxl/cache_aligned.cc",
"/third_party/jpeg-xl/lib/jxl/chroma_from_luma.cc",
"/third_party/jpeg-xl/lib/jxl/coeff_order.cc",
"/third_party/jpeg-xl/lib/jxl/color_encoding_internal.cc",
@ -85,6 +84,7 @@ SOURCES += [
"/third_party/jpeg-xl/lib/jxl/render_pipeline/stage_ycbcr.cc",
"/third_party/jpeg-xl/lib/jxl/simd_util.cc",
"/third_party/jpeg-xl/lib/jxl/splines.cc",
"/third_party/jpeg-xl/lib/jxl/test_memory_manager.cc",
"/third_party/jpeg-xl/lib/jxl/toc.cc",
]

Просмотреть файл

@ -10,9 +10,9 @@ origin:
url: https://github.com/libjxl/libjxl
release: v0.10.3 (2024-06-27T14:10:08+02:00).
release: v0.11.0 (2024-09-13T07:31:05+02:00).
revision: v0.10.3
revision: v0.11.0
license: Apache-2.0

5
third_party/jpeg-xl/.clang-tidy поставляемый
Просмотреть файл

@ -25,17 +25,20 @@ Checks: >-
modernize-*,
performance-*,
readability-*,
-bugprone-narrowing-conversions,
-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,

5
third_party/jpeg-xl/AUTHORS поставляемый
Просмотреть файл

@ -39,9 +39,11 @@ 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]
@ -53,17 +55,20 @@ 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>
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>

5
third_party/jpeg-xl/BUILD.bazel поставляемый
Просмотреть файл

@ -1,3 +1,8 @@
# 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.
package(default_visibility = ["//:__subpackages__"])
filegroup(

19
third_party/jpeg-xl/CHANGELOG.md поставляемый
Просмотреть файл

@ -5,10 +5,23 @@ 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).
## [0.10.3] - 2024-06-27
## [0.11.0] - 2024-09-13
### Fixed
- fix decoding of some special images (#3662)
### 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

51
third_party/jpeg-xl/CMakeLists.txt поставляемый
Просмотреть файл

@ -11,7 +11,7 @@ project(LIBJXL LANGUAGES C CXX)
# TODO(sboukortt): remove once oss-fuzz passes -DBUILD_SHARED_LIBS=OFF
if(JPEGXL_ENABLE_FUZZERS)
message(INFO "Fuzzer build detected, building static libs")
message(STATUS "Fuzzer build detected, building static libs")
set(BUILD_SHARED_LIBS OFF)
endif()
@ -21,6 +21,10 @@ check_cxx_compiler_flag("-fsanitize=fuzzer-no-link" CXX_FUZZERS_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)
@ -86,6 +90,16 @@ 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.
@ -124,7 +138,7 @@ 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_ENABLE_VIEWERS false CACHE BOOL
"Build JPEGXL viewer tools for evaluation.")
@ -160,14 +174,14 @@ 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_TRHEADS true CACHE BOOL
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
@ -208,13 +222,20 @@ 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 MultiThreaded)
# 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
@ -224,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)
@ -265,7 +295,7 @@ if(JPEGXL_STATIC)
endif()
endif() # JPEGXL_STATIC
if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_TRHEADS)
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")
@ -343,7 +373,6 @@ else ()
if(JPEGXL_ENABLE_COVERAGE)
set(JPEGXL_COVERAGE_FLAGS
-g -O0 -fprofile-arcs -ftest-coverage
-DJXL_ENABLE_ASSERT=0 -DJXL_ENABLE_CHECK=0
)
set(JPEGXL_COVERAGE_LINK_FLAGS
--coverage
@ -431,7 +460,7 @@ if(JPEGXL_ENABLE_MANPAGES)
find_program(ASCIIDOC a2x)
if(ASCIIDOC)
file(STRINGS "${ASCIIDOC}" ASCIIDOC_SHEBANG LIMIT_COUNT 1)
if(ASCIIDOC_SHEBANG MATCHES "/sh|/bash" OR MINGW)
if(ASCIIDOC_SHEBANG MATCHES "sh$" OR MINGW)
set(ASCIIDOC_PY_FOUND ON)
# Run the program directly and set ASCIIDOC as empty.
set(ASCIIDOC_PY "${ASCIIDOC}")

12
third_party/jpeg-xl/MODULE.bazel поставляемый
Просмотреть файл

@ -1,4 +1,12 @@
bazel_dep(name = "bazel_skylib", version = "1.5.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.
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 = "openexr", version = "3.2.1")
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")

1527
third_party/jpeg-xl/MODULE.bazel.lock поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

10
third_party/jpeg-xl/README.md поставляемый
Просмотреть файл

@ -73,11 +73,14 @@ To decode a JPEG XL file run:
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).
JPEG file (when the extension of the output file is `.jpg`).
### Benchmarking
@ -127,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

191
third_party/jpeg-xl/WORKSPACE поставляемый
Просмотреть файл

@ -1,8 +1,13 @@
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")
# 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",
@ -30,185 +35,3 @@ cc_library(
""",
path = "third_party/skcms",
)
new_git_repository(
name = "libjpeg_turbo",
build_file_content = """
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
SUBSTITUTIONS = {
"@BUILD@" : "20230208",
"@CMAKE_PROJECT_NAME@" : "libjpeg-turbo",
"@COPYRIGHT_YEAR@" : "2023",
"@INLINE@" : "__inline__",
"@JPEG_LIB_VERSION@" : "62",
"@LIBJPEG_TURBO_VERSION_NUMBER@" : "2001091",
"@SIZE_T@" : "8",
"@THREAD_LOCAL@" : "__thread",
"@VERSION@" : "2.1.91",
}
YES_DEFINES = [
"C_ARITH_CODING_SUPPORTED", "D_ARITH_CODING_SUPPORTED",
"HAVE_BUILTIN_CTZL", "MEM_SRCDST_SUPPORTED"
]
NO_DEFINES = [
"WITH_SIMD", "RIGHT_SHIFT_IS_UNSIGNED", "HAVE_INTRIN_H"
]
SUBSTITUTIONS.update({
"#cmakedefine " + key : "#define " + key for key in YES_DEFINES
})
SUBSTITUTIONS.update({
"#cmakedefine " + key : "// #define " + key for key in NO_DEFINES
})
[
expand_template(
name = "expand_" + src,
template = src + ".in",
out = src,
substitutions = SUBSTITUTIONS,
visibility = ["//visibility:public"],
) for src in ["jconfig.h", "jconfigint.h", "jversion.h"]
]
JPEG16_SOURCES = [
"jccolor.c",
"jcdiffct.c",
"jclossls.c",
"jcmainct.c",
"jcprepct.c",
"jcsample.c",
"jdcolor.c",
"jddiffct.c",
"jdlossls.c",
"jdmainct.c",
"jdmerge.c",
"jdpostct.c",
"jdsample.c",
"jquant1.c",
"jquant2.c",
"jutils.c",
]
JPEG12_SOURCES = JPEG16_SOURCES + [
"jccoefct.c",
"jcdctmgr.c",
"jdcoefct.c",
"jddctmgr.c",
"jfdctfst.c",
"jfdctint.c",
"jidctflt.c",
"jidctfst.c",
"jidctint.c",
"jidctred.c",
]
JPEG_SOURCES = JPEG12_SOURCES + [
"jaricom.c",
"jcapimin.c",
"jcapistd.c",
"jcarith.c",
"jchuff.c",
"jcicc.c",
"jcinit.c",
"jclhuff.c",
"jcmarker.c",
"jcmaster.c",
"jcomapi.c",
"jcparam.c",
"jcphuff.c",
"jdapimin.c",
"jdapistd.c",
"jdarith.c",
"jdatadst.c",
"jdatasrc.c",
"jdhuff.c",
"jdicc.c",
"jdinput.c",
"jdlhuff.c",
"jdmarker.c",
"jdmaster.c",
"jdphuff.c",
"jdtrans.c",
"jerror.c",
"jfdctflt.c",
"jmemmgr.c",
"jmemnobs.c",
]
JPEG_HEADERS = [
"jccolext.c",
"jchuff.h",
"jcmaster.h",
"jconfig.h",
"jconfigint.h",
"jdcoefct.h",
"jdcol565.c",
"jdcolext.c",
"jdct.h",
"jdhuff.h",
"jdmainct.h",
"jdmaster.h",
"jdmerge.h",
"jdmrg565.c",
"jdmrgext.c",
"jdsample.h",
"jerror.h",
"jinclude.h",
"jlossls.h",
"jmemsys.h",
"jmorecfg.h",
"jpeg_nbits_table.h",
"jpegapicomp.h",
"jpegint.h",
"jpeglib.h",
"jsamplecomp.h",
"jsimd.h",
"jsimddct.h",
"jstdhuff.c",
"jversion.h",
]
cc_library(
name = "jpeg16",
srcs = JPEG16_SOURCES,
hdrs = JPEG_HEADERS,
local_defines = ["BITS_IN_JSAMPLE=16"],
visibility = ["//visibility:public"],
)
cc_library(
name = "jpeg12",
srcs = JPEG12_SOURCES,
hdrs = JPEG_HEADERS,
local_defines = ["BITS_IN_JSAMPLE=12"],
visibility = ["//visibility:public"],
)
cc_library(
name = "jpeg",
srcs = JPEG_SOURCES,
hdrs = JPEG_HEADERS,
deps = [":jpeg16", ":jpeg12"],
includes = ["."],
visibility = ["//visibility:public"],
)
exports_files([
"jmorecfg.h",
"jpeglib.h",
])
""",
remote = "https://github.com/libjpeg-turbo/libjpeg-turbo.git",
tag = "2.1.91",
)
http_archive(
name = "gif",
build_file_content = """
cc_library(
name = "gif",
srcs = [
"dgif_lib.c", "egif_lib.c", "gifalloc.c", "gif_err.c", "gif_font.c",
"gif_hash.c", "openbsd-reallocarray.c", "gif_hash.h",
"gif_lib_private.h"
],
hdrs = ["gif_lib.h"],
includes = ["."],
visibility = ["//visibility:public"],
)
""",
sha256 = "31da5562f44c5f15d63340a09a4fd62b48c45620cd302f77a6d9acf0077879bd",
strip_prefix = "giflib-5.2.1",
url = "https://netcologne.dl.sourceforge.net/project/giflib/giflib-5.2.1.tar.gz",
)

9
third_party/jpeg-xl/bash_test.sh поставляемый
Просмотреть файл

@ -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
@ -106,12 +107,6 @@ 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 /testing.h); then
echo "Don't include gmock directly, instead include 'testing.h'. " >&2
ret=1
fi
local f
for f in $(git ls-files | grep -E "\.cc$" | xargs grep 'PRI[udx]S' |
cut -f 1 -d : | uniq); do

223
third_party/jpeg-xl/ci.sh поставляемый
Просмотреть файл

@ -12,10 +12,13 @@ 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:-}
@ -79,6 +82,12 @@ if [[ "${ENABLE_WASM_SIMD}" -eq "2" ]]; then
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
@ -128,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,
@ -411,7 +437,7 @@ cmake_build_and_test() {
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 - \
@ -459,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
}
@ -473,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
}
@ -553,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.
@ -566,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
@ -578,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
}
@ -606,7 +630,6 @@ cmd_msan() {
-fsanitize=memory
-fno-omit-frame-pointer
-DJXL_ENABLE_ASSERT=1
-g
-DMEMORY_SANITIZER
@ -639,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
}
@ -657,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++}"
@ -664,23 +695,36 @@ 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}"
local TARGET_OPTS=""
@ -692,32 +736,29 @@ cmd_msan_install() {
"
fi
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_SHARED_LINKER_FLAGS="${CMAKE_SHARED_LINKER_FLAGS}" \
-DCMAKE_INSTALL_PREFIX="${msan_prefix}" \
${TARGET_OPTS} \
${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.
@ -791,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}")
@ -831,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)
@ -844,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
@ -856,15 +903,24 @@ 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=(
@ -873,20 +929,20 @@ run_benchmark() {
--output_dir "${output_dir}"
--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]}
)
}
# Helper function to wait for the CPU temperature to cool down on ARM.
@ -1027,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}")
@ -1076,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 ',')
@ -1092,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}")
@ -1122,12 +1178,12 @@ 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}/"
)
@ -1154,7 +1210,7 @@ cmd_lint() {
# 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$"`
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
@ -1167,6 +1223,15 @@ cmd_lint() {
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=()
local clang_patch
local clang_format

34
third_party/jpeg-xl/cmake/FindHWY.cmake поставляемый
Просмотреть файл

@ -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]+)" _sink "${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]+)" _sink "${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]+)" _sink "${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)

6
third_party/jpeg-xl/debian/changelog поставляемый
Просмотреть файл

@ -1,8 +1,8 @@
jpeg-xl (0.10.3) UNRELEASED; urgency=medium
jpeg-xl (0.11.0) unstable; urgency=medium
* Bump JPEG XL version to 0.10.3.
* Bump JPEG XL version to 0.11.0.
-- JPEG XL Maintainers <jpegxl@google.com> Thu, 27 Jun 2024 12:23:45 +0200
-- JPEG XL Maintainers <jpegxl@google.com> Tue, 06 Aug 2024 14:35:34 +0200
jpeg-xl (0.10.2) unstable; urgency=medium

1
third_party/jpeg-xl/debian/control поставляемый
Просмотреть файл

@ -11,7 +11,6 @@ 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 (>= 1.0.0),

7
third_party/jpeg-xl/deps.sh поставляемый
Просмотреть файл

@ -9,13 +9,15 @@
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.
TESTDATA="873045a9c42ed60721756e26e2a6b32e17415205"
THIRD_PARTY_BROTLI="36533a866ed1ca4b75cf049f4521e4ec5fe24727"
THIRD_PARTY_HIGHWAY="58b52a717469e62b2d9b8eaa2f5dddb44d4a4cbf"
THIRD_PARTY_GOOGLETEST="58d77fa8070e8cec2dc1ed015d66b454c8d78850"
THIRD_PARTY_HIGHWAY="457c891775a7397bdb0376bb1031e6e027af1c48"
THIRD_PARTY_SKCMS="42030a771244ba67f86b1c1c76a6493f873c5f91"
THIRD_PARTY_SJPEG="e5ab13008bb214deb66d5f3e17ca2f8dbff150bf"
THIRD_PARTY_ZLIB="51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf" # v1.3.1
@ -82,6 +84,7 @@ EOF
# 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 \

3
third_party/jpeg-xl/examples/CMakeLists.txt поставляемый
Просмотреть файл

@ -15,6 +15,9 @@ 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)

Просмотреть файл

@ -22,7 +22,8 @@ bool DecodeJpegXlExif(const uint8_t* jxl, size_t size,
// 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;
}
@ -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);

Просмотреть файл

@ -169,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);

Просмотреть файл

@ -6,16 +6,20 @@
// 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>
bool WritePAM(const char* filename, const uint8_t* buffer, size_t w, size_t h) {
@ -174,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);
@ -220,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;

Просмотреть файл

@ -48,7 +48,7 @@ bool ReadPFM(const char* filename, std::vector<float>* pixels, uint32_t* xsize,
return false;
}
long size = ftell(file);
long size = ftell(file); // NOLINT
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
@ -64,7 +64,7 @@ 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 (static_cast<long>(readsize) != size) {
if (static_cast<long>(readsize) != size) { // NOLINT
fclose(file);
return false;
}

2
third_party/jpeg-xl/examples/examples.cmake поставляемый
Просмотреть файл

@ -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)

1
third_party/jpeg-xl/flake.nix поставляемый
Просмотреть файл

@ -19,7 +19,6 @@
cmake
pkg-config
gtest
gmock
doxygen
graphviz
python3

9
third_party/jpeg-xl/lib/BUILD поставляемый
Просмотреть файл

@ -26,8 +26,8 @@ load(
"libjxl_enc_sources",
"libjxl_extras_for_tools_sources",
"libjxl_extras_sources",
#'libjxl_gbench_sources',
"libjxl_jpegli_lib_version",
# "libjxl_gbench_sources",
# "libjxl_jpegli_lib_version",
"libjxl_jpegli_libjpeg_helper_files",
"libjxl_jpegli_sources",
"libjxl_jpegli_testlib_files",
@ -54,7 +54,8 @@ load(
"libjxl_deps_png",
"libjxl_deps_runfiles",
"libjxl_deps_skcms",
"libjxl_deps_testdata",
# "libjxl_deps_testdata",
# "libjxl_deps_webp",
"libjxl_root_package",
"libjxl_test_shards",
"libjxl_test_timeouts",
@ -67,7 +68,7 @@ DEFAULT_COMPATIBILITY = []
INCLUDES_DIR = "include"
package(
default_visibility = ["//:__subpackages__"],
default_visibility = DEFAULT_VISIBILITY,
)
licenses(["notice"])

6
third_party/jpeg-xl/lib/CMakeLists.txt поставляемый
Просмотреть файл

@ -4,8 +4,8 @@
# license that can be found in the LICENSE file.
set(JPEGXL_MAJOR_VERSION 0)
set(JPEGXL_MINOR_VERSION 10)
set(JPEGXL_PATCH_VERSION 3)
set(JPEGXL_MINOR_VERSION 11)
set(JPEGXL_PATCH_VERSION 0)
set(JPEGXL_LIBRARY_VERSION
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_MINOR_VERSION}.${JPEGXL_PATCH_VERSION}")
@ -15,7 +15,7 @@ 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 10)
set(JPEGXL_SO_MINOR_VERSION 11)
if (JPEGXL_MAJOR_VERSION EQUAL 0)
set(JPEGXL_LIBRARY_SOVERSION
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_SO_MINOR_VERSION}")

20
third_party/jpeg-xl/lib/extras/alpha_blend.cc поставляемый
Просмотреть файл

@ -6,21 +6,23 @@
#include "lib/extras/alpha_blend.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
namespace {
void AlphaBlend(PackedFrame* frame, const float background[3]) {
if (!frame) return;
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;
return true;
}
--format.num_channels;
PackedImage blended(im.xsize, im.ysize, format);
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) {
@ -44,19 +46,21 @@ void AlphaBlend(PackedFrame* frame, const float background[3]) {
}
}
frame->color = blended.Copy();
return true;
}
} // namespace
void AlphaBlend(PackedPixelFile* ppf, const float background[3]) {
Status AlphaBlend(PackedPixelFile* ppf, const float background[3]) {
if (!ppf || ppf->info.alpha_bits == 0) {
return;
return true;
}
ppf->info.alpha_bits = 0;
AlphaBlend(ppf->preview_frame.get(), background);
JXL_RETURN_IF_ERROR(AlphaBlend(ppf->preview_frame.get(), background));
for (auto& frame : ppf->frames) {
AlphaBlend(&frame, background);
JXL_RETURN_IF_ERROR(AlphaBlend(&frame, background));
}
return true;
}
} // namespace extras

Просмотреть файл

@ -7,11 +7,12 @@
#define LIB_EXTRAS_ALPHA_BLEND_H_
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
void AlphaBlend(PackedPixelFile* ppf, const float background[3]);
Status AlphaBlend(PackedPixelFile* ppf, const float background[3]);
} // namespace extras
} // namespace jxl

3
third_party/jpeg-xl/lib/extras/codec.cc поставляемый
Просмотреть файл

@ -17,7 +17,6 @@
#include "lib/extras/packed_image.h"
#include "lib/extras/packed_image_convert.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image_bundle.h"
namespace jxl {
namespace {
@ -95,7 +94,7 @@ Status Encode(const extras::PackedPixelFile& ppf, const extras::Codec codec,
}
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;

91
third_party/jpeg-xl/lib/extras/codec_test.cc поставляемый
Просмотреть файл

@ -7,11 +7,12 @@
#include <jxl/color_encoding.h>
#include <jxl/encode.h>
#include <jxl/types.h>
#include <stddef.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <sstream>
@ -22,10 +23,11 @@
#include "lib/extras/common.h"
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/dec/decode.h"
#include "lib/extras/dec/pnm.h"
#include "lib/extras/enc/encode.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/span.h"
#include "lib/jxl/base/status.h"
@ -35,16 +37,18 @@
namespace jxl {
using test::ThreadPoolForTests;
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::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,
@ -112,15 +116,15 @@ 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(c_internal.FromExternal(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(c.FromExternal(color_encoding));
JXL_CHECK(!c.ICC().empty());
EXPECT_TRUE(c.FromExternal(color_encoding));
EXPECT_TRUE(!c.ICC().empty());
return c.ICC();
}
@ -233,13 +237,17 @@ void CreateTestImage(const TestImageParams& params, PackedPixelFile* ppf) {
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;
PackedImage ec(params.xsize, params.ysize, ec_format);
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;
@ -335,10 +343,10 @@ TEST(CodecTest, TestRoundTrip) {
params.add_alpha = add_alpha;
params.big_endian = big_endian;
params.add_extra_channels = false;
TestRoundTrip(params, &pool);
TestRoundTrip(params, pool.get());
if (codec == Codec::kPNM && add_alpha) {
params.add_extra_channels = true;
TestRoundTrip(params, &pool);
TestRoundTrip(params, pool.get());
}
}
}
@ -371,7 +379,7 @@ TEST(CodecTest, LosslessPNMRoundtrip) {
EncodedImage encoded;
auto encoder = Encoder::FromExtension(extension);
ASSERT_TRUE(encoder.get());
ASSERT_TRUE(encoder->Encode(ppf, &encoded, &pool));
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,
@ -380,7 +388,40 @@ TEST(CodecTest, LosslessPNMRoundtrip) {
}
}
TEST(CodecTest, TestPNM) { TestCodecPNM(); }
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));
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);
ASSERT_TRUE(PnmParseUnsigned(MakeSpan("32"), &u));
ASSERT_TRUE(u == 32);
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, FormatNegotiation) {
const std::vector<JxlPixelFormat> accepted_formats = {
@ -432,15 +473,17 @@ TEST(CodecTest, EncodeToPNG) {
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(Bytes(encoded_png.bitstreams.front()),

1
third_party/jpeg-xl/lib/extras/common.cc поставляемый
Просмотреть файл

@ -27,6 +27,7 @@ Status SelectFormat(const std::vector<JxlPixelFormat>& accepted_formats,
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 (

53
third_party/jpeg-xl/lib/extras/compressed_icc.cc поставляемый Normal 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;
}

47
third_party/jpeg-xl/lib/extras/compressed_icc_test.cc поставляемый Normal 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

1554
third_party/jpeg-xl/lib/extras/dec/apng.cc поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

3
third_party/jpeg-xl/lib/extras/dec/apng.h поставляемый
Просмотреть файл

@ -8,11 +8,10 @@
// 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/span.h"
#include "lib/jxl/base/status.h"

Просмотреть файл

@ -164,7 +164,7 @@ 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) {
@ -203,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;
}

Просмотреть файл

@ -91,6 +91,15 @@ bool CanDecode(Codec codec) {
}
}
std::string ListOfDecodeCodecs() {
std::string list_of_codecs("JXL, PPM, PNM, PFM, PAM, PGX");
if (CanDecode(Codec::kPNG)) list_of_codecs.append(", PNG, APNG");
if (CanDecode(Codec::kGIF)) list_of_codecs.append(", GIF");
if (CanDecode(Codec::kJPG)) list_of_codecs.append(", JPEG");
if (CanDecode(Codec::kEXR)) list_of_codecs.append(", EXR");
return list_of_codecs;
}
Status DecodeBytes(const Span<const uint8_t> bytes,
const ColorHints& color_hints, extras::PackedPixelFile* ppf,
const SizeConstraints* constraints, Codec* orig_codec) {

8
third_party/jpeg-xl/lib/extras/dec/decode.h поставляемый
Просмотреть файл

@ -8,11 +8,9 @@
// Facade for image decoders (PNG, PNM, ...).
#include <stddef.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "lib/extras/dec/color_hints.h"
#include "lib/jxl/base/span.h"
@ -38,6 +36,8 @@ enum class Codec : uint32_t {
bool CanDecode(Codec codec);
std::string ListOfDecodeCodecs();
// If and only if extension is ".pfm", *bits_per_sample is updated to 32 so
// that Encode() would encode to PFM instead of PPM.
Codec CodecFromPath(const std::string& path,

70
third_party/jpeg-xl/lib/extras/dec/exr.cc поставляемый
Просмотреть файл

@ -5,19 +5,51 @@
#include "lib/extras/dec/exr.h"
#if JPEGXL_ENABLE_EXR
#include <cstdint>
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
#if !JPEGXL_ENABLE_EXR
namespace jxl {
namespace extras {
bool CanDecodeEXR() { return false; }
Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
PackedPixelFile* ppf,
const SizeConstraints* constraints) {
(void)bytes;
(void)color_hints;
(void)ppf;
(void)constraints;
return JXL_FAILURE("EXR is not supported");
}
} // namespace extras
} // namespace jxl
#else // JPEGXL_ENABLE_EXR
#include <ImfChromaticitiesAttribute.h>
#include <ImfIO.h>
#include <ImfRgbaFile.h>
#include <ImfStandardAttributes.h>
#endif
#include <vector>
#ifdef __EXCEPTIONS
#include <stdexcept>
#define JXL_EXR_THROW_LENGTH_ERROR() throw std::length_error("");
#else // __EXCEPTIONS
#define JXL_EXR_THROW_LENGTH_ERROR() JXL_CRASH()
#endif // __EXCEPTIONS
namespace jxl {
namespace extras {
#if JPEGXL_ENABLE_EXR
namespace {
namespace OpenEXR = OPENEXR_IMF_NAMESPACE;
@ -39,7 +71,9 @@ class InMemoryIStream : public OpenEXR::IStream {
bool isMemoryMapped() const override { return true; }
char* readMemoryMapped(const int n) override {
JXL_ASSERT(pos_ + n <= bytes_.size());
if (pos_ + n < pos_ || pos_ + n > bytes_.size()) {
JXL_EXR_THROW_LENGTH_ERROR();
}
char* const result =
const_cast<char*>(reinterpret_cast<const char*>(bytes_.data() + pos_));
pos_ += n;
@ -52,7 +86,9 @@ class InMemoryIStream : public OpenEXR::IStream {
ExrInt64 tellg() override { return pos_; }
void seekg(const ExrInt64 pos) override {
JXL_ASSERT(pos + 1 <= bytes_.size());
if (pos >= bytes_.size()) {
JXL_EXR_THROW_LENGTH_ERROR();
}
pos_ = pos;
}
@ -62,26 +98,18 @@ class InMemoryIStream : public OpenEXR::IStream {
};
} // namespace
#endif
bool CanDecodeEXR() {
#if JPEGXL_ENABLE_EXR
return true;
#else
return false;
#endif
}
bool CanDecodeEXR() { return true; }
Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
PackedPixelFile* ppf,
const SizeConstraints* constraints) {
#if JPEGXL_ENABLE_EXR
InMemoryIStream is(bytes);
#ifdef __EXCEPTIONS
std::unique_ptr<OpenEXR::RgbaInputFile> input_ptr;
try {
input_ptr.reset(new OpenEXR::RgbaInputFile(is));
input_ptr = jxl::make_unique<OpenEXR::RgbaInputFile>(is);
} catch (...) {
// silently return false if it is not an EXR file
return false;
@ -121,7 +149,12 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
};
ppf->frames.clear();
// Allocates the frame buffer.
ppf->frames.emplace_back(image_size.x, image_size.y, format);
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(image_size.x, image_size.y, format));
ppf->frames.emplace_back(std::move(frame));
}
const auto& frame = ppf->frames.back();
const int row_size = input.dataWindow().size().x + 1;
@ -192,10 +225,9 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
ppf->info.intensity_target = intensity_target;
return true;
#else
return false;
#endif
}
} // namespace extras
} // namespace jxl
#endif // JPEGXL_ENABLE_EXR

2
third_party/jpeg-xl/lib/extras/dec/exr.h поставляемый
Просмотреть файл

@ -8,6 +8,8 @@
// Decodes OpenEXR images in memory.
#include <cstdint>
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/data_parallel.h"

59
third_party/jpeg-xl/lib/extras/dec/gif.cc поставляемый
Просмотреть файл

@ -5,19 +5,22 @@
#include "lib/extras/dec/gif.h"
#include "lib/jxl/base/status.h"
#if JPEGXL_ENABLE_GIF
#include <gif_lib.h>
#endif
#include <jxl/codestream_header.h>
#include <string.h>
#include <cstring>
#include <memory>
#include <utility>
#include <vector>
#include "lib/extras/size_constraints.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/sanitizers.h"
#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/sanitizers.h"
namespace jxl {
namespace extras {
@ -42,19 +45,22 @@ struct PackedRgb {
uint8_t r, g, b;
};
void ensure_have_alpha(PackedFrame* frame) {
if (!frame->extra_channels.empty()) return;
Status ensure_have_alpha(PackedFrame* frame) {
if (!frame->extra_channels.empty()) return true;
const JxlPixelFormat alpha_format{
/*num_channels=*/1u,
/*data_type=*/JXL_TYPE_UINT8,
/*endianness=*/JXL_NATIVE_ENDIAN,
/*align=*/0,
};
frame->extra_channels.emplace_back(frame->color.xsize, frame->color.ysize,
alpha_format);
JXL_ASSIGN_OR_RETURN(PackedImage image,
PackedImage::Create(frame->color.xsize,
frame->color.ysize, alpha_format));
frame->extra_channels.emplace_back(std::move(image));
// We need to set opaque-by-default.
std::fill_n(static_cast<uint8_t*>(frame->extra_channels[0].pixels()),
frame->color.xsize * frame->color.ysize, 255u);
return true;
}
} // namespace
#endif
@ -81,7 +87,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
n = state->bytes.size();
}
memcpy(bytes, state->bytes.data(), n);
state->bytes.remove_prefix(n);
if (!state->bytes.remove_prefix(n)) return 0;
return n;
};
GifUniquePtr gif(DGifOpen(&state, ReadFromSpan, &error));
@ -137,7 +143,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
if (gif->ImageCount > 1) {
ppf->info.have_animation = JXL_TRUE;
// Delays in GIF are specified in 100ths of a second.
// Delays in GIF are specified in censiseconds.
ppf->info.animation.tps_numerator = 100;
ppf->info.animation.tps_denominator = 1;
}
@ -186,7 +192,9 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
const PackedRgba background_rgba{background_color.Red, background_color.Green,
background_color.Blue, 0};
PackedFrame canvas(gif->SWidth, gif->SHeight, canvas_format);
JXL_ASSIGN_OR_RETURN(
PackedFrame canvas,
PackedFrame::Create(gif->SWidth, gif->SHeight, canvas_format));
std::fill_n(static_cast<PackedRgba*>(canvas.color.pixels()),
canvas.color.xsize * canvas.color.ysize, background_rgba);
Rect canvas_rect{0, 0, canvas.color.xsize, canvas.color.ysize};
@ -230,26 +238,33 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Allocates the frame buffer.
ppf->frames.emplace_back(total_rect.xsize(), total_rect.ysize(),
packed_frame_format);
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(total_rect.xsize(), total_rect.ysize(),
packed_frame_format));
ppf->frames.emplace_back(std::move(frame));
}
PackedFrame* frame = &ppf->frames.back();
// We cannot tell right from the start whether there will be a
// need for an alpha channel. This is discovered only as soon as
// we see a transparent pixel. We hence initialize alpha lazily.
auto set_pixel_alpha = [&frame](size_t x, size_t y, uint8_t a) {
auto set_pixel_alpha = [&frame](size_t x, size_t y, uint8_t a) -> Status {
// If we do not have an alpha-channel and a==255 (fully opaque),
// we can skip setting this pixel-value and rely on
// "no alpha channel = no transparency".
if (a == 255 && !frame->extra_channels.empty()) return;
ensure_have_alpha(frame);
if (a == 255 && !frame->extra_channels.empty()) return true;
JXL_RETURN_IF_ERROR(ensure_have_alpha(frame));
static_cast<uint8_t*>(
frame->extra_channels[0].pixels())[y * frame->color.xsize + x] = a;
return true;
};
const ColorMapObject* const color_map =
image.ImageDesc.ColorMap ? image.ImageDesc.ColorMap : gif->SColorMap;
JXL_CHECK(color_map);
JXL_ENSURE(color_map);
msan::UnpoisonMemory(color_map, sizeof(*color_map));
msan::UnpoisonMemory(color_map->Colors,
sizeof(*color_map->Colors) * color_map->ColorCount);
@ -301,8 +316,10 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Update the canvas by creating a copy first.
PackedImage new_canvas_image(canvas.color.xsize, canvas.color.ysize,
canvas.color.format);
JXL_ASSIGN_OR_RETURN(
PackedImage new_canvas_image,
PackedImage::Create(canvas.color.xsize, canvas.color.ysize,
canvas.color.format));
memcpy(new_canvas_image.pixels(), canvas.color.pixels(),
new_canvas_image.pixels_size);
for (size_t y = 0, byte_index = 0; y < image_rect.ysize(); ++y) {
@ -338,7 +355,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
row_out[x].r = row_in[x].r;
row_out[x].g = row_in[x].g;
row_out[x].b = row_in[x].b;
set_pixel_alpha(x, y, row_in[x].a);
JXL_RETURN_IF_ERROR(set_pixel_alpha(x, y, row_in[x].a));
}
}
} else {
@ -355,14 +372,14 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
row[x].r = 0;
row[x].g = 0;
row[x].b = 0;
set_pixel_alpha(x, y, 0);
JXL_RETURN_IF_ERROR(set_pixel_alpha(x, y, 0));
continue;
}
GifColorType color = color_map->Colors[byte];
row[x].r = color.Red;
row[x].g = color.Green;
row[x].b = color.Blue;
set_pixel_alpha(x, y, 255);
JXL_RETURN_IF_ERROR(set_pixel_alpha(x, y, 255));
}
}
}
@ -402,7 +419,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
if (seen_alpha) {
for (PackedFrame& frame : ppf->frames) {
ensure_have_alpha(&frame);
JXL_RETURN_IF_ERROR(ensure_have_alpha(&frame));
}
}
return true;

47
third_party/jpeg-xl/lib/extras/dec/jpegli.cc поставляемый
Просмотреть файл

@ -6,16 +6,17 @@
#include "lib/extras/dec/jpegli.h"
#include <setjmp.h>
#include <stdint.h>
#include <algorithm>
#include <numeric>
#include <cstdint>
#include <memory>
#include <utility>
#include <vector>
#include "lib/jpegli/decode.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/sanitizers.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jxl {
namespace extras {
@ -114,25 +115,26 @@ void MyErrorExit(j_common_ptr cinfo) {
}
void MyOutputMessage(j_common_ptr cinfo) {
#if JXL_DEBUG_WARNING == 1
char buf[JMSG_LENGTH_MAX + 1];
(*cinfo->err->format_message)(cinfo, buf);
buf[JMSG_LENGTH_MAX] = 0;
JXL_WARNING("%s", buf);
#endif
if (JXL_IS_DEBUG_BUILD) {
char buf[JMSG_LENGTH_MAX + 1];
(*cinfo->err->format_message)(cinfo, buf);
buf[JMSG_LENGTH_MAX] = 0;
JXL_WARNING("%s", buf);
}
}
void UnmapColors(uint8_t* row, size_t xsize, int components,
JSAMPARRAY colormap, size_t num_colors) {
JXL_CHECK(colormap != nullptr);
Status UnmapColors(uint8_t* row, size_t xsize, int components,
JSAMPARRAY colormap, size_t num_colors) {
JXL_ENSURE(colormap != nullptr);
std::vector<uint8_t> tmp(xsize * components);
for (size_t x = 0; x < xsize; ++x) {
JXL_CHECK(row[x] < num_colors);
JXL_ENSURE(row[x] < num_colors);
for (int c = 0; c < components; ++c) {
tmp[x * components + c] = colormap[c][row[x]];
}
}
memcpy(row, tmp.data(), tmp.size());
return true;
}
} // namespace
@ -181,7 +183,9 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
}
int nbcomp = cinfo.num_components;
if (nbcomp != 1 && nbcomp != 3) {
return failure("unsupported number of components in JPEG");
std::string msg =
"unsupported number of components in JPEG: " + std::to_string(nbcomp);
return failure(msg.c_str());
}
if (dparams.force_rgb) {
cinfo.out_color_space = JCS_RGB;
@ -246,11 +250,17 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
};
ppf->frames.clear();
// Allocates the frame buffer.
ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
ppf->frames.emplace_back(std::move(frame));
}
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
JXL_ENSURE(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=
frame.color.stride);
if (dparams.num_colors > 0) JXL_ENSURE(cinfo.colormap != nullptr);
for (size_t y = 0; y < cinfo.image_height; ++y) {
JSAMPROW rows[] = {reinterpret_cast<JSAMPLE*>(
@ -258,8 +268,9 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
frame.color.stride * y)};
jpegli_read_scanlines(&cinfo, rows, 1);
if (dparams.num_colors > 0) {
UnmapColors(rows[0], cinfo.output_width, cinfo.out_color_components,
cinfo.colormap, cinfo.actual_number_of_colors);
JXL_RETURN_IF_ERROR(
UnmapColors(rows[0], cinfo.output_width, cinfo.out_color_components,
cinfo.colormap, cinfo.actual_number_of_colors));
}
}

52
third_party/jpeg-xl/lib/extras/dec/jpg.cc поставляемый
Просмотреть файл

@ -6,19 +6,19 @@
#include "lib/extras/dec/jpg.h"
#if JPEGXL_ENABLE_JPEG
#include <jpeglib.h>
#include <setjmp.h>
#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#endif
#include <stdint.h>
#include <algorithm>
#include <cstdint>
#include <numeric>
#include <utility>
#include <vector>
#include "lib/extras/size_constraints.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/sanitizers.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jxl {
namespace extras {
@ -110,7 +110,7 @@ Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
}
if (seen_markers_count != num_markers) {
JXL_DASSERT(has_num_markers);
JXL_ENSURE(has_num_markers);
return JXL_FAILURE("Incomplete set of ICC chunks");
}
@ -156,25 +156,26 @@ void MyErrorExit(j_common_ptr cinfo) {
}
void MyOutputMessage(j_common_ptr cinfo) {
#if JXL_DEBUG_WARNING == 1
char buf[JMSG_LENGTH_MAX + 1];
(*cinfo->err->format_message)(cinfo, buf);
buf[JMSG_LENGTH_MAX] = 0;
JXL_WARNING("%s", buf);
#endif
if (JXL_IS_DEBUG_BUILD) {
char buf[JMSG_LENGTH_MAX + 1];
(*cinfo->err->format_message)(cinfo, buf);
buf[JMSG_LENGTH_MAX] = 0;
JXL_WARNING("%s", buf);
}
}
void UnmapColors(uint8_t* row, size_t xsize, int components,
JSAMPARRAY colormap, size_t num_colors) {
JXL_CHECK(colormap != nullptr);
Status UnmapColors(uint8_t* row, size_t xsize, int components,
JSAMPARRAY colormap, size_t num_colors) {
JXL_ENSURE(colormap != nullptr);
std::vector<uint8_t> tmp(xsize * components);
for (size_t x = 0; x < xsize; ++x) {
JXL_CHECK(row[x] < num_colors);
JXL_ENSURE(row[x] < num_colors);
for (int c = 0; c < components; ++c) {
tmp[x * components + c] = colormap[c][row[x]];
}
}
memcpy(row, tmp.data(), tmp.size());
return true;
}
} // namespace
@ -268,7 +269,7 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
ppf->info.ysize = cinfo.image_height;
// Original data is uint, so exponent_bits_per_sample = 0.
ppf->info.bits_per_sample = BITS_IN_JSAMPLE;
JXL_ASSERT(BITS_IN_JSAMPLE == 8 || BITS_IN_JSAMPLE == 16);
static_assert(BITS_IN_JSAMPLE == 8 || BITS_IN_JSAMPLE == 16);
ppf->info.exponent_bits_per_sample = 0;
ppf->info.uses_original_profile = JXL_TRUE;
@ -287,7 +288,7 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
}
jpeg_start_decompress(&cinfo);
JXL_ASSERT(cinfo.out_color_components == nbcomp);
JXL_ENSURE(cinfo.out_color_components == nbcomp);
JxlDataType data_type =
ppf->info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16;
@ -299,9 +300,14 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
ppf->frames.emplace_back(std::move(frame));
}
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
JXL_ENSURE(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=
frame.color.stride);
@ -315,6 +321,9 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
cinfo.actual_number_of_colors * sizeof(JSAMPLE));
}
}
if (dparams && dparams->num_colors > 0) {
JXL_ENSURE(cinfo.colormap != nullptr);
}
for (size_t y = 0; y < cinfo.image_height; ++y) {
JSAMPROW rows[] = {reinterpret_cast<JSAMPLE*>(
static_cast<uint8_t*>(frame.color.pixels()) +
@ -323,8 +332,9 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
msan::UnpoisonMemory(rows[0], sizeof(JSAMPLE) * cinfo.output_components *
cinfo.image_width);
if (dparams && dparams->num_colors > 0) {
UnmapColors(rows[0], cinfo.output_width, cinfo.out_color_components,
cinfo.colormap, cinfo.actual_number_of_colors);
JXL_RETURN_IF_ERROR(
UnmapColors(rows[0], cinfo.output_width, cinfo.out_color_components,
cinfo.colormap, cinfo.actual_number_of_colors));
}
}

70
third_party/jpeg-xl/lib/extras/dec/jxl.cc поставляемый
Просмотреть файл

@ -6,14 +6,21 @@
#include "lib/extras/dec/jxl.h"
#include <jxl/cms.h>
#include <jxl/codestream_header.h>
#include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <jxl/types.h>
#include <cinttypes>
#include <cinttypes> // PRIu32
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <vector>
#include "lib/extras/common.h"
#include "lib/extras/dec/color_description.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/exif.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/status.h"
@ -22,17 +29,27 @@ namespace jxl {
namespace extras {
namespace {
#define QUIT(M) \
fprintf(stderr, "%s\n", M); \
return false;
struct BoxProcessor {
explicit BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); }
void InitializeOutput(std::vector<uint8_t>* out) {
JXL_ASSERT(out != nullptr);
bool InitializeOutput(std::vector<uint8_t>* out) {
if (out == nullptr) {
fprintf(stderr, "internal: out == nullptr\n");
return false;
}
box_data_ = out;
AddMoreOutput();
return AddMoreOutput();
}
bool AddMoreOutput() {
JXL_ASSERT(box_data_ != nullptr);
if (box_data_ == nullptr) {
fprintf(stderr, "internal: box_data_ == nullptr\n");
return false;
}
Flush();
static const size_t kBoxOutputChunkSize = 1 << 16;
box_data_->resize(box_data_->size() + kBoxOutputChunkSize);
@ -118,7 +135,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
// silently return false if this is not a JXL file
if (sig == JXL_SIG_INVALID) return false;
auto decoder = JxlDecoderMake(/*memory_manager=*/nullptr);
auto decoder = JxlDecoderMake(dparams.memory_manager);
JxlDecoder* dec = decoder.get();
ppf->frames.clear();
@ -211,7 +228,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
uint32_t progression_index = 0;
bool codestream_done = accepted_formats.empty();
bool codestream_done = jpeg_bytes == nullptr && accepted_formats.empty();
BoxProcessor boxes(dec);
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec);
@ -252,14 +269,20 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
box_data = &ppf->metadata.iptc;
} else if (memcmp(box_type, "jumb", 4) == 0) {
box_data = &ppf->metadata.jumbf;
} else if (memcmp(box_type, "jhgm", 4) == 0) {
box_data = &ppf->metadata.jhgm;
} else if (memcmp(box_type, "xml ", 4) == 0) {
box_data = &ppf->metadata.xmp;
}
if (box_data) {
boxes.InitializeOutput(box_data);
if (!boxes.InitializeOutput(box_data)) {
return false;
}
}
} else if (status == JXL_DEC_BOX_NEED_MORE_OUTPUT) {
boxes.AddMoreOutput();
if (!boxes.AddMoreOutput()) {
return false;
}
} else if (status == JXL_DEC_JPEG_RECONSTRUCTION) {
can_reconstruct_jpeg = true;
// Decoding to JPEG.
@ -270,7 +293,10 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
} else if (status == JXL_DEC_JPEG_NEED_MORE_OUTPUT) {
JXL_ASSERT(jpeg_bytes != nullptr); // Help clang-tidy.
if (jpeg_bytes == nullptr) {
fprintf(stderr, "internal: jpeg_bytes == nullptr\n");
return false;
}
// Decoded a chunk to JPEG.
size_t used_jpeg_output =
jpeg_data_chunk.size() - JxlDecoderReleaseJPEGBuffer(dec);
@ -392,7 +418,12 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
}
} else if (status == JXL_DEC_FRAME) {
jxl::extras::PackedFrame frame(ppf->info.xsize, ppf->info.ysize, format);
auto frame_or = jxl::extras::PackedFrame::Create(ppf->info.xsize,
ppf->info.ysize, format);
JXL_ASSIGN_OR_QUIT(jxl::extras::PackedFrame frame,
jxl::extras::PackedFrame::Create(
ppf->info.xsize, ppf->info.ysize, format),
"Failed to create image frame.");
if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec, &frame.frame_info)) {
fprintf(stderr, "JxlDecoderGetFrameHeader failed\n");
return false;
@ -431,9 +462,13 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
fprintf(stderr, "JxlDecoderPreviewOutBufferSize failed\n");
return false;
}
ppf->preview_frame = std::unique_ptr<jxl::extras::PackedFrame>(
new jxl::extras::PackedFrame(ppf->info.preview.xsize,
ppf->info.preview.ysize, format));
JXL_ASSIGN_OR_QUIT(
jxl::extras::PackedImage preview_image,
jxl::extras::PackedImage::Create(ppf->info.preview.xsize,
ppf->info.preview.ysize, format),
"Failed to create preview image.");
ppf->preview_frame =
jxl::make_unique<jxl::extras::PackedFrame>(std::move(preview_image));
if (buffer_size != ppf->preview_frame->color.pixels_size) {
fprintf(stderr, "Invalid out buffer size %" PRIuS " %" PRIuS "\n",
buffer_size, ppf->preview_frame->color.pixels_size);
@ -500,8 +535,11 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
JxlPixelFormat ec_format = format;
ec_format.num_channels = 1;
for (auto& eci : ppf->extra_channels_info) {
frame.extra_channels.emplace_back(ppf->info.xsize, ppf->info.ysize,
ec_format);
JXL_ASSIGN_OR_QUIT(jxl::extras::PackedImage image,
jxl::extras::PackedImage::Create(
ppf->info.xsize, ppf->info.ysize, ec_format),
"Failed to create extra channel image.");
frame.extra_channels.emplace_back(std::move(image));
auto& ec = frame.extra_channels.back();
size_t buffer_size;
if (JXL_DEC_SUCCESS != JxlDecoderExtraChannelBufferSize(

7
third_party/jpeg-xl/lib/extras/dec/jxl.h поставляемый
Просмотреть файл

@ -8,10 +8,12 @@
// Decodes JPEG XL images in memory.
#include <jxl/memory_manager.h>
#include <jxl/parallel_runner.h>
#include <jxl/types.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <string>
#include <vector>
@ -38,6 +40,9 @@ struct JXLDecompressParams {
JxlParallelRunner runner;
void* runner_opaque = nullptr;
// If memory_manager is set, decoder uses it.
JxlMemoryManager* memory_manager = nullptr;
// Whether truncated input should be treated as an error.
bool allow_partial_input = false;

9
third_party/jpeg-xl/lib/extras/dec/pgx.cc поставляемый
Просмотреть файл

@ -150,7 +150,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
const SizeConstraints* constraints) {
Parser parser(bytes);
HeaderPGX header = {};
const uint8_t* pos;
const uint8_t* pos = nullptr;
if (!parser.ParseHeader(&header, &pos)) return false;
JXL_RETURN_IF_ERROR(
VerifyDimensions(constraints, header.xsize, header.ysize));
@ -188,7 +188,12 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
ppf->frames.emplace_back(header.xsize, header.ysize, format);
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(header.xsize, header.ysize, format));
ppf->frames.emplace_back(std::move(frame));
}
const auto& frame = ppf->frames.back();
size_t pgx_remaining_size = bytes.data() + bytes.size() - pos;
if (pgx_remaining_size < frame.color.pixels_size) {

Просмотреть файл

@ -5,10 +5,17 @@
#include "lib/extras/dec/pgx.h"
#include <cstdint>
#include <cstring>
#include <string>
#include "lib/extras/packed_image.h"
#include "lib/extras/packed_image_convert.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/image_bundle.h"
#include "lib/jxl/image_ops.h"
#include "lib/jxl/test_memory_manager.h"
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testing.h"
namespace jxl {
@ -26,7 +33,7 @@ TEST(CodecPGXTest, Test8bits) {
ThreadPool* pool = nullptr;
EXPECT_TRUE(DecodeImagePGX(MakeSpan(pgx.c_str()), ColorHints(), &ppf));
CodecInOut io;
CodecInOut io{jxl::test::MemoryManager()};
EXPECT_TRUE(ConvertPackedPixelFileToCodecInOut(ppf, pool, &io));
ScaleImage(255.f, io.Main().color());
@ -53,7 +60,7 @@ TEST(CodecPGXTest, Test16bits) {
ThreadPool* pool = nullptr;
EXPECT_TRUE(DecodeImagePGX(MakeSpan(pgx.c_str()), ColorHints(), &ppf));
CodecInOut io;
CodecInOut io{jxl::test::MemoryManager()};
EXPECT_TRUE(ConvertPackedPixelFileToCodecInOut(ppf, pool, &io));
ScaleImage(255.f, io.Main().color());

90
third_party/jpeg-xl/lib/extras/dec/pnm.cc поставляемый
Просмотреть файл

@ -5,17 +5,18 @@
#include "lib/extras/dec/pnm.h"
#include <stdlib.h>
#include <string.h>
#include <jxl/encode.h>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <mutex>
#include <cstdlib>
#include <cstring>
#include "jxl/encode.h"
#include "lib/extras/size_constraints.h"
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/c_callback_support.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
namespace jxl {
@ -226,6 +227,10 @@ class Parser {
header->ec_types.push_back(JXL_CHANNEL_CFA);
} else if (MatchString("Thermal")) {
header->ec_types.push_back(JXL_CHANNEL_THERMAL);
} else if (MatchString("Unknown")) {
header->ec_types.push_back(JXL_CHANNEL_UNKNOWN);
} else if (MatchString("Optional")) {
header->ec_types.push_back(JXL_CHANNEL_OPTIONAL);
} else {
return JXL_FAILURE("PAM: unknown TUPLTYPE");
}
@ -314,10 +319,6 @@ class Parser {
const uint8_t* const end_;
};
Span<const uint8_t> MakeSpan(const char* str) {
return Bytes(reinterpret_cast<const uint8_t*>(str), strlen(str));
}
} // namespace
struct PNMChunkedInputFrame {
@ -332,7 +333,7 @@ struct PNMChunkedInputFrame {
METHOD_TO_C_CALLBACK(&PNMChunkedInputFrame::ReleaseCurrentData)};
}
void GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
void /* NOLINT */ GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
*pixel_format = format;
}
@ -349,13 +350,18 @@ struct PNMChunkedInputFrame {
void GetExtraChannelPixelFormat(size_t ec_index,
JxlPixelFormat* pixel_format) {
JXL_ABORT("Not implemented");
(void)this;
*pixel_format = {};
JXL_DEBUG_ABORT("Not implemented");
}
const void* GetExtraChannelDataAt(size_t ec_index, size_t xpos, size_t ypos,
size_t xsize, size_t ysize,
size_t* row_offset) {
JXL_ABORT("Not implemented");
(void)this;
*row_offset = 0;
JXL_DEBUG_ABORT("Not implemented");
return nullptr;
}
void ReleaseCurrentData(const void* buffer) {}
@ -391,8 +397,8 @@ StatusOr<ChunkedPNMDecoder> ChunkedPNMDecoder::Init(const char* path) {
const size_t num_channels = dec.header_.is_gray ? 1 : 3;
const size_t bytes_per_pixel = num_channels * bytes_per_channel;
size_t row_size = dec.header_.xsize * bytes_per_pixel;
if (header.ysize * row_size + dec.data_start_ < size) {
return JXL_FAILURE("Invalid ppm");
if (size < header.ysize * row_size + dec.data_start_) {
return JXL_FAILURE("PNM file too small");
}
return dec;
}
@ -473,7 +479,7 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
ppf->info.num_extra_channels = num_alpha_channels + header.ec_types.size();
for (auto type : header.ec_types) {
PackedExtraChannel pec;
PackedExtraChannel pec = {};
pec.ec_info.bits_per_sample = ppf->info.bits_per_sample;
pec.ec_info.type = type;
ppf->extra_channels_info.emplace_back(std::move(pec));
@ -499,10 +505,18 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
};
const JxlPixelFormat ec_format{1, format.data_type, format.endianness, 0};
ppf->frames.clear();
ppf->frames.emplace_back(header.xsize, header.ysize, format);
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(header.xsize, header.ysize, format));
ppf->frames.emplace_back(std::move(frame));
}
auto* frame = &ppf->frames.back();
for (size_t i = 0; i < header.ec_types.size(); ++i) {
frame->extra_channels.emplace_back(header.xsize, header.ysize, ec_format);
JXL_ASSIGN_OR_RETURN(
PackedImage ec,
PackedImage::Create(header.xsize, header.ysize, ec_format));
frame->extra_channels.emplace_back(std::move(ec));
}
size_t pnm_remaining_size = bytes.data() + bytes.size() - pos;
if (pnm_remaining_size < frame->color.pixels_size) {
@ -523,6 +537,7 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
memcpy(row_out, row_in, frame->color.stride);
}
} else {
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(data_type));
size_t pwidth = PackedImage::BitsPerChannel(data_type) / 8;
for (size_t y = 0; y < header.ysize; ++y) {
for (size_t x = 0; x < header.xsize; ++x) {
@ -537,42 +552,19 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
}
}
}
if (ppf->info.exponent_bits_per_sample == 0) {
ppf->input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
}
return true;
}
void TestCodecPNM() {
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.
#ifndef JXL_CRASH_ON_ERROR
JXL_CHECK(false == Parser(MakeSpan("")).ParseUnsigned(&u));
JXL_CHECK(false == Parser(MakeSpan("+")).ParseUnsigned(&u));
JXL_CHECK(false == Parser(MakeSpan("-")).ParseUnsigned(&u));
JXL_CHECK(false == Parser(MakeSpan("A")).ParseUnsigned(&u));
// Exposed for testing.
Status PnmParseSigned(Bytes str, double* v) {
return Parser(str).ParseSigned(v);
}
JXL_CHECK(false == Parser(MakeSpan("")).ParseSigned(&d));
JXL_CHECK(false == Parser(MakeSpan("+")).ParseSigned(&d));
JXL_CHECK(false == Parser(MakeSpan("-")).ParseSigned(&d));
JXL_CHECK(false == Parser(MakeSpan("A")).ParseSigned(&d));
#endif
JXL_CHECK(true == Parser(MakeSpan("1")).ParseUnsigned(&u));
JXL_CHECK(u == 1);
JXL_CHECK(true == Parser(MakeSpan("32")).ParseUnsigned(&u));
JXL_CHECK(u == 32);
JXL_CHECK(true == Parser(MakeSpan("1")).ParseSigned(&d));
JXL_CHECK(d == 1.0);
JXL_CHECK(true == Parser(MakeSpan("+2")).ParseSigned(&d));
JXL_CHECK(d == 2.0);
JXL_CHECK(true == Parser(MakeSpan("-3")).ParseSigned(&d));
JXL_CHECK(std::abs(d - -3.0) < 1E-15);
JXL_CHECK(true == Parser(MakeSpan("3.141592")).ParseSigned(&d));
JXL_CHECK(std::abs(d - 3.141592) < 1E-15);
JXL_CHECK(true == Parser(MakeSpan("-3.141592")).ParseSigned(&d));
JXL_CHECK(std::abs(d - -3.141592) < 1E-15);
Status PnmParseUnsigned(Bytes str, size_t* v) {
return Parser(str).ParseUnsigned(v);
}
} // namespace extras

4
third_party/jpeg-xl/lib/extras/dec/pnm.h поставляемый
Просмотреть файл

@ -13,12 +13,10 @@
// TODO(janwas): workaround for incorrect Win64 codegen (cause unknown)
#include <hwy/highway.h>
#include <mutex>
#include "lib/extras/dec/color_hints.h"
#include "lib/extras/mmap.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
@ -34,8 +32,6 @@ Status DecodeImagePNM(Span<const uint8_t> bytes, const ColorHints& color_hints,
PackedPixelFile* ppf,
const SizeConstraints* constraints = nullptr);
void TestCodecPNM();
struct HeaderPNM {
size_t xsize;
size_t ysize;

122
third_party/jpeg-xl/lib/extras/enc/apng.cc поставляемый
Просмотреть файл

@ -36,8 +36,7 @@
*
*/
#include <string.h>
#include <cstring>
#include <string>
#include <vector>
@ -62,7 +61,8 @@ class APNGEncoder : public Encoder {
std::vector<JxlPixelFormat> AcceptedFormats() const override {
std::vector<JxlPixelFormat> formats;
for (const uint32_t num_channels : {1, 2, 3, 4}) {
for (const JxlDataType data_type : {JXL_TYPE_UINT8, JXL_TYPE_UINT16}) {
for (const JxlDataType data_type :
{JXL_TYPE_UINT8, JXL_TYPE_UINT16, JXL_TYPE_FLOAT}) {
for (JxlEndianness endianness : {JXL_BIG_ENDIAN, JXL_LITTLE_ENDIAN}) {
formats.push_back(
JxlPixelFormat{num_channels, data_type, endianness, /*align=*/0});
@ -73,17 +73,30 @@ class APNGEncoder : public Encoder {
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
ThreadPool* pool) const override {
// Encode main image frames
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
encoded_image->icc.clear();
encoded_image->bitstreams.resize(1);
return EncodePackedPixelFileToAPNG(ppf, pool,
&encoded_image->bitstreams.front());
JXL_RETURN_IF_ERROR(EncodePackedPixelFileToAPNG(
ppf, pool, &encoded_image->bitstreams.front()));
// Encode extra channels
for (size_t i = 0; i < ppf.extra_channels_info.size(); ++i) {
encoded_image->extra_channel_bitstreams.emplace_back();
auto& ec_bitstreams = encoded_image->extra_channel_bitstreams.back();
ec_bitstreams.emplace_back();
JXL_RETURN_IF_ERROR(EncodePackedPixelFileToAPNG(
ppf, pool, &ec_bitstreams.back(), true, i));
}
return true;
}
private:
Status EncodePackedPixelFileToAPNG(const PackedPixelFile& ppf,
ThreadPool* pool,
std::vector<uint8_t>* bytes) const;
std::vector<uint8_t>* bytes,
bool encode_extra_channels = false,
size_t extra_channel_index = 0) const;
};
void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
@ -127,9 +140,14 @@ class BlobsWriterPNG {
}
private:
// TODO(eustas): use array
static JXL_INLINE char EncodeNibble(const uint8_t nibble) {
JXL_ASSERT(nibble < 16);
return (nibble < 10) ? '0' + nibble : 'a' + nibble - 10;
if (nibble < 16) {
return (nibble < 10) ? '0' + nibble : 'a' + nibble - 10;
} else {
JXL_DEBUG_ABORT("Internal logic error");
return 0;
}
}
static Status EncodeBase16(const std::string& type,
@ -146,7 +164,7 @@ class BlobsWriterPNG {
base16.push_back(EncodeNibble(bytes[i] & 0x0F));
}
base16.push_back('\n');
JXL_ASSERT(base16.length() == base16_size);
JXL_ENSURE(base16.length() == base16_size);
char key[30];
snprintf(key, sizeof(key), "Raw profile type %s", type.c_str());
@ -247,13 +265,10 @@ void MaybeAddCLLi(const JxlColorEncoding& c_enc, const float intensity_target,
png_structp png_ptr, png_infop info_ptr) {
if (c_enc.transfer_function != JXL_TRANSFER_FUNCTION_PQ) return;
const uint32_t max_cll =
const uint32_t max_content_light_level =
static_cast<uint32_t>(10000.f * Clamp1(intensity_target, 0.f, 10000.f));
png_byte chunk_data[8] = {};
chunk_data[0] = (max_cll >> 24) & 0xFF;
chunk_data[1] = (max_cll >> 16) & 0xFF;
chunk_data[2] = (max_cll >> 8) & 0xFF;
chunk_data[3] = max_cll & 0xFF;
png_save_uint_32(chunk_data, max_content_light_level);
// Leave MaxFALL set to 0.
png_unknown_chunk chunk;
memcpy(chunk.name, "cLLi", 5);
@ -266,15 +281,21 @@ void MaybeAddCLLi(const JxlColorEncoding& c_enc, const float intensity_target,
}
Status APNGEncoder::EncodePackedPixelFileToAPNG(
const PackedPixelFile& ppf, ThreadPool* pool,
std::vector<uint8_t>* bytes) const {
size_t xsize = ppf.info.xsize;
size_t ysize = ppf.info.ysize;
bool has_alpha = ppf.info.alpha_bits != 0;
bool is_gray = ppf.info.num_color_channels == 1;
size_t color_channels = ppf.info.num_color_channels;
const PackedPixelFile& ppf, ThreadPool* pool, std::vector<uint8_t>* bytes,
bool encode_extra_channels, size_t extra_channel_index) const {
JxlExtraChannelInfo ec_info{};
if (encode_extra_channels) {
if (ppf.extra_channels_info.size() <= extra_channel_index) {
return JXL_FAILURE("Invalid index for extra channel");
}
ec_info = ppf.extra_channels_info[extra_channel_index].ec_info;
}
bool has_alpha = !encode_extra_channels && (ppf.info.alpha_bits != 0);
bool is_gray = encode_extra_channels || (ppf.info.num_color_channels == 1);
size_t color_channels =
encode_extra_channels ? 1 : ppf.info.num_color_channels;
size_t num_channels = color_channels + (has_alpha ? 1 : 0);
size_t num_samples = num_channels * xsize * ysize;
if (!ppf.info.have_animation && ppf.frames.size() != 1) {
return JXL_FAILURE("Invalid number of frames");
@ -284,11 +305,27 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
size_t anim_chunks = 0;
for (const auto& frame : ppf.frames) {
JXL_RETURN_IF_ERROR(VerifyPackedImage(frame.color, ppf.info));
const PackedImage& color = encode_extra_channels
? frame.extra_channels[extra_channel_index]
: frame.color;
const PackedImage& color = frame.color;
size_t xsize = color.xsize;
size_t ysize = color.ysize;
size_t num_samples = num_channels * xsize * ysize;
uint32_t bits_per_sample = encode_extra_channels ? ec_info.bits_per_sample
: ppf.info.bits_per_sample;
if (!encode_extra_channels) {
JXL_RETURN_IF_ERROR(VerifyPackedImage(color, ppf.info));
} else {
JXL_RETURN_IF_ERROR(VerifyFormat(color.format));
JXL_RETURN_IF_ERROR(VerifyBitDepth(color.format.data_type,
bits_per_sample,
ec_info.exponent_bits_per_sample));
}
const JxlPixelFormat format = color.format;
const uint8_t* in = reinterpret_cast<const uint8_t*>(color.pixels());
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(format.data_type));
size_t data_bits_per_sample = PackedImage::BitsPerChannel(format.data_type);
size_t bytes_per_sample = data_bits_per_sample / 8;
size_t out_bytes_per_sample = bytes_per_sample > 1 ? 2 : 1;
@ -297,28 +334,41 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
std::vector<uint8_t> out(out_size);
if (format.data_type == JXL_TYPE_UINT8) {
if (ppf.info.bits_per_sample < 8) {
float mul = 255.0 / ((1u << ppf.info.bits_per_sample) - 1);
if (bits_per_sample < 8) {
float mul = 255.0 / ((1u << bits_per_sample) - 1);
for (size_t i = 0; i < num_samples; ++i) {
out[i] = static_cast<uint8_t>(in[i] * mul + 0.5);
out[i] = static_cast<uint8_t>(std::lroundf(in[i] * mul));
}
} else {
memcpy(out.data(), in, out_size);
}
} else if (format.data_type == JXL_TYPE_UINT16) {
if (ppf.info.bits_per_sample < 16 ||
format.endianness != JXL_BIG_ENDIAN) {
float mul = 65535.0 / ((1u << ppf.info.bits_per_sample) - 1);
if (bits_per_sample < 16 || format.endianness != JXL_BIG_ENDIAN) {
float mul = 65535.0 / ((1u << bits_per_sample) - 1);
const uint8_t* p_in = in;
uint8_t* p_out = out.data();
for (size_t i = 0; i < num_samples; ++i, p_in += 2, p_out += 2) {
uint32_t val = (format.endianness == JXL_BIG_ENDIAN ? LoadBE16(p_in)
: LoadLE16(p_in));
StoreBE16(static_cast<uint32_t>(val * mul + 0.5), p_out);
StoreBE16(static_cast<uint32_t>(std::lroundf(val * mul)), p_out);
}
} else {
memcpy(out.data(), in, out_size);
}
} else if (format.data_type == JXL_TYPE_FLOAT) {
constexpr float kMul = 65535.0;
const uint8_t* p_in = in;
uint8_t* p_out = out.data();
for (size_t i = 0; i < num_samples;
++i, p_in += sizeof(float), p_out += 2) {
float val =
Clamp1(format.endianness == JXL_BIG_ENDIAN ? LoadBEFloat(p_in)
: format.endianness == JXL_LITTLE_ENDIAN
? LoadLEFloat(p_in)
: *reinterpret_cast<const float*>(p_in),
0.f, 1.f);
StoreBE16(static_cast<uint32_t>(std::lroundf(val * kMul)), p_out);
}
}
png_structp png_ptr;
png_infop info_ptr;
@ -344,7 +394,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
if (count == 0) {
if (count == 0 && !encode_extra_channels) {
if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
MaybeAddCICP(ppf.color_encoding, png_ptr, info_ptr);
if (!ppf.icc.empty()) {
@ -415,10 +465,10 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
size_t p = pos;
while (p + 8 < bytes->size()) {
size_t len = png_get_uint_32(bytes->data() + p);
JXL_ASSERT(bytes->operator[](p + 4) == 'I');
JXL_ASSERT(bytes->operator[](p + 5) == 'D');
JXL_ASSERT(bytes->operator[](p + 6) == 'A');
JXL_ASSERT(bytes->operator[](p + 7) == 'T');
JXL_ENSURE(bytes->operator[](p + 4) == 'I');
JXL_ENSURE(bytes->operator[](p + 5) == 'D');
JXL_ENSURE(bytes->operator[](p + 6) == 'A');
JXL_ENSURE(bytes->operator[](p + 7) == 'T');
fdata.insert(fdata.end(), bytes->data() + p + 8,
bytes->data() + p + 8 + len);
p += len + 12;

Просмотреть файл

@ -134,5 +134,13 @@ std::unique_ptr<Encoder> Encoder::FromExtension(std::string extension) {
return nullptr;
}
std::string ListOfEncodeCodecs() {
std::string list_of_codecs("PPM, PNM, PFM, PAM, PGX");
if (GetAPNGEncoder()) list_of_codecs.append(", PNG, APNG");
if (GetJPEGEncoder()) list_of_codecs.append(", JPEG");
if (GetEXREncoder()) list_of_codecs.append(", EXR");
return list_of_codecs;
}
} // namespace extras
} // namespace jxl

2
third_party/jpeg-xl/lib/extras/enc/encode.h поставляемый
Просмотреть файл

@ -82,6 +82,8 @@ class Encoder {
std::unordered_map<std::string, std::string> options_;
};
std::string ListOfEncodeCodecs();
} // namespace extras
} // namespace jxl

69
third_party/jpeg-xl/lib/extras/enc/jpegli.cc поставляемый
Просмотреть файл

@ -9,11 +9,11 @@
#include <jxl/codestream_header.h>
#include <jxl/types.h>
#include <setjmp.h>
#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <hwy/aligned_allocator.h>
@ -33,7 +33,6 @@
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/enc_xyb.h"
#include "lib/jxl/image.h"
#include "lib/jxl/simd_util.h"
namespace jxl {
@ -54,6 +53,10 @@ Status VerifyInput(const PackedPixelFile& ppf) {
if (ppf.frames.size() != 1) {
return JXL_FAILURE("JPEG input must have exactly one frame.");
}
if (info.num_color_channels != 1 && info.num_color_channels != 3) {
return JXL_FAILURE("Invalid number of color channels %d",
info.num_color_channels);
}
const PackedImage& image = ppf.frames[0].color;
JXL_RETURN_IF_ERROR(Encoder::VerifyImageSize(image, info));
if (image.format.data_type == JXL_TYPE_FLOAT16) {
@ -249,32 +252,48 @@ JpegliEndianness ConvertEndianness(JxlEndianness endianness) {
}
}
void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t len,
float* row_out) {
void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t xsize,
size_t c_out, float* row_out) {
bool is_little_endian =
(format.endianness == JXL_LITTLE_ENDIAN ||
(format.endianness == JXL_NATIVE_ENDIAN && IsLittleEndian()));
static constexpr double kMul8 = 1.0 / 255.0;
static constexpr double kMul16 = 1.0 / 65535.0;
const size_t c_in = format.num_channels;
if (format.data_type == JXL_TYPE_UINT8) {
for (size_t x = 0; x < len; ++x) {
row_out[x] = row_in[x] * kMul8;
for (size_t x = 0; x < xsize; ++x) {
for (size_t c = 0; c < c_out; ++c) {
const size_t ix = c_in * x + c;
row_out[c_out * x + c] = row_in[ix] * kMul8;
}
}
} else if (format.data_type == JXL_TYPE_UINT16 && is_little_endian) {
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadLE16(&row_in[2 * x]) * kMul16;
for (size_t x = 0; x < xsize; ++x) {
for (size_t c = 0; c < c_out; ++c) {
const size_t ix = c_in * x + c;
row_out[c_out * x + c] = LoadLE16(&row_in[2 * ix]) * kMul16;
}
}
} else if (format.data_type == JXL_TYPE_UINT16 && !is_little_endian) {
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadBE16(&row_in[2 * x]) * kMul16;
for (size_t x = 0; x < xsize; ++x) {
for (size_t c = 0; c < c_out; ++c) {
const size_t ix = c_in * x + c;
row_out[c_out * x + c] = LoadBE16(&row_in[2 * ix]) * kMul16;
}
}
} else if (format.data_type == JXL_TYPE_FLOAT && is_little_endian) {
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadLEFloat(&row_in[4 * x]);
for (size_t x = 0; x < xsize; ++x) {
for (size_t c = 0; c < c_out; ++c) {
const size_t ix = c_in * x + c;
row_out[c_out * x + c] = LoadLEFloat(&row_in[4 * ix]);
}
}
} else if (format.data_type == JXL_TYPE_FLOAT && !is_little_endian) {
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadBEFloat(&row_in[4 * x]);
for (size_t x = 0; x < xsize; ++x) {
for (size_t c = 0; c < c_out; ++c) {
const size_t ix = c_in * x + c;
row_out[c_out * x + c] = LoadBEFloat(&row_in[4 * ix]);
}
}
}
}
@ -353,9 +372,6 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
ColorSpaceTransform c_transform(*JxlGetDefaultCms());
ColorEncoding xyb_encoding;
if (jpeg_settings.xyb) {
if (ppf.info.num_color_channels != 3) {
return JXL_FAILURE("Only RGB input is supported in XYB mode.");
}
if (HasICCProfile(jpeg_settings.app_data)) {
return JXL_FAILURE("APP data ICC profile is not supported in XYB mode.");
}
@ -373,13 +389,14 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
// before the call to setjmp().
std::vector<uint8_t> pixels;
unsigned char* output_buffer = nullptr;
unsigned long output_size = 0;
unsigned long output_size = 0; // NOLINT
std::vector<uint8_t> row_bytes;
size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize());
const size_t max_vector_size = MaxVectorSize();
size_t rowlen = RoundUpTo(ppf.info.xsize, max_vector_size);
hwy::AlignedFreeUniquePtr<float[]> xyb_tmp =
hwy::AllocateAligned<float>(6 * rowlen);
hwy::AlignedFreeUniquePtr<float[]> premul_absorb =
hwy::AllocateAligned<float>(MaxVectorSize() * 12);
hwy::AllocateAligned<float>(max_vector_size * 12);
ComputePremulAbsorb(255.0f, premul_absorb.get());
jpeg_compress_struct cinfo;
@ -402,6 +419,8 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
cinfo.input_components == 1 ? JCS_GRAYSCALE : JCS_RGB;
if (jpeg_settings.xyb) {
jpegli_set_xyb_mode(&cinfo);
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
} else if (jpeg_settings.use_std_quant_tables) {
jpegli_use_standard_quant_tables(&cinfo);
}
@ -435,6 +454,10 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
cinfo.comp_info[i].h_samp_factor = 1;
cinfo.comp_info[i].v_samp_factor = 1;
}
} else if (!jpeg_settings.xyb) {
// Default is no chroma subsampling.
cinfo.comp_info[0].h_samp_factor = 1;
cinfo.comp_info[0].v_samp_factor = 1;
}
jpegli_enable_adaptive_quantization(
&cinfo, TO_JXL_BOOL(jpeg_settings.use_adaptive_quantization));
@ -477,8 +500,8 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
float* dst_buf = c_transform.BufDst(0);
for (size_t y = 0; y < image.ysize; ++y) {
// convert to float
ToFloatRow(&pixels[y * image.stride], image.format, 3 * image.xsize,
src_buf);
ToFloatRow(&pixels[y * image.stride], image.format, image.xsize,
info.num_color_channels, src_buf);
// convert to linear srgb
if (!c_transform.Run(0, src_buf, dst_buf, image.xsize)) {
return false;
@ -517,6 +540,8 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
}
} else {
for (size_t y = 0; y < info.ysize; ++y) {
JXL_RETURN_IF_ERROR(
PackedImage::ValidateDataType(image.format.data_type));
int bytes_per_channel =
PackedImage::BitsPerChannel(image.format.data_type) / 8;
int bytes_per_pixel = cinfo.num_components * bytes_per_channel;

13
third_party/jpeg-xl/lib/extras/enc/jpg.cc поставляемый
Просмотреть файл

@ -6,26 +6,23 @@
#include "lib/extras/enc/jpg.h"
#if JPEGXL_ENABLE_JPEG
#include <jpeglib.h>
#include <setjmp.h>
#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#endif
#include <stdint.h>
#include <algorithm>
#include <array>
#include <cmath>
#include <cstdint>
#include <fstream>
#include <iterator>
#include <memory>
#include <numeric>
#include <sstream>
#include <utility>
#include <vector>
#include "lib/extras/exif.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/sanitizers.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
#if JPEGXL_ENABLE_SJPEG
#include "sjpeg.h"
#include "sjpegi.h"
@ -276,7 +273,7 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
unsigned char* buffer = nullptr;
unsigned long size = 0;
unsigned long size = 0; // NOLINT
jpeg_mem_dest(&cinfo, &buffer, &size);
cinfo.image_width = image.xsize;
cinfo.image_height = image.ysize;
@ -476,7 +473,7 @@ Status EncodeWithSJpeg(const PackedImage& image, const JxlBasicInfo& info,
param.tolerance = params.search_tolerance;
param.qmin = params.search_q_min;
param.qmax = params.search_q_max;
hook.reset(new MySearchHook());
hook = jxl::make_unique<MySearchHook>();
hook->ReadBaseTables(params.custom_base_quant_fn);
hook->q_start = params.search_q_start;
hook->q_precision = params.search_q_precision;

33
third_party/jpeg-xl/lib/extras/enc/jxl.cc поставляемый
Просмотреть файл

@ -5,10 +5,18 @@
#include "lib/extras/enc/jxl.h"
#include <jxl/codestream_header.h>
#include <jxl/encode.h>
#include <jxl/encode_cxx.h>
#include <jxl/types.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <vector>
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/exif.h"
namespace jxl {
@ -112,7 +120,7 @@ bool ReadCompressedOutput(JxlEncoder* enc, std::vector<uint8_t>* compressed) {
bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
const std::vector<uint8_t>* jpeg_bytes,
std::vector<uint8_t>* compressed) {
auto encoder = JxlEncoderMake(/*memory_manager=*/nullptr);
auto encoder = JxlEncoderMake(params.memory_manager);
JxlEncoder* enc = encoder.get();
if (params.allow_expert_options) {
@ -153,7 +161,8 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
bool has_jpeg_bytes = (jpeg_bytes != nullptr);
bool use_boxes = !ppf.metadata.exif.empty() || !ppf.metadata.xmp.empty() ||
!ppf.metadata.jumbf.empty() || !ppf.metadata.iptc.empty();
!ppf.metadata.jhgm.empty() || !ppf.metadata.jumbf.empty() ||
!ppf.metadata.iptc.empty();
bool use_container = params.use_container || use_boxes ||
(has_jpeg_bytes && params.jpeg_store_metadata);
@ -202,7 +211,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
fprintf(stderr,
"JPEG bitstream reconstruction data could not be created. "
"Possibly there is too much tail data.\n"
"Try using --jpeg_store_metadata 0, to losslessly "
"Try using --allow_jpeg_reconstruction 0, to losslessly "
"recompress the JPEG image data without bitstream "
"reconstruction data.\n");
} else {
@ -223,7 +232,14 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
std::max<uint32_t>(num_alpha_channels, ppf.info.num_extra_channels);
basic_info.num_color_channels = ppf.info.num_color_channels;
const bool lossless = (params.distance == 0);
basic_info.uses_original_profile = TO_JXL_BOOL(lossless);
auto non_perceptual_option = std::find_if(
params.options.begin(), params.options.end(), [](JXLOption option) {
return option.id ==
JXL_ENC_FRAME_SETTING_DISABLE_PERCEPTUAL_HEURISTICS;
});
const bool non_perceptual = non_perceptual_option != params.options.end() &&
non_perceptual_option->ival == 1;
basic_info.uses_original_profile = TO_JXL_BOOL(lossless || non_perceptual);
if (params.override_bitdepth != 0) {
basic_info.bits_per_sample = params.override_bitdepth;
basic_info.exponent_bits_per_sample =
@ -245,7 +261,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
if (JXL_ENC_SUCCESS !=
JxlEncoderSetFrameBitDepth(settings, &params.input_bitdepth)) {
JxlEncoderSetFrameBitDepth(settings, &ppf.input_bitdepth)) {
fprintf(stderr, "JxlEncoderSetFrameBitDepth() failed.\n");
return false;
}
@ -291,10 +307,9 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
const char* type;
const std::vector<uint8_t>& bytes;
} boxes[] = {
{"Exif", exif_with_offset},
{"xml ", ppf.metadata.xmp},
{"jumb", ppf.metadata.jumbf},
{"xml ", ppf.metadata.iptc},
{"Exif", exif_with_offset}, {"xml ", ppf.metadata.xmp},
{"jumb", ppf.metadata.jumbf}, {"xml ", ppf.metadata.iptc},
{"jhgm", ppf.metadata.jhgm},
};
for (auto box : boxes) {
if (!box.bytes.empty()) {

19
third_party/jpeg-xl/lib/extras/enc/jxl.h поставляемый
Просмотреть файл

@ -7,11 +7,13 @@
#define LIB_EXTRAS_ENC_JXL_H_
#include <jxl/encode.h>
#include <jxl/memory_manager.h>
#include <jxl/parallel_runner.h>
#include <jxl/thread_parallel_runner.h>
#include <jxl/types.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
#include <vector>
#include "lib/extras/packed_image.h"
@ -36,32 +38,41 @@ struct JXLOption {
struct JXLCompressParams {
std::vector<JXLOption> options;
// Target butteraugli distance, 0.0 means lossless.
float distance = 1.0f;
float alpha_distance = 0.0f;
// If set to true, forces container mode.
bool use_container = false;
// Whether to enable/disable byte-exact jpeg reconstruction for jpeg inputs.
bool jpeg_store_metadata = true;
bool jpeg_strip_exif = false;
bool jpeg_strip_xmp = false;
bool jpeg_strip_jumbf = false;
// Whether to create brob boxes.
bool compress_boxes = true;
// Upper bound on the intensity level present in the image in nits (zero means
// that the library chooses a default).
float intensity_target = 0;
int already_downsampled = 1;
int upsampling_mode = -1;
// Overrides for bitdepth, codestream level and alpha premultiply.
size_t override_bitdepth = 0;
int32_t codestream_level = -1;
int32_t premultiply = -1;
// Override input buffer interpretation.
JxlBitDepth input_bitdepth = {JXL_BIT_DEPTH_FROM_PIXEL_FORMAT, 0, 0};
// If runner_opaque is set, the decoder uses this parallel runner.
// If runner_opaque is set, the encoder uses this parallel runner.
JxlParallelRunner runner = JxlThreadParallelRunner;
void* runner_opaque = nullptr;
// If memory_manager is set, encoder uses it.
JxlMemoryManager* memory_manager = nullptr;
JxlEncoderOutputProcessor output_processor = {};
JxlDebugImageCallback debug_image = nullptr;
void* debug_image_opaque = nullptr;

4
third_party/jpeg-xl/lib/extras/enc/npy.cc поставляемый
Просмотреть файл

@ -254,14 +254,14 @@ bool WriteFrameToNPYArray(size_t xsize, size_t ysize, const PackedFrame& frame,
size_t sample_size = color.pixel_stride();
size_t offset = y * color.stride + x * sample_size;
uint8_t* pixels = reinterpret_cast<uint8_t*>(color.pixels());
JXL_ASSERT(offset + sample_size <= color.pixels_size);
JXL_ENSURE(offset + sample_size <= color.pixels_size);
Append(out, pixels + offset, sample_size);
}
for (const auto& ec : frame.extra_channels) {
size_t sample_size = ec.pixel_stride();
size_t offset = y * ec.stride + x * sample_size;
uint8_t* pixels = reinterpret_cast<uint8_t*>(ec.pixels());
JXL_ASSERT(offset + sample_size <= ec.pixels_size);
JXL_ENSURE(offset + sample_size <= ec.pixels_size);
Append(out, pixels + offset, sample_size);
}
}

4
third_party/jpeg-xl/lib/extras/enc/pgx.cc поставляемый
Просмотреть файл

@ -6,7 +6,8 @@
#include "lib/extras/enc/pgx.h"
#include <jxl/codestream_header.h>
#include <string.h>
#include <cstring>
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/byte_order.h"
@ -49,6 +50,7 @@ Status EncodeImagePGX(const PackedFrame& frame, const JxlBasicInfo& info,
const PackedImage& color = frame.color;
const JxlPixelFormat format = color.format;
const uint8_t* in = reinterpret_cast<const uint8_t*>(color.pixels());
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(format.data_type));
size_t data_bits_per_sample = PackedImage::BitsPerChannel(format.data_type);
size_t bytes_per_sample = data_bits_per_sample / kBitsPerByte;
size_t num_samples = info.xsize * info.ysize;

30
third_party/jpeg-xl/lib/extras/enc/pnm.cc поставляемый
Просмотреть файл

@ -5,28 +5,23 @@
#include "lib/extras/enc/pnm.h"
#include <string.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include <vector>
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/printf_macros.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/dec_external_image.h"
#include "lib/jxl/enc_external_image.h"
#include "lib/jxl/enc_image_bundle.h"
#include "lib/jxl/fields.h" // AllDefault
#include "lib/jxl/image.h"
#include "lib/jxl/image_bundle.h"
namespace jxl {
namespace extras {
namespace {
constexpr size_t kMaxHeaderSize = 200;
constexpr size_t kMaxHeaderSize = 2000;
class BasePNMEncoder : public Encoder {
public:
@ -87,8 +82,8 @@ class PNMEncoder : public BasePNMEncoder {
}
private:
Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
std::vector<uint8_t>* bytes) const {
static Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
std::vector<uint8_t>* bytes) {
uint32_t maxval = (1u << bits_per_sample) - 1;
char type = image.format.num_channels == 1 ? '5' : '6';
char header[kMaxHeaderSize];
@ -161,8 +156,8 @@ class PFMEncoder : public BasePNMEncoder {
}
private:
Status EncodeImage(const PackedImage& image,
std::vector<uint8_t>* bytes) const {
static Status EncodeImage(const PackedImage& image,
std::vector<uint8_t>* bytes) {
char type = image.format.num_channels == 1 ? 'f' : 'F';
double scale = image.format.endianness == JXL_LITTLE_ENDIAN ? -1.0 : 1.0;
char header[kMaxHeaderSize];
@ -262,6 +257,7 @@ class PAMEncoder : public BasePNMEncoder {
reinterpret_cast<const uint8_t*>(frame.extra_channels[i].pixels());
}
uint8_t* out = bytes->data() + pos;
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(color.format.data_type));
size_t pwidth = PackedImage::BitsPerChannel(color.format.data_type) / 8;
for (size_t y = 0; y < color.ysize; ++y) {
for (size_t x = 0; x < color.xsize; ++x) {
@ -299,6 +295,10 @@ class PAMEncoder : public BasePNMEncoder {
return std::string("CFA");
case JXL_CHANNEL_THERMAL:
return std::string("Thermal");
case JXL_CHANNEL_UNKNOWN:
return std::string("Unknown");
case JXL_CHANNEL_OPTIONAL:
return std::string("Optional");
default:
return std::string("UNKNOWN");
}

231
third_party/jpeg-xl/lib/extras/gain_map.cc поставляемый Normal file
Просмотреть файл

@ -0,0 +1,231 @@
// 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/gain_map.h>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_bit_reader.h"
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_bit_writer.h"
#include "lib/jxl/fields.h"
#include "lib/jxl/memory_manager_internal.h"
namespace {
template <size_t N>
class FixedSizeMemoryManager {
public:
FixedSizeMemoryManager() = default;
JxlMemoryManager* memory_manager() { return &manager_; }
private:
static void* FixedSizeMemoryManagerAlloc(void* opaque, size_t capacity) {
auto manager = static_cast<FixedSizeMemoryManager<N>*>(opaque);
if (capacity > N + jxl::memory_manager_internal::kAlias) {
return nullptr;
}
return manager->memory_;
}
static void FixedSizeMemoryManagerFree(void* opaque, void* pointer) {}
uint8_t memory_[N + jxl::memory_manager_internal::kAlias];
JxlMemoryManager manager_ = {
/*opaque=*/this,
/*alloc=*/&FixedSizeMemoryManagerAlloc,
/*free=*/&FixedSizeMemoryManagerFree,
};
};
} // namespace
JXL_BOOL JxlGainMapGetBundleSize(const JxlGainMapBundle* map_bundle,
size_t* bundle_size) {
if (map_bundle == nullptr) return JXL_FALSE;
jxl::ColorEncoding internal_color_encoding;
size_t color_encoding_size = 0;
size_t extension_bits = 0;
if (map_bundle->has_color_encoding) {
JXL_RETURN_IF_ERROR(
internal_color_encoding.FromExternal(map_bundle->color_encoding));
if (!jxl::Bundle::CanEncode(internal_color_encoding, &extension_bits,
&color_encoding_size)) {
return JXL_FALSE;
}
}
*bundle_size =
1 + // size of jhgm_version
2 + // size_of gain_map_metadata_size
map_bundle->gain_map_metadata_size + // size of gain_map_metadata
1 + // size of color_encoding_size
jxl::DivCeil(color_encoding_size, 8) + // size of the color_encoding
4 + // size of compressed_icc_size
map_bundle->alt_icc_size + // size of compressed_icc
map_bundle->gain_map_size; // size of gain map
return JXL_TRUE;
}
JXL_BOOL JxlGainMapWriteBundle(const JxlGainMapBundle* map_bundle,
uint8_t* output_buffer,
size_t output_buffer_size,
size_t* bytes_written) {
if (map_bundle == nullptr) return JXL_FALSE;
uint8_t jhgm_version = map_bundle->jhgm_version;
FixedSizeMemoryManager<sizeof(jxl::ColorEncoding)> memory_manager;
jxl::ColorEncoding internal_color_encoding;
jxl::BitWriter color_encoding_writer(memory_manager.memory_manager());
if (map_bundle->has_color_encoding) {
JXL_RETURN_IF_ERROR(
internal_color_encoding.FromExternal(map_bundle->color_encoding));
if (!jxl::Bundle::Write(internal_color_encoding, &color_encoding_writer,
jxl::LayerType::Header, nullptr)) {
return JXL_FALSE;
}
}
color_encoding_writer.ZeroPadToByte();
uint64_t cursor = 0;
uint64_t next_cursor = 0;
#define SAFE_CURSOR_UPDATE(n) \
do { \
cursor = next_cursor; \
if (!jxl::SafeAdd(cursor, n, next_cursor) || \
next_cursor > output_buffer_size) { \
return JXL_FALSE; \
} \
} while (false)
SAFE_CURSOR_UPDATE(1);
memcpy(output_buffer + cursor, &jhgm_version, 1);
SAFE_CURSOR_UPDATE(2);
StoreBE16(map_bundle->gain_map_metadata_size, output_buffer + cursor);
SAFE_CURSOR_UPDATE(map_bundle->gain_map_metadata_size);
memcpy(output_buffer + cursor, map_bundle->gain_map_metadata,
map_bundle->gain_map_metadata_size);
jxl::Bytes bytes = color_encoding_writer.GetSpan();
uint8_t color_enc_size = static_cast<uint8_t>(bytes.size());
if (color_enc_size != bytes.size()) return JXL_FALSE;
SAFE_CURSOR_UPDATE(1);
memcpy(output_buffer + cursor, &color_enc_size, 1);
SAFE_CURSOR_UPDATE(color_enc_size);
memcpy(output_buffer + cursor, bytes.data(), color_enc_size);
SAFE_CURSOR_UPDATE(4);
StoreBE32(map_bundle->alt_icc_size, output_buffer + cursor);
SAFE_CURSOR_UPDATE(map_bundle->alt_icc_size);
memcpy(output_buffer + cursor, map_bundle->alt_icc, map_bundle->alt_icc_size);
SAFE_CURSOR_UPDATE(map_bundle->gain_map_size);
memcpy(output_buffer + cursor, map_bundle->gain_map,
map_bundle->gain_map_size);
#undef SAFE_CURSOR_UPDATE
cursor = next_cursor;
if (bytes_written != nullptr)
*bytes_written = cursor; // Ensure size_t compatibility
return cursor == output_buffer_size ? JXL_TRUE : JXL_FALSE;
}
JXL_BOOL JxlGainMapReadBundle(JxlGainMapBundle* map_bundle,
const uint8_t* input_buffer,
const size_t input_buffer_size,
size_t* bytes_read) {
if (map_bundle == nullptr || input_buffer == nullptr ||
input_buffer_size == 0) {
return JXL_FALSE;
}
uint64_t cursor = 0;
uint64_t next_cursor = 0;
#define SAFE_CURSOR_UPDATE(n) \
do { \
cursor = next_cursor; \
if (!jxl::SafeAdd(cursor, n, next_cursor) || \
next_cursor > input_buffer_size) { \
return JXL_FALSE; \
} \
} while (false)
// Read the version byte
SAFE_CURSOR_UPDATE(1);
map_bundle->jhgm_version = input_buffer[cursor];
// Read gain_map_metadata_size
SAFE_CURSOR_UPDATE(2);
uint16_t gain_map_metadata_size = LoadBE16(input_buffer + cursor);
SAFE_CURSOR_UPDATE(gain_map_metadata_size);
map_bundle->gain_map_metadata_size = gain_map_metadata_size;
map_bundle->gain_map_metadata = input_buffer + cursor;
// Read compressed_color_encoding_size
SAFE_CURSOR_UPDATE(1);
uint8_t compressed_color_encoding_size;
memcpy(&compressed_color_encoding_size, input_buffer + cursor, 1);
map_bundle->has_color_encoding = (compressed_color_encoding_size > 0);
if (map_bundle->has_color_encoding) {
SAFE_CURSOR_UPDATE(compressed_color_encoding_size);
// Decode color encoding
jxl::Span<const uint8_t> color_encoding_span(
input_buffer + cursor, compressed_color_encoding_size);
jxl::BitReader color_encoding_reader(color_encoding_span);
jxl::ColorEncoding internal_color_encoding;
if (!jxl::Bundle::Read(&color_encoding_reader, &internal_color_encoding)) {
return JXL_FALSE;
}
JXL_RETURN_IF_ERROR(color_encoding_reader.Close());
map_bundle->color_encoding = internal_color_encoding.ToExternal();
}
// Read compressed_icc_size
SAFE_CURSOR_UPDATE(4);
uint32_t compressed_icc_size = LoadBE32(input_buffer + cursor);
SAFE_CURSOR_UPDATE(compressed_icc_size);
map_bundle->alt_icc_size = compressed_icc_size;
map_bundle->alt_icc = input_buffer + cursor;
// Calculate remaining bytes for gain map
cursor = next_cursor;
// This calculation is guaranteed not to underflow because `cursor` is always
// updated to a position within or at the end of `input_buffer` (not beyond).
// Thus, subtracting `cursor` from `input_buffer_size` (the total size of the
// buffer) will always result in a non-negative integer representing the
// remaining buffer size.
map_bundle->gain_map_size = input_buffer_size - cursor;
SAFE_CURSOR_UPDATE(map_bundle->gain_map_size);
map_bundle->gain_map = input_buffer + cursor;
#undef SAFE_CURSOR_UPDATE
cursor = next_cursor;
if (bytes_read != nullptr) {
*bytes_read = cursor;
}
return JXL_TRUE;
}

173
third_party/jpeg-xl/lib/extras/gain_map_test.cc поставляемый Normal file
Просмотреть файл

@ -0,0 +1,173 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "jxl/gain_map.h"
#include <jxl/color_encoding.h>
#include <jxl/encode.h>
#include <jxl/types.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include <vector>
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testing.h"
namespace {
std::vector<uint8_t> GoldenTestGainMap(bool has_icc, bool has_color_encoding) {
// Define the parts of the gain map
uint8_t jhgm_version = 0x00;
std::vector<uint8_t> gain_map_metadata_size = {0x00, 0x58}; // 88 in decimal
// TODO(firsching): Replace with more realistic data
std::string first_placeholder =
"placeholder gain map metadata, fill with actual example after (ISO "
"21496-1) is finalized";
uint8_t color_encoding_size = has_color_encoding ? 3 : 0;
std::vector<uint8_t> color_encoding = {0x50, 0xb4, 0x00};
std::vector<uint8_t> icc_size = {0x00, 0x00, 0x00, 0x00};
if (has_icc) {
icc_size = {0x00, 0x00, 0x00, 0x88}; // 136 in decimal
}
std::vector<uint8_t> icc_data = jxl::test::GetCompressedIccTestProfile();
std::string second_placeholder =
"placeholder for an actual naked JPEG XL codestream";
// Assemble the gain map
std::vector<uint8_t> gain_map;
gain_map.push_back(jhgm_version);
gain_map.insert(gain_map.end(), gain_map_metadata_size.begin(),
gain_map_metadata_size.end());
gain_map.insert(gain_map.end(), first_placeholder.begin(),
first_placeholder.end());
gain_map.push_back(color_encoding_size);
if (has_color_encoding) {
gain_map.insert(gain_map.end(), color_encoding.begin(),
color_encoding.end());
}
gain_map.insert(gain_map.end(), icc_size.begin(), icc_size.end());
if (has_icc) {
gain_map.insert(gain_map.end(), icc_data.begin(), icc_data.end());
}
gain_map.insert(gain_map.end(), second_placeholder.begin(),
second_placeholder.end());
return gain_map;
}
} // namespace
namespace jxl {
namespace {
struct GainMapTestParams {
bool has_color_encoding;
std::vector<uint8_t> icc_data;
};
class GainMapTest : public ::testing::TestWithParam<GainMapTestParams> {};
TEST_P(GainMapTest, GainMapRoundtrip) {
size_t bundle_size;
const GainMapTestParams& params = GetParam();
std::vector<uint8_t> golden_gain_map =
GoldenTestGainMap(!params.icc_data.empty(), params.has_color_encoding);
JxlGainMapBundle orig_bundle;
// Initialize the bundle with some test data
orig_bundle.jhgm_version = 0;
const char* metadata_str =
"placeholder gain map metadata, fill with actual example after (ISO "
"21496-1) is finalized";
std::vector<uint8_t> gain_map_metadata(metadata_str,
metadata_str + strlen(metadata_str));
orig_bundle.gain_map_metadata_size = gain_map_metadata.size();
orig_bundle.gain_map_metadata = gain_map_metadata.data();
// Use the ICC profile from the parameter
orig_bundle.has_color_encoding = TO_JXL_BOOL(params.has_color_encoding);
if (orig_bundle.has_color_encoding) {
JxlColorEncoding color_encoding = {};
JxlColorEncodingSetToLinearSRGB(&color_encoding, /*is_gray=*/JXL_FALSE);
orig_bundle.color_encoding = color_encoding;
}
std::vector<uint8_t> alt_icc(params.icc_data.begin(), params.icc_data.end());
orig_bundle.alt_icc = alt_icc.data();
orig_bundle.alt_icc_size = alt_icc.size();
const char* gain_map_str =
"placeholder for an actual naked JPEG XL codestream";
std::vector<uint8_t> gain_map(gain_map_str,
gain_map_str + strlen(gain_map_str));
orig_bundle.gain_map_size = gain_map.size();
orig_bundle.gain_map = gain_map.data();
ASSERT_TRUE(JxlGainMapGetBundleSize(&orig_bundle, &bundle_size));
EXPECT_EQ(bundle_size, golden_gain_map.size());
std::vector<uint8_t> buffer(bundle_size);
size_t bytes_written;
ASSERT_TRUE(JxlGainMapWriteBundle(&orig_bundle, buffer.data(), buffer.size(),
&bytes_written));
EXPECT_EQ(bytes_written, bundle_size);
EXPECT_EQ(buffer[0], orig_bundle.jhgm_version);
EXPECT_EQ(buffer.size(), golden_gain_map.size());
EXPECT_TRUE(
std::equal(buffer.begin(), buffer.end(), golden_gain_map.begin()));
JxlGainMapBundle output_bundle;
size_t bytes_read;
ASSERT_TRUE(JxlGainMapReadBundle(&output_bundle, buffer.data(), buffer.size(),
&bytes_read));
EXPECT_EQ(output_bundle.gain_map_size, orig_bundle.gain_map_size);
EXPECT_EQ(output_bundle.gain_map_metadata_size,
orig_bundle.gain_map_metadata_size);
EXPECT_EQ(output_bundle.alt_icc_size, orig_bundle.alt_icc_size);
EXPECT_EQ(output_bundle.has_color_encoding, params.has_color_encoding);
EXPECT_EQ(output_bundle.jhgm_version, orig_bundle.jhgm_version);
std::vector<uint8_t> output_gain_map_metadata(
output_bundle.gain_map_metadata,
output_bundle.gain_map_metadata + output_bundle.gain_map_metadata_size);
std::vector<uint8_t> output_alt_icc(
output_bundle.alt_icc,
output_bundle.alt_icc + output_bundle.alt_icc_size);
std::vector<uint8_t> output_gain_map(
output_bundle.gain_map,
output_bundle.gain_map + output_bundle.gain_map_size);
EXPECT_TRUE(std::equal(output_gain_map_metadata.begin(),
output_gain_map_metadata.end(),
gain_map_metadata.begin()));
EXPECT_TRUE(std::equal(output_alt_icc.begin(), output_alt_icc.end(),
alt_icc.begin()));
EXPECT_TRUE(std::equal(output_gain_map.begin(), output_gain_map.end(),
gain_map.begin()));
}
JXL_GTEST_INSTANTIATE_TEST_SUITE_P(
GainMapTestCases, GainMapTest,
::testing::Values(
GainMapTestParams{true, std::vector<uint8_t>()},
GainMapTestParams{true, test::GetCompressedIccTestProfile()},
GainMapTestParams{false, test::GetCompressedIccTestProfile()},
GainMapTestParams{false, std::vector<uint8_t>()}),
[](const testing::TestParamInfo<GainMapTest::ParamType>& info) {
std::string name =
"HasColorEncoding" + std::to_string(info.param.has_color_encoding);
name += "ICCSize" + std::to_string(info.param.icc_data.size());
return name;
});
} // namespace
} // namespace jxl

42
third_party/jpeg-xl/lib/extras/hlg.cc поставляемый
Просмотреть файл

@ -26,27 +26,27 @@ Status HlgOOTF(ImageBundle* ib, const float gamma, ThreadPool* pool) {
JXL_RETURN_IF_ERROR(
ib->TransformTo(linear_rec2020, *JxlGetDefaultCms(), pool));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, ib->ysize(), ThreadPool::NoInit,
[&](const int y, const int thread) {
float* const JXL_RESTRICT rows[3] = {ib->color()->PlaneRow(0, y),
ib->color()->PlaneRow(1, y),
ib->color()->PlaneRow(2, y)};
for (size_t x = 0; x < ib->xsize(); ++x) {
float& red = rows[0][x];
float& green = rows[1][x];
float& blue = rows[2][x];
const float luminance =
0.2627f * red + 0.6780f * green + 0.0593f * blue;
const float ratio = std::pow(luminance, gamma - 1);
if (std::isfinite(ratio)) {
red *= ratio;
green *= ratio;
blue *= ratio;
}
}
},
"HlgOOTF"));
const auto process_row = [&](const int y, const int thread) -> Status {
float* const JXL_RESTRICT rows[3] = {ib->color()->PlaneRow(0, y),
ib->color()->PlaneRow(1, y),
ib->color()->PlaneRow(2, y)};
for (size_t x = 0; x < ib->xsize(); ++x) {
float& red = rows[0][x];
float& green = rows[1][x];
float& blue = rows[2][x];
const float luminance = 0.2627f * red + 0.6780f * green + 0.0593f * blue;
const float ratio = std::pow(luminance, gamma - 1);
if (std::isfinite(ratio)) {
red *= ratio;
green *= ratio;
blue *= ratio;
}
}
return true;
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, ib->ysize(), ThreadPool::NoInit,
process_row, "HlgOOTF"));
return true;
}

34
third_party/jpeg-xl/lib/extras/jpegli_test.cc поставляемый
Просмотреть файл

@ -9,7 +9,6 @@
#include <jxl/color_encoding.h>
#include <jxl/types.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
@ -40,9 +39,9 @@ namespace jxl {
namespace extras {
namespace {
using test::Butteraugli3Norm;
using test::ButteraugliDistance;
using test::TestImage;
using ::jxl::test::Butteraugli3Norm;
using ::jxl::test::ButteraugliDistance;
using ::jxl::test::TestImage;
Status ReadTestImage(const std::string& pathname, PackedPixelFile* ppf) {
const std::vector<uint8_t> encoded = jxl::test::ReadTestData(pathname);
@ -93,7 +92,7 @@ Status EncodeWithLibjpeg(const PackedPixelFile& ppf, int quality,
std::string Description(const JxlColorEncoding& color_encoding) {
ColorEncoding c_enc;
JXL_CHECK(c_enc.FromExternal(color_encoding));
EXPECT_TRUE(c_enc.FromExternal(color_encoding));
return Description(c_enc);
}
@ -156,8 +155,8 @@ TEST(JpegliTest, JpegliXYBEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.45f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.45f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
}
TEST(JpegliTest, JpegliDecodeTestLargeSmoothArea) {
@ -165,9 +164,10 @@ TEST(JpegliTest, JpegliDecodeTestLargeSmoothArea) {
TestImage t;
const size_t xsize = 2070;
const size_t ysize = 1063;
t.SetDimensions(xsize, ysize).SetChannels(3);
ASSERT_TRUE(t.SetDimensions(xsize, ysize));
ASSERT_TRUE(t.SetChannels(3));
t.SetAllBitDepths(8).SetEndianness(JXL_NATIVE_ENDIAN);
TestImage::Frame frame = t.AddFrame();
JXL_TEST_ASSIGN_OR_DIE(TestImage::Frame frame, t.AddFrame());
frame.RandomFill();
// Create a large smooth area in the top half of the image. This is to test
// that the bias statistics calculation can handle many blocks with all-zero
@ -175,7 +175,7 @@ TEST(JpegliTest, JpegliDecodeTestLargeSmoothArea) {
for (size_t y = 0; y < ysize / 2; ++y) {
for (size_t x = 0; x < xsize; ++x) {
for (size_t c = 0; c < 3; ++c) {
frame.SetValue(y, x, c, 0.5f);
ASSERT_TRUE(frame.SetValue(y, x, c, 0.5f));
}
}
}
@ -205,8 +205,8 @@ TEST(JpegliTest, JpegliYUVEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.7f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.7f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
}
TEST(JpegliTest, JpegliYUVChromaSubsamplingEncodeTest) {
@ -247,15 +247,15 @@ TEST(JpegliTest, JpegliYUVEncodeTestNoAq) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.85f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.25f));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.85f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.25f);
}
TEST(JpegliTest, JpegliHDRRoundtripTest) {
std::string testimage = "jxl/hdr_room.png";
PackedPixelFile ppf_in;
ASSERT_TRUE(ReadTestImage(testimage, &ppf_in));
EXPECT_EQ("RGB_D65_202_Rel_HLG", Description(ppf_in.color_encoding));
EXPECT_EQ("Rec2100HLG", Description(ppf_in.color_encoding));
EXPECT_EQ(16, ppf_in.info.bits_per_sample);
std::vector<uint8_t> compressed;
@ -267,8 +267,8 @@ TEST(JpegliTest, JpegliHDRRoundtripTest) {
JpegDecompressParams dparams;
dparams.output_data_type = JXL_TYPE_UINT16;
ASSERT_TRUE(DecodeJpeg(compressed, dparams, nullptr, &ppf_out));
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(2.95f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.05f));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 2.95f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.05f);
}
TEST(JpegliTest, JpegliSetAppData) {

15
third_party/jpeg-xl/lib/extras/metrics.cc поставляемый
Просмотреть файл

@ -16,6 +16,7 @@
#include <hwy/highway.h>
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
HWY_BEFORE_NAMESPACE();
@ -125,23 +126,27 @@ double ComputeDistanceP(const ImageF& distmap, const ButteraugliParams& params,
void ComputeSumOfSquares(const ImageBundle& ib1, const ImageBundle& ib2,
const JxlCmsInterface& cms, double sum_of_squares[3]) {
sum_of_squares[0] = sum_of_squares[1] = sum_of_squares[2] =
std::numeric_limits<double>::max();
// Convert to sRGB - closer to perception than linear.
const Image3F* srgb1 = &ib1.color();
Image3F copy1;
if (!ib1.IsSRGB()) {
JXL_CHECK(
ib1.CopyTo(Rect(ib1), ColorEncoding::SRGB(ib1.IsGray()), cms, &copy1));
if (!ib1.CopyTo(Rect(ib1), ColorEncoding::SRGB(ib1.IsGray()), cms, &copy1))
return;
srgb1 = &copy1;
}
const Image3F* srgb2 = &ib2.color();
Image3F copy2;
if (!ib2.IsSRGB()) {
JXL_CHECK(
ib2.CopyTo(Rect(ib2), ColorEncoding::SRGB(ib2.IsGray()), cms, &copy2));
if (!ib2.CopyTo(Rect(ib2), ColorEncoding::SRGB(ib2.IsGray()), cms, &copy2))
return;
srgb2 = &copy2;
}
JXL_CHECK(SameSize(*srgb1, *srgb2));
if (!SameSize(*srgb1, *srgb2)) return;
sum_of_squares[0] = sum_of_squares[1] = sum_of_squares[2] = 0.0;
// TODO(veluca): SIMD.
float yuvmatrix[3][3] = {{0.299, 0.587, 0.114},

8
third_party/jpeg-xl/lib/extras/mmap.h поставляемый
Просмотреть файл

@ -18,10 +18,10 @@ class MemoryMappedFile {
static StatusOr<MemoryMappedFile> Init(const char* path);
const uint8_t* data() const;
size_t size() const;
MemoryMappedFile();
~MemoryMappedFile();
MemoryMappedFile(MemoryMappedFile&&) noexcept;
MemoryMappedFile& operator=(MemoryMappedFile&&) noexcept;
MemoryMappedFile(); // NOLINT
~MemoryMappedFile(); // NOLINT
MemoryMappedFile(MemoryMappedFile&&) noexcept; // NOLINT
MemoryMappedFile& operator=(MemoryMappedFile&&) noexcept; // NOLINT
private:
std::unique_ptr<MemoryMappedFileImpl> impl_;

61
third_party/jpeg-xl/lib/extras/packed_image.h поставляемый
Просмотреть файл

@ -12,22 +12,19 @@
#include <jxl/codestream_header.h>
#include <jxl/encode.h>
#include <jxl/types.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <vector>
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/c_callback_support.h"
#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
@ -37,11 +34,18 @@ namespace extras {
// Class representing an interleaved image with a bunch of channels.
class PackedImage {
public:
PackedImage(size_t xsize, size_t ysize, const JxlPixelFormat& format)
: PackedImage(xsize, ysize, format, CalcStride(format, xsize)) {}
static StatusOr<PackedImage> Create(size_t xsize, size_t ysize,
const JxlPixelFormat& format) {
PackedImage image(xsize, ysize, format, CalcStride(format, xsize));
if (!image.pixels()) {
// TODO(szabadka): use specialized OOM error code
return JXL_FAILURE("Failed to allocate memory for image");
}
return image;
}
PackedImage Copy() const {
PackedImage copy(xsize, ysize, format);
PackedImage copy(xsize, ysize, format, CalcStride(format, xsize));
memcpy(reinterpret_cast<uint8_t*>(copy.pixels()),
reinterpret_cast<const uint8_t*>(pixels()), pixels_size);
return copy;
@ -73,6 +77,15 @@ class PackedImage {
size_t pixel_stride() const { return pixel_stride_; }
static Status ValidateDataType(JxlDataType data_type) {
if ((data_type != JXL_TYPE_UINT8) && (data_type != JXL_TYPE_UINT16) &&
(data_type != JXL_TYPE_FLOAT) && (data_type != JXL_TYPE_FLOAT16)) {
return JXL_FAILURE("Unhandled data type: %d",
static_cast<int>(data_type));
}
return true;
}
static size_t BitsPerChannel(JxlDataType data_type) {
switch (data_type) {
case JXL_TYPE_UINT8:
@ -84,7 +97,8 @@ class PackedImage {
case JXL_TYPE_FLOAT16:
return 16;
default:
JXL_ABORT("Unhandled JxlDataType");
JXL_DEBUG_ABORT("Unreachable");
return 0;
}
}
@ -104,7 +118,8 @@ class PackedImage {
return swap_endianness_ ? BSwapFloat(val) : val;
}
default:
JXL_ABORT("Unhandled JxlDataType");
JXL_DEBUG_ABORT("Unreachable");
return 0.0f;
}
}
@ -130,7 +145,7 @@ class PackedImage {
break;
}
default:
JXL_ABORT("Unhandled JxlDataType");
JXL_DEBUG_ABORT("Unreachable");
}
}
@ -169,11 +184,20 @@ class PackedImage {
// as all other frames in the same image.
class PackedFrame {
public:
template <typename... Args>
explicit PackedFrame(Args&&... args) : color(std::forward<Args>(args)...) {}
explicit PackedFrame(PackedImage&& image) : color(std::move(image)) {}
PackedFrame Copy() const {
PackedFrame copy(color.xsize, color.ysize, color.format);
static StatusOr<PackedFrame> Create(size_t xsize, size_t ysize,
const JxlPixelFormat& format) {
JXL_ASSIGN_OR_RETURN(PackedImage image,
PackedImage::Create(xsize, ysize, format));
PackedFrame frame(std::move(image));
return frame;
}
StatusOr<PackedFrame> Copy() const {
JXL_ASSIGN_OR_RETURN(
PackedFrame copy,
PackedFrame::Create(color.xsize, color.ysize, color.format));
copy.frame_info = frame_info;
copy.name = name;
copy.color = color.Copy();
@ -224,6 +248,7 @@ class PackedMetadata {
public:
std::vector<uint8_t> exif;
std::vector<uint8_t> iptc;
std::vector<uint8_t> jhgm;
std::vector<uint8_t> jumbf;
std::vector<uint8_t> xmp;
};
@ -261,6 +286,8 @@ class PackedPixelFile {
// The icc profile of the original image.
std::vector<uint8_t> orig_icc;
JxlBitDepth input_bitdepth = {JXL_BIT_DEPTH_FROM_PIXEL_FORMAT, 0, 0};
std::unique_ptr<PackedFrame> preview_frame;
std::vector<PackedFrame> frames;
mutable std::vector<ChunkedPackedFrame> chunked_frames;

Просмотреть файл

@ -7,10 +7,14 @@
#include <jxl/cms.h>
#include <jxl/color_encoding.h>
#include <jxl/memory_manager.h>
#include <jxl/types.h>
#include <cstdint>
#include <cstdio>
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/rect.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/dec_external_image.h"
@ -22,25 +26,31 @@ namespace jxl {
namespace extras {
Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
const JxlBitDepth& input_bitdepth,
const PackedFrame& frame,
const CodecInOut& io, ThreadPool* pool,
ImageBundle* bundle) {
JXL_ASSERT(frame.color.pixels() != nullptr);
const bool float_in = frame.color.format.data_type == JXL_TYPE_FLOAT16 ||
frame.color.format.data_type == JXL_TYPE_FLOAT;
size_t frame_bits_per_sample =
float_in ? PackedImage::BitsPerChannel(frame.color.format.data_type)
: info.bits_per_sample;
JXL_ASSERT(frame_bits_per_sample != 0);
JxlMemoryManager* memory_manager = io.memory_manager;
JXL_ENSURE(frame.color.pixels() != nullptr);
size_t frame_bits_per_sample;
if (input_bitdepth.type == JXL_BIT_DEPTH_FROM_PIXEL_FORMAT) {
JXL_RETURN_IF_ERROR(
PackedImage::ValidateDataType(frame.color.format.data_type));
frame_bits_per_sample =
PackedImage::BitsPerChannel(frame.color.format.data_type);
} else {
frame_bits_per_sample = info.bits_per_sample;
}
JXL_ENSURE(frame_bits_per_sample != 0);
// It is ok for the frame.color.format.num_channels to not match the
// number of channels on the image.
JXL_ASSERT(1 <= frame.color.format.num_channels &&
JXL_ENSURE(1 <= frame.color.format.num_channels &&
frame.color.format.num_channels <= 4);
const Span<const uint8_t> span(
static_cast<const uint8_t*>(frame.color.pixels()),
frame.color.pixels_size);
JXL_ASSERT(Rect(frame.frame_info.layer_info.crop_x0,
JXL_ENSURE(Rect(frame.frame_info.layer_info.crop_x0,
frame.frame_info.layer_info.crop_y0,
frame.frame_info.layer_info.xsize,
frame.frame_info.layer_info.ysize)
@ -54,7 +64,7 @@ Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
bundle->origin.y0 = frame.frame_info.layer_info.crop_y0;
}
bundle->name = frame.name; // frame.frame_info.name_length is ignored here.
JXL_ASSERT(io.metadata.m.color_encoding.IsGray() ==
JXL_ENSURE(io.metadata.m.color_encoding.IsGray() ==
(frame.color.format.num_channels <= 2));
JXL_RETURN_IF_ERROR(ConvertFromExternal(
@ -64,31 +74,33 @@ Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
bundle->extra_channels().resize(io.metadata.m.extra_channel_info.size());
for (size_t i = 0; i < frame.extra_channels.size(); i++) {
const auto& ppf_ec = frame.extra_channels[i];
JXL_ASSIGN_OR_RETURN(bundle->extra_channels()[i],
ImageF::Create(ppf_ec.xsize, ppf_ec.ysize));
JXL_CHECK(BufferToImageF(ppf_ec.format, ppf_ec.xsize, ppf_ec.ysize,
ppf_ec.pixels(), ppf_ec.pixels_size, pool,
&bundle->extra_channels()[i]));
JXL_ASSIGN_OR_RETURN(
bundle->extra_channels()[i],
ImageF::Create(memory_manager, ppf_ec.xsize, ppf_ec.ysize));
JXL_RETURN_IF_ERROR(BufferToImageF(
ppf_ec.format, ppf_ec.xsize, ppf_ec.ysize, ppf_ec.pixels(),
ppf_ec.pixels_size, pool, &bundle->extra_channels()[i]));
}
return true;
}
Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
ThreadPool* pool, CodecInOut* io) {
JxlMemoryManager* memory_manager = io->memory_manager;
const bool has_alpha = ppf.info.alpha_bits != 0;
JXL_ASSERT(!ppf.frames.empty());
JXL_ENSURE(!ppf.frames.empty());
if (has_alpha) {
JXL_ASSERT(ppf.info.alpha_bits == ppf.info.bits_per_sample);
JXL_ASSERT(ppf.info.alpha_exponent_bits ==
JXL_ENSURE(ppf.info.alpha_bits == ppf.info.bits_per_sample);
JXL_ENSURE(ppf.info.alpha_exponent_bits ==
ppf.info.exponent_bits_per_sample);
}
const bool is_gray = (ppf.info.num_color_channels == 1);
JXL_ASSERT(ppf.info.num_color_channels == 1 ||
JXL_ENSURE(ppf.info.num_color_channels == 1 ||
ppf.info.num_color_channels == 3);
// Convert the image metadata
io->SetSize(ppf.info.xsize, ppf.info.ysize);
JXL_RETURN_IF_ERROR(io->SetSize(ppf.info.xsize, ppf.info.ysize));
io->metadata.m.bit_depth.bits_per_sample = ppf.info.bits_per_sample;
io->metadata.m.bit_depth.exponent_bits_per_sample =
ppf.info.exponent_bits_per_sample;
@ -103,11 +115,11 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
if (alpha) alpha->bit_depth = io->metadata.m.bit_depth;
io->metadata.m.xyb_encoded = !FROM_JXL_BOOL(ppf.info.uses_original_profile);
JXL_ASSERT(ppf.info.orientation > 0 && ppf.info.orientation <= 8);
JXL_ENSURE(ppf.info.orientation > 0 && ppf.info.orientation <= 8);
io->metadata.m.orientation = ppf.info.orientation;
// Convert animation metadata
JXL_ASSERT(ppf.frames.size() == 1 || ppf.info.have_animation);
JXL_ENSURE(ppf.frames.size() == 1 || ppf.info.have_animation);
io->metadata.m.have_animation = FROM_JXL_BOOL(ppf.info.have_animation);
io->metadata.m.animation.tps_numerator = ppf.info.animation.tps_numerator;
io->metadata.m.animation.tps_denominator = ppf.info.animation.tps_denominator;
@ -141,6 +153,7 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
// Convert the extra blobs
io->blobs.exif = ppf.metadata.exif;
io->blobs.iptc = ppf.metadata.iptc;
io->blobs.jhgm = ppf.metadata.jhgm;
io->blobs.jumbf = ppf.metadata.jumbf;
io->blobs.xmp = ppf.metadata.xmp;
@ -171,15 +184,16 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
JXL_RETURN_IF_ERROR(
io->metadata.m.preview_size.Set(preview_xsize, preview_ysize));
JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
ppf.info, *ppf.preview_frame, *io, pool, &io->preview_frame));
ppf.info, ppf.input_bitdepth, *ppf.preview_frame, *io, pool,
&io->preview_frame));
}
// Convert the pixels
io->frames.clear();
for (const auto& frame : ppf.frames) {
ImageBundle bundle(&io->metadata.m);
JXL_RETURN_IF_ERROR(
ConvertPackedFrameToImageBundle(ppf.info, frame, *io, pool, &bundle));
ImageBundle bundle(memory_manager, &io->metadata.m);
JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
ppf.info, ppf.input_bitdepth, frame, *io, pool, &bundle));
io->frames.push_back(std::move(bundle));
}
@ -192,18 +206,18 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
} else {
SetIntensityTarget(&io->metadata.m);
}
io->CheckMetadata();
JXL_RETURN_IF_ERROR(io->CheckMetadata());
return true;
}
PackedPixelFile ConvertImage3FToPackedPixelFile(const Image3F& image,
const ColorEncoding& c_enc,
JxlPixelFormat format,
ThreadPool* pool) {
PackedPixelFile ppf;
StatusOr<PackedPixelFile> ConvertImage3FToPackedPixelFile(
const Image3F& image, const ColorEncoding& c_enc, JxlPixelFormat format,
ThreadPool* pool) {
PackedPixelFile ppf{};
ppf.info.xsize = image.xsize();
ppf.info.ysize = image.ysize();
ppf.info.num_color_channels = 3;
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(format.data_type));
ppf.info.bits_per_sample = PackedImage::BitsPerChannel(format.data_type);
ppf.info.exponent_bits_per_sample = format.data_type == JXL_TYPE_FLOAT ? 8
: format.data_type == JXL_TYPE_FLOAT16
@ -211,13 +225,15 @@ PackedPixelFile ConvertImage3FToPackedPixelFile(const Image3F& image,
: 0;
ppf.color_encoding = c_enc.ToExternal();
ppf.frames.clear();
PackedFrame frame(image.xsize(), image.ysize(), format);
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(image.xsize(), image.ysize(), format));
const ImageF* channels[3];
for (int c = 0; c < 3; ++c) {
channels[c] = &image.Plane(c);
}
bool float_samples = ppf.info.exponent_bits_per_sample > 0;
JXL_CHECK(ConvertChannelsToExternal(
JXL_RETURN_IF_ERROR(ConvertChannelsToExternal(
channels, 3, ppf.info.bits_per_sample, float_samples, format.endianness,
frame.color.stride, pool, frame.color.pixels(0, 0, 0),
frame.color.pixels_size, PixelCallback(), Orientation::kIdentity));
@ -231,14 +247,15 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
const ColorEncoding& c_desired,
ThreadPool* pool,
PackedPixelFile* ppf) {
JxlMemoryManager* memory_manager = io.memory_manager;
const bool has_alpha = io.metadata.m.HasAlpha();
JXL_ASSERT(!io.frames.empty());
JXL_ENSURE(!io.frames.empty());
if (has_alpha) {
JXL_ASSERT(io.metadata.m.GetAlphaBits() ==
JXL_ENSURE(io.metadata.m.GetAlphaBits() ==
io.metadata.m.bit_depth.bits_per_sample);
const auto* alpha_channel = io.metadata.m.Find(ExtraChannel::kAlpha);
JXL_ASSERT(alpha_channel->bit_depth.exponent_bits_per_sample ==
JXL_ENSURE(alpha_channel->bit_depth.exponent_bits_per_sample ==
io.metadata.m.bit_depth.exponent_bits_per_sample);
ppf->info.alpha_bits = alpha_channel->bit_depth.bits_per_sample;
ppf->info.alpha_exponent_bits =
@ -262,13 +279,13 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
TO_JXL_BOOL(io.metadata.m.tone_mapping.relative_to_max_display);
ppf->info.uses_original_profile = TO_JXL_BOOL(!io.metadata.m.xyb_encoded);
JXL_ASSERT(0 < io.metadata.m.orientation && io.metadata.m.orientation <= 8);
JXL_ENSURE(0 < io.metadata.m.orientation && io.metadata.m.orientation <= 8);
ppf->info.orientation =
static_cast<JxlOrientation>(io.metadata.m.orientation);
ppf->info.num_color_channels = io.metadata.m.color_encoding.Channels();
// Convert animation metadata
JXL_ASSERT(io.frames.size() == 1 || io.metadata.m.have_animation);
JXL_ENSURE(io.frames.size() == 1 || io.metadata.m.have_animation);
ppf->info.have_animation = TO_JXL_BOOL(io.metadata.m.have_animation);
ppf->info.animation.tps_numerator = io.metadata.m.animation.tps_numerator;
ppf->info.animation.tps_denominator = io.metadata.m.animation.tps_denominator;
@ -284,6 +301,7 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
// Convert the extra blobs
ppf->metadata.exif = io.blobs.exif;
ppf->metadata.iptc = io.blobs.iptc;
ppf->metadata.jhgm = io.blobs.jhgm;
ppf->metadata.jumbf = io.blobs.jumbf;
ppf->metadata.xmp = io.blobs.xmp;
const bool float_out = pixel_format.data_type == JXL_TYPE_FLOAT ||
@ -291,7 +309,7 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
// Convert the pixels
ppf->frames.clear();
for (const auto& frame : io.frames) {
JXL_ASSERT(frame.metadata()->bit_depth.bits_per_sample != 0);
JXL_ENSURE(frame.metadata()->bit_depth.bits_per_sample != 0);
// It is ok for the frame.color().kNumPlanes to not match the
// number of channels on the image.
const uint32_t alpha_channels = has_alpha ? 1 : 0;
@ -302,8 +320,10 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
/*endianness=*/pixel_format.endianness,
/*align=*/pixel_format.align};
PackedFrame packed_frame(frame.oriented_xsize(), frame.oriented_ysize(),
format);
JXL_ASSIGN_OR_RETURN(PackedFrame packed_frame,
PackedFrame::Create(frame.oriented_xsize(),
frame.oriented_ysize(), format));
JXL_RETURN_IF_ERROR(PackedImage::ValidateDataType(pixel_format.data_type));
const size_t bits_per_sample =
float_out ? packed_frame.color.BitsPerChannel(pixel_format.data_type)
: ppf->info.bits_per_sample;
@ -313,7 +333,7 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
JXL_ASSIGN_OR_RETURN(ImageBundle ib, frame.Copy());
const ImageBundle* to_color_transform = &ib;
ImageMetadata metadata = io.metadata.m;
ImageBundle store(&metadata);
ImageBundle store(memory_manager, &metadata);
const ImageBundle* transformed;
// TODO(firsching): handle the transform here.
JXL_RETURN_IF_ERROR(TransformIfNeeded(*to_color_transform, c_desired,
@ -329,7 +349,7 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
// TODO(firsching): Convert the extra channels, beside one potential alpha
// channel. FIXME!
JXL_CHECK(frame.extra_channels().size() <= has_alpha);
JXL_ENSURE(frame.extra_channels().size() <= (has_alpha ? 1 : 0));
ppf->frames.push_back(std::move(packed_frame));
}

Просмотреть файл

@ -31,10 +31,9 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
ThreadPool* pool,
PackedPixelFile* ppf);
PackedPixelFile ConvertImage3FToPackedPixelFile(const Image3F& image,
const ColorEncoding& c_enc,
JxlPixelFormat format,
ThreadPool* pool);
StatusOr<PackedPixelFile> ConvertImage3FToPackedPixelFile(
const Image3F& image, const ColorEncoding& c_enc, JxlPixelFormat format,
ThreadPool* pool);
} // namespace extras
} // namespace jxl

2
third_party/jpeg-xl/lib/extras/time.cc поставляемый
Просмотреть файл

@ -46,7 +46,7 @@ double Now() {
if (timebase.denom == 0) {
(void)mach_timebase_info(&timebase);
}
return double(t) * timebase.numer / timebase.denom * 1E-9;
return double(t) * timebase.numer / timebase.denom * 1E-9; // notypo
#elif JXL_OS_HAIKU
return double(system_time_nsecs()) * 1E-9;
#else

Просмотреть файл

@ -19,7 +19,7 @@ HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
static constexpr float rec2020_luminances[3] = {0.2627f, 0.6780f, 0.0593f};
static constexpr Vector3 rec2020_luminances{0.2627f, 0.6780f, 0.0593f};
Status ToneMapFrame(const std::pair<float, float> display_nits,
ImageBundle* const ib, ThreadPool* const pool) {
@ -44,23 +44,25 @@ Status ToneMapFrame(const std::pair<float, float> display_nits,
ib->metadata()->IntensityTarget()},
display_nits, rec2020_luminances);
return RunOnPool(
pool, 0, ib->ysize(), ThreadPool::NoInit,
[&](const uint32_t y, size_t /* thread */) {
float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
V red = Load(df, row_r + x);
V green = Load(df, row_g + x);
V blue = Load(df, row_b + x);
tone_mapper.ToneMap(&red, &green, &blue);
Store(red, df, row_r + x);
Store(green, df, row_g + x);
Store(blue, df, row_b + x);
}
},
"ToneMap");
const auto process_row = [&](const uint32_t y,
size_t /* thread */) -> Status {
float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
V red = Load(df, row_r + x);
V green = Load(df, row_g + x);
V blue = Load(df, row_b + x);
tone_mapper.ToneMap(&red, &green, &blue);
Store(red, df, row_r + x);
Store(green, df, row_g + x);
Store(blue, df, row_b + x);
}
return true;
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, ib->ysize(), ThreadPool::NoInit,
process_row, "ToneMap"));
return true;
}
Status GamutMapFrame(ImageBundle* const ib, float preserve_saturation,
@ -77,24 +79,24 @@ Status GamutMapFrame(ImageBundle* const ib, float preserve_saturation,
JXL_RETURN_IF_ERROR(
ib->TransformTo(linear_rec2020, *JxlGetDefaultCms(), pool));
JXL_RETURN_IF_ERROR(RunOnPool(
pool, 0, ib->ysize(), ThreadPool::NoInit,
[&](const uint32_t y, size_t /* thread*/) {
float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
V red = Load(df, row_r + x);
V green = Load(df, row_g + x);
V blue = Load(df, row_b + x);
GamutMap(&red, &green, &blue, rec2020_luminances,
preserve_saturation);
Store(red, df, row_r + x);
Store(green, df, row_g + x);
Store(blue, df, row_b + x);
}
},
"GamutMap"));
const auto process_row = [&](const uint32_t y, size_t /* thread*/) -> Status {
float* const JXL_RESTRICT row_r = ib->color()->PlaneRow(0, y);
float* const JXL_RESTRICT row_g = ib->color()->PlaneRow(1, y);
float* const JXL_RESTRICT row_b = ib->color()->PlaneRow(2, y);
for (size_t x = 0; x < ib->xsize(); x += Lanes(df)) {
V red = Load(df, row_r + x);
V green = Load(df, row_g + x);
V blue = Load(df, row_b + x);
GamutMap(&red, &green, &blue, rec2020_luminances, preserve_saturation);
Store(red, df, row_r + x);
Store(green, df, row_g + x);
Store(blue, df, row_b + x);
}
return true;
};
JXL_RETURN_IF_ERROR(RunOnPool(pool, 0, ib->ysize(), ThreadPool::NoInit,
process_row, "GamutMap"));
return true;
}

Просмотреть файл

@ -3,37 +3,55 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <jxl/memory_manager.h>
#include "benchmark/benchmark.h"
#include "lib/extras/codec.h"
#include "lib/extras/tone_mapping.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/image.h"
#include "tools/no_memory_manager.h"
namespace jxl {
#define QUIT(M) \
state.SkipWithError(M); \
return;
#define BM_CHECK(C) \
if (!(C)) { \
QUIT(#C) \
}
static void BM_ToneMapping(benchmark::State& state) {
JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(2268, 1512));
JxlMemoryManager* memory_manager = jpegxl::tools::NoMemoryManager();
JXL_ASSIGN_OR_QUIT(Image3F color, Image3F::Create(memory_manager, 2268, 1512),
"Failed to allocate color plane");
FillImage(0.5f, &color);
// Use linear Rec. 2020 so that `ToneMapTo` doesn't have to convert to it and
// we mainly measure the tone mapping itself.
ColorEncoding linear_rec2020;
linear_rec2020.SetColorSpace(ColorSpace::kRGB);
JXL_CHECK(linear_rec2020.SetPrimariesType(Primaries::k2100));
JXL_CHECK(linear_rec2020.SetWhitePointType(WhitePoint::kD65));
BM_CHECK(linear_rec2020.SetPrimariesType(Primaries::k2100));
BM_CHECK(linear_rec2020.SetWhitePointType(WhitePoint::kD65));
linear_rec2020.Tf().SetTransferFunction(TransferFunction::kLinear);
JXL_CHECK(linear_rec2020.CreateICC());
BM_CHECK(linear_rec2020.CreateICC());
for (auto _ : state) {
(void)_;
state.PauseTiming();
CodecInOut tone_mapping_input;
JXL_ASSIGN_OR_DIE(Image3F color2,
Image3F::Create(color.xsize(), color.ysize()));
CopyImageTo(color, &color2);
tone_mapping_input.SetFromImage(std::move(color2), linear_rec2020);
CodecInOut tone_mapping_input{memory_manager};
JXL_ASSIGN_OR_QUIT(
Image3F color2,
Image3F::Create(memory_manager, color.xsize(), color.ysize()),
"Failed to allocate color plane");
BM_CHECK(CopyImageTo(color, &color2));
BM_CHECK(
tone_mapping_input.SetFromImage(std::move(color2), linear_rec2020));
tone_mapping_input.metadata.m.SetIntensityTarget(255);
state.ResumeTiming();
JXL_CHECK(ToneMapTo({0.1, 100}, &tone_mapping_input));
BM_CHECK(ToneMapTo({0.1, 100}, &tone_mapping_input));
}
state.SetItemsProcessed(state.iterations() * color.xsize() * color.ysize());

Просмотреть файл

@ -23,7 +23,7 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -246,7 +246,7 @@ typedef struct {
jpegxl_cms_destroy_func destroy;
} JxlCmsInterface;
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -19,7 +19,7 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -424,7 +424,7 @@ typedef struct {
JxlLayerInfo layer_info;
} JxlFrameHeader;
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -14,9 +14,7 @@
#ifndef JXL_COLOR_ENCODING_H_
#define JXL_COLOR_ENCODING_H_
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -34,9 +32,9 @@ typedef enum {
JXL_COLOR_SPACE_UNKNOWN,
} JxlColorSpace;
/** Built-in whitepoints for color encoding. When decoding, the numerical xy
* whitepoint value can be read from the @ref JxlColorEncoding white_point field
* regardless of the enum value. When encoding, enum values except
/** Built-in white points for color encoding. When decoding, the numerical xy
* white point value can be read from the @ref JxlColorEncoding white_point
* field regardless of the enum value. When encoding, enum values except
* ::JXL_WHITE_POINT_CUSTOM override the numerical fields. Some enum values
* match a subset of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)), however
* the white point and RGB primaries are separate enums here.
@ -80,7 +78,7 @@ typedef enum {
* of CICP (Rec. ITU-T H.273 | ISO/IEC 23091-2:2019(E)) unless specified
* otherwise. */
typedef enum {
/** As specified in SMPTE RP 431-2 */
/** As specified in ITU-R BT.709-6 */
JXL_TRANSFER_FUNCTION_709 = 1,
/** None of the other table entries describe the transfer function. */
JXL_TRANSFER_FUNCTION_UNKNOWN = 2,
@ -99,7 +97,7 @@ typedef enum {
JXL_TRANSFER_FUNCTION_GAMMA = 65535,
} JxlTransferFunction;
/** Renderig intent for color encoding, as specified in ISO 15076-1:2010 */
/** Rendering intent for color encoding, as specified in ISO 15076-1:2010 */
typedef enum {
/** vendor-specific */
JXL_RENDERING_INTENT_PERCEPTUAL = 0,
@ -119,7 +117,7 @@ typedef struct {
JxlColorSpace color_space;
/** Built-in white point. If this value is ::JXL_WHITE_POINT_CUSTOM, must
* use the numerical whitepoint values from white_point_xy.
* use the numerical white point values from white_point_xy.
*/
JxlWhitePoint white_point;
@ -154,7 +152,7 @@ typedef struct {
JxlRenderingIntent rendering_intent;
} JxlColorEncoding;
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

75
third_party/jpeg-xl/lib/include/jxl/compressed_icc.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,75 @@
/* 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.
*/
/** @addtogroup libjxl_metadata
* @{
* @file compressed_icc.h
* @brief Utility functions to compress and decompress ICC streams.
*/
#ifndef JXL_COMPRESSED_ICC_H_
#define JXL_COMPRESSED_ICC_H_
#include <jxl/jxl_export.h>
#include <jxl/memory_manager.h>
#include <jxl/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Allocates a buffer using the memory manager, fills it with a compressed
* representation of an ICC profile, returns the result through @c output_buffer
* and indicates its size through @c output_size.
*
* The result must be freed using the memory manager once it is not of any more
* use.
*
* @param[in] memory_manager Pointer to a JxlMemoryManager.
* @param[in] icc Pointer to a buffer containing the uncompressed ICC profile.
* @param[in] icc_size Size of the buffer containing the ICC profile.
* @param[out] compressed_icc Will be set to a pointer to the buffer containing
* the result.
* @param[out] compressed_icc_size Will be set to the size of the buffer
* containing the result.
* @return Whether compressing the profile was successful.
*/
JXL_EXPORT JXL_BOOL JxlICCProfileEncode(const JxlMemoryManager* memory_manager,
const uint8_t* icc, size_t icc_size,
uint8_t** compressed_icc,
size_t* compressed_icc_size);
/**
* Allocates a buffer using the memory manager, fills it with the decompressed
* version of the ICC profile in @c compressed_icc, returns the result through
* @c output_buffer and indicates its size through @c output_size.
*
* The result must be freed using the memory manager once it is not of any more
* use.
*
* @param[in] memory_manager Pointer to a JxlMemoryManager.
* @param[in] compressed_icc Pointer to a buffer containing the compressed ICC
* profile.
* @param[in] compressed_icc_size Size of the buffer containing the compressed
* ICC profile.
* @param[out] icc Will be set to a pointer to the buffer containing the result.
* @param[out] icc_size Will be set to the size of the buffer containing the
* result.
* @return Whether decompressing the profile was successful.
*/
JXL_EXPORT JXL_BOOL JxlICCProfileDecode(const JxlMemoryManager* memory_manager,
const uint8_t* compressed_icc,
size_t compressed_icc_size,
uint8_t** icc, size_t* icc_size);
#ifdef __cplusplus
}
#endif
#endif /* JXL_COMPRESSED_ICC_H_ */
/** @} */

44
third_party/jpeg-xl/lib/include/jxl/decode.h поставляемый
Просмотреть файл

@ -24,7 +24,7 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -290,12 +290,13 @@ typedef enum {
*
* The buffer set with @ref JxlDecoderSetBoxBuffer must be set again for each
* next box to be obtained, or can be left unset to skip outputting this box.
* The output buffer contains the full box data when the next ::JXL_DEC_BOX
* event or ::JXL_DEC_SUCCESS occurs. ::JXL_DEC_BOX occurs for all
* boxes, including non-metadata boxes such as the signature box or codestream
* boxes. To check whether the box is a metadata type for respectively EXIF,
* XMP or JUMBF, use @ref JxlDecoderGetBoxType and check for types "Exif",
* "xml " and "jumb" respectively.
* The output buffer contains the full box data when the
* ::JXL_DEC_BOX_COMPLETE (if subscribed to) or subsequent ::JXL_DEC_SUCCESS
* or ::JXL_DEC_BOX event occurs. ::JXL_DEC_BOX occurs for all boxes,
* including non-metadata boxes such as the signature box or codestream boxes.
* To check whether the box is a metadata type for respectively EXIF, XMP or
* JUMBF, use @ref JxlDecoderGetBoxType and check for types "Exif", "xml " and
* "jumb" respectively.
*
* In this case, @ref JxlDecoderReleaseInput will return all bytes from the
* start of the box header as unprocessed.
@ -318,6 +319,11 @@ typedef enum {
* unprocessed.
*/
JXL_DEC_FRAME_PROGRESSION = 0x8000,
/** The box being decoded is now complete. This is only emitted if a buffer
* was set for the box.
*/
JXL_DEC_BOX_COMPLETE = 0x10000,
} JxlDecoderStatus;
/** Types of progressive detail.
@ -721,7 +727,7 @@ typedef enum {
* It is often possible to use @ref JxlDecoderGetColorAsICCProfile as an
* alternative anyway. The following scenarios are possible:
* - The JPEG XL image has an attached ICC Profile, in that case, the encoded
* structured data is not available, this function will return an error
* structured data is not available and this function will return an error
* status. @ref JxlDecoderGetColorAsICCProfile should be called instead.
* - The JPEG XL image has an encoded structured color profile, and it
* represents an RGB or grayscale color space. This function will return it.
@ -800,8 +806,8 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetICCProfileSize(
* or the color profile of the decoded pixels.
* @param icc_profile buffer to copy the ICC profile into
* @param size size of the icc_profile buffer in bytes
* @return ::JXL_DEC_SUCCESS if the profile was successfully returned is
* available, ::JXL_DEC_NEED_MORE_INPUT if not yet available, @ref
* @return ::JXL_DEC_SUCCESS if the profile was successfully returned,
* ::JXL_DEC_NEED_MORE_INPUT if not yet available, @ref
* JXL_DEC_ERROR if the profile doesn't exist or the output size is not
* large enough.
*/
@ -869,7 +875,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDesiredIntensityTarget(
*
* This function must not be called before @ref JxlDecoderSetCms.
*
* @param dec decoder orbject
* @param dec decoder object
* @param color_encoding the output color encoding
* @param icc_data bytes of the icc profile
* @param icc_size size of the icc profile in bytes
@ -913,7 +919,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderPreviewOutBufferSize(
const JxlDecoder* dec, const JxlPixelFormat* format, size_t* size);
/**
* Sets the buffer to write the small resolution preview image
* Sets the buffer to write the low-resolution preview image
* to. The size of the buffer must be at least as large as given by @ref
* JxlDecoderPreviewOutBufferSize. The buffer follows the format described
* by @ref JxlPixelFormat. The preview image dimensions are given by the
@ -962,10 +968,10 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderGetFrameName(const JxlDecoder* dec,
/**
* Outputs the blend information for the current frame for a specific extra
* channel. This function can be called when ::JXL_DEC_FRAME occurred for the
* current frame, even when have_animation in the @ref JxlBasicInfo is @ref
* JXL_FALSE. This information is only useful if coalescing is disabled;
* otherwise the decoder will have performed blending already.
* channel. This function can be called once the ::JXL_DEC_FRAME event occurred
* for the current frame, even if the `have_animation` field in the @ref
* JxlBasicInfo is @ref JXL_FALSE. This information is only useful if coalescing
* is disabled; otherwise the decoder will have performed blending already.
*
* @param dec decoder object
* @param index the index of the extra channel
@ -1344,7 +1350,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDecompressBoxes(JxlDecoder* dec,
* animation allowing the decoder to jump to individual frames more
* efficiently.
* - "jbrd": JPEG reconstruction box, contains the information required to
* byte-for-byte losslessly recontruct a JPEG-1 image. The JPEG DCT
* byte-for-byte losslessly reconstruct a JPEG-1 image. The JPEG DCT
* coefficients (pixel content) themselves as well as the ICC profile are
* encoded in the JXL codestream (jxlc or jxlp) itself. EXIF, XMP and JUMBF
* metadata is encoded in the corresponding boxes. The jbrd box itself
@ -1366,7 +1372,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDecompressBoxes(JxlDecoder* dec,
* @param decompressed which box type to get: JXL_FALSE to get the raw box type,
* which can be "brob", JXL_TRUE, get the underlying box type.
* @return ::JXL_DEC_SUCCESS if the value is available, ::JXL_DEC_ERROR if
* not, for example the JXL file does not use the container format.
* not, for example the JPEG XL file does not use the container format.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxType(JxlDecoder* dec,
JxlBoxType type,
@ -1457,7 +1463,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderFlushImage(JxlDecoder* dec);
JXL_EXPORT JxlDecoderStatus
JxlDecoderSetImageOutBitDepth(JxlDecoder* dec, const JxlBitDepth* bit_depth);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -20,7 +20,7 @@
#include <memory>
#if !(defined(__cplusplus) || defined(c_plusplus))
#ifndef __cplusplus
#error "This a C++ only header. Use jxl/decode.h from C sources."
#endif

Просмотреть файл

@ -25,7 +25,7 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -388,6 +388,11 @@ typedef enum {
*/
JXL_ENC_FRAME_SETTING_USE_FULL_IMAGE_HEURISTICS = 38,
/** Disable perceptual optimizations. 0 = optimizations enabled (default), 1 =
* optimizations disabled.
*/
JXL_ENC_FRAME_SETTING_DISABLE_PERCEPTUAL_HEURISTICS = 39,
/** Enum value not to be used as an option. This value is added to force the
* C compiler to have the enum to take a known size.
*/
@ -1588,7 +1593,7 @@ JXL_EXPORT void JxlEncoderSetDebugImageCallback(
JXL_EXPORT void JxlEncoderCollectStats(JxlEncoderFrameSettings* frame_settings,
JxlEncoderStats* stats);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -20,7 +20,7 @@
#include <memory>
#if !(defined(__cplusplus) || defined(c_plusplus))
#ifndef __cplusplus
#error "This a C++ only header. Use jxl/encode.h from C sources."
#endif

129
third_party/jpeg-xl/lib/include/jxl/gain_map.h поставляемый Normal file
Просмотреть файл

@ -0,0 +1,129 @@
/* 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.
*/
/** @addtogroup libjxl_metadata
* @{
* @file gain_map.h
* @brief Utility functions to manipulate jhgm (gain map) boxes.
*/
#ifndef JXL_GAIN_MAP_H_
#define JXL_GAIN_MAP_H_
#include <jxl/color_encoding.h>
#include <jxl/jxl_export.h>
#include <jxl/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Gain map bundle
*
* This structure is used to serialize gain map data to and from an input
* buffer. It holds pointers to sections within the buffer, and different parts
* of the gain map data such as metadata, ICC profile data, and the gain map
* itself.
*
* The pointers in this structure do not take ownership of the memory they point
* to. Instead, they reference specific locations within the provided buffer. It
* is the caller's responsibility to ensure that the buffer remains valid and is
* not deallocated as long as these pointers are in use. The structure should be
* considered as providing a view into the buffer, not as an owner of the data.
*/
typedef struct {
/** Version number of the gain map bundle. */
uint8_t jhgm_version;
/** Size of the gain map metadata in bytes. */
uint16_t gain_map_metadata_size;
/** Pointer to the gain map metadata, which is a binary
* blob following ISO 21496-1. This pointer references data within the input
* buffer. */
const uint8_t* gain_map_metadata;
/** Indicates whether a color encoding is present. */
JXL_BOOL has_color_encoding;
/** If has_color_encoding is true, this field contains the
* uncompressed color encoding data. */
JxlColorEncoding color_encoding;
/** Size of the alternative ICC profile in bytes (compressed
* size). */
uint32_t alt_icc_size;
/** Pointer to the compressed ICC profile. This pointer references
* data within the input buffer. */
const uint8_t* alt_icc;
/** Size of the gain map in bytes. */
uint32_t gain_map_size;
/** Pointer to the gain map data, which is a JPEG XL naked
* codestream. This pointer references data within the input buffer.*/
const uint8_t* gain_map;
} JxlGainMapBundle;
/**
* Calculates the total size required to serialize the gain map bundle into a
* binary buffer. This function accounts for all the necessary space to
* serialize fields such as gain map metadata, color encoding, compressed ICC
* profile data, and the gain map itself.
*
* @param[in] map_bundle Pointer to the JxlGainMapBundle containing all
* necessary data to compute the size.
* @param[out] bundle_size The size in bytes required to serialize the bundle.
* @return Whether setting the size was successful.
*/
JXL_EXPORT JXL_BOOL JxlGainMapGetBundleSize(const JxlGainMapBundle* map_bundle,
size_t* bundle_size);
/**
* Serializes the gain map bundle into a preallocated buffer. The function
* ensures that all parts of the bundle such as metadata, color encoding,
* compressed ICC profile, and the gain map are correctly encoded into the
* buffer. First call `JxlGainMapGetBundleSize` to get the size needed for
* the buffer.
*
* @param[in] map_bundle Pointer to the `JxlGainMapBundle` to serialize.
* @param[out] output_buffer Pointer to the buffer where the serialized data
* will be written.
* @param[in] output_buffer_size The size of the output buffer in bytes. Must be
* large enough to hold the entire serialized data.
* @param[out] bytes_written The number of bytes written to the output buffer.
* @return Whether writing the bundle was successful.
*/
JXL_EXPORT JXL_BOOL JxlGainMapWriteBundle(const JxlGainMapBundle* map_bundle,
uint8_t* output_buffer,
size_t output_buffer_size,
size_t* bytes_written);
/**
* Deserializes a gain map bundle from a provided buffer and populates a
* `JxlGainMapBundle` structure with the data extracted. This function assumes
* the buffer contains a valid serialized gain map bundle. After successful
* execution, the `JxlGainMapBundle` structure will reference three different
* sections within the buffer:
* - gain_map_metadata
* - alt_icc
* - gain_map
* These sections will be accompanied by their respective sizes. Users must
* ensure that the buffer remains valid as long as these pointers are in use.
* @param[in,out] map_bundle Pointer to a preallocated `JxlGainMapBundle` where
* the deserialized data will be stored.
* @param[in] input_buffer Pointer to the buffer containing the serialized gain
* map bundle data.
* @param[in] input_buffer_size The size of the input buffer in bytes.
* @param[out] bytes_read The number of bytes read from the input buffer.
* @return Whether reading the bundle was successful.
*/
JXL_EXPORT JXL_BOOL JxlGainMapReadBundle(JxlGainMapBundle* map_bundle,
const uint8_t* input_buffer,
size_t input_buffer_size,
size_t* bytes_read);
#ifdef __cplusplus
}
#endif
#endif /* JXL_GAIN_MAP_H_ */
/** @} */

Просмотреть файл

@ -15,7 +15,7 @@
#include <stddef.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -55,7 +55,8 @@ typedef struct JxlMemoryManagerStruct {
/** Memory allocation function. This can be NULL if and only if also the
* free() member in this class is NULL. All dynamic memory will be allocated
* and freed with these functions if they are not NULL. */
* and freed with these functions if they are not NULL, otherwise with the
* standard malloc/free. */
jpegxl_alloc_func alloc;
/** Free function matching the alloc() member. */
jpegxl_free_func free;
@ -63,7 +64,7 @@ typedef struct JxlMemoryManagerStruct {
/* TODO(deymo): Add cache-aligned alloc/free functions here. */
} JxlMemoryManager;
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -40,20 +40,25 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
/** Return code used in the JxlParallel* functions as return value. A value
* of 0 means success and any other value means error. The special value
* ::JXL_PARALLEL_RET_RUNNER_ERROR can be used by the runner to indicate any
* other error.
* of ::JXL_PARALLEL_RET_SUCCESS means success and any other value means error.
* The special value ::JXL_PARALLEL_RET_RUNNER_ERROR can be used by the runner
* to indicate any other error.
*/
typedef int JxlParallelRetCode;
/**
* General error returned by the @ref JxlParallelRunInit function to indicate
* an error.
* Code returned by the @ref JxlParallelRunInit function to indicate success.
*/
#define JXL_PARALLEL_RET_SUCCESS (0)
/**
* Code returned by the @ref JxlParallelRunInit function to indicate a general
* error.
*/
#define JXL_PARALLEL_RET_RUNNER_ERROR (-1)
@ -146,11 +151,11 @@ typedef JxlParallelRetCode (*JxlParallelRunner)(
// order.
(*func)(jpegxl_opaque, i, 0);
}
return 0;
return JXL_PARALLEL_RET_SUCCESS;
}
*/
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -37,7 +37,7 @@
#include <stdint.h>
#include <stdlib.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -68,7 +68,7 @@ JxlResizableParallelRunnerSuggestThreads(uint64_t xsize, uint64_t ysize);
*/
JXL_THREADS_EXPORT void JxlResizableParallelRunnerDestroy(void* runner_opaque);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -21,7 +21,7 @@
#include <memory>
#if !(defined(__cplusplus) || defined(c_plusplus))
#ifndef __cplusplus
#error \
"This a C++ only header. Use jxl/jxl_resizable_parallel_runner.h from C" \
"sources."

4
third_party/jpeg-xl/lib/include/jxl/stats.h поставляемый
Просмотреть файл

@ -16,7 +16,7 @@
#include <jxl/jxl_export.h>
#include <stddef.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -94,7 +94,7 @@ JXL_EXPORT size_t JxlEncoderStatsGet(const JxlEncoderStats* stats,
JXL_EXPORT void JxlEncoderStatsMerge(JxlEncoderStats* stats,
const JxlEncoderStats* other);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -37,7 +37,7 @@
#include <stdint.h>
#include <stdlib.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -62,7 +62,7 @@ JXL_THREADS_EXPORT void JxlThreadParallelRunnerDestroy(void* runner_opaque);
*/
JXL_THREADS_EXPORT size_t JxlThreadParallelRunnerDefaultNumWorkerThreads(void);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -21,7 +21,7 @@
#include <cstddef>
#include <memory>
#if !(defined(__cplusplus) || defined(c_plusplus))
#ifndef __cplusplus
#error \
"This a C++ only header. Use jxl/jxl_thread_parallel_runner.h from C" \
"sources."

4
third_party/jpeg-xl/lib/include/jxl/types.h поставляемый
Просмотреть файл

@ -16,7 +16,7 @@
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -145,7 +145,7 @@ typedef struct {
*/
typedef char JxlBoxType[4];
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
}
#endif

1
third_party/jpeg-xl/lib/jpegli.cmake поставляемый
Просмотреть файл

@ -88,7 +88,6 @@ foreach (TESTFILE IN LISTS JPEGXL_INTERNAL_JPEGLI_TESTS)
target_link_libraries(${TESTNAME}
hwy
jpegli-static
gmock
GTest::GTest
GTest::Main
${JPEG_LIBRARIES}

3
third_party/jpeg-xl/lib/jpegli/README.md поставляемый
Просмотреть файл

@ -1,3 +1,6 @@
:warning: **Important Update:** Development continues at https://github.com/google/jpegli
# Improved JPEG encoder and decoder implementation
This subdirectory contains a JPEG encoder and decoder implementation that is

Просмотреть файл

@ -279,8 +279,8 @@ V GammaModulation(const D d, const size_t x, const size_t y,
// ideally -1.0, but likely optimal correction adds some entropy, so slightly
// less than that.
// ln(2) constant folded in because we want std::log but have FastLog2f.
const auto kGam = Set(d, -0.15526878023684174f * 0.693147180559945f);
return MulAdd(kGam, FastLog2f(d, overall_ratio), out_val);
const auto kGamma = Set(d, -0.15526878023684174f * 0.693147180559945f);
return MulAdd(kGamma, FastLog2f(d, overall_ratio), out_val);
}
// Change precision in 8x8 blocks that have high frequency content.
@ -478,11 +478,11 @@ void ComputePreErosion(const RowBuffer<float>& input, const size_t xsize,
}
if (iy % 4 == 3) {
size_t y_out = y0_out + iy / 4;
float* row_dout = pre_erosion->Row(y_out);
float* row_d_out = pre_erosion->Row(y_out);
for (size_t x = 0; x < xsize_out; x++) {
row_dout[x] = (row_out[x * 4] + row_out[x * 4 + 1] +
row_out[x * 4 + 2] + row_out[x * 4 + 3]) *
0.25f;
row_d_out[x] = (row_out[x * 4] + row_out[x * 4 + 1] +
row_out[x * 4 + 2] + row_out[x * 4 + 3]) *
0.25f;
}
pre_erosion->PadRow(y_out, xsize_out, border);
}

Просмотреть файл

@ -11,7 +11,6 @@
#include "lib/jpegli/decode_internal.h"
#include "lib/jpegli/error.h"
#include "lib/jxl/base/status.h"
namespace jpegli {
@ -438,8 +437,8 @@ void FindCandidatesForCell(j_decompress_ptr cinfo, int ncomp, const int cell[],
void CreateInverseColorMap(j_decompress_ptr cinfo) {
jpeg_decomp_master* m = cinfo->master;
int ncomp = cinfo->out_color_components;
JXL_ASSERT(ncomp > 0);
JXL_ASSERT(ncomp <= kMaxComponents);
JPEGLI_CHECK(ncomp > 0);
JPEGLI_CHECK(ncomp <= kMaxComponents);
int num_cells = 1;
for (int c = 0; c < ncomp; ++c) {
num_cells *= (1 << kNumColorCellBits[c]);
@ -474,7 +473,7 @@ int LookupColorIndex(j_decompress_ptr cinfo, const JSAMPLE* pixel) {
cell_idx += (pixel[c] >> (8 - kNumColorCellBits[c])) * stride;
stride <<= kNumColorCellBits[c];
}
JXL_ASSERT(cell_idx < m->candidate_lists_.size());
JPEGLI_CHECK(cell_idx < m->candidate_lists_.size());
int mindist = std::numeric_limits<int>::max();
const auto& candidates = m->candidate_lists_[cell_idx];
for (uint8_t i : candidates) {
@ -489,7 +488,7 @@ int LookupColorIndex(j_decompress_ptr cinfo, const JSAMPLE* pixel) {
}
}
}
JXL_ASSERT(index < cinfo->actual_number_of_colors);
JPEGLI_CHECK(index < cinfo->actual_number_of_colors);
return index;
}

Просмотреть файл

@ -26,11 +26,16 @@ using hwy::HWY_NAMESPACE::Mul;
using hwy::HWY_NAMESPACE::MulAdd;
using hwy::HWY_NAMESPACE::Sub;
void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
template <int kRed, int kGreen, int kBlue, int kAlpha>
void YCbCrToExtRGB(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
float* JXL_RESTRICT row1 = row[1];
float* JXL_RESTRICT row2 = row[2];
const float* row_y = row[0];
const float* row_cb = row[1];
const float* row_cr = row[2];
float* row_r = row[kRed];
float* row_g = row[kGreen];
float* row_b = row[kBlue];
float* row_a = row[kAlpha];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
@ -38,20 +43,48 @@ void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
const auto cgcb = Set(df, -0.114f * 1.772f / 0.587f);
const auto cgcr = Set(df, -0.299f * 1.402f / 0.587f);
const auto cbcb = Set(df, 1.772f);
const auto alpha_opaque = Set(df, 127.0f / 255.0f);
for (size_t x = 0; x < xsize; x += Lanes(df)) {
const auto y_vec = Load(df, row0 + x);
const auto cb_vec = Load(df, row1 + x);
const auto cr_vec = Load(df, row2 + x);
const auto y_vec = Load(df, row_y + x);
const auto cb_vec = Load(df, row_cb + x);
const auto cr_vec = Load(df, row_cr + x);
const auto r_vec = MulAdd(crcr, cr_vec, y_vec);
const auto g_vec = MulAdd(cgcr, cr_vec, MulAdd(cgcb, cb_vec, y_vec));
const auto b_vec = MulAdd(cbcb, cb_vec, y_vec);
Store(r_vec, df, row0 + x);
Store(g_vec, df, row1 + x);
Store(b_vec, df, row2 + x);
Store(r_vec, df, row_r + x);
Store(g_vec, df, row_g + x);
Store(b_vec, df, row_b + x);
if (kAlpha >= 0) {
Store(alpha_opaque, df, row_a + x);
}
}
}
void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
YCbCrToExtRGB<0, 1, 2, -1>(row, xsize);
}
void YCbCrToBGR(float* row[kMaxComponents], size_t xsize) {
YCbCrToExtRGB<2, 1, 0, -1>(row, xsize);
}
void YCbCrToRGBA(float* row[kMaxComponents], size_t xsize) {
YCbCrToExtRGB<0, 1, 2, 3>(row, xsize);
}
void YCbCrToBGRA(float* row[kMaxComponents], size_t xsize) {
YCbCrToExtRGB<2, 1, 0, 3>(row, xsize);
}
void YCbCrToARGB(float* row[kMaxComponents], size_t xsize) {
YCbCrToExtRGB<1, 2, 3, 0>(row, xsize);
}
void YCbCrToABGR(float* row[kMaxComponents], size_t xsize) {
YCbCrToExtRGB<3, 2, 1, 0>(row, xsize);
}
void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
@ -66,11 +99,15 @@ void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
}
}
void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
template <int kRed, int kGreen, int kBlue>
void ExtRGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
float* JXL_RESTRICT row1 = row[1];
float* JXL_RESTRICT row2 = row[2];
const float* row_r = row[kRed];
const float* row_g = row[kGreen];
const float* row_b = row[kBlue];
float* row_y = row[0];
float* row_cb = row[1];
float* row_cr = row[2];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
const auto c128 = Set(df, 128.0f);
@ -85,9 +122,9 @@ void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const auto kNormB = Div(Set(df, 1.0f), (Add(kR, Add(kG, kAmpB))));
for (size_t x = 0; x < xsize; x += Lanes(df)) {
const auto r = Load(df, row0 + x);
const auto g = Load(df, row1 + x);
const auto b = Load(df, row2 + x);
const auto r = Load(df, row_r + x);
const auto g = Load(df, row_g + x);
const auto b = Load(df, row_b + x);
const auto r_base = Mul(r, kR);
const auto r_diff = Mul(r, kDiffR);
const auto g_base = Mul(g, kG);
@ -96,12 +133,28 @@ void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const auto y_base = Add(r_base, Add(g_base, b_base));
const auto cb_vec = MulAdd(Sub(b_diff, y_base), kNormB, c128);
const auto cr_vec = MulAdd(Sub(r_diff, y_base), kNormR, c128);
Store(y_base, df, row0 + x);
Store(cb_vec, df, row1 + x);
Store(cr_vec, df, row2 + x);
Store(y_base, df, row_y + x);
Store(cb_vec, df, row_cb + x);
Store(cr_vec, df, row_cr + x);
}
}
void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
ExtRGBToYCbCr<0, 1, 2>(row, xsize);
}
void BGRToYCbCr(float* row[kMaxComponents], size_t xsize) {
ExtRGBToYCbCr<2, 1, 0>(row, xsize);
}
void ARGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
ExtRGBToYCbCr<1, 2, 3>(row, xsize);
}
void ABGRToYCbCr(float* row[kMaxComponents], size_t xsize) {
ExtRGBToYCbCr<3, 2, 1>(row, xsize);
}
void CMYKToYCCK(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
@ -127,7 +180,15 @@ namespace jpegli {
HWY_EXPORT(CMYKToYCCK);
HWY_EXPORT(YCCKToCMYK);
HWY_EXPORT(YCbCrToRGB);
HWY_EXPORT(YCbCrToBGR);
HWY_EXPORT(YCbCrToRGBA);
HWY_EXPORT(YCbCrToBGRA);
HWY_EXPORT(YCbCrToARGB);
HWY_EXPORT(YCbCrToABGR);
HWY_EXPORT(RGBToYCbCr);
HWY_EXPORT(BGRToYCbCr);
HWY_EXPORT(ARGBToYCbCr);
HWY_EXPORT(ABGRToYCbCr);
bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
switch (colorspace) {
@ -135,19 +196,25 @@ bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
return num_components == 1;
case JCS_RGB:
case JCS_YCbCr:
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
case JCS_EXT_BGR:
#endif
return num_components == 3;
case JCS_CMYK:
case JCS_YCCK:
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGBX:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
#endif
#ifdef JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
case JCS_EXT_BGRA:
case JCS_EXT_ABGR:
case JCS_EXT_ARGB:
#endif
return num_components == 4;
default:
// Unrecognized colorspaces can have any number of channels, since no
@ -158,16 +225,73 @@ bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
void NullTransform(float* row[kMaxComponents], size_t len) {}
void FillAlpha(float* row, size_t len) {
static const float kAlpha = 127.0f / 255.0f;
for (size_t i = 0; i < len; ++i) {
row[i] = kAlpha;
}
}
// Works for BGR as well.
void GrayscaleToRGB(float* row[kMaxComponents], size_t len) {
memcpy(row[1], row[0], len * sizeof(row[1][0]));
memcpy(row[2], row[0], len * sizeof(row[2][0]));
}
// Works for BGRA as well.
void GrayscaleToRGBA(float* row[kMaxComponents], size_t len) {
memcpy(row[1], row[0], len * sizeof(row[1][0]));
memcpy(row[2], row[0], len * sizeof(row[2][0]));
FillAlpha(row[3], len);
}
// Works for ABGR as well.
void GrayscaleToARGB(float* row[kMaxComponents], size_t len) {
memcpy(row[1], row[0], len * sizeof(row[1][0]));
memcpy(row[2], row[0], len * sizeof(row[2][0]));
memcpy(row[3], row[0], len * sizeof(row[1][0]));
FillAlpha(row[0], len);
}
void GrayscaleToYCbCr(float* row[kMaxComponents], size_t len) {
memset(row[1], 0, len * sizeof(row[1][0]));
memset(row[2], 0, len * sizeof(row[2][0]));
}
void RGBToBGR(float* row[kMaxComponents], size_t len) {
for (size_t i = 0; i < len; ++i) {
std::swap(row[0][i], row[2][i]);
}
}
void RGBToRGBA(float* row[kMaxComponents], size_t len) {
FillAlpha(row[3], len);
}
void RGBToBGRA(float* row[kMaxComponents], size_t len) {
static const float kAlpha = 127.0f / 255.0f;
for (size_t i = 0; i < len; ++i) {
std::swap(row[0][i], row[2][i]);
row[3][i] = kAlpha;
}
}
void RGBToARGB(float* row[kMaxComponents], size_t len) {
memcpy(row[3], row[2], len * sizeof(row[1][0]));
memcpy(row[2], row[1], len * sizeof(row[2][0]));
memcpy(row[1], row[0], len * sizeof(row[1][0]));
FillAlpha(row[0], len);
}
void RGBToABGR(float* row[kMaxComponents], size_t len) {
static const float kAlpha = 127.0f / 255.0f;
for (size_t i = 0; i < len; ++i) {
std::swap(row[1][i], row[2][i]);
row[3][i] = row[0][i];
row[0][i] = kAlpha;
}
}
void ChooseColorTransform(j_compress_ptr cinfo) {
jpeg_comp_master* m = cinfo->master;
if (!CheckColorSpaceComponents(cinfo->input_components,
@ -220,6 +344,43 @@ void ChooseColorTransform(j_compress_ptr cinfo) {
}
}
if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
cinfo->jpeg_color_space == JCS_YCbCr) {
switch (cinfo->in_color_space) {
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
case JCS_EXT_RGBX:
m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
break;
case JCS_EXT_BGR:
case JCS_EXT_BGRX:
m->color_transform = HWY_DYNAMIC_DISPATCH(BGRToYCbCr);
break;
case JCS_EXT_XRGB:
m->color_transform = HWY_DYNAMIC_DISPATCH(ARGBToYCbCr);
break;
case JCS_EXT_XBGR:
m->color_transform = HWY_DYNAMIC_DISPATCH(ABGRToYCbCr);
break;
#endif
#ifdef JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
break;
case JCS_EXT_BGRA:
m->color_transform = HWY_DYNAMIC_DISPATCH(BGRToYCbCr);
break;
case JCS_EXT_ARGB:
m->color_transform = HWY_DYNAMIC_DISPATCH(ARGBToYCbCr);
break;
case JCS_EXT_ABGR:
m->color_transform = HWY_DYNAMIC_DISPATCH(ABGRToYCbCr);
break;
#endif
default:; // Nothing to do.
}
}
if (m->color_transform == nullptr) {
// TODO(szabadka) Support more color transforms.
JPEGLI_ERROR("Unsupported color transform %d -> %d", cinfo->in_color_space,
@ -251,18 +412,123 @@ void ChooseColorTransform(j_decompress_ptr cinfo) {
m->color_transform = nullptr;
if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
if (cinfo->out_color_space == JCS_RGB) {
m->color_transform = GrayscaleToRGB;
switch (cinfo->out_color_space) {
case JCS_RGB:
m->color_transform = GrayscaleToRGB;
break;
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
case JCS_EXT_BGR:
m->color_transform = GrayscaleToRGB;
break;
case JCS_EXT_RGBX:
case JCS_EXT_BGRX:
m->color_transform = GrayscaleToRGBA;
break;
case JCS_EXT_XRGB:
case JCS_EXT_XBGR:
m->color_transform = GrayscaleToARGB;
break;
#endif
#ifdef JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
case JCS_EXT_BGRA:
m->color_transform = GrayscaleToRGBA;
break;
case JCS_EXT_ARGB:
case JCS_EXT_ABGR:
m->color_transform = GrayscaleToARGB;
break;
#endif
default:
m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_RGB) {
if (cinfo->out_color_space == JCS_GRAYSCALE) {
m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
switch (cinfo->out_color_space) {
case JCS_GRAYSCALE:
m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
break;
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
m->color_transform = NullTransform;
break;
case JCS_EXT_BGR:
m->color_transform = RGBToBGR;
break;
case JCS_EXT_RGBX:
m->color_transform = RGBToRGBA;
break;
case JCS_EXT_BGRX:
m->color_transform = RGBToBGRA;
break;
case JCS_EXT_XRGB:
m->color_transform = RGBToARGB;
break;
case JCS_EXT_XBGR:
m->color_transform = RGBToABGR;
break;
#endif
#ifdef JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
m->color_transform = RGBToRGBA;
break;
case JCS_EXT_BGRA:
m->color_transform = RGBToBGRA;
break;
case JCS_EXT_ARGB:
m->color_transform = RGBToARGB;
break;
case JCS_EXT_ABGR:
m->color_transform = RGBToABGR;
break;
#endif
default:
m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_YCbCr) {
if (cinfo->out_color_space == JCS_RGB) {
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
} else if (cinfo->out_color_space == JCS_GRAYSCALE) {
m->color_transform = NullTransform;
switch (cinfo->out_color_space) {
case JCS_GRAYSCALE:
m->color_transform = NullTransform;
break;
case JCS_RGB:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
break;
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
break;
case JCS_EXT_BGR:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGR);
break;
case JCS_EXT_RGBX:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGBA);
break;
case JCS_EXT_BGRX:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGRA);
break;
case JCS_EXT_XRGB:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToARGB);
break;
case JCS_EXT_XBGR:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToABGR);
break;
#endif
#ifdef JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGBA);
break;
case JCS_EXT_BGRA:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGRA);
break;
case JCS_EXT_ARGB:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToARGB);
break;
case JCS_EXT_ABGR:
m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToABGR);
break;
#endif
default:
m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_YCCK) {
if (cinfo->out_color_space == JCS_CMYK) {

11
third_party/jpeg-xl/lib/jpegli/common.h поставляемый
Просмотреть файл

@ -20,14 +20,9 @@
#ifndef LIB_JPEGLI_COMMON_H_
#define LIB_JPEGLI_COMMON_H_
/* clang-format off */
#include <stdio.h>
#include <jpeglib.h>
/* clang-format on */
#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#include "lib/jpegli/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -41,7 +36,7 @@ JQUANT_TBL* jpegli_alloc_quant_table(j_common_ptr cinfo);
JHUFF_TBL* jpegli_alloc_huff_table(j_common_ptr cinfo);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
} // extern "C"
#endif

Просмотреть файл

@ -6,17 +6,33 @@
#ifndef LIB_JPEGLI_COMMON_INTERNAL_H_
#define LIB_JPEGLI_COMMON_INTERNAL_H_
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
// Suppress any -Wdeprecated-declarations warning that might be emitted by
// GCC or Clang by std::stable_sort in C++17 or later mode
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <algorithm>
#ifdef __clang__
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#include <hwy/aligned_allocator.h>
#include "lib/jpegli/memory_manager.h"
#include "lib/jpegli/simd.h"
#include "lib/jxl/base/compiler_specific.h" // for ssize_t
#include "lib/jxl/base/status.h" // for JXL_CHECK
namespace jpegli {
@ -94,8 +110,8 @@ class RowBuffer {
public:
template <typename CInfoType>
void Allocate(CInfoType cinfo, size_t num_rows, size_t rowsize) {
static_assert(sizeof(T) == 4);
size_t vec_size = std::max(VectorSize(), sizeof(T));
JXL_CHECK(vec_size % sizeof(T) == 0);
size_t alignment = std::max<size_t>(HWY_ALIGNMENT, vec_size);
size_t min_memstride = alignment + rowsize * sizeof(T) + vec_size;
size_t memstride = RoundUpTo(min_memstride, alignment);

32
third_party/jpeg-xl/lib/jpegli/dct-inl.h поставляемый
Просмотреть файл

@ -35,24 +35,24 @@ using D = HWY_FULL(float);
using DI = HWY_FULL(int32_t);
template <size_t N>
void AddReverse(const float* JXL_RESTRICT ain1, const float* JXL_RESTRICT ain2,
float* JXL_RESTRICT aout) {
void AddReverse(const float* JXL_RESTRICT a_in1,
const float* JXL_RESTRICT a_in2, float* JXL_RESTRICT a_out) {
HWY_CAPPED(float, 8) d8;
for (size_t i = 0; i < N; i++) {
auto in1 = Load(d8, ain1 + i * 8);
auto in2 = Load(d8, ain2 + (N - i - 1) * 8);
Store(Add(in1, in2), d8, aout + i * 8);
auto in1 = Load(d8, a_in1 + i * 8);
auto in2 = Load(d8, a_in2 + (N - i - 1) * 8);
Store(Add(in1, in2), d8, a_out + i * 8);
}
}
template <size_t N>
void SubReverse(const float* JXL_RESTRICT ain1, const float* JXL_RESTRICT ain2,
float* JXL_RESTRICT aout) {
void SubReverse(const float* JXL_RESTRICT a_in1,
const float* JXL_RESTRICT a_in2, float* JXL_RESTRICT a_out) {
HWY_CAPPED(float, 8) d8;
for (size_t i = 0; i < N; i++) {
auto in1 = Load(d8, ain1 + i * 8);
auto in2 = Load(d8, ain2 + (N - i - 1) * 8);
Store(Sub(in1, in2), d8, aout + i * 8);
auto in1 = Load(d8, a_in1 + i * 8);
auto in2 = Load(d8, a_in2 + (N - i - 1) * 8);
Store(Sub(in1, in2), d8, a_out + i * 8);
}
}
@ -73,15 +73,15 @@ void B(float* JXL_RESTRICT coeff) {
// Ideally optimized away by compiler (except the multiply).
template <size_t N>
void InverseEvenOdd(const float* JXL_RESTRICT ain, float* JXL_RESTRICT aout) {
void InverseEvenOdd(const float* JXL_RESTRICT a_in, float* JXL_RESTRICT a_out) {
HWY_CAPPED(float, 8) d8;
for (size_t i = 0; i < N / 2; i++) {
auto in1 = Load(d8, ain + i * 8);
Store(in1, d8, aout + 2 * i * 8);
auto in1 = Load(d8, a_in + i * 8);
Store(in1, d8, a_out + 2 * i * 8);
}
for (size_t i = N / 2; i < N; i++) {
auto in1 = Load(d8, ain + i * 8);
Store(in1, d8, aout + (2 * (i - N / 2) + 1) * 8);
auto in1 = Load(d8, a_in + i * 8);
Store(in1, d8, a_out + (2 * (i - N / 2) + 1) * 8);
}
}
@ -109,8 +109,10 @@ struct WcMultipliers<8> {
};
};
#if JXL_CXX_LANG < JXL_CXX_17
constexpr float WcMultipliers<4>::kMultipliers[];
constexpr float WcMultipliers<8>::kMultipliers[];
#endif
// Invoked on full vector.
template <size_t N>

62
third_party/jpeg-xl/lib/jpegli/decode.cc поставляемый
Просмотреть файл

@ -54,6 +54,7 @@ void InitializeImage(j_decompress_ptr cinfo) {
m->found_soi_ = false;
m->found_dri_ = false;
m->found_sof_ = false;
m->found_sos_ = false;
m->found_eoi_ = false;
m->icc_index_ = 0;
m->icc_total_ = 0;
@ -177,7 +178,7 @@ void BuildHuffmanLookupTable(j_decompress_ptr cinfo, JHUFF_TBL* table,
for (int i = 0; i < total_count; ++i) {
int value = table->huffval[i];
if (values_seen[value]) {
return JPEGLI_ERROR("Duplicate Huffman code value %d", value);
JPEGLI_ERROR("Duplicate Huffman code value %d", value);
}
values_seen[value] = 1;
values[i] = value;
@ -225,7 +226,7 @@ void PrepareForScan(j_decompress_ptr cinfo) {
HuffmanTableEntry* huff_lut =
&m->dc_huff_lut_[dc_tbl_idx * kJpegHuffmanLutSize];
if (!table) {
return JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
}
BuildHuffmanLookupTable(cinfo, table, huff_lut);
}
@ -235,7 +236,7 @@ void PrepareForScan(j_decompress_ptr cinfo) {
HuffmanTableEntry* huff_lut =
&m->ac_huff_lut_[ac_tbl_idx * kJpegHuffmanLutSize];
if (!table) {
return JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
}
BuildHuffmanLookupTable(cinfo, table, huff_lut);
}
@ -243,10 +244,14 @@ void PrepareForScan(j_decompress_ptr cinfo) {
// Copy quantization tables into comp_info.
for (int i = 0; i < cinfo->comps_in_scan; ++i) {
jpeg_component_info* comp = cinfo->cur_comp_info[i];
int quant_tbl_idx = comp->quant_tbl_no;
JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[quant_tbl_idx];
if (!quant_table) {
JPEGLI_ERROR("Quantization table with index %d not found", quant_tbl_idx);
}
if (comp->quant_table == nullptr) {
comp->quant_table = Allocate<JQUANT_TBL>(cinfo, 1, JPOOL_IMAGE);
memcpy(comp->quant_table, cinfo->quant_tbl_ptrs[comp->quant_tbl_no],
sizeof(JQUANT_TBL));
memcpy(comp->quant_table, quant_table, sizeof(JQUANT_TBL));
}
}
if (cinfo->comps_in_scan == 1) {
@ -723,16 +728,36 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
}
}
if (cinfo->out_color_space == JCS_GRAYSCALE) {
cinfo->out_color_components = 1;
} else if (cinfo->out_color_space == JCS_RGB ||
cinfo->out_color_space == JCS_YCbCr) {
cinfo->out_color_components = 3;
} else if (cinfo->out_color_space == JCS_CMYK ||
cinfo->out_color_space == JCS_YCCK) {
cinfo->out_color_components = 4;
} else {
cinfo->out_color_components = cinfo->num_components;
switch (cinfo->out_color_space) {
case JCS_GRAYSCALE:
cinfo->out_color_components = 1;
break;
case JCS_RGB:
case JCS_YCbCr:
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
case JCS_EXT_BGR:
#endif
cinfo->out_color_components = 3;
break;
case JCS_CMYK:
case JCS_YCCK:
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGBX:
case JCS_EXT_BGRX:
case JCS_EXT_XBGR:
case JCS_EXT_XRGB:
#endif
#ifdef JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
case JCS_EXT_BGRA:
case JCS_EXT_ABGR:
case JCS_EXT_ARGB:
#endif
cinfo->out_color_components = 4;
break;
default:
cinfo->out_color_components = cinfo->num_components;
}
cinfo->output_components =
cinfo->quantize_colors ? 1 : cinfo->out_color_components;
@ -740,8 +765,11 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
boolean jpegli_has_multiple_scans(j_decompress_ptr cinfo) {
if (cinfo->input_scan_number == 0) {
JPEGLI_ERROR("No SOS marker found.");
if (cinfo->global_state != jpegli::kDecHeaderDone &&
cinfo->global_state != jpegli::kDecProcessScan &&
cinfo->global_state != jpegli::kDecProcessMarkers) {
JPEGLI_ERROR("jpegli_has_multiple_scans: unexpected state %d",
cinfo->global_state);
}
return TO_JXL_BOOL(cinfo->master->is_multiscan_);
}

7
third_party/jpeg-xl/lib/jpegli/decode.h поставляемый
Просмотреть файл

@ -21,8 +21,9 @@
#define LIB_JPEGLI_DECODE_H_
#include "lib/jpegli/common.h"
#include "lib/jpegli/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
extern "C" {
#endif
@ -36,7 +37,7 @@ void jpegli_CreateDecompress(j_decompress_ptr cinfo, int version,
void jpegli_stdio_src(j_decompress_ptr cinfo, FILE *infile);
void jpegli_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer,
unsigned long insize);
unsigned long insize /* NOLINT */);
int jpegli_read_header(j_decompress_ptr cinfo, boolean require_image);
@ -99,7 +100,7 @@ void jpegli_new_colormap(j_decompress_ptr cinfo);
void jpegli_set_output_format(j_decompress_ptr cinfo, JpegliDataType data_type,
JpegliEndianness endianness);
#if defined(__cplusplus) || defined(c_plusplus)
#ifdef __cplusplus
} // extern "C"
#endif

Просмотреть файл

@ -3,17 +3,27 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <cmath>
#include <jxl/types.h>
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ostream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
#include "lib/jpegli/libjpeg_test_util.h"
#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jpegli/types.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
@ -78,7 +88,8 @@ class SourceManager {
return TRUE;
}
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
static void skip_input_data(j_decompress_ptr cinfo,
long num_bytes /* NOLINT */) {
auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
if (num_bytes <= 0) {
return;
@ -219,13 +230,14 @@ struct TestConfig {
float max_diff = 35.0f;
};
std::vector<uint8_t> GetTestJpegData(TestConfig& config) {
jxl::StatusOr<std::vector<uint8_t>> GetTestJpegData(TestConfig& config) {
std::vector<uint8_t> compressed;
if (!config.fn.empty()) {
compressed = ReadTestData(config.fn);
JXL_ASSIGN_OR_RETURN(compressed, ReadTestData(config.fn));
} else {
GeneratePixels(&config.input);
JXL_CHECK(EncodeWithJpegli(config.input, config.jparams, &compressed));
JXL_RETURN_IF_ERROR(
EncodeWithJpegli(config.input, config.jparams, &compressed));
}
if (config.dparams.size_factor < 1.0f) {
compressed.resize(compressed.size() * config.dparams.size_factor);
@ -256,8 +268,8 @@ void TestAPINonBuffered(const CompressParams& jparams,
if (!jparams.icc.empty()) {
uint8_t* icc_data = nullptr;
unsigned int icc_len;
JXL_CHECK(jpegli_read_icc_profile(cinfo, &icc_data, &icc_len));
JXL_CHECK(icc_data);
ASSERT_TRUE(jpegli_read_icc_profile(cinfo, &icc_data, &icc_len));
ASSERT_TRUE(icc_data);
EXPECT_EQ(0, memcmp(jparams.icc.data(), icc_data, icc_len));
free(icc_data);
}
@ -278,7 +290,7 @@ void TestAPINonBuffered(const CompressParams& jparams,
}
if (dparams.output_mode == COEFFICIENTS) {
jvirt_barray_ptr* coef_arrays = jpegli_read_coefficients(cinfo);
JXL_CHECK(coef_arrays != nullptr);
ASSERT_TRUE(coef_arrays != nullptr);
CopyCoefficients(cinfo, coef_arrays, output);
} else {
jpegli_start_decompress(cinfo);
@ -297,10 +309,10 @@ void TestAPIBuffered(const CompressParams& jparams,
SetDecompressParams(dparams, cinfo);
jpegli_set_output_format(cinfo, dparams.data_type, dparams.endianness);
VerifyHeader(jparams, cinfo);
bool has_multiple_scans = FROM_JXL_BOOL(jpegli_has_multiple_scans(cinfo));
EXPECT_TRUE(jpegli_start_decompress(cinfo));
// start decompress should not read the whole input in buffered image mode
EXPECT_FALSE(jpegli_input_complete(cinfo));
bool has_multiple_scans = FROM_JXL_BOOL(jpegli_has_multiple_scans(cinfo));
EXPECT_EQ(0, cinfo->output_scan_number);
int sos_marker_cnt = 1; // read_header reads the first SOS marker
while (!jpegli_input_complete(cinfo)) {
@ -330,7 +342,7 @@ void TestAPIBuffered(const CompressParams& jparams,
++sos_marker_cnt; // finish output reads the next SOS marker or EOI
if (dparams.output_mode == COEFFICIENTS) {
jvirt_barray_ptr* coef_arrays = jpegli_read_coefficients(cinfo);
JXL_CHECK(coef_arrays != nullptr);
ASSERT_TRUE(coef_arrays != nullptr);
CopyCoefficients(cinfo, coef_arrays, &output_progression->back());
}
}
@ -366,7 +378,8 @@ TEST(DecodeAPITest, ReuseCinfo) {
"Generating input with %dx%d chroma subsampling "
"progressive level %d\n",
h_samp, v_samp, progr);
JXL_CHECK(EncodeWithJpegli(input, jparams, &compressed));
JPEGLI_TEST_ENSURE_TRUE(
EncodeWithJpegli(input, jparams, &compressed));
for (JpegIOMode output_mode : {PIXELS, RAW_DATA, COEFFICIENTS}) {
for (bool crop : {true, false}) {
if (crop && output_mode != PIXELS) continue;
@ -408,8 +421,8 @@ TEST(DecodeAPITest, ReuseCinfo) {
output_progression.clear();
src.Reset();
TestAPIBuffered(jparams, dparams, &cinfo, &output_progression);
JXL_CHECK(output_progression.size() ==
expected_output_progression.size());
JPEGLI_TEST_ENSURE_TRUE(output_progression.size() ==
expected_output_progression.size());
for (size_t i = 0; i < output_progression.size(); ++i) {
const TestImage& output = output_progression[i];
const TestImage& expected = expected_output_progression[i];
@ -447,7 +460,7 @@ std::vector<TestConfig> GenerateBasicConfigs() {
TEST(DecodeAPITest, ReuseCinfoSameMemSource) {
std::vector<TestConfig> all_configs = GenerateBasicConfigs();
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0;
unsigned long buffer_size = 0; // NOLINT
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -487,7 +500,7 @@ TEST(DecodeAPITest, ReuseCinfoSameMemSource) {
TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
std::vector<TestConfig> all_configs = GenerateBasicConfigs();
FILE* tmpf = tmpfile();
JXL_CHECK(tmpf);
ASSERT_TRUE(tmpf);
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -502,7 +515,7 @@ TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
EXPECT_TRUE(try_catch_block());
jpegli_destroy_compress(&cinfo);
}
rewind(tmpf);
fseek(tmpf, 0, SEEK_SET);
std::vector<TestImage> all_outputs(all_configs.size());
{
jpeg_decompress_struct cinfo;
@ -527,9 +540,9 @@ TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
TEST(DecodeAPITest, AbbreviatedStreams) {
uint8_t* table_stream = nullptr;
unsigned long table_stream_size = 0;
unsigned long table_stream_size = 0; // NOLINT
uint8_t* data_stream = nullptr;
unsigned long data_stream_size = 0;
unsigned long data_stream_size = 0; // NOLINT
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -591,7 +604,8 @@ TEST_P(DecodeAPITestParam, TestAPI) {
TestConfig config = GetParam();
const DecompressParams& dparams = config.dparams;
if (dparams.skip_scans) return;
const std::vector<uint8_t> compressed = GetTestJpegData(config);
JXL_ASSIGN_OR_QUIT(std::vector<uint8_t> compressed, GetTestJpegData(config),
"Failed to create test data");
SourceManager src(compressed.data(), compressed.size(), dparams.chunk_size);
TestImage output1;
@ -625,7 +639,8 @@ class DecodeAPITestParamBuffered : public ::testing::TestWithParam<TestConfig> {
TEST_P(DecodeAPITestParamBuffered, TestAPI) {
TestConfig config = GetParam();
const DecompressParams& dparams = config.dparams;
const std::vector<uint8_t> compressed = GetTestJpegData(config);
JXL_ASSIGN_OR_QUIT(std::vector<uint8_t> compressed, GetTestJpegData(config),
"Failed to create test data.");
SourceManager src(compressed.data(), compressed.size(), dparams.chunk_size);
std::vector<TestImage> output_progression1;
@ -893,7 +908,9 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
all_tests.push_back(config);
}
// Tests for color transforms.
for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_GRAYSCALE}) {
for (J_COLOR_SPACE out_color_space :
{JCS_RGB, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR, JCS_EXT_RGBA,
JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = JCS_GRAYSCALE;
@ -902,7 +919,9 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
all_tests.push_back(config);
}
for (J_COLOR_SPACE jpeg_color_space : {JCS_RGB, JCS_YCbCr}) {
for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
for (J_COLOR_SPACE out_color_space :
{JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR,
JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
if (jpeg_color_space == JCS_RGB && out_color_space == JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
@ -1107,6 +1126,8 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
TestConfig config;
config.input.xsize = xsize;
config.input.ysize = ysize;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
}

Просмотреть файл

@ -6,14 +6,15 @@
#ifndef LIB_JPEGLI_DECODE_INTERNAL_H_
#define LIB_JPEGLI_DECODE_INTERNAL_H_
#include <stdint.h>
#include <sys/types.h>
#include <cstdint>
#include <vector>
#include "lib/jpegli/common.h"
#include "lib/jpegli/common_internal.h"
#include "lib/jpegli/huffman.h"
#include "lib/jpegli/types.h"
namespace jpegli {
@ -45,19 +46,26 @@ struct jpeg_decomp_master {
size_t input_buffer_pos_;
// Number of bits after codestream_pos_ that were already processed.
size_t codestream_bits_ahead_;
bool streaming_mode_;
// Coefficient buffers
jvirt_barray_ptr* coef_arrays;
JBLOCKARRAY coeff_rows[jpegli::kMaxComponents];
bool streaming_mode_;
//
// Marker data processing state.
//
bool found_soi_;
bool found_dri_;
bool found_sof_;
bool found_sos_;
bool found_eoi_;
// Whether this jpeg has multiple scans (progressive or non-interleaved
// sequential).
bool is_multiscan_;
size_t icc_index_;
size_t icc_total_;
std::vector<uint8_t> icc_profile_;
@ -66,16 +74,13 @@ struct jpeg_decomp_master {
uint8_t markers_to_save_[32];
jpeg_marker_parser_method app_marker_parsers[16];
jpeg_marker_parser_method com_marker_parser;
// Whether this jpeg has multiple scans (progressive or non-interleaved
// sequential).
bool is_multiscan_;
// Fields defined by SOF marker.
size_t iMCU_cols_;
int h_factor[jpegli::kMaxComponents];
int v_factor[jpegli::kMaxComponents];
// Initialized at strat of frame.
// Initialized at start of frame.
uint16_t scan_progression_[jpegli::kMaxComponents][DCTSIZE2];
//
@ -96,9 +101,11 @@ struct jpeg_decomp_master {
//
int output_passes_done_;
JpegliDataType output_data_type_ = JPEGLI_TYPE_UINT8;
bool swap_endianness_ = false;
size_t xoffset_;
bool swap_endianness_ = false;
bool need_context_rows_;
bool regenerate_inverse_colormap_;
bool apply_smoothing;
int min_scaled_dct_size;
int scaled_dct_size[jpegli::kMaxComponents];
@ -127,7 +134,6 @@ struct jpeg_decomp_master {
uint8_t* pixels_;
JSAMPARRAY scanlines_;
std::vector<std::vector<uint8_t>> candidate_lists_;
bool regenerate_inverse_colormap_;
float* dither_[jpegli::kMaxComponents];
float* error_row_[2 * jpegli::kMaxComponents];
size_t dither_size_;
@ -145,7 +151,6 @@ struct jpeg_decomp_master {
// i.e. the bottom half when rendering incomplete scans.
int (*coef_bits_latch)[SAVED_COEFS];
int (*prev_coef_bits_latch)[SAVED_COEFS];
bool apply_smoothing;
};
#endif // LIB_JPEGLI_DECODE_INTERNAL_H_

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше