diff options
Diffstat (limited to 'third_party/jpeg-xl/lib/extras/enc/jpegli.cc')
-rw-r--r-- | third_party/jpeg-xl/lib/extras/enc/jpegli.cc | 82 |
1 files changed, 51 insertions, 31 deletions
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); } |