Bug 1904318 - Update libjxl by release instead of weeks r=tnikkel

This also matches what we do for several other media libraries e.g. libaom: https://searchfox.org/mozilla-central/search?q=frequency:%20release&path=&case=true&regexp=false

Differential Revision: https://phabricator.services.mozilla.com/D214710
This commit is contained in:
Kagami Sascha Rosylight 2024-06-24 14:00:23 +00:00
parent 4a4a1b2ec4
commit 68a70d49b5
421 changed files with 6905 additions and 9948 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Modified build files in third_party/libwebrtc - Bug 1897501 - Vendor libwebrtc from 326df690b2
Modified build files in third_party/jpeg-xl - Bug 1904318 - Update libjxl by release instead of weeks

View File

@ -15,6 +15,7 @@ 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",
@ -84,7 +85,6 @@ 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",
]

View File

@ -10,9 +10,9 @@ origin:
url: https://github.com/libjxl/libjxl
release: d947eb5f98f04a403bc5e96c1f4c71e6a1b3cca4 (2024-06-05T13:13:01Z).
release: e1489592a770b989303b0edc5cc1dc447bbe0515 (2024-03-08T08:10:58Z).
revision: d947eb5f98f04a403bc5e96c1f4c71e6a1b3cca4
revision: e1489592a770b989303b0edc5cc1dc447bbe0515
license: Apache-2.0
@ -24,7 +24,7 @@ updatebot:
tasks:
- type: vendoring
enabled: True
frequency: 3 weeks
frequency: release
vendoring:
url: https://github.com/libjxl/libjxl

View File

@ -25,20 +25,17 @@ 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,

View File

@ -39,7 +39,6 @@ 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>
@ -54,13 +53,11 @@ 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>

View File

@ -5,17 +5,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## Unreleased
### Added
### Removed
### Changed / clarified
### Fixed
## [0.10.2] - 2024-03-08
### Fixed

View File

@ -21,10 +21,6 @@ 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)
@ -164,14 +160,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_THREADS true CACHE BOOL
set(JPEGXL_ENABLE_WASM_TRHEADS 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) instead of third_party/googletest source.")
"Force using system installed googletest (gtest/gmock) instead of third_party/googletest source.")
set(JPEGXL_FORCE_SYSTEM_LCMS2 false CACHE BOOL
"Force using system installed lcms2 instead of third_party/lcms source.")
set(JPEGXL_FORCE_SYSTEM_HWY false CACHE BOOL
@ -215,12 +211,10 @@ if(JPEGXL_STATIC)
# 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)
string(APPEND CMAKE_EXE_LINKER_FLAGS " -static")
endif()
if ((NOT WIN32 AND NOT APPLE) OR CYGWIN OR MINGW)
if (NOT MSVC AND NOT APPLE)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
string(APPEND CMAKE_EXE_LINKER_FLAGS " -static-libgcc -static-libstdc++")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -static -static-libgcc -static-libstdc++")
endif()
endif() # JPEGXL_STATIC
@ -230,16 +224,7 @@ find_package(Threads REQUIRED)
# These settings are important to drive check_cxx_source_compiles
# See CMP0067 (min cmake version is 3.10 anyway)
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_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
@ -280,7 +265,7 @@ if(JPEGXL_STATIC)
endif()
endif() # JPEGXL_STATIC
if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_THREADS)
if (EMSCRIPTEN AND JPEGXL_ENABLE_WASM_TRHEADS)
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")
@ -446,7 +431,7 @@ if(JPEGXL_ENABLE_MANPAGES)
find_program(ASCIIDOC a2x)
if(ASCIIDOC)
file(STRINGS "${ASCIIDOC}" ASCIIDOC_SHEBANG LIMIT_COUNT 1)
if(ASCIIDOC_SHEBANG MATCHES "sh$" OR MINGW)
if(ASCIIDOC_SHEBANG MATCHES "/sh|/bash" OR MINGW)
set(ASCIIDOC_PY_FOUND ON)
# Run the program directly and set ASCIIDOC as empty.
set(ASCIIDOC_PY "${ASCIIDOC}")

View File

@ -1,7 +1,4 @@
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "giflib", version = "5.2.1")
bazel_dep(name = "googletest", version = "1.14.0")
bazel_dep(name = "libjpeg_turbo", version = "2.1.91")
bazel_dep(name = "libpng", version = "1.6.40")
bazel_dep(name = "libwebp", version = "1.3.2")
bazel_dep(name = "openexr", version = "3.2.1")
bazel_dep(name = "libpng", version = "1.6.40")

View File

