GitLab Commit is coming up on August 3-4. Learn how to innovate together using GitLab, the DevOps platform. Register for free: gitlabcommitvirtual2021.com

Commit 31c71b0f authored by  jpegxl-bot's avatar jpegxl-bot 🤖 Committed by Alex Deymo
Browse files

Update JPEG-XL with latest changes.

This includes all changes up to 2020-12-24 16:16:37 +0000.

Bump version to v0.2.

Note that this changes the way that losslessly-compressed JPEG files
(obtained with `cjxl input.jpeg output.jxl`) are encoded. If you have
such files, you should decompress them to JPEG using `djxl --jpeg`
prior to updating, to prepare them for later recompression.
parent d11752ff
......@@ -44,11 +44,12 @@ WarningsAsErrors: >-
-clang-diagnostic-unused-command-line-argument,
google-build-using-namespace,
google-explicit-constructor,
google-readability-namespace-comments
google-readability-namespace-comments,
readability-inconsistent-declaration-parameter-name
# We are only interested in the headers from this projects, excluding
# third_party/ and build/.
HeaderFilterRegex: '^.*/(jxl|fuif|tools)/.*\.h$'
HeaderFilterRegex: '^.*/(lib|tools)/.*\.h$'
CheckOptions:
- key: readability-braces-around-statements.ShortStatementLines
......
......@@ -31,7 +31,7 @@ variables:
# A template for running in the generic cloud builders. These are tagged with
# "linux" and run on shared VMs.
.linux_host_template: &linux_host_template
image: &jpegxl-builder gcr.io/jpegxl/jpegxl-builder@sha256:2add2725e5b9c3fb655bb90cdcb4fd2a48353714a86794f542b289addad6a5d0
image: &jpegxl-builder gcr.io/jpegxl/jpegxl-builder@sha256:ecf2acf6855f99ffff3b111fea62edffa0cba2378318cff3ca96113d946673a5
tags:
- linux
# By default all the workflows run on master and on request. This can be
......@@ -128,6 +128,8 @@ build:x86_64:clang:release:
- schedules
- tags
script:
# Check that the build files are up to date.
- tools/build_cleaner.py
- SKIP_TEST=1 PACK_TEST=1 STACK_SIZE=1
./ci.sh release -DCMAKE_INSTALL_PREFIX=`pwd`/prefix
# Test that the package can be installed.
......@@ -514,7 +516,7 @@ test:fast_benchmark.msan:
# This template runs on actual aarch64 hardware.
.benchmark_aarch64_template: &benchmark_aarch64_template
<<: *linux_host_template
image: gcr.io/jpegxl/jpegxl-builder-run-aarch64@sha256:f262597eb9c45a1b6ee9c18524abe84f340d6ef64b82285976776883813300bb
image: gcr.io/jpegxl/jpegxl-builder-run-aarch64@sha256:27c2bb6319023ab94d66670135a971401869a3275a7e0dda177c9bb247d57e03
stage: test
tags:
- aarch64
......
......@@ -170,6 +170,10 @@ if(JPEGXL_STATIC)
endif() # MINGW
endif() # JPEGXL_STATIC
if (MSVC)
# TODO(janwas): add flags
else ()
# Global compiler flags for all targets here and in subdirectories.
add_definitions(
# Avoid changing the binary based on the current time and date.
......@@ -219,6 +223,7 @@ add_compile_options(
if (JPEGXL_WARNINGS_AS_ERRORS)
add_compile_options(-Werror)
endif ()
endif () # !MSVC
include(GNUInstallDirs)
......
......@@ -3,14 +3,13 @@
This repository contains a reference implementation of JPEG XL (encoder and
decoder).
**NOTE**
JPEG XL is in the final stages of standardization and its codestream format is
frozen.
JPEG XL is in the final stages of standardization and is ready for freezing of
the codestream format. The current version is a release candidate, and we are
not expecting any changes beyond what is required by bug fixing.
**WARNING:** until further notice, do not depend on future decoders being able
to decode the output of a current encoder.
The libraries API, command line options and tools in this repository are subject
to change, however files encoded with `cjxl` conform to the JPEG XL format
specification and can be decoded with current and future `djxl` decoders or
`libjxl` decoding library.
## Quick start guide
......
......@@ -164,6 +164,26 @@ EOF
done < .gitmodules
}
# Make sure that all the Fields objects are fuzzed directly.
test_fuzz_fields() {
local ret=0
# List all the classes of the form "ClassName : public Fields".
# This doesn't catch class names that are too long to fit.
local field_classes=$( git ls-files |
grep -E '\.(cc|h)' | grep -v 'test\.cc$' |
xargs grep -h -o -E '\b[^ ]+ : public Fields' | cut -f 1 -d ' ')
local classname
for classname in ${field_classes}; do
if ! grep -E "\\b${classname}\\b" tools/fields_fuzzer.cc >/dev/null; then
cat >&2 <<EOF
tools/fields_fuzzer.cc: Class ${classname} not found in the fields_fuzzer.
EOF
ret=1
fi
done
return $ret
}
main() {
local ret=0
cd "${MYDIR}"
......
......@@ -1056,12 +1056,21 @@ cmd_fuzz() {
# Runs the linter (clang-format) on the pending CLs.
cmd_lint() {
merge_request_commits
# { set +x; } 2>/dev/null
{ set +x; } 2>/dev/null
local versions=(${1:-6.0 7 8 9})
local clang_format_bins=("${versions[@]/#/clang-format-}" clang-format)
local tmpdir=$(mktemp -d)
CLEANUP_FILES+=("${tmpdir}")
local ret=0
local build_patch="${tmpdir}/build_cleaner.patch"
if ! "${MYDIR}/tools/build_cleaner.py" >"${build_patch}"; then
ret=1
echo "build_cleaner.py findings:" >&2
"${COLORDIFF_BIN}" <"${build_patch}"
echo "Run \`tools/build_cleaner.py --update\` to apply them" >&2
fi
local installed=()
local clang_patch
local clang_format
......@@ -1085,7 +1094,7 @@ cmd_lint() {
clang_patch="${tmppatch}"
else
echo "clang-format check OK" >&2
return 0
return ${ret}
fi
done
......
jpeg-xl (0.2) UNRELEASED; urgency=medium
* Bump JPEG XL version to 0.2.
-- Alex Deymo <deymo@google.com> Wed, 23 Nov 2020 20:42:10 +0100
jpeg-xl (0.1) UNRELEASED; urgency=medium
* JPEG XL format release candidate.
......
......@@ -20,7 +20,11 @@ FROM ubuntu:bionic
# Set a prompt for when using it locally.
ENV PS1="\[\033[01;33m\]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "
COPY scripts/99_norecommends /etc/apt/apt.conf.d/99_norecommends
COPY scripts /jpegxl_scripts
ARG DEBIAN_FRONTEND=noninteractive
RUN /jpegxl_scripts/jpegxl_builder.sh && \
rm -rf /jpegxl_scripts
......@@ -18,15 +18,20 @@
FROM arm64v8/ubuntu:bionic
COPY scripts/99_norecommends /etc/apt/apt.conf.d/99_norecommends
# Set a prompt for when using it locally.
ENV PS1="\[\033[01;33m\]\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ "
ARG DEBIAN_FRONTEND=noninteractive
RUN set -ex; \
apt-get update -y; \
apt-get install -y \
bsdmainutils \
cmake \
curl \
ca-certificates \
extra-cmake-modules \
git \
imagemagick \
......
APT::Install-Recommends "false";
......@@ -92,7 +92,7 @@ LIST_WASM_TARGETS=(
# Setup the apt repositories and supported architectures.
setup_apt() {
apt-get update -y
apt-get install -y curl gnupg
apt-get install -y curl gnupg ca-certificates
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1E9377A2BA9EF27F
......@@ -153,6 +153,7 @@ install_pkgs() {
# For cross-compiling to Windows with mingw.
mingw-w64
wine64
wine-binfmt
# Native tools.
bsdmainutils
......@@ -237,8 +238,7 @@ install_pkgs() {
# Install all the manual packages via "apt install" for the main arch. These
# will be installed for other archs via manual download and unpack.
DEBIAN_FRONTEND=noninteractive apt install -y \
"${packages[@]}" "${UNPACK_PKGS[@]}"
apt install -y "${packages[@]}" "${UNPACK_PKGS[@]}"
}
# binutils <2.32 need a patch.
......@@ -471,7 +471,7 @@ main() {
ln -s "/opt/.jsvu/v8-${V8_VERSION}" "/opt/.jsvu/v8"
# Cleanup.
rm -rf /var/lib/apt/lists/*
find /var/lib/apt/lists/ -mindepth 1 -delete
}
main "$@"
......@@ -13,7 +13,7 @@
# limitations under the License.
set(JPEGXL_MAJOR_VERSION 0)
set(JPEGXL_MINOR_VERSION 1)
set(JPEGXL_MINOR_VERSION 2)
set(JPEGXL_PATCH_VERSION 0)
set(JPEGXL_LIBRARY_VERSION
"${JPEGXL_MAJOR_VERSION}.${JPEGXL_MINOR_VERSION}.${JPEGXL_PATCH_VERSION}")
......@@ -23,6 +23,11 @@ set(JPEGXL_LIBRARY_SOVERSION "${JPEGXL_MAJOR_VERSION}")
# List of warning and feature flags for our library and tests.
if (MSVC)
set(JPEGXL_INTERNAL_FLAGS
# TODO(janwas): add flags
)
else ()
set(JPEGXL_INTERNAL_FLAGS
# F_FLAGS
-fmerge-all-constants
......@@ -49,6 +54,8 @@ if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
list(APPEND JPEGXL_INTERNAL_FLAGS
-Wc++2a-extensions
-Wdeprecated-increment-bool
# TODO(deymo): Add -Wextra-semi once we update third_party/highway.
# -Wextra-semi
-Wfloat-overflow-conversion
-Wfloat-zero-conversion
-Wfor-loop-analysis
......@@ -63,6 +70,7 @@ if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
-Wtautological-overlap-compare
-Wthread-safety-analysis
-Wundefined-func-template
-Wunreachable-code
-Wunused-comparison
)
endif() # Clang
......@@ -115,6 +123,7 @@ set(JPEGXL_COVERAGE_FLAGS
-DJXL_ENABLE_ASSERT=0 -DJXL_ENABLE_CHECK=0
)
endif() # JPEGXL_ENABLE_COVERAGE
endif() #!MSVC
# The jxl library definition.
include(jxl.cmake)
......
......@@ -28,6 +28,7 @@
#include <vector>
#include "lib/jxl/base/compiler_specific.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/color_management.h"
#include "lib/jxl/common.h"
......@@ -67,10 +68,14 @@ bool MarkerIsICC(const jpeg_saved_marker_ptr marker) {
Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
PaddedBytes* const icc) {
constexpr size_t kICCSignatureSize = sizeof kICCSignature;
// ICC signature + uint8_t index + uint8_t max_index.
constexpr size_t kICCHeadSize = kICCSignatureSize + 2;
// Markers are 1-indexed, and we keep them that way in this vector to get a
// convenient 0 at the front for when we compute the offsets later.
std::vector<size_t> marker_lengths;
int num_markers = 0;
int seen_markers_count = 0;
bool has_num_markers = false;
for (jpeg_saved_marker_ptr marker = cinfo->marker_list; marker != nullptr;
marker = marker->next) {
......@@ -82,8 +87,8 @@ Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
#endif
if (!MarkerIsICC(marker)) continue;
const int current_marker = marker->data[sizeof kICCSignature];
const int current_num_markers = marker->data[sizeof kICCSignature + 1];
const int current_marker = marker->data[kICCSignatureSize];
const int current_num_markers = marker->data[kICCSignatureSize + 1];
if (current_marker > current_num_markers) {
return JXL_FAILURE("inconsistent JPEG ICC marker numbering");
}
......@@ -97,11 +102,18 @@ Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
marker_lengths.resize(num_markers + 1);
}
size_t marker_length = marker->data_length - kICCHeadSize;
if (marker_length == 0) {
// NB: if we allow empty chunks, then the next check is incorrect.
return JXL_FAILURE("Empty ICC chunk");
}
if (marker_lengths[current_marker] != 0) {
return JXL_FAILURE("duplicate JPEG ICC marker number");
}
marker_lengths[current_marker] =
marker->data_length - sizeof kICCSignature - 2;
marker_lengths[current_marker] = marker_length;
seen_markers_count++;
}
if (marker_lengths.empty()) {
......@@ -109,6 +121,11 @@ Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
return false;
}
if (seen_markers_count != num_markers) {
JXL_DASSERT(has_num_markers);
return JXL_FAILURE("Incomplete set of ICC chunks");
}
std::vector<size_t> offsets = std::move(marker_lengths);
std::partial_sum(offsets.begin(), offsets.end(), offsets.begin());
icc->resize(offsets.back());
......@@ -116,14 +133,11 @@ Status ReadICCProfile(jpeg_decompress_struct* const cinfo,
for (jpeg_saved_marker_ptr marker = cinfo->marker_list; marker != nullptr;
marker = marker->next) {
if (!MarkerIsICC(marker)) continue;
const uint8_t* first = marker->data + sizeof kICCSignature + 2;
size_t count = marker->data_length - sizeof kICCSignature - 2;
size_t offset = offsets[marker->data[sizeof kICCSignature] - 1];
if (offset + count > icc->size()) {
// TODO(lode): catch this issue earlier at the root cause of this.
return JXL_FAILURE("ICC out of bounds");
}
std::copy_n(first, count, icc->data() + offset);
const uint8_t* first = marker->data + kICCHeadSize;
uint8_t current_marker = marker->data[kICCSignatureSize];
size_t offset = offsets[current_marker - 1];
size_t marker_length = offsets[current_marker] - offset;
std::copy_n(first, marker_length, icc->data() + offset);
}
return true;
......@@ -264,18 +278,21 @@ Status ParseChunkedMarker(const jpeg::JPEGData& src, uint8_t marker_type,
return true;
}
void SetColorEncodingFromJpegData(const jpeg::JPEGData& jpg,
ColorEncoding* color_encoding) {
Status SetColorEncodingFromJpegData(const jpeg::JPEGData& jpg,
ColorEncoding* color_encoding) {
PaddedBytes icc_profile;
if (!ParseChunkedMarker(jpg, kApp2, ByteSpan(kIccProfileTag), &icc_profile)) {
JXL_WARNING("ReJPEG: corrupted ICC profile\n");
icc_profile.clear();
}
if (!color_encoding->SetICC(std::move(icc_profile))) {
if (icc_profile.empty()) {
bool is_gray = (jpg.components.size() == 1);
*color_encoding = ColorEncoding::SRGB(is_gray);
return true;
}
return color_encoding->SetICC(std::move(icc_profile));
}
} // namespace
......@@ -297,7 +314,8 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, ThreadPool* pool,
jpeg::JpegReadMode::kReadAll, jpeg_data)) {
return JXL_FAILURE("Error reading JPEG");
}
SetColorEncodingFromJpegData(*jpeg_data, &io->metadata.m.color_encoding);
JXL_RETURN_IF_ERROR(SetColorEncodingFromJpegData(
*jpeg_data, &io->metadata.m.color_encoding));
size_t nbcomp = jpeg_data->components.size();
if (nbcomp != 1 && nbcomp != 3) {
return JXL_FAILURE(
......@@ -311,12 +329,48 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, ThreadPool* pool,
vsample[i] = jpeg_data->components[i].v_samp_factor;
}
JXL_RETURN_IF_ERROR(cs.Set(hsample, vsample));
} else if (nbcomp == 1) {
uint8_t hsample[3], vsample[3];
for (size_t i = 0; i < 3; i++) {
hsample[i] = jpeg_data->components[0].h_samp_factor;
vsample[i] = jpeg_data->components[0].v_samp_factor;
}
JXL_RETURN_IF_ERROR(cs.Set(hsample, vsample));
}
bool is_rgb = false;
{
const auto& markers = jpeg_data->marker_order;
// If there is a JFIF marker, this is YCbCr. Otherwise...
if (std::find(markers.begin(), markers.end(), 0xE0) == markers.end()) {
// Try to find an 'Adobe' marker.
size_t app_markers = 0;
size_t i = 0;
for (; i < markers.size(); i++) {
// This is an APP marker.
if ((markers[i] & 0xF0) == 0xE0) {
JXL_CHECK(app_markers < jpeg_data->app_data.size());
// APP14 marker
if (markers[i] == 0xEE) {
const auto& data = jpeg_data->app_data[app_markers];
if (data.size() == 15 && data[3] == 'A' && data[4] == 'd' &&
data[5] == 'o' && data[6] == 'b' && data[7] == 'e') {
// 'Adobe' marker.
is_rgb = data[14] == 0;
break;
}
}
app_markers++;
}
}
if (i == markers.size()) {
// No 'Adobe' marker, guess from component IDs.
is_rgb = nbcomp == 3 && jpeg_data->components[0].id == 'R' &&
jpeg_data->components[1].id == 'G' &&
jpeg_data->components[2].id == 'B';
}
}
}
// TODO(veluca): This is just a guess, but it's similar to what libjpeg
// does.
bool is_rgb = nbcomp == 3 && jpeg_data->components[0].id == 'R' &&
jpeg_data->components[1].id == 'G' &&
jpeg_data->components[2].id == 'B';
io->Main().chroma_subsampling = cs;
io->Main().color_transform =
......@@ -365,6 +419,11 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, ThreadPool* pool,
bytes.size());
jpeg_save_markers(&cinfo, kICCMarker, 0xFFFF);
jpeg_read_header(&cinfo, TRUE);
if (!io->VerifyDimensions(cinfo.image_width, cinfo.image_height)) {
jpeg_abort_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return JXL_FAILURE("image too big");
}
if (ReadICCProfile(&cinfo, &icc)) {
if (!color_encoding.SetICC(std::move(icc))) {
jpeg_abort_decompress(&cinfo);
......@@ -390,11 +449,6 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes, ThreadPool* pool,
});
jpeg_start_decompress(&cinfo);
if (!io->VerifyDimensions(cinfo.image_width, cinfo.image_height)) {
jpeg_abort_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return JXL_FAILURE("image too big");
}
JXL_ASSERT(cinfo.output_components == nbcomp);
image = Image3F(cinfo.image_width, cinfo.image_height);
row.reset(new JSAMPLE[cinfo.output_components * cinfo.image_width]);
......@@ -554,14 +608,11 @@ Status EncodeImageJPG(const CodecInOut* io, JpegEncoder encoder, size_t quality,
}
if (target == DecodeTarget::kQuantizedCoeffs) {
auto write = [](void* data, const uint8_t* buf, size_t len) {
PaddedBytes* bytes = reinterpret_cast<PaddedBytes*>(data);
auto write = [&bytes](const uint8_t* buf, size_t len) {
bytes->append(buf, buf + len);
return len;
};
jpeg::JPEGOutput out(static_cast<jpeg::JPEGOutputHook>(write),
reinterpret_cast<void*>(bytes));
return jpeg::WriteJpeg(*io->Main().jpeg_data, out);
return jpeg::WriteJpeg(*io->Main().jpeg_data, write);
}
const ImageBundle* ib;
......
......@@ -257,11 +257,13 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes, ThreadPool* pool,
const bool has_alpha = false;
const bool flipped_y = false;
const Span<const uint8_t> span(pos, bytes.data() + bytes.size() - pos);
JXL_RETURN_IF_ERROR(ConvertImage(span, header.xsize, header.ysize,
io->metadata.m.color_encoding, has_alpha,
/*alpha_is_premultiplied=*/false,
io->metadata.m.bit_depth.bits_per_sample,
header.big_endian, flipped_y, pool, &ib));
JXL_RETURN_IF_ERROR(
ConvertImage(span, header.xsize, header.ysize,
io->metadata.m.color_encoding, has_alpha,
/*alpha_is_premultiplied=*/false,
io->metadata.m.bit_depth.bits_per_sample,
header.big_endian ? JXL_BIG_ENDIAN : JXL_LITTLE_ENDIAN,
flipped_y, pool, &ib));
io->frames.push_back(std::move(ib));
SetIntensityTarget(io);
return true;
......@@ -291,8 +293,8 @@ Status EncodeImagePGX(const CodecInOut* io, const ColorEncoding& c_desired,
size_t stride = ib.xsize() * (bits_per_sample / kBitsPerByte);
JXL_RETURN_IF_ERROR(ConvertImage(*transformed, bits_per_sample,
/*float_out=*/false, /*apply_srgb_tf=*/false,
/*num_channels=*/1, /*little_endian=*/false,
stride, pool, pixels.data(), pixels.size(),
/*num_channels=*/1, JXL_BIG_ENDIAN, stride,
pool, pixels.data(), pixels.size(),
jxl::Orientation::kIdentity));
char header[kMaxHeaderSize];
......
......@@ -387,6 +387,10 @@ class ColorEncodingReaderPNG {
}
char type_char[5];
if (chunk + 8 >= end) {
JXL_NOTIFY_ERROR("PNG: malformed chunk");
break;
}
lodepng_chunk_type(type_char, chunk);
std::string type = type_char;
......@@ -407,6 +411,7 @@ class ColorEncodingReaderPNG {
}
if (lodepng_chunk_check_crc(chunk) != 0) {
JXL_NOTIFY_ERROR("CRC mismatch in unknown PNG chunk");
chunk = lodepng_chunk_next_const(chunk, end);
continue;
}
......@@ -722,12 +727,12 @@ Status DecodeImagePNG(const Span<const uint8_t> bytes, ThreadPool* pool,
const size_t num_channels = (is_gray ? 1 : 3) + has_alpha;
const size_t out_size = w * h * num_channels * bits_per_sample / kBitsPerByte;
const bool big_endian = true; // PNG requirement
const JxlEndianness endianness = JXL_BIG_ENDIAN; // PNG requirement
const Span<const uint8_t> span(out, out_size);
const bool ok =
ConvertImage(span, w, h, io->metadata.m.color_encoding, has_alpha,
/*alpha_is_premultiplied=*/false,
io->metadata.m.bit_depth.bits_per_sample, big_endian,
io->metadata.m.bit_depth.bits_per_sample, endianness,
/*flipped_y=*/false, pool, &io->Main());
JXL_RETURN_IF_ERROR(ok);
io->dec_pixels = w * h;
......@@ -750,12 +755,11 @@ Status EncodeImagePNG(const CodecInOut* io, const ColorEncoding& c_desired,
ib.xsize() * DivCeil(c_desired.Channels() * bits_per_sample + alpha_bits,
kBitsPerByte);
PaddedBytes raw_bytes(stride * ib.ysize());
JXL_RETURN_IF_ERROR(
ConvertImage(*transformed, bits_per_sample,
/*float_out=*/false, /*apply_srgb_tf=*/false,
c_desired.Channels() + (ib.HasAlpha() ? 1 : 0),
/*little_endian=*/false, stride, pool, raw_bytes.data(),
raw_bytes.size(), jxl::Orientation::kIdentity));
JXL_RETURN_IF_ERROR(ConvertImage(
*transformed, bits_per_sample, /*float_out=*/false,
/*apply_srgb_tf=*/false, c_desired.Channels() + (ib.HasAlpha() ? 1 : 0),
JXL_BIG_ENDIAN, stride, pool, raw_bytes.data(), raw_bytes.size(),
jxl::Orientation::kIdentity));
PNGState state;
// For maximum compatibility, still store 8-bit even if pixels are all zero.
......
......@@ -354,8 +354,9 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes, ThreadPool* pool,
JXL_RETURN_IF_ERROR(ConvertImage(
span, header.xsize, header.ysize, io->metadata.m.color_encoding,
/*has_alpha=*/false, /*alpha_is_premultiplied=*/false,
io->metadata.m.bit_depth.bits_per_sample, header.big_endian, flipped_y,
pool, &io->Main()));
io->metadata.m.bit_depth.bits_per_sample,
header.big_endian ? JXL_BIG_ENDIAN : JXL_LITTLE_ENDIAN, flipped_y, pool,
&io->Main()));
if (!header.floating_point) {
io->metadata.m.bit_depth.bits_per_sample = io->Main().DetectRealBitdepth();
}
......@@ -369,7 +370,8 @@ Status EncodeImagePNM(const CodecInOut* io, const ColorEncoding& c_desired,
PaddedBytes* bytes) {
const bool floating_point = bits_per_sample > 16;
// Choose native for PFM; PGM/PPM require big-endian (N/A for PBM)
const bool little_endian = floating_point ? IsLittleEndian() : false;
const JxlEndianness endianness =
floating_point ? JXL_NATIVE_ENDIAN : JXL_BIG_ENDIAN;
ImageMetadata metadata_copy = io->metadata.m;
// AllDefault sets all_default, which can cause a race condition.
......@@ -402,12 +404,12 @@ Status EncodeImagePNM(const CodecInOut* io, const ColorEncoding& c_desired,
PaddedBytes pixels(stride * ib.ysize());
JXL_RETURN_IF_ERROR(ConvertImage(
*transformed, bits_per_sample, floating_point,
/*apply_srgb_tf=*/false, c_desired.Channels(), little_endian, stride,
pool, pixels.data(), pixels.size(), jxl::Orientation::kIdentity));
/*apply_srgb_tf=*/false, c_desired.Channels(), endianness, stride, pool,
pixels.data(), pixels.size(), jxl::Orientation::kIdentity));
char header[kMaxHeaderSize];
int header_size = 0;
JXL_RETURN_IF_ERROR(EncodeHeader(*transformed, bits_per_sample, little_endian,
JXL_RETURN_IF_ERROR(EncodeHeader(*transformed, bits_per_sample, endianness,
header, &header_size));
bytes->resize(static_cast<size_t>(header_size) + pixels.size());
......