summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/extras/enc/jpegli.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/jpeg-xl/lib/extras/enc/jpegli.cc')
-rw-r--r--third_party/jpeg-xl/lib/extras/enc/jpegli.cc82
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);
}