summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/jpegli
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/jpeg-xl/lib/jpegli')
-rw-r--r--third_party/jpeg-xl/lib/jpegli/color_transform.cc316
-rw-r--r--third_party/jpeg-xl/lib/jpegli/common.h7
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode.cc49
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode.h1
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_api_test.cc24
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_internal.h4
-rw-r--r--third_party/jpeg-xl/lib/jpegli/decode_marker.cc6
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode.cc40
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode.h1
-rw-r--r--third_party/jpeg-xl/lib/jpegli/encode_api_test.cc47
-rw-r--r--third_party/jpeg-xl/lib/jpegli/error_handling_test.cc22
-rw-r--r--third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc14
-rw-r--r--third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc7
-rw-r--r--third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc12
-rw-r--r--third_party/jpeg-xl/lib/jpegli/source_manager_test.cc3
-rw-r--r--third_party/jpeg-xl/lib/jpegli/streaming_test.cc10
-rw-r--r--third_party/jpeg-xl/lib/jpegli/test_utils.cc63
-rw-r--r--third_party/jpeg-xl/lib/jpegli/test_utils.h28
-rw-r--r--third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc9
19 files changed, 556 insertions, 107 deletions
diff --git a/third_party/jpeg-xl/lib/jpegli/color_transform.cc b/third_party/jpeg-xl/lib/jpegli/color_transform.cc
index 60a0dc83bb..ec906bedce 100644
--- a/third_party/jpeg-xl/lib/jpegli/color_transform.cc
+++ b/third_party/jpeg-xl/lib/jpegli/color_transform.cc
@@ -26,11 +26,16 @@ using hwy::HWY_NAMESPACE::Mul;
using hwy::HWY_NAMESPACE::MulAdd;
using hwy::HWY_NAMESPACE::Sub;
-void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
+template <int kRed, int kGreen, int kBlue, int kAlpha>
+void YCbCrToExtRGB(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
- float* JXL_RESTRICT row0 = row[0];
- float* JXL_RESTRICT row1 = row[1];
- float* JXL_RESTRICT row2 = row[2];
+ const float* row_y = row[0];
+ const float* row_cb = row[1];
+ const float* row_cr = row[2];
+ float* row_r = row[kRed];
+ float* row_g = row[kGreen];
+ float* row_b = row[kBlue];
+ float* row_a = row[kAlpha];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
@@ -38,20 +43,48 @@ void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
const auto cgcb = Set(df, -0.114f * 1.772f / 0.587f);
const auto cgcr = Set(df, -0.299f * 1.402f / 0.587f);
const auto cbcb = Set(df, 1.772f);
+ const auto alpha_opaque = Set(df, 127.0f / 255.0f);
for (size_t x = 0; x < xsize; x += Lanes(df)) {
- const auto y_vec = Load(df, row0 + x);
- const auto cb_vec = Load(df, row1 + x);
- const auto cr_vec = Load(df, row2 + x);
+ const auto y_vec = Load(df, row_y + x);
+ const auto cb_vec = Load(df, row_cb + x);
+ const auto cr_vec = Load(df, row_cr + x);
const auto r_vec = MulAdd(crcr, cr_vec, y_vec);
const auto g_vec = MulAdd(cgcr, cr_vec, MulAdd(cgcb, cb_vec, y_vec));
const auto b_vec = MulAdd(cbcb, cb_vec, y_vec);
- Store(r_vec, df, row0 + x);
- Store(g_vec, df, row1 + x);
- Store(b_vec, df, row2 + x);
+ Store(r_vec, df, row_r + x);
+ Store(g_vec, df, row_g + x);
+ Store(b_vec, df, row_b + x);
+ if (kAlpha >= 0) {
+ Store(alpha_opaque, df, row_a + x);
+ }
}
}
+void YCbCrToRGB(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<0, 1, 2, -1>(row, xsize);
+}
+
+void YCbCrToBGR(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<2, 1, 0, -1>(row, xsize);
+}
+
+void YCbCrToRGBA(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<0, 1, 2, 3>(row, xsize);
+}
+
+void YCbCrToBGRA(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<2, 1, 0, 3>(row, xsize);
+}
+
+void YCbCrToARGB(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<1, 2, 3, 0>(row, xsize);
+}
+
+void YCbCrToABGR(float* row[kMaxComponents], size_t xsize) {
+ YCbCrToExtRGB<3, 2, 1, 0>(row, xsize);
+}
+
void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
@@ -66,11 +99,15 @@ void YCCKToCMYK(float* row[kMaxComponents], size_t xsize) {
}
}
-void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
+template <int kRed, int kGreen, int kBlue>
+void ExtRGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
- float* JXL_RESTRICT row0 = row[0];
- float* JXL_RESTRICT row1 = row[1];
- float* JXL_RESTRICT row2 = row[2];
+ const float* row_r = row[kRed];
+ const float* row_g = row[kGreen];
+ const float* row_b = row[kBlue];
+ float* row_y = row[0];
+ float* row_cb = row[1];
+ float* row_cr = row[2];
// Full-range BT.601 as defined by JFIF Clause 7:
// https://www.itu.int/rec/T-REC-T.871-201105-I/en
const auto c128 = Set(df, 128.0f);
@@ -85,9 +122,9 @@ void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const auto kNormB = Div(Set(df, 1.0f), (Add(kR, Add(kG, kAmpB))));
for (size_t x = 0; x < xsize; x += Lanes(df)) {
- const auto r = Load(df, row0 + x);
- const auto g = Load(df, row1 + x);
- const auto b = Load(df, row2 + x);
+ const auto r = Load(df, row_r + x);
+ const auto g = Load(df, row_g + x);
+ const auto b = Load(df, row_b + x);
const auto r_base = Mul(r, kR);
const auto r_diff = Mul(r, kDiffR);
const auto g_base = Mul(g, kG);
@@ -96,12 +133,28 @@ void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
const auto y_base = Add(r_base, Add(g_base, b_base));
const auto cb_vec = MulAdd(Sub(b_diff, y_base), kNormB, c128);
const auto cr_vec = MulAdd(Sub(r_diff, y_base), kNormR, c128);
- Store(y_base, df, row0 + x);
- Store(cb_vec, df, row1 + x);
- Store(cr_vec, df, row2 + x);
+ Store(y_base, df, row_y + x);
+ Store(cb_vec, df, row_cb + x);
+ Store(cr_vec, df, row_cr + x);
}
}
+void RGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<0, 1, 2>(row, xsize);
+}
+
+void BGRToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<2, 1, 0>(row, xsize);
+}
+
+void ARGBToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<1, 2, 3>(row, xsize);
+}
+
+void ABGRToYCbCr(float* row[kMaxComponents], size_t xsize) {
+ ExtRGBToYCbCr<3, 2, 1>(row, xsize);
+}
+
void CMYKToYCCK(float* row[kMaxComponents], size_t xsize) {
const HWY_CAPPED(float, 8) df;
float* JXL_RESTRICT row0 = row[0];
@@ -127,7 +180,15 @@ namespace jpegli {
HWY_EXPORT(CMYKToYCCK);
HWY_EXPORT(YCCKToCMYK);
HWY_EXPORT(YCbCrToRGB);
+HWY_EXPORT(YCbCrToBGR);
+HWY_EXPORT(YCbCrToRGBA);
+HWY_EXPORT(YCbCrToBGRA);
+HWY_EXPORT(YCbCrToARGB);
+HWY_EXPORT(YCbCrToABGR);
HWY_EXPORT(RGBToYCbCr);
+HWY_EXPORT(BGRToYCbCr);
+HWY_EXPORT(ARGBToYCbCr);
+HWY_EXPORT(ABGRToYCbCr);
bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
switch (colorspace) {
@@ -164,16 +225,73 @@ bool CheckColorSpaceComponents(int num_components, J_COLOR_SPACE colorspace) {
void NullTransform(float* row[kMaxComponents], size_t len) {}
+void FillAlpha(float* row, size_t len) {
+ static const float kAlpha = 127.0f / 255.0f;
+ for (size_t i = 0; i < len; ++i) {
+ row[i] = kAlpha;
+ }
+}
+
+// Works for BGR as well.
void GrayscaleToRGB(float* row[kMaxComponents], size_t len) {
memcpy(row[1], row[0], len * sizeof(row[1][0]));
memcpy(row[2], row[0], len * sizeof(row[2][0]));
}
+// Works for BGRA as well.
+void GrayscaleToRGBA(float* row[kMaxComponents], size_t len) {
+ memcpy(row[1], row[0], len * sizeof(row[1][0]));
+ memcpy(row[2], row[0], len * sizeof(row[2][0]));
+ FillAlpha(row[3], len);
+}
+
+// Works for ABGR as well.
+void GrayscaleToARGB(float* row[kMaxComponents], size_t len) {
+ memcpy(row[1], row[0], len * sizeof(row[1][0]));
+ memcpy(row[2], row[0], len * sizeof(row[2][0]));
+ memcpy(row[3], row[0], len * sizeof(row[1][0]));
+ FillAlpha(row[0], len);
+}
+
void GrayscaleToYCbCr(float* row[kMaxComponents], size_t len) {
memset(row[1], 0, len * sizeof(row[1][0]));
memset(row[2], 0, len * sizeof(row[2][0]));
}
+void RGBToBGR(float* row[kMaxComponents], size_t len) {
+ for (size_t i = 0; i < len; ++i) {
+ std::swap(row[0][i], row[2][i]);
+ }
+}
+
+void RGBToRGBA(float* row[kMaxComponents], size_t len) {
+ FillAlpha(row[3], len);
+}
+
+void RGBToBGRA(float* row[kMaxComponents], size_t len) {
+ static const float kAlpha = 127.0f / 255.0f;
+ for (size_t i = 0; i < len; ++i) {
+ std::swap(row[0][i], row[2][i]);
+ row[3][i] = kAlpha;
+ }
+}
+
+void RGBToARGB(float* row[kMaxComponents], size_t len) {
+ memcpy(row[3], row[2], len * sizeof(row[1][0]));
+ memcpy(row[2], row[1], len * sizeof(row[2][0]));
+ memcpy(row[1], row[0], len * sizeof(row[1][0]));
+ FillAlpha(row[0], len);
+}
+
+void RGBToABGR(float* row[kMaxComponents], size_t len) {
+ static const float kAlpha = 127.0f / 255.0f;
+ for (size_t i = 0; i < len; ++i) {
+ std::swap(row[1][i], row[2][i]);
+ row[3][i] = row[0][i];
+ row[0][i] = kAlpha;
+ }
+}
+
void ChooseColorTransform(j_compress_ptr cinfo) {
jpeg_comp_master* m = cinfo->master;
if (!CheckColorSpaceComponents(cinfo->input_components,
@@ -226,6 +344,43 @@ void ChooseColorTransform(j_compress_ptr cinfo) {
}
}
+ if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
+ cinfo->jpeg_color_space == JCS_YCbCr) {
+ switch (cinfo->in_color_space) {
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_RGBX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ break;
+ case JCS_EXT_BGR:
+ case JCS_EXT_BGRX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(BGRToYCbCr);
+ break;
+ case JCS_EXT_XRGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ARGBToYCbCr);
+ break;
+ case JCS_EXT_XBGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ABGRToYCbCr);
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ break;
+ case JCS_EXT_BGRA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(BGRToYCbCr);
+ break;
+ case JCS_EXT_ARGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ARGBToYCbCr);
+ break;
+ case JCS_EXT_ABGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(ABGRToYCbCr);
+ break;
+#endif
+ default:; // Nothing to do.
+ }
+ }
+
if (m->color_transform == nullptr) {
// TODO(szabadka) Support more color transforms.
JPEGLI_ERROR("Unsupported color transform %d -> %d", cinfo->in_color_space,
@@ -257,18 +412,123 @@ void ChooseColorTransform(j_decompress_ptr cinfo) {
m->color_transform = nullptr;
if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
- if (cinfo->out_color_space == JCS_RGB) {
- m->color_transform = GrayscaleToRGB;
+ switch (cinfo->out_color_space) {
+ case JCS_RGB:
+ m->color_transform = GrayscaleToRGB;
+ break;
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_BGR:
+ m->color_transform = GrayscaleToRGB;
+ break;
+ case JCS_EXT_RGBX:
+ case JCS_EXT_BGRX:
+ m->color_transform = GrayscaleToRGBA;
+ break;
+ case JCS_EXT_XRGB:
+ case JCS_EXT_XBGR:
+ m->color_transform = GrayscaleToARGB;
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ case JCS_EXT_BGRA:
+ m->color_transform = GrayscaleToRGBA;
+ break;
+ case JCS_EXT_ARGB:
+ case JCS_EXT_ABGR:
+ m->color_transform = GrayscaleToARGB;
+ break;
+#endif
+ default:
+ m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_RGB) {
- if (cinfo->out_color_space == JCS_GRAYSCALE) {
- m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(RGBToYCbCr);
+ break;
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ m->color_transform = NullTransform;
+ break;
+ case JCS_EXT_BGR:
+ m->color_transform = RGBToBGR;
+ break;
+ case JCS_EXT_RGBX:
+ m->color_transform = RGBToRGBA;
+ break;
+ case JCS_EXT_BGRX:
+ m->color_transform = RGBToBGRA;
+ break;
+ case JCS_EXT_XRGB:
+ m->color_transform = RGBToARGB;
+ break;
+ case JCS_EXT_XBGR:
+ m->color_transform = RGBToABGR;
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ m->color_transform = RGBToRGBA;
+ break;
+ case JCS_EXT_BGRA:
+ m->color_transform = RGBToBGRA;
+ break;
+ case JCS_EXT_ARGB:
+ m->color_transform = RGBToARGB;
+ break;
+ case JCS_EXT_ABGR:
+ m->color_transform = RGBToABGR;
+ break;
+#endif
+ default:
+ m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_YCbCr) {
- if (cinfo->out_color_space == JCS_RGB) {
- m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
- } else if (cinfo->out_color_space == JCS_GRAYSCALE) {
- m->color_transform = NullTransform;
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ m->color_transform = NullTransform;
+ break;
+ case JCS_RGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
+ break;
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGB);
+ break;
+ case JCS_EXT_BGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGR);
+ break;
+ case JCS_EXT_RGBX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGBA);
+ break;
+ case JCS_EXT_BGRX:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGRA);
+ break;
+ case JCS_EXT_XRGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToARGB);
+ break;
+ case JCS_EXT_XBGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToABGR);
+ break;
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToRGBA);
+ break;
+ case JCS_EXT_BGRA:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToBGRA);
+ break;
+ case JCS_EXT_ARGB:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToARGB);
+ break;
+ case JCS_EXT_ABGR:
+ m->color_transform = HWY_DYNAMIC_DISPATCH(YCbCrToABGR);
+ break;
+#endif
+ default:
+ m->color_transform = nullptr;
}
} else if (cinfo->jpeg_color_space == JCS_YCCK) {
if (cinfo->out_color_space == JCS_CMYK) {
diff --git a/third_party/jpeg-xl/lib/jpegli/common.h b/third_party/jpeg-xl/lib/jpegli/common.h
index 42487f2b89..514483afef 100644
--- a/third_party/jpeg-xl/lib/jpegli/common.h
+++ b/third_party/jpeg-xl/lib/jpegli/common.h
@@ -20,12 +20,7 @@
#ifndef LIB_JPEGLI_COMMON_H_
#define LIB_JPEGLI_COMMON_H_
-/* clang-format off */
-#include <stdio.h>
-#include <jpeglib.h>
-/* clang-format on */
-
-#include "lib/jpegli/types.h"
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
diff --git a/third_party/jpeg-xl/lib/jpegli/decode.cc b/third_party/jpeg-xl/lib/jpegli/decode.cc
index 9fdf68dd18..d967b787d3 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode.cc
@@ -54,6 +54,7 @@ void InitializeImage(j_decompress_ptr cinfo) {
m->found_soi_ = false;
m->found_dri_ = false;
m->found_sof_ = false;
+ m->found_sos_ = false;
m->found_eoi_ = false;
m->icc_index_ = 0;
m->icc_total_ = 0;
@@ -243,10 +244,14 @@ void PrepareForScan(j_decompress_ptr cinfo) {
// Copy quantization tables into comp_info.
for (int i = 0; i < cinfo->comps_in_scan; ++i) {
jpeg_component_info* comp = cinfo->cur_comp_info[i];
+ int quant_tbl_idx = comp->quant_tbl_no;
+ JQUANT_TBL* quant_table = cinfo->quant_tbl_ptrs[quant_tbl_idx];
+ if (!quant_table) {
+ JPEGLI_ERROR("Quantization table with index %d not found", quant_tbl_idx);
+ }
if (comp->quant_table == nullptr) {
comp->quant_table = Allocate<JQUANT_TBL>(cinfo, 1, JPOOL_IMAGE);
- memcpy(comp->quant_table, cinfo->quant_tbl_ptrs[comp->quant_tbl_no],
- sizeof(JQUANT_TBL));
+ memcpy(comp->quant_table, quant_table, sizeof(JQUANT_TBL));
}
}
if (cinfo->comps_in_scan == 1) {
@@ -723,16 +728,36 @@ void jpegli_calc_output_dimensions(j_decompress_ptr cinfo) {
}
}
}
- if (cinfo->out_color_space == JCS_GRAYSCALE) {
- cinfo->out_color_components = 1;
- } else if (cinfo->out_color_space == JCS_RGB ||
- cinfo->out_color_space == JCS_YCbCr) {
- cinfo->out_color_components = 3;
- } else if (cinfo->out_color_space == JCS_CMYK ||
- cinfo->out_color_space == JCS_YCCK) {
- cinfo->out_color_components = 4;
- } else {
- cinfo->out_color_components = cinfo->num_components;
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ break;
+ case JCS_RGB:
+ case JCS_YCbCr:
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_BGR:
+#endif
+ cinfo->out_color_components = 3;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGBX:
+ case JCS_EXT_BGRX:
+ case JCS_EXT_XBGR:
+ case JCS_EXT_XRGB:
+#endif
+#ifdef JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ case JCS_EXT_BGRA:
+ case JCS_EXT_ABGR:
+ case JCS_EXT_ARGB:
+#endif
+ cinfo->out_color_components = 4;
+ break;
+ default:
+ cinfo->out_color_components = cinfo->num_components;
}
cinfo->output_components =
cinfo->quantize_colors ? 1 : cinfo->out_color_components;
diff --git a/third_party/jpeg-xl/lib/jpegli/decode.h b/third_party/jpeg-xl/lib/jpegli/decode.h
index f5b099eda3..668d630586 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode.h
@@ -21,6 +21,7 @@
#define LIB_JPEGLI_DECODE_H_
#include "lib/jpegli/common.h"
+#include "lib/jpegli/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
index 3ecd479951..c429f0f810 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_api_test.cc
@@ -3,17 +3,27 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <jxl/types.h>
+
+#include <algorithm>
#include <cstdint>
#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
#include <vector>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/base/byte_order.h"
+#include "lib/jpegli/types.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
@@ -894,7 +904,9 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
all_tests.push_back(config);
}
// Tests for color transforms.
- for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_GRAYSCALE}) {
+ for (J_COLOR_SPACE out_color_space :
+ {JCS_RGB, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR, JCS_EXT_RGBA,
+ JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = JCS_GRAYSCALE;
@@ -903,7 +915,9 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
all_tests.push_back(config);
}
for (J_COLOR_SPACE jpeg_color_space : {JCS_RGB, JCS_YCbCr}) {
- for (J_COLOR_SPACE out_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
+ for (J_COLOR_SPACE out_color_space :
+ {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR,
+ JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
if (jpeg_color_space == JCS_RGB && out_color_space == JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
@@ -1108,6 +1122,8 @@ std::vector<TestConfig> GenerateTests(bool buffered) {
TestConfig config;
config.input.xsize = xsize;
config.input.ysize = ysize;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
}
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_internal.h b/third_party/jpeg-xl/lib/jpegli/decode_internal.h
index 37dfcc4526..8455fae392 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_internal.h
+++ b/third_party/jpeg-xl/lib/jpegli/decode_internal.h
@@ -6,14 +6,15 @@
#ifndef LIB_JPEGLI_DECODE_INTERNAL_H_
#define LIB_JPEGLI_DECODE_INTERNAL_H_
-#include <stdint.h>
#include <sys/types.h>
+#include <cstdint>
#include <vector>
#include "lib/jpegli/common.h"
#include "lib/jpegli/common_internal.h"
#include "lib/jpegli/huffman.h"
+#include "lib/jpegli/types.h"
namespace jpegli {
@@ -58,6 +59,7 @@ struct jpeg_decomp_master {
bool found_soi_;
bool found_dri_;
bool found_sof_;
+ bool found_sos_;
bool found_eoi_;
// Whether this jpeg has multiple scans (progressive or non-interleaved
diff --git a/third_party/jpeg-xl/lib/jpegli/decode_marker.cc b/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
index a9ed4df329..2621ed0867 100644
--- a/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
+++ b/third_party/jpeg-xl/lib/jpegli/decode_marker.cc
@@ -103,9 +103,6 @@ void ProcessSOF(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
int quant_tbl_idx = ReadUint8(data, &pos);
JPEG_VERIFY_INPUT(quant_tbl_idx, 0, NUM_QUANT_TBLS - 1);
comp->quant_tbl_no = quant_tbl_idx;
- if (cinfo->quant_tbl_ptrs[quant_tbl_idx] == nullptr) {
- JPEGLI_ERROR("Quantization table with index %u not found", quant_tbl_idx);
- }
comp->quant_table = nullptr; // will be allocated after SOS marker
}
JPEG_VERIFY_MARKER_END();
@@ -168,6 +165,7 @@ void ProcessSOS(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
if (!m->found_sof_) {
JPEGLI_ERROR("Unexpected SOS marker.");
}
+ m->found_sos_ = true;
size_t pos = 2;
JPEG_VERIFY_LEN(1);
cinfo->comps_in_scan = ReadUint8(data, &pos);
@@ -337,7 +335,7 @@ void ProcessDHT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
void ProcessDQT(j_decompress_ptr cinfo, const uint8_t* data, size_t len) {
jpeg_decomp_master* m = cinfo->master;
- if (m->found_sof_) {
+ if (m->found_sos_) {
JPEGLI_ERROR("Updating quant tables between scans is not supported.");
}
size_t pos = 2;
diff --git a/third_party/jpeg-xl/lib/jpegli/encode.cc b/third_party/jpeg-xl/lib/jpegli/encode.cc
index 5326f2cb0f..6cfd54ad30 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode.cc
@@ -283,15 +283,15 @@ void ProcessCompressionParams(j_compress_ptr cinfo) {
JPEGLI_ERROR("Invalid sampling factor %d x %d", comp->h_samp_factor,
comp->v_samp_factor);
}
+ if (cinfo->num_components == 1) {
+ // Force samp factors to 1x1 for single-component images.
+ comp->h_samp_factor = comp->v_samp_factor = 1;
+ }
cinfo->max_h_samp_factor =
std::max(comp->h_samp_factor, cinfo->max_h_samp_factor);
cinfo->max_v_samp_factor =
std::max(comp->v_samp_factor, cinfo->max_v_samp_factor);
}
- if (cinfo->num_components == 1 &&
- (cinfo->max_h_samp_factor != 1 || cinfo->max_v_samp_factor != 1)) {
- JPEGLI_ERROR("Sampling is not supported for simgle component image.");
- }
size_t iMCU_width = DCTSIZE * cinfo->max_h_samp_factor;
size_t iMCU_height = DCTSIZE * cinfo->max_v_samp_factor;
size_t total_iMCU_cols = DivCeil(cinfo->image_width, iMCU_width);
@@ -713,18 +713,31 @@ void jpegli_set_defaults(j_compress_ptr cinfo) {
void jpegli_default_colorspace(j_compress_ptr cinfo) {
CheckState(cinfo, jpegli::kEncStart);
+ if (cinfo->in_color_space == JCS_RGB && cinfo->master->xyb_mode) {
+ jpegli_set_colorspace(cinfo, JCS_RGB);
+ return;
+ }
switch (cinfo->in_color_space) {
case JCS_GRAYSCALE:
jpegli_set_colorspace(cinfo, JCS_GRAYSCALE);
break;
- case JCS_RGB: {
- if (cinfo->master->xyb_mode) {
- jpegli_set_colorspace(cinfo, JCS_RGB);
- } else {
- jpegli_set_colorspace(cinfo, JCS_YCbCr);
- }
+ case JCS_RGB:
+#ifdef JCS_EXTENSIONS
+ case JCS_EXT_RGB:
+ case JCS_EXT_BGR:
+ case JCS_EXT_RGBX:
+ case JCS_EXT_BGRX:
+ case JCS_EXT_XRGB:
+ case JCS_EXT_XBGR:
+#endif
+#if JCS_ALPHA_EXTENSIONS
+ case JCS_EXT_RGBA:
+ case JCS_EXT_BGRA:
+ case JCS_EXT_ARGB:
+ case JCS_EXT_ABGR:
+#endif
+ jpegli_set_colorspace(cinfo, JCS_YCbCr);
break;
- }
case JCS_YCbCr:
jpegli_set_colorspace(cinfo, JCS_YCbCr);
break;
@@ -806,6 +819,11 @@ void jpegli_set_colorspace(j_compress_ptr cinfo, J_COLOR_SPACE colorspace) {
cinfo->comp_info[2].quant_tbl_no = 1;
cinfo->comp_info[1].dc_tbl_no = cinfo->comp_info[1].ac_tbl_no = 1;
cinfo->comp_info[2].dc_tbl_no = cinfo->comp_info[2].ac_tbl_no = 1;
+ // Use chroma subsampling by default
+ cinfo->comp_info[0].h_samp_factor = cinfo->comp_info[0].v_samp_factor = 2;
+ if (colorspace == JCS_YCCK) {
+ cinfo->comp_info[3].h_samp_factor = cinfo->comp_info[3].v_samp_factor = 2;
+ }
}
}
diff --git a/third_party/jpeg-xl/lib/jpegli/encode.h b/third_party/jpeg-xl/lib/jpegli/encode.h
index ed34838450..33de674471 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode.h
+++ b/third_party/jpeg-xl/lib/jpegli/encode.h
@@ -21,6 +21,7 @@
#define LIB_JPEGLI_ENCODE_H_
#include "lib/jpegli/common.h"
+#include "lib/jpegli/types.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
diff --git a/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
index 2978b3f35d..81b1b25bef 100644
--- a/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/encode_api_test.cc
@@ -4,14 +4,23 @@
// license that can be found in the LICENSE file.
#include <algorithm>
-#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
#include <vector>
#include "lib/jpegli/encode.h"
-#include "lib/jpegli/error.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/sanitizers.h"
+#include "lib/jpegli/types.h"
+#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
@@ -372,6 +381,8 @@ std::vector<TestConfig> GenerateTests() {
{
TestConfig config;
config.jparams.quality = 100;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 6.6;
config.max_dist = 0.6;
all_tests.push_back(config);
@@ -510,17 +521,23 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.libjpeg_mode = true;
config.max_bpp = 2.1;
config.max_dist = 1.7;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
- for (J_COLOR_SPACE in_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
+ for (J_COLOR_SPACE in_color_space :
+ {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE, JCS_EXT_RGB, JCS_EXT_BGR,
+ JCS_EXT_RGBA, JCS_EXT_BGRA, JCS_EXT_ARGB, JCS_EXT_ABGR}) {
for (J_COLOR_SPACE jpeg_color_space : {JCS_RGB, JCS_YCbCr, JCS_GRAYSCALE}) {
- if (jpeg_color_space == JCS_RGB && in_color_space == JCS_YCbCr) continue;
+ if (jpeg_color_space == JCS_RGB && in_color_space >= JCS_YCbCr) continue;
TestConfig config;
config.input.xsize = config.input.ysize = 256;
config.input.color_space = in_color_space;
config.jparams.set_jpeg_colorspace = true;
config.jparams.jpeg_color_space = jpeg_color_space;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = jpeg_color_space == JCS_RGB ? 4.5 : 1.85;
config.max_dist = jpeg_color_space == JCS_RGB ? 1.4 : 2.05;
all_tests.push_back(config);
@@ -536,6 +553,8 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.set_jpeg_colorspace = true;
config.jparams.jpeg_color_space = jpeg_color_space;
}
+ config.jparams.h_sampling = {1, 1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1, 1};
config.max_bpp = jpeg_color_space == JCS_CMYK ? 4.0 : 3.6;
config.max_dist = jpeg_color_space == JCS_CMYK ? 1.2 : 1.5;
all_tests.push_back(config);
@@ -546,6 +565,8 @@ std::vector<TestConfig> GenerateTests() {
config.input.color_space = JCS_YCbCr;
config.max_bpp = 1.6;
config.max_dist = 1.35;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
all_tests.push_back(config);
}
for (bool xyb : {false, true}) {
@@ -596,6 +617,8 @@ std::vector<TestConfig> GenerateTests() {
table.add_raw = add_raw;
table.Generate();
config.jparams.optimize_coding = 1;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.jparams.quant_tables.push_back(table);
config.jparams.quant_indexes = {0, 0, 0};
float q = (type == 0 ? 16 : type) * scale * 0.01f;
@@ -614,6 +637,8 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 2.25;
config.max_dist = 2.8;
all_tests.push_back(config);
@@ -626,6 +651,8 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
CustomQuantTable table;
table.slot_idx = slot_idx;
table.Generate();
@@ -643,6 +670,10 @@ std::vector<TestConfig> GenerateTests() {
config.jparams.xyb_mode = xyb;
config.jparams.quant_indexes = {(qidx >> 2) & 1, (qidx >> 1) & 1,
(qidx >> 0) & 1};
+ if (!xyb) {
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
+ }
{
CustomQuantTable table;
table.slot_idx = 0;
@@ -667,6 +698,10 @@ std::vector<TestConfig> GenerateTests() {
config.input.ysize = 256;
config.jparams.xyb_mode = xyb;
config.jparams.quant_indexes = {0, 1, 2};
+ if (!xyb) {
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
+ }
{
CustomQuantTable table;
table.slot_idx = 0;
@@ -738,6 +773,8 @@ std::vector<TestConfig> GenerateTests() {
}
config.jparams.progressive_mode = 0;
config.jparams.optimize_coding = 0;
+ config.jparams.h_sampling = {1, 1, 1};
+ config.jparams.v_sampling = {1, 1, 1};
config.max_bpp = 1.85;
config.max_dist = 2.05;
if (input_mode == COEFFICIENTS) {
diff --git a/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc b/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
index bcd7355124..582c6b170b 100644
--- a/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/error_handling_test.cc
@@ -3,12 +3,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <vector>
+
+#include "lib/jpegli/common.h"
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
-#include "lib/jpegli/error.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/sanitizers.h"
+#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
@@ -996,6 +1004,9 @@ TEST(EncoderErrorHandlingTest, AddOnTableNoStringParam) {
const uint8_t kCompressed0[] = {
// SOI
0xff, 0xd8, //
+ // SOF
+ 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
+ 0x01, 0x11, 0x00, //
// DQT
0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x03, 0x02, //
0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x03, 0x03, 0x04, 0x05, //
@@ -1004,9 +1015,6 @@ const uint8_t kCompressed0[] = {
0x0e, 0x12, 0x10, 0x0d, 0x0e, 0x11, 0x0e, 0x0b, 0x0b, 0x10, //
0x16, 0x10, 0x11, 0x13, 0x14, 0x15, 0x15, 0x15, 0x0c, 0x0f, //
0x17, 0x18, 0x16, 0x14, 0x18, 0x12, 0x14, 0x15, 0x14, //
- // SOF
- 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, 0x01, //
- 0x01, 0x11, 0x00, //
// DHT
0xff, 0xc4, 0x00, 0xd2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, //
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
@@ -1039,8 +1047,8 @@ const uint8_t kCompressed0[] = {
};
const size_t kLen0 = sizeof(kCompressed0);
-const size_t kDQTOffset = 2;
-const size_t kSOFOffset = 71;
+const size_t kSOFOffset = 2;
+const size_t kDQTOffset = 15;
const size_t kDHTOffset = 84;
const size_t kSOSOffset = 296;
diff --git a/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc b/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
index 6546b7b087..dc5aee2fc5 100644
--- a/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/input_suspension_test.cc
@@ -3,16 +3,24 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <cmath>
+#include <jxl/types.h>
+
+#include <algorithm>
+#include <cstddef>
#include <cstdint>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
#include <vector>
#include "lib/jpegli/decode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/base/byte_order.h"
#include "lib/jxl/base/status.h"
-#include "lib/jxl/sanitizers.h"
namespace jpegli {
namespace {
diff --git a/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc b/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
index 020adf5e9e..d34ec7e999 100644
--- a/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
+++ b/third_party/jpeg-xl/lib/jpegli/libjpeg_test_util.cc
@@ -5,12 +5,7 @@
#include "lib/jpegli/libjpeg_test_util.h"
-/* clang-format off */
-#include <stdio.h>
-#include <jpeglib.h>
-#include <setjmp.h>
-/* clang-format on */
-
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
#include "lib/jxl/sanitizers.h"
namespace jpegli {
diff --git a/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc b/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
index 3cb2fd3ee4..44d63fdcbb 100644
--- a/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/output_suspension_test.cc
@@ -3,7 +3,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
@@ -130,6 +141,7 @@ TEST_P(OutputSuspensionTestParam, RawData) {
cinfo.input_components = input.components;
cinfo.in_color_space = JCS_YCbCr;
jpegli_set_defaults(&cinfo);
+ cinfo.comp_info[0].h_samp_factor = config.jparams.h_sampling[0];
cinfo.comp_info[0].v_samp_factor = config.jparams.v_sampling[0];
jpegli_set_progressive_level(&cinfo, 0);
cinfo.optimize_coding = FALSE;
diff --git a/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc b/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
index a513b7063b..2d49ac16ba 100644
--- a/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/source_manager_test.cc
@@ -3,14 +3,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include <cmath>
#include <cstdint>
#include <vector>
#include "lib/jpegli/decode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
-#include "lib/jxl/base/status.h"
namespace jpegli {
namespace {
diff --git a/third_party/jpeg-xl/lib/jpegli/streaming_test.cc b/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
index 1f19dc2045..29a224385f 100644
--- a/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/streaming_test.cc
@@ -3,8 +3,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
diff --git a/third_party/jpeg-xl/lib/jpegli/test_utils.cc b/third_party/jpeg-xl/lib/jpegli/test_utils.cc
index db5a30e8dc..5315c692a1 100644
--- a/third_party/jpeg-xl/lib/jpegli/test_utils.cc
+++ b/third_party/jpeg-xl/lib/jpegli/test_utils.cc
@@ -8,6 +8,7 @@
#include <cmath>
#include <cstdint>
#include <fstream>
+#include <sstream>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
@@ -171,6 +172,18 @@ std::string ColorSpaceName(J_COLOR_SPACE colorspace) {
return "CMYK";
case JCS_YCCK:
return "YCCK";
+ case JCS_EXT_RGB:
+ return "EXT_RGB";
+ case JCS_EXT_BGR:
+ return "EXT_BGR";
+ case JCS_EXT_RGBA:
+ return "EXT_RGBA";
+ case JCS_EXT_BGRA:
+ return "EXT_BGRA";
+ case JCS_EXT_ARGB:
+ return "EXT_ARGB";
+ case JCS_EXT_ABGR:
+ return "EXT_ABGR";
default:
return "";
}
@@ -301,9 +314,12 @@ std::ostream& operator<<(std::ostream& os, const CompressParams& jparams) {
void SetNumChannels(J_COLOR_SPACE colorspace, size_t* channels) {
if (colorspace == JCS_GRAYSCALE) {
*channels = 1;
- } else if (colorspace == JCS_RGB || colorspace == JCS_YCbCr) {
+ } else if (colorspace == JCS_RGB || colorspace == JCS_YCbCr ||
+ colorspace == JCS_EXT_RGB || colorspace == JCS_EXT_BGR) {
*channels = 3;
- } else if (colorspace == JCS_CMYK || colorspace == JCS_YCCK) {
+ } else if (colorspace == JCS_CMYK || colorspace == JCS_YCCK ||
+ colorspace == JCS_EXT_RGBA || colorspace == JCS_EXT_BGRA ||
+ colorspace == JCS_EXT_ARGB || colorspace == JCS_EXT_ABGR) {
*channels = 4;
} else if (colorspace == JCS_UNKNOWN) {
JXL_CHECK(*channels <= 4);
@@ -330,7 +346,28 @@ void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
if (colorspace == JCS_GRAYSCALE) {
const float Y = 0.299f * r + 0.587f * g + 0.114f * b;
out8[0] = static_cast<uint8_t>(std::round(Y * kMul));
- } else if (colorspace == JCS_RGB || colorspace == JCS_UNKNOWN) {
+ } else if (colorspace == JCS_RGB || colorspace == JCS_EXT_RGB ||
+ colorspace == JCS_EXT_RGBA) {
+ out8[0] = input_rgb[0];
+ out8[1] = input_rgb[1];
+ out8[2] = input_rgb[2];
+ if (colorspace == JCS_EXT_RGBA) out8[3] = 255;
+ } else if (colorspace == JCS_EXT_BGR || colorspace == JCS_EXT_BGRA) {
+ out8[2] = input_rgb[0];
+ out8[1] = input_rgb[1];
+ out8[0] = input_rgb[2];
+ if (colorspace == JCS_EXT_BGRA) out8[3] = 255;
+ } else if (colorspace == JCS_EXT_ABGR) {
+ out8[0] = 255;
+ out8[3] = input_rgb[0];
+ out8[2] = input_rgb[1];
+ out8[1] = input_rgb[2];
+ } else if (colorspace == JCS_EXT_ARGB) {
+ out8[0] = 255;
+ out8[1] = input_rgb[0];
+ out8[2] = input_rgb[1];
+ out8[3] = input_rgb[2];
+ } else if (colorspace == JCS_UNKNOWN) {
for (size_t c = 0; c < num_channels; ++c) {
out8[c] = input_rgb[std::min<size_t>(2, c)];
}
@@ -390,9 +427,23 @@ void ConvertPixel(const uint8_t* input_rgb, uint8_t* out,
void ConvertToGrayscale(TestImage* img) {
if (img->color_space == JCS_GRAYSCALE) return;
JXL_CHECK(img->data_type == JPEGLI_TYPE_UINT8);
- for (size_t i = 0; i < img->pixels.size(); i += 3) {
- if (img->color_space == JCS_RGB) {
- ConvertPixel(&img->pixels[i], &img->pixels[i / 3], JCS_GRAYSCALE, 1);
+ bool rgb_pre_alpha =
+ img->color_space == JCS_EXT_ARGB || img->color_space == JCS_EXT_ABGR;
+ bool rgb_post_alpha =
+ img->color_space == JCS_EXT_RGBA || img->color_space == JCS_EXT_BGRA;
+ bool rgb_alpha = rgb_pre_alpha || rgb_post_alpha;
+ bool is_rgb = img->color_space == JCS_RGB ||
+ img->color_space == JCS_EXT_RGB ||
+ img->color_space == JCS_EXT_BGR || rgb_alpha;
+ bool switch_br = img->color_space == JCS_EXT_BGR ||
+ img->color_space == JCS_EXT_ABGR ||
+ img->color_space == JCS_EXT_BGRA;
+ size_t stride = rgb_alpha ? 4 : 3;
+ size_t offset = rgb_pre_alpha ? 1 : 0;
+ for (size_t i = offset; i < img->pixels.size(); i += stride) {
+ if (is_rgb) {
+ if (switch_br) std::swap(img->pixels[i], img->pixels[i + 2]);
+ ConvertPixel(&img->pixels[i], &img->pixels[i / stride], JCS_GRAYSCALE, 1);
} else if (img->color_space == JCS_YCbCr) {
img->pixels[i / 3] = img->pixels[i];
}
diff --git a/third_party/jpeg-xl/lib/jpegli/test_utils.h b/third_party/jpeg-xl/lib/jpegli/test_utils.h
index 132cfd042a..22c620c46c 100644
--- a/third_party/jpeg-xl/lib/jpegli/test_utils.h
+++ b/third_party/jpeg-xl/lib/jpegli/test_utils.h
@@ -6,22 +6,15 @@
#ifndef LIB_JPEGLI_TEST_UTILS_H_
#define LIB_JPEGLI_TEST_UTILS_H_
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
+#include <cstddef>
+#include <cstdint>
#include <string>
#include <vector>
-/* clang-format off */
-#include <stdio.h>
-#include <jpeglib.h>
-#include <setjmp.h>
-/* clang-format on */
-
-#include "lib/jpegli/common.h"
-#include "lib/jpegli/libjpeg_test_util.h"
#include "lib/jpegli/test_params.h"
+#include "lib/jpegli/types.h"
+#include "lib/jxl/base/compiler_specific.h"
+#include "lib/jxl/base/include_jpeglib.h" // NOLINT
namespace jpegli {
@@ -127,4 +120,15 @@ void VerifyOutputImage(const TestImage& input, const TestImage& output,
} // namespace jpegli
+#if !defined(FUZZ_TEST)
+struct FuzzTestSink {
+ template <typename F>
+ FuzzTestSink WithSeeds(F) {
+ return *this;
+ }
+};
+#define FUZZ_TEST(A, B) \
+ const JXL_MAYBE_UNUSED FuzzTestSink unused##A##B = FuzzTestSink()
+#endif
+
#endif // LIB_JPEGLI_TEST_UTILS_H_
diff --git a/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
index 13c81a1119..413d5ae996 100644
--- a/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
+++ b/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
@@ -3,10 +3,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <ostream>
+#include <sstream>
+#include <string>
#include <vector>
#include "lib/jpegli/decode.h"
#include "lib/jpegli/encode.h"
+#include "lib/jpegli/libjpeg_test_util.h"
+#include "lib/jpegli/test_params.h"
#include "lib/jpegli/test_utils.h"
#include "lib/jpegli/testing.h"
#include "lib/jxl/base/status.h"