summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/extras
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/jpeg-xl/lib/extras')
-rw-r--r--third_party/jpeg-xl/lib/extras/alpha_blend.cc7
-rw-r--r--third_party/jpeg-xl/lib/extras/alpha_blend.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/codec.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/codec_test.cc36
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/apng.cc119
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/color_description.cc99
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/color_hints.cc9
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/decode.cc6
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/decode.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/exr.cc9
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/gif.cc28
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jpegli.cc21
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jpg.cc30
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jxl.cc90
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/jxl.h4
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/pgx.cc11
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/pnm.cc31
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/apng.cc29
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/encode.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/encode.h2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/exr.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpegli.cc82
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpg.cc81
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jxl.cc45
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jxl.h8
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/npy.cc35
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/pgx.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/pnm.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/jpegli_test.cc18
-rw-r--r--third_party/jpeg-xl/lib/extras/mmap.cc7
-rw-r--r--third_party/jpeg-xl/lib/extras/packed_image.h55
-rw-r--r--third_party/jpeg-xl/lib/extras/packed_image_convert.cc51
-rw-r--r--third_party/jpeg-xl/lib/extras/tone_mapping.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc6
34 files changed, 564 insertions, 375 deletions
diff --git a/third_party/jpeg-xl/lib/extras/alpha_blend.cc b/third_party/jpeg-xl/lib/extras/alpha_blend.cc
index 50c141c6fb..afb37b0a7d 100644
--- a/third_party/jpeg-xl/lib/extras/alpha_blend.cc
+++ b/third_party/jpeg-xl/lib/extras/alpha_blend.cc
@@ -12,7 +12,7 @@ namespace extras {
namespace {
-void AlphaBlend(PackedFrame* frame, float background[3]) {
+void AlphaBlend(PackedFrame* frame, const float background[3]) {
if (!frame) return;
const PackedImage& im = frame->color;
JxlPixelFormat format = im.format;
@@ -20,7 +20,8 @@ void AlphaBlend(PackedFrame* frame, float background[3]) {
return;
}
--format.num_channels;
- PackedImage blended(im.xsize, im.ysize, format);
+ JXL_ASSIGN_OR_DIE(PackedImage blended,
+ PackedImage::Create(im.xsize, im.ysize, format));
// TODO(szabadka) SIMDify this and make it work for float16.
for (size_t y = 0; y < im.ysize; ++y) {
for (size_t x = 0; x < im.xsize; ++x) {
@@ -48,7 +49,7 @@ void AlphaBlend(PackedFrame* frame, float background[3]) {
} // namespace
-void AlphaBlend(PackedPixelFile* ppf, float background[3]) {
+void AlphaBlend(PackedPixelFile* ppf, const float background[3]) {
if (!ppf || ppf->info.alpha_bits == 0) {
return;
}
diff --git a/third_party/jpeg-xl/lib/extras/alpha_blend.h b/third_party/jpeg-xl/lib/extras/alpha_blend.h
index 4d78e8681b..e49349393c 100644
--- a/third_party/jpeg-xl/lib/extras/alpha_blend.h
+++ b/third_party/jpeg-xl/lib/extras/alpha_blend.h
@@ -11,7 +11,7 @@
namespace jxl {
namespace extras {
-void AlphaBlend(PackedPixelFile* ppf, float background[3]);
+void AlphaBlend(PackedPixelFile* ppf, const float background[3]);
} // namespace extras
} // namespace jxl
diff --git a/third_party/jpeg-xl/lib/extras/codec.h b/third_party/jpeg-xl/lib/extras/codec.h
index b7bc2a397e..9fd61503cb 100644
--- a/third_party/jpeg-xl/lib/extras/codec.h
+++ b/third_party/jpeg-xl/lib/extras/codec.h
@@ -43,7 +43,7 @@ JXL_INLINE Status SetFromBytes(const Span<const uint8_t> bytes, CodecInOut* io,
orig_codec);
}
-Status Encode(const extras::PackedPixelFile& ppf, const extras::Codec codec,
+Status Encode(const extras::PackedPixelFile& ppf, extras::Codec codec,
std::vector<uint8_t>* bytes, ThreadPool* pool);
Status Encode(const extras::PackedPixelFile& ppf, const std::string& pathname,
diff --git a/third_party/jpeg-xl/lib/extras/codec_test.cc b/third_party/jpeg-xl/lib/extras/codec_test.cc
index 4d8a60cb33..50d5e37bc9 100644
--- a/third_party/jpeg-xl/lib/extras/codec_test.cc
+++ b/third_party/jpeg-xl/lib/extras/codec_test.cc
@@ -40,12 +40,6 @@ 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) {
@@ -78,8 +72,8 @@ void VerifySameImage(const PackedImage& im0, size_t bits_per_sample0,
};
double factor0 = get_factor(im0.format, bits_per_sample0);
double factor1 = get_factor(im1.format, bits_per_sample1);
- auto pixels0 = static_cast<const uint8_t*>(im0.pixels());
- auto pixels1 = static_cast<const uint8_t*>(im1.pixels());
+ const auto* pixels0 = static_cast<const uint8_t*>(im0.pixels());
+ const auto* pixels1 = static_cast<const uint8_t*>(im1.pixels());
auto rgba0 =
test::ConvertToRGBA32(pixels0, im0.xsize, im0.ysize, im0.format, factor0);
auto rgba1 =
@@ -227,19 +221,23 @@ void CreateTestImage(const TestImageParams& params, PackedPixelFile* ppf) {
ppf->info.exponent_bits_per_sample = params.bits_per_sample == 32 ? 8 : 0;
ppf->info.num_color_channels = params.is_gray ? 1 : 3;
ppf->info.alpha_bits = params.add_alpha ? params.bits_per_sample : 0;
- ppf->info.alpha_premultiplied = (params.codec == Codec::kEXR);
+ ppf->info.alpha_premultiplied = TO_JXL_BOOL(params.codec == Codec::kEXR);
JxlColorEncoding color_encoding = CreateTestColorEncoding(params.is_gray);
ppf->icc = GenerateICC(color_encoding);
ppf->color_encoding = color_encoding;
- PackedFrame frame(params.xsize, params.ysize, params.PixelFormat());
+ JXL_ASSIGN_OR_DIE(
+ PackedFrame frame,
+ PackedFrame::Create(params.xsize, params.ysize, params.PixelFormat()));
FillPackedImage(params.bits_per_sample, &frame.color);
if (params.add_extra_channels) {
for (size_t i = 0; i < 7; ++i) {
JxlPixelFormat ec_format = params.PixelFormat();
ec_format.num_channels = 1;
- PackedImage ec(params.xsize, params.ysize, ec_format);
+ JXL_ASSIGN_OR_DIE(
+ PackedImage ec,
+ PackedImage::Create(params.xsize, params.ysize, ec_format));
FillPackedImage(params.bits_per_sample, &ec);
frame.extra_channels.emplace_back(std::move(ec));
PackedExtraChannel pec;
@@ -432,15 +430,17 @@ TEST(CodecTest, EncodeToPNG) {
ASSERT_TRUE(extras::DecodeBytes(Bytes(original_png), ColorHints(), &ppf));
const JxlPixelFormat& format = ppf.frames.front().color.format;
- ASSERT_THAT(
- png_encoder->AcceptedFormats(),
- Contains(AllOf(Field(&JxlPixelFormat::num_channels, format.num_channels),
- Field(&JxlPixelFormat::data_type, format.data_type),
- Field(&JxlPixelFormat::endianness, format.endianness))));
+ const auto& format_matcher = [&format](const JxlPixelFormat& candidate) {
+ return (candidate.num_channels == format.num_channels) &&
+ (candidate.data_type == format.data_type) &&
+ (candidate.endianness == format.endianness);
+ };
+ const auto formats = png_encoder->AcceptedFormats();
+ ASSERT_TRUE(std::any_of(formats.begin(), formats.end(), format_matcher));
EncodedImage encoded_png;
ASSERT_TRUE(png_encoder->Encode(ppf, &encoded_png, pool));
- EXPECT_THAT(encoded_png.icc, IsEmpty());
- ASSERT_THAT(encoded_png.bitstreams, SizeIs(1));
+ EXPECT_TRUE(encoded_png.icc.empty());
+ ASSERT_EQ(encoded_png.bitstreams.size(), 1);
PackedPixelFile decoded_ppf;
ASSERT_TRUE(extras::DecodeBytes(Bytes(encoded_png.bitstreams.front()),
diff --git a/third_party/jpeg-xl/lib/extras/dec/apng.cc b/third_party/jpeg-xl/lib/extras/dec/apng.cc
index f77dab77d1..8b0da06eb1 100644
--- a/third_party/jpeg-xl/lib/extras/dec/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/apng.cc
@@ -71,9 +71,7 @@ const png_byte kIgnoredPngChunks[] = {
};
// Returns floating-point value from the PNG encoding (times 10^5).
-static double F64FromU32(const uint32_t x) {
- return static_cast<int32_t>(x) * 1E-5;
-}
+double F64FromU32(const uint32_t x) { return static_cast<int32_t>(x) * 1E-5; }
Status DecodeSRGB(const unsigned char* payload, const size_t payload_size,
JxlColorEncoding* color_encoding) {
@@ -402,7 +400,8 @@ class BlobsReaderPNG {
}
if (pos + 2 >= encoded_end) return false; // Truncated base16 2;
- uint32_t nibble0, nibble1;
+ uint32_t nibble0;
+ uint32_t nibble1;
JXL_RETURN_IF_ERROR(DecodeNibble(pos[0], &nibble0));
JXL_RETURN_IF_ERROR(DecodeNibble(pos[1], &nibble1));
bytes->push_back(static_cast<uint8_t>((nibble0 << 4) + nibble1));
@@ -432,9 +431,22 @@ constexpr uint32_t kId_cHRM = 0x4D524863;
constexpr uint32_t kId_eXIf = 0x66495865;
struct APNGFrame {
- std::vector<uint8_t> pixels;
+ APNGFrame() : pixels(nullptr, free) {}
+ std::unique_ptr<void, decltype(free)*> pixels;
+ size_t pixels_size = 0;
std::vector<uint8_t*> rows;
unsigned int w, h, delay_num, delay_den;
+ Status Resize(size_t new_size) {
+ if (new_size > pixels_size) {
+ pixels.reset(malloc(new_size));
+ if (!pixels.get()) {
+ // TODO(szabadka): use specialized OOM error code
+ return JXL_FAILURE("Failed to allocate memory for image buffer");
+ }
+ pixels_size = new_size;
+ }
+ return true;
+ }
};
struct Reader {
@@ -447,7 +459,7 @@ struct Reader {
next += to_copy;
return (len == to_copy);
}
- bool Eof() { return next == last; }
+ bool Eof() const { return next == last; }
};
const unsigned long cMaxPNGSize = 1000000UL;
@@ -463,10 +475,11 @@ void info_fn(png_structp png_ptr, png_infop info_ptr) {
void row_fn(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num,
int pass) {
- APNGFrame* frame = (APNGFrame*)png_get_progressive_ptr(png_ptr);
+ APNGFrame* frame =
+ reinterpret_cast<APNGFrame*>(png_get_progressive_ptr(png_ptr));
JXL_CHECK(frame);
JXL_CHECK(row_num < frame->rows.size());
- JXL_CHECK(frame->rows[row_num] < frame->pixels.data() + frame->pixels.size());
+ JXL_CHECK(frame->rows[row_num] < frame->rows[0] + frame->pixels_size);
png_progressive_combine_row(png_ptr, frame->rows[row_num], new_row);
}
@@ -494,12 +507,13 @@ int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr,
unsigned char header[8] = {137, 80, 78, 71, 13, 10, 26, 10};
// Cleanup prior decoder, if any.
- png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+ png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
// Just in case. Not all versions on libpng wipe-out the pointers.
png_ptr = nullptr;
info_ptr = nullptr;
- png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_ptr =
+ png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
info_ptr = png_create_info_struct(png_ptr);
if (!png_ptr || !info_ptr) return 1;
@@ -508,18 +522,17 @@ int processing_start(png_structp& png_ptr, png_infop& info_ptr, void* frame_ptr,
}
png_set_keep_unknown_chunks(png_ptr, 1, kIgnoredPngChunks,
- (int)sizeof(kIgnoredPngChunks) / 5);
+ static_cast<int>(sizeof(kIgnoredPngChunks) / 5));
png_set_crc_action(png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
- png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, NULL);
+ png_set_progressive_read_fn(png_ptr, frame_ptr, info_fn, row_fn, nullptr);
png_process_data(png_ptr, info_ptr, header, 8);
png_process_data(png_ptr, info_ptr, chunkIHDR.data(), chunkIHDR.size());
if (hasInfo) {
- for (unsigned int i = 0; i < chunksInfo.size(); i++) {
- png_process_data(png_ptr, info_ptr, chunksInfo[i].data(),
- chunksInfo[i].size());
+ for (auto& chunk : chunksInfo) {
+ png_process_data(png_ptr, info_ptr, chunk.data(), chunk.size());
}
}
return 0;
@@ -575,8 +588,6 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
const SizeConstraints* constraints) {
#if JPEGXL_ENABLE_APNG
Reader r;
- unsigned int id, j, w, h, w0, h0, x0, y0;
- unsigned int delay_num, delay_den, dop, bop, rowbytes, imagesize;
unsigned char sig[8];
png_structp png_ptr = nullptr;
png_infop info_ptr = nullptr;
@@ -588,7 +599,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
bool seenFctl = false;
APNGFrame frameRaw = {};
uint32_t num_channels;
- JxlPixelFormat format;
+ JxlPixelFormat format = {};
unsigned int bytes_per_pixel = 0;
struct FrameInfo {
@@ -604,7 +615,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
// Make sure png memory is released in any case.
auto scope_guard = MakeScopeGuard([&]() {
- png_destroy_read_struct(&png_ptr, &info_ptr, 0);
+ png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
// Just in case. Not all versions on libpng wipe-out the pointers.
png_ptr = nullptr;
info_ptr = nullptr;
@@ -616,7 +627,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (!r.Read(sig, 8) || memcmp(sig, png_signature, 8) != 0) {
return false;
}
- id = read_chunk(&r, &chunkIHDR);
+ unsigned int id = read_chunk(&r, &chunkIHDR);
ppf->info.exponent_bits_per_sample = 0;
ppf->info.alpha_exponent_bits = 0;
@@ -625,18 +636,22 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
ppf->frames.clear();
bool have_color = false;
- bool have_cicp = false, have_iccp = false, have_srgb = false;
+ bool have_cicp = false;
+ bool have_iccp = false;
+ bool have_srgb = false;
bool errorstate = true;
if (id == kId_IHDR && chunkIHDR.size() == 25) {
- x0 = 0;
- y0 = 0;
- delay_num = 1;
- delay_den = 10;
- dop = 0;
- bop = 0;
-
- w0 = w = png_get_uint_32(chunkIHDR.data() + 8);
- h0 = h = png_get_uint_32(chunkIHDR.data() + 12);
+ unsigned int x0 = 0;
+ unsigned int y0 = 0;
+ unsigned int delay_num = 1;
+ unsigned int delay_den = 10;
+ unsigned int dop = 0;
+ unsigned int bop = 0;
+
+ unsigned int w = png_get_uint_32(chunkIHDR.data() + 8);
+ unsigned int h = png_get_uint_32(chunkIHDR.data() + 12);
+ unsigned int w0 = w;
+ unsigned int h0 = h;
if (w > cMaxPNGSize || h > cMaxPNGSize) {
return false;
}
@@ -648,8 +663,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
ppf->color_encoding.transfer_function = JXL_TRANSFER_FUNCTION_SRGB;
ppf->color_encoding.rendering_intent = JXL_RENDERING_INTENT_RELATIVE;
- if (!processing_start(png_ptr, info_ptr, (void*)&frameRaw, hasInfo,
- chunkIHDR, chunksInfo)) {
+ if (!processing_start(png_ptr, info_ptr, static_cast<void*>(&frameRaw),
+ hasInfo, chunkIHDR, chunksInfo)) {
while (!r.Eof()) {
id = read_chunk(&r, &chunk);
if (!id) break;
@@ -657,7 +672,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (id == kId_acTL && !hasInfo && !isAnimated) {
isAnimated = true;
- ppf->info.have_animation = true;
+ ppf->info.have_animation = JXL_TRUE;
ppf->info.animation.tps_numerator = 1000;
ppf->info.animation.tps_denominator = 1;
} else if (id == kId_IEND ||
@@ -666,8 +681,10 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (!processing_finish(png_ptr, info_ptr, &ppf->metadata)) {
// Allocates the frame buffer.
uint32_t duration = delay_num * 1000 / delay_den;
- frames.push_back(FrameInfo{PackedImage(w0, h0, format), duration,
- x0, w0, y0, h0, dop, bop});
+ JXL_ASSIGN_OR_RETURN(PackedImage image,
+ PackedImage::Create(w0, h0, format));
+ frames.push_back(FrameInfo{std::move(image), duration, x0, w0, y0,
+ h0, dop, bop});
auto& frame = frames.back().data;
for (size_t y = 0; y < h0; ++y) {
memcpy(static_cast<uint8_t*>(frame.pixels()) + frame.stride * y,
@@ -707,7 +724,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
if (hasInfo) {
memcpy(chunkIHDR.data() + 8, chunk.data() + 12, 8);
- if (processing_start(png_ptr, info_ptr, (void*)&frameRaw, hasInfo,
+ if (processing_start(png_ptr, info_ptr,
+ static_cast<void*>(&frameRaw), hasInfo,
chunkIHDR, chunksInfo)) {
break;
}
@@ -724,7 +742,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
int colortype = png_get_color_type(png_ptr, info_ptr);
int png_bit_depth = png_get_bit_depth(png_ptr, info_ptr);
ppf->info.bits_per_sample = png_bit_depth;
- png_color_8p sigbits = NULL;
+ png_color_8p sigbits = nullptr;
png_get_sBIT(png_ptr, info_ptr, &sigbits);
if (colortype & 1) {
// palette will actually be 8-bit regardless of the index bitdepth
@@ -784,12 +802,18 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
}
bytes_per_pixel =
num_channels * (format.data_type == JXL_TYPE_UINT16 ? 2 : 1);
- rowbytes = w * bytes_per_pixel;
- imagesize = h * rowbytes;
- frameRaw.pixels.resize(imagesize);
+ size_t rowbytes = w * bytes_per_pixel;
+ if (h > std::numeric_limits<size_t>::max() / rowbytes) {
+ return JXL_FAILURE("Image too big.");
+ }
+ size_t imagesize = h * rowbytes;
+ JXL_RETURN_IF_ERROR(frameRaw.Resize(imagesize));
frameRaw.rows.resize(h);
- for (j = 0; j < h; j++)
- frameRaw.rows[j] = frameRaw.pixels.data() + j * rowbytes;
+ for (size_t j = 0; j < h; j++) {
+ frameRaw.rows[j] =
+ reinterpret_cast<uint8_t*>(frameRaw.pixels.get()) +
+ j * rowbytes;
+ }
if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
break;
@@ -813,6 +837,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
have_cicp = true;
have_color = true;
ppf->icc.clear();
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
}
} else if (!have_cicp && id == kId_iCCP) {
if (processing_data(png_ptr, info_ptr, chunk.data(), chunk.size())) {
@@ -830,6 +856,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
&profile, &proflen);
if (ok && proflen) {
ppf->icc.assign(profile, profile + proflen);
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
have_color = true;
have_iccp = true;
} else {
@@ -922,7 +949,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
py0 + pys >= y0 + ysize && use_for_next_frame) {
// If the new frame is contained within the old frame, we can pad the
// new frame with zeros and not blend.
- PackedImage new_data(pxs, pys, frame.data.format);
+ JXL_ASSIGN_OR_RETURN(PackedImage new_data,
+ PackedImage::Create(pxs, pys, frame.data.format));
memset(new_data.pixels(), 0, new_data.pixels_size);
for (size_t y = 0; y < ysize; y++) {
size_t bytes_per_pixel =
@@ -944,7 +972,8 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
ppf->frames.emplace_back(std::move(new_data));
} else {
// If all else fails, insert a placeholder blank frame with kReplace.
- PackedImage blank(pxs, pys, frame.data.format);
+ JXL_ASSIGN_OR_RETURN(PackedImage blank,
+ PackedImage::Create(pxs, pys, frame.data.format));
memset(blank.pixels(), 0, blank.pixels_size);
ppf->frames.emplace_back(std::move(blank));
auto& pframe = ppf->frames.back();
@@ -984,7 +1013,7 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
has_nontrivial_background && frame.dispose_op == DISPOSE_OP_BACKGROUND;
}
if (ppf->frames.empty()) return JXL_FAILURE("No frames decoded");
- ppf->frames.back().frame_info.is_last = true;
+ ppf->frames.back().frame_info.is_last = JXL_TRUE;
return true;
#else
diff --git a/third_party/jpeg-xl/lib/extras/dec/color_description.cc b/third_party/jpeg-xl/lib/extras/dec/color_description.cc
index 54f6aa4206..bf229632d0 100644
--- a/third_party/jpeg-xl/lib/extras/dec/color_description.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/color_description.cc
@@ -9,6 +9,8 @@
#include <cmath>
+#include "lib/jxl/base/common.h"
+
namespace jxl {
namespace {
@@ -19,49 +21,46 @@ struct EnumName {
T value;
};
-const EnumName<JxlColorSpace> kJxlColorSpaceNames[] = {
- {"RGB", JXL_COLOR_SPACE_RGB},
- {"Gra", JXL_COLOR_SPACE_GRAY},
- {"XYB", JXL_COLOR_SPACE_XYB},
- {"CS?", JXL_COLOR_SPACE_UNKNOWN},
-};
-
-const EnumName<JxlWhitePoint> kJxlWhitePointNames[] = {
- {"D65", JXL_WHITE_POINT_D65},
- {"Cst", JXL_WHITE_POINT_CUSTOM},
- {"EER", JXL_WHITE_POINT_E},
- {"DCI", JXL_WHITE_POINT_DCI},
-};
-
-const EnumName<JxlPrimaries> kJxlPrimariesNames[] = {
- {"SRG", JXL_PRIMARIES_SRGB},
- {"Cst", JXL_PRIMARIES_CUSTOM},
- {"202", JXL_PRIMARIES_2100},
- {"DCI", JXL_PRIMARIES_P3},
-};
-
-const EnumName<JxlTransferFunction> kJxlTransferFunctionNames[] = {
- {"709", JXL_TRANSFER_FUNCTION_709},
- {"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN},
- {"Lin", JXL_TRANSFER_FUNCTION_LINEAR},
- {"SRG", JXL_TRANSFER_FUNCTION_SRGB},
- {"PeQ", JXL_TRANSFER_FUNCTION_PQ},
- {"DCI", JXL_TRANSFER_FUNCTION_DCI},
- {"HLG", JXL_TRANSFER_FUNCTION_HLG},
- {"", JXL_TRANSFER_FUNCTION_GAMMA},
-};
-
-const EnumName<JxlRenderingIntent> kJxlRenderingIntentNames[] = {
- {"Per", JXL_RENDERING_INTENT_PERCEPTUAL},
- {"Rel", JXL_RENDERING_INTENT_RELATIVE},
- {"Sat", JXL_RENDERING_INTENT_SATURATION},
- {"Abs", JXL_RENDERING_INTENT_ABSOLUTE},
-};
-
-template <typename T>
-Status ParseEnum(const std::string& token, const EnumName<T>* enum_values,
- size_t enum_len, T* value) {
- for (size_t i = 0; i < enum_len; i++) {
+constexpr auto kJxlColorSpaceNames =
+ to_array<EnumName<JxlColorSpace>>({{"RGB", JXL_COLOR_SPACE_RGB},
+ {"Gra", JXL_COLOR_SPACE_GRAY},
+ {"XYB", JXL_COLOR_SPACE_XYB},
+ {"CS?", JXL_COLOR_SPACE_UNKNOWN}});
+
+constexpr auto kJxlWhitePointNames =
+ to_array<EnumName<JxlWhitePoint>>({{"D65", JXL_WHITE_POINT_D65},
+ {"Cst", JXL_WHITE_POINT_CUSTOM},
+ {"EER", JXL_WHITE_POINT_E},
+ {"DCI", JXL_WHITE_POINT_DCI}});
+
+constexpr auto kJxlPrimariesNames =
+ to_array<EnumName<JxlPrimaries>>({{"SRG", JXL_PRIMARIES_SRGB},
+ {"Cst", JXL_PRIMARIES_CUSTOM},
+ {"202", JXL_PRIMARIES_2100},
+ {"DCI", JXL_PRIMARIES_P3}});
+
+constexpr auto kJxlTransferFunctionNames =
+ to_array<EnumName<JxlTransferFunction>>(
+ {{"709", JXL_TRANSFER_FUNCTION_709},
+ {"TF?", JXL_TRANSFER_FUNCTION_UNKNOWN},
+ {"Lin", JXL_TRANSFER_FUNCTION_LINEAR},
+ {"SRG", JXL_TRANSFER_FUNCTION_SRGB},
+ {"PeQ", JXL_TRANSFER_FUNCTION_PQ},
+ {"DCI", JXL_TRANSFER_FUNCTION_DCI},
+ {"HLG", JXL_TRANSFER_FUNCTION_HLG},
+ {"", JXL_TRANSFER_FUNCTION_GAMMA}});
+
+constexpr auto kJxlRenderingIntentNames =
+ to_array<EnumName<JxlRenderingIntent>>(
+ {{"Per", JXL_RENDERING_INTENT_PERCEPTUAL},
+ {"Rel", JXL_RENDERING_INTENT_RELATIVE},
+ {"Sat", JXL_RENDERING_INTENT_SATURATION},
+ {"Abs", JXL_RENDERING_INTENT_ABSOLUTE}});
+
+template <typename T, size_t N>
+Status ParseEnum(const std::string& token,
+ const std::array<EnumName<T>, N>& enum_values, T* value) {
+ for (size_t i = 0; i < enum_values.size(); i++) {
if (enum_values[i].name == token) {
*value = enum_values[i].value;
return true;
@@ -69,9 +68,6 @@ Status ParseEnum(const std::string& token, const EnumName<T>* enum_values,
}
return false;
}
-#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
-#define PARSE_ENUM(type, token, value) \
- ParseEnum<type>(token, k##type##Names, ARRAY_SIZE(k##type##Names), value)
class Tokenizer {
public:
@@ -122,7 +118,7 @@ Status ParseColorSpace(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
JxlColorSpace cs;
- if (PARSE_ENUM(JxlColorSpace, str, &cs)) {
+ if (ParseEnum(str, kJxlColorSpaceNames, &cs)) {
c->color_space = cs;
return true;
}
@@ -139,7 +135,7 @@ Status ParseWhitePoint(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlWhitePoint, str, &c->white_point)) return true;
+ if (ParseEnum(str, kJxlWhitePointNames, &c->white_point)) return true;
Tokenizer xy_tokenizer(&str, ';');
c->white_point = JXL_WHITE_POINT_CUSTOM;
@@ -157,7 +153,7 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlPrimaries, str, &c->primaries)) return true;
+ if (ParseEnum(str, kJxlPrimariesNames, &c->primaries)) return true;
Tokenizer xy_tokenizer(&str, ';');
JXL_RETURN_IF_ERROR(ParseDouble(&xy_tokenizer, c->primaries_red_xy + 0));
@@ -174,7 +170,8 @@ Status ParsePrimaries(Tokenizer* tokenizer, JxlColorEncoding* c) {
Status ParseRenderingIntent(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlRenderingIntent, str, &c->rendering_intent)) return true;
+ if (ParseEnum(str, kJxlRenderingIntentNames, &c->rendering_intent))
+ return true;
return JXL_FAILURE("Invalid RenderingIntent %s\n", str.c_str());
}
@@ -189,7 +186,7 @@ Status ParseTransferFunction(Tokenizer* tokenizer, JxlColorEncoding* c) {
std::string str;
JXL_RETURN_IF_ERROR(tokenizer->Next(&str));
- if (PARSE_ENUM(JxlTransferFunction, str, &c->transfer_function)) {
+ if (ParseEnum(str, kJxlTransferFunctionNames, &c->transfer_function)) {
return true;
}
diff --git a/third_party/jpeg-xl/lib/extras/dec/color_hints.cc b/third_party/jpeg-xl/lib/extras/dec/color_hints.cc
index 5c6d7b84a0..b1edd9f6ea 100644
--- a/third_party/jpeg-xl/lib/extras/dec/color_hints.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/color_hints.cc
@@ -43,20 +43,21 @@ Status ApplyColorHints(const ColorHints& color_hints,
} else if (key == "icc") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> icc(data, data + value.size());
- ppf->icc.swap(icc);
+ ppf->icc = std::move(icc);
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
got_color_space = true;
} else if (key == "exif") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> blob(data, data + value.size());
- ppf->metadata.exif.swap(blob);
+ ppf->metadata.exif = std::move(blob);
} else if (key == "xmp") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> blob(data, data + value.size());
- ppf->metadata.xmp.swap(blob);
+ ppf->metadata.xmp = std::move(blob);
} else if (key == "jumbf") {
const uint8_t* data = reinterpret_cast<const uint8_t*>(value.data());
std::vector<uint8_t> blob(data, data + value.size());
- ppf->metadata.jumbf.swap(blob);
+ ppf->metadata.jumbf = std::move(blob);
} else {
JXL_WARNING("Ignoring %s hint", key.c_str());
}
diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.cc b/third_party/jpeg-xl/lib/extras/dec/decode.cc
index b3ca711bb2..3546cb65c0 100644
--- a/third_party/jpeg-xl/lib/extras/dec/decode.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/decode.cc
@@ -35,7 +35,8 @@ std::string GetExtension(const std::string& path) {
} // namespace
-Codec CodecFromPath(std::string path, size_t* JXL_RESTRICT bits_per_sample,
+Codec CodecFromPath(const std::string& path,
+ size_t* JXL_RESTRICT bits_per_sample,
std::string* extension) {
std::string ext = GetExtension(path);
if (extension) {
@@ -98,7 +99,7 @@ Status DecodeBytes(const Span<const uint8_t> bytes,
*ppf = extras::PackedPixelFile();
// Default values when not set by decoders.
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
ppf->info.orientation = JXL_ORIENT_IDENTITY;
const auto choose_codec = [&]() -> Codec {
@@ -116,6 +117,7 @@ Status DecodeBytes(const Span<const uint8_t> bytes,
dparams.accepted_formats.push_back(
{num_channels, JXL_TYPE_FLOAT, JXL_LITTLE_ENDIAN, /*align=*/0});
}
+ dparams.output_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM;
size_t decoded_bytes;
if (DecodeImageJXL(bytes.data(), bytes.size(), dparams, &decoded_bytes,
ppf) &&
diff --git a/third_party/jpeg-xl/lib/extras/dec/decode.h b/third_party/jpeg-xl/lib/extras/dec/decode.h
index 0d7dfcbef2..1a90f4c6a3 100644
--- a/third_party/jpeg-xl/lib/extras/dec/decode.h
+++ b/third_party/jpeg-xl/lib/extras/dec/decode.h
@@ -40,7 +40,7 @@ bool CanDecode(Codec codec);
// 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(std::string path,
+Codec CodecFromPath(const std::string& path,
size_t* JXL_RESTRICT bits_per_sample = nullptr,
std::string* extension = nullptr);
diff --git a/third_party/jpeg-xl/lib/extras/dec/exr.cc b/third_party/jpeg-xl/lib/extras/dec/exr.cc
index 821e0f4b21..d5903155e9 100644
--- a/third_party/jpeg-xl/lib/extras/dec/exr.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/exr.cc
@@ -121,7 +121,12 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(image_size.x, image_size.y, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(image_size.x, image_size.y, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
const int row_size = input.dataWindow().size().x + 1;
@@ -188,7 +193,7 @@ Status DecodeImageEXR(Span<const uint8_t> bytes, const ColorHints& color_hints,
if (has_alpha) {
ppf->info.alpha_bits = kExrAlphaBits;
ppf->info.alpha_exponent_bits = ppf->info.exponent_bits_per_sample;
- ppf->info.alpha_premultiplied = true;
+ ppf->info.alpha_premultiplied = JXL_TRUE;
}
ppf->info.intensity_target = intensity_target;
return true;
diff --git a/third_party/jpeg-xl/lib/extras/dec/gif.cc b/third_party/jpeg-xl/lib/extras/dec/gif.cc
index 3d963941c0..3f89d460b8 100644
--- a/third_party/jpeg-xl/lib/extras/dec/gif.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/gif.cc
@@ -50,8 +50,10 @@ void ensure_have_alpha(PackedFrame* frame) {
/*endianness=*/JXL_NATIVE_ENDIAN,
/*align=*/0,
};
- frame->extra_channels.emplace_back(frame->color.xsize, frame->color.ysize,
- alpha_format);
+ JXL_ASSIGN_OR_DIE(PackedImage image,
+ PackedImage::Create(frame->color.xsize, frame->color.ysize,
+ alpha_format));
+ frame->extra_channels.emplace_back(std::move(image));
// We need to set opaque-by-default.
std::fill_n(static_cast<uint8_t*>(frame->extra_channels[0].pixels()),
frame->color.xsize * frame->color.ysize, 255u);
@@ -136,7 +138,7 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
if (gif->ImageCount > 1) {
- ppf->info.have_animation = true;
+ ppf->info.have_animation = JXL_TRUE;
// Delays in GIF are specified in 100ths of a second.
ppf->info.animation.tps_numerator = 100;
ppf->info.animation.tps_denominator = 1;
@@ -186,7 +188,9 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
const PackedRgba background_rgba{background_color.Red, background_color.Green,
background_color.Blue, 0};
- PackedFrame canvas(gif->SWidth, gif->SHeight, canvas_format);
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame canvas,
+ PackedFrame::Create(gif->SWidth, gif->SHeight, canvas_format));
std::fill_n(static_cast<PackedRgba*>(canvas.color.pixels()),
canvas.color.xsize * canvas.color.ysize, background_rgba);
Rect canvas_rect{0, 0, canvas.color.xsize, canvas.color.ysize};
@@ -230,8 +234,14 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Allocates the frame buffer.
- ppf->frames.emplace_back(total_rect.xsize(), total_rect.ysize(),
- packed_frame_format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(total_rect.xsize(), total_rect.ysize(),
+ packed_frame_format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
+
PackedFrame* frame = &ppf->frames.back();
// We cannot tell right from the start whether there will be a
@@ -301,8 +311,10 @@ Status DecodeImageGIF(Span<const uint8_t> bytes, const ColorHints& color_hints,
}
// Update the canvas by creating a copy first.
- PackedImage new_canvas_image(canvas.color.xsize, canvas.color.ysize,
- canvas.color.format);
+ JXL_ASSIGN_OR_RETURN(
+ PackedImage new_canvas_image,
+ PackedImage::Create(canvas.color.xsize, canvas.color.ysize,
+ canvas.color.format));
memcpy(new_canvas_image.pixels(), canvas.color.pixels(),
new_canvas_image.pixels_size);
for (size_t y = 0, byte_index = 0; y < image_rect.ysize(); ++y) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/jpegli.cc b/third_party/jpeg-xl/lib/extras/dec/jpegli.cc
index ffa1b79c25..443dfe86ba 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jpegli.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jpegli.cc
@@ -27,7 +27,7 @@ constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69,
constexpr int kExifMarker = JPEG_APP0 + 1;
constexpr int kICCMarker = JPEG_APP0 + 2;
-static inline bool IsJPG(const std::vector<uint8_t>& bytes) {
+inline bool IsJPG(const std::vector<uint8_t>& bytes) {
if (bytes.size() < 2) return false;
if (bytes[0] != 0xFF || bytes[1] != 0xD8) return false;
return true;
@@ -188,7 +188,11 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
} else if (dparams.force_grayscale) {
cinfo.out_color_space = JCS_GRAYSCALE;
}
- if (!ReadICCProfile(&cinfo, &ppf->icc)) {
+ if (ReadICCProfile(&cinfo, &ppf->icc)) {
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ } else {
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
ppf->icc.clear();
// Default to SRGB
ppf->color_encoding.color_space =
@@ -214,7 +218,7 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
} else {
return failure("unsupported data type");
}
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in JPG
ppf->info.alpha_bits = 0;
@@ -227,8 +231,8 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
if (dparams.num_colors > 0) {
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = dparams.num_colors;
- cinfo.two_pass_quantize = dparams.two_pass_quant;
- cinfo.dither_mode = (J_DITHER_MODE)dparams.dither_mode;
+ cinfo.two_pass_quantize = static_cast<boolean>(dparams.two_pass_quant);
+ cinfo.dither_mode = static_cast<J_DITHER_MODE>(dparams.dither_mode);
}
jpegli_start_decompress(&cinfo);
@@ -242,7 +246,12 @@ Status DecodeJpeg(const std::vector<uint8_t>& compressed,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=
diff --git a/third_party/jpeg-xl/lib/extras/dec/jpg.cc b/third_party/jpeg-xl/lib/extras/dec/jpg.cc
index 3c8a4bccfe..4a3e0d3b21 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jpg.cc
@@ -34,7 +34,7 @@ constexpr unsigned char kExifSignature[6] = {0x45, 0x78, 0x69,
0x66, 0x00, 0x00};
constexpr int kExifMarker = JPEG_APP0 + 1;
-static inline bool IsJPG(const Span<const uint8_t> bytes) {
+inline bool IsJPG(const Span<const uint8_t> bytes) {
if (bytes.size() < 2) return false;
if (bytes[0] != 0xFF || bytes[1] != 0xD8) return false;
return true;
@@ -242,7 +242,11 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
if (nbcomp != 1 && nbcomp != 3) {
return failure("unsupported number of components in JPEG");
}
- if (!ReadICCProfile(&cinfo, &ppf->icc)) {
+ if (ReadICCProfile(&cinfo, &ppf->icc)) {
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ } else {
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
ppf->icc.clear();
// Default to SRGB
// Actually, (cinfo.output_components == nbcomp) will be checked after
@@ -266,7 +270,7 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
ppf->info.bits_per_sample = BITS_IN_JSAMPLE;
JXL_ASSERT(BITS_IN_JSAMPLE == 8 || BITS_IN_JSAMPLE == 16);
ppf->info.exponent_bits_per_sample = 0;
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in JPG
ppf->info.alpha_bits = 0;
@@ -278,8 +282,8 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
if (dparams && dparams->num_colors > 0) {
cinfo.quantize_colors = TRUE;
cinfo.desired_number_of_colors = dparams->num_colors;
- cinfo.two_pass_quantize = dparams->two_pass_quant;
- cinfo.dither_mode = (J_DITHER_MODE)dparams->dither_mode;
+ cinfo.two_pass_quantize = static_cast<boolean>(dparams->two_pass_quant);
+ cinfo.dither_mode = static_cast<J_DITHER_MODE>(dparams->dither_mode);
}
jpeg_start_decompress(&cinfo);
@@ -295,19 +299,25 @@ Status DecodeImageJPG(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(cinfo.image_width, cinfo.image_height, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(cinfo.image_width, cinfo.image_height, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
JXL_ASSERT(sizeof(JSAMPLE) * cinfo.out_color_components *
cinfo.image_width <=
frame.color.stride);
if (cinfo.quantize_colors) {
- jxl::msan::UnpoisonMemory(cinfo.colormap, cinfo.out_color_components *
- sizeof(cinfo.colormap[0]));
+ JSAMPLE** colormap = cinfo.colormap;
+ jxl::msan::UnpoisonMemory(reinterpret_cast<void*>(colormap),
+ cinfo.out_color_components * sizeof(JSAMPLE*));
for (int c = 0; c < cinfo.out_color_components; ++c) {
jxl::msan::UnpoisonMemory(
- cinfo.colormap[c],
- cinfo.actual_number_of_colors * sizeof(cinfo.colormap[c][0]));
+ reinterpret_cast<void*>(colormap[c]),
+ cinfo.actual_number_of_colors * sizeof(JSAMPLE));
}
}
for (size_t y = 0; y < cinfo.image_height; ++y) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.cc b/third_party/jpeg-xl/lib/extras/dec/jxl.cc
index f3e62c970a..5b7fa03f02 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jxl.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/jxl.cc
@@ -16,20 +16,23 @@
#include "lib/extras/dec/color_description.h"
#include "lib/jxl/base/exif.h"
#include "lib/jxl/base/printf_macros.h"
+#include "lib/jxl/base/status.h"
namespace jxl {
namespace extras {
namespace {
struct BoxProcessor {
- BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); }
+ explicit BoxProcessor(JxlDecoder* dec) : dec_(dec) { Reset(); }
void InitializeOutput(std::vector<uint8_t>* out) {
+ JXL_ASSERT(out != nullptr);
box_data_ = out;
AddMoreOutput();
}
bool AddMoreOutput() {
+ JXL_ASSERT(box_data_ != nullptr);
Flush();
static const size_t kBoxOutputChunkSize = 1 << 16;
box_data_->resize(box_data_->size() + kBoxOutputChunkSize);
@@ -126,7 +129,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
- JxlPixelFormat format;
+ JxlPixelFormat format = {}; // Initialize to calm down clang-tidy.
std::vector<JxlPixelFormat> accepted_formats = dparams.accepted_formats;
JxlColorEncoding color_encoding;
@@ -177,18 +180,18 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
if (jpeg_bytes == nullptr) {
- if (JXL_DEC_SUCCESS !=
- JxlDecoderSetRenderSpotcolors(dec, dparams.render_spotcolors)) {
+ if (JXL_DEC_SUCCESS != JxlDecoderSetRenderSpotcolors(
+ dec, TO_JXL_BOOL(dparams.render_spotcolors))) {
fprintf(stderr, "JxlDecoderSetRenderSpotColors failed\n");
return false;
}
- if (JXL_DEC_SUCCESS !=
- JxlDecoderSetKeepOrientation(dec, dparams.keep_orientation)) {
+ if (JXL_DEC_SUCCESS != JxlDecoderSetKeepOrientation(
+ dec, TO_JXL_BOOL(dparams.keep_orientation))) {
fprintf(stderr, "JxlDecoderSetKeepOrientation failed\n");
return false;
}
- if (JXL_DEC_SUCCESS !=
- JxlDecoderSetUnpremultiplyAlpha(dec, dparams.unpremultiply_alpha)) {
+ if (JXL_DEC_SUCCESS != JxlDecoderSetUnpremultiplyAlpha(
+ dec, TO_JXL_BOOL(dparams.unpremultiply_alpha))) {
fprintf(stderr, "JxlDecoderSetUnpremultiplyAlpha failed\n");
return false;
}
@@ -267,6 +270,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
return false;
}
} else if (status == JXL_DEC_JPEG_NEED_MORE_OUTPUT) {
+ JXL_ASSERT(jpeg_bytes != nullptr); // Help clang-tidy.
// Decoded a chunk to JPEG.
size_t used_jpeg_output =
jpeg_data_chunk.size() - JxlDecoderReleaseJPEGBuffer(dec);
@@ -309,7 +313,7 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
} else {
if (dparams.unpremultiply_alpha) {
// Mark in the basic info that alpha was unpremultiplied.
- ppf->info.alpha_premultiplied = false;
+ ppf->info.alpha_premultiplied = JXL_FALSE;
}
}
bool alpha_found = false;
@@ -327,7 +331,8 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
std::string name(eci.name_length + 1, 0);
if (JXL_DEC_SUCCESS !=
- JxlDecoderGetExtraChannelName(dec, i, &name[0], name.size())) {
+ JxlDecoderGetExtraChannelName(
+ dec, i, const_cast<char*>(name.data()), name.size())) {
fprintf(stderr, "JxlDecoderGetExtraChannelName failed\n");
return false;
}
@@ -351,24 +356,26 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
size_t icc_size = 0;
JxlColorProfileTarget target = JXL_COLOR_PROFILE_TARGET_DATA;
- ppf->color_encoding.color_space = JXL_COLOR_SPACE_UNKNOWN;
- if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsEncodedProfile(
- dec, target, &ppf->color_encoding) ||
- dparams.need_icc) {
- // only get ICC if it is not an Enum color encoding
- if (JXL_DEC_SUCCESS !=
- JxlDecoderGetICCProfileSize(dec, target, &icc_size)) {
- fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n");
- }
- if (icc_size != 0) {
- ppf->icc.resize(icc_size);
- if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
- dec, target, ppf->icc.data(), icc_size)) {
- fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
- return false;
- }
+ if (JXL_DEC_SUCCESS !=
+ JxlDecoderGetICCProfileSize(dec, target, &icc_size)) {
+ fprintf(stderr, "JxlDecoderGetICCProfileSize failed\n");
+ }
+ if (icc_size != 0) {
+ ppf->primary_color_representation = PackedPixelFile::kIccIsPrimary;
+ ppf->icc.resize(icc_size);
+ if (JXL_DEC_SUCCESS != JxlDecoderGetColorAsICCProfile(
+ dec, target, ppf->icc.data(), icc_size)) {
+ fprintf(stderr, "JxlDecoderGetColorAsICCProfile failed\n");
+ return false;
}
}
+ if (JXL_DEC_SUCCESS == JxlDecoderGetColorAsEncodedProfile(
+ dec, target, &ppf->color_encoding)) {
+ ppf->primary_color_representation =
+ PackedPixelFile::kColorEncodingIsPrimary;
+ } else {
+ ppf->color_encoding.color_space = JXL_COLOR_SPACE_UNKNOWN;
+ }
icc_size = 0;
target = JXL_COLOR_PROFILE_TARGET_ORIGINAL;
if (JXL_DEC_SUCCESS !=
@@ -385,14 +392,21 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
}
}
} else if (status == JXL_DEC_FRAME) {
- jxl::extras::PackedFrame frame(ppf->info.xsize, ppf->info.ysize, format);
+ auto frame_or = jxl::extras::PackedFrame::Create(ppf->info.xsize,
+ ppf->info.ysize, format);
+ if (!frame_or.status()) {
+ fprintf(stderr, "Failed to create image frame.");
+ return false;
+ }
+ jxl::extras::PackedFrame frame = std::move(frame_or).value();
if (JXL_DEC_SUCCESS != JxlDecoderGetFrameHeader(dec, &frame.frame_info)) {
fprintf(stderr, "JxlDecoderGetFrameHeader failed\n");
return false;
}
frame.name.resize(frame.frame_info.name_length + 1, 0);
if (JXL_DEC_SUCCESS !=
- JxlDecoderGetFrameName(dec, &frame.name[0], frame.name.size())) {
+ JxlDecoderGetFrameName(dec, const_cast<char*>(frame.name.data()),
+ frame.name.size())) {
fprintf(stderr, "JxlDecoderGetFrameName failed\n");
return false;
}
@@ -423,9 +437,16 @@ 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 = std::unique_ptr<jxl::extras::PackedFrame>(
- new jxl::extras::PackedFrame(ppf->info.preview.xsize,
- ppf->info.preview.ysize, format));
+ new jxl::extras::PackedFrame(std::move(preview_image)));
if (buffer_size != ppf->preview_frame->color.pixels_size) {
fprintf(stderr, "Invalid out buffer size %" PRIuS " %" PRIuS "\n",
buffer_size, ppf->preview_frame->color.pixels_size);
@@ -492,8 +513,13 @@ bool DecodeImageJXL(const uint8_t* bytes, size_t bytes_size,
JxlPixelFormat ec_format = format;
ec_format.num_channels = 1;
for (auto& eci : ppf->extra_channels_info) {
- frame.extra_channels.emplace_back(jxl::extras::PackedImage(
- ppf->info.xsize, ppf->info.ysize, ec_format));
+ 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());
auto& ec = frame.extra_channels.back();
size_t buffer_size;
if (JXL_DEC_SUCCESS != JxlDecoderExtraChannelBufferSize(
diff --git a/third_party/jpeg-xl/lib/extras/dec/jxl.h b/third_party/jpeg-xl/lib/extras/dec/jxl.h
index cbada1f6dd..5f4ed7f683 100644
--- a/third_party/jpeg-xl/lib/extras/dec/jxl.h
+++ b/third_party/jpeg-xl/lib/extras/dec/jxl.h
@@ -41,10 +41,6 @@ struct JXLDecompressParams {
// Whether truncated input should be treated as an error.
bool allow_partial_input = false;
- // Set to true if an ICC profile has to be synthesized for Enum color
- // encodings
- bool need_icc = false;
-
// How many passes to decode at most. By default, decode everything.
uint32_t max_passes = std::numeric_limits<uint32_t>::max();
diff --git a/third_party/jpeg-xl/lib/extras/dec/pgx.cc b/third_party/jpeg-xl/lib/extras/dec/pgx.cc
index a99eb0f4ee..4499069d77 100644
--- a/third_party/jpeg-xl/lib/extras/dec/pgx.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/pgx.cc
@@ -150,7 +150,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
const SizeConstraints* constraints) {
Parser parser(bytes);
HeaderPGX header = {};
- const uint8_t* pos;
+ const uint8_t* pos = nullptr;
if (!parser.ParseHeader(&header, &pos)) return false;
JXL_RETURN_IF_ERROR(
VerifyDimensions(constraints, header.xsize, header.ysize));
@@ -165,7 +165,7 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
// Original data is uint, so exponent_bits_per_sample = 0.
ppf->info.bits_per_sample = header.bits_per_sample;
ppf->info.exponent_bits_per_sample = 0;
- ppf->info.uses_original_profile = true;
+ ppf->info.uses_original_profile = JXL_TRUE;
// No alpha in PGX
ppf->info.alpha_bits = 0;
@@ -188,7 +188,12 @@ Status DecodeImagePGX(const Span<const uint8_t> bytes,
};
ppf->frames.clear();
// Allocates the frame buffer.
- ppf->frames.emplace_back(header.xsize, header.ysize, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(header.xsize, header.ysize, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
const auto& frame = ppf->frames.back();
size_t pgx_remaining_size = bytes.data() + bytes.size() - pos;
if (pgx_remaining_size < frame.color.pixels_size) {
diff --git a/third_party/jpeg-xl/lib/extras/dec/pnm.cc b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
index 4c4618d41d..040c0bff81 100644
--- a/third_party/jpeg-xl/lib/extras/dec/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
@@ -9,6 +9,7 @@
#include <string.h>
#include <cmath>
+#include <cstdint>
#include <mutex>
#include "jxl/encode.h"
@@ -55,8 +56,10 @@ class Parser {
case 'f':
header->is_gray = true;
return ParseHeaderPFM(header, pos);
+
+ default:
+ return false;
}
- return false;
}
// Exposed for testing
@@ -160,11 +163,12 @@ class Parser {
Status MatchString(const char* keyword, bool skipws = true) {
const uint8_t* ppos = pos_;
- while (*keyword) {
+ const uint8_t* kw = reinterpret_cast<const uint8_t*>(keyword);
+ while (*kw) {
if (ppos >= end_) return JXL_FAILURE("PAM: unexpected end of input");
- if (*keyword != *ppos) return false;
+ if (*kw != *ppos) return false;
ppos++;
- keyword++;
+ kw++;
}
pos_ = ppos;
if (skipws) {
@@ -387,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 (header.ysize * row_size + dec.data_start_ < size) {
- return JXL_FAILURE("Invalid ppm");
+ if (size < header.ysize * row_size + dec.data_start_) {
+ return JXL_FAILURE("PNM file too small");
}
return dec;
}
@@ -495,10 +499,18 @@ Status DecodeImagePNM(const Span<const uint8_t> bytes,
};
const JxlPixelFormat ec_format{1, format.data_type, format.endianness, 0};
ppf->frames.clear();
- ppf->frames.emplace_back(header.xsize, header.ysize, format);
+ {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame frame,
+ PackedFrame::Create(header.xsize, header.ysize, format));
+ ppf->frames.emplace_back(std::move(frame));
+ }
auto* frame = &ppf->frames.back();
for (size_t i = 0; i < header.ec_types.size(); ++i) {
- frame->extra_channels.emplace_back(header.xsize, header.ysize, ec_format);
+ JXL_ASSIGN_OR_RETURN(
+ PackedImage ec,
+ PackedImage::Create(header.xsize, header.ysize, ec_format));
+ frame->extra_channels.emplace_back(std::move(ec));
}
size_t pnm_remaining_size = bytes.data() + bytes.size() - pos;
if (pnm_remaining_size < frame->color.pixels_size) {
@@ -533,6 +545,9 @@ 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;
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/apng.cc b/third_party/jpeg-xl/lib/extras/enc/apng.cc
index 413a9c8081..40aa876e84 100644
--- a/third_party/jpeg-xl/lib/extras/enc/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/apng.cc
@@ -86,7 +86,7 @@ class APNGEncoder : public Encoder {
std::vector<uint8_t>* bytes) const;
};
-static void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
+void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
std::vector<uint8_t>* bytes =
static_cast<std::vector<uint8_t>*>(png_get_io_ptr(png_ptr));
bytes->insert(bytes->end(), data, data + length);
@@ -137,7 +137,7 @@ class BlobsWriterPNG {
std::vector<std::string>* strings) {
// Encoding: base16 with newline after 72 chars.
const size_t base16_size =
- 2 * bytes.size() + DivCeil(bytes.size(), size_t(36)) + 1;
+ 2 * bytes.size() + DivCeil(bytes.size(), static_cast<size_t>(36)) + 1;
std::string base16;
base16.reserve(base16_size);
for (size_t i = 0; i < bytes.size(); ++i) {
@@ -155,7 +155,7 @@ class BlobsWriterPNG {
snprintf(header, sizeof(header), "\n%s\n%8" PRIuS, type.c_str(),
bytes.size());
- strings->push_back(std::string(key));
+ strings->emplace_back(key);
strings->push_back(std::string(header) + base16);
return true;
}
@@ -303,7 +303,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
out[i] = static_cast<uint8_t>(in[i] * mul + 0.5);
}
} else {
- memcpy(&out[0], in, out_size);
+ memcpy(out.data(), in, out_size);
}
} else if (format.data_type == JXL_TYPE_UINT16) {
if (ppf.info.bits_per_sample < 16 ||
@@ -317,20 +317,21 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
StoreBE16(static_cast<uint32_t>(val * mul + 0.5), p_out);
}
} else {
- memcpy(&out[0], in, out_size);
+ memcpy(out.data(), in, out_size);
}
}
png_structp png_ptr;
png_infop info_ptr;
- png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
+ nullptr);
if (!png_ptr) return JXL_FAILURE("Could not init png encoder");
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) return JXL_FAILURE("Could not init png info struct");
- png_set_write_fn(png_ptr, bytes, PngWrite, NULL);
+ png_set_write_fn(png_ptr, bytes, PngWrite, nullptr);
png_set_flush(png_ptr, 0);
int width = xsize;
@@ -344,11 +345,13 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
if (count == 0) {
- if (!ppf.icc.empty()) {
- png_set_benign_errors(png_ptr, 1);
- png_set_iCCP(png_ptr, info_ptr, "1", 0, ppf.icc.data(), ppf.icc.size());
- } else if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
+ if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
MaybeAddCICP(ppf.color_encoding, png_ptr, info_ptr);
+ if (!ppf.icc.empty()) {
+ png_set_benign_errors(png_ptr, 1);
+ png_set_iCCP(png_ptr, info_ptr, "1", 0, ppf.icc.data(),
+ ppf.icc.size());
+ }
MaybeAddCHRM(ppf.color_encoding, png_ptr, info_ptr);
MaybeAddGAMA(ppf.color_encoding, png_ptr, info_ptr);
}
@@ -404,7 +407,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
png_write_flush(png_ptr);
const size_t pos = bytes->size();
- png_write_image(png_ptr, &rows[0]);
+ png_write_image(png_ptr, rows.data());
png_write_flush(png_ptr);
if (count > 0) {
std::vector<uint8_t> fdata(4);
@@ -428,7 +431,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
count++;
if (count == ppf.frames.size() || !ppf.info.have_animation) {
- png_write_end(png_ptr, NULL);
+ png_write_end(png_ptr, nullptr);
}
png_destroy_write_struct(&png_ptr, &info_ptr);
diff --git a/third_party/jpeg-xl/lib/extras/enc/encode.cc b/third_party/jpeg-xl/lib/extras/enc/encode.cc
index 8c9a148b27..c5e22d8c7e 100644
--- a/third_party/jpeg-xl/lib/extras/enc/encode.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/encode.cc
@@ -54,7 +54,7 @@ Status Encoder::VerifyBitDepth(JxlDataType data_type, uint32_t bits_per_sample,
(bits_per_sample > 16 || exponent_bits > 5))) {
return JXL_FAILURE(
"Incompatible data_type %d and bit depth %u with exponent bits %u",
- (int)data_type, bits_per_sample, exponent_bits);
+ static_cast<int>(data_type), bits_per_sample, exponent_bits);
}
return true;
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/encode.h b/third_party/jpeg-xl/lib/extras/enc/encode.h
index da5f509838..2502d9976b 100644
--- a/third_party/jpeg-xl/lib/extras/enc/encode.h
+++ b/third_party/jpeg-xl/lib/extras/enc/encode.h
@@ -56,7 +56,7 @@ class Encoder {
// Any existing data in encoded_image is discarded.
virtual Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const = 0;
+ ThreadPool* pool) const = 0;
void SetOption(std::string name, std::string value) {
options_[std::move(name)] = std::move(value);
diff --git a/third_party/jpeg-xl/lib/extras/enc/exr.cc b/third_party/jpeg-xl/lib/extras/enc/exr.cc
index d4005c3097..5a4f7d768c 100644
--- a/third_party/jpeg-xl/lib/extras/enc/exr.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/exr.cc
@@ -84,7 +84,7 @@ Status EncodeImageEXR(const PackedImage& image, const JxlBasicInfo& info,
const size_t xsize = info.xsize;
const size_t ysize = info.ysize;
const bool has_alpha = info.alpha_bits > 0;
- const bool alpha_is_premultiplied = info.alpha_premultiplied;
+ const bool alpha_is_premultiplied = FROM_JXL_BOOL(info.alpha_premultiplied);
if (info.num_color_channels != 3 ||
c_enc.color_space != JXL_COLOR_SPACE_RGB ||
@@ -177,7 +177,7 @@ class EXREncoder : public Encoder {
return formats;
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
encoded_image->icc.clear();
encoded_image->bitstreams.clear();
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
index 7e1aa426df..aa10b584d0 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
@@ -34,6 +34,7 @@
#include "lib/jxl/color_encoding_internal.h"
#include "lib/jxl/enc_xyb.h"
#include "lib/jxl/image.h"
+#include "lib/jxl/simd_util.h"
namespace jxl {
namespace extras {
@@ -53,6 +54,10 @@ Status VerifyInput(const PackedPixelFile& ppf) {
if (ppf.frames.size() != 1) {
return JXL_FAILURE("JPEG input must have exactly one frame.");
}
+ if (info.num_color_channels != 1 && info.num_color_channels != 3) {
+ return JXL_FAILURE("Invalid number of color channels %d",
+ info.num_color_channels);
+ }
const PackedImage& image = ppf.frames[0].color;
JXL_RETURN_IF_ERROR(Encoder::VerifyImageSize(image, info));
if (image.format.data_type == JXL_TYPE_FLOAT16) {
@@ -71,7 +76,7 @@ Status VerifyInput(const PackedPixelFile& ppf) {
Status GetColorEncoding(const PackedPixelFile& ppf,
ColorEncoding* color_encoding) {
- if (!ppf.icc.empty()) {
+ if (ppf.primary_color_representation == PackedPixelFile::kIccIsPrimary) {
IccBytes icc = ppf.icc;
JXL_RETURN_IF_ERROR(
color_encoding->SetICC(std::move(icc), JxlGetDefaultCms()));
@@ -122,12 +127,12 @@ Status WriteAppData(j_compress_ptr cinfo,
return true;
}
-static constexpr int kICCMarker = 0xe2;
+constexpr int kICCMarker = 0xe2;
constexpr unsigned char kICCSignature[12] = {
0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00};
-static constexpr uint8_t kUnknownTf = 2;
-static constexpr unsigned char kCICPTagSignature[4] = {0x63, 0x69, 0x63, 0x70};
-static constexpr size_t kCICPTagSize = 12;
+constexpr uint8_t kUnknownTf = 2;
+constexpr unsigned char kCICPTagSignature[4] = {0x63, 0x69, 0x63, 0x70};
+constexpr size_t kCICPTagSize = 12;
bool FindCICPTag(const uint8_t* icc_data, size_t len, bool is_first_chunk,
size_t* cicp_offset, size_t* cicp_length, uint8_t* cicp_tag,
@@ -248,32 +253,48 @@ JpegliEndianness ConvertEndianness(JxlEndianness endianness) {
}
}
-void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t len,
- float* row_out) {
+void ToFloatRow(const uint8_t* row_in, JxlPixelFormat format, size_t xsize,
+ size_t c_out, float* row_out) {
bool is_little_endian =
(format.endianness == JXL_LITTLE_ENDIAN ||
(format.endianness == JXL_NATIVE_ENDIAN && IsLittleEndian()));
static constexpr double kMul8 = 1.0 / 255.0;
static constexpr double kMul16 = 1.0 / 65535.0;
+ const size_t c_in = format.num_channels;
if (format.data_type == JXL_TYPE_UINT8) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = row_in[x] * kMul8;
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = row_in[ix] * kMul8;
+ }
}
} else if (format.data_type == JXL_TYPE_UINT16 && is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadLE16(&row_in[2 * x]) * kMul16;
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadLE16(&row_in[2 * ix]) * kMul16;
+ }
}
} else if (format.data_type == JXL_TYPE_UINT16 && !is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadBE16(&row_in[2 * x]) * kMul16;
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadBE16(&row_in[2 * ix]) * kMul16;
+ }
}
} else if (format.data_type == JXL_TYPE_FLOAT && is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadLEFloat(&row_in[4 * x]);
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadLEFloat(&row_in[4 * ix]);
+ }
}
} else if (format.data_type == JXL_TYPE_FLOAT && !is_little_endian) {
- for (size_t x = 0; x < len; ++x) {
- row_out[x] = LoadBEFloat(&row_in[4 * x]);
+ for (size_t x = 0; x < xsize; ++x) {
+ for (size_t c = 0; c < c_out; ++c) {
+ const size_t ix = c_in * x + c;
+ row_out[c_out * x + c] = LoadBEFloat(&row_in[4 * ix]);
+ }
}
}
}
@@ -352,9 +373,6 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
ColorSpaceTransform c_transform(*JxlGetDefaultCms());
ColorEncoding xyb_encoding;
if (jpeg_settings.xyb) {
- if (ppf.info.num_color_channels != 3) {
- return JXL_FAILURE("Only RGB input is supported in XYB mode.");
- }
if (HasICCProfile(jpeg_settings.app_data)) {
return JXL_FAILURE("APP data ICC profile is not supported in XYB mode.");
}
@@ -374,11 +392,11 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
unsigned char* output_buffer = nullptr;
unsigned long output_size = 0;
std::vector<uint8_t> row_bytes;
- size_t rowlen = RoundUpTo(ppf.info.xsize, VectorSize());
+ size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize());
hwy::AlignedFreeUniquePtr<float[]> xyb_tmp =
hwy::AllocateAligned<float>(6 * rowlen);
hwy::AlignedFreeUniquePtr<float[]> premul_absorb =
- hwy::AllocateAligned<float>(VectorSize() * 12);
+ hwy::AllocateAligned<float>(MaxVectorSize() * 12);
ComputePremulAbsorb(255.0f, premul_absorb.get());
jpeg_compress_struct cinfo;
@@ -401,6 +419,8 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
cinfo.input_components == 1 ? JCS_GRAYSCALE : JCS_RGB;
if (jpeg_settings.xyb) {
jpegli_set_xyb_mode(&cinfo);
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
} else if (jpeg_settings.use_std_quant_tables) {
jpegli_use_standard_quant_tables(&cinfo);
}
@@ -436,7 +456,7 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
}
}
jpegli_enable_adaptive_quantization(
- &cinfo, jpeg_settings.use_adaptive_quantization);
+ &cinfo, TO_JXL_BOOL(jpeg_settings.use_adaptive_quantization));
if (jpeg_settings.psnr_target > 0.0) {
jpegli_set_psnr(&cinfo, jpeg_settings.psnr_target,
jpeg_settings.search_tolerance,
@@ -448,11 +468,11 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
jpegli_set_distance(&cinfo, jpeg_settings.distance, TRUE);
}
jpegli_set_progressive_level(&cinfo, jpeg_settings.progressive_level);
- cinfo.optimize_coding = jpeg_settings.optimize_coding;
+ cinfo.optimize_coding = TO_JXL_BOOL(jpeg_settings.optimize_coding);
if (!jpeg_settings.app_data.empty()) {
// Make sure jpegli_start_compress() does not write any APP markers.
- cinfo.write_JFIF_header = false;
- cinfo.write_Adobe_marker = false;
+ cinfo.write_JFIF_header = JXL_FALSE;
+ cinfo.write_Adobe_marker = JXL_FALSE;
}
const PackedImage& image = ppf.frames[0].color;
if (jpeg_settings.xyb) {
@@ -476,10 +496,10 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
float* dst_buf = c_transform.BufDst(0);
for (size_t y = 0; y < image.ysize; ++y) {
// convert to float
- ToFloatRow(&pixels[y * image.stride], image.format, 3 * image.xsize,
- src_buf);
+ ToFloatRow(&pixels[y * image.stride], image.format, image.xsize,
+ info.num_color_channels, src_buf);
// convert to linear srgb
- if (!c_transform.Run(0, src_buf, dst_buf)) {
+ if (!c_transform.Run(0, src_buf, dst_buf, image.xsize)) {
return false;
}
// deinterleave channels
@@ -508,9 +528,9 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
}
} else {
row_bytes.resize(image.stride);
- if (cinfo.num_components == (int)image.format.num_channels) {
+ if (cinfo.num_components == static_cast<int>(image.format.num_channels)) {
for (size_t y = 0; y < info.ysize; ++y) {
- memcpy(&row_bytes[0], pixels + y * image.stride, image.stride);
+ memcpy(row_bytes.data(), pixels + y * image.stride, image.stride);
JSAMPROW row[] = {row_bytes.data()};
jpegli_write_scanlines(&cinfo, row, 1);
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpg.cc b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
index c34dc6c13f..de0228fc0d 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
@@ -23,6 +23,7 @@
#include <vector>
#include "lib/extras/exif.h"
+#include "lib/jxl/base/common.h"
#include "lib/jxl/base/status.h"
#include "lib/jxl/sanitizers.h"
#if JPEGXL_ENABLE_SJPEG
@@ -50,23 +51,21 @@ enum class JpegEncoder {
kSJpeg,
};
-#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
-
// Popular jpeg scan scripts
// The fields of the individual scans are:
// comps_in_scan, component_index[], Ss, Se, Ah, Al
-static constexpr jpeg_scan_info kScanScript1[] = {
+constexpr auto kScanScript1 = to_array<jpeg_scan_info>({
{1, {0}, 0, 0, 0, 0}, //
{1, {1}, 0, 0, 0, 0}, //
{1, {2}, 0, 0, 0, 0}, //
{1, {0}, 1, 8, 0, 0}, //
{1, {0}, 9, 63, 0, 0}, //
{1, {1}, 1, 63, 0, 0}, //
- {1, {2}, 1, 63, 0, 0}, //
-};
-static constexpr size_t kNumScans1 = ARRAY_SIZE(kScanScript1);
+ {1, {2}, 1, 63, 0, 0} //
+});
+constexpr size_t kNumScans1 = kScanScript1.size();
-static constexpr jpeg_scan_info kScanScript2[] = {
+constexpr auto kScanScript2 = to_array<jpeg_scan_info>({
{1, {0}, 0, 0, 0, 0}, //
{1, {1}, 0, 0, 0, 0}, //
{1, {2}, 0, 0, 0, 0}, //
@@ -74,11 +73,11 @@ static constexpr jpeg_scan_info kScanScript2[] = {
{1, {0}, 3, 63, 0, 1}, //
{1, {0}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 0, 0}, //
- {1, {2}, 1, 63, 0, 0}, //
-};
-static constexpr size_t kNumScans2 = ARRAY_SIZE(kScanScript2);
+ {1, {2}, 1, 63, 0, 0} //
+});
+constexpr size_t kNumScans2 = kScanScript2.size();
-static constexpr jpeg_scan_info kScanScript3[] = {
+constexpr auto kScanScript3 = to_array<jpeg_scan_info>({
{1, {0}, 0, 0, 0, 0}, //
{1, {1}, 0, 0, 0, 0}, //
{1, {2}, 0, 0, 0, 0}, //
@@ -86,11 +85,11 @@ static constexpr jpeg_scan_info kScanScript3[] = {
{1, {0}, 1, 63, 2, 1}, //
{1, {0}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 0, 0}, //
- {1, {2}, 1, 63, 0, 0}, //
-};
-static constexpr size_t kNumScans3 = ARRAY_SIZE(kScanScript3);
+ {1, {2}, 1, 63, 0, 0} //
+});
+constexpr size_t kNumScans3 = kScanScript3.size();
-static constexpr jpeg_scan_info kScanScript4[] = {
+constexpr auto kScanScript4 = to_array<jpeg_scan_info>({
{3, {0, 1, 2}, 0, 0, 0, 1}, //
{1, {0}, 1, 5, 0, 2}, //
{1, {2}, 1, 63, 0, 1}, //
@@ -100,11 +99,11 @@ static constexpr jpeg_scan_info kScanScript4[] = {
{3, {0, 1, 2}, 0, 0, 1, 0}, //
{1, {2}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 1, 0}, //
- {1, {0}, 1, 63, 1, 0}, //
-};
-static constexpr size_t kNumScans4 = ARRAY_SIZE(kScanScript4);
+ {1, {0}, 1, 63, 1, 0} //
+});
+constexpr size_t kNumScans4 = kScanScript4.size();
-static constexpr jpeg_scan_info kScanScript5[] = {
+constexpr auto kScanScript5 = to_array<jpeg_scan_info>({
{3, {0, 1, 2}, 0, 0, 0, 1}, //
{1, {0}, 1, 5, 0, 2}, //
{1, {1}, 1, 5, 0, 2}, //
@@ -118,12 +117,12 @@ static constexpr jpeg_scan_info kScanScript5[] = {
{3, {0, 1, 2}, 0, 0, 1, 0}, //
{1, {0}, 1, 63, 1, 0}, //
{1, {1}, 1, 63, 1, 0}, //
- {1, {2}, 1, 63, 1, 0}, //
-};
-static constexpr size_t kNumScans5 = ARRAY_SIZE(kScanScript5);
+ {1, {2}, 1, 63, 1, 0} //
+});
+constexpr size_t kNumScans5 = kScanScript5.size();
// default progressive mode of jpegli
-static constexpr jpeg_scan_info kScanScript6[] = {
+constexpr auto kScanScript6 = to_array<jpeg_scan_info>({
{3, {0, 1, 2}, 0, 0, 0, 0}, //
{1, {0}, 1, 2, 0, 0}, //
{1, {1}, 1, 2, 0, 0}, //
@@ -137,8 +136,8 @@ static constexpr jpeg_scan_info kScanScript6[] = {
{1, {0}, 3, 63, 1, 0}, //
{1, {1}, 3, 63, 1, 0}, //
{1, {2}, 3, 63, 1, 0}, //
-};
-static constexpr size_t kNumScans6 = ARRAY_SIZE(kScanScript6);
+});
+constexpr size_t kNumScans6 = kScanScript6.size();
// Adapt RGB scan info to grayscale jpegs.
void FilterScanComponents(const jpeg_compress_struct* cinfo,
@@ -163,12 +162,12 @@ Status SetJpegProgression(int progressive_id,
jpeg_simple_progression(cinfo);
return true;
}
- constexpr const jpeg_scan_info* kScanScripts[] = {kScanScript1, kScanScript2,
- kScanScript3, kScanScript4,
- kScanScript5, kScanScript6};
- constexpr size_t kNumScans[] = {kNumScans1, kNumScans2, kNumScans3,
- kNumScans4, kNumScans5, kNumScans6};
- if (progressive_id > static_cast<int>(ARRAY_SIZE(kNumScans))) {
+ const jpeg_scan_info* kScanScripts[] = {
+ kScanScript1.data(), kScanScript2.data(), kScanScript3.data(),
+ kScanScript4.data(), kScanScript5.data(), kScanScript6.data()};
+ constexpr auto kNumScans = to_array<size_t>(
+ {kNumScans1, kNumScans2, kNumScans3, kNumScans4, kNumScans5, kNumScans6});
+ if (progressive_id > static_cast<int>(kNumScans.size())) {
return JXL_FAILURE("Unknown jpeg scan script id %d", progressive_id);
}
const jpeg_scan_info* scan_script = kScanScripts[progressive_id - 1];
@@ -178,7 +177,7 @@ Status SetJpegProgression(int progressive_id,
jpeg_scan_info scan_info = scan_script[i];
FilterScanComponents(cinfo, &scan_info);
if (scan_info.comps_in_scan > 0) {
- scan_infos->emplace_back(std::move(scan_info));
+ scan_infos->emplace_back(scan_info);
}
}
cinfo->scan_info = scan_infos->data();
@@ -217,8 +216,8 @@ void WriteExif(jpeg_compress_struct* const cinfo,
for (const unsigned char c : kExifSignature) {
jpeg_write_m_byte(cinfo, c);
}
- for (size_t i = 0; i < exif.size(); ++i) {
- jpeg_write_m_byte(cinfo, exif[i]);
+ for (uint8_t c : exif) {
+ jpeg_write_m_byte(cinfo, c);
}
}
@@ -284,7 +283,7 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
cinfo.input_components = info.num_color_channels;
cinfo.in_color_space = info.num_color_channels == 1 ? JCS_GRAYSCALE : JCS_RGB;
jpeg_set_defaults(&cinfo);
- cinfo.optimize_coding = params.optimize_coding;
+ cinfo.optimize_coding = static_cast<boolean>(params.optimize_coding);
if (cinfo.input_components == 3) {
JXL_RETURN_IF_ERROR(
SetChromaSubsampling(params.chroma_subsampling, &cinfo));
@@ -310,10 +309,10 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
std::vector<uint8_t> row_bytes(image.stride);
const uint8_t* pixels = reinterpret_cast<const uint8_t*>(image.pixels());
- if (cinfo.num_components == (int)image.format.num_channels &&
+ if (cinfo.num_components == static_cast<int>(image.format.num_channels) &&
image.format.data_type == JXL_TYPE_UINT8) {
for (size_t y = 0; y < info.ysize; ++y) {
- memcpy(&row_bytes[0], pixels + y * image.stride, image.stride);
+ memcpy(row_bytes.data(), pixels + y * image.stride, image.stride);
JSAMPROW row[] = {row_bytes.data()};
jpeg_write_scanlines(&cinfo, row, 1);
}
@@ -401,7 +400,7 @@ struct MySearchHook : public sjpeg::SearchHook {
}
bool Update(float result) override {
value = result;
- if (fabs(value - target) < tolerance * target) {
+ if (std::fabs(value - target) < tolerance * target) {
return true;
}
if (value > target) {
@@ -420,9 +419,9 @@ struct MySearchHook : public sjpeg::SearchHook {
} else {
q = (qmin + qmax) / 2.;
}
- return (pass > 0 && fabs(q - last_q) < q_precision);
+ return (pass > 0 && std::fabs(q - last_q) < q_precision);
}
- ~MySearchHook() override {}
+ ~MySearchHook() override = default;
};
#endif
@@ -539,7 +538,7 @@ class JPEGEncoder : public Encoder {
return formats;
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
JpegEncoder jpeg_encoder = JpegEncoder::kLibJpeg;
JpegParams params;
diff --git a/third_party/jpeg-xl/lib/extras/enc/jxl.cc b/third_party/jpeg-xl/lib/extras/enc/jxl.cc
index 00adbb7dda..d563f298e6 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jxl.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jxl.cc
@@ -7,6 +7,7 @@
#include <jxl/encode.h>
#include <jxl/encode_cxx.h>
+#include <jxl/types.h>
#include "lib/jxl/base/exif.h"
@@ -132,7 +133,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
- auto settings = JxlEncoderFrameSettingsCreate(enc, nullptr);
+ auto* settings = JxlEncoderFrameSettingsCreate(enc, nullptr);
size_t option_idx = 0;
if (!SetFrameOptions(params.options, 0, &option_idx, settings)) {
return false;
@@ -150,10 +151,11 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
JxlEncoderCollectStats(settings, params.stats);
}
+ bool has_jpeg_bytes = (jpeg_bytes != nullptr);
bool use_boxes = !ppf.metadata.exif.empty() || !ppf.metadata.xmp.empty() ||
!ppf.metadata.jumbf.empty() || !ppf.metadata.iptc.empty();
bool use_container = params.use_container || use_boxes ||
- (jpeg_bytes && params.jpeg_store_metadata);
+ (has_jpeg_bytes && params.jpeg_store_metadata);
if (JXL_ENC_SUCCESS !=
JxlEncoderUseContainer(enc, static_cast<int>(use_container))) {
@@ -161,12 +163,22 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
- if (jpeg_bytes) {
+ if (has_jpeg_bytes) {
if (params.jpeg_store_metadata &&
JXL_ENC_SUCCESS != JxlEncoderStoreJPEGMetadata(enc, JXL_TRUE)) {
fprintf(stderr, "Storing JPEG metadata failed.\n");
return false;
}
+ if (params.jpeg_store_metadata && params.jpeg_strip_exif) {
+ fprintf(stderr,
+ "Cannot store metadata and strip exif at the same time.\n");
+ return false;
+ }
+ if (params.jpeg_store_metadata && params.jpeg_strip_xmp) {
+ fprintf(stderr,
+ "Cannot store metadata and strip xmp at the same time.\n");
+ return false;
+ }
if (!params.jpeg_store_metadata && params.jpeg_strip_exif) {
JxlEncoderFrameSettingsSetOption(settings,
JXL_ENC_FRAME_SETTING_JPEG_KEEP_EXIF, 0);
@@ -210,8 +222,8 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
basic_info.num_extra_channels =
std::max<uint32_t>(num_alpha_channels, ppf.info.num_extra_channels);
basic_info.num_color_channels = ppf.info.num_color_channels;
- const bool lossless = params.distance == 0;
- basic_info.uses_original_profile = lossless;
+ const bool lossless = (params.distance == 0);
+ 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 =
@@ -233,7 +245,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
return false;
}
if (JXL_ENC_SUCCESS !=
- JxlEncoderSetFrameBitDepth(settings, &params.input_bitdepth)) {
+ JxlEncoderSetFrameBitDepth(settings, &ppf.input_bitdepth)) {
fprintf(stderr, "JxlEncoderSetFrameBitDepth() failed.\n");
return false;
}
@@ -248,7 +260,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
fprintf(stderr, "JxlEncoderSetFrameLossless() failed.\n");
return false;
}
- if (!ppf.icc.empty()) {
+ if (ppf.primary_color_representation == PackedPixelFile::kIccIsPrimary) {
if (JXL_ENC_SUCCESS !=
JxlEncoderSetICCProfile(enc, ppf.icc.data(), ppf.icc.size())) {
fprintf(stderr, "JxlEncoderSetICCProfile() failed.\n");
@@ -284,14 +296,15 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
{"jumb", ppf.metadata.jumbf},
{"xml ", ppf.metadata.iptc},
};
- for (size_t i = 0; i < sizeof boxes / sizeof *boxes; ++i) {
- const BoxInfo& box = boxes[i];
- if (!box.bytes.empty() &&
- JXL_ENC_SUCCESS != JxlEncoderAddBox(enc, box.type, box.bytes.data(),
- box.bytes.size(),
- params.compress_boxes)) {
- fprintf(stderr, "JxlEncoderAddBox() failed (%s).\n", box.type);
- return false;
+ for (auto box : boxes) {
+ if (!box.bytes.empty()) {
+ if (JXL_ENC_SUCCESS !=
+ JxlEncoderAddBox(enc, box.type, box.bytes.data(),
+ box.bytes.size(),
+ TO_JXL_BOOL(params.compress_boxes))) {
+ fprintf(stderr, "JxlEncoderAddBox() failed (%s).\n", box.type);
+ return false;
+ }
}
}
JxlEncoderCloseBoxes(enc);
@@ -336,7 +349,7 @@ bool EncodeImageJXL(const JXLCompressParams& params, const PackedPixelFile& ppf,
}
const bool last_frame = fi + 1 == ppf.chunked_frames.size();
if (JXL_ENC_SUCCESS !=
- JxlEncoderAddChunkedFrame(settings, last_frame,
+ JxlEncoderAddChunkedFrame(settings, TO_JXL_BOOL(last_frame),
chunked_frame.GetInputSource())) {
fprintf(stderr, "JxlEncoderAddChunkedFrame() failed.\n");
return false;
diff --git a/third_party/jpeg-xl/lib/extras/enc/jxl.h b/third_party/jpeg-xl/lib/extras/enc/jxl.h
index b8ca5bda2f..2b3793c0c4 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jxl.h
+++ b/third_party/jpeg-xl/lib/extras/enc/jxl.h
@@ -38,7 +38,7 @@ struct JXLCompressParams {
std::vector<JXLOption> options;
// Target butteraugli distance, 0.0 means lossless.
float distance = 1.0f;
- float alpha_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.
@@ -57,8 +57,6 @@ struct JXLCompressParams {
size_t override_bitdepth = 0;
int32_t codestream_level = -1;
int32_t premultiply = -1;
- // Override input buffer interpretation.
- JxlBitDepth input_bitdepth = {JXL_BIT_DEPTH_FROM_PIXEL_FORMAT, 0, 0};
// If runner_opaque is set, the decoder uses this parallel runner.
JxlParallelRunner runner = JxlThreadParallelRunner;
void* runner_opaque = nullptr;
@@ -69,10 +67,10 @@ struct JXLCompressParams {
bool allow_expert_options = false;
void AddOption(JxlEncoderFrameSettingId id, int64_t val) {
- options.emplace_back(JXLOption(id, val, 0));
+ options.emplace_back(id, val, 0);
}
void AddFloatOption(JxlEncoderFrameSettingId id, float val) {
- options.emplace_back(JXLOption(id, val, 0));
+ options.emplace_back(id, val, 0);
}
bool HasOutputProcessor() const {
return (output_processor.get_buffer != nullptr &&
diff --git a/third_party/jpeg-xl/lib/extras/enc/npy.cc b/third_party/jpeg-xl/lib/extras/enc/npy.cc
index ae8cf13cc4..8d9954ef31 100644
--- a/third_party/jpeg-xl/lib/extras/enc/npy.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/npy.cc
@@ -7,11 +7,13 @@
#include <jxl/types.h>
+#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "lib/extras/packed_image.h"
+#include "lib/jxl/base/common.h"
namespace jxl {
namespace extras {
@@ -52,14 +54,17 @@ class JSONDict : public JSONField {
static_assert(std::is_convertible<T*, JSONField*>::value,
"T must be a JSONField");
T* ret = new T();
- values_.emplace_back(
- key, std::unique_ptr<JSONField>(static_cast<JSONField*>(ret)));
+ JSONField* field = static_cast<JSONField*>(ret);
+ auto handle = std::unique_ptr<JSONField>(field);
+ values_.emplace_back(key, std::move(handle));
return ret;
}
template <typename T>
void Add(const std::string& key, const T& value) {
- values_.emplace_back(key, std::unique_ptr<JSONField>(new JSONValue(value)));
+ JSONField* field = static_cast<JSONField*>(new JSONValue(value));
+ auto handle = std::unique_ptr<JSONField>(field);
+ values_.emplace_back(key, std::move(handle));
}
void Write(std::ostream& o, uint32_t indent) const override {
@@ -71,11 +76,11 @@ class JSONDict : public JSONField {
o << ",";
}
is_first = false;
- o << std::endl << indent_str << " \"" << key_value.first << "\": ";
+ o << "\n" << indent_str << " \"" << key_value.first << "\": ";
key_value.second->Write(o, indent + 2);
}
if (!values_.empty()) {
- o << std::endl << indent_str;
+ o << "\n" << indent_str;
}
o << "}";
}
@@ -112,11 +117,11 @@ class JSONArray : public JSONField {
o << ",";
}
is_first = false;
- o << std::endl << indent_str << " ";
+ o << "\n" << indent_str << " ";
value->Write(o, indent + 2);
}
if (!values_.empty()) {
- o << std::endl << indent_str;
+ o << "\n" << indent_str;
}
o << "]";
}
@@ -160,13 +165,13 @@ void GenerateMetadata(const PackedPixelFile& ppf, std::vector<uint8_t>* out) {
}
{
- auto ectype = meta.AddEmpty<JSONArray>("extra_channel_type");
- auto bps = meta.AddEmpty<JSONArray>("bits_per_sample");
- auto ebps = meta.AddEmpty<JSONArray>("exp_bits_per_sample");
+ auto* ectype = meta.AddEmpty<JSONArray>("extra_channel_type");
+ auto* bps = meta.AddEmpty<JSONArray>("bits_per_sample");
+ auto* ebps = meta.AddEmpty<JSONArray>("exp_bits_per_sample");
bps->Add(ppf.info.bits_per_sample);
ebps->Add(ppf.info.exponent_bits_per_sample);
- for (size_t i = 0; i < ppf.extra_channels_info.size(); i++) {
- switch (ppf.extra_channels_info[i].ec_info.type) {
+ for (const auto& eci : ppf.extra_channels_info) {
+ switch (eci.ec_info.type) {
case JXL_CHANNEL_ALPHA: {
ectype->Add(std::string("Alpha"));
break;
@@ -200,8 +205,8 @@ void GenerateMetadata(const PackedPixelFile& ppf, std::vector<uint8_t>* out) {
break;
}
}
- bps->Add(ppf.extra_channels_info[i].ec_info.bits_per_sample);
- ebps->Add(ppf.extra_channels_info[i].ec_info.exponent_bits_per_sample);
+ bps->Add(eci.ec_info.bits_per_sample);
+ ebps->Add(eci.ec_info.exponent_bits_per_sample);
}
}
@@ -282,7 +287,7 @@ bool WriteNPYArray(const PackedPixelFile& ppf, std::vector<uint8_t>* out) {
class NumPyEncoder : public Encoder {
public:
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
GenerateMetadata(ppf, &encoded_image->metadata);
encoded_image->bitstreams.emplace_back();
diff --git a/third_party/jpeg-xl/lib/extras/enc/pgx.cc b/third_party/jpeg-xl/lib/extras/enc/pgx.cc
index d4809e38b6..eb8eab4271 100644
--- a/third_party/jpeg-xl/lib/extras/enc/pgx.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/pgx.cc
@@ -60,7 +60,7 @@ Status EncodeImagePGX(const PackedFrame& frame, const JxlBasicInfo& info,
std::vector<uint8_t> pixels(num_samples * bytes_per_sample);
if (format.data_type == JXL_TYPE_UINT8) {
- memcpy(&pixels[0], in, num_samples * bytes_per_sample);
+ memcpy(pixels.data(), in, num_samples * bytes_per_sample);
} else if (format.data_type == JXL_TYPE_UINT16) {
if (format.endianness != JXL_BIG_ENDIAN) {
const uint8_t* p_in = in;
@@ -69,7 +69,7 @@ Status EncodeImagePGX(const PackedFrame& frame, const JxlBasicInfo& info,
StoreBE16(LoadLE16(p_in), p_out);
}
} else {
- memcpy(&pixels[0], in, num_samples * bytes_per_sample);
+ memcpy(pixels.data(), in, num_samples * bytes_per_sample);
}
} else {
return JXL_FAILURE("Unsupported pixel data type");
diff --git a/third_party/jpeg-xl/lib/extras/enc/pnm.cc b/third_party/jpeg-xl/lib/extras/enc/pnm.cc
index 4183900198..966611cfca 100644
--- a/third_party/jpeg-xl/lib/extras/enc/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/pnm.cc
@@ -31,7 +31,7 @@ constexpr size_t kMaxHeaderSize = 200;
class BasePNMEncoder : public Encoder {
public:
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
- ThreadPool* pool = nullptr) const override {
+ ThreadPool* pool) const override {
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
if (!ppf.metadata.exif.empty() || !ppf.metadata.iptc.empty() ||
!ppf.metadata.jumbf.empty() || !ppf.metadata.xmp.empty()) {
diff --git a/third_party/jpeg-xl/lib/extras/jpegli_test.cc b/third_party/jpeg-xl/lib/extras/jpegli_test.cc
index 66c18617a6..3049049a64 100644
--- a/third_party/jpeg-xl/lib/extras/jpegli_test.cc
+++ b/third_party/jpeg-xl/lib/extras/jpegli_test.cc
@@ -85,7 +85,7 @@ Status EncodeWithLibjpeg(const PackedPixelFile& ppf, int quality,
std::unique_ptr<Encoder> encoder = GetJPEGEncoder();
encoder->SetOption("q", std::to_string(quality));
EncodedImage encoded;
- JXL_RETURN_IF_ERROR(encoder->Encode(ppf, &encoded));
+ JXL_RETURN_IF_ERROR(encoder->Encode(ppf, &encoded, nullptr));
JXL_RETURN_IF_ERROR(!encoded.bitstreams.empty());
*compressed = std::move(encoded.bitstreams[0]);
return true;
@@ -156,8 +156,8 @@ TEST(JpegliTest, JpegliXYBEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.45f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.45f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
}
TEST(JpegliTest, JpegliDecodeTestLargeSmoothArea) {
@@ -205,8 +205,8 @@ TEST(JpegliTest, JpegliYUVEncodeTest) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.7f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.32f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.7f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.32f);
}
TEST(JpegliTest, JpegliYUVChromaSubsamplingEncodeTest) {
@@ -247,8 +247,8 @@ TEST(JpegliTest, JpegliYUVEncodeTestNoAq) {
PackedPixelFile ppf_out;
ASSERT_TRUE(DecodeWithLibjpeg(compressed, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(1.85f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.25f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 1.85f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.25f);
}
TEST(JpegliTest, JpegliHDRRoundtripTest) {
@@ -267,8 +267,8 @@ TEST(JpegliTest, JpegliHDRRoundtripTest) {
JpegDecompressParams dparams;
dparams.output_data_type = JXL_TYPE_UINT16;
ASSERT_TRUE(DecodeJpeg(compressed, dparams, nullptr, &ppf_out));
- EXPECT_THAT(BitsPerPixel(ppf_in, compressed), IsSlightlyBelow(2.95f));
- EXPECT_THAT(ButteraugliDistance(ppf_in, ppf_out), IsSlightlyBelow(1.05f));
+ EXPECT_SLIGHTLY_BELOW(BitsPerPixel(ppf_in, compressed), 2.95f);
+ EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(ppf_in, ppf_out), 1.05f);
}
TEST(JpegliTest, JpegliSetAppData) {
diff --git a/third_party/jpeg-xl/lib/extras/mmap.cc b/third_party/jpeg-xl/lib/extras/mmap.cc
index 7852831ebd..9f5bba97ed 100644
--- a/third_party/jpeg-xl/lib/extras/mmap.cc
+++ b/third_party/jpeg-xl/lib/extras/mmap.cc
@@ -10,7 +10,8 @@
#include "lib/jxl/base/common.h"
-#if __unix__
+#if defined(__unix__) || defined(__unix) || \
+ defined(__APPLE__) && defined(__MACH__)
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
@@ -54,7 +55,7 @@ struct MemoryMappedFileImpl {
} // namespace jxl
-#elif __WIN32__
+#elif defined(_WIN32)
#include <string.h>
#include <windows.h>
@@ -97,6 +98,8 @@ struct MemoryMappedFileImpl {
return f;
}
+ ~MemoryMappedFileImpl() { UnmapViewOfFile(ptr); }
+
const uint8_t* data() const { return reinterpret_cast<const uint8_t*>(ptr); }
size_t size() const { return fsize.QuadPart; }
diff --git a/third_party/jpeg-xl/lib/extras/packed_image.h b/third_party/jpeg-xl/lib/extras/packed_image.h
index edd5f1be75..a66ddfbd70 100644
--- a/third_party/jpeg-xl/lib/extras/packed_image.h
+++ b/third_party/jpeg-xl/lib/extras/packed_image.h
@@ -37,11 +37,18 @@ namespace extras {
// Class representing an interleaved image with a bunch of channels.
class PackedImage {
public:
- PackedImage(size_t xsize, size_t ysize, const JxlPixelFormat& format)
- : PackedImage(xsize, ysize, format, CalcStride(format, xsize)) {}
+ static StatusOr<PackedImage> Create(size_t xsize, size_t ysize,
+ const JxlPixelFormat& format) {
+ PackedImage image(xsize, ysize, format, CalcStride(format, xsize));
+ if (!image.pixels()) {
+ // TODO(szabadka): use specialized OOM error code
+ return JXL_FAILURE("Failed to allocate memory for image");
+ }
+ return image;
+ }
PackedImage Copy() const {
- PackedImage copy(xsize, ysize, format);
+ PackedImage copy(xsize, ysize, format, CalcStride(format, xsize));
memcpy(reinterpret_cast<uint8_t*>(copy.pixels()),
reinterpret_cast<const uint8_t*>(pixels()), pixels_size);
return copy;
@@ -108,7 +115,7 @@ class PackedImage {
}
}
- void SetPixelValue(size_t y, size_t x, size_t c, float val) {
+ void SetPixelValue(size_t y, size_t x, size_t c, float val) const {
uint8_t* data = pixels(y, x, c);
switch (format.data_type) {
case JXL_TYPE_UINT8:
@@ -169,17 +176,25 @@ class PackedImage {
// as all other frames in the same image.
class PackedFrame {
public:
- template <typename... Args>
- explicit PackedFrame(Args&&... args) : color(std::forward<Args>(args)...) {}
+ explicit PackedFrame(PackedImage&& image) : color(std::move(image)) {}
+
+ 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;
+ }
- PackedFrame Copy() const {
- PackedFrame copy(color.xsize, color.ysize, color.format);
+ StatusOr<PackedFrame> Copy() const {
+ JXL_ASSIGN_OR_RETURN(
+ PackedFrame copy,
+ PackedFrame::Create(color.xsize, color.ysize, color.format));
copy.frame_info = frame_info;
copy.name = name;
copy.color = color.Copy();
- for (size_t i = 0; i < extra_channels.size(); ++i) {
- PackedImage ec = extra_channels[i].Copy();
- copy.extra_channels.emplace_back(std::move(ec));
+ for (const auto& ec : extra_channels) {
+ copy.extra_channels.emplace_back(ec.Copy());
}
return copy;
}
@@ -244,12 +259,26 @@ class PackedPixelFile {
std::vector<PackedExtraChannel> extra_channels_info;
// Color information of the decoded pixels.
- // If the icc is empty, the JxlColorEncoding should be used instead.
- std::vector<uint8_t> icc;
+ // `primary_color_representation` indicates whether `color_encoding` or `icc`
+ // is the “authoritative” encoding of the colorspace, as opposed to a fallback
+ // encoding. For example, if `color_encoding` is the primary one, as would
+ // occur when decoding a jxl file with such a representation, then `enc/jxl`
+ // will use it and ignore the ICC profile, whereas `enc/png` will include the
+ // ICC profile for compatibility.
+ // If `icc` is the primary representation, `enc/jxl` will preserve it when
+ // compressing losslessly, but *may* encode it as a color_encoding when
+ // compressing lossily.
+ enum {
+ kColorEncodingIsPrimary,
+ kIccIsPrimary
+ } primary_color_representation = kColorEncodingIsPrimary;
JxlColorEncoding color_encoding = {};
+ std::vector<uint8_t> icc;
// 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;
diff --git a/third_party/jpeg-xl/lib/extras/packed_image_convert.cc b/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
index 56f3b044a4..2ad001bf09 100644
--- a/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
+++ b/third_party/jpeg-xl/lib/extras/packed_image_convert.cc
@@ -22,15 +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) {
JXL_ASSERT(frame.color.pixels() != nullptr);
- const bool float_in = frame.color.format.data_type == JXL_TYPE_FLOAT16 ||
- frame.color.format.data_type == JXL_TYPE_FLOAT;
size_t frame_bits_per_sample =
- float_in ? PackedImage::BitsPerChannel(frame.color.format.data_type)
- : info.bits_per_sample;
+ input_bitdepth.type == JXL_BIT_DEPTH_FROM_PIXEL_FORMAT
+ ? 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.
@@ -64,7 +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];
- bundle->extra_channels()[i] = ImageF(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]));
@@ -97,23 +98,23 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
ppf.info.exponent_bits_per_sample == 0 && ppf.info.bits_per_sample <= 12;
io->metadata.m.SetAlphaBits(ppf.info.alpha_bits,
- ppf.info.alpha_premultiplied);
+ FROM_JXL_BOOL(ppf.info.alpha_premultiplied));
ExtraChannelInfo* alpha = io->metadata.m.Find(ExtraChannel::kAlpha);
if (alpha) alpha->bit_depth = io->metadata.m.bit_depth;
- io->metadata.m.xyb_encoded = !ppf.info.uses_original_profile;
+ io->metadata.m.xyb_encoded = !FROM_JXL_BOOL(ppf.info.uses_original_profile);
JXL_ASSERT(ppf.info.orientation > 0 && ppf.info.orientation <= 8);
io->metadata.m.orientation = ppf.info.orientation;
// Convert animation metadata
JXL_ASSERT(ppf.frames.size() == 1 || ppf.info.have_animation);
- io->metadata.m.have_animation = ppf.info.have_animation;
+ io->metadata.m.have_animation = FROM_JXL_BOOL(ppf.info.have_animation);
io->metadata.m.animation.tps_numerator = ppf.info.animation.tps_numerator;
io->metadata.m.animation.tps_denominator = ppf.info.animation.tps_denominator;
io->metadata.m.animation.num_loops = ppf.info.animation.num_loops;
// Convert the color encoding.
- if (!ppf.icc.empty()) {
+ if (ppf.primary_color_representation == PackedPixelFile::kIccIsPrimary) {
IccBytes icc = ppf.icc;
if (!io->metadata.m.color_encoding.SetICC(std::move(icc),
JxlGetDefaultCms())) {
@@ -170,15 +171,16 @@ Status ConvertPackedPixelFileToCodecInOut(const PackedPixelFile& ppf,
JXL_RETURN_IF_ERROR(
io->metadata.m.preview_size.Set(preview_xsize, preview_ysize));
JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
- ppf.info, *ppf.preview_frame, *io, pool, &io->preview_frame));
+ ppf.info, ppf.input_bitdepth, *ppf.preview_frame, *io, pool,
+ &io->preview_frame));
}
// Convert the pixels
io->frames.clear();
for (const auto& frame : ppf.frames) {
ImageBundle bundle(&io->metadata.m);
- JXL_RETURN_IF_ERROR(
- ConvertPackedFrameToImageBundle(ppf.info, frame, *io, pool, &bundle));
+ JXL_RETURN_IF_ERROR(ConvertPackedFrameToImageBundle(
+ ppf.info, ppf.input_bitdepth, frame, *io, pool, &bundle));
io->frames.push_back(std::move(bundle));
}
@@ -210,7 +212,8 @@ PackedPixelFile ConvertImage3FToPackedPixelFile(const Image3F& image,
: 0;
ppf.color_encoding = c_enc.ToExternal();
ppf.frames.clear();
- PackedFrame frame(image.xsize(), image.ysize(), format);
+ JXL_ASSIGN_OR_DIE(PackedFrame frame,
+ PackedFrame::Create(image.xsize(), image.ysize(), format));
const ImageF* channels[3];
for (int c = 0; c < 3; ++c) {
channels[c] = &image.Plane(c);
@@ -242,7 +245,8 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
ppf->info.alpha_bits = alpha_channel->bit_depth.bits_per_sample;
ppf->info.alpha_exponent_bits =
alpha_channel->bit_depth.exponent_bits_per_sample;
- ppf->info.alpha_premultiplied = alpha_channel->alpha_associated;
+ ppf->info.alpha_premultiplied =
+ TO_JXL_BOOL(alpha_channel->alpha_associated);
}
// Convert the image metadata
@@ -257,9 +261,9 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
ppf->info.linear_below = io.metadata.m.tone_mapping.linear_below;
ppf->info.min_nits = io.metadata.m.tone_mapping.min_nits;
ppf->info.relative_to_max_display =
- io.metadata.m.tone_mapping.relative_to_max_display;
+ TO_JXL_BOOL(io.metadata.m.tone_mapping.relative_to_max_display);
- ppf->info.uses_original_profile = !io.metadata.m.xyb_encoded;
+ ppf->info.uses_original_profile = TO_JXL_BOOL(!io.metadata.m.xyb_encoded);
JXL_ASSERT(0 < io.metadata.m.orientation && io.metadata.m.orientation <= 8);
ppf->info.orientation =
static_cast<JxlOrientation>(io.metadata.m.orientation);
@@ -267,13 +271,16 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
// Convert animation metadata
JXL_ASSERT(io.frames.size() == 1 || io.metadata.m.have_animation);
- ppf->info.have_animation = io.metadata.m.have_animation;
+ ppf->info.have_animation = TO_JXL_BOOL(io.metadata.m.have_animation);
ppf->info.animation.tps_numerator = io.metadata.m.animation.tps_numerator;
ppf->info.animation.tps_denominator = io.metadata.m.animation.tps_denominator;
ppf->info.animation.num_loops = io.metadata.m.animation.num_loops;
// Convert the color encoding
ppf->icc.assign(c_desired.ICC().begin(), c_desired.ICC().end());
+ ppf->primary_color_representation =
+ c_desired.WantICC() ? PackedPixelFile::kIccIsPrimary
+ : PackedPixelFile::kColorEncodingIsPrimary;
ppf->color_encoding = c_desired.ToExternal();
// Convert the extra blobs
@@ -289,22 +296,24 @@ Status ConvertCodecInOutToPackedPixelFile(const CodecInOut& io,
JXL_ASSERT(frame.metadata()->bit_depth.bits_per_sample != 0);
// It is ok for the frame.color().kNumPlanes to not match the
// number of channels on the image.
+ const uint32_t alpha_channels = has_alpha ? 1 : 0;
const uint32_t num_channels =
- frame.metadata()->color_encoding.Channels() + has_alpha;
+ frame.metadata()->color_encoding.Channels() + alpha_channels;
JxlPixelFormat format{/*num_channels=*/num_channels,
/*data_type=*/pixel_format.data_type,
/*endianness=*/pixel_format.endianness,
/*align=*/pixel_format.align};
- PackedFrame packed_frame(frame.oriented_xsize(), frame.oriented_ysize(),
- format);
+ JXL_ASSIGN_OR_RETURN(PackedFrame packed_frame,
+ PackedFrame::Create(frame.oriented_xsize(),
+ frame.oriented_ysize(), format));
const size_t bits_per_sample =
float_out ? packed_frame.color.BitsPerChannel(pixel_format.data_type)
: ppf->info.bits_per_sample;
packed_frame.name = frame.name;
packed_frame.frame_info.name_length = frame.name.size();
// Color transform
- ImageBundle ib = frame.Copy();
+ JXL_ASSIGN_OR_RETURN(ImageBundle ib, frame.Copy());
const ImageBundle* to_color_transform = &ib;
ImageMetadata metadata = io.metadata.m;
ImageBundle store(&metadata);
diff --git a/third_party/jpeg-xl/lib/extras/tone_mapping.cc b/third_party/jpeg-xl/lib/extras/tone_mapping.cc
index 3d0269524b..39df304501 100644
--- a/third_party/jpeg-xl/lib/extras/tone_mapping.cc
+++ b/third_party/jpeg-xl/lib/extras/tone_mapping.cc
@@ -19,7 +19,7 @@ HWY_BEFORE_NAMESPACE();
namespace jxl {
namespace HWY_NAMESPACE {
-static constexpr float rec2020_luminances[3] = {0.2627f, 0.6780f, 0.0593f};
+static constexpr Vector3 rec2020_luminances{0.2627f, 0.6780f, 0.0593f};
Status ToneMapFrame(const std::pair<float, float> display_nits,
ImageBundle* const ib, ThreadPool* const pool) {
diff --git a/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc b/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc
index 34cbdde781..8fc928a4fd 100644
--- a/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc
+++ b/third_party/jpeg-xl/lib/extras/tone_mapping_gbench.cc
@@ -6,11 +6,12 @@
#include "benchmark/benchmark.h"
#include "lib/extras/codec.h"
#include "lib/extras/tone_mapping.h"
+#include "lib/jxl/image.h"
namespace jxl {
static void BM_ToneMapping(benchmark::State& state) {
- Image3F color(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
@@ -25,7 +26,8 @@ static void BM_ToneMapping(benchmark::State& state) {
for (auto _ : state) {
state.PauseTiming();
CodecInOut tone_mapping_input;
- Image3F color2(color.xsize(), color.ysize());
+ 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);