libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

transcode_api_test.cc (4362B)


      1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file.
      5 
      6 #include <vector>
      7 
      8 #include "lib/jpegli/decode.h"
      9 #include "lib/jpegli/encode.h"
     10 #include "lib/jpegli/test_utils.h"
     11 #include "lib/jpegli/testing.h"
     12 #include "lib/jxl/base/status.h"
     13 
     14 namespace jpegli {
     15 namespace {
     16 
     17 void TranscodeWithJpegli(const std::vector<uint8_t>& jpeg_input,
     18                          const CompressParams& jparams,
     19                          std::vector<uint8_t>* jpeg_output) {
     20   jpeg_decompress_struct dinfo = {};
     21   jpeg_compress_struct cinfo = {};
     22   uint8_t* transcoded_data = nullptr;
     23   unsigned long transcoded_size;
     24   const auto try_catch_block = [&]() -> bool {
     25     ERROR_HANDLER_SETUP(jpegli);
     26     dinfo.err = cinfo.err;
     27     dinfo.client_data = cinfo.client_data;
     28     jpegli_create_decompress(&dinfo);
     29     jpegli_mem_src(&dinfo, jpeg_input.data(), jpeg_input.size());
     30     EXPECT_EQ(JPEG_REACHED_SOS,
     31               jpegli_read_header(&dinfo, /*require_image=*/TRUE));
     32     jvirt_barray_ptr* coef_arrays = jpegli_read_coefficients(&dinfo);
     33     JXL_CHECK(coef_arrays != nullptr);
     34     jpegli_create_compress(&cinfo);
     35     jpegli_mem_dest(&cinfo, &transcoded_data, &transcoded_size);
     36     jpegli_copy_critical_parameters(&dinfo, &cinfo);
     37     jpegli_set_progressive_level(&cinfo, jparams.progressive_mode);
     38     cinfo.optimize_coding = jparams.optimize_coding;
     39     jpegli_write_coefficients(&cinfo, coef_arrays);
     40     jpegli_finish_compress(&cinfo);
     41     jpegli_finish_decompress(&dinfo);
     42     return true;
     43   };
     44   ASSERT_TRUE(try_catch_block());
     45   jpegli_destroy_decompress(&dinfo);
     46   jpegli_destroy_compress(&cinfo);
     47   if (transcoded_data) {
     48     jpeg_output->assign(transcoded_data, transcoded_data + transcoded_size);
     49     free(transcoded_data);
     50   }
     51 }
     52 
     53 struct TestConfig {
     54   TestImage input;
     55   CompressParams jparams;
     56 };
     57 
     58 class TranscodeAPITestParam : public ::testing::TestWithParam<TestConfig> {};
     59 
     60 TEST_P(TranscodeAPITestParam, TestAPI) {
     61   TestConfig config = GetParam();
     62   CompressParams& jparams = config.jparams;
     63   GeneratePixels(&config.input);
     64 
     65   // Start with sequential non-optimized jpeg.
     66   jparams.progressive_mode = 0;
     67   jparams.optimize_coding = 0;
     68   std::vector<uint8_t> compressed;
     69   ASSERT_TRUE(EncodeWithJpegli(config.input, jparams, &compressed));
     70   TestImage output0;
     71   DecodeWithLibjpeg(jparams, DecompressParams(), compressed, &output0);
     72 
     73   // Transcode first to a sequential optimized jpeg, and then further to
     74   // a progressive jpeg.
     75   for (int progr : {0, 2}) {
     76     std::vector<uint8_t> transcoded;
     77     jparams.progressive_mode = progr;
     78     jparams.optimize_coding = 1;
     79     TranscodeWithJpegli(compressed, jparams, &transcoded);
     80 
     81     // We expect a size reduction of at least 2%.
     82     EXPECT_LT(transcoded.size(), compressed.size() * 0.98f);
     83 
     84     // Verify that transcoding is lossless.
     85     TestImage output1;
     86     DecodeWithLibjpeg(jparams, DecompressParams(), transcoded, &output1);
     87     ASSERT_EQ(output0.pixels.size(), output1.pixels.size());
     88     EXPECT_EQ(0, memcmp(output0.pixels.data(), output1.pixels.data(),
     89                         output0.pixels.size()));
     90     compressed = transcoded;
     91   }
     92 }
     93 
     94 std::vector<TestConfig> GenerateTests() {
     95   std::vector<TestConfig> all_tests;
     96   const size_t xsize0 = 1024;
     97   const size_t ysize0 = 768;
     98   for (int dxsize : {0, 1, 8, 9}) {
     99     for (int dysize : {0, 1, 8, 9}) {
    100       for (int h_sampling : {1, 2}) {
    101         for (int v_sampling : {1, 2}) {
    102           TestConfig config;
    103           config.input.xsize = xsize0 + dxsize;
    104           config.input.ysize = ysize0 + dysize;
    105           config.jparams.h_sampling = {h_sampling, 1, 1};
    106           config.jparams.v_sampling = {v_sampling, 1, 1};
    107           all_tests.push_back(config);
    108         }
    109       }
    110     }
    111   }
    112   return all_tests;
    113 }
    114 
    115 std::ostream& operator<<(std::ostream& os, const TestConfig& c) {
    116   os << c.input;
    117   os << c.jparams;
    118   return os;
    119 }
    120 
    121 std::string TestDescription(
    122     const testing::TestParamInfo<TranscodeAPITestParam::ParamType>& info) {
    123   std::stringstream name;
    124   name << info.param;
    125   return name.str();
    126 }
    127 
    128 JPEGLI_INSTANTIATE_TEST_SUITE_P(TranscodeAPITest, TranscodeAPITestParam,
    129                                 testing::ValuesIn(GenerateTests()),
    130                                 TestDescription);
    131 
    132 }  // namespace
    133 }  // namespace jpegli