summaryrefslogtreecommitdiffstats
path: root/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc')
-rw-r--r--third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc133
1 files changed, 133 insertions, 0 deletions
diff --git a/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc b/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
new file mode 100644
index 0000000000..1d99ce37fa
--- /dev/null
+++ b/third_party/jpeg-xl/lib/jpegli/transcode_api_test.cc
@@ -0,0 +1,133 @@
+// Copyright (c) the JPEG XL Project Authors. All rights reserved.
+//
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include <vector>
+
+#include "lib/jpegli/decode.h"
+#include "lib/jpegli/encode.h"
+#include "lib/jpegli/test_utils.h"
+#include "lib/jpegli/testing.h"
+#include "lib/jxl/base/status.h"
+
+namespace jpegli {
+namespace {
+
+void TranscodeWithJpegli(const std::vector<uint8_t>& jpeg_input,
+ const CompressParams& jparams,
+ std::vector<uint8_t>* jpeg_output) {
+ jpeg_decompress_struct dinfo = {};
+ jpeg_compress_struct cinfo = {};
+ uint8_t* transcoded_data = nullptr;
+ unsigned long transcoded_size;
+ const auto try_catch_block = [&]() -> bool {
+ ERROR_HANDLER_SETUP(jpegli);
+ dinfo.err = cinfo.err;
+ dinfo.client_data = cinfo.client_data;
+ jpegli_create_decompress(&dinfo);
+ jpegli_mem_src(&dinfo, jpeg_input.data(), jpeg_input.size());
+ EXPECT_EQ(JPEG_REACHED_SOS,
+ jpegli_read_header(&dinfo, /*require_image=*/TRUE));
+ jvirt_barray_ptr* coef_arrays = jpegli_read_coefficients(&dinfo);
+ JXL_CHECK(coef_arrays != nullptr);
+ jpegli_create_compress(&cinfo);
+ jpegli_mem_dest(&cinfo, &transcoded_data, &transcoded_size);
+ jpegli_copy_critical_parameters(&dinfo, &cinfo);
+ jpegli_set_progressive_level(&cinfo, jparams.progressive_mode);
+ cinfo.optimize_coding = jparams.optimize_coding;
+ jpegli_write_coefficients(&cinfo, coef_arrays);
+ jpegli_finish_compress(&cinfo);
+ jpegli_finish_decompress(&dinfo);
+ return true;
+ };
+ ASSERT_TRUE(try_catch_block());
+ jpegli_destroy_decompress(&dinfo);
+ jpegli_destroy_compress(&cinfo);
+ if (transcoded_data) {
+ jpeg_output->assign(transcoded_data, transcoded_data + transcoded_size);
+ free(transcoded_data);
+ }
+}
+
+struct TestConfig {
+ TestImage input;
+ CompressParams jparams;
+};
+
+class TranscodeAPITestParam : public ::testing::TestWithParam<TestConfig> {};
+
+TEST_P(TranscodeAPITestParam, TestAPI) {
+ TestConfig config = GetParam();
+ CompressParams& jparams = config.jparams;
+ GeneratePixels(&config.input);
+
+ // Start with sequential non-optimized jpeg.
+ jparams.progressive_mode = 0;
+ jparams.optimize_coding = 0;
+ std::vector<uint8_t> compressed;
+ ASSERT_TRUE(EncodeWithJpegli(config.input, jparams, &compressed));
+ TestImage output0;
+ DecodeWithLibjpeg(jparams, DecompressParams(), compressed, &output0);
+
+ // Transcode first to a sequential optimized jpeg, and then further to
+ // a progressive jpeg.
+ for (int progr : {0, 2}) {
+ std::vector<uint8_t> transcoded;
+ jparams.progressive_mode = progr;
+ jparams.optimize_coding = 1;
+ TranscodeWithJpegli(compressed, jparams, &transcoded);
+
+ // We expect a size reduction of at least 2%.
+ EXPECT_LT(transcoded.size(), compressed.size() * 0.98f);
+
+ // Verify that transcoding is lossless.
+ TestImage output1;
+ DecodeWithLibjpeg(jparams, DecompressParams(), transcoded, &output1);
+ ASSERT_EQ(output0.pixels.size(), output1.pixels.size());
+ EXPECT_EQ(0, memcmp(output0.pixels.data(), output1.pixels.data(),
+ output0.pixels.size()));
+ compressed = transcoded;
+ }
+}
+
+std::vector<TestConfig> GenerateTests() {
+ std::vector<TestConfig> all_tests;
+ const size_t xsize0 = 1024;
+ const size_t ysize0 = 768;
+ for (int dxsize : {0, 1, 8, 9}) {
+ for (int dysize : {0, 1, 8, 9}) {
+ for (int h_sampling : {1, 2}) {
+ for (int v_sampling : {1, 2}) {
+ TestConfig config;
+ config.input.xsize = xsize0 + dxsize;
+ config.input.ysize = ysize0 + dysize;
+ config.jparams.h_sampling = {h_sampling, 1, 1};
+ config.jparams.v_sampling = {v_sampling, 1, 1};
+ all_tests.push_back(config);
+ }
+ }
+ }
+ }
+ return all_tests;
+}
+
+std::ostream& operator<<(std::ostream& os, const TestConfig& c) {
+ os << c.input;
+ os << c.jparams;
+ return os;
+}
+
+std::string TestDescription(
+ const testing::TestParamInfo<TranscodeAPITestParam::ParamType>& info) {
+ std::stringstream name;
+ name << info.param;
+ return name.str();
+}
+
+JPEGLI_INSTANTIATE_TEST_SUITE_P(TranscodeAPITest, TranscodeAPITestParam,
+ testing::ValuesIn(GenerateTests()),
+ TestDescription);
+
+} // namespace
+} // namespace jpegli