tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

transcode_api_test.cc (4564B)


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