gain_map_test.cc (6467B)
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 "jxl/gain_map.h" 7 8 #include <jxl/color_encoding.h> 9 #include <jxl/encode.h> 10 #include <jxl/types.h> 11 12 #include <algorithm> 13 #include <cstddef> 14 #include <cstdint> 15 #include <cstring> 16 #include <string> 17 #include <vector> 18 19 #include "lib/jxl/test_utils.h" 20 #include "lib/jxl/testing.h" 21 22 namespace { 23 24 std::vector<uint8_t> GoldenTestGainMap(bool has_icc, bool has_color_encoding) { 25 // Define the parts of the gain map 26 uint8_t jhgm_version = 0x00; 27 std::vector<uint8_t> gain_map_metadata_size = {0x00, 0x58}; // 88 in decimal 28 // TODO(firsching): Replace with more realistic data 29 std::string first_placeholder = 30 "placeholder gain map metadata, fill with actual example after (ISO " 31 "21496-1) is finalized"; 32 33 uint8_t color_encoding_size = has_color_encoding ? 3 : 0; 34 std::vector<uint8_t> color_encoding = {0x50, 0xb4, 0x00}; 35 36 std::vector<uint8_t> icc_size = {0x00, 0x00, 0x00, 0x00}; 37 if (has_icc) { 38 icc_size = {0x00, 0x00, 0x00, 0x88}; // 136 in decimal 39 } 40 std::vector<uint8_t> icc_data = jxl::test::GetCompressedIccTestProfile(); 41 std::string second_placeholder = 42 "placeholder for an actual naked JPEG XL codestream"; 43 44 // Assemble the gain map 45 std::vector<uint8_t> gain_map; 46 gain_map.push_back(jhgm_version); 47 gain_map.insert(gain_map.end(), gain_map_metadata_size.begin(), 48 gain_map_metadata_size.end()); 49 gain_map.insert(gain_map.end(), first_placeholder.begin(), 50 first_placeholder.end()); 51 gain_map.push_back(color_encoding_size); 52 if (has_color_encoding) { 53 gain_map.insert(gain_map.end(), color_encoding.begin(), 54 color_encoding.end()); 55 } 56 gain_map.insert(gain_map.end(), icc_size.begin(), icc_size.end()); 57 if (has_icc) { 58 gain_map.insert(gain_map.end(), icc_data.begin(), icc_data.end()); 59 } 60 gain_map.insert(gain_map.end(), second_placeholder.begin(), 61 second_placeholder.end()); 62 63 return gain_map; 64 } 65 66 } // namespace 67 68 namespace jxl { 69 namespace { 70 71 struct GainMapTestParams { 72 bool has_color_encoding; 73 std::vector<uint8_t> icc_data; 74 }; 75 76 class GainMapTest : public ::testing::TestWithParam<GainMapTestParams> {}; 77 78 TEST_P(GainMapTest, GainMapRoundtrip) { 79 size_t bundle_size; 80 const GainMapTestParams& params = GetParam(); 81 std::vector<uint8_t> golden_gain_map = 82 GoldenTestGainMap(!params.icc_data.empty(), params.has_color_encoding); 83 84 JxlGainMapBundle orig_bundle; 85 // Initialize the bundle with some test data 86 orig_bundle.jhgm_version = 0; 87 const char* metadata_str = 88 "placeholder gain map metadata, fill with actual example after (ISO " 89 "21496-1) is finalized"; 90 std::vector<uint8_t> gain_map_metadata(metadata_str, 91 metadata_str + strlen(metadata_str)); 92 orig_bundle.gain_map_metadata_size = gain_map_metadata.size(); 93 orig_bundle.gain_map_metadata = gain_map_metadata.data(); 94 95 // Use the ICC profile from the parameter 96 orig_bundle.has_color_encoding = TO_JXL_BOOL(params.has_color_encoding); 97 if (orig_bundle.has_color_encoding) { 98 JxlColorEncoding color_encoding = {}; 99 JxlColorEncodingSetToLinearSRGB(&color_encoding, /*is_gray=*/JXL_FALSE); 100 orig_bundle.color_encoding = color_encoding; 101 } 102 103 std::vector<uint8_t> alt_icc(params.icc_data.begin(), params.icc_data.end()); 104 orig_bundle.alt_icc = alt_icc.data(); 105 orig_bundle.alt_icc_size = alt_icc.size(); 106 107 const char* gain_map_str = 108 "placeholder for an actual naked JPEG XL codestream"; 109 std::vector<uint8_t> gain_map(gain_map_str, 110 gain_map_str + strlen(gain_map_str)); 111 orig_bundle.gain_map_size = gain_map.size(); 112 orig_bundle.gain_map = gain_map.data(); 113 114 ASSERT_TRUE(JxlGainMapGetBundleSize(&orig_bundle, &bundle_size)); 115 EXPECT_EQ(bundle_size, golden_gain_map.size()); 116 117 std::vector<uint8_t> buffer(bundle_size); 118 size_t bytes_written; 119 ASSERT_TRUE(JxlGainMapWriteBundle(&orig_bundle, buffer.data(), buffer.size(), 120 &bytes_written)); 121 EXPECT_EQ(bytes_written, bundle_size); 122 EXPECT_EQ(buffer[0], orig_bundle.jhgm_version); 123 EXPECT_EQ(buffer.size(), golden_gain_map.size()); 124 EXPECT_TRUE( 125 std::equal(buffer.begin(), buffer.end(), golden_gain_map.begin())); 126 127 JxlGainMapBundle output_bundle; 128 size_t bytes_read; 129 ASSERT_TRUE(JxlGainMapReadBundle(&output_bundle, buffer.data(), buffer.size(), 130 &bytes_read)); 131 132 EXPECT_EQ(output_bundle.gain_map_size, orig_bundle.gain_map_size); 133 EXPECT_EQ(output_bundle.gain_map_metadata_size, 134 orig_bundle.gain_map_metadata_size); 135 EXPECT_EQ(output_bundle.alt_icc_size, orig_bundle.alt_icc_size); 136 EXPECT_EQ(output_bundle.has_color_encoding, params.has_color_encoding); 137 EXPECT_EQ(output_bundle.jhgm_version, orig_bundle.jhgm_version); 138 std::vector<uint8_t> output_gain_map_metadata( 139 output_bundle.gain_map_metadata, 140 output_bundle.gain_map_metadata + output_bundle.gain_map_metadata_size); 141 std::vector<uint8_t> output_alt_icc( 142 output_bundle.alt_icc, 143 output_bundle.alt_icc + output_bundle.alt_icc_size); 144 std::vector<uint8_t> output_gain_map( 145 output_bundle.gain_map, 146 output_bundle.gain_map + output_bundle.gain_map_size); 147 EXPECT_TRUE(std::equal(output_gain_map_metadata.begin(), 148 output_gain_map_metadata.end(), 149 gain_map_metadata.begin())); 150 EXPECT_TRUE(std::equal(output_alt_icc.begin(), output_alt_icc.end(), 151 alt_icc.begin())); 152 EXPECT_TRUE(std::equal(output_gain_map.begin(), output_gain_map.end(), 153 gain_map.begin())); 154 } 155 156 JXL_GTEST_INSTANTIATE_TEST_SUITE_P( 157 GainMapTestCases, GainMapTest, 158 ::testing::Values( 159 GainMapTestParams{true, std::vector<uint8_t>()}, 160 GainMapTestParams{true, test::GetCompressedIccTestProfile()}, 161 GainMapTestParams{false, test::GetCompressedIccTestProfile()}, 162 GainMapTestParams{false, std::vector<uint8_t>()}), 163 [](const testing::TestParamInfo<GainMapTest::ParamType>& info) { 164 std::string name = 165 "HasColorEncoding" + std::to_string(info.param.has_color_encoding); 166 167 name += "ICCSize" + std::to_string(info.param.icc_data.size()); 168 169 return name; 170 }); 171 172 } // namespace 173 } // namespace jxl