@ -73,14 +73,11 @@ 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:
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`).
When possible `cjxl`/`djxl` are able to read/write the following
image formats: .exr, .gif, .jpeg/.jpg, .pfm, .pgm/.ppm, .pgx, .png.
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

View File

@ -1,5 +1,5 @@
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")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
workspace(name = "libjxl")
@ -30,3 +30,185 @@ 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",
)

View File

@ -106,6 +106,12 @@ 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

View File

@ -16,8 +16,6 @@ MYDIR=$(dirname $(realpath "$0"))
### 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:-}
@ -81,12 +79,6 @@ 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
@ -136,34 +128,17 @@ if [[ "${BUILD_TARGET%%-*}" != "arm" ]]; then
)
fi
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)}
CLANG_TIDY_BIN=$(which clang-tidy-6.0 clang-tidy-7 clang-tidy-8 clang-tidy | head -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 2>/dev/null | head -n 1)
COLORDIFF_BIN=$(which colordiff cat | head -n 1)
else
COLORDIFF_BIN="cat"
fi
FIND_BIN=$(which gfind find 2>/dev/null | head -n 1)
FIND_BIN=$(which gfind find | head -n 1)
# "false" will disable wine64 when not installed. This won't allow
# cross-compiling.
WINE_BIN=$(which wine64 false 2>/dev/null | head -n 1)
WINE_BIN=$(which wine64 false | head -n 1)
CLANG_VERSION="${CLANG_VERSION:-}"
# Detect the clang version suffix and store it in CLANG_VERSION. For example,
@ -436,7 +411,7 @@ cmake_build_and_test() {
if [[ "${PACK_TEST:-}" == "1" ]]; then
(cd "${BUILD_DIR}"
${FIND_BIN} -name '*.cmake' -a '!' -path '*CMakeFiles*'
# gtest / gtest_main shared libs
# gtest / gmock / 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 - \
@ -484,7 +459,7 @@ strip_dead_code() {
### Externally visible commands
cmd_debug() {
CMAKE_BUILD_TYPE="DebugOpt"
CMAKE_BUILD_TYPE="Debug"
cmake_configure "$@"
cmake_build_and_test
}
@ -498,7 +473,7 @@ cmd_release() {
cmd_opt() {
CMAKE_BUILD_TYPE="RelWithDebInfo"
CMAKE_CXX_FLAGS+=" -DJXL_DEBUG_BUILD -DJXL_DEBUG_ON_ERROR"
CMAKE_CXX_FLAGS+=" -DJXL_DEBUG_WARNING -DJXL_DEBUG_ON_ERROR"
cmake_configure "$@"
cmake_build_and_test
}
@ -578,7 +553,6 @@ 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.
@ -607,11 +581,13 @@ cmd_tsan() {
-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
}
@ -663,22 +639,16 @@ cmd_msan() {
-Wl,-rpath -Wl,"${msan_prefix}"/lib/
)
CMAKE_C_FLAGS+=" ${msan_c_flags[@]}"
CMAKE_CXX_FLAGS+=" ${msan_cxx_flags[@]}"
CMAKE_C_FLAGS+=" ${msan_c_flags[@]} ${UBSAN_FLAGS[@]}"
CMAKE_CXX_FLAGS+=" ${msan_cxx_flags[@]} ${UBSAN_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[@]}" \
-DJPEGXL_ENABLE_FUZZERS=OFF
-DCMAKE_REQUIRED_LINK_OPTIONS="${msan_linker_flags[@]}"
cmake_build_and_test
}
@ -687,8 +657,6 @@ 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++}"
@ -696,36 +664,23 @@ cmd_msan_install() {
# Allow overriding the LLVM checkout.
local llvm_root="${LLVM_ROOT:-}"
if [ -z "${llvm_root}" ]; then
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
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"
tar -C "${tmpdir}" -zxf "${llvm_targz}"
llvm_root="${tmpdir}/llvm-project-${llvm_tag}"
fi
local msan_prefix="${msan_root}/${CLANG_VERSION}"
local msan_prefix="${HOME}/.msan/${CLANG_VERSION}"
rm -rf "${msan_prefix}"
local TARGET_OPTS=""
@ -737,29 +692,32 @@ cmd_msan_install() {
"
fi
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
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
}
# Internal build step shared between all cmd_ossfuzz_* commands.
@ -833,13 +791,9 @@ 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}"
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
curl --show-error -o "${small_corpus_tar}" -z "${small_corpus_tar}" \
"https://storage.googleapis.com/artifacts.jpegxl.appspot.com/corpora/jyrki-full.tar"
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
@ -877,7 +831,7 @@ cmd_benchmark() {
png_filename="${filename%.ppm}.png"
png_filename=$(echo "${png_filename}" | tr '/' '_')
sem --bg --id "${sem_id}" -j"${nprocs}" -- \
"${TOOLS_DIR}/decode_and_encode" \
"${BUILD_DIR}/tools/decode_and_encode" \
"${tmpdir}/${filename}" "${mode}" "${tmpdir}/${png_filename}"
images+=( "${png_filename}" )
done < <(cd "${tmpdir}"; ${FIND_BIN} . -name '*.ppm' -type f)
@ -890,8 +844,6 @@ 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
@ -904,24 +856,15 @@ run_benchmark() {
local output_dir="${BUILD_DIR}/benchmark_results"
mkdir -p "${output_dir}"
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
# 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
fi
local benchmark_args=(
@ -930,20 +873,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}"
"${TOOLS_DIR}/benchmark_xl" "${benchmark_args[@]}" | \
"${BUILD_DIR}/tools/benchmark_xl" "${benchmark_args[@]}" | \
tee "${output_dir}/results.txt"
# Check error code for benchmark_xl command. This will exit if not.
# Check error code for benckmark_xl command. This will exit if not.
return ${PIPESTATUS[0]}
)
}
# Helper function to wait for the CPU temperature to cool down on ARM.
@ -1084,7 +1027,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=("${TOOLS_DIR}/cjxl")
local enc_binaries=("${BUILD_DIR}/tools/cjxl")
local src_ext="${src_img##*.}"
for enc_binary in "${enc_binaries[@]}"; do
local enc_binary_base=$(basename "${enc_binary}")
@ -1133,7 +1076,7 @@ cmd_arm_benchmark() {
local dec_output
wait_for_temp
dec_output=$("${TOOLS_DIR}/djxl" "${enc_file}" \
dec_output=$("${BUILD_DIR}/tools/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 ',')
@ -1149,7 +1092,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=$("${TOOLS_DIR}/djxl" "${enc_file}" \
dec_output=$("${BUILD_DIR}/tools/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}")
@ -1179,12 +1122,12 @@ cmd_fuzz() {
local fuzzer_crash_dir=$(realpath "${BUILD_DIR}/fuzzer_crash")
mkdir -p "${corpus_dir}" "${fuzzer_crash_dir}"
# Generate step.
"${TOOLS_DIR}/fuzzer_corpus" "${corpus_dir}"
"${BUILD_DIR}/tools/fuzzer_corpus" "${corpus_dir}"
# Run step:
local nprocs=$(nproc --all || echo 1)
(
cd "${TOOLS_DIR}"
djxl_fuzzer "${fuzzer_crash_dir}" "${corpus_dir}" \
cd "${BUILD_DIR}"
"tools/djxl_fuzzer" "${fuzzer_crash_dir}" "${corpus_dir}" \
-max_total_time="${FUZZER_MAX_TIME}" -jobs=${nprocs} \
-artifact_prefix="${fuzzer_crash_dir}/"
)
@ -1224,15 +1167,6 @@ 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

View File

@ -1,4 +1,4 @@
jpeg-xl (0.10.2) unstable; urgency=medium
jpeg-xl (0.10.2) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.10.2.

View File

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

View File

@ -97,7 +97,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
return false;
}
long size = ftell(file); // NOLINT
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);

View File

@ -169,7 +169,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
return false;
}
long size = ftell(file); // NOLINT
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);

View File

@ -6,20 +6,16 @@
// This C++ example decodes a JPEG XL image progressively (input bytes are
// passed in chunks). The example outputs the intermediate steps to PAM files.
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
#include <inttypes.h>
#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) {
@ -178,7 +174,7 @@ bool LoadFile(const char* filename, std::vector<uint8_t>* out) {
return false;
}
long size = ftell(file); // NOLINT
long size = ftell(file);
// Avoid invalid file or directory.
if (size >= LONG_MAX || size < 0) {
fclose(file);
@ -224,7 +220,7 @@ int main(int argc, char* argv[]) {
}
size_t chunksize = jxl.size();
if (argc > 3) {
long cs = atol(argv[3]); // NOLINT
long cs = atol(argv[3]);
if (cs < 100) {
fprintf(stderr, "Chunk size is too low, try at least 100 bytes\n");
return 1;

View File

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

View File

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

View File

@ -3,9 +3,6 @@
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
# Load sources/headers/tests lists.
load(
"jxl_lists.bzl",
@ -26,8 +23,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,12 +51,13 @@ load(
"libjxl_deps_png",
"libjxl_deps_runfiles",
"libjxl_deps_skcms",
# "libjxl_deps_testdata",
# "libjxl_deps_webp",
"libjxl_deps_testdata",
"libjxl_root_package",
"libjxl_test_shards",
"libjxl_test_timeouts",
)
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
DEFAULT_VISIBILITY = ["//:__subpackages__"]
@ -68,7 +66,7 @@ DEFAULT_COMPATIBILITY = []
INCLUDES_DIR = "include"
package(
default_visibility = DEFAULT_VISIBILITY,
default_visibility = ["//:__subpackages__"],
)
licenses(["notice"])

View File

@ -20,8 +20,7 @@ void AlphaBlend(PackedFrame* frame, const float background[3]) {
return;
}
--format.num_channels;
JXL_ASSIGN_OR_DIE(PackedImage blended,
PackedImage::Create(im.xsize, im.ysize, format));
PackedImage blended(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) {

View File

@ -26,7 +26,6 @@
#include "lib/extras/enc/encode.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/byte_order.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"
@ -41,6 +40,12 @@ using test::ThreadPoolForTests;
namespace extras {
namespace {
using ::testing::AllOf;
using ::testing::Contains;
using ::testing::Field;
using ::testing::IsEmpty;
using ::testing::SizeIs;
std::string ExtensionFromCodec(Codec codec, const bool is_gray,
const bool has_alpha,
const size_t bits_per_sample) {
@ -228,17 +233,13 @@ void CreateTestImage(const TestImageParams& params, PackedPixelFile* ppf) {
ppf->icc = GenerateICC(color_encoding);
ppf->color_encoding = color_encoding;
JXL_ASSIGN_OR_DIE(
PackedFrame frame,
PackedFrame::Create(params.xsize, params.ysize, params.PixelFormat()));
PackedFrame frame(params.xsize, params.ysize, params.PixelFormat());
FillPackedImage(params.bits_per_sample, &frame.color);
if (params.add_extra_channels) {
for (size_t i = 0; i < 7; ++i) {
JxlPixelFormat ec_format = params.PixelFormat();
ec_format.num_channels = 1;
JXL_ASSIGN_OR_DIE(
PackedImage ec,
PackedImage::Create(params.xsize, params.ysize, ec_format));
PackedImage ec(params.xsize, params.ysize, ec_format);
FillPackedImage(params.bits_per_sample, &ec);
frame.extra_channels.emplace_back(std::move(ec));
PackedExtraChannel pec;
@ -334,10 +335,10 @@ TEST(CodecTest, TestRoundTrip) {
params.add_alpha = add_alpha;
params.big_endian = big_endian;
params.add_extra_channels = false;
TestRoundTrip(params, pool.get());
TestRoundTrip(params, &pool);
if (codec == Codec::kPNM && add_alpha) {
params.add_extra_channels = true;
TestRoundTrip(params, pool.get());
TestRoundTrip(params, &pool);
}
}
}
@ -370,7 +371,7 @@ TEST(CodecTest, LosslessPNMRoundtrip) {
EncodedImage encoded;
auto encoder = Encoder::FromExtension(extension);
ASSERT_TRUE(encoder.get());
ASSERT_TRUE(encoder->Encode(ppf, &encoded, pool.get()));
ASSERT_TRUE(encoder->Encode(ppf, &encoded, &pool));
ASSERT_EQ(encoded.bitstreams.size(), 1);
ASSERT_EQ(orig.size(), encoded.bitstreams[0].size());
EXPECT_EQ(0,
@ -431,17 +432,15 @@ TEST(CodecTest, EncodeToPNG) {
ASSERT_TRUE(extras::DecodeBytes(Bytes(original_png), ColorHints(), &ppf));
const JxlPixelFormat& format = ppf.frames.front().color.format;
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));
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))));
EncodedImage encoded_png;
ASSERT_TRUE(png_encoder->Encode(ppf, &encoded_png, pool));
EXPECT_TRUE(encoded_png.icc.empty());
ASSERT_EQ(encoded_png.bitstreams.size(), 1);
EXPECT_THAT(encoded_png.icc, IsEmpty());
ASSERT_THAT(encoded_png.bitstreams, SizeIs(1));
PackedPixelFile decoded_ppf;
ASSERT_TRUE(extras::DecodeBytes(Bytes(encoded_png.bitstreams.front()),

View File

@ -1,43 +0,0 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <jxl/compressed_icc.h>
#include "lib/jxl/enc_aux_out.h"
#include "lib/jxl/enc_icc_codec.h"
#include "lib/jxl/icc_codec.h"
JXL_BOOL JxlICCProfileEncode(JxlMemoryManager* memory_manager,
const uint8_t* icc, size_t icc_size,
uint8_t** compressed_icc,
size_t* compressed_icc_size) {
jxl::BitWriter writer(memory_manager);
JXL_RETURN_IF_ERROR(jxl::WriteICC(jxl::Span<const uint8_t>(icc, icc_size),
&writer, jxl::LayerType::Header, nullptr));
writer.ZeroPadToByte();
*compressed_icc_size = writer.GetSpan().size();
*compressed_icc = static_cast<uint8_t*>(
memory_manager->alloc(memory_manager->opaque, *compressed_icc_size));
memcpy(*compressed_icc, writer.GetSpan().data(), *compressed_icc_size);
return JXL_TRUE;
}
JXL_BOOL JxlICCProfileDecode(JxlMemoryManager* memory_manager,
const uint8_t* compressed_icc,
size_t compressed_icc_size, uint8_t** icc,
size_t* icc_size) {
jxl::ICCReader icc_reader(memory_manager);
jxl::PaddedBytes decompressed(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, /*output_limit=*/0));
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*>(
memory_manager->alloc(memory_manager->opaque, *icc_size));
memcpy(*icc, decompressed.data(), *icc_size);
return JXL_TRUE;
}

View File

@ -1,40 +0,0 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "jxl/compressed_icc.h"
#include "lib/jxl/test_memory_manager.h"
#include "lib/jxl/test_utils.h"
#include "lib/jxl/testing.h"
namespace jxl {
namespace {
TEST(CompressedIccTest, Roundtrip) {
JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
uint8_t* compressed_icc;
size_t compressed_icc_size;
const IccBytes icc = jxl::test::GetIccTestProfile();
ASSERT_TRUE(JxlICCProfileEncode(memory_manager, icc.data(), icc.size(),
&compressed_icc, &compressed_icc_size));
EXPECT_LT(compressed_icc_size, icc.size());
uint8_t* decompressed_icc;
size_t decompressed_icc_size;
ASSERT_TRUE(JxlICCProfileDecode(memory_manager, compressed_icc,
compressed_icc_size, &decompressed_icc,
&decompressed_icc_size));
ASSERT_EQ(decompressed_icc_size, icc.size());
EXPECT_EQ(0, memcmp(decompressed_icc, icc.data(), decompressed_icc_size));
memory_manager->free(memory_manager->opaque, compressed_icc);
memory_manager->free(memory_manager->opaque, decompressed_icc);
}
} // namespace
} // namespace jxl

File diff suppressed because it is too large Load Diff

View File

@ -8,10 +8,11 @@
// Decodes APNG images in memory.
#include <cstdint>
#include <stdint.h>
#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"

View File

@ -203,38 +203,12 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) {
Status ParseDescription(const std::string& description, JxlColorEncoding* c) {
*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));
}
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;
}

View File

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

View File

@ -8,9 +8,11 @@
// Facade for image decoders (PNG, PNM, ...).
#include <cstddef>
#include <cstdint>
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "lib/extras/dec/color_hints.h"
#include "lib/jxl/base/span.h"
@ -36,8 +38,6 @@ 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,

View File

@ -5,8 +5,6 @@
#include "lib/extras/dec/exr.h"
#include "lib/jxl/base/common.h"
#if JPEGXL_ENABLE_EXR
#include <ImfChromaticitiesAttribute.h>
#include <ImfIO.h>
@ -83,7 +81,7 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
#ifdef __EXCEPTIONS
std::unique_ptr<OpenEXR::RgbaInputFile> input_ptr;
try {
input_ptr = jxl::make_unique<OpenEXR::RgbaInputFile>(is);
input_ptr.reset(new OpenEXR::RgbaInputFile(is));
} catch (...) {
// silently return false if it is not an EXR file
return false;
@ -123,12 +121,7 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
};
ppf->frames.clear();
// Allocates the frame buffer.
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(image_size.x, image_size.y, format));
ppf->frames.emplace_back(std::move(frame));
}
ppf->frames.emplace_back(image_size.x, image_size.y, format);
const auto& frame = ppf->frames.back();
const int row_size = input.dataWindow().size().x + 1;

View File

@ -9,16 +9,15 @@
#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/base/rect.h"
#include "lib/jxl/base/sanitizers.h"
#include "lib/jxl/sanitizers.h"
namespace jxl {
namespace extras {
@ -51,10 +50,8 @@ void ensure_have_alpha(PackedFrame* frame) {
/*endianness=*/JXL_NATIVE_ENDIAN,
/*align=*/0,
};
JXL_ASSIGN_OR_DIE(PackedImage image,
PackedImage::Create(frame->color.xsize, frame->color.ysize,
alpha_format));
frame->extra_channels.emplace_back(std::move(image));
frame->extra_channels.emplace_back(frame->color.xsize, frame->color.ysize,
alpha_format);
// 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);
@ -140,7 +137,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 censiseconds.
// Delays in GIF are specified in 100ths of a second.
ppf->info.animation.tps_numerator = 100;
ppf->info.animation.tps_denominator = 1;
}
@ -189,9 +186,7 @@ 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};
JXL_ASSIGN_OR_RETURN(
PackedFrame canvas,
PackedFrame::Create(gif->SWidth, gif->SHeight, canvas_format));
PackedFrame canvas(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};
@ -235,14 +230,8 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Allocates the frame buffer.
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(total_rect.xsize(), total_rect.ysize(),
packed_frame_format));
ppf->frames.emplace_back(std::move(frame));
}
ppf->frames.emplace_back(total_rect.xsize(), total_rect.ysize(),
packed_frame_format);
PackedFrame* frame = &ppf->frames.back();
// We cannot tell right from the start whether there will be a
@ -312,10 +301,8 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Update the canvas by creating a copy first.
JXL_ASSIGN_OR_RETURN(
PackedImage new_canvas_image,
PackedImage::Create(canvas.color.xsize, canvas.color.ysize,
canvas.color.format));
PackedImage new_canvas_image(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) {

View File

@ -6,17 +6,16 @@
#include "lib/extras/dec/jpegli.h"
#include <setjmp.h>
#include <stdint.h>
#include <algorithm>
#include <cstdint>
#include <memory>
#include <numeric>
#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 {
@ -115,12 +114,12 @@ void MyErrorExit(j_common_ptr cinfo) {
}
void MyOutputMessage(j_common_ptr cinfo) {
if (JXL_DEBUG_BUILD) {
char buf[JMSG_LENGTH_MAX + 1];
(*cinfo->err->format_message)(cinfo, buf);
buf[JMSG_LENGTH_MAX] = 0;
JXL_WARNING("%s", buf);
}
#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
}
void UnmapColors(uint8_t* row, size_t xsize, int components,
@ -182,9 +181,7 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
}
int nbcomp = cinfo.num_components;
if (nbcomp != 1 && nbcomp != 3) {
std::string msg =
"unsupported number of components in JPEG: " + std::to_string(nbcomp);
return failure(msg.c_str());
return failure("unsupported number of components in JPEG");
}
if (dparams.force_rgb) {
cinfo.out_color_space = JCS_RGB;
@ -249,12 +246,7 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
};
ppf->frames.clear();
// Allocates the frame buffer.
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
ppf->frames.emplace_back(std::move(frame));
}
ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=

View File

@ -6,19 +6,19 @@
#include "lib/extras/dec/jpg.h"
#if JPEGXL_ENABLE_JPEG
#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#include <jpeglib.h>
#include <setjmp.h>
#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 {
@ -156,12 +156,12 @@ void MyErrorExit(j_common_ptr cinfo) {
}
void MyOutputMessage(j_common_ptr cinfo) {
if (JXL_DEBUG_BUILD) {
char buf[JMSG_LENGTH_MAX + 1];
(*cinfo->err->format_message)(cinfo, buf);
buf[JMSG_LENGTH_MAX] = 0;
JXL_WARNING("%s", buf);
}
#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
}
void UnmapColors(uint8_t* row, size_t xsize, int components,
@ -299,12 +299,7 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
ppf->frames.emplace_back(std::move(frame));
}
ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=

View File

@ -6,21 +6,14 @@
#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> // PRIu32
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <vector>
#include <cinttypes>
#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"
@ -125,7 +118,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(dparams.memory_manager);
auto decoder = JxlDecoderMake(/*memory_manager=*/nullptr);
JxlDecoder* dec = decoder.get();
ppf->frames.clear();
@ -218,7 +211,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
uint32_t progression_index = 0;
bool codestream_done = jpeg_bytes == nullptr && accepted_formats.empty();
bool codestream_done = accepted_formats.empty();
BoxProcessor boxes(dec);
for (;;) {
JxlDecoderStatus status = JxlDecoderProcessInput(dec);
@ -259,8 +252,6 @@ 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;
}
@ -401,13 +392,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
}
} else if (status == JXL_DEC_FRAME) {
auto frame_or = jxl::extras::PackedFrame::Create(ppf->info.xsize,
ppf->info.ysize, format);
if (!frame_or.status()) {
fprintf(stderr, "Failed to create image frame.");
return false;
}
jxl::extras::PackedFrame frame = std::move(frame_or).value();
jxl::extras::PackedFrame frame(ppf->info.xsize, ppf->info.ysize, format);
if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec, &frame.frame_info)) {
fprintf(stderr, "JxlDecoderGetFrameHeader failed\n");
return false;
@ -446,16 +431,9 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
fprintf(stderr, "JxlDecoderPreviewOutBufferSize failed\n");
return false;
}
auto preview_image_or = jxl::extras::PackedImage::Create(
ppf->info.preview.xsize, ppf->info.preview.ysize, format);
if (!preview_image_or.status()) {
fprintf(stderr, "Failed to create preview image\n");
return false;
}
jxl::extras::PackedImage preview_image =
std::move(preview_image_or).value();
ppf->preview_frame =
jxl::make_unique<jxl::extras::PackedFrame>(std::move(preview_image));
ppf->preview_frame = std::unique_ptr<jxl::extras::PackedFrame>(
new jxl::extras::PackedFrame(ppf->info.preview.xsize,
ppf->info.preview.ysize, format));
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);
@ -522,13 +500,8 @@ 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) {
auto image = jxl::extras::PackedImage::Create(
ppf->info.xsize, ppf->info.ysize, ec_format);
if (!image.status()) {
fprintf(stderr, "Failed to create extra channel image\n");
return false;
}
frame.extra_channels.emplace_back(std::move(image).value());
frame.extra_channels.emplace_back(ppf->info.xsize, ppf->info.ysize,
ec_format);
auto& ec = frame.extra_channels.back();
size_t buffer_size;
if (JXL_DEC_SUCCESS != JxlDecoderExtraChannelBufferSize(

View File

@ -8,12 +8,10 @@
// 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>
@ -40,9 +38,6 @@ 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;

View File

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

View File

@ -5,17 +5,10 @@
#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 {
@ -33,7 +26,7 @@ TEST(CodecPGXTest, Test8bits) {
ThreadPool* pool = nullptr;
EXPECT_TRUE(DecodeImagePGX(MakeSpan(pgx.c_str()), ColorHints(), &ppf));
CodecInOut io{jxl::test::MemoryManager()};
CodecInOut io;
EXPECT_TRUE(ConvertPackedPixelFileToCodecInOut(ppf, pool, &io));
ScaleImage(255.f, io.Main().color());
@ -60,7 +53,7 @@ TEST(CodecPGXTest, Test16bits) {
ThreadPool* pool = nullptr;
EXPECT_TRUE(DecodeImagePGX(MakeSpan(pgx.c_str()), ColorHints(), &ppf));
CodecInOut io{jxl::test::MemoryManager()};
CodecInOut io;
EXPECT_TRUE(ConvertPackedPixelFileToCodecInOut(ppf, pool, &io));
ScaleImage(255.f, io.Main().color());

View File

@ -5,18 +5,17 @@
#include "lib/extras/dec/pnm.h"
#include <jxl/encode.h>
#include <stdlib.h>
#include <string.h>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <mutex>
#include "jxl/encode.h"
#include "lib/extras/size_constraints.h"
#include "lib/jxl/base/bits.h"
#include "lib/jxl/base/c_callback_support.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
namespace jxl {
@ -333,7 +332,7 @@ struct PNMChunkedInputFrame {
METHOD_TO_C_CALLBACK(&PNMChunkedInputFrame::ReleaseCurrentData)};
}
void /* NOLINT */ GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
void GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
*pixel_format = format;
}
@ -350,14 +349,12 @@ struct PNMChunkedInputFrame {
void GetExtraChannelPixelFormat(size_t ec_index,
JxlPixelFormat* pixel_format) {
(void)this;
JXL_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) {
(void)this;
JXL_ABORT("Not implemented");
}
@ -394,8 +391,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 (size < header.ysize * row_size + dec.data_start_) {
return JXL_FAILURE("PNM file too small");
if (header.ysize * row_size + dec.data_start_ < size) {
return JXL_FAILURE("Invalid ppm");
}
return dec;
}
@ -476,7 +473,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));
@ -502,18 +499,10 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
};
const JxlPixelFormat ec_format{1, format.data_type, format.endianness, 0};
ppf->frames.clear();
{
JXL_ASSIGN_OR_RETURN(
PackedFrame frame,
PackedFrame::Create(header.xsize, header.ysize, format));
ppf->frames.emplace_back(std::move(frame));
}
ppf->frames.emplace_back(header.xsize, header.ysize, format);
auto* frame = &ppf->frames.back();
for (size_t i = 0; i < header.ec_types.size(); ++i) {
JXL_ASSIGN_OR_RETURN(
PackedImage ec,
PackedImage::Create(header.xsize, header.ysize, ec_format));
frame->extra_channels.emplace_back(std::move(ec));
frame->extra_channels.emplace_back(header.xsize, header.ysize, ec_format);
}
size_t pnm_remaining_size = bytes.data() + bytes.size() - pos;
if (pnm_remaining_size < frame->color.pixels_size) {
@ -548,9 +537,6 @@ 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;
}

View File

@ -73,30 +73,17 @@ 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);
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;
return EncodePackedPixelFileToAPNG(ppf, pool,
&encoded_image->bitstreams.front());
}
private:
Status EncodePackedPixelFileToAPNG(const PackedPixelFile& ppf,
ThreadPool* pool,
std::vector<uint8_t>* bytes,
bool encode_extra_channels = false,
size_t extra_channel_index = 0) const;
std::vector<uint8_t>* bytes) const;
};
void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
@ -260,13 +247,13 @@ 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_content_light_level =
const uint32_t max_cll =
static_cast<uint32_t>(10000.f * Clamp1(intensity_target, 0.f, 10000.f));
png_byte chunk_data[8] = {};
chunk_data[0] = (max_content_light_level >> 24) & 0xFF;
chunk_data[1] = (max_content_light_level >> 16) & 0xFF;
chunk_data[2] = (max_content_light_level >> 8) & 0xFF;
chunk_data[3] = max_content_light_level & 0xFF;
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;
// Leave MaxFALL set to 0.
png_unknown_chunk chunk;
memcpy(chunk.name, "cLLi", 5);
@ -279,21 +266,15 @@ void MaybeAddCLLi(const JxlColorEncoding& c_enc, const float intensity_target,
}
Status APNGEncoder::EncodePackedPixelFileToAPNG(
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;
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;
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");
@ -303,24 +284,9 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
size_t anim_chunks = 0;
for (const auto& frame : ppf.frames) {
const PackedImage& color = encode_extra_channels
? frame.extra_channels[extra_channel_index]
: frame.color;
JXL_RETURN_IF_ERROR(VerifyPackedImage(frame.color, ppf.info));
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 PackedImage& color = frame.color;
const JxlPixelFormat format = color.format;
const uint8_t* in = reinterpret_cast<const uint8_t*>(color.pixels());
size_t data_bits_per_sample = PackedImage::BitsPerChannel(format.data_type);
@ -331,23 +297,24 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
std::vector<uint8_t> out(out_size);
if (format.data_type == JXL_TYPE_UINT8) {
if (bits_per_sample < 8) {
float mul = 255.0 / ((1u << bits_per_sample) - 1);
if (ppf.info.bits_per_sample < 8) {
float mul = 255.0 / ((1u << ppf.info.bits_per_sample) - 1);
for (size_t i = 0; i < num_samples; ++i) {
out[i] = static_cast<uint8_t>(std::lroundf(in[i] * mul));
out[i] = static_cast<uint8_t>(in[i] * mul + 0.5);
}
} else {
memcpy(out.data(), in, out_size);
}
} else if (format.data_type == JXL_TYPE_UINT16) {
if (bits_per_sample < 16 || format.endianness != JXL_BIG_ENDIAN) {
float mul = 65535.0 / ((1u << bits_per_sample) - 1);
if (ppf.info.bits_per_sample < 16 ||
format.endianness != JXL_BIG_ENDIAN) {
float mul = 65535.0 / ((1u << ppf.info.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>(std::lroundf(val * mul)), p_out);
StoreBE16(static_cast<uint32_t>(val * mul + 0.5), p_out);
}
} else {
memcpy(out.data(), in, out_size);
@ -377,7 +344,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 && !encode_extra_channels) {
if (count == 0) {
if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
MaybeAddCICP(ppf.color_encoding, png_ptr, info_ptr);
if (!ppf.icc.empty()) {

View File

@ -134,13 +134,5 @@ 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

View File

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

View File

@ -54,10 +54,6 @@ 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) {
@ -253,48 +249,32 @@ JpegliEndianness ConvertEndianness(JxlEndianness endianness) {
}
}
void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t xsize,
size_t c_out, float* row_out) {
void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t len,
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 < 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;
}
for (size_t x = 0; x < len; ++x) {
row_out[x] = row_in[x] * kMul8;
}
} else if (format.data_type == JXL_TYPE_UINT16 && is_little_endian) {
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;
}
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadLE16(&row_in[2 * x]) * kMul16;
}
} else if (format.data_type == JXL_TYPE_UINT16 && !is_little_endian) {
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;
}
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadBE16(&row_in[2 * x]) * kMul16;
}
} else if (format.data_type == JXL_TYPE_FLOAT && is_little_endian) {
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]);
}
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadLEFloat(&row_in[4 * x]);
}
} else if (format.data_type == JXL_TYPE_FLOAT && !is_little_endian) {
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]);
}
for (size_t x = 0; x < len; ++x) {
row_out[x] = LoadBEFloat(&row_in[4 * x]);
}
}
}
@ -373,6 +353,9 @@ 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.");
}
@ -390,7 +373,7 @@ 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; // NOLINT
unsigned long output_size = 0;
std::vector<uint8_t> row_bytes;
size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize());
hwy::AlignedFreeUniquePtr<float[]> xyb_tmp =
@ -419,8 +402,6 @@ 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);
}
@ -454,10 +435,6 @@ 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));
@ -500,8 +477,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, image.xsize,
info.num_color_channels, src_buf);
ToFloatRow(&pixels[y * image.stride], image.format, 3 * image.xsize,
src_buf);
// convert to linear srgb
if (!c_transform.Run(0, src_buf, dst_buf, image.xsize)) {
return false;

View File

@ -6,23 +6,26 @@
#include "lib/extras/enc/jpg.h"
#if JPEGXL_ENABLE_JPEG
#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#include <jpeglib.h>
#include <setjmp.h>
#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"
@ -273,7 +276,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; // NOLINT
unsigned long size = 0;
jpeg_mem_dest(&cinfo, &buffer, &size);
cinfo.image_width = image.xsize;
cinfo.image_height = image.ysize;
@ -473,7 +476,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 = jxl::make_unique<MySearchHook>();
hook.reset(new MySearchHook());
hook->ReadBaseTables(params.custom_base_quant_fn);
hook->q_start = params.search_q_start;
hook->q_precision = params.search_q_precision;

View File

@ -5,18 +5,10 @@
#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 {
@ -120,7 +112,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(params.memory_manager);
auto encoder = JxlEncoderMake(/*memory_manager=*/nullptr);
JxlEncoder* enc = encoder.get();
if (params.allow_expert_options) {
@ -161,8 +153,7 @@ 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.jhgm.empty() || !ppf.metadata.jumbf.empty() ||
!ppf.metadata.iptc.empty();
!ppf.metadata.jumbf.empty() || !ppf.metadata.iptc.empty();
bool use_container = params.use_container || use_boxes ||
(has_jpeg_bytes && params.jpeg_store_metadata);
@ -211,7 +202,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 --allow_jpeg_reconstruction 0, to losslessly "
"Try using --jpeg_store_metadata 0, to losslessly "
"recompress the JPEG image data without bitstream "
"reconstruction data.\n");
} else {
@ -232,14 +223,7 @@ 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);
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);
basic_info.uses_original_profile = TO_JXL_BOOL(lossless);
if (params.override_bitdepth != 0) {
basic_info.bits_per_sample = params.override_bitdepth;
basic_info.exponent_bits_per_sample =
@ -261,7 +245,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
if (JXL_ENC_SUCCESS !=
JxlEncoderSetFrameBitDepth(settings, &ppf.input_bitdepth)) {
JxlEncoderSetFrameBitDepth(settings, &params.input_bitdepth)) {
fprintf(stderr, "JxlEncoderSetFrameBitDepth() failed.\n");
return false;
}
@ -307,9 +291,10 @@ 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},
{"jhgm", ppf.metadata.jhgm},
{"Exif", exif_with_offset},
{"xml ", ppf.metadata.xmp},
{"jumb", ppf.metadata.jumbf},
{"xml ", ppf.metadata.iptc},
};
for (auto box : boxes) {
if (!box.bytes.empty()) {

View File

@ -7,13 +7,11 @@
#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"
@ -38,41 +36,32 @@ 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;
// If runner_opaque is set, the encoder uses this parallel runner.
// 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.
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;

View File

@ -26,7 +26,7 @@ namespace jxl {
namespace extras {
namespace {
constexpr size_t kMaxHeaderSize = 2000;
constexpr size_t kMaxHeaderSize = 200;
class BasePNMEncoder : public Encoder {
public:
@ -87,8 +87,8 @@ class PNMEncoder : public BasePNMEncoder {
}
private:
static Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
std::vector<uint8_t>* bytes) {
Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
std::vector<uint8_t>* bytes) const {
uint32_t maxval = (1u << bits_per_sample) - 1;
char type = image.format.num_channels == 1 ? '5' : '6';
char header[kMaxHeaderSize];
@ -161,8 +161,8 @@ class PFMEncoder : public BasePNMEncoder {
}
private:
static Status EncodeImage(const PackedImage& image,
std::vector<uint8_t>* bytes) {
Status EncodeImage(const PackedImage& image,
std::vector<uint8_t>* bytes) const {
char type = image.format.num_channels == 1 ? 'f' : 'F';
double scale = image.format.endianness == JXL_LITTLE_ENDIAN ? -1.0 : 1.0;
char header[kMaxHeaderSize];

View File

@ -1,231 +0,0 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#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);
uint8_t color_enc_size =
static_cast<uint8_t>(color_encoding_writer.GetSpan().size());
SAFE_CURSOR_UPDATE(1);
memcpy(output_buffer + cursor, &color_enc_size, 1);
SAFE_CURSOR_UPDATE(color_enc_size);
memcpy(output_buffer + cursor, color_encoding_writer.GetSpan().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;
}

View File

@ -1,170 +0,0 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "jxl/gain_map.h"
#include <jxl/encode.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#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 = 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

View File

@ -156,8 +156,8 @@ TEST(JpegliTest, JpegliXYBEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.45f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.45f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
}
TEST(JpegliTest, JpegliDecodeTestLargeSmoothArea) {
@ -205,8 +205,8 @@ TEST(JpegliTest, JpegliYUVEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.7f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.7f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
}
TEST(JpegliTest, JpegliYUVChromaSubsamplingEncodeTest) {
@ -247,15 +247,15 @@ TEST(JpegliTest, JpegliYUVEncodeTestNoAq) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.85f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.25f);
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.85f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.25f));
}
TEST(JpegliTest, JpegliHDRRoundtripTest) {
std::string testimage = "jxl/hdr_room.png";
PackedPixelFile ppf_in;
ASSERT_TRUE(ReadTestImage(testimage, &ppf_in));
EXPECT_EQ("Rec2100HLG", Description(ppf_in.color_encoding));
EXPECT_EQ("RGB_D65_202_Rel_HLG", 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_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 2.95f);
EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.05f);
EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(2.95f));
EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.05f));
}
TEST(JpegliTest, JpegliSetAppData) {

View File

@ -16,7 +16,6 @@
#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();

View File

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

View File

@ -12,19 +12,22 @@
#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"
@ -34,18 +37,11 @@ namespace extras {
// Class representing an interleaved image with a bunch of channels.
class PackedImage {
public:
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(size_t xsize, size_t ysize, const JxlPixelFormat& format)
: PackedImage(xsize, ysize, format, CalcStride(format, xsize)) {}
PackedImage Copy() const {
PackedImage copy(xsize, ysize, format, CalcStride(format, xsize));
PackedImage copy(xsize, ysize, format);
memcpy(reinterpret_cast<uint8_t*>(copy.pixels()),
reinterpret_cast<const uint8_t*>(pixels()), pixels_size);
return copy;
@ -173,20 +169,11 @@ class PackedImage {
// as all other frames in the same image.
class PackedFrame {
public:
explicit PackedFrame(PackedImage&& image) : color(std::move(image)) {}
template <typename... Args>
explicit PackedFrame(Args&&... args) : color(std::forward<Args>(args)...) {}
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));
PackedFrame Copy() const {
PackedFrame copy(color.xsize, color.ysize, color.format);
copy.frame_info = frame_info;
copy.name = name;
copy.color = color.Copy();
@ -237,7 +224,6 @@ 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;
};
@ -275,8 +261,6 @@ 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;

View File

@ -7,12 +7,10 @@
#include <jxl/cms.h>
#include <jxl/color_encoding.h>
#include <jxl/memory_manager.h>
#include <jxl/types.h>
#include <cstdint>
#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"
@ -24,16 +22,15 @@ namespace jxl {
namespace extras {
Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
const JxlBitDepth& input_bitdepth,
const PackedFrame& frame,
const CodecInOut& io, ThreadPool* pool,
ImageBundle* bundle) {
JxlMemoryManager* memory_manager = io.memory_manager;
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 =
input_bitdepth.type == JXL_BIT_DEPTH_FROM_PIXEL_FORMAT
? PackedImage::BitsPerChannel(frame.color.format.data_type)
: info.bits_per_sample;
float_in ? PackedImage::BitsPerChannel(frame.color.format.data_type)
: info.bits_per_sample;
JXL_ASSERT(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.
@ -67,9 +64,8 @@ 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(memory_manager, ppf_ec.xsize, ppf_ec.ysize));
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]));
@ -79,7 +75,6 @@ Status ConvertPackedFrameToImageBundle(const JxlBasicInfo& info,
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());
if (has_alpha) {
@ -146,7 +141,6 @@ 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;
@ -177,16 +171,15 @@ 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.input_bitdepth, *ppf.preview_frame, *io, pool,
&io->preview_frame));
ppf.info, *ppf.preview_frame, *io, pool, &io->preview_frame));
}
// Convert the pixels
io->frames.clear();
for (const auto& frame : ppf.frames) {
ImageBundle bundle(memory_manager, &io->metadata.m);
JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
ppf.info, ppf.input_bitdepth, frame, *io, pool, &bundle));
ImageBundle bundle(&io->metadata.m);
JXL_RETURN_IF_ERROR(
ConvertPackedFrameToImageBundle(ppf.info, frame, *io, pool, &bundle));
io->frames.push_back(std::move(bundle));
}
@ -199,7 +192,7 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
} else {
SetIntensityTarget(&io->metadata.m);
}
JXL_RETURN_IF_ERROR(io->CheckMetadata());
io->CheckMetadata();
return true;
}
@ -218,8 +211,7 @@ PackedPixelFile ConvertImage3FToPackedPixelFile(const Image3F& image,
: 0;
ppf.color_encoding = c_enc.ToExternal();
ppf.frames.clear();
JXL_ASSIGN_OR_DIE(PackedFrame frame,
PackedFrame::Create(image.xsize(), image.ysize(), format));
PackedFrame frame(image.xsize(), image.ysize(), format);
const ImageF* channels[3];
for (int c = 0; c < 3; ++c) {
channels[c] = &image.Plane(c);
@ -239,7 +231,6 @@ 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());
@ -293,7 +284,6 @@ 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 ||
@ -312,9 +302,8 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
/*endianness=*/pixel_format.endianness,
/*align=*/pixel_format.align};
JXL_ASSIGN_OR_RETURN(PackedFrame packed_frame,
PackedFrame::Create(frame.oriented_xsize(),
frame.oriented_ysize(), format));
PackedFrame packed_frame(frame.oriented_xsize(), frame.oriented_ysize(),
format);
const size_t bits_per_sample =
float_out ? packed_frame.color.BitsPerChannel(pixel_format.data_type)
: ppf->info.bits_per_sample;
@ -324,7 +313,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(memory_manager, &metadata);
ImageBundle store(&metadata);
const ImageBundle* transformed;
// TODO(firsching): handle the transform here.
JXL_RETURN_IF_ERROR(TransformIfNeeded(*to_color_transform, c_desired,
@ -340,7 +329,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 ? 1 : 0));
JXL_CHECK(frame.extra_channels().size() <= has_alpha);
ppf->frames.push_back(std::move(packed_frame));
}

View File

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

View File

@ -19,7 +19,7 @@ HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
static constexpr Vector3 rec2020_luminances{0.2627f, 0.6780f, 0.0593f};
static constexpr float rec2020_luminances[3] = {0.2627f, 0.6780f, 0.0593f};
Status ToneMapFrame(const std::pair<float, float> display_nits,
ImageBundle* const ib, ThreadPool* const pool) {

View File

@ -3,18 +3,15 @@
// 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/image.h"
#include "tools/no_memory_manager.h"
namespace jxl {
static void BM_ToneMapping(benchmark::State& state) {
JxlMemoryManager* memory_manager = jpegxl::tools::NoMemoryManager();
JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(memory_manager, 2268, 1512));
JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(2268, 1512));
FillImage(0.5f, &color);
// Use linear Rec. 2020 so that `ToneMapTo` doesn't have to convert to it and
@ -27,12 +24,10 @@ static void BM_ToneMapping(benchmark::State& state) {
JXL_CHECK(linear_rec2020.CreateICC());
for (auto _ : state) {
(void)_;
state.PauseTiming();
CodecInOut tone_mapping_input{memory_manager};
JXL_ASSIGN_OR_DIE(
Image3F color2,
Image3F::Create(memory_manager, color.xsize(), color.ysize()));
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);
tone_mapping_input.metadata.m.SetIntensityTarget(255);

View File

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

View File

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

View File

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

View File

@ -1,75 +0,0 @@
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
/** @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>
#ifndef __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(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(JxlMemoryManager* memory_manager,
const uint8_t* compressed_icc,
size_t compressed_icc_size,
uint8_t** icc, size_t* icc_size);
#ifndef __cplusplus
}
#endif
#endif /* JXL_COMPRESSED_ICC_H_ */
/** @} */

View File

@ -24,7 +24,7 @@
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
@ -721,7 +721,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 and this function will return an error
* structured data is not available, 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 +800,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,
* ::JXL_DEC_NEED_MORE_INPUT if not yet available, @ref
* @return ::JXL_DEC_SUCCESS if the profile was successfully returned is
* available, ::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 +869,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderSetDesiredIntensityTarget(
*
* This function must not be called before @ref JxlDecoderSetCms.
*
* @param dec decoder object
* @param dec decoder orbject
* @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 +913,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderPreviewOutBufferSize(
const JxlDecoder* dec, const JxlPixelFormat* format, size_t* size);
/**
* Sets the buffer to write the low-resolution preview image
* Sets the buffer to write the small 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 +962,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 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.
* 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.
*
* @param dec decoder object
* @param index the index of the extra channel
@ -1344,7 +1344,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 reconstruct a JPEG-1 image. The JPEG DCT
* byte-for-byte losslessly recontruct 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 +1366,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 JPEG XL file does not use the container format.
* not, for example the JXL file does not use the container format.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderGetBoxType(JxlDecoder* dec,
JxlBoxType type,
@ -1457,7 +1457,7 @@ JXL_EXPORT JxlDecoderStatus JxlDecoderFlushImage(JxlDecoder* dec);
JXL_EXPORT JxlDecoderStatus
JxlDecoderSetImageOutBitDepth(JxlDecoder* dec, const JxlBitDepth* bit_depth);
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

View File

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

View File

@ -25,7 +25,7 @@
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
@ -388,11 +388,6 @@ 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.
*/
@ -1593,7 +1588,7 @@ JXL_EXPORT void JxlEncoderSetDebugImageCallback(
JXL_EXPORT void JxlEncoderCollectStats(JxlEncoderFrameSettings* frame_settings,
JxlEncoderStats* stats);
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

View File

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

View File

@ -1,129 +0,0 @@
/* Copyright (c) the JPEG XL Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style
* license that can be found in the LICENSE file.
*/
/** @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>
#ifndef __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. */
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);
#ifndef __cplusplus
}
#endif
#endif /* JXL_GAIN_MAP_H_ */
/** @} */

View File

@ -15,7 +15,7 @@
#include <stddef.h>
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
@ -63,7 +63,7 @@ typedef struct JxlMemoryManagerStruct {
/* TODO(deymo): Add cache-aligned alloc/free functions here. */
} JxlMemoryManager;
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

View File

@ -40,7 +40,7 @@
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
@ -150,7 +150,7 @@ typedef JxlParallelRetCode (*JxlParallelRunner)(
}
*/
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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_d_out = pre_erosion->Row(y_out);
float* row_dout = pre_erosion->Row(y_out);
for (size_t x = 0; x < xsize_out; x++) {
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;
row_dout[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);
}

View File

@ -26,16 +26,11 @@ using hwy::HWY_NAMESPACE::Mul;
using hwy::HWY_NAMESPACE::MulAdd;
using hwy::HWY_NAMESPACE::Sub;
template <int kRed, int kGreen, int kBlue, int kAlpha>
void YCbCrToExtRGB(float* row[kMaxComponents], size_t xsize) {
void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
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];
float* JXL_RESTRICT row0 = row[0];
float* JXL_RESTRICT row1 = row[1];
float* JXL_RESTRICT row2 = row[2];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
@ -43,48 +38,20 @@ void YCbCrToExtRGB(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, row_y + x);
const auto cb_vec = Load(df, row_cb + x);
const auto cr_vec = Load(df, row_cr + x);
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 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, 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);
}
Store(r_vec, df, row0 + x);
Store(g_vec, df, row1 + x);
Store(b_vec, df, row2 + 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];
@ -99,15 +66,11 @@ void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
}
}
template <int kRed, int kGreen, int kBlue>
void ExtRGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
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];
float* JXL_RESTRICT row0 = row[0];
float* JXL_RESTRICT row1 = row[1];
float* JXL_RESTRICT row2 = 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);
@ -122,9 +85,9 @@ void ExtRGBToYCbCr(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, row_r + x);
const auto g = Load(df, row_g + x);
const auto b = Load(df, row_b + x);
const auto r = Load(df, row0 + x);
const auto g = Load(df, row1 + x);
const auto b = Load(df, row2 + x);
const auto r_base = Mul(r, kR);
const auto r_diff = Mul(r, kDiffR);
const auto g_base = Mul(g, kG);
@ -133,28 +96,12 @@ void ExtRGBToYCbCr(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, row_y + x);
Store(cb_vec, df, row_cb + x);
Store(cr_vec, df, row_cr + x);
Store(y_base, df, row0 + x);
Store(cb_vec, df, row1 + x);
Store(cr_vec, df, row2 + 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];
@ -180,15 +127,7 @@ 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) {
@ -196,25 +135,19 @@ 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
@ -225,73 +158,16 @@ 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,
@ -344,43 +220,6 @@ 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,
@ -412,123 +251,18 @@ void ChooseColorTransform(j_decompress_ptr cinfo) {
m->color_transform = nullptr;
if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
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;
if (cinfo->out_color_space == JCS_RGB) {
m->color_transform = GrayscaleToRGB;
}
} else if (cinfo->jpeg_color_space == JCS_RGB) {
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;
if (cinfo->out_color_space == JCS_GRAYSCALE) {
m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
}
} else if (cinfo->jpeg_color_space == JCS_YCbCr) {
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;
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;
}
} else if (cinfo->jpeg_color_space == JCS_YCCK) {
if (cinfo->out_color_space == JCS_CMYK) {

View File

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

View File

@ -10,24 +10,7 @@
#include <stdint.h>
#include <string.h>
// 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"

View File

@ -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 a_in1,
const float* JXL_RESTRICT a_in2, float* JXL_RESTRICT a_out) {
void AddReverse(const float* JXL_RESTRICT ain1, const float* JXL_RESTRICT ain2,
float* JXL_RESTRICT aout) {
HWY_CAPPED(float, 8) d8;
for (size_t i = 0; i < N; i++) {
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);
auto in1 = Load(d8, ain1 + i * 8);
auto in2 = Load(d8, ain2 + (N - i - 1) * 8);
Store(Add(in1, in2), d8, aout + i * 8);
}
}
template <size_t N>
void SubReverse(const float* JXL_RESTRICT a_in1,
const float* JXL_RESTRICT a_in2, float* JXL_RESTRICT a_out) {
void SubReverse(const float* JXL_RESTRICT ain1, const float* JXL_RESTRICT ain2,
float* JXL_RESTRICT aout) {
HWY_CAPPED(float, 8) d8;
for (size_t i = 0; i < N; i++) {
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);
auto in1 = Load(d8, ain1 + i * 8);
auto in2 = Load(d8, ain2 + (N - i - 1) * 8);
Store(Sub(in1, in2), d8, aout + 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 a_in, float* JXL_RESTRICT a_out) {
void InverseEvenOdd(const float* JXL_RESTRICT ain, float* JXL_RESTRICT aout) {
HWY_CAPPED(float, 8) d8;
for (size_t i = 0; i < N / 2; i++) {
auto in1 = Load(d8, a_in + i * 8);
Store(in1, d8, a_out + 2 * i * 8);
auto in1 = Load(d8, ain + i * 8);
Store(in1, d8, aout + 2 * i * 8);
}
for (size_t i = N / 2; i < N; i++) {
auto in1 = Load(d8, a_in + i * 8);
Store(in1, d8, a_out + (2 * (i - N / 2) + 1) * 8);
auto in1 = Load(d8, ain + i * 8);
Store(in1, d8, aout + (2 * (i - N / 2) + 1) * 8);
}
}
@ -109,10 +109,8 @@ 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>

View File

@ -54,7 +54,6 @@ 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;
@ -178,7 +177,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]) {
JPEGLI_ERROR("Duplicate Huffman code value %d", value);
return JPEGLI_ERROR("Duplicate Huffman code value %d", value);
}
values_seen[value] = 1;
values[i] = value;
@ -226,7 +225,7 @@ void PrepareForScan(j_decompress_ptr cinfo) {
HuffmanTableEntry* huff_lut =
&m->dc_huff_lut_[dc_tbl_idx * kJpegHuffmanLutSize];
if (!table) {
JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
return JPEGLI_ERROR("DC Huffman table %d not found", dc_tbl_idx);
}
BuildHuffmanLookupTable(cinfo, table, huff_lut);
}
@ -236,7 +235,7 @@ void PrepareForScan(j_decompress_ptr cinfo) {
HuffmanTableEntry* huff_lut =
&m->ac_huff_lut_[ac_tbl_idx * kJpegHuffmanLutSize];
if (!table) {
JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
return JPEGLI_ERROR("AC Huffman table %d not found", ac_tbl_idx);
}
BuildHuffmanLookupTable(cinfo, table, huff_lut);
}
@ -244,14 +243,10 @@ 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, quant_table, sizeof(JQUANT_TBL));
memcpy(comp->quant_table, cinfo->quant_tbl_ptrs[comp->quant_tbl_no],
sizeof(JQUANT_TBL));
}
}
if (cinfo->comps_in_scan == 1) {
@ -728,36 +723,16 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
}
}
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;
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;
}
cinfo->output_components =
cinfo->quantize_colors ? 1 : cinfo->out_color_components;
@ -765,11 +740,8 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
boolean jpegli_has_multiple_scans(j_decompress_ptr cinfo) {
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);
if (cinfo->input_scan_number == 0) {
JPEGLI_ERROR("No SOS marker found.");
}
return TO_JXL_BOOL(cinfo->master->is_multiscan_);
}

View File

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

View File

@ -3,27 +3,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <jxl/types.h>
#include <algorithm>
#include <cmath>
#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/jpegli/types.h"
#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
@ -88,8 +78,7 @@ class SourceManager {
return TRUE;
}
static void skip_input_data(j_decompress_ptr cinfo,
long num_bytes /* NOLINT */) {
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
if (num_bytes <= 0) {
return;
@ -308,10 +297,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)) {
@ -458,7 +447,7 @@ std::vector<TestConfig> GenerateBasicConfigs() {
TEST(DecodeAPITest, ReuseCinfoSameMemSource) {
std::vector<TestConfig> all_configs = GenerateBasicConfigs();
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -513,7 +502,7 @@ TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
EXPECT_TRUE(try_catch_block());
jpegli_destroy_compress(&cinfo);
}
fseek(tmpf, 0, SEEK_SET);
rewind(tmpf);
std::vector<TestImage> all_outputs(all_configs.size());
{
jpeg_decompress_struct cinfo;
@ -538,9 +527,9 @@ TEST(DecodeAPITest, ReuseCinfoSameStdSource) {
TEST(DecodeAPITest, AbbreviatedStreams) {
uint8_t* table_stream = nullptr;
unsigned long table_stream_size = 0; // NOLINT
unsigned long table_stream_size = 0;
uint8_t* data_stream = nullptr;
unsigned long data_stream_size = 0; // NOLINT
unsigned long data_stream_size = 0;
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -904,9 +893,7 @@ 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, JCS_EXT_RGB, JCS_EXT_BGR, JCS_EXT_RGBA,
JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_GRAYSCALE}) {
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = JCS_GRAYSCALE;
@ -915,9 +902,7 @@ 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, JCS_EXT_RGB, JCS_EXT_BGR,
JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
if (jpeg_color_space == JCS_RGB && out_color_space == JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
@ -1122,8 +1107,6 @@ 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);
}
}

View File

@ -6,15 +6,14 @@
#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 {
@ -46,26 +45,19 @@ 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_;
@ -74,13 +66,16 @@ 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 start of frame.
// Initialized at strat of frame.
uint16_t scan_progression_[jpegli::kMaxComponents][DCTSIZE2];
//
@ -101,11 +96,9 @@ struct jpeg_decomp_master {
//
int output_passes_done_;
JpegliDataType output_data_type_ = JPEGLI_TYPE_UINT8;
size_t xoffset_;
bool swap_endianness_ = false;
size_t xoffset_;
bool need_context_rows_;
bool regenerate_inverse_colormap_;
bool apply_smoothing;
int min_scaled_dct_size;
int scaled_dct_size[jpegli::kMaxComponents];
@ -134,6 +127,7 @@ 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_;
@ -151,6 +145,7 @@ 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_

View File

@ -23,22 +23,23 @@ constexpr uint8_t kIccProfileTag[12] = "ICC_PROFILE";
// Macros for commonly used error conditions.
#define JPEG_VERIFY_LEN(n) \
if (pos + (n) > len) { \
JPEGLI_ERROR("Unexpected end of marker: pos=%" PRIuS \
" need=%d len=%" PRIuS, \
pos, static_cast<int>(n), len); \
#define JPEG_VERIFY_LEN(n) \
if (pos + (n) > len) { \
return JPEGLI_ERROR("Unexpected end of marker: pos=%" PRIuS \
" need=%d len=%" PRIuS, \
pos, static_cast<int>(n), len); \
}
#define JPEG_VERIFY_INPUT(var, low, high) \
if ((var) < (low) || (var) > (high)) { \
JPEGLI_ERROR("Invalid " #var ": %d", static_cast<int>(var)); \
#define JPEG_VERIFY_INPUT(var, low, high) \
if ((var) < (low) || (var) > (high)) { \
return JPEGLI_ERROR("Invalid " #var ": %d", static_cast<int>(var)); \
}
#define JPEG_VERIFY_MARKER_END() \
if (pos != len) { \
JPEGLI_ERROR("Invalid marker length: declared=%" PRIuS " actual=%" PRIuS, \
len, pos); \
#define JPEG_VERIFY_MARKER_END() \
if (pos != len) { \
return JPEGLI_ERROR("Invalid marker length: declared=%" PRIuS \
" actual=%" PRIuS, \
len, pos); \
}
inline int ReadUint8(const uint8_t* data, size_t* pos) {
@ -103,6 +104,9 @@ void ProcessSOF(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
int quant_tbl_idx = ReadUint8(data, &pos);
JPEG_VERIFY_INPUT(quant_tbl_idx, 0, NUM_QUANT_TBLS - 1);
comp->quant_tbl_no = quant_tbl_idx;
if (cinfo->quant_tbl_ptrs[quant_tbl_idx] == nullptr) {
JPEGLI_ERROR("Quantization table with index %u not found", quant_tbl_idx);
}
comp->quant_table = nullptr; // will be allocated after SOS marker
}
JPEG_VERIFY_MARKER_END();
@ -165,7 +169,6 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
if (!m->found_sof_) {
JPEGLI_ERROR("Unexpected SOS marker.");
}
m->found_sos_ = true;
size_t pos = 2;
JPEG_VERIFY_LEN(1);
cinfo->comps_in_scan = ReadUint8(data, &pos);
@ -179,7 +182,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
for (int i = 0; i < cinfo->comps_in_scan; ++i) {
int id = ReadUint8(data, &pos);
if (ids_seen[id]) { // (cf. section B.2.3, regarding CSj)
JPEGLI_ERROR("Duplicate ID %d in SOS.", id);
return JPEGLI_ERROR("Duplicate ID %d in SOS.", id);
}
ids_seen[id] = 1;
jpeg_component_info* comp = nullptr;
@ -190,7 +193,8 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
}
}
if (!comp) {
JPEGLI_ERROR("SOS marker: Could not find component with id %d", id);
return JPEGLI_ERROR("SOS marker: Could not find component with id %d",
id);
}
int c = ReadUint8(data, &pos);
comp->dc_tbl_no = c >> 4;
@ -258,12 +262,12 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
int comp_idx = cinfo->cur_comp_info[i]->component_index;
for (int k = cinfo->Ss; k <= cinfo->Se; ++k) {
if (m->scan_progression_[comp_idx][k] & scan_bitmask) {
JPEGLI_ERROR(
return JPEGLI_ERROR(
"Overlapping scans: component=%d k=%d prev_mask: %u cur_mask %u",
comp_idx, k, m->scan_progression_[i][k], scan_bitmask);
}
if (m->scan_progression_[comp_idx][k] & refinement_bitmask) {
JPEGLI_ERROR(
return JPEGLI_ERROR(
"Invalid scan order, a more refined scan was already done: "
"component=%d k=%d prev_mask=%u cur_mask=%u",
comp_idx, k, m->scan_progression_[i][k], scan_bitmask);
@ -272,7 +276,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
}
}
if (cinfo->Al > 10) {
JPEGLI_ERROR("Scan parameter Al=%d is not supported.", cinfo->Al);
return JPEGLI_ERROR("Scan parameter Al=%d is not supported.", cinfo->Al);
}
}
@ -282,7 +286,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
size_t pos = 2;
if (pos == len) {
JPEGLI_ERROR("DHT marker: no Huffman table found");
return JPEGLI_ERROR("DHT marker: no Huffman table found");
}
while (pos < len) {
JPEG_VERIFY_LEN(1 + kJpegHuffmanMaxBitLength);
@ -335,12 +339,12 @@ void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDQT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
jpeg_decomp_master* m = cinfo->master;
if (m->found_sos_) {
if (m->found_sof_) {
JPEGLI_ERROR("Updating quant tables between scans is not supported.");
}
size_t pos = 2;
if (pos == len) {
JPEGLI_ERROR("DQT marker: no quantization table found");
return JPEGLI_ERROR("DQT marker: no quantization table found");
}
while (pos < len) {
JPEG_VERIFY_LEN(1);
@ -374,7 +378,7 @@ void ProcessDNL(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDRI(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
jpeg_decomp_master* m = cinfo->master;
if (m->found_dri_) {
JPEGLI_ERROR("Duplicate DRI marker.");
return JPEGLI_ERROR("Duplicate DRI marker.");
}
m->found_dri_ = true;
size_t pos = 2;
@ -408,24 +412,24 @@ void ProcessAPP(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
payload += sizeof(kIccProfileTag);
payload_size -= sizeof(kIccProfileTag);
if (payload_size < 2) {
JPEGLI_ERROR("ICC chunk is too small.");
return JPEGLI_ERROR("ICC chunk is too small.");
}
uint8_t index = payload[0];
uint8_t total = payload[1];
++m->icc_index_;
if (m->icc_index_ != index) {
JPEGLI_ERROR("Invalid ICC chunk order.");
return JPEGLI_ERROR("Invalid ICC chunk order.");
}
if (total == 0) {
JPEGLI_ERROR("Invalid ICC chunk total.");
return JPEGLI_ERROR("Invalid ICC chunk total.");
}
if (m->icc_total_ == 0) {
m->icc_total_ = total;
} else if (m->icc_total_ != total) {
JPEGLI_ERROR("Invalid ICC chunk total.");
return JPEGLI_ERROR("Invalid ICC chunk total.");
}
if (m->icc_index_ > m->icc_total_) {
JPEGLI_ERROR("Invalid ICC chunk index.");
return JPEGLI_ERROR("Invalid ICC chunk index.");
}
m->icc_profile_.insert(m->icc_profile_.end(), payload + 2,
payload + payload_size);

View File

@ -52,7 +52,7 @@ struct MemoryDestinationManager {
jpeg_destination_mgr pub;
// Output buffer supplied by the application
uint8_t** output;
unsigned long* output_size; // NOLINT
unsigned long* output_size;
// Output buffer allocated by us.
uint8_t* temp_buffer;
// Current output buffer (either application supplied or allocated by us).
@ -113,7 +113,7 @@ void jpegli_stdio_dest(j_compress_ptr cinfo, FILE* outfile) {
}
void jpegli_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer,
unsigned long* outsize /* NOLINT */) {
unsigned long* outsize) {
if (outbuffer == nullptr || outsize == nullptr) {
JPEGLI_ERROR("jpegli_mem_dest: Invalid destination.");
}

View File

@ -295,14 +295,13 @@ void DownsampleInputBuffer(j_compress_ptr cinfo) {
}
auto& input = *m->smooth_input[c];
auto& output = *m->raw_data[c];
const size_t y_out0 = y0 / v_factor;
const size_t yout0 = y0 / v_factor;
float* rows_in[MAX_SAMP_FACTOR];
for (size_t y_in = y0, y_out = y_out0; y_in < y1;
y_in += v_factor, ++y_out) {
for (size_t yin = y0, yout = yout0; yin < y1; yin += v_factor, ++yout) {
for (int iy = 0; iy < v_factor; ++iy) {
rows_in[iy] = input.Row(y_in + iy);
rows_in[iy] = input.Row(yin + iy);
}
float* row_out = output.Row(y_out);
float* row_out = output.Row(yout);
(*m->downsample_method[c])(rows_in, xsize_padded, row_out);
}
}

View File

@ -283,15 +283,15 @@ void ProcessCompressionParams(j_compress_ptr cinfo) {
JPEGLI_ERROR("Invalid sampling factor %d x %d", comp->h_samp_factor,
comp->v_samp_factor);
}
if (cinfo->num_components == 1) {
// Force samp factors to 1x1 for single-component images.
comp->h_samp_factor = comp->v_samp_factor = 1;
}
cinfo->max_h_samp_factor =
std::max(comp->h_samp_factor, cinfo->max_h_samp_factor);
cinfo->max_v_samp_factor =
std::max(comp->v_samp_factor, cinfo->max_v_samp_factor);
}
if (cinfo->num_components == 1 &&
(cinfo->max_h_samp_factor != 1 || cinfo->max_v_samp_factor != 1)) {
JPEGLI_ERROR("Sampling is not supported for simgle component image.");
}
size_t iMCU_width = DCTSIZE * cinfo->max_h_samp_factor;
size_t iMCU_height = DCTSIZE * cinfo->max_v_samp_factor;
size_t total_iMCU_cols = DivCeil(cinfo->image_width, iMCU_width);
@ -628,9 +628,9 @@ void ZigZagShuffleBlocks(j_compress_ptr cinfo) {
for (int c = 0; c < cinfo->num_components; ++c) {
jpeg_component_info* comp = &cinfo->comp_info[c];
for (JDIMENSION by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY blocks = GetBlockRow(cinfo, c, by);
JBLOCKARRAY ba = GetBlockRow(cinfo, c, by);
for (JDIMENSION bx = 0; bx < comp->width_in_blocks; ++bx) {
JCOEF* block = &blocks[0][bx][0];
JCOEF* block = &ba[0][bx][0];
for (int k = 0; k < DCTSIZE2; ++k) {
tmp[k] = block[kJPEGNaturalOrder[k]];
}
@ -713,31 +713,18 @@ void jpegli_set_defaults(j_compress_ptr cinfo) {
void jpegli_default_colorspace(j_compress_ptr cinfo) {
CheckState(cinfo, jpegli::kEncStart);
if (cinfo->in_color_space == JCS_RGB && cinfo->master->xyb_mode) {
jpegli_set_colorspace(cinfo, JCS_RGB);
return;
}
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
jpegli_set_colorspace(cinfo, JCS_GRAYSCALE);
break;
case JCS_RGB:
#ifdef JCS_EXTENSIONS
case JCS_EXT_RGB:
case JCS_EXT_BGR:
case JCS_EXT_RGBX:
case JCS_EXT_BGRX:
case JCS_EXT_XRGB:
case JCS_EXT_XBGR:
#endif
#if JCS_ALPHA_EXTENSIONS
case JCS_EXT_RGBA:
case JCS_EXT_BGRA:
case JCS_EXT_ARGB:
case JCS_EXT_ABGR:
#endif
jpegli_set_colorspace(cinfo, JCS_YCbCr);
case JCS_RGB: {
if (cinfo->master->xyb_mode) {
jpegli_set_colorspace(cinfo, JCS_RGB);
} else {
jpegli_set_colorspace(cinfo, JCS_YCbCr);
}
break;
}
case JCS_YCbCr:
jpegli_set_colorspace(cinfo, JCS_YCbCr);
break;
@ -819,11 +806,6 @@ void jpegli_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace) {
cinfo->comp_info[2].quant_tbl_no = 1;
cinfo->comp_info[1].dc_tbl_no = cinfo->comp_info[1].ac_tbl_no = 1;
cinfo->comp_info[2].dc_tbl_no = cinfo->comp_info[2].ac_tbl_no = 1;
// Use chroma subsampling by default
cinfo->comp_info[0].h_samp_factor = cinfo->comp_info[0].v_samp_factor = 2;
if (colorspace == JCS_YCCK) {
cinfo->comp_info[3].h_samp_factor = cinfo->comp_info[3].v_samp_factor = 2;
}
}
}
@ -975,7 +957,7 @@ void jpegli_copy_critical_parameters(j_decompress_ptr srcinfo,
jpegli_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
if (dstinfo->num_components != srcinfo->num_components) {
const auto& cinfo = dstinfo;
JPEGLI_ERROR("Mismatch between src colorspace and components");
return JPEGLI_ERROR("Mismatch between src colorspace and components");
}
dstinfo->data_precision = srcinfo->data_precision;
dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;

View File

@ -21,9 +21,8 @@
#define LIB_JPEGLI_ENCODE_H_
#include "lib/jpegli/common.h"
#include "lib/jpegli/types.h"
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
@ -36,7 +35,7 @@ void jpegli_CreateCompress(j_compress_ptr cinfo, int version,
void jpegli_stdio_dest(j_compress_ptr cinfo, FILE* outfile);
void jpegli_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer,
unsigned long* outsize /* NOLINT */);
unsigned long* outsize);
void jpegli_set_defaults(j_compress_ptr cinfo);
@ -152,7 +151,7 @@ void jpegli_set_progressive_level(j_compress_ptr cinfo, int level);
// AC coefficients. Must be called before jpegli_set_defaults().
void jpegli_use_standard_quant_tables(j_compress_ptr cinfo);
#ifdef __cplusplus
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif

View File

@ -4,23 +4,14 @@
// license that can be found in the LICENSE file.
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ostream>
#include <sstream>
#include <string>
#include <cmath>
#include <vector>
#include "lib/jpegli/encode.h"
#include "lib/jpegli/libjpeg_test_util.h"
#include "lib/jpegli/test_params.h"
#include "lib/jpegli/error.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
#include "lib/jpegli/types.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
@ -78,7 +69,7 @@ TEST(EncodeAPITest, ReuseCinfoSameImageTwice) {
CompressParams jparams;
GenerateInput(PIXELS, jparams, &input);
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
std::vector<uint8_t> compressed0;
std::vector<uint8_t> compressed1;
jpeg_compress_struct cinfo;
@ -126,7 +117,7 @@ std::vector<TestConfig> GenerateBasicConfigs() {
TEST(EncodeAPITest, ReuseCinfoSameMemOutput) {
std::vector<TestConfig> all_configs = GenerateBasicConfigs();
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -170,7 +161,7 @@ TEST(EncodeAPITest, ReuseCinfoSameStdOutput) {
jpegli_destroy_compress(&cinfo);
}
size_t total_size = ftell(tmpf);
fseek(tmpf, 0, SEEK_SET);
rewind(tmpf);
std::vector<uint8_t> compressed(total_size);
JXL_CHECK(total_size == fread(compressed.data(), 1, total_size, tmpf));
fclose(tmpf);
@ -190,7 +181,7 @@ TEST(EncodeAPITest, ReuseCinfoChangeParams) {
CompressParams jparams;
DecompressParams dparams;
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
std::vector<uint8_t> compressed;
jpeg_compress_struct cinfo;
const auto max_rms = [](int q, int hs, int vs) {
@ -255,9 +246,9 @@ TEST(EncodeAPITest, ReuseCinfoChangeParams) {
TEST(EncodeAPITest, AbbreviatedStreams) {
uint8_t* table_stream = nullptr;
unsigned long table_stream_size = 0; // NOLINT
unsigned long table_stream_size = 0;
uint8_t* data_stream = nullptr;
unsigned long data_stream_size = 0; // NOLINT
unsigned long data_stream_size = 0;
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -381,8 +372,6 @@ std::vector<TestConfig> GenerateTests() {
{
TestConfig config;
config.jparams.quality = 100;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 6.6;
config.max_dist = 0.6;
all_tests.push_back(config);
@ -521,23 +510,17 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.libjpeg_mode = true;
config.max_bpp = 2.1;
config.max_dist = 1.7;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
for (J_COLOR_SPACE in_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}) {
for (J_COLOR_SPACE in_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
for (J_COLOR_SPACE jpeg_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
if (jpeg_color_space == JCS_RGB && in_color_space >= JCS_YCbCr) continue;
if (jpeg_color_space == JCS_RGB && in_color_space == JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = in_color_space;
config.jparams.set_jpeg_colorspace = true;
config.jparams.jpeg_color_space = jpeg_color_space;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = jpeg_color_space == JCS_RGB ? 4.5 : 1.85;
config.max_dist = jpeg_color_space == JCS_RGB ? 1.4 : 2.05;
all_tests.push_back(config);
@ -553,8 +536,6 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.set_jpeg_colorspace = true;
config.jparams.jpeg_color_space = jpeg_color_space;
}
config.jparams.h_sampling = {1, 1, 1, 1};
config.jparams.v_sampling = {1, 1, 1, 1};
config.max_bpp = jpeg_color_space == JCS_CMYK ? 4.0 : 3.6;
config.max_dist = jpeg_color_space == JCS_CMYK ? 1.2 : 1.5;
all_tests.push_back(config);
@ -565,8 +546,6 @@ std::vector<TestConfig> GenerateTests() {
config.input.color_space = JCS_YCbCr;
config.max_bpp = 1.6;
config.max_dist = 1.35;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
for (bool xyb : {false, true}) {
@ -617,8 +596,6 @@ std::vector<TestConfig> GenerateTests() {
table.add_raw = add_raw;
table.Generate();
config.jparams.optimize_coding = 1;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
config.jparams.quant_tables.push_back(table);
config.jparams.quant_indexes = {0, 0, 0};
float q = (type == 0 ? 16 : type) * scale * 0.01f;
@ -637,8 +614,6 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 2.25;
config.max_dist = 2.8;
all_tests.push_back(config);
@ -651,8 +626,6 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
CustomQuantTable table;
table.slot_idx = slot_idx;
table.Generate();
@ -670,10 +643,6 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.xyb_mode = xyb;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
if (!xyb) {
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
}
{
CustomQuantTable table;
table.slot_idx = 0;
@ -698,10 +667,6 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.xyb_mode = xyb;
config.jparams.quant_indexes = {0, 1, 2};
if (!xyb) {
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
}
{
CustomQuantTable table;
table.slot_idx = 0;
@ -773,8 +738,6 @@ std::vector<TestConfig> GenerateTests() {
}
config.jparams.progressive_mode = 0;
config.jparams.optimize_coding = 0;
config.jparams.h_sampling = {1, 1, 1};
config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 1.85;
config.max_dist = 2.05;
if (input_mode == COEFFICIENTS) {

View File

@ -99,10 +99,10 @@ float ComputePSNR(j_compress_ptr cinfo, int sampling) {
HWY_ALIGN float iqmc[64];
ComputeInverseWeights(qmc, iqmc);
for (JDIMENSION by = 0; by < comp->height_in_blocks; by += sampling) {
JBLOCKARRAY blocks = GetBlockRow(cinfo, c, by);
JBLOCKARRAY ba = GetBlockRow(cinfo, c, by);
const float* qf = m->quant_field.Row(by * v_factor);
for (JDIMENSION bx = 0; bx < comp->width_in_blocks; bx += sampling) {
error += BlockError(&blocks[0][bx][0], qmc, iqmc, qf[bx * h_factor],
error += BlockError(&ba[0][bx][0], qmc, iqmc, qf[bx * h_factor],
zero_bias_offset, zero_bias_mul);
num += DCTSIZE2;
}
@ -122,11 +122,11 @@ void ReQuantizeCoeffs(j_compress_ptr cinfo) {
const float* zero_bias_offset = m->zero_bias_offset[c];
const float* zero_bias_mul = m->zero_bias_mul[c];
for (JDIMENSION by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY block = GetBlockRow(cinfo, c, by);
JBLOCKARRAY ba = GetBlockRow(cinfo, c, by);
const float* qf = m->quant_field.Row(by * v_factor);
for (JDIMENSION bx = 0; bx < comp->width_in_blocks; ++bx) {
ReQuantizeBlock(&block[0][bx][0], qmc, qf[bx * h_factor],
zero_bias_offset, zero_bias_mul);
ReQuantizeBlock(&ba[0][bx][0], qmc, qf[bx * h_factor], zero_bias_offset,
zero_bias_mul);
}
}
}

View File

@ -114,14 +114,14 @@ void ProcessiMCURow(j_compress_ptr cinfo) {
int32_t* nonzero_idx = m->block_tmp + 3 * DCTSIZE2;
coeff_t* JXL_RESTRICT last_dc_coeff = m->last_dc_coeff;
bool adaptive_quant = m->use_adaptive_quantization && m->psnr_target == 0;
JBLOCKARRAY blocks[kMaxComponents];
JBLOCKARRAY ba[kMaxComponents];
if (kMode == kStreamingModeCoefficients) {
for (int c = 0; c < cinfo->num_components; ++c) {
jpeg_component_info* comp = &cinfo->comp_info[c];
int by0 = mcu_y * comp->v_samp_factor;
int block_rows_left = comp->height_in_blocks - by0;
int max_block_rows = std::min(comp->v_samp_factor, block_rows_left);
blocks[c] = (*cinfo->mem->access_virt_barray)(
ba[c] = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[c], by0,
max_block_rows, true);
}
@ -189,7 +189,7 @@ void ProcessiMCURow(j_compress_ptr cinfo) {
aq_strength, zero_bias_offset, zero_bias_mul,
m->dct_buffer, block);
if (kMode == kStreamingModeCoefficients) {
JCOEF* cblock = &blocks[c][iy][bx][0];
JCOEF* cblock = &ba[c][iy][bx][0];
for (int k = 0; k < DCTSIZE2; ++k) {
cblock[k] = block[kJPEGNaturalOrder[k]];
}

View File

@ -106,7 +106,7 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
eob_run = 0;
};
for (JDIMENSION by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY blocks = (*cinfo->mem->access_virt_barray)(
JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[comp_idx], by,
1, FALSE);
// Each coefficient can appear in at most one token, but we have to reserve
@ -132,7 +132,7 @@ void TokenizeACProgressiveScan(j_compress_ptr cinfo, int scan_index,
sti->restarts[restart_idx++] = m->total_num_tokens + ta->num_tokens;
restarts_to_go = restart_interval;
}
const coeff_t* block = &blocks[0][bx][0];
const coeff_t* block = &ba[0][bx][0];
coeff_t temp2;
coeff_t temp;
int r = 0;
@ -213,7 +213,7 @@ void TokenizeACRefinementScan(j_compress_ptr cinfo, int scan_index,
uint16_t* next_eobrun = sti->eobruns;
size_t restart_idx = 0;
for (JDIMENSION by = 0; by < comp->height_in_blocks; ++by) {
JBLOCKARRAY blocks = (*cinfo->mem->access_virt_barray)(
JBLOCKARRAY ba = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[comp_idx], by,
1, FALSE);
for (JDIMENSION bx = 0; bx < comp->width_in_blocks; ++bx) {
@ -223,7 +223,7 @@ void TokenizeACRefinementScan(j_compress_ptr cinfo, int scan_index,
next_eob_token = next_token;
eob_run = eob_refbits = 0;
}
const coeff_t* block = &blocks[0][bx][0];
const coeff_t* block = &ba[0][bx][0];
int num_eob_refinement_bits = 0;
int num_refinement_bits = 0;
int num_nzeros = 0;
@ -347,7 +347,7 @@ void TokenizeScan(j_compress_ptr cinfo, size_t scan_index, int ac_ctx_offset,
}
}
JBLOCKARRAY blocks[MAX_COMPS_IN_SCAN];
JBLOCKARRAY ba[MAX_COMPS_IN_SCAN];
size_t block_idx = 0;
for (size_t mcu_y = 0; mcu_y < sti->MCU_rows_in_scan; ++mcu_y) {
for (int i = 0; i < scan_info->comps_in_scan; ++i) {
@ -357,7 +357,7 @@ void TokenizeScan(j_compress_ptr cinfo, size_t scan_index, int ac_ctx_offset,
int by0 = mcu_y * n_blocks_y;
int block_rows_left = comp->height_in_blocks - by0;
int max_block_rows = std::min(n_blocks_y, block_rows_left);
blocks[i] = (*cinfo->mem->access_virt_barray)(
ba[i] = (*cinfo->mem->access_virt_barray)(
reinterpret_cast<j_common_ptr>(cinfo), m->coeff_buffers[comp_idx],
by0, max_block_rows, FALSE);
}
@ -400,7 +400,7 @@ void TokenizeScan(j_compress_ptr cinfo, size_t scan_index, int ac_ctx_offset,
block_y >= comp->height_in_blocks) {
block = kSinkBlock;
} else {
block = &blocks[i][iy][block_x][0];
block = &ba[i][iy][block_x][0];
}
if (!is_progressive) {
HWY_DYNAMIC_DISPATCH(ComputeTokensSequential)

View File

@ -22,7 +22,7 @@ const char* const kErrorMessageTable[] = {
bool FormatString(char* buffer, const char* format, ...) {
va_list args;
va_start(args, format);
vsnprintf(buffer, JMSG_STR_PARM_MAX, format, args); // notypo
vsnprintf(buffer, JMSG_STR_PARM_MAX, format, args);
va_end(args);
return false;
}

View File

@ -10,7 +10,6 @@
#include <stdint.h>
#include "lib/jpegli/common.h"
#include "lib/jxl/base/status.h"
namespace jpegli {
@ -18,12 +17,10 @@ bool FormatString(char* buffer, const char* format, ...);
} // namespace jpegli
// `error_exit` should be no-return; but let's add some guarantees on our side.
#define JPEGLI_ERROR(format, ...) \
jpegli::FormatString(cinfo->err->msg_parm.s, ("%s:%d: " format), __FILE__, \
__LINE__, ##__VA_ARGS__), \
(*cinfo->err->error_exit)(reinterpret_cast<j_common_ptr>(cinfo)), \
(void)jxl::Abort()
(*cinfo->err->error_exit)(reinterpret_cast<j_common_ptr>(cinfo))
#define JPEGLI_WARN(format, ...) \
jpegli::FormatString(cinfo->err->msg_parm.s, ("%s:%d: " format), __FILE__, \

View File

@ -3,27 +3,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <vector>
#include "lib/jpegli/common.h"
#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/error.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
TEST(EncoderErrorHandlingTest, MinimalSuccess) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
{
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
@ -72,7 +64,7 @@ TEST(EncoderErrorHandlingTest, NoDestination) {
TEST(EncoderErrorHandlingTest, NoImageDimensions) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -90,7 +82,7 @@ TEST(EncoderErrorHandlingTest, NoImageDimensions) {
TEST(EncoderErrorHandlingTest, ImageTooBig) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -110,7 +102,7 @@ TEST(EncoderErrorHandlingTest, ImageTooBig) {
TEST(EncoderErrorHandlingTest, NoInputComponents) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -129,7 +121,7 @@ TEST(EncoderErrorHandlingTest, NoInputComponents) {
TEST(EncoderErrorHandlingTest, TooManyInputComponents) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -149,7 +141,7 @@ TEST(EncoderErrorHandlingTest, TooManyInputComponents) {
TEST(EncoderErrorHandlingTest, NoSetDefaults) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -172,7 +164,7 @@ TEST(EncoderErrorHandlingTest, NoSetDefaults) {
TEST(EncoderErrorHandlingTest, NoStartCompress) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -194,7 +186,7 @@ TEST(EncoderErrorHandlingTest, NoStartCompress) {
TEST(EncoderErrorHandlingTest, NoWriteScanlines) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -215,7 +207,7 @@ TEST(EncoderErrorHandlingTest, NoWriteScanlines) {
TEST(EncoderErrorHandlingTest, NoWriteAllScanlines) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -239,7 +231,7 @@ TEST(EncoderErrorHandlingTest, NoWriteAllScanlines) {
TEST(EncoderErrorHandlingTest, InvalidQuantValue) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -268,7 +260,7 @@ TEST(EncoderErrorHandlingTest, InvalidQuantValue) {
TEST(EncoderErrorHandlingTest, InvalidQuantTableIndex) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -293,7 +285,7 @@ TEST(EncoderErrorHandlingTest, InvalidQuantTableIndex) {
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch1) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -314,7 +306,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch1) {
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch2) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -335,7 +327,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch2) {
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch3) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -361,7 +353,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch3) {
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch4) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -386,7 +378,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch4) {
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch5) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -411,7 +403,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch5) {
TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch6) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -437,7 +429,7 @@ TEST(EncoderErrorHandlingTest, NumberOfComponentsMismatch6) {
TEST(EncoderErrorHandlingTest, InvalidColorTransform) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -463,7 +455,7 @@ TEST(EncoderErrorHandlingTest, InvalidColorTransform) {
TEST(EncoderErrorHandlingTest, DuplicateComponentIds) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -485,7 +477,7 @@ TEST(EncoderErrorHandlingTest, DuplicateComponentIds) {
TEST(EncoderErrorHandlingTest, InvalidComponentIndex) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -506,7 +498,7 @@ TEST(EncoderErrorHandlingTest, InvalidComponentIndex) {
TEST(EncoderErrorHandlingTest, ArithmeticCoding) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -527,7 +519,7 @@ TEST(EncoderErrorHandlingTest, ArithmeticCoding) {
TEST(EncoderErrorHandlingTest, CCIR601Sampling) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -548,7 +540,7 @@ TEST(EncoderErrorHandlingTest, CCIR601Sampling) {
TEST(EncoderErrorHandlingTest, InvalidScanScript1) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -571,7 +563,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript1) {
TEST(EncoderErrorHandlingTest, InvalidScanScript2) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -594,7 +586,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript2) {
TEST(EncoderErrorHandlingTest, InvalidScanScript3) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -617,7 +609,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript3) {
TEST(EncoderErrorHandlingTest, InvalidScanScript4) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -640,7 +632,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript4) {
TEST(EncoderErrorHandlingTest, InvalidScanScript5) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -663,7 +655,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript5) {
TEST(EncoderErrorHandlingTest, InvalidScanScript6) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -686,7 +678,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript6) {
TEST(EncoderErrorHandlingTest, InvalidScanScript7) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -709,7 +701,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript7) {
TEST(EncoderErrorHandlingTest, InvalidScanScript8) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -734,7 +726,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript8) {
TEST(EncoderErrorHandlingTest, InvalidScanScript9) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -759,7 +751,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript9) {
TEST(EncoderErrorHandlingTest, InvalidScanScript10) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -784,7 +776,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript10) {
TEST(EncoderErrorHandlingTest, InvalidScanScript11) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -809,7 +801,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript11) {
TEST(EncoderErrorHandlingTest, InvalidScanScript12) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -834,7 +826,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript12) {
TEST(EncoderErrorHandlingTest, InvalidScanScript13) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -862,7 +854,7 @@ TEST(EncoderErrorHandlingTest, InvalidScanScript13) {
TEST(EncoderErrorHandlingTest, MCUSizeTooBig) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -885,7 +877,7 @@ TEST(EncoderErrorHandlingTest, MCUSizeTooBig) {
TEST(EncoderErrorHandlingTest, RestartIntervalTooBig) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -906,7 +898,7 @@ TEST(EncoderErrorHandlingTest, RestartIntervalTooBig) {
TEST(EncoderErrorHandlingTest, SamplingFactorTooBig) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -927,7 +919,7 @@ TEST(EncoderErrorHandlingTest, SamplingFactorTooBig) {
TEST(EncoderErrorHandlingTest, NonIntegralSamplingRatio) {
uint8_t* buffer = nullptr;
unsigned long buffer_size = 0; // NOLINT
unsigned long buffer_size = 0;
jpeg_compress_struct cinfo;
const auto try_catch_block = [&]() -> bool {
ERROR_HANDLER_SETUP(jpegli);
@ -1004,9 +996,6 @@ TEST(EncoderErrorHandlingTest, AddOnTableNoStringParam) {
const uint8_t kCompressed0[] = {
// SOI
0xff, 0xd8, //
// SOF
0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
0x01, 0x11, 0x00, //
// DQT
0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, //
0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, //
@ -1015,6 +1004,9 @@ const uint8_t kCompressed0[] = {
0x0e, 0x12, 0x10, 0x0d, 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, //
0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f, //
0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14, //
// SOF
0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
0x01, 0x11, 0x00, //
// DHT
0xff, 0xc4, 0x00, 0xd2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, //
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
@ -1047,8 +1039,8 @@ const uint8_t kCompressed0[] = {
};
const size_t kLen0 = sizeof(kCompressed0);
const size_t kSOFOffset = 2;
const size_t kDQTOffset = 15;
const size_t kDQTOffset = 2;
const size_t kSOFOffset = 71;
const size_t kDHTOffset = 84;
const size_t kSOSOffset = 296;
@ -1177,7 +1169,7 @@ TEST(DecoderErrorHandlingTest, InvalidDQT) {
compressed[kDQTOffset + 3] += diff;
EXPECT_FALSE(ParseCompressed(compressed));
}
// invalid table index / precision
// inavlid table index / precision
for (int val : {0x20, 0x05}) {
std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
compressed[kDQTOffset + 4] = val;
@ -1242,7 +1234,7 @@ TEST(DecoderErrorHandlingTest, InvalidDHT) {
compressed[kDHTOffset + 2] += 17;
EXPECT_FALSE(ParseCompressed(compressed));
}
// invalid table slot_id
// inavlid table slot_id
for (int val : {0x05, 0x15, 0x20}) {
std::vector<uint8_t> compressed(kCompressed0, kCompressed0 + kLen0);
compressed[kDHTOffset + 4] = val;

View File

@ -1,22 +0,0 @@
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef LIB_JPEGLI_FUZZTEST_H_
#define LIB_JPEGLI_FUZZTEST_H_
#include "lib/jxl/base/compiler_specific.h"
#if !defined(FUZZ_TEST)
struct FuzzTestSink {
template <typename F>
FuzzTestSink WithSeeds(F /*f*/) {
return *this;
}
};
#define FUZZ_TEST(A, B) \
const JXL_MAYBE_UNUSED FuzzTestSink unused##A##B = FuzzTestSink()
#endif
#endif // LIB_JPEGLI_FUZZTEST_H_

View File

@ -8,7 +8,6 @@
#include <cmath>
#include "lib/jpegli/decode_internal.h"
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#undef HWY_TARGET_INCLUDE
@ -63,15 +62,15 @@ void DequantBlock(const int16_t* JXL_RESTRICT qblock,
}
template <size_t N>
void ForwardEvenOdd(const float* JXL_RESTRICT a_in, size_t a_in_stride,
float* JXL_RESTRICT a_out) {
void ForwardEvenOdd(const float* JXL_RESTRICT ain, size_t ain_stride,
float* JXL_RESTRICT aout) {
for (size_t i = 0; i < N / 2; i++) {
auto in1 = LoadU(d8, a_in + 2 * i * a_in_stride);
Store(in1, d8, a_out + i * 8);
auto in1 = LoadU(d8, ain + 2 * i * ain_stride);
Store(in1, d8, aout + i * 8);
}
for (size_t i = N / 2; i < N; i++) {
auto in1 = LoadU(d8, a_in + (2 * (i - N / 2) + 1) * a_in_stride);
Store(in1, d8, a_out + i * 8);
auto in1 = LoadU(d8, ain + (2 * (i - N / 2) + 1) * ain_stride);
Store(in1, d8, aout + i * 8);
}
}
@ -112,10 +111,8 @@ struct WcMultipliers<8> {
};
};
#if JXL_CXX_LANG < JXL_CXX_17
constexpr float WcMultipliers<4>::kMultipliers[];
constexpr float WcMultipliers<8>::kMultipliers[];
#endif
template <size_t N>
void MultiplyAndAdd(const float* JXL_RESTRICT coeff, float* JXL_RESTRICT out,

View File

@ -3,24 +3,16 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <jxl/types.h>
#include <algorithm>
#include <cstddef>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <ostream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "lib/jpegli/decode.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/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
@ -88,8 +80,7 @@ struct SourceManager {
static boolean fill_input_buffer(j_decompress_ptr cinfo) { return FALSE; }
static void skip_input_data(j_decompress_ptr cinfo,
long num_bytes /* NOLINT*/) {
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
auto* src = reinterpret_cast<SourceManager*>(cinfo->src);
if (num_bytes <= 0) {
return;

View File

@ -5,11 +5,13 @@
#include "lib/jpegli/libjpeg_test_util.h"
#include <cstring>
/* clang-format off */
#include <stdio.h>
#include <jpeglib.h>
#include <setjmp.h>
/* clang-format on */
#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#include "lib/jxl/base/sanitizers.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
namespace jpegli {
@ -124,8 +126,6 @@ void DecodeWithLibjpeg(const CompressParams& jparams,
if (dparams.output_mode == COEFFICIENTS) {
jvirt_barray_ptr* coef_arrays = jpeg_read_coefficients(cinfo);
JXL_CHECK(coef_arrays != nullptr);
jxl::msan::UnpoisonMemory(coef_arrays,
cinfo->num_components * sizeof(jvirt_barray_ptr));
CopyCoefficients(cinfo, coef_arrays, output);
} else {
JXL_CHECK(jpeg_start_decompress(cinfo));
@ -204,8 +204,6 @@ void DecodeAllScansWithLibjpeg(const CompressParams& jparams,
if (dparams.output_mode == COEFFICIENTS) {
jvirt_barray_ptr* coef_arrays = jpeg_read_coefficients(&cinfo);
JXL_CHECK(coef_arrays != nullptr);
jxl::msan::UnpoisonMemory(
coef_arrays, cinfo.num_components * sizeof(jvirt_barray_ptr));
CopyCoefficients(&cinfo, coef_arrays, &output_progression->back());
}
}
@ -245,7 +243,6 @@ size_t DecodeWithLibjpeg(const CompressParams& jparams,
}
jpeg_mem_src(&cinfo, compressed, len);
DecodeWithLibjpeg(jparams, dparams, &cinfo, output);
jxl::msan::UnpoisonMemory(cinfo.src, sizeof(jpeg_source_mgr));
bytes_read = len - cinfo.src->bytes_in_buffer;
return true;
};

View File

@ -38,7 +38,7 @@ void jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile) {
}
void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *inbuffer,
unsigned long insize /* NOLINT */) {
unsigned long insize) {
jpegli_mem_src(cinfo, inbuffer, insize);
}
@ -138,7 +138,7 @@ void jpeg_stdio_dest(j_compress_ptr cinfo, FILE *outfile) {
}
void jpeg_mem_dest(j_compress_ptr cinfo, unsigned char **outbuffer,
unsigned long *outsize /* NOLINT */) {
unsigned long *outsize) {
jpegli_mem_dest(cinfo, outbuffer, outsize);
}

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