From d8bbc7858622b6d9c278469aab701ca0b609cddf Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 15 May 2024 05:35:49 +0200 Subject: Merging upstream version 126.0. Signed-off-by: Daniel Baumann --- third_party/jpeg-xl/lib/extras/enc/apng.cc | 77 ++++++++++++++++++++-------- third_party/jpeg-xl/lib/extras/enc/jpegli.cc | 2 +- third_party/jpeg-xl/lib/extras/enc/jpg.cc | 2 +- third_party/jpeg-xl/lib/extras/enc/pnm.cc | 8 +-- 4 files changed, 61 insertions(+), 28 deletions(-) (limited to 'third_party/jpeg-xl/lib/extras/enc') 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* bytes) const; + std::vector* 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* 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* 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(color.pixels()); size_t data_bits_per_sample = PackedImage::BitsPerChannel(format.data_type); @@ -297,24 +331,23 @@ Status APNGEncoder::EncodePackedPixelFileToAPNG( std::vector 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(in[i] * mul + 0.5); + out[i] = static_cast(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(val * mul + 0.5), p_out); + StoreBE16(static_cast(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 pixels; unsigned char* output_buffer = nullptr; - unsigned long output_size = 0; + unsigned long output_size = 0; // NOLINT std::vector row_bytes; size_t rowlen = RoundUpTo(ppf.info.xsize, MaxVectorSize()); hwy::AlignedFreeUniquePtr 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* bytes) const { + static Status EncodeImage(const PackedImage& image, size_t bits_per_sample, + std::vector* 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* bytes) const { + static Status EncodeImage(const PackedImage& image, + std::vector* 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]; -- cgit v1.2.3