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/codec_test.cc7
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/apng.cc34
-rw-r--r--third_party/jpeg-xl/lib/extras/dec/pnm.cc4
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/apng.cc77
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpegli.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpg.cc2
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/pnm.cc8
-rw-r--r--third_party/jpeg-xl/lib/extras/mmap.h8
8 files changed, 90 insertions, 52 deletions
diff --git a/third_party/jpeg-xl/lib/extras/codec_test.cc b/third_party/jpeg-xl/lib/extras/codec_test.cc
index 50d5e37bc9..1357b5a616 100644
--- a/third_party/jpeg-xl/lib/extras/codec_test.cc
+++ b/third_party/jpeg-xl/lib/extras/codec_test.cc
@@ -26,6 +26,7 @@
#include "lib/extras/enc/encode.h"
#include "lib/extras/packed_image.h"
#include "lib/jxl/base/byte_order.h"
+#include "lib/jxl/base/data_parallel.h"
#include "lib/jxl/base/random.h"
#include "lib/jxl/base/span.h"
#include "lib/jxl/base/status.h"
@@ -333,10 +334,10 @@ TEST(CodecTest, TestRoundTrip) {
params.add_alpha = add_alpha;
params.big_endian = big_endian;
params.add_extra_channels = false;
- TestRoundTrip(params, &pool);
+ TestRoundTrip(params, pool.get());
if (codec == Codec::kPNM && add_alpha) {
params.add_extra_channels = true;
- TestRoundTrip(params, &pool);
+ TestRoundTrip(params, pool.get());
}
}
}
@@ -369,7 +370,7 @@ TEST(CodecTest, LosslessPNMRoundtrip) {
EncodedImage encoded;
auto encoder = Encoder::FromExtension(extension);
ASSERT_TRUE(encoder.get());
- ASSERT_TRUE(encoder->Encode(ppf, &encoded, &pool));
+ ASSERT_TRUE(encoder->Encode(ppf, &encoded, pool.get()));
ASSERT_EQ(encoded.bitstreams.size(), 1);
ASSERT_EQ(orig.size(), encoded.bitstreams[0].size());
EXPECT_EQ(0,
diff --git a/third_party/jpeg-xl/lib/extras/dec/apng.cc b/third_party/jpeg-xl/lib/extras/dec/apng.cc
index 8b0da06eb1..c607a71d08 100644
--- a/third_party/jpeg-xl/lib/extras/dec/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/apng.cc
@@ -381,9 +381,11 @@ class BlobsReaderPNG {
// We need 2*bytes for the hex values plus 1 byte every 36 values,
// plus terminal \n for length.
- const unsigned long needed_bytes =
- bytes_to_decode * 2 + 1 + DivCeil(bytes_to_decode, 36);
- if (needed_bytes != static_cast<size_t>(encoded_end - pos)) {
+ size_t tail = static_cast<size_t>(encoded_end - pos);
+ bool ok = ((tail / 2) >= bytes_to_decode);
+ if (ok) tail -= 2 * static_cast<size_t>(bytes_to_decode);
+ ok = ok && (tail == 1 + DivCeil(bytes_to_decode, 36));
+ if (!ok) {
return JXL_FAILURE("Not enough bytes to parse %d bytes in hex",
bytes_to_decode);
}
@@ -439,7 +441,7 @@ struct APNGFrame {
Status Resize(size_t new_size) {
if (new_size > pixels_size) {
pixels.reset(malloc(new_size));
- if (!pixels.get()) {
+ if (!pixels) {
// TODO(szabadka): use specialized OOM error code
return JXL_FAILURE("Failed to allocate memory for image buffer");
}
@@ -462,7 +464,7 @@ struct Reader {
bool Eof() const { return next == last; }
};
-const unsigned long cMaxPNGSize = 1000000UL;
+const uint32_t cMaxPNGSize = 1000000UL;
const size_t kMaxPNGChunkSize = 1lu << 30; // 1 GB
void info_fn(png_structp png_ptr, png_infop info_ptr) {
@@ -641,17 +643,17 @@ Status DecodeImageAPNG(const Span<const uint8_t> bytes,
bool have_srgb = false;
bool errorstate = true;
if (id == kId_IHDR && chunkIHDR.size() == 25) {
- 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;
+ uint32_t x0 = 0;
+ uint32_t y0 = 0;
+ uint32_t delay_num = 1;
+ uint32_t delay_den = 10;
+ uint32_t dop = 0;
+ uint32_t bop = 0;
+
+ uint32_t w = png_get_uint_32(chunkIHDR.data() + 8);
+ uint32_t h = png_get_uint_32(chunkIHDR.data() + 12);
+ uint32_t w0 = w;
+ uint32_t h0 = h;
if (w > cMaxPNGSize || h > cMaxPNGSize) {
return false;
}
diff --git a/third_party/jpeg-xl/lib/extras/dec/pnm.cc b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
index 040c0bff81..e64d7e95f9 100644
--- a/third_party/jpeg-xl/lib/extras/dec/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/dec/pnm.cc
@@ -332,7 +332,7 @@ struct PNMChunkedInputFrame {
METHOD_TO_C_CALLBACK(&PNMChunkedInputFrame::ReleaseCurrentData)};
}
- void GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
+ void /* NOLINT */ GetColorChannelsPixelFormat(JxlPixelFormat* pixel_format) {
*pixel_format = format;
}
@@ -349,12 +349,14 @@ struct PNMChunkedInputFrame {
void GetExtraChannelPixelFormat(size_t ec_index,
JxlPixelFormat* pixel_format) {
+ (void)this;
JXL_ABORT("Not implemented");
}
const void* GetExtraChannelDataAt(size_t ec_index, size_t xpos, size_t ypos,
size_t xsize, size_t ysize,
size_t* row_offset) {
+ (void)this;
JXL_ABORT("Not implemented");
}
diff --git a/third_party/jpeg-xl/lib/extras/enc/apng.cc b/third_party/jpeg-xl/lib/extras/enc/apng.cc
index 40aa876e84..a28408a7f2 100644
--- a/third_party/jpeg-xl/lib/extras/enc/apng.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/apng.cc
@@ -73,17 +73,30 @@ class APNGEncoder : public Encoder {
}
Status Encode(const PackedPixelFile& ppf, EncodedImage* encoded_image,
ThreadPool* pool) const override {
+ // Encode main image frames
JXL_RETURN_IF_ERROR(VerifyBasicInfo(ppf.info));
encoded_image->icc.clear();
encoded_image->bitstreams.resize(1);
- return EncodePackedPixelFileToAPNG(ppf, pool,
- &encoded_image->bitstreams.front());
+ JXL_RETURN_IF_ERROR(EncodePackedPixelFileToAPNG(
+ ppf, pool, &encoded_image->bitstreams.front()));
+
+ // Encode extra channels
+ for (size_t i = 0; i < ppf.extra_channels_info.size(); ++i) {
+ encoded_image->extra_channel_bitstreams.emplace_back();
+ auto& ec_bitstreams = encoded_image->extra_channel_bitstreams.back();
+ ec_bitstreams.emplace_back();
+ JXL_RETURN_IF_ERROR(EncodePackedPixelFileToAPNG(
+ ppf, pool, &ec_bitstreams.back(), true, i));
+ }
+ return true;
}
private:
Status EncodePackedPixelFileToAPNG(const PackedPixelFile& ppf,
ThreadPool* pool,
- std::vector<uint8_t>* bytes) const;
+ std::vector<uint8_t>* bytes,
+ bool encode_extra_channels = false,
+ size_t extra_channel_index = 0) const;
};
void PngWrite(png_structp png_ptr, png_bytep data, png_size_t length) {
@@ -266,15 +279,21 @@ void MaybeAddCLLi(const JxlColorEncoding& c_enc, const float intensity_target,
}
Status APNGEncoder::EncodePackedPixelFileToAPNG(
- const PackedPixelFile& ppf, ThreadPool* pool,
- std::vector<uint8_t>* bytes) const {
- size_t xsize = ppf.info.xsize;
- size_t ysize = ppf.info.ysize;
- bool has_alpha = ppf.info.alpha_bits != 0;
- bool is_gray = ppf.info.num_color_channels == 1;
- size_t color_channels = ppf.info.num_color_channels;
+ const PackedPixelFile& ppf, ThreadPool* pool, std::vector<uint8_t>* bytes,
+ bool encode_extra_channels, size_t extra_channel_index) const {
+ JxlExtraChannelInfo ec_info{};
+ if (encode_extra_channels) {
+ if (ppf.extra_channels_info.size() <= extra_channel_index) {
+ return JXL_FAILURE("Invalid index for extra channel");
+ }
+ ec_info = ppf.extra_channels_info[extra_channel_index].ec_info;
+ }
+
+ bool has_alpha = !encode_extra_channels && (ppf.info.alpha_bits != 0);
+ bool is_gray = encode_extra_channels || (ppf.info.num_color_channels == 1);
+ size_t color_channels =
+ encode_extra_channels ? 1 : ppf.info.num_color_channels;
size_t num_channels = color_channels + (has_alpha ? 1 : 0);
- size_t num_samples = num_channels * xsize * ysize;
if (!ppf.info.have_animation && ppf.frames.size() != 1) {
return JXL_FAILURE("Invalid number of frames");
@@ -284,9 +303,24 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
size_t anim_chunks = 0;
for (const auto& frame : ppf.frames) {
- JXL_RETURN_IF_ERROR(VerifyPackedImage(frame.color, ppf.info));
-
- const PackedImage& color = frame.color;
+ const PackedImage& color = encode_extra_channels
+ ? frame.extra_channels[extra_channel_index]
+ : frame.color;
+
+ size_t xsize = color.xsize;
+ size_t ysize = color.ysize;
+ size_t num_samples = num_channels * xsize * ysize;
+
+ uint32_t bits_per_sample = encode_extra_channels ? ec_info.bits_per_sample
+ : ppf.info.bits_per_sample;
+ if (!encode_extra_channels) {
+ JXL_RETURN_IF_ERROR(VerifyPackedImage(color, ppf.info));
+ } else {
+ JXL_RETURN_IF_ERROR(VerifyFormat(color.format));
+ JXL_RETURN_IF_ERROR(VerifyBitDepth(color.format.data_type,
+ bits_per_sample,
+ ec_info.exponent_bits_per_sample));
+ }
const JxlPixelFormat format = color.format;
const uint8_t* in = reinterpret_cast<const uint8_t*>(color.pixels());
size_t data_bits_per_sample = PackedImage::BitsPerChannel(format.data_type);
@@ -297,24 +331,23 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
std::vector<uint8_t> out(out_size);
if (format.data_type == JXL_TYPE_UINT8) {
- if (ppf.info.bits_per_sample < 8) {
- float mul = 255.0 / ((1u << ppf.info.bits_per_sample) - 1);
+ if (bits_per_sample < 8) {
+ float mul = 255.0 / ((1u << bits_per_sample) - 1);
for (size_t i = 0; i < num_samples; ++i) {
- out[i] = static_cast<uint8_t>(in[i] * mul + 0.5);
+ out[i] = static_cast<uint8_t>(std::lroundf(in[i] * mul));
}
} else {
memcpy(out.data(), in, out_size);
}
} else if (format.data_type == JXL_TYPE_UINT16) {
- if (ppf.info.bits_per_sample < 16 ||
- format.endianness != JXL_BIG_ENDIAN) {
- float mul = 65535.0 / ((1u << ppf.info.bits_per_sample) - 1);
+ if (bits_per_sample < 16 || format.endianness != JXL_BIG_ENDIAN) {
+ float mul = 65535.0 / ((1u << bits_per_sample) - 1);
const uint8_t* p_in = in;
uint8_t* p_out = out.data();
for (size_t i = 0; i < num_samples; ++i, p_in += 2, p_out += 2) {
uint32_t val = (format.endianness == JXL_BIG_ENDIAN ? LoadBE16(p_in)
: LoadLE16(p_in));
- StoreBE16(static_cast<uint32_t>(val * mul + 0.5), p_out);
+ StoreBE16(static_cast<uint32_t>(std::lroundf(val * mul)), p_out);
}
} else {
memcpy(out.data(), in, out_size);
@@ -344,7 +377,7 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG(
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
PNG_FILTER_TYPE_BASE);
- if (count == 0) {
+ if (count == 0 && !encode_extra_channels) {
if (!MaybeAddSRGB(ppf.color_encoding, png_ptr, info_ptr)) {
MaybeAddCICP(ppf.color_encoding, png_ptr, info_ptr);
if (!ppf.icc.empty()) {
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
index aa10b584d0..cb473a1290 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
@@ -390,7 +390,7 @@ Status EncodeJpeg(const PackedPixelFile& ppf, const JpegSettings& jpeg_settings,
// before the call to setjmp().
std::vector<uint8_t> pixels;
unsigned char* output_buffer = nullptr;
- unsigned long output_size = 0;
+ unsigned long output_size = 0; // NOLINT
std::vector<uint8_t> row_bytes;
size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize());
hwy::AlignedFreeUniquePtr<float[]> xyb_tmp =
diff --git a/third_party/jpeg-xl/lib/extras/enc/jpg.cc b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
index de0228fc0d..0095ac9294 100644
--- a/third_party/jpeg-xl/lib/extras/enc/jpg.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/jpg.cc
@@ -276,7 +276,7 @@ Status EncodeWithLibJpeg(const PackedImage& image, const JxlBasicInfo& info,
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
unsigned char* buffer = nullptr;
- unsigned long size = 0;
+ unsigned long size = 0; // NOLINT
jpeg_mem_dest(&cinfo, &buffer, &size);
cinfo.image_width = image.xsize;
cinfo.image_height = image.ysize;
diff --git a/third_party/jpeg-xl/lib/extras/enc/pnm.cc b/third_party/jpeg-xl/lib/extras/enc/pnm.cc
index 966611cfca..d2d67ae52a 100644
--- a/third_party/jpeg-xl/lib/extras/enc/pnm.cc
+++ b/third_party/jpeg-xl/lib/extras/enc/pnm.cc
@@ -87,8 +87,8 @@ class PNMEncoder : public BasePNMEncoder {
}
private:
- Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
- std::vector<uint8_t>* bytes) const {
+ static Status EncodeImage(const PackedImage& image, size_t bits_per_sample,
+ std::vector<uint8_t>* bytes) {
uint32_t maxval = (1u << bits_per_sample) - 1;
char type = image.format.num_channels == 1 ? '5' : '6';
char header[kMaxHeaderSize];
@@ -161,8 +161,8 @@ class PFMEncoder : public BasePNMEncoder {
}
private:
- Status EncodeImage(const PackedImage& image,
- std::vector<uint8_t>* bytes) const {
+ static Status EncodeImage(const PackedImage& image,
+ std::vector<uint8_t>* bytes) {
char type = image.format.num_channels == 1 ? 'f' : 'F';
double scale = image.format.endianness == JXL_LITTLE_ENDIAN ? -1.0 : 1.0;
char header[kMaxHeaderSize];
diff --git a/third_party/jpeg-xl/lib/extras/mmap.h b/third_party/jpeg-xl/lib/extras/mmap.h
index 8bc023dec0..60cc215993 100644
--- a/third_party/jpeg-xl/lib/extras/mmap.h
+++ b/third_party/jpeg-xl/lib/extras/mmap.h
@@ -18,10 +18,10 @@ class MemoryMappedFile {
static StatusOr<MemoryMappedFile> Init(const char* path);
const uint8_t* data() const;
size_t size() const;
- MemoryMappedFile();
- ~MemoryMappedFile();
- MemoryMappedFile(MemoryMappedFile&&) noexcept;
- MemoryMappedFile& operator=(MemoryMappedFile&&) noexcept;
+ MemoryMappedFile(); // NOLINT
+ ~MemoryMappedFile(); // NOLINT
+ MemoryMappedFile(MemoryMappedFile&&) noexcept; // NOLINT
+ MemoryMappedFile& operator=(MemoryMappedFile&&) noexcept; // NOLINT
private:
std::unique_ptr<MemoryMappedFileImpl> impl_;