source_manager_test.cc (4628B)
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 <cstdio> 9 #include <ostream> 10 #include <sstream> 11 #include <string> 12 #include <utility> 13 #include <vector> 14 15 #include "lib/jpegli/decode.h" 16 #include "lib/jpegli/libjpeg_test_util.h" 17 #include "lib/jpegli/test_params.h" 18 #include "lib/jpegli/test_utils.h" 19 #include "lib/jpegli/testing.h" 20 #include "lib/jxl/base/status.h" 21 22 namespace jpegli { 23 namespace { 24 25 void ReadOutputImage(j_decompress_ptr cinfo, TestImage* output) { 26 jpegli_read_header(cinfo, /*require_image=*/TRUE); 27 jpegli_start_decompress(cinfo); 28 output->ysize = cinfo->output_height; 29 output->xsize = cinfo->output_width; 30 output->components = cinfo->num_components; 31 output->AllocatePixels(); 32 size_t stride = cinfo->output_width * cinfo->num_components; 33 while (cinfo->output_scanline < cinfo->output_height) { 34 JSAMPROW scanline = &output->pixels[cinfo->output_scanline * stride]; 35 jpegli_read_scanlines(cinfo, &scanline, 1); 36 } 37 jpegli_finish_decompress(cinfo); 38 } 39 40 struct TestConfig { 41 std::string fn; 42 std::string fn_desc; 43 DecompressParams dparams; 44 }; 45 46 class SourceManagerTestParam : public ::testing::TestWithParam<TestConfig> {}; 47 48 namespace { 49 FILE* MemOpen(const std::vector<uint8_t>& data) { 50 FILE* src = tmpfile(); 51 if (!src) return nullptr; 52 fwrite(data.data(), 1, data.size(), src); 53 fseek(src, 0, SEEK_SET); 54 return src; 55 } 56 } // namespace 57 58 TEST_P(SourceManagerTestParam, TestStdioSourceManager) { 59 TestConfig config = GetParam(); 60 JXL_ASSIGN_OR_QUIT(std::vector<uint8_t> compressed, ReadTestData(config.fn), 61 "Failed to read test data."); 62 if (config.dparams.size_factor < 1.0) { 63 compressed.resize(compressed.size() * config.dparams.size_factor); 64 } 65 FILE* src = MemOpen(compressed); 66 ASSERT_TRUE(src); 67 TestImage output0; 68 jpeg_decompress_struct cinfo; 69 const auto try_catch_block = [&]() -> bool { 70 ERROR_HANDLER_SETUP(jpegli); 71 jpegli_create_decompress(&cinfo); 72 jpegli_stdio_src(&cinfo, src); 73 ReadOutputImage(&cinfo, &output0); 74 return true; 75 }; 76 bool ok = try_catch_block(); 77 fclose(src); 78 ASSERT_TRUE(ok); 79 jpegli_destroy_decompress(&cinfo); 80 81 TestImage output1; 82 DecodeWithLibjpeg(CompressParams(), DecompressParams(), compressed, &output1); 83 VerifyOutputImage(output1, output0, 1.0f); 84 } 85 86 TEST_P(SourceManagerTestParam, TestMemSourceManager) { 87 TestConfig config = GetParam(); 88 JXL_ASSIGN_OR_QUIT(std::vector<uint8_t> compressed, ReadTestData(config.fn), 89 "Failed to read test data."); 90 if (config.dparams.size_factor < 1.0f) { 91 compressed.resize(compressed.size() * config.dparams.size_factor); 92 } 93 TestImage output0; 94 jpeg_decompress_struct cinfo; 95 const auto try_catch_block = [&]() -> bool { 96 ERROR_HANDLER_SETUP(jpegli); 97 jpegli_create_decompress(&cinfo); 98 jpegli_mem_src(&cinfo, compressed.data(), compressed.size()); 99 ReadOutputImage(&cinfo, &output0); 100 return true; 101 }; 102 ASSERT_TRUE(try_catch_block()); 103 jpegli_destroy_decompress(&cinfo); 104 105 TestImage output1; 106 DecodeWithLibjpeg(CompressParams(), DecompressParams(), compressed, &output1); 107 VerifyOutputImage(output1, output0, 1.0f); 108 } 109 110 std::vector<TestConfig> GenerateTests() { 111 std::vector<TestConfig> all_tests; 112 { 113 std::vector<std::pair<std::string, std::string>> testfiles({ 114 {"jxl/flower/flower.png.im_q85_444.jpg", "Q85YUV444"}, 115 {"jxl/flower/flower.png.im_q85_420.jpg", "Q85YUV420"}, 116 {"jxl/flower/flower.png.im_q85_420_R13B.jpg", "Q85YUV420R13B"}, 117 }); 118 for (const auto& it : testfiles) { 119 for (float size_factor : {0.1f, 0.33f, 0.5f, 0.75f}) { 120 TestConfig config; 121 config.fn = it.first; 122 config.fn_desc = it.second; 123 config.dparams.size_factor = size_factor; 124 all_tests.push_back(config); 125 } 126 } 127 return all_tests; 128 } 129 } 130 131 std::ostream& operator<<(std::ostream& os, const TestConfig& c) { 132 os << c.fn_desc; 133 if (c.dparams.size_factor < 1.0f) { 134 os << "Partial" << static_cast<int>(c.dparams.size_factor * 100) << "p"; 135 } 136 return os; 137 } 138 139 std::string TestDescription( 140 const testing::TestParamInfo<SourceManagerTestParam::ParamType>& info) { 141 std::stringstream name; 142 name << info.param; 143 return name.str(); 144 } 145 146 JPEGLI_INSTANTIATE_TEST_SUITE_P(SourceManagerTest, SourceManagerTestParam, 147 testing::ValuesIn(GenerateTests()), 148 TestDescription); 149 150 } // namespace 151 } // namespace jpegli