/src/libjxl/lib/jxl/cms/jxl_cms_internal.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef LIB_JXL_CMS_JXL_CMS_INTERNAL_H_ |
7 | | #define LIB_JXL_CMS_JXL_CMS_INTERNAL_H_ |
8 | | |
9 | | // ICC profiles and color space conversions. |
10 | | |
11 | | #include <jxl/color_encoding.h> |
12 | | |
13 | | #include <algorithm> |
14 | | #include <cmath> |
15 | | #include <cstddef> |
16 | | #include <cstdint> |
17 | | #include <cstring> |
18 | | #include <string> |
19 | | #include <vector> |
20 | | |
21 | | #include "lib/jxl/base/common.h" |
22 | | #include "lib/jxl/base/compiler_specific.h" |
23 | | #include "lib/jxl/base/matrix_ops.h" |
24 | | #include "lib/jxl/base/span.h" // Bytes |
25 | | #include "lib/jxl/base/status.h" |
26 | | #include "lib/jxl/cms/opsin_params.h" |
27 | | #include "lib/jxl/cms/tone_mapping.h" |
28 | | #include "lib/jxl/cms/transfer_functions.h" |
29 | | |
30 | | #ifndef JXL_ENABLE_3D_ICC_TONEMAPPING |
31 | | #define JXL_ENABLE_3D_ICC_TONEMAPPING 1 |
32 | | #endif |
33 | | |
34 | | namespace jxl { |
35 | | |
36 | | enum class ExtraTF { |
37 | | kNone, |
38 | | kPQ, |
39 | | kHLG, |
40 | | kSRGB, |
41 | | }; |
42 | | |
43 | | static Status PrimariesToXYZ(float rx, float ry, float gx, float gy, float bx, |
44 | 8.72k | float by, float wx, float wy, Matrix3x3& matrix) { |
45 | 8.72k | bool ok = (wx >= 0) && (wx <= 1) && (wy > 0) && (wy <= 1); |
46 | 8.72k | if (!ok) { |
47 | 0 | return JXL_FAILURE("Invalid white point"); |
48 | 0 | } |
49 | | // TODO(lode): also require rx, ry, gx, gy, bx, to be in range 0-1? ICC |
50 | | // profiles in theory forbid negative XYZ values, but in practice the ACES P0 |
51 | | // color space uses a negative y for the blue primary. |
52 | 8.72k | Matrix3x3 primaries{{{rx, gx, bx}, |
53 | 8.72k | {ry, gy, by}, |
54 | 8.72k | {1.0f - rx - ry, 1.0f - gx - gy, 1.0f - bx - by}}}; |
55 | 8.72k | Matrix3x3 primaries_inv; |
56 | 8.72k | primaries_inv = primaries; |
57 | 8.72k | JXL_RETURN_IF_ERROR(Inv3x3Matrix(primaries_inv)); |
58 | | |
59 | 8.72k | Vector3 w{wx / wy, 1.0f, (1.0f - wx - wy) / wy}; |
60 | | // 1 / tiny float can still overflow |
61 | 8.72k | JXL_RETURN_IF_ERROR(std::isfinite(w[0]) && std::isfinite(w[2])); |
62 | 8.72k | Vector3 xyz; |
63 | 8.72k | Mul3x3Vector(primaries_inv, w, xyz); |
64 | | |
65 | 8.72k | Matrix3x3 a{{{xyz[0], 0, 0}, {0, xyz[1], 0}, {0, 0, xyz[2]}}}; |
66 | | |
67 | 8.72k | Mul3x3Matrix(primaries, a, matrix); |
68 | 8.72k | return true; |
69 | 8.72k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::PrimariesToXYZ(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) color_encoding_internal.cc:jxl::PrimariesToXYZ(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Line | Count | Source | 44 | 8.72k | float by, float wx, float wy, Matrix3x3& matrix) { | 45 | 8.72k | bool ok = (wx >= 0) && (wx <= 1) && (wy > 0) && (wy <= 1); | 46 | 8.72k | if (!ok) { | 47 | 0 | return JXL_FAILURE("Invalid white point"); | 48 | 0 | } | 49 | | // TODO(lode): also require rx, ry, gx, gy, bx, to be in range 0-1? ICC | 50 | | // profiles in theory forbid negative XYZ values, but in practice the ACES P0 | 51 | | // color space uses a negative y for the blue primary. | 52 | 8.72k | Matrix3x3 primaries{{{rx, gx, bx}, | 53 | 8.72k | {ry, gy, by}, | 54 | 8.72k | {1.0f - rx - ry, 1.0f - gx - gy, 1.0f - bx - by}}}; | 55 | 8.72k | Matrix3x3 primaries_inv; | 56 | 8.72k | primaries_inv = primaries; | 57 | 8.72k | JXL_RETURN_IF_ERROR(Inv3x3Matrix(primaries_inv)); | 58 | | | 59 | 8.72k | Vector3 w{wx / wy, 1.0f, (1.0f - wx - wy) / wy}; | 60 | | // 1 / tiny float can still overflow | 61 | 8.72k | JXL_RETURN_IF_ERROR(std::isfinite(w[0]) && std::isfinite(w[2])); | 62 | 8.72k | Vector3 xyz; | 63 | 8.72k | Mul3x3Vector(primaries_inv, w, xyz); | 64 | | | 65 | 8.72k | Matrix3x3 a{{{xyz[0], 0, 0}, {0, xyz[1], 0}, {0, 0, xyz[2]}}}; | 66 | | | 67 | 8.72k | Mul3x3Matrix(primaries, a, matrix); | 68 | 8.72k | return true; | 69 | 8.72k | } |
Unexecuted instantiation: frame_header.cc:jxl::PrimariesToXYZ(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Unexecuted instantiation: image_metadata.cc:jxl::PrimariesToXYZ(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) |
70 | | |
71 | | /* Chromatic adaptation matrices*/ |
72 | | constexpr Matrix3x3 kBradford{{{0.8951f, 0.2664f, -0.1614f}, |
73 | | {-0.7502f, 1.7135f, 0.0367f}, |
74 | | {0.0389f, -0.0685f, 1.0296f}}}; |
75 | | constexpr Matrix3x3 kBradfordInv{{{0.9869929f, -0.1470543f, 0.1599627f}, |
76 | | {0.4323053f, 0.5183603f, 0.0492912f}, |
77 | | {-0.0085287f, 0.0400428f, 0.9684867f}}}; |
78 | | |
79 | | // Adapts white point x, y to D50 |
80 | 11.6k | static Status AdaptToXYZD50(float wx, float wy, Matrix3x3& matrix) { |
81 | 11.6k | bool ok = (wx >= 0) && (wx <= 1) && (wy > 0) && (wy <= 1); |
82 | 11.6k | if (!ok) { |
83 | | // Out of range values can cause division through zero |
84 | | // further down with the bradford adaptation too. |
85 | 7 | return JXL_FAILURE("Invalid white point"); |
86 | 7 | } |
87 | 11.6k | Vector3 w{wx / wy, 1.0f, (1.0f - wx - wy) / wy}; |
88 | | // 1 / tiny float can still overflow |
89 | 11.6k | JXL_RETURN_IF_ERROR(std::isfinite(w[0]) && std::isfinite(w[2])); |
90 | 11.6k | Vector3 w50{0.96422f, 1.0f, 0.82521f}; |
91 | | |
92 | 11.6k | Vector3 lms; |
93 | 11.6k | Vector3 lms50; |
94 | | |
95 | 11.6k | Mul3x3Vector(kBradford, w, lms); |
96 | 11.6k | Mul3x3Vector(kBradford, w50, lms50); |
97 | | |
98 | 11.6k | if (lms[0] == 0 || lms[1] == 0 || lms[2] == 0) { |
99 | 3 | return JXL_FAILURE("Invalid white point"); |
100 | 3 | } |
101 | 11.6k | Matrix3x3 a{{{lms50[0] / lms[0], 0, 0}, |
102 | 11.6k | {0, lms50[1] / lms[1], 0}, |
103 | 11.6k | {0, 0, lms50[2] / lms[2]}}}; |
104 | 11.6k | if (!std::isfinite(a[0][0]) || !std::isfinite(a[1][1]) || |
105 | 11.6k | !std::isfinite(a[2][2])) { |
106 | 0 | return JXL_FAILURE("Invalid white point"); |
107 | 0 | } |
108 | | |
109 | 11.6k | Matrix3x3 b; |
110 | 11.6k | Mul3x3Matrix(a, kBradford, b); |
111 | 11.6k | Mul3x3Matrix(kBradfordInv, b, matrix); |
112 | | |
113 | 11.6k | return true; |
114 | 11.6k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::AdaptToXYZD50(float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) color_encoding_internal.cc:jxl::AdaptToXYZD50(float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Line | Count | Source | 80 | 11.6k | static Status AdaptToXYZD50(float wx, float wy, Matrix3x3& matrix) { | 81 | 11.6k | bool ok = (wx >= 0) && (wx <= 1) && (wy > 0) && (wy <= 1); | 82 | 11.6k | if (!ok) { | 83 | | // Out of range values can cause division through zero | 84 | | // further down with the bradford adaptation too. | 85 | 7 | return JXL_FAILURE("Invalid white point"); | 86 | 7 | } | 87 | 11.6k | Vector3 w{wx / wy, 1.0f, (1.0f - wx - wy) / wy}; | 88 | | // 1 / tiny float can still overflow | 89 | 11.6k | JXL_RETURN_IF_ERROR(std::isfinite(w[0]) && std::isfinite(w[2])); | 90 | 11.6k | Vector3 w50{0.96422f, 1.0f, 0.82521f}; | 91 | | | 92 | 11.6k | Vector3 lms; | 93 | 11.6k | Vector3 lms50; | 94 | | | 95 | 11.6k | Mul3x3Vector(kBradford, w, lms); | 96 | 11.6k | Mul3x3Vector(kBradford, w50, lms50); | 97 | | | 98 | 11.6k | if (lms[0] == 0 || lms[1] == 0 || lms[2] == 0) { | 99 | 3 | return JXL_FAILURE("Invalid white point"); | 100 | 3 | } | 101 | 11.6k | Matrix3x3 a{{{lms50[0] / lms[0], 0, 0}, | 102 | 11.6k | {0, lms50[1] / lms[1], 0}, | 103 | 11.6k | {0, 0, lms50[2] / lms[2]}}}; | 104 | 11.6k | if (!std::isfinite(a[0][0]) || !std::isfinite(a[1][1]) || | 105 | 11.6k | !std::isfinite(a[2][2])) { | 106 | 0 | return JXL_FAILURE("Invalid white point"); | 107 | 0 | } | 108 | | | 109 | 11.6k | Matrix3x3 b; | 110 | 11.6k | Mul3x3Matrix(a, kBradford, b); | 111 | 11.6k | Mul3x3Matrix(kBradfordInv, b, matrix); | 112 | | | 113 | 11.6k | return true; | 114 | 11.6k | } |
Unexecuted instantiation: frame_header.cc:jxl::AdaptToXYZD50(float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Unexecuted instantiation: image_metadata.cc:jxl::AdaptToXYZD50(float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) |
115 | | |
116 | | static Status PrimariesToXYZD50(float rx, float ry, float gx, float gy, |
117 | | float bx, float by, float wx, float wy, |
118 | 2.88k | Matrix3x3& matrix) { |
119 | 2.88k | Matrix3x3 toXYZ; |
120 | 2.88k | JXL_RETURN_IF_ERROR(PrimariesToXYZ(rx, ry, gx, gy, bx, by, wx, wy, toXYZ)); |
121 | 2.88k | Matrix3x3 d50; |
122 | 2.88k | JXL_RETURN_IF_ERROR(AdaptToXYZD50(wx, wy, d50)); |
123 | | |
124 | 2.88k | Mul3x3Matrix(d50, toXYZ, matrix); |
125 | 2.88k | return true; |
126 | 2.88k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::PrimariesToXYZD50(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) color_encoding_internal.cc:jxl::PrimariesToXYZD50(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Line | Count | Source | 118 | 2.88k | Matrix3x3& matrix) { | 119 | 2.88k | Matrix3x3 toXYZ; | 120 | 2.88k | JXL_RETURN_IF_ERROR(PrimariesToXYZ(rx, ry, gx, gy, bx, by, wx, wy, toXYZ)); | 121 | 2.88k | Matrix3x3 d50; | 122 | 2.88k | JXL_RETURN_IF_ERROR(AdaptToXYZD50(wx, wy, d50)); | 123 | | | 124 | 2.88k | Mul3x3Matrix(d50, toXYZ, matrix); | 125 | 2.88k | return true; | 126 | 2.88k | } |
Unexecuted instantiation: frame_header.cc:jxl::PrimariesToXYZD50(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Unexecuted instantiation: image_metadata.cc:jxl::PrimariesToXYZD50(float, float, float, float, float, float, float, float, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) |
127 | | |
128 | | static Status ToneMapPixel(const JxlColorEncoding& c, const float in[3], |
129 | 5.83k | uint8_t pcslab_out[3]) { |
130 | 5.83k | Matrix3x3 primaries_XYZ; |
131 | 5.83k | JXL_RETURN_IF_ERROR(PrimariesToXYZ( |
132 | 5.83k | c.primaries_red_xy[0], c.primaries_red_xy[1], c.primaries_green_xy[0], |
133 | 5.83k | c.primaries_green_xy[1], c.primaries_blue_xy[0], c.primaries_blue_xy[1], |
134 | 5.83k | c.white_point_xy[0], c.white_point_xy[1], primaries_XYZ)); |
135 | 5.83k | const Vector3 luminances = primaries_XYZ[1]; |
136 | 5.83k | Color linear; |
137 | 5.83k | JxlTransferFunction tf = c.transfer_function; |
138 | 5.83k | if (tf == JXL_TRANSFER_FUNCTION_PQ) { |
139 | 17.4k | for (size_t i = 0; i < 3; ++i) { |
140 | 13.1k | linear[i] = TF_PQ_Base::DisplayFromEncoded( |
141 | 13.1k | /*display_intensity_target=*/10000.0, in[i]); |
142 | 13.1k | } |
143 | 4.37k | } else { |
144 | 5.83k | for (size_t i = 0; i < 3; ++i) { |
145 | 4.37k | linear[i] = TF_HLG_Base::DisplayFromEncoded(in[i]); |
146 | 4.37k | } |
147 | 1.45k | } |
148 | 5.83k | if (tf == JXL_TRANSFER_FUNCTION_PQ) { |
149 | 4.37k | Rec2408ToneMapperBase tone_mapper({0, 10000}, {0, 250}, luminances); |
150 | 4.37k | tone_mapper.ToneMap(linear); |
151 | 4.37k | } else { |
152 | 1.45k | HlgOOTF_Base ootf(/*source_luminance=*/300, /*target_luminance=*/80, |
153 | 1.45k | luminances); |
154 | 1.45k | ootf.Apply(linear); |
155 | 1.45k | } |
156 | 5.83k | GamutMapScalar(linear, luminances, |
157 | 5.83k | /*preserve_saturation=*/0.3f); |
158 | | |
159 | 5.83k | Matrix3x3 chad; |
160 | 5.83k | JXL_RETURN_IF_ERROR( |
161 | 5.83k | AdaptToXYZD50(c.white_point_xy[0], c.white_point_xy[1], chad)); |
162 | 5.83k | Matrix3x3 to_xyzd50; |
163 | 5.83k | Mul3x3Matrix(chad, primaries_XYZ, to_xyzd50); |
164 | | |
165 | 5.83k | Vector3 xyz{0, 0, 0}; |
166 | 23.3k | for (size_t xyz_c = 0; xyz_c < 3; ++xyz_c) { |
167 | 69.9k | for (size_t rgb_c = 0; rgb_c < 3; ++rgb_c) { |
168 | 52.4k | xyz[xyz_c] += linear[rgb_c] * to_xyzd50[xyz_c][rgb_c]; |
169 | 52.4k | } |
170 | 17.4k | } |
171 | | |
172 | 17.4k | const auto lab_f = [](const float x) { |
173 | 17.4k | static constexpr float kDelta = 6. / 29; |
174 | 17.4k | return x <= kDelta * kDelta * kDelta |
175 | 17.4k | ? x * (1 / (3 * kDelta * kDelta)) + 4.f / 29 |
176 | 17.4k | : std::cbrt(x); |
177 | 17.4k | }; |
178 | 5.83k | static constexpr float kXn = 0.964212; |
179 | 5.83k | static constexpr float kYn = 1; |
180 | 5.83k | static constexpr float kZn = 0.825188; |
181 | | |
182 | 5.83k | const float f_x = lab_f(xyz[0] / kXn); |
183 | 5.83k | const float f_y = lab_f(xyz[1] / kYn); |
184 | 5.83k | const float f_z = lab_f(xyz[2] / kZn); |
185 | | |
186 | 5.83k | pcslab_out[0] = static_cast<uint8_t>( |
187 | 5.83k | std::lroundf(255.f * Clamp1(1.16f * f_y - .16f, 0.f, 1.f))); |
188 | 5.83k | pcslab_out[1] = static_cast<uint8_t>( |
189 | 5.83k | std::lroundf(128.f + Clamp1(500 * (f_x - f_y), -128.f, 127.f))); |
190 | 5.83k | pcslab_out[2] = static_cast<uint8_t>( |
191 | 5.83k | std::lroundf(128.f + Clamp1(200 * (f_y - f_z), -128.f, 127.f))); |
192 | | |
193 | 5.83k | return true; |
194 | 5.83k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::ToneMapPixel(JxlColorEncoding const&, float const*, unsigned char*) color_encoding_internal.cc:jxl::ToneMapPixel(JxlColorEncoding const&, float const*, unsigned char*) Line | Count | Source | 129 | 5.83k | uint8_t pcslab_out[3]) { | 130 | 5.83k | Matrix3x3 primaries_XYZ; | 131 | 5.83k | JXL_RETURN_IF_ERROR(PrimariesToXYZ( | 132 | 5.83k | c.primaries_red_xy[0], c.primaries_red_xy[1], c.primaries_green_xy[0], | 133 | 5.83k | c.primaries_green_xy[1], c.primaries_blue_xy[0], c.primaries_blue_xy[1], | 134 | 5.83k | c.white_point_xy[0], c.white_point_xy[1], primaries_XYZ)); | 135 | 5.83k | const Vector3 luminances = primaries_XYZ[1]; | 136 | 5.83k | Color linear; | 137 | 5.83k | JxlTransferFunction tf = c.transfer_function; | 138 | 5.83k | if (tf == JXL_TRANSFER_FUNCTION_PQ) { | 139 | 17.4k | for (size_t i = 0; i < 3; ++i) { | 140 | 13.1k | linear[i] = TF_PQ_Base::DisplayFromEncoded( | 141 | 13.1k | /*display_intensity_target=*/10000.0, in[i]); | 142 | 13.1k | } | 143 | 4.37k | } else { | 144 | 5.83k | for (size_t i = 0; i < 3; ++i) { | 145 | 4.37k | linear[i] = TF_HLG_Base::DisplayFromEncoded(in[i]); | 146 | 4.37k | } | 147 | 1.45k | } | 148 | 5.83k | if (tf == JXL_TRANSFER_FUNCTION_PQ) { | 149 | 4.37k | Rec2408ToneMapperBase tone_mapper({0, 10000}, {0, 250}, luminances); | 150 | 4.37k | tone_mapper.ToneMap(linear); | 151 | 4.37k | } else { | 152 | 1.45k | HlgOOTF_Base ootf(/*source_luminance=*/300, /*target_luminance=*/80, | 153 | 1.45k | luminances); | 154 | 1.45k | ootf.Apply(linear); | 155 | 1.45k | } | 156 | 5.83k | GamutMapScalar(linear, luminances, | 157 | 5.83k | /*preserve_saturation=*/0.3f); | 158 | | | 159 | 5.83k | Matrix3x3 chad; | 160 | 5.83k | JXL_RETURN_IF_ERROR( | 161 | 5.83k | AdaptToXYZD50(c.white_point_xy[0], c.white_point_xy[1], chad)); | 162 | 5.83k | Matrix3x3 to_xyzd50; | 163 | 5.83k | Mul3x3Matrix(chad, primaries_XYZ, to_xyzd50); | 164 | | | 165 | 5.83k | Vector3 xyz{0, 0, 0}; | 166 | 23.3k | for (size_t xyz_c = 0; xyz_c < 3; ++xyz_c) { | 167 | 69.9k | for (size_t rgb_c = 0; rgb_c < 3; ++rgb_c) { | 168 | 52.4k | xyz[xyz_c] += linear[rgb_c] * to_xyzd50[xyz_c][rgb_c]; | 169 | 52.4k | } | 170 | 17.4k | } | 171 | | | 172 | 5.83k | const auto lab_f = [](const float x) { | 173 | 5.83k | static constexpr float kDelta = 6. / 29; | 174 | 5.83k | return x <= kDelta * kDelta * kDelta | 175 | 5.83k | ? x * (1 / (3 * kDelta * kDelta)) + 4.f / 29 | 176 | 5.83k | : std::cbrt(x); | 177 | 5.83k | }; | 178 | 5.83k | static constexpr float kXn = 0.964212; | 179 | 5.83k | static constexpr float kYn = 1; | 180 | 5.83k | static constexpr float kZn = 0.825188; | 181 | | | 182 | 5.83k | const float f_x = lab_f(xyz[0] / kXn); | 183 | 5.83k | const float f_y = lab_f(xyz[1] / kYn); | 184 | 5.83k | const float f_z = lab_f(xyz[2] / kZn); | 185 | | | 186 | 5.83k | pcslab_out[0] = static_cast<uint8_t>( | 187 | 5.83k | std::lroundf(255.f * Clamp1(1.16f * f_y - .16f, 0.f, 1.f))); | 188 | 5.83k | pcslab_out[1] = static_cast<uint8_t>( | 189 | 5.83k | std::lroundf(128.f + Clamp1(500 * (f_x - f_y), -128.f, 127.f))); | 190 | 5.83k | pcslab_out[2] = static_cast<uint8_t>( | 191 | 5.83k | std::lroundf(128.f + Clamp1(200 * (f_y - f_z), -128.f, 127.f))); | 192 | | | 193 | 5.83k | return true; | 194 | 5.83k | } |
Unexecuted instantiation: frame_header.cc:jxl::ToneMapPixel(JxlColorEncoding const&, float const*, unsigned char*) Unexecuted instantiation: image_metadata.cc:jxl::ToneMapPixel(JxlColorEncoding const&, float const*, unsigned char*) |
195 | | |
196 | | static std::vector<uint16_t> CreateTableCurve(uint32_t N, const ExtraTF tf, |
197 | 19 | bool tone_map) { |
198 | | // The generated PQ curve will make room for highlights up to this luminance. |
199 | | // TODO(sboukortt): make this variable? |
200 | 19 | static constexpr float kPQIntensityTarget = 10000; |
201 | | |
202 | 19 | JXL_ASSERT(N <= 4096); // ICC MFT2 only allows 4K entries |
203 | 19 | JXL_ASSERT(tf == ExtraTF::kPQ || tf == ExtraTF::kHLG); |
204 | | |
205 | 19 | static constexpr Vector3 kLuminances{1.f / 3, 1.f / 3, 1.f / 3}; |
206 | 19 | Rec2408ToneMapperBase tone_mapper({0, kPQIntensityTarget}, |
207 | 19 | {0, kDefaultIntensityTarget}, kLuminances); |
208 | | // No point using float - LCMS converts to 16-bit for A2B/MFT. |
209 | 19 | std::vector<uint16_t> table(N); |
210 | 1.23k | for (uint32_t i = 0; i < N; ++i) { |
211 | 1.21k | const float x = static_cast<float>(i) / (N - 1); // 1.0 at index N - 1. |
212 | 1.21k | const double dx = static_cast<double>(x); |
213 | | // LCMS requires EOTF (e.g. 2.4 exponent). |
214 | 1.21k | double y = (tf == ExtraTF::kHLG) |
215 | 1.21k | ? TF_HLG_Base::DisplayFromEncoded(dx) |
216 | 1.21k | : TF_PQ_Base::DisplayFromEncoded(kPQIntensityTarget, dx); |
217 | 1.21k | if (tone_map && tf == ExtraTF::kPQ && |
218 | 1.21k | kPQIntensityTarget > kDefaultIntensityTarget) { |
219 | 0 | float l = y * 10000 / kPQIntensityTarget; |
220 | 0 | Color gray{l, l, l}; |
221 | 0 | tone_mapper.ToneMap(gray); |
222 | 0 | y = gray[0]; |
223 | 0 | } |
224 | 1.21k | JXL_ASSERT(y >= 0.0); |
225 | | // Clamp to table range - necessary for HLG. |
226 | 1.21k | if (y > 1.0) y = 1.0; |
227 | | // 1.0 corresponds to table value 0xFFFF. |
228 | 1.21k | table[i] = static_cast<uint16_t>(roundf(y * 65535.0)); |
229 | 1.21k | } |
230 | 19 | return table; |
231 | 19 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::CreateTableCurve(unsigned int, jxl::ExtraTF, bool) color_encoding_internal.cc:jxl::CreateTableCurve(unsigned int, jxl::ExtraTF, bool) Line | Count | Source | 197 | 19 | bool tone_map) { | 198 | | // The generated PQ curve will make room for highlights up to this luminance. | 199 | | // TODO(sboukortt): make this variable? | 200 | 19 | static constexpr float kPQIntensityTarget = 10000; | 201 | | | 202 | 19 | JXL_ASSERT(N <= 4096); // ICC MFT2 only allows 4K entries | 203 | 19 | JXL_ASSERT(tf == ExtraTF::kPQ || tf == ExtraTF::kHLG); | 204 | | | 205 | 19 | static constexpr Vector3 kLuminances{1.f / 3, 1.f / 3, 1.f / 3}; | 206 | 19 | Rec2408ToneMapperBase tone_mapper({0, kPQIntensityTarget}, | 207 | 19 | {0, kDefaultIntensityTarget}, kLuminances); | 208 | | // No point using float - LCMS converts to 16-bit for A2B/MFT. | 209 | 19 | std::vector<uint16_t> table(N); | 210 | 1.23k | for (uint32_t i = 0; i < N; ++i) { | 211 | 1.21k | const float x = static_cast<float>(i) / (N - 1); // 1.0 at index N - 1. | 212 | 1.21k | const double dx = static_cast<double>(x); | 213 | | // LCMS requires EOTF (e.g. 2.4 exponent). | 214 | 1.21k | double y = (tf == ExtraTF::kHLG) | 215 | 1.21k | ? TF_HLG_Base::DisplayFromEncoded(dx) | 216 | 1.21k | : TF_PQ_Base::DisplayFromEncoded(kPQIntensityTarget, dx); | 217 | 1.21k | if (tone_map && tf == ExtraTF::kPQ && | 218 | 1.21k | kPQIntensityTarget > kDefaultIntensityTarget) { | 219 | 0 | float l = y * 10000 / kPQIntensityTarget; | 220 | 0 | Color gray{l, l, l}; | 221 | 0 | tone_mapper.ToneMap(gray); | 222 | 0 | y = gray[0]; | 223 | 0 | } | 224 | 1.21k | JXL_ASSERT(y >= 0.0); | 225 | | // Clamp to table range - necessary for HLG. | 226 | 1.21k | if (y > 1.0) y = 1.0; | 227 | | // 1.0 corresponds to table value 0xFFFF. | 228 | 1.21k | table[i] = static_cast<uint16_t>(roundf(y * 65535.0)); | 229 | 1.21k | } | 230 | 19 | return table; | 231 | 19 | } |
Unexecuted instantiation: frame_header.cc:jxl::CreateTableCurve(unsigned int, jxl::ExtraTF, bool) Unexecuted instantiation: image_metadata.cc:jxl::CreateTableCurve(unsigned int, jxl::ExtraTF, bool) |
232 | | |
233 | 26 | static Status CIEXYZFromWhiteCIExy(double wx, double wy, Color& XYZ) { |
234 | | // Target Y = 1. |
235 | 26 | if (std::abs(wy) < 1e-12) return JXL_FAILURE("Y value is too small"); |
236 | 25 | const float factor = 1 / wy; |
237 | 25 | XYZ[0] = wx * factor; |
238 | 25 | XYZ[1] = 1; |
239 | 25 | XYZ[2] = (1 - wx - wy) * factor; |
240 | 25 | return true; |
241 | 26 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::CIEXYZFromWhiteCIExy(double, double, std::__1::array<float, 3ul>&) color_encoding_internal.cc:jxl::CIEXYZFromWhiteCIExy(double, double, std::__1::array<float, 3ul>&) Line | Count | Source | 233 | 26 | static Status CIEXYZFromWhiteCIExy(double wx, double wy, Color& XYZ) { | 234 | | // Target Y = 1. | 235 | 26 | if (std::abs(wy) < 1e-12) return JXL_FAILURE("Y value is too small"); | 236 | 25 | const float factor = 1 / wy; | 237 | 25 | XYZ[0] = wx * factor; | 238 | 25 | XYZ[1] = 1; | 239 | 25 | XYZ[2] = (1 - wx - wy) * factor; | 240 | 25 | return true; | 241 | 26 | } |
Unexecuted instantiation: frame_header.cc:jxl::CIEXYZFromWhiteCIExy(double, double, std::__1::array<float, 3ul>&) Unexecuted instantiation: image_metadata.cc:jxl::CIEXYZFromWhiteCIExy(double, double, std::__1::array<float, 3ul>&) |
242 | | |
243 | | namespace detail { |
244 | | |
245 | | constexpr bool kEnable3DToneMapping = JXL_ENABLE_3D_ICC_TONEMAPPING; |
246 | | |
247 | 5.85k | static bool CanToneMap(const JxlColorEncoding& encoding) { |
248 | | // If the color space cannot be represented by a CICP tag in the ICC profile |
249 | | // then the rest of the profile must unambiguously identify it; we have less |
250 | | // freedom to do use it for tone mapping. |
251 | 5.85k | JxlTransferFunction tf = encoding.transfer_function; |
252 | 5.85k | JxlPrimaries p = encoding.primaries; |
253 | 5.85k | JxlWhitePoint wp = encoding.white_point; |
254 | 5.85k | return encoding.color_space == JXL_COLOR_SPACE_RGB && |
255 | 5.85k | (tf == JXL_TRANSFER_FUNCTION_PQ || tf == JXL_TRANSFER_FUNCTION_HLG) && |
256 | 5.85k | ((p == JXL_PRIMARIES_P3 && |
257 | 60 | (wp == JXL_WHITE_POINT_D65 || wp == JXL_WHITE_POINT_DCI)) || |
258 | 60 | (p != JXL_PRIMARIES_CUSTOM && wp == JXL_WHITE_POINT_D65)); |
259 | 5.85k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CanToneMap(JxlColorEncoding const&) color_encoding_internal.cc:jxl::detail::CanToneMap(JxlColorEncoding const&) Line | Count | Source | 247 | 5.85k | static bool CanToneMap(const JxlColorEncoding& encoding) { | 248 | | // If the color space cannot be represented by a CICP tag in the ICC profile | 249 | | // then the rest of the profile must unambiguously identify it; we have less | 250 | | // freedom to do use it for tone mapping. | 251 | 5.85k | JxlTransferFunction tf = encoding.transfer_function; | 252 | 5.85k | JxlPrimaries p = encoding.primaries; | 253 | 5.85k | JxlWhitePoint wp = encoding.white_point; | 254 | 5.85k | return encoding.color_space == JXL_COLOR_SPACE_RGB && | 255 | 5.85k | (tf == JXL_TRANSFER_FUNCTION_PQ || tf == JXL_TRANSFER_FUNCTION_HLG) && | 256 | 5.85k | ((p == JXL_PRIMARIES_P3 && | 257 | 60 | (wp == JXL_WHITE_POINT_D65 || wp == JXL_WHITE_POINT_DCI)) || | 258 | 60 | (p != JXL_PRIMARIES_CUSTOM && wp == JXL_WHITE_POINT_D65)); | 259 | 5.85k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CanToneMap(JxlColorEncoding const&) Unexecuted instantiation: image_metadata.cc:jxl::detail::CanToneMap(JxlColorEncoding const&) |
260 | | |
261 | | static void ICCComputeMD5(const std::vector<uint8_t>& data, uint8_t sum[16]) |
262 | 2.90k | JXL_NO_SANITIZE("unsigned-integer-overflow") { |
263 | 2.90k | std::vector<uint8_t> data64 = data; |
264 | 2.90k | data64.push_back(128); |
265 | | // Add bytes such that ((size + 8) & 63) == 0. |
266 | 2.90k | size_t extra = ((64 - ((data64.size() + 8) & 63)) & 63); |
267 | 2.90k | data64.resize(data64.size() + extra, 0); |
268 | 26.1k | for (uint64_t i = 0; i < 64; i += 8) { |
269 | 23.2k | data64.push_back(static_cast<uint64_t>(data.size() << 3u) >> i); |
270 | 23.2k | } |
271 | | |
272 | 2.90k | static const uint32_t sineparts[64] = { |
273 | 2.90k | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, |
274 | 2.90k | 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, |
275 | 2.90k | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, |
276 | 2.90k | 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, |
277 | 2.90k | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, |
278 | 2.90k | 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, |
279 | 2.90k | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, |
280 | 2.90k | 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, |
281 | 2.90k | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, |
282 | 2.90k | 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, |
283 | 2.90k | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, |
284 | 2.90k | }; |
285 | 2.90k | static const uint32_t shift[64] = { |
286 | 2.90k | 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, |
287 | 2.90k | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, |
288 | 2.90k | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, |
289 | 2.90k | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, |
290 | 2.90k | }; |
291 | | |
292 | 2.90k | uint32_t a0 = 0x67452301; |
293 | 2.90k | uint32_t b0 = 0xefcdab89; |
294 | 2.90k | uint32_t c0 = 0x98badcfe; |
295 | 2.90k | uint32_t d0 = 0x10325476; |
296 | | |
297 | 29.5k | for (size_t i = 0; i < data64.size(); i += 64) { |
298 | 26.6k | uint32_t a = a0; |
299 | 26.6k | uint32_t b = b0; |
300 | 26.6k | uint32_t c = c0; |
301 | 26.6k | uint32_t d = d0; |
302 | 26.6k | uint32_t f; |
303 | 26.6k | uint32_t g; |
304 | 1.73M | for (size_t j = 0; j < 64; j++) { |
305 | 1.70M | if (j < 16) { |
306 | 426k | f = (b & c) | ((~b) & d); |
307 | 426k | g = j; |
308 | 1.27M | } else if (j < 32) { |
309 | 426k | f = (d & b) | ((~d) & c); |
310 | 426k | g = (5 * j + 1) & 0xf; |
311 | 852k | } else if (j < 48) { |
312 | 426k | f = b ^ c ^ d; |
313 | 426k | g = (3 * j + 5) & 0xf; |
314 | 426k | } else { |
315 | 426k | f = c ^ (b | (~d)); |
316 | 426k | g = (7 * j) & 0xf; |
317 | 426k | } |
318 | 1.70M | uint32_t dg0 = data64[i + g * 4 + 0]; |
319 | 1.70M | uint32_t dg1 = data64[i + g * 4 + 1]; |
320 | 1.70M | uint32_t dg2 = data64[i + g * 4 + 2]; |
321 | 1.70M | uint32_t dg3 = data64[i + g * 4 + 3]; |
322 | 1.70M | uint32_t u = dg0 | (dg1 << 8u) | (dg2 << 16u) | (dg3 << 24u); |
323 | 1.70M | f += a + sineparts[j] + u; |
324 | 1.70M | a = d; |
325 | 1.70M | d = c; |
326 | 1.70M | c = b; |
327 | 1.70M | b += (f << shift[j]) | (f >> (32u - shift[j])); |
328 | 1.70M | } |
329 | 26.6k | a0 += a; |
330 | 26.6k | b0 += b; |
331 | 26.6k | c0 += c; |
332 | 26.6k | d0 += d; |
333 | 26.6k | } |
334 | 2.90k | sum[0] = a0; |
335 | 2.90k | sum[1] = a0 >> 8u; |
336 | 2.90k | sum[2] = a0 >> 16u; |
337 | 2.90k | sum[3] = a0 >> 24u; |
338 | 2.90k | sum[4] = b0; |
339 | 2.90k | sum[5] = b0 >> 8u; |
340 | 2.90k | sum[6] = b0 >> 16u; |
341 | 2.90k | sum[7] = b0 >> 24u; |
342 | 2.90k | sum[8] = c0; |
343 | 2.90k | sum[9] = c0 >> 8u; |
344 | 2.90k | sum[10] = c0 >> 16u; |
345 | 2.90k | sum[11] = c0 >> 24u; |
346 | 2.90k | sum[12] = d0; |
347 | 2.90k | sum[13] = d0 >> 8u; |
348 | 2.90k | sum[14] = d0 >> 16u; |
349 | 2.90k | sum[15] = d0 >> 24u; |
350 | 2.90k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ICCComputeMD5(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, unsigned char*) color_encoding_internal.cc:jxl::detail::ICCComputeMD5(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, unsigned char*) Line | Count | Source | 262 | 2.90k | JXL_NO_SANITIZE("unsigned-integer-overflow") { | 263 | 2.90k | std::vector<uint8_t> data64 = data; | 264 | 2.90k | data64.push_back(128); | 265 | | // Add bytes such that ((size + 8) & 63) == 0. | 266 | 2.90k | size_t extra = ((64 - ((data64.size() + 8) & 63)) & 63); | 267 | 2.90k | data64.resize(data64.size() + extra, 0); | 268 | 26.1k | for (uint64_t i = 0; i < 64; i += 8) { | 269 | 23.2k | data64.push_back(static_cast<uint64_t>(data.size() << 3u) >> i); | 270 | 23.2k | } | 271 | | | 272 | 2.90k | static const uint32_t sineparts[64] = { | 273 | 2.90k | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, | 274 | 2.90k | 0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, | 275 | 2.90k | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, | 276 | 2.90k | 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, | 277 | 2.90k | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, | 278 | 2.90k | 0x676f02d9, 0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, | 279 | 2.90k | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, 0x289b7ec6, 0xeaa127fa, | 280 | 2.90k | 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, | 281 | 2.90k | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, | 282 | 2.90k | 0xffeff47d, 0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, | 283 | 2.90k | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, | 284 | 2.90k | }; | 285 | 2.90k | static const uint32_t shift[64] = { | 286 | 2.90k | 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, | 287 | 2.90k | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, | 288 | 2.90k | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, | 289 | 2.90k | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, | 290 | 2.90k | }; | 291 | | | 292 | 2.90k | uint32_t a0 = 0x67452301; | 293 | 2.90k | uint32_t b0 = 0xefcdab89; | 294 | 2.90k | uint32_t c0 = 0x98badcfe; | 295 | 2.90k | uint32_t d0 = 0x10325476; | 296 | | | 297 | 29.5k | for (size_t i = 0; i < data64.size(); i += 64) { | 298 | 26.6k | uint32_t a = a0; | 299 | 26.6k | uint32_t b = b0; | 300 | 26.6k | uint32_t c = c0; | 301 | 26.6k | uint32_t d = d0; | 302 | 26.6k | uint32_t f; | 303 | 26.6k | uint32_t g; | 304 | 1.73M | for (size_t j = 0; j < 64; j++) { | 305 | 1.70M | if (j < 16) { | 306 | 426k | f = (b & c) | ((~b) & d); | 307 | 426k | g = j; | 308 | 1.27M | } else if (j < 32) { | 309 | 426k | f = (d & b) | ((~d) & c); | 310 | 426k | g = (5 * j + 1) & 0xf; | 311 | 852k | } else if (j < 48) { | 312 | 426k | f = b ^ c ^ d; | 313 | 426k | g = (3 * j + 5) & 0xf; | 314 | 426k | } else { | 315 | 426k | f = c ^ (b | (~d)); | 316 | 426k | g = (7 * j) & 0xf; | 317 | 426k | } | 318 | 1.70M | uint32_t dg0 = data64[i + g * 4 + 0]; | 319 | 1.70M | uint32_t dg1 = data64[i + g * 4 + 1]; | 320 | 1.70M | uint32_t dg2 = data64[i + g * 4 + 2]; | 321 | 1.70M | uint32_t dg3 = data64[i + g * 4 + 3]; | 322 | 1.70M | uint32_t u = dg0 | (dg1 << 8u) | (dg2 << 16u) | (dg3 << 24u); | 323 | 1.70M | f += a + sineparts[j] + u; | 324 | 1.70M | a = d; | 325 | 1.70M | d = c; | 326 | 1.70M | c = b; | 327 | 1.70M | b += (f << shift[j]) | (f >> (32u - shift[j])); | 328 | 1.70M | } | 329 | 26.6k | a0 += a; | 330 | 26.6k | b0 += b; | 331 | 26.6k | c0 += c; | 332 | 26.6k | d0 += d; | 333 | 26.6k | } | 334 | 2.90k | sum[0] = a0; | 335 | 2.90k | sum[1] = a0 >> 8u; | 336 | 2.90k | sum[2] = a0 >> 16u; | 337 | 2.90k | sum[3] = a0 >> 24u; | 338 | 2.90k | sum[4] = b0; | 339 | 2.90k | sum[5] = b0 >> 8u; | 340 | 2.90k | sum[6] = b0 >> 16u; | 341 | 2.90k | sum[7] = b0 >> 24u; | 342 | 2.90k | sum[8] = c0; | 343 | 2.90k | sum[9] = c0 >> 8u; | 344 | 2.90k | sum[10] = c0 >> 16u; | 345 | 2.90k | sum[11] = c0 >> 24u; | 346 | 2.90k | sum[12] = d0; | 347 | 2.90k | sum[13] = d0 >> 8u; | 348 | 2.90k | sum[14] = d0 >> 16u; | 349 | 2.90k | sum[15] = d0 >> 24u; | 350 | 2.90k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ICCComputeMD5(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, unsigned char*) Unexecuted instantiation: image_metadata.cc:jxl::detail::ICCComputeMD5(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> > const&, unsigned char*) |
351 | | |
352 | 2.90k | static Status CreateICCChadMatrix(double wx, double wy, Matrix3x3& result) { |
353 | 2.90k | Matrix3x3 m; |
354 | 2.90k | if (wy == 0) { // WhitePoint can not be pitch-black. |
355 | 1 | return JXL_FAILURE("Invalid WhitePoint"); |
356 | 1 | } |
357 | 2.90k | JXL_RETURN_IF_ERROR(AdaptToXYZD50(wx, wy, m)); |
358 | 2.89k | result = m; |
359 | 2.89k | return true; |
360 | 2.90k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCChadMatrix(double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) color_encoding_internal.cc:jxl::detail::CreateICCChadMatrix(double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Line | Count | Source | 352 | 2.90k | static Status CreateICCChadMatrix(double wx, double wy, Matrix3x3& result) { | 353 | 2.90k | Matrix3x3 m; | 354 | 2.90k | if (wy == 0) { // WhitePoint can not be pitch-black. | 355 | 1 | return JXL_FAILURE("Invalid WhitePoint"); | 356 | 1 | } | 357 | 2.90k | JXL_RETURN_IF_ERROR(AdaptToXYZD50(wx, wy, m)); | 358 | 2.89k | result = m; | 359 | 2.89k | return true; | 360 | 2.90k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCChadMatrix(double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCChadMatrix(double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) |
361 | | |
362 | | // Creates RGB to XYZ matrix given RGB primaries and white point in xy. |
363 | | static Status CreateICCRGBMatrix(double rx, double ry, double gx, double gy, |
364 | | double bx, double by, double wx, double wy, |
365 | 2.88k | Matrix3x3& result) { |
366 | 2.88k | Matrix3x3 m; |
367 | 2.88k | JXL_RETURN_IF_ERROR(PrimariesToXYZD50(rx, ry, gx, gy, bx, by, wx, wy, m)); |
368 | 2.88k | result = m; |
369 | 2.88k | return true; |
370 | 2.88k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCRGBMatrix(double, double, double, double, double, double, double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) color_encoding_internal.cc:jxl::detail::CreateICCRGBMatrix(double, double, double, double, double, double, double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Line | Count | Source | 365 | 2.88k | Matrix3x3& result) { | 366 | 2.88k | Matrix3x3 m; | 367 | 2.88k | JXL_RETURN_IF_ERROR(PrimariesToXYZD50(rx, ry, gx, gy, bx, by, wx, wy, m)); | 368 | 2.88k | result = m; | 369 | 2.88k | return true; | 370 | 2.88k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCRGBMatrix(double, double, double, double, double, double, double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCRGBMatrix(double, double, double, double, double, double, double, double, std::__1::array<std::__1::array<float, 3ul>, 3ul>&) |
371 | | |
372 | | static void WriteICCUint32(uint32_t value, size_t pos, |
373 | 261k | std::vector<uint8_t>* icc) { |
374 | 261k | if (icc->size() < pos + 4) icc->resize(pos + 4); |
375 | 261k | (*icc)[pos + 0] = (value >> 24u) & 255; |
376 | 261k | (*icc)[pos + 1] = (value >> 16u) & 255; |
377 | 261k | (*icc)[pos + 2] = (value >> 8u) & 255; |
378 | 261k | (*icc)[pos + 3] = value & 255; |
379 | 261k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::WriteICCUint32(unsigned int, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::WriteICCUint32(unsigned int, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 373 | 261k | std::vector<uint8_t>* icc) { | 374 | 261k | if (icc->size() < pos + 4) icc->resize(pos + 4); | 375 | 261k | (*icc)[pos + 0] = (value >> 24u) & 255; | 376 | 261k | (*icc)[pos + 1] = (value >> 16u) & 255; | 377 | 261k | (*icc)[pos + 2] = (value >> 8u) & 255; | 378 | 261k | (*icc)[pos + 3] = value & 255; | 379 | 261k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::WriteICCUint32(unsigned int, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::WriteICCUint32(unsigned int, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
380 | | |
381 | | static void WriteICCUint16(uint16_t value, size_t pos, |
382 | 24.7k | std::vector<uint8_t>* icc) { |
383 | 24.7k | if (icc->size() < pos + 2) icc->resize(pos + 2); |
384 | 24.7k | (*icc)[pos + 0] = (value >> 8u) & 255; |
385 | 24.7k | (*icc)[pos + 1] = value & 255; |
386 | 24.7k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::WriteICCUint16(unsigned short, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::WriteICCUint16(unsigned short, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 382 | 24.7k | std::vector<uint8_t>* icc) { | 383 | 24.7k | if (icc->size() < pos + 2) icc->resize(pos + 2); | 384 | 24.7k | (*icc)[pos + 0] = (value >> 8u) & 255; | 385 | 24.7k | (*icc)[pos + 1] = value & 255; | 386 | 24.7k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::WriteICCUint16(unsigned short, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::WriteICCUint16(unsigned short, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
387 | | |
388 | | static void WriteICCUint8(uint8_t value, size_t pos, |
389 | 41.2k | std::vector<uint8_t>* icc) { |
390 | 41.2k | if (icc->size() < pos + 1) icc->resize(pos + 1); |
391 | 41.2k | (*icc)[pos] = value; |
392 | 41.2k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::WriteICCUint8(unsigned char, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::WriteICCUint8(unsigned char, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 389 | 41.2k | std::vector<uint8_t>* icc) { | 390 | 41.2k | if (icc->size() < pos + 1) icc->resize(pos + 1); | 391 | 41.2k | (*icc)[pos] = value; | 392 | 41.2k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::WriteICCUint8(unsigned char, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::WriteICCUint8(unsigned char, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
393 | | |
394 | | // Writes a 4-character tag |
395 | | static void WriteICCTag(const char* value, size_t pos, |
396 | 84.3k | std::vector<uint8_t>* icc) { |
397 | 84.3k | if (icc->size() < pos + 4) icc->resize(pos + 4); |
398 | 84.3k | memcpy(icc->data() + pos, value, 4); |
399 | 84.3k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::WriteICCTag(char const*, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::WriteICCTag(char const*, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 396 | 84.3k | std::vector<uint8_t>* icc) { | 397 | 84.3k | if (icc->size() < pos + 4) icc->resize(pos + 4); | 398 | 84.3k | memcpy(icc->data() + pos, value, 4); | 399 | 84.3k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::WriteICCTag(char const*, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::WriteICCTag(char const*, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
400 | | |
401 | | static Status WriteICCS15Fixed16(float value, size_t pos, |
402 | 75.2k | std::vector<uint8_t>* icc) { |
403 | | // "nextafterf" for 32768.0f towards zero are: |
404 | | // 32767.998046875, 32767.99609375, 32767.994140625 |
405 | | // Even the first value works well,... |
406 | 75.2k | bool ok = (-32767.995f <= value) && (value <= 32767.995f); |
407 | 75.2k | if (!ok) return JXL_FAILURE("ICC value is out of range / NaN"); |
408 | 75.2k | int32_t i = static_cast<int32_t>(std::lround(value * 65536.0f)); |
409 | | // Use two's complement |
410 | 75.2k | uint32_t u = static_cast<uint32_t>(i); |
411 | 75.2k | WriteICCUint32(u, pos, icc); |
412 | 75.2k | return true; |
413 | 75.2k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::WriteICCS15Fixed16(float, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::WriteICCS15Fixed16(float, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 402 | 75.2k | std::vector<uint8_t>* icc) { | 403 | | // "nextafterf" for 32768.0f towards zero are: | 404 | | // 32767.998046875, 32767.99609375, 32767.994140625 | 405 | | // Even the first value works well,... | 406 | 75.2k | bool ok = (-32767.995f <= value) && (value <= 32767.995f); | 407 | 75.2k | if (!ok) return JXL_FAILURE("ICC value is out of range / NaN"); | 408 | 75.2k | int32_t i = static_cast<int32_t>(std::lround(value * 65536.0f)); | 409 | | // Use two's complement | 410 | 75.2k | uint32_t u = static_cast<uint32_t>(i); | 411 | 75.2k | WriteICCUint32(u, pos, icc); | 412 | 75.2k | return true; | 413 | 75.2k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::WriteICCS15Fixed16(float, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::WriteICCS15Fixed16(float, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
414 | | |
415 | | static Status CreateICCHeader(const JxlColorEncoding& c, |
416 | 2.93k | std::vector<uint8_t>* header) { |
417 | | // TODO(lode): choose color management engine name, e.g. "skia" if |
418 | | // integrated in skia. |
419 | 2.93k | static const char* kCmm = "jxl "; |
420 | | |
421 | 2.93k | header->resize(128, 0); |
422 | | |
423 | 2.93k | WriteICCUint32(0, 0, header); // size, correct value filled in at end |
424 | 2.93k | WriteICCTag(kCmm, 4, header); |
425 | 2.93k | WriteICCUint32(0x04400000u, 8, header); |
426 | 2.93k | const char* profile_type = |
427 | 2.93k | c.color_space == JXL_COLOR_SPACE_XYB ? "scnr" : "mntr"; |
428 | 2.93k | WriteICCTag(profile_type, 12, header); |
429 | 2.93k | WriteICCTag(c.color_space == JXL_COLOR_SPACE_GRAY ? "GRAY" : "RGB ", 16, |
430 | 2.93k | header); |
431 | 2.93k | if (kEnable3DToneMapping && CanToneMap(c)) { |
432 | | // We are going to use a 3D LUT for tone mapping, which will be more compact |
433 | | // with an 8-bit LUT to CIELAB than with a 16-bit LUT to XYZ. 8-bit XYZ |
434 | | // would not be viable due to XYZ being linear, whereas it is fine with |
435 | | // CIELAB's ~cube root. |
436 | 8 | WriteICCTag("Lab ", 20, header); |
437 | 2.92k | } else { |
438 | 2.92k | WriteICCTag("XYZ ", 20, header); |
439 | 2.92k | } |
440 | | |
441 | | // Three uint32_t's date/time encoding. |
442 | | // TODO(lode): encode actual date and time, this is a placeholder |
443 | 2.93k | uint32_t year = 2019; |
444 | 2.93k | uint32_t month = 12; |
445 | 2.93k | uint32_t day = 1; |
446 | 2.93k | uint32_t hour = 0; |
447 | 2.93k | uint32_t minute = 0; |
448 | 2.93k | uint32_t second = 0; |
449 | 2.93k | WriteICCUint16(year, 24, header); |
450 | 2.93k | WriteICCUint16(month, 26, header); |
451 | 2.93k | WriteICCUint16(day, 28, header); |
452 | 2.93k | WriteICCUint16(hour, 30, header); |
453 | 2.93k | WriteICCUint16(minute, 32, header); |
454 | 2.93k | WriteICCUint16(second, 34, header); |
455 | | |
456 | 2.93k | WriteICCTag("acsp", 36, header); |
457 | 2.93k | WriteICCTag("APPL", 40, header); |
458 | 2.93k | WriteICCUint32(0, 44, header); // flags |
459 | 2.93k | WriteICCUint32(0, 48, header); // device manufacturer |
460 | 2.93k | WriteICCUint32(0, 52, header); // device model |
461 | 2.93k | WriteICCUint32(0, 56, header); // device attributes |
462 | 2.93k | WriteICCUint32(0, 60, header); // device attributes |
463 | 2.93k | WriteICCUint32(static_cast<uint32_t>(c.rendering_intent), 64, header); |
464 | | |
465 | | // Mandatory D50 white point of profile connection space |
466 | 2.93k | WriteICCUint32(0x0000f6d6, 68, header); |
467 | 2.93k | WriteICCUint32(0x00010000, 72, header); |
468 | 2.93k | WriteICCUint32(0x0000d32d, 76, header); |
469 | | |
470 | 2.93k | WriteICCTag(kCmm, 80, header); |
471 | | |
472 | 2.93k | return true; |
473 | 2.93k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCHeader(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCHeader(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 416 | 2.93k | std::vector<uint8_t>* header) { | 417 | | // TODO(lode): choose color management engine name, e.g. "skia" if | 418 | | // integrated in skia. | 419 | 2.93k | static const char* kCmm = "jxl "; | 420 | | | 421 | 2.93k | header->resize(128, 0); | 422 | | | 423 | 2.93k | WriteICCUint32(0, 0, header); // size, correct value filled in at end | 424 | 2.93k | WriteICCTag(kCmm, 4, header); | 425 | 2.93k | WriteICCUint32(0x04400000u, 8, header); | 426 | 2.93k | const char* profile_type = | 427 | 2.93k | c.color_space == JXL_COLOR_SPACE_XYB ? "scnr" : "mntr"; | 428 | 2.93k | WriteICCTag(profile_type, 12, header); | 429 | 2.93k | WriteICCTag(c.color_space == JXL_COLOR_SPACE_GRAY ? "GRAY" : "RGB ", 16, | 430 | 2.93k | header); | 431 | 2.93k | if (kEnable3DToneMapping && CanToneMap(c)) { | 432 | | // We are going to use a 3D LUT for tone mapping, which will be more compact | 433 | | // with an 8-bit LUT to CIELAB than with a 16-bit LUT to XYZ. 8-bit XYZ | 434 | | // would not be viable due to XYZ being linear, whereas it is fine with | 435 | | // CIELAB's ~cube root. | 436 | 8 | WriteICCTag("Lab ", 20, header); | 437 | 2.92k | } else { | 438 | 2.92k | WriteICCTag("XYZ ", 20, header); | 439 | 2.92k | } | 440 | | | 441 | | // Three uint32_t's date/time encoding. | 442 | | // TODO(lode): encode actual date and time, this is a placeholder | 443 | 2.93k | uint32_t year = 2019; | 444 | 2.93k | uint32_t month = 12; | 445 | 2.93k | uint32_t day = 1; | 446 | 2.93k | uint32_t hour = 0; | 447 | 2.93k | uint32_t minute = 0; | 448 | 2.93k | uint32_t second = 0; | 449 | 2.93k | WriteICCUint16(year, 24, header); | 450 | 2.93k | WriteICCUint16(month, 26, header); | 451 | 2.93k | WriteICCUint16(day, 28, header); | 452 | 2.93k | WriteICCUint16(hour, 30, header); | 453 | 2.93k | WriteICCUint16(minute, 32, header); | 454 | 2.93k | WriteICCUint16(second, 34, header); | 455 | | | 456 | 2.93k | WriteICCTag("acsp", 36, header); | 457 | 2.93k | WriteICCTag("APPL", 40, header); | 458 | 2.93k | WriteICCUint32(0, 44, header); // flags | 459 | 2.93k | WriteICCUint32(0, 48, header); // device manufacturer | 460 | 2.93k | WriteICCUint32(0, 52, header); // device model | 461 | 2.93k | WriteICCUint32(0, 56, header); // device attributes | 462 | 2.93k | WriteICCUint32(0, 60, header); // device attributes | 463 | 2.93k | WriteICCUint32(static_cast<uint32_t>(c.rendering_intent), 64, header); | 464 | | | 465 | | // Mandatory D50 white point of profile connection space | 466 | 2.93k | WriteICCUint32(0x0000f6d6, 68, header); | 467 | 2.93k | WriteICCUint32(0x00010000, 72, header); | 468 | 2.93k | WriteICCUint32(0x0000d32d, 76, header); | 469 | | | 470 | 2.93k | WriteICCTag(kCmm, 80, header); | 471 | | | 472 | 2.93k | return true; | 473 | 2.93k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCHeader(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCHeader(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
474 | | |
475 | | static void AddToICCTagTable(const char* tag, size_t offset, size_t size, |
476 | | std::vector<uint8_t>* tagtable, |
477 | 31.8k | std::vector<size_t>* offsets) { |
478 | 31.8k | WriteICCTag(tag, tagtable->size(), tagtable); |
479 | | // writing true offset deferred to later |
480 | 31.8k | WriteICCUint32(0, tagtable->size(), tagtable); |
481 | 31.8k | offsets->push_back(offset); |
482 | 31.8k | WriteICCUint32(size, tagtable->size(), tagtable); |
483 | 31.8k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::AddToICCTagTable(char const*, unsigned long, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) color_encoding_internal.cc:jxl::detail::AddToICCTagTable(char const*, unsigned long, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) Line | Count | Source | 477 | 31.8k | std::vector<size_t>* offsets) { | 478 | 31.8k | WriteICCTag(tag, tagtable->size(), tagtable); | 479 | | // writing true offset deferred to later | 480 | 31.8k | WriteICCUint32(0, tagtable->size(), tagtable); | 481 | 31.8k | offsets->push_back(offset); | 482 | 31.8k | WriteICCUint32(size, tagtable->size(), tagtable); | 483 | 31.8k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::AddToICCTagTable(char const*, unsigned long, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::AddToICCTagTable(char const*, unsigned long, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) |
484 | | |
485 | | static void FinalizeICCTag(std::vector<uint8_t>* tags, size_t* offset, |
486 | 26.0k | size_t* size) { |
487 | 37.7k | while ((tags->size() & 3) != 0) { |
488 | 11.6k | tags->push_back(0); |
489 | 11.6k | } |
490 | 26.0k | *offset += *size; |
491 | 26.0k | *size = tags->size() - *offset; |
492 | 26.0k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::FinalizeICCTag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*) color_encoding_internal.cc:jxl::detail::FinalizeICCTag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*) Line | Count | Source | 486 | 26.0k | size_t* size) { | 487 | 37.7k | while ((tags->size() & 3) != 0) { | 488 | 11.6k | tags->push_back(0); | 489 | 11.6k | } | 490 | 26.0k | *offset += *size; | 491 | 26.0k | *size = tags->size() - *offset; | 492 | 26.0k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::FinalizeICCTag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*) Unexecuted instantiation: image_metadata.cc:jxl::detail::FinalizeICCTag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*) |
493 | | |
494 | | // The input text must be ASCII, writing other characters to UTF-16 is not |
495 | | // implemented. |
496 | | static void CreateICCMlucTag(const std::string& text, |
497 | 5.86k | std::vector<uint8_t>* tags) { |
498 | 5.86k | WriteICCTag("mluc", tags->size(), tags); |
499 | 5.86k | WriteICCUint32(0, tags->size(), tags); |
500 | 5.86k | WriteICCUint32(1, tags->size(), tags); |
501 | 5.86k | WriteICCUint32(12, tags->size(), tags); |
502 | 5.86k | WriteICCTag("enUS", tags->size(), tags); |
503 | 5.86k | WriteICCUint32(text.size() * 2, tags->size(), tags); |
504 | 5.86k | WriteICCUint32(28, tags->size(), tags); |
505 | 65.9k | for (char c : text) { |
506 | 65.9k | tags->push_back(0); // prepend 0 for UTF-16 |
507 | 65.9k | tags->push_back(c); |
508 | 65.9k | } |
509 | 5.86k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCMlucTag(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCMlucTag(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 497 | 5.86k | std::vector<uint8_t>* tags) { | 498 | 5.86k | WriteICCTag("mluc", tags->size(), tags); | 499 | 5.86k | WriteICCUint32(0, tags->size(), tags); | 500 | 5.86k | WriteICCUint32(1, tags->size(), tags); | 501 | 5.86k | WriteICCUint32(12, tags->size(), tags); | 502 | 5.86k | WriteICCTag("enUS", tags->size(), tags); | 503 | 5.86k | WriteICCUint32(text.size() * 2, tags->size(), tags); | 504 | 5.86k | WriteICCUint32(28, tags->size(), tags); | 505 | 65.9k | for (char c : text) { | 506 | 65.9k | tags->push_back(0); // prepend 0 for UTF-16 | 507 | 65.9k | tags->push_back(c); | 508 | 65.9k | } | 509 | 5.86k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCMlucTag(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCMlucTag(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
510 | | |
511 | 11.5k | static Status CreateICCXYZTag(const Color& xyz, std::vector<uint8_t>* tags) { |
512 | 11.5k | WriteICCTag("XYZ ", tags->size(), tags); |
513 | 11.5k | WriteICCUint32(0, tags->size(), tags); |
514 | 46.3k | for (size_t i = 0; i < 3; ++i) { |
515 | 34.7k | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(xyz[i], tags->size(), tags)); |
516 | 34.7k | } |
517 | 11.5k | return true; |
518 | 11.5k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCXYZTag(std::__1::array<float, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCXYZTag(std::__1::array<float, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 511 | 11.5k | static Status CreateICCXYZTag(const Color& xyz, std::vector<uint8_t>* tags) { | 512 | 11.5k | WriteICCTag("XYZ ", tags->size(), tags); | 513 | 11.5k | WriteICCUint32(0, tags->size(), tags); | 514 | 46.3k | for (size_t i = 0; i < 3; ++i) { | 515 | 34.7k | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(xyz[i], tags->size(), tags)); | 516 | 34.7k | } | 517 | 11.5k | return true; | 518 | 11.5k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCXYZTag(std::__1::array<float, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCXYZTag(std::__1::array<float, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
519 | | |
520 | | static Status CreateICCChadTag(const Matrix3x3& chad, |
521 | 2.89k | std::vector<uint8_t>* tags) { |
522 | 2.89k | WriteICCTag("sf32", tags->size(), tags); |
523 | 2.89k | WriteICCUint32(0, tags->size(), tags); |
524 | 11.5k | for (size_t j = 0; j < 3; j++) { |
525 | 34.7k | for (size_t i = 0; i < 3; i++) { |
526 | 26.0k | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(chad[j][i], tags->size(), tags)); |
527 | 26.0k | } |
528 | 8.67k | } |
529 | 2.89k | return true; |
530 | 2.89k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCChadTag(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCChadTag(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 521 | 2.89k | std::vector<uint8_t>* tags) { | 522 | 2.89k | WriteICCTag("sf32", tags->size(), tags); | 523 | 2.89k | WriteICCUint32(0, tags->size(), tags); | 524 | 11.5k | for (size_t j = 0; j < 3; j++) { | 525 | 34.7k | for (size_t i = 0; i < 3; i++) { | 526 | 26.0k | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(chad[j][i], tags->size(), tags)); | 527 | 26.0k | } | 528 | 8.67k | } | 529 | 2.89k | return true; | 530 | 2.89k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCChadTag(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCChadTag(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
531 | | |
532 | | static void MaybeCreateICCCICPTag(const JxlColorEncoding& c, |
533 | | std::vector<uint8_t>* tags, size_t* offset, |
534 | | size_t* size, std::vector<uint8_t>* tagtable, |
535 | 2.88k | std::vector<size_t>* offsets) { |
536 | 2.88k | if (c.color_space != JXL_COLOR_SPACE_RGB) { |
537 | 0 | return; |
538 | 0 | } |
539 | 2.88k | uint8_t primaries = 0; |
540 | 2.88k | if (c.primaries == JXL_PRIMARIES_P3) { |
541 | 11 | if (c.white_point == JXL_WHITE_POINT_D65) { |
542 | 5 | primaries = 12; |
543 | 6 | } else if (c.white_point == JXL_WHITE_POINT_DCI) { |
544 | 2 | primaries = 11; |
545 | 4 | } else { |
546 | 4 | return; |
547 | 4 | } |
548 | 2.87k | } else if (c.primaries != JXL_PRIMARIES_CUSTOM && |
549 | 2.87k | c.white_point == JXL_WHITE_POINT_D65) { |
550 | 2.84k | primaries = static_cast<uint8_t>(c.primaries); |
551 | 2.84k | } else { |
552 | 37 | return; |
553 | 37 | } |
554 | 2.84k | JxlTransferFunction tf = c.transfer_function; |
555 | 2.84k | if (tf == JXL_TRANSFER_FUNCTION_UNKNOWN || |
556 | 2.84k | tf == JXL_TRANSFER_FUNCTION_GAMMA) { |
557 | 6 | return; |
558 | 6 | } |
559 | 2.84k | WriteICCTag("cicp", tags->size(), tags); |
560 | 2.84k | WriteICCUint32(0, tags->size(), tags); |
561 | 2.84k | WriteICCUint8(primaries, tags->size(), tags); |
562 | 2.84k | WriteICCUint8(static_cast<uint8_t>(tf), tags->size(), tags); |
563 | | // Matrix |
564 | 2.84k | WriteICCUint8(0, tags->size(), tags); |
565 | | // Full range |
566 | 2.84k | WriteICCUint8(1, tags->size(), tags); |
567 | 2.84k | FinalizeICCTag(tags, offset, size); |
568 | 2.84k | AddToICCTagTable("cicp", *offset, *size, tagtable, offsets); |
569 | 2.84k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::MaybeCreateICCCICPTag(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) color_encoding_internal.cc:jxl::detail::MaybeCreateICCCICPTag(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) Line | Count | Source | 535 | 2.88k | std::vector<size_t>* offsets) { | 536 | 2.88k | if (c.color_space != JXL_COLOR_SPACE_RGB) { | 537 | 0 | return; | 538 | 0 | } | 539 | 2.88k | uint8_t primaries = 0; | 540 | 2.88k | if (c.primaries == JXL_PRIMARIES_P3) { | 541 | 11 | if (c.white_point == JXL_WHITE_POINT_D65) { | 542 | 5 | primaries = 12; | 543 | 6 | } else if (c.white_point == JXL_WHITE_POINT_DCI) { | 544 | 2 | primaries = 11; | 545 | 4 | } else { | 546 | 4 | return; | 547 | 4 | } | 548 | 2.87k | } else if (c.primaries != JXL_PRIMARIES_CUSTOM && | 549 | 2.87k | c.white_point == JXL_WHITE_POINT_D65) { | 550 | 2.84k | primaries = static_cast<uint8_t>(c.primaries); | 551 | 2.84k | } else { | 552 | 37 | return; | 553 | 37 | } | 554 | 2.84k | JxlTransferFunction tf = c.transfer_function; | 555 | 2.84k | if (tf == JXL_TRANSFER_FUNCTION_UNKNOWN || | 556 | 2.84k | tf == JXL_TRANSFER_FUNCTION_GAMMA) { | 557 | 6 | return; | 558 | 6 | } | 559 | 2.84k | WriteICCTag("cicp", tags->size(), tags); | 560 | 2.84k | WriteICCUint32(0, tags->size(), tags); | 561 | 2.84k | WriteICCUint8(primaries, tags->size(), tags); | 562 | 2.84k | WriteICCUint8(static_cast<uint8_t>(tf), tags->size(), tags); | 563 | | // Matrix | 564 | 2.84k | WriteICCUint8(0, tags->size(), tags); | 565 | | // Full range | 566 | 2.84k | WriteICCUint8(1, tags->size(), tags); | 567 | 2.84k | FinalizeICCTag(tags, offset, size); | 568 | 2.84k | AddToICCTagTable("cicp", *offset, *size, tagtable, offsets); | 569 | 2.84k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::MaybeCreateICCCICPTag(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::MaybeCreateICCCICPTag(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, unsigned long*, unsigned long*, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*, std::__1::vector<unsigned long, std::__1::allocator<unsigned long> >*) |
570 | | |
571 | | static void CreateICCCurvCurvTag(const std::vector<uint16_t>& curve, |
572 | 19 | std::vector<uint8_t>* tags) { |
573 | 19 | size_t pos = tags->size(); |
574 | 19 | tags->resize(tags->size() + 12 + curve.size() * 2, 0); |
575 | 19 | WriteICCTag("curv", pos, tags); |
576 | 19 | WriteICCUint32(0, pos + 4, tags); |
577 | 19 | WriteICCUint32(curve.size(), pos + 8, tags); |
578 | 1.23k | for (size_t i = 0; i < curve.size(); i++) { |
579 | 1.21k | WriteICCUint16(curve[i], pos + 12 + i * 2, tags); |
580 | 1.21k | } |
581 | 19 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCCurvCurvTag(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCCurvCurvTag(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 572 | 19 | std::vector<uint8_t>* tags) { | 573 | 19 | size_t pos = tags->size(); | 574 | 19 | tags->resize(tags->size() + 12 + curve.size() * 2, 0); | 575 | 19 | WriteICCTag("curv", pos, tags); | 576 | 19 | WriteICCUint32(0, pos + 4, tags); | 577 | 19 | WriteICCUint32(curve.size(), pos + 8, tags); | 578 | 1.23k | for (size_t i = 0; i < curve.size(); i++) { | 579 | 1.21k | WriteICCUint16(curve[i], pos + 12 + i * 2, tags); | 580 | 1.21k | } | 581 | 19 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCCurvCurvTag(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCCurvCurvTag(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> > const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
582 | | |
583 | | // Writes 12 + 4*params.size() bytes |
584 | | static Status CreateICCCurvParaTag(const std::vector<float>& params, |
585 | | size_t curve_type, |
586 | 2.92k | std::vector<uint8_t>* tags) { |
587 | 2.92k | WriteICCTag("para", tags->size(), tags); |
588 | 2.92k | WriteICCUint32(0, tags->size(), tags); |
589 | 2.92k | WriteICCUint16(curve_type, tags->size(), tags); |
590 | 2.92k | WriteICCUint16(0, tags->size(), tags); |
591 | 14.3k | for (float param : params) { |
592 | 14.3k | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(param, tags->size(), tags)); |
593 | 14.3k | } |
594 | 2.92k | return true; |
595 | 2.92k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCCurvParaTag(std::__1::vector<float, std::__1::allocator<float> > const&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCCurvParaTag(std::__1::vector<float, std::__1::allocator<float> > const&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 586 | 2.92k | std::vector<uint8_t>* tags) { | 587 | 2.92k | WriteICCTag("para", tags->size(), tags); | 588 | 2.92k | WriteICCUint32(0, tags->size(), tags); | 589 | 2.92k | WriteICCUint16(curve_type, tags->size(), tags); | 590 | 2.92k | WriteICCUint16(0, tags->size(), tags); | 591 | 14.3k | for (float param : params) { | 592 | 14.3k | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(param, tags->size(), tags)); | 593 | 14.3k | } | 594 | 2.92k | return true; | 595 | 2.92k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCCurvParaTag(std::__1::vector<float, std::__1::allocator<float> > const&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCCurvParaTag(std::__1::vector<float, std::__1::allocator<float> > const&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
596 | | |
597 | 2 | static Status CreateICCLutAtoBTagForXYB(std::vector<uint8_t>* tags) { |
598 | 2 | WriteICCTag("mAB ", tags->size(), tags); |
599 | | // 4 reserved bytes set to 0 |
600 | 2 | WriteICCUint32(0, tags->size(), tags); |
601 | | // number of input channels |
602 | 2 | WriteICCUint8(3, tags->size(), tags); |
603 | | // number of output channels |
604 | 2 | WriteICCUint8(3, tags->size(), tags); |
605 | | // 2 reserved bytes for padding |
606 | 2 | WriteICCUint16(0, tags->size(), tags); |
607 | | // offset to first B curve |
608 | 2 | WriteICCUint32(32, tags->size(), tags); |
609 | | // offset to matrix |
610 | 2 | WriteICCUint32(244, tags->size(), tags); |
611 | | // offset to first M curve |
612 | 2 | WriteICCUint32(148, tags->size(), tags); |
613 | | // offset to CLUT |
614 | 2 | WriteICCUint32(80, tags->size(), tags); |
615 | | // offset to first A curve |
616 | | // (reuse linear B curves) |
617 | 2 | WriteICCUint32(32, tags->size(), tags); |
618 | | |
619 | | // offset = 32 |
620 | | // no-op curves |
621 | 2 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); |
622 | 2 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); |
623 | 2 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); |
624 | | // offset = 80 |
625 | | // number of grid points for each input channel |
626 | 34 | for (int i = 0; i < 16; ++i) { |
627 | 32 | WriteICCUint8(i < 3 ? 2 : 0, tags->size(), tags); |
628 | 32 | } |
629 | | // precision = 2 |
630 | 2 | WriteICCUint8(2, tags->size(), tags); |
631 | | // 3 bytes of padding |
632 | 2 | WriteICCUint8(0, tags->size(), tags); |
633 | 2 | WriteICCUint16(0, tags->size(), tags); |
634 | | // 2*2*2*3 entries of 2 bytes each = 48 bytes |
635 | 2 | const jxl::cms::ColorCube3D& cube = jxl::cms::UnscaledA2BCube(); |
636 | 6 | for (size_t ix = 0; ix < 2; ++ix) { |
637 | 12 | for (size_t iy = 0; iy < 2; ++iy) { |
638 | 24 | for (size_t ib = 0; ib < 2; ++ib) { |
639 | 16 | const jxl::cms::ColorCube0D& out_f = cube[ix][iy][ib]; |
640 | 64 | for (int i = 0; i < 3; ++i) { |
641 | 48 | int32_t val = static_cast<int32_t>(std::lroundf(65535 * out_f[i])); |
642 | 48 | JXL_DASSERT(val >= 0 && val <= 65535); |
643 | 48 | WriteICCUint16(val, tags->size(), tags); |
644 | 48 | } |
645 | 16 | } |
646 | 8 | } |
647 | 4 | } |
648 | | // offset = 148 |
649 | | // 3 curves with 5 parameters = 3 * (12 + 5 * 4) = 96 bytes |
650 | 8 | for (size_t i = 0; i < 3; ++i) { |
651 | 6 | const float b = -jxl::cms::kXYBOffset[i] - |
652 | 6 | std::cbrt(jxl::cms::kNegOpsinAbsorbanceBiasRGB[i]); |
653 | 6 | std::vector<float> params = { |
654 | 6 | 3, |
655 | 6 | 1.0f / jxl::cms::kXYBScale[i], |
656 | 6 | b, |
657 | 6 | 0, // unused |
658 | 6 | std::max(0.f, -b * jxl::cms::kXYBScale[i]), // make skcms happy |
659 | 6 | }; |
660 | 6 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag(params, 3, tags)); |
661 | 6 | } |
662 | | // offset = 244 |
663 | 2 | const double matrix[] = {1.5170095, -1.1065225, 0.071623, |
664 | 2 | -0.050022, 0.5683655, -0.018344, |
665 | 2 | -1.387676, 1.1145555, 0.6857255}; |
666 | | // 12 * 4 = 48 bytes |
667 | 18 | for (double v : matrix) { |
668 | 18 | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(v, tags->size(), tags)); |
669 | 18 | } |
670 | 8 | for (size_t i = 0; i < 3; ++i) { |
671 | 6 | float intercept = 0; |
672 | 24 | for (size_t j = 0; j < 3; ++j) { |
673 | 18 | intercept += matrix[i * 3 + j] * jxl::cms::kNegOpsinAbsorbanceBiasRGB[j]; |
674 | 18 | } |
675 | 6 | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(intercept, tags->size(), tags)); |
676 | 6 | } |
677 | 2 | return true; |
678 | 2 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCLutAtoBTagForXYB(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCLutAtoBTagForXYB(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 597 | 2 | static Status CreateICCLutAtoBTagForXYB(std::vector<uint8_t>* tags) { | 598 | 2 | WriteICCTag("mAB ", tags->size(), tags); | 599 | | // 4 reserved bytes set to 0 | 600 | 2 | WriteICCUint32(0, tags->size(), tags); | 601 | | // number of input channels | 602 | 2 | WriteICCUint8(3, tags->size(), tags); | 603 | | // number of output channels | 604 | 2 | WriteICCUint8(3, tags->size(), tags); | 605 | | // 2 reserved bytes for padding | 606 | 2 | WriteICCUint16(0, tags->size(), tags); | 607 | | // offset to first B curve | 608 | 2 | WriteICCUint32(32, tags->size(), tags); | 609 | | // offset to matrix | 610 | 2 | WriteICCUint32(244, tags->size(), tags); | 611 | | // offset to first M curve | 612 | 2 | WriteICCUint32(148, tags->size(), tags); | 613 | | // offset to CLUT | 614 | 2 | WriteICCUint32(80, tags->size(), tags); | 615 | | // offset to first A curve | 616 | | // (reuse linear B curves) | 617 | 2 | WriteICCUint32(32, tags->size(), tags); | 618 | | | 619 | | // offset = 32 | 620 | | // no-op curves | 621 | 2 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); | 622 | 2 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); | 623 | 2 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); | 624 | | // offset = 80 | 625 | | // number of grid points for each input channel | 626 | 34 | for (int i = 0; i < 16; ++i) { | 627 | 32 | WriteICCUint8(i < 3 ? 2 : 0, tags->size(), tags); | 628 | 32 | } | 629 | | // precision = 2 | 630 | 2 | WriteICCUint8(2, tags->size(), tags); | 631 | | // 3 bytes of padding | 632 | 2 | WriteICCUint8(0, tags->size(), tags); | 633 | 2 | WriteICCUint16(0, tags->size(), tags); | 634 | | // 2*2*2*3 entries of 2 bytes each = 48 bytes | 635 | 2 | const jxl::cms::ColorCube3D& cube = jxl::cms::UnscaledA2BCube(); | 636 | 6 | for (size_t ix = 0; ix < 2; ++ix) { | 637 | 12 | for (size_t iy = 0; iy < 2; ++iy) { | 638 | 24 | for (size_t ib = 0; ib < 2; ++ib) { | 639 | 16 | const jxl::cms::ColorCube0D& out_f = cube[ix][iy][ib]; | 640 | 64 | for (int i = 0; i < 3; ++i) { | 641 | 48 | int32_t val = static_cast<int32_t>(std::lroundf(65535 * out_f[i])); | 642 | 48 | JXL_DASSERT(val >= 0 && val <= 65535); | 643 | 48 | WriteICCUint16(val, tags->size(), tags); | 644 | 48 | } | 645 | 16 | } | 646 | 8 | } | 647 | 4 | } | 648 | | // offset = 148 | 649 | | // 3 curves with 5 parameters = 3 * (12 + 5 * 4) = 96 bytes | 650 | 8 | for (size_t i = 0; i < 3; ++i) { | 651 | 6 | const float b = -jxl::cms::kXYBOffset[i] - | 652 | 6 | std::cbrt(jxl::cms::kNegOpsinAbsorbanceBiasRGB[i]); | 653 | 6 | std::vector<float> params = { | 654 | 6 | 3, | 655 | 6 | 1.0f / jxl::cms::kXYBScale[i], | 656 | 6 | b, | 657 | 6 | 0, // unused | 658 | 6 | std::max(0.f, -b * jxl::cms::kXYBScale[i]), // make skcms happy | 659 | 6 | }; | 660 | 6 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag(params, 3, tags)); | 661 | 6 | } | 662 | | // offset = 244 | 663 | 2 | const double matrix[] = {1.5170095, -1.1065225, 0.071623, | 664 | 2 | -0.050022, 0.5683655, -0.018344, | 665 | 2 | -1.387676, 1.1145555, 0.6857255}; | 666 | | // 12 * 4 = 48 bytes | 667 | 18 | for (double v : matrix) { | 668 | 18 | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(v, tags->size(), tags)); | 669 | 18 | } | 670 | 8 | for (size_t i = 0; i < 3; ++i) { | 671 | 6 | float intercept = 0; | 672 | 24 | for (size_t j = 0; j < 3; ++j) { | 673 | 18 | intercept += matrix[i * 3 + j] * jxl::cms::kNegOpsinAbsorbanceBiasRGB[j]; | 674 | 18 | } | 675 | 6 | JXL_RETURN_IF_ERROR(WriteICCS15Fixed16(intercept, tags->size(), tags)); | 676 | 6 | } | 677 | 2 | return true; | 678 | 2 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCLutAtoBTagForXYB(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCLutAtoBTagForXYB(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
679 | | |
680 | | static Status CreateICCLutAtoBTagForHDR(JxlColorEncoding c, |
681 | 8 | std::vector<uint8_t>* tags) { |
682 | 8 | static constexpr size_t k3DLutDim = 9; |
683 | 8 | WriteICCTag("mft1", tags->size(), tags); |
684 | | // 4 reserved bytes set to 0 |
685 | 8 | WriteICCUint32(0, tags->size(), tags); |
686 | | // number of input channels |
687 | 8 | WriteICCUint8(3, tags->size(), tags); |
688 | | // number of output channels |
689 | 8 | WriteICCUint8(3, tags->size(), tags); |
690 | | // number of CLUT grid points |
691 | 8 | WriteICCUint8(k3DLutDim, tags->size(), tags); |
692 | | // 1 reserved bytes for padding |
693 | 8 | WriteICCUint8(0, tags->size(), tags); |
694 | | |
695 | | // Matrix (per specification, must be identity if input is not XYZ) |
696 | 32 | for (size_t i = 0; i < 3; ++i) { |
697 | 96 | for (size_t j = 0; j < 3; ++j) { |
698 | 72 | JXL_RETURN_IF_ERROR( |
699 | 72 | WriteICCS15Fixed16(i == j ? 1.f : 0.f, tags->size(), tags)); |
700 | 72 | } |
701 | 24 | } |
702 | | |
703 | | // Input tables |
704 | 32 | for (size_t c = 0; c < 3; ++c) { |
705 | 6.16k | for (size_t i = 0; i < 256; ++i) { |
706 | 6.14k | WriteICCUint8(i, tags->size(), tags); |
707 | 6.14k | } |
708 | 24 | } |
709 | | |
710 | 80 | for (size_t ix = 0; ix < k3DLutDim; ++ix) { |
711 | 720 | for (size_t iy = 0; iy < k3DLutDim; ++iy) { |
712 | 6.48k | for (size_t ib = 0; ib < k3DLutDim; ++ib) { |
713 | 5.83k | float f[3] = {ix * (1.0f / (k3DLutDim - 1)), |
714 | 5.83k | iy * (1.0f / (k3DLutDim - 1)), |
715 | 5.83k | ib * (1.0f / (k3DLutDim - 1))}; |
716 | 5.83k | uint8_t pcslab_out[3]; |
717 | 5.83k | JXL_RETURN_IF_ERROR(ToneMapPixel(c, f, pcslab_out)); |
718 | 17.4k | for (uint8_t val : pcslab_out) { |
719 | 17.4k | WriteICCUint8(val, tags->size(), tags); |
720 | 17.4k | } |
721 | 5.83k | } |
722 | 648 | } |
723 | 72 | } |
724 | | |
725 | | // Output tables |
726 | 32 | for (size_t c = 0; c < 3; ++c) { |
727 | 6.16k | for (size_t i = 0; i < 256; ++i) { |
728 | 6.14k | WriteICCUint8(i, tags->size(), tags); |
729 | 6.14k | } |
730 | 24 | } |
731 | | |
732 | 8 | return true; |
733 | 8 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCLutAtoBTagForHDR(JxlColorEncoding, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCLutAtoBTagForHDR(JxlColorEncoding, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 681 | 8 | std::vector<uint8_t>* tags) { | 682 | 8 | static constexpr size_t k3DLutDim = 9; | 683 | 8 | WriteICCTag("mft1", tags->size(), tags); | 684 | | // 4 reserved bytes set to 0 | 685 | 8 | WriteICCUint32(0, tags->size(), tags); | 686 | | // number of input channels | 687 | 8 | WriteICCUint8(3, tags->size(), tags); | 688 | | // number of output channels | 689 | 8 | WriteICCUint8(3, tags->size(), tags); | 690 | | // number of CLUT grid points | 691 | 8 | WriteICCUint8(k3DLutDim, tags->size(), tags); | 692 | | // 1 reserved bytes for padding | 693 | 8 | WriteICCUint8(0, tags->size(), tags); | 694 | | | 695 | | // Matrix (per specification, must be identity if input is not XYZ) | 696 | 32 | for (size_t i = 0; i < 3; ++i) { | 697 | 96 | for (size_t j = 0; j < 3; ++j) { | 698 | 72 | JXL_RETURN_IF_ERROR( | 699 | 72 | WriteICCS15Fixed16(i == j ? 1.f : 0.f, tags->size(), tags)); | 700 | 72 | } | 701 | 24 | } | 702 | | | 703 | | // Input tables | 704 | 32 | for (size_t c = 0; c < 3; ++c) { | 705 | 6.16k | for (size_t i = 0; i < 256; ++i) { | 706 | 6.14k | WriteICCUint8(i, tags->size(), tags); | 707 | 6.14k | } | 708 | 24 | } | 709 | | | 710 | 80 | for (size_t ix = 0; ix < k3DLutDim; ++ix) { | 711 | 720 | for (size_t iy = 0; iy < k3DLutDim; ++iy) { | 712 | 6.48k | for (size_t ib = 0; ib < k3DLutDim; ++ib) { | 713 | 5.83k | float f[3] = {ix * (1.0f / (k3DLutDim - 1)), | 714 | 5.83k | iy * (1.0f / (k3DLutDim - 1)), | 715 | 5.83k | ib * (1.0f / (k3DLutDim - 1))}; | 716 | 5.83k | uint8_t pcslab_out[3]; | 717 | 5.83k | JXL_RETURN_IF_ERROR(ToneMapPixel(c, f, pcslab_out)); | 718 | 17.4k | for (uint8_t val : pcslab_out) { | 719 | 17.4k | WriteICCUint8(val, tags->size(), tags); | 720 | 17.4k | } | 721 | 5.83k | } | 722 | 648 | } | 723 | 72 | } | 724 | | | 725 | | // Output tables | 726 | 32 | for (size_t c = 0; c < 3; ++c) { | 727 | 6.16k | for (size_t i = 0; i < 256; ++i) { | 728 | 6.14k | WriteICCUint8(i, tags->size(), tags); | 729 | 6.14k | } | 730 | 24 | } | 731 | | | 732 | 8 | return true; | 733 | 8 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCLutAtoBTagForHDR(JxlColorEncoding, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCLutAtoBTagForHDR(JxlColorEncoding, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
734 | | |
735 | | // Some software (Apple Safari, Preview) requires this. |
736 | 10 | static Status CreateICCNoOpBToATag(std::vector<uint8_t>* tags) { |
737 | 10 | WriteICCTag("mBA ", tags->size(), tags); |
738 | | // 4 reserved bytes set to 0 |
739 | 10 | WriteICCUint32(0, tags->size(), tags); |
740 | | // number of input channels |
741 | 10 | WriteICCUint8(3, tags->size(), tags); |
742 | | // number of output channels |
743 | 10 | WriteICCUint8(3, tags->size(), tags); |
744 | | // 2 reserved bytes for padding |
745 | 10 | WriteICCUint16(0, tags->size(), tags); |
746 | | // offset to first B curve |
747 | 10 | WriteICCUint32(32, tags->size(), tags); |
748 | | // offset to matrix |
749 | 10 | WriteICCUint32(0, tags->size(), tags); |
750 | | // offset to first M curve |
751 | 10 | WriteICCUint32(0, tags->size(), tags); |
752 | | // offset to CLUT |
753 | 10 | WriteICCUint32(0, tags->size(), tags); |
754 | | // offset to first A curve |
755 | 10 | WriteICCUint32(0, tags->size(), tags); |
756 | | |
757 | 10 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); |
758 | 10 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); |
759 | 10 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); |
760 | | |
761 | 10 | return true; |
762 | 10 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::CreateICCNoOpBToATag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::CreateICCNoOpBToATag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 736 | 10 | static Status CreateICCNoOpBToATag(std::vector<uint8_t>* tags) { | 737 | 10 | WriteICCTag("mBA ", tags->size(), tags); | 738 | | // 4 reserved bytes set to 0 | 739 | 10 | WriteICCUint32(0, tags->size(), tags); | 740 | | // number of input channels | 741 | 10 | WriteICCUint8(3, tags->size(), tags); | 742 | | // number of output channels | 743 | 10 | WriteICCUint8(3, tags->size(), tags); | 744 | | // 2 reserved bytes for padding | 745 | 10 | WriteICCUint16(0, tags->size(), tags); | 746 | | // offset to first B curve | 747 | 10 | WriteICCUint32(32, tags->size(), tags); | 748 | | // offset to matrix | 749 | 10 | WriteICCUint32(0, tags->size(), tags); | 750 | | // offset to first M curve | 751 | 10 | WriteICCUint32(0, tags->size(), tags); | 752 | | // offset to CLUT | 753 | 10 | WriteICCUint32(0, tags->size(), tags); | 754 | | // offset to first A curve | 755 | 10 | WriteICCUint32(0, tags->size(), tags); | 756 | | | 757 | 10 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); | 758 | 10 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); | 759 | 10 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({1.0f}, 0, tags)); | 760 | | | 761 | 10 | return true; | 762 | 10 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::CreateICCNoOpBToATag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::CreateICCNoOpBToATag(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
763 | | |
764 | | // These strings are baked into Description - do not change. |
765 | | |
766 | 2.92k | static std::string ToString(JxlColorSpace color_space) { |
767 | 2.92k | switch (color_space) { |
768 | 2.89k | case JXL_COLOR_SPACE_RGB: |
769 | 2.89k | return "RGB"; |
770 | 26 | case JXL_COLOR_SPACE_GRAY: |
771 | 26 | return "Gra"; |
772 | 2 | case JXL_COLOR_SPACE_XYB: |
773 | 2 | return "XYB"; |
774 | 0 | case JXL_COLOR_SPACE_UNKNOWN: |
775 | 0 | return "CS?"; |
776 | 2.92k | } |
777 | | // Should not happen - visitor fails if enum is invalid. |
778 | 0 | JXL_UNREACHABLE("Invalid ColorSpace %u", static_cast<uint32_t>(color_space)); |
779 | 0 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ToString(JxlColorSpace) color_encoding_internal.cc:jxl::detail::ToString(JxlColorSpace) Line | Count | Source | 766 | 2.92k | static std::string ToString(JxlColorSpace color_space) { | 767 | 2.92k | switch (color_space) { | 768 | 2.89k | case JXL_COLOR_SPACE_RGB: | 769 | 2.89k | return "RGB"; | 770 | 26 | case JXL_COLOR_SPACE_GRAY: | 771 | 26 | return "Gra"; | 772 | 2 | case JXL_COLOR_SPACE_XYB: | 773 | 2 | return "XYB"; | 774 | 0 | case JXL_COLOR_SPACE_UNKNOWN: | 775 | 0 | return "CS?"; | 776 | 2.92k | } | 777 | | // Should not happen - visitor fails if enum is invalid. | 778 | 0 | JXL_UNREACHABLE("Invalid ColorSpace %u", static_cast<uint32_t>(color_space)); | 779 | 0 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ToString(JxlColorSpace) Unexecuted instantiation: image_metadata.cc:jxl::detail::ToString(JxlColorSpace) |
780 | | |
781 | 2.88k | static std::string ToString(JxlWhitePoint white_point) { |
782 | 2.88k | switch (white_point) { |
783 | 2.87k | case JXL_WHITE_POINT_D65: |
784 | 2.87k | return "D65"; |
785 | 0 | case JXL_WHITE_POINT_CUSTOM: |
786 | 0 | return "Cst"; |
787 | 5 | case JXL_WHITE_POINT_E: |
788 | 5 | return "EER"; |
789 | 4 | case JXL_WHITE_POINT_DCI: |
790 | 4 | return "DCI"; |
791 | 2.88k | } |
792 | | // Should not happen - visitor fails if enum is invalid. |
793 | 0 | JXL_UNREACHABLE("Invalid WhitePoint %u", static_cast<uint32_t>(white_point)); |
794 | 0 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ToString(JxlWhitePoint) color_encoding_internal.cc:jxl::detail::ToString(JxlWhitePoint) Line | Count | Source | 781 | 2.88k | static std::string ToString(JxlWhitePoint white_point) { | 782 | 2.88k | switch (white_point) { | 783 | 2.87k | case JXL_WHITE_POINT_D65: | 784 | 2.87k | return "D65"; | 785 | 0 | case JXL_WHITE_POINT_CUSTOM: | 786 | 0 | return "Cst"; | 787 | 5 | case JXL_WHITE_POINT_E: | 788 | 5 | return "EER"; | 789 | 4 | case JXL_WHITE_POINT_DCI: | 790 | 4 | return "DCI"; | 791 | 2.88k | } | 792 | | // Should not happen - visitor fails if enum is invalid. | 793 | 0 | JXL_UNREACHABLE("Invalid WhitePoint %u", static_cast<uint32_t>(white_point)); | 794 | 0 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ToString(JxlWhitePoint) Unexecuted instantiation: image_metadata.cc:jxl::detail::ToString(JxlWhitePoint) |
795 | | |
796 | 2.87k | static std::string ToString(JxlPrimaries primaries) { |
797 | 2.87k | switch (primaries) { |
798 | 2.85k | case JXL_PRIMARIES_SRGB: |
799 | 2.85k | return "SRG"; |
800 | 8 | case JXL_PRIMARIES_2100: |
801 | 8 | return "202"; |
802 | 10 | case JXL_PRIMARIES_P3: |
803 | 10 | return "DCI"; |
804 | 0 | case JXL_PRIMARIES_CUSTOM: |
805 | 0 | return "Cst"; |
806 | 2.87k | } |
807 | | // Should not happen - visitor fails if enum is invalid. |
808 | 0 | JXL_UNREACHABLE("Invalid Primaries %u", static_cast<uint32_t>(primaries)); |
809 | 0 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ToString(JxlPrimaries) color_encoding_internal.cc:jxl::detail::ToString(JxlPrimaries) Line | Count | Source | 796 | 2.87k | static std::string ToString(JxlPrimaries primaries) { | 797 | 2.87k | switch (primaries) { | 798 | 2.85k | case JXL_PRIMARIES_SRGB: | 799 | 2.85k | return "SRG"; | 800 | 8 | case JXL_PRIMARIES_2100: | 801 | 8 | return "202"; | 802 | 10 | case JXL_PRIMARIES_P3: | 803 | 10 | return "DCI"; | 804 | 0 | case JXL_PRIMARIES_CUSTOM: | 805 | 0 | return "Cst"; | 806 | 2.87k | } | 807 | | // Should not happen - visitor fails if enum is invalid. | 808 | 0 | JXL_UNREACHABLE("Invalid Primaries %u", static_cast<uint32_t>(primaries)); | 809 | 0 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ToString(JxlPrimaries) Unexecuted instantiation: image_metadata.cc:jxl::detail::ToString(JxlPrimaries) |
810 | | |
811 | 2.90k | static std::string ToString(JxlTransferFunction transfer_function) { |
812 | 2.90k | switch (transfer_function) { |
813 | 2.82k | case JXL_TRANSFER_FUNCTION_SRGB: |
814 | 2.82k | return "SRG"; |
815 | 6 | case JXL_TRANSFER_FUNCTION_LINEAR: |
816 | 6 | return "Lin"; |
817 | 39 | case JXL_TRANSFER_FUNCTION_709: |
818 | 39 | return "709"; |
819 | 19 | case JXL_TRANSFER_FUNCTION_PQ: |
820 | 19 | return "PeQ"; |
821 | 8 | case JXL_TRANSFER_FUNCTION_HLG: |
822 | 8 | return "HLG"; |
823 | 3 | case JXL_TRANSFER_FUNCTION_DCI: |
824 | 3 | return "DCI"; |
825 | 0 | case JXL_TRANSFER_FUNCTION_UNKNOWN: |
826 | 0 | return "TF?"; |
827 | 0 | case JXL_TRANSFER_FUNCTION_GAMMA: |
828 | 0 | JXL_UNREACHABLE("Invalid TransferFunction: gamma"); |
829 | 2.90k | } |
830 | | // Should not happen - visitor fails if enum is invalid. |
831 | 0 | JXL_UNREACHABLE("Invalid TransferFunction %u", |
832 | 0 | static_cast<uint32_t>(transfer_function)); |
833 | 0 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ToString(JxlTransferFunction) color_encoding_internal.cc:jxl::detail::ToString(JxlTransferFunction) Line | Count | Source | 811 | 2.90k | static std::string ToString(JxlTransferFunction transfer_function) { | 812 | 2.90k | switch (transfer_function) { | 813 | 2.82k | case JXL_TRANSFER_FUNCTION_SRGB: | 814 | 2.82k | return "SRG"; | 815 | 6 | case JXL_TRANSFER_FUNCTION_LINEAR: | 816 | 6 | return "Lin"; | 817 | 39 | case JXL_TRANSFER_FUNCTION_709: | 818 | 39 | return "709"; | 819 | 19 | case JXL_TRANSFER_FUNCTION_PQ: | 820 | 19 | return "PeQ"; | 821 | 8 | case JXL_TRANSFER_FUNCTION_HLG: | 822 | 8 | return "HLG"; | 823 | 3 | case JXL_TRANSFER_FUNCTION_DCI: | 824 | 3 | return "DCI"; | 825 | 0 | case JXL_TRANSFER_FUNCTION_UNKNOWN: | 826 | 0 | return "TF?"; | 827 | 0 | case JXL_TRANSFER_FUNCTION_GAMMA: | 828 | 0 | JXL_UNREACHABLE("Invalid TransferFunction: gamma"); | 829 | 2.90k | } | 830 | | // Should not happen - visitor fails if enum is invalid. | 831 | 0 | JXL_UNREACHABLE("Invalid TransferFunction %u", | 832 | 0 | static_cast<uint32_t>(transfer_function)); | 833 | 0 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ToString(JxlTransferFunction) Unexecuted instantiation: image_metadata.cc:jxl::detail::ToString(JxlTransferFunction) |
834 | | |
835 | 2.92k | static std::string ToString(JxlRenderingIntent rendering_intent) { |
836 | 2.92k | switch (rendering_intent) { |
837 | 59 | case JXL_RENDERING_INTENT_PERCEPTUAL: |
838 | 59 | return "Per"; |
839 | 2.86k | case JXL_RENDERING_INTENT_RELATIVE: |
840 | 2.86k | return "Rel"; |
841 | 3 | case JXL_RENDERING_INTENT_SATURATION: |
842 | 3 | return "Sat"; |
843 | 3 | case JXL_RENDERING_INTENT_ABSOLUTE: |
844 | 3 | return "Abs"; |
845 | 2.92k | } |
846 | | // Should not happen - visitor fails if enum is invalid. |
847 | 0 | JXL_UNREACHABLE("Invalid RenderingIntent %u", |
848 | 0 | static_cast<uint32_t>(rendering_intent)); |
849 | 0 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ToString(JxlRenderingIntent) color_encoding_internal.cc:jxl::detail::ToString(JxlRenderingIntent) Line | Count | Source | 835 | 2.92k | static std::string ToString(JxlRenderingIntent rendering_intent) { | 836 | 2.92k | switch (rendering_intent) { | 837 | 59 | case JXL_RENDERING_INTENT_PERCEPTUAL: | 838 | 59 | return "Per"; | 839 | 2.86k | case JXL_RENDERING_INTENT_RELATIVE: | 840 | 2.86k | return "Rel"; | 841 | 3 | case JXL_RENDERING_INTENT_SATURATION: | 842 | 3 | return "Sat"; | 843 | 3 | case JXL_RENDERING_INTENT_ABSOLUTE: | 844 | 3 | return "Abs"; | 845 | 2.92k | } | 846 | | // Should not happen - visitor fails if enum is invalid. | 847 | 0 | JXL_UNREACHABLE("Invalid RenderingIntent %u", | 848 | 0 | static_cast<uint32_t>(rendering_intent)); | 849 | 0 | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ToString(JxlRenderingIntent) Unexecuted instantiation: image_metadata.cc:jxl::detail::ToString(JxlRenderingIntent) |
850 | | |
851 | 2.93k | static std::string ColorEncodingDescriptionImpl(const JxlColorEncoding& c) { |
852 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_RGB && |
853 | 2.93k | c.white_point == JXL_WHITE_POINT_D65) { |
854 | 2.86k | if (c.rendering_intent == JXL_RENDERING_INTENT_PERCEPTUAL && |
855 | 2.86k | c.transfer_function == JXL_TRANSFER_FUNCTION_SRGB) { |
856 | 3 | if (c.primaries == JXL_PRIMARIES_SRGB) return "sRGB"; |
857 | 2 | if (c.primaries == JXL_PRIMARIES_P3) return "DisplayP3"; |
858 | 2 | } |
859 | 2.86k | if (c.rendering_intent == JXL_RENDERING_INTENT_RELATIVE && |
860 | 2.86k | c.primaries == JXL_PRIMARIES_2100) { |
861 | 5 | if (c.transfer_function == JXL_TRANSFER_FUNCTION_PQ) return "Rec2100PQ"; |
862 | 4 | if (c.transfer_function == JXL_TRANSFER_FUNCTION_HLG) return "Rec2100HLG"; |
863 | 4 | } |
864 | 2.86k | } |
865 | | |
866 | 2.92k | std::string d = ToString(c.color_space); |
867 | | |
868 | 2.92k | bool explicit_wp_tf = (c.color_space != JXL_COLOR_SPACE_XYB); |
869 | 2.92k | if (explicit_wp_tf) { |
870 | 2.92k | d += '_'; |
871 | 2.92k | if (c.white_point == JXL_WHITE_POINT_CUSTOM) { |
872 | 41 | d += jxl::ToString(c.white_point_xy[0]) + ';'; |
873 | 41 | d += jxl::ToString(c.white_point_xy[1]); |
874 | 2.88k | } else { |
875 | 2.88k | d += ToString(c.white_point); |
876 | 2.88k | } |
877 | 2.92k | } |
878 | | |
879 | 2.92k | if ((c.color_space != JXL_COLOR_SPACE_GRAY) && |
880 | 2.92k | (c.color_space != JXL_COLOR_SPACE_XYB)) { |
881 | 2.89k | d += '_'; |
882 | 2.89k | if (c.primaries == JXL_PRIMARIES_CUSTOM) { |
883 | 25 | d += jxl::ToString(c.primaries_red_xy[0]) + ';'; |
884 | 25 | d += jxl::ToString(c.primaries_red_xy[1]) + ';'; |
885 | 25 | d += jxl::ToString(c.primaries_green_xy[0]) + ';'; |
886 | 25 | d += jxl::ToString(c.primaries_green_xy[1]) + ';'; |
887 | 25 | d += jxl::ToString(c.primaries_blue_xy[0]) + ';'; |
888 | 25 | d += jxl::ToString(c.primaries_blue_xy[1]); |
889 | 2.87k | } else { |
890 | 2.87k | d += ToString(c.primaries); |
891 | 2.87k | } |
892 | 2.89k | } |
893 | | |
894 | 2.92k | d += '_'; |
895 | 2.92k | d += ToString(c.rendering_intent); |
896 | | |
897 | 2.92k | if (explicit_wp_tf) { |
898 | 2.92k | JxlTransferFunction tf = c.transfer_function; |
899 | 2.92k | d += '_'; |
900 | 2.92k | if (tf == JXL_TRANSFER_FUNCTION_GAMMA) { |
901 | 23 | d += 'g'; |
902 | 23 | d += jxl::ToString(c.gamma); |
903 | 2.90k | } else { |
904 | 2.90k | d += ToString(tf); |
905 | 2.90k | } |
906 | 2.92k | } |
907 | 2.92k | return d; |
908 | 2.93k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::ColorEncodingDescriptionImpl(JxlColorEncoding const&) color_encoding_internal.cc:jxl::detail::ColorEncodingDescriptionImpl(JxlColorEncoding const&) Line | Count | Source | 851 | 2.93k | static std::string ColorEncodingDescriptionImpl(const JxlColorEncoding& c) { | 852 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_RGB && | 853 | 2.93k | c.white_point == JXL_WHITE_POINT_D65) { | 854 | 2.86k | if (c.rendering_intent == JXL_RENDERING_INTENT_PERCEPTUAL && | 855 | 2.86k | c.transfer_function == JXL_TRANSFER_FUNCTION_SRGB) { | 856 | 3 | if (c.primaries == JXL_PRIMARIES_SRGB) return "sRGB"; | 857 | 2 | if (c.primaries == JXL_PRIMARIES_P3) return "DisplayP3"; | 858 | 2 | } | 859 | 2.86k | if (c.rendering_intent == JXL_RENDERING_INTENT_RELATIVE && | 860 | 2.86k | c.primaries == JXL_PRIMARIES_2100) { | 861 | 5 | if (c.transfer_function == JXL_TRANSFER_FUNCTION_PQ) return "Rec2100PQ"; | 862 | 4 | if (c.transfer_function == JXL_TRANSFER_FUNCTION_HLG) return "Rec2100HLG"; | 863 | 4 | } | 864 | 2.86k | } | 865 | | | 866 | 2.92k | std::string d = ToString(c.color_space); | 867 | | | 868 | 2.92k | bool explicit_wp_tf = (c.color_space != JXL_COLOR_SPACE_XYB); | 869 | 2.92k | if (explicit_wp_tf) { | 870 | 2.92k | d += '_'; | 871 | 2.92k | if (c.white_point == JXL_WHITE_POINT_CUSTOM) { | 872 | 41 | d += jxl::ToString(c.white_point_xy[0]) + ';'; | 873 | 41 | d += jxl::ToString(c.white_point_xy[1]); | 874 | 2.88k | } else { | 875 | 2.88k | d += ToString(c.white_point); | 876 | 2.88k | } | 877 | 2.92k | } | 878 | | | 879 | 2.92k | if ((c.color_space != JXL_COLOR_SPACE_GRAY) && | 880 | 2.92k | (c.color_space != JXL_COLOR_SPACE_XYB)) { | 881 | 2.89k | d += '_'; | 882 | 2.89k | if (c.primaries == JXL_PRIMARIES_CUSTOM) { | 883 | 25 | d += jxl::ToString(c.primaries_red_xy[0]) + ';'; | 884 | 25 | d += jxl::ToString(c.primaries_red_xy[1]) + ';'; | 885 | 25 | d += jxl::ToString(c.primaries_green_xy[0]) + ';'; | 886 | 25 | d += jxl::ToString(c.primaries_green_xy[1]) + ';'; | 887 | 25 | d += jxl::ToString(c.primaries_blue_xy[0]) + ';'; | 888 | 25 | d += jxl::ToString(c.primaries_blue_xy[1]); | 889 | 2.87k | } else { | 890 | 2.87k | d += ToString(c.primaries); | 891 | 2.87k | } | 892 | 2.89k | } | 893 | | | 894 | 2.92k | d += '_'; | 895 | 2.92k | d += ToString(c.rendering_intent); | 896 | | | 897 | 2.92k | if (explicit_wp_tf) { | 898 | 2.92k | JxlTransferFunction tf = c.transfer_function; | 899 | 2.92k | d += '_'; | 900 | 2.92k | if (tf == JXL_TRANSFER_FUNCTION_GAMMA) { | 901 | 23 | d += 'g'; | 902 | 23 | d += jxl::ToString(c.gamma); | 903 | 2.90k | } else { | 904 | 2.90k | d += ToString(tf); | 905 | 2.90k | } | 906 | 2.92k | } | 907 | 2.92k | return d; | 908 | 2.93k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::ColorEncodingDescriptionImpl(JxlColorEncoding const&) Unexecuted instantiation: image_metadata.cc:jxl::detail::ColorEncodingDescriptionImpl(JxlColorEncoding const&) |
909 | | |
910 | | static Status MaybeCreateProfileImpl(const JxlColorEncoding& c, |
911 | 2.93k | std::vector<uint8_t>* icc) { |
912 | 2.93k | std::vector<uint8_t> header; |
913 | 2.93k | std::vector<uint8_t> tagtable; |
914 | 2.93k | std::vector<uint8_t> tags; |
915 | 2.93k | JxlTransferFunction tf = c.transfer_function; |
916 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_UNKNOWN || |
917 | 2.93k | tf == JXL_TRANSFER_FUNCTION_UNKNOWN) { |
918 | 0 | return false; // Not an error |
919 | 0 | } |
920 | | |
921 | 2.93k | switch (c.color_space) { |
922 | 2.90k | case JXL_COLOR_SPACE_RGB: |
923 | 2.92k | case JXL_COLOR_SPACE_GRAY: |
924 | 2.93k | case JXL_COLOR_SPACE_XYB: |
925 | 2.93k | break; // OK |
926 | 0 | default: |
927 | 0 | return JXL_FAILURE("Invalid CS %u", |
928 | 2.93k | static_cast<unsigned int>(c.color_space)); |
929 | 2.93k | } |
930 | | |
931 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_XYB && |
932 | 2.93k | c.rendering_intent != JXL_RENDERING_INTENT_PERCEPTUAL) { |
933 | 2 | return JXL_FAILURE( |
934 | 2 | "Only perceptual rendering intent implemented for XYB " |
935 | 2 | "ICC profile."); |
936 | 2 | } |
937 | | |
938 | 2.93k | JXL_RETURN_IF_ERROR(CreateICCHeader(c, &header)); |
939 | | |
940 | 2.93k | std::vector<size_t> offsets; |
941 | | // tag count, deferred to later |
942 | 2.93k | WriteICCUint32(0, tagtable.size(), &tagtable); |
943 | | |
944 | 2.93k | size_t tag_offset = 0; |
945 | 2.93k | size_t tag_size = 0; |
946 | | |
947 | 2.93k | CreateICCMlucTag(ColorEncodingDescriptionImpl(c), &tags); |
948 | 2.93k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
949 | 2.93k | AddToICCTagTable("desc", tag_offset, tag_size, &tagtable, &offsets); |
950 | | |
951 | 2.93k | const std::string copyright = "CC0"; |
952 | 2.93k | CreateICCMlucTag(copyright, &tags); |
953 | 2.93k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
954 | 2.93k | AddToICCTagTable("cprt", tag_offset, tag_size, &tagtable, &offsets); |
955 | | |
956 | | // TODO(eustas): isn't it the other way round: gray image has d50 WhitePoint? |
957 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_GRAY) { |
958 | 26 | Color wtpt; |
959 | 26 | JXL_RETURN_IF_ERROR( |
960 | 26 | CIEXYZFromWhiteCIExy(c.white_point_xy[0], c.white_point_xy[1], wtpt)); |
961 | 25 | JXL_RETURN_IF_ERROR(CreateICCXYZTag(wtpt, &tags)); |
962 | 2.90k | } else { |
963 | 2.90k | Color d50{0.964203, 1.0, 0.824905}; |
964 | 2.90k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(d50, &tags)); |
965 | 2.90k | } |
966 | 2.92k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
967 | 2.92k | AddToICCTagTable("wtpt", tag_offset, tag_size, &tagtable, &offsets); |
968 | | |
969 | 2.92k | if (c.color_space != JXL_COLOR_SPACE_GRAY) { |
970 | | // Chromatic adaptation matrix |
971 | 2.90k | Matrix3x3 chad; |
972 | 2.90k | JXL_RETURN_IF_ERROR( |
973 | 2.90k | CreateICCChadMatrix(c.white_point_xy[0], c.white_point_xy[1], chad)); |
974 | | |
975 | 2.89k | JXL_RETURN_IF_ERROR(CreateICCChadTag(chad, &tags)); |
976 | 2.89k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
977 | 2.89k | AddToICCTagTable("chad", tag_offset, tag_size, &tagtable, &offsets); |
978 | 2.89k | } |
979 | | |
980 | 2.91k | if (c.color_space == JXL_COLOR_SPACE_RGB) { |
981 | 2.88k | MaybeCreateICCCICPTag(c, &tags, &tag_offset, &tag_size, &tagtable, |
982 | 2.88k | &offsets); |
983 | | |
984 | 2.88k | Matrix3x3 m; |
985 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCRGBMatrix( |
986 | 2.88k | c.primaries_red_xy[0], c.primaries_red_xy[1], c.primaries_green_xy[0], |
987 | 2.88k | c.primaries_green_xy[1], c.primaries_blue_xy[0], c.primaries_blue_xy[1], |
988 | 2.88k | c.white_point_xy[0], c.white_point_xy[1], m)); |
989 | 2.88k | Color r{m[0][0], m[1][0], m[2][0]}; |
990 | 2.88k | Color g{m[0][1], m[1][1], m[2][1]}; |
991 | 2.88k | Color b{m[0][2], m[1][2], m[2][2]}; |
992 | | |
993 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(r, &tags)); |
994 | 2.88k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
995 | 2.88k | AddToICCTagTable("rXYZ", tag_offset, tag_size, &tagtable, &offsets); |
996 | | |
997 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(g, &tags)); |
998 | 2.88k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
999 | 2.88k | AddToICCTagTable("gXYZ", tag_offset, tag_size, &tagtable, &offsets); |
1000 | | |
1001 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(b, &tags)); |
1002 | 2.88k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
1003 | 2.88k | AddToICCTagTable("bXYZ", tag_offset, tag_size, &tagtable, &offsets); |
1004 | 2.88k | } |
1005 | | |
1006 | 2.90k | if (c.color_space == JXL_COLOR_SPACE_XYB) { |
1007 | 2 | JXL_RETURN_IF_ERROR(CreateICCLutAtoBTagForXYB(&tags)); |
1008 | 2 | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
1009 | 2 | AddToICCTagTable("A2B0", tag_offset, tag_size, &tagtable, &offsets); |
1010 | 2 | JXL_RETURN_IF_ERROR(CreateICCNoOpBToATag(&tags)); |
1011 | 2 | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
1012 | 2 | AddToICCTagTable("B2A0", tag_offset, tag_size, &tagtable, &offsets); |
1013 | 2.90k | } else if (kEnable3DToneMapping && CanToneMap(c)) { |
1014 | 8 | JXL_RETURN_IF_ERROR(CreateICCLutAtoBTagForHDR(c, &tags)); |
1015 | 8 | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
1016 | 8 | AddToICCTagTable("A2B0", tag_offset, tag_size, &tagtable, &offsets); |
1017 | 8 | JXL_RETURN_IF_ERROR(CreateICCNoOpBToATag(&tags)); |
1018 | 8 | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
1019 | 8 | AddToICCTagTable("B2A0", tag_offset, tag_size, &tagtable, &offsets); |
1020 | 2.89k | } else { |
1021 | 2.89k | if (tf == JXL_TRANSFER_FUNCTION_GAMMA) { |
1022 | 19 | float gamma = 1.0 / c.gamma; |
1023 | 19 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({gamma}, 0, &tags)); |
1024 | 2.87k | } else if (c.color_space != JXL_COLOR_SPACE_XYB) { |
1025 | 2.87k | switch (tf) { |
1026 | 7 | case JXL_TRANSFER_FUNCTION_HLG: |
1027 | 7 | CreateICCCurvCurvTag( |
1028 | 7 | CreateTableCurve(64, ExtraTF::kHLG, CanToneMap(c)), &tags); |
1029 | 7 | break; |
1030 | 12 | case JXL_TRANSFER_FUNCTION_PQ: |
1031 | 12 | CreateICCCurvCurvTag( |
1032 | 12 | CreateTableCurve(64, ExtraTF::kPQ, CanToneMap(c)), &tags); |
1033 | 12 | break; |
1034 | 2.82k | case JXL_TRANSFER_FUNCTION_SRGB: |
1035 | 2.82k | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag( |
1036 | 2.82k | {2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045}, 3, |
1037 | 2.82k | &tags)); |
1038 | 2.82k | break; |
1039 | 2.82k | case JXL_TRANSFER_FUNCTION_709: |
1040 | 25 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag( |
1041 | 25 | {1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081}, 3, |
1042 | 25 | &tags)); |
1043 | 25 | break; |
1044 | 25 | case JXL_TRANSFER_FUNCTION_LINEAR: |
1045 | 3 | JXL_RETURN_IF_ERROR( |
1046 | 3 | CreateICCCurvParaTag({1.0, 1.0, 0.0, 1.0, 0.0}, 3, &tags)); |
1047 | 3 | break; |
1048 | 3 | case JXL_TRANSFER_FUNCTION_DCI: |
1049 | 3 | JXL_RETURN_IF_ERROR( |
1050 | 3 | CreateICCCurvParaTag({2.6, 1.0, 0.0, 1.0, 0.0}, 3, &tags)); |
1051 | 3 | break; |
1052 | 3 | default: |
1053 | 0 | JXL_UNREACHABLE("Unknown TF %u", static_cast<unsigned int>(tf)); |
1054 | 2.87k | } |
1055 | 2.87k | } |
1056 | 2.89k | FinalizeICCTag(&tags, &tag_offset, &tag_size); |
1057 | 2.89k | if (c.color_space == JXL_COLOR_SPACE_GRAY) { |
1058 | 23 | AddToICCTagTable("kTRC", tag_offset, tag_size, &tagtable, &offsets); |
1059 | 2.87k | } else { |
1060 | 2.87k | AddToICCTagTable("rTRC", tag_offset, tag_size, &tagtable, &offsets); |
1061 | 2.87k | AddToICCTagTable("gTRC", tag_offset, tag_size, &tagtable, &offsets); |
1062 | 2.87k | AddToICCTagTable("bTRC", tag_offset, tag_size, &tagtable, &offsets); |
1063 | 2.87k | } |
1064 | 2.89k | } |
1065 | | |
1066 | | // Tag count |
1067 | 2.90k | WriteICCUint32(offsets.size(), 0, &tagtable); |
1068 | 34.6k | for (size_t i = 0; i < offsets.size(); i++) { |
1069 | 31.7k | WriteICCUint32(offsets[i] + header.size() + tagtable.size(), 4 + 12 * i + 4, |
1070 | 31.7k | &tagtable); |
1071 | 31.7k | } |
1072 | | |
1073 | | // ICC profile size |
1074 | 2.90k | WriteICCUint32(header.size() + tagtable.size() + tags.size(), 0, &header); |
1075 | | |
1076 | 2.90k | *icc = header; |
1077 | 2.90k | Bytes(tagtable).AppendTo(*icc); |
1078 | 2.90k | Bytes(tags).AppendTo(*icc); |
1079 | | |
1080 | | // The MD5 checksum must be computed on the profile with profile flags, |
1081 | | // rendering intent, and region of the checksum itself, set to 0. |
1082 | | // TODO(lode): manually verify with a reliable tool that this creates correct |
1083 | | // signature (profile id) for ICC profiles. |
1084 | 2.90k | std::vector<uint8_t> icc_sum = *icc; |
1085 | 2.90k | if (icc_sum.size() >= 64 + 4) { |
1086 | 2.90k | memset(icc_sum.data() + 44, 0, 4); |
1087 | 2.90k | memset(icc_sum.data() + 64, 0, 4); |
1088 | 2.90k | } |
1089 | 2.90k | uint8_t checksum[16]; |
1090 | 2.90k | detail::ICCComputeMD5(icc_sum, checksum); |
1091 | | |
1092 | 2.90k | memcpy(icc->data() + 84, checksum, sizeof(checksum)); |
1093 | | |
1094 | 2.90k | return true; |
1095 | 2.90k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::detail::MaybeCreateProfileImpl(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::detail::MaybeCreateProfileImpl(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 911 | 2.93k | std::vector<uint8_t>* icc) { | 912 | 2.93k | std::vector<uint8_t> header; | 913 | 2.93k | std::vector<uint8_t> tagtable; | 914 | 2.93k | std::vector<uint8_t> tags; | 915 | 2.93k | JxlTransferFunction tf = c.transfer_function; | 916 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_UNKNOWN || | 917 | 2.93k | tf == JXL_TRANSFER_FUNCTION_UNKNOWN) { | 918 | 0 | return false; // Not an error | 919 | 0 | } | 920 | | | 921 | 2.93k | switch (c.color_space) { | 922 | 2.90k | case JXL_COLOR_SPACE_RGB: | 923 | 2.92k | case JXL_COLOR_SPACE_GRAY: | 924 | 2.93k | case JXL_COLOR_SPACE_XYB: | 925 | 2.93k | break; // OK | 926 | 0 | default: | 927 | 0 | return JXL_FAILURE("Invalid CS %u", | 928 | 2.93k | static_cast<unsigned int>(c.color_space)); | 929 | 2.93k | } | 930 | | | 931 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_XYB && | 932 | 2.93k | c.rendering_intent != JXL_RENDERING_INTENT_PERCEPTUAL) { | 933 | 2 | return JXL_FAILURE( | 934 | 2 | "Only perceptual rendering intent implemented for XYB " | 935 | 2 | "ICC profile."); | 936 | 2 | } | 937 | | | 938 | 2.93k | JXL_RETURN_IF_ERROR(CreateICCHeader(c, &header)); | 939 | | | 940 | 2.93k | std::vector<size_t> offsets; | 941 | | // tag count, deferred to later | 942 | 2.93k | WriteICCUint32(0, tagtable.size(), &tagtable); | 943 | | | 944 | 2.93k | size_t tag_offset = 0; | 945 | 2.93k | size_t tag_size = 0; | 946 | | | 947 | 2.93k | CreateICCMlucTag(ColorEncodingDescriptionImpl(c), &tags); | 948 | 2.93k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 949 | 2.93k | AddToICCTagTable("desc", tag_offset, tag_size, &tagtable, &offsets); | 950 | | | 951 | 2.93k | const std::string copyright = "CC0"; | 952 | 2.93k | CreateICCMlucTag(copyright, &tags); | 953 | 2.93k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 954 | 2.93k | AddToICCTagTable("cprt", tag_offset, tag_size, &tagtable, &offsets); | 955 | | | 956 | | // TODO(eustas): isn't it the other way round: gray image has d50 WhitePoint? | 957 | 2.93k | if (c.color_space == JXL_COLOR_SPACE_GRAY) { | 958 | 26 | Color wtpt; | 959 | 26 | JXL_RETURN_IF_ERROR( | 960 | 26 | CIEXYZFromWhiteCIExy(c.white_point_xy[0], c.white_point_xy[1], wtpt)); | 961 | 25 | JXL_RETURN_IF_ERROR(CreateICCXYZTag(wtpt, &tags)); | 962 | 2.90k | } else { | 963 | 2.90k | Color d50{0.964203, 1.0, 0.824905}; | 964 | 2.90k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(d50, &tags)); | 965 | 2.90k | } | 966 | 2.92k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 967 | 2.92k | AddToICCTagTable("wtpt", tag_offset, tag_size, &tagtable, &offsets); | 968 | | | 969 | 2.92k | if (c.color_space != JXL_COLOR_SPACE_GRAY) { | 970 | | // Chromatic adaptation matrix | 971 | 2.90k | Matrix3x3 chad; | 972 | 2.90k | JXL_RETURN_IF_ERROR( | 973 | 2.90k | CreateICCChadMatrix(c.white_point_xy[0], c.white_point_xy[1], chad)); | 974 | | | 975 | 2.89k | JXL_RETURN_IF_ERROR(CreateICCChadTag(chad, &tags)); | 976 | 2.89k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 977 | 2.89k | AddToICCTagTable("chad", tag_offset, tag_size, &tagtable, &offsets); | 978 | 2.89k | } | 979 | | | 980 | 2.91k | if (c.color_space == JXL_COLOR_SPACE_RGB) { | 981 | 2.88k | MaybeCreateICCCICPTag(c, &tags, &tag_offset, &tag_size, &tagtable, | 982 | 2.88k | &offsets); | 983 | | | 984 | 2.88k | Matrix3x3 m; | 985 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCRGBMatrix( | 986 | 2.88k | c.primaries_red_xy[0], c.primaries_red_xy[1], c.primaries_green_xy[0], | 987 | 2.88k | c.primaries_green_xy[1], c.primaries_blue_xy[0], c.primaries_blue_xy[1], | 988 | 2.88k | c.white_point_xy[0], c.white_point_xy[1], m)); | 989 | 2.88k | Color r{m[0][0], m[1][0], m[2][0]}; | 990 | 2.88k | Color g{m[0][1], m[1][1], m[2][1]}; | 991 | 2.88k | Color b{m[0][2], m[1][2], m[2][2]}; | 992 | | | 993 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(r, &tags)); | 994 | 2.88k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 995 | 2.88k | AddToICCTagTable("rXYZ", tag_offset, tag_size, &tagtable, &offsets); | 996 | | | 997 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(g, &tags)); | 998 | 2.88k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 999 | 2.88k | AddToICCTagTable("gXYZ", tag_offset, tag_size, &tagtable, &offsets); | 1000 | | | 1001 | 2.88k | JXL_RETURN_IF_ERROR(CreateICCXYZTag(b, &tags)); | 1002 | 2.88k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 1003 | 2.88k | AddToICCTagTable("bXYZ", tag_offset, tag_size, &tagtable, &offsets); | 1004 | 2.88k | } | 1005 | | | 1006 | 2.90k | if (c.color_space == JXL_COLOR_SPACE_XYB) { | 1007 | 2 | JXL_RETURN_IF_ERROR(CreateICCLutAtoBTagForXYB(&tags)); | 1008 | 2 | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 1009 | 2 | AddToICCTagTable("A2B0", tag_offset, tag_size, &tagtable, &offsets); | 1010 | 2 | JXL_RETURN_IF_ERROR(CreateICCNoOpBToATag(&tags)); | 1011 | 2 | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 1012 | 2 | AddToICCTagTable("B2A0", tag_offset, tag_size, &tagtable, &offsets); | 1013 | 2.90k | } else if (kEnable3DToneMapping && CanToneMap(c)) { | 1014 | 8 | JXL_RETURN_IF_ERROR(CreateICCLutAtoBTagForHDR(c, &tags)); | 1015 | 8 | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 1016 | 8 | AddToICCTagTable("A2B0", tag_offset, tag_size, &tagtable, &offsets); | 1017 | 8 | JXL_RETURN_IF_ERROR(CreateICCNoOpBToATag(&tags)); | 1018 | 8 | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 1019 | 8 | AddToICCTagTable("B2A0", tag_offset, tag_size, &tagtable, &offsets); | 1020 | 2.89k | } else { | 1021 | 2.89k | if (tf == JXL_TRANSFER_FUNCTION_GAMMA) { | 1022 | 19 | float gamma = 1.0 / c.gamma; | 1023 | 19 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag({gamma}, 0, &tags)); | 1024 | 2.87k | } else if (c.color_space != JXL_COLOR_SPACE_XYB) { | 1025 | 2.87k | switch (tf) { | 1026 | 7 | case JXL_TRANSFER_FUNCTION_HLG: | 1027 | 7 | CreateICCCurvCurvTag( | 1028 | 7 | CreateTableCurve(64, ExtraTF::kHLG, CanToneMap(c)), &tags); | 1029 | 7 | break; | 1030 | 12 | case JXL_TRANSFER_FUNCTION_PQ: | 1031 | 12 | CreateICCCurvCurvTag( | 1032 | 12 | CreateTableCurve(64, ExtraTF::kPQ, CanToneMap(c)), &tags); | 1033 | 12 | break; | 1034 | 2.82k | case JXL_TRANSFER_FUNCTION_SRGB: | 1035 | 2.82k | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag( | 1036 | 2.82k | {2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 0.04045}, 3, | 1037 | 2.82k | &tags)); | 1038 | 2.82k | break; | 1039 | 2.82k | case JXL_TRANSFER_FUNCTION_709: | 1040 | 25 | JXL_RETURN_IF_ERROR(CreateICCCurvParaTag( | 1041 | 25 | {1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081}, 3, | 1042 | 25 | &tags)); | 1043 | 25 | break; | 1044 | 25 | case JXL_TRANSFER_FUNCTION_LINEAR: | 1045 | 3 | JXL_RETURN_IF_ERROR( | 1046 | 3 | CreateICCCurvParaTag({1.0, 1.0, 0.0, 1.0, 0.0}, 3, &tags)); | 1047 | 3 | break; | 1048 | 3 | case JXL_TRANSFER_FUNCTION_DCI: | 1049 | 3 | JXL_RETURN_IF_ERROR( | 1050 | 3 | CreateICCCurvParaTag({2.6, 1.0, 0.0, 1.0, 0.0}, 3, &tags)); | 1051 | 3 | break; | 1052 | 3 | default: | 1053 | 0 | JXL_UNREACHABLE("Unknown TF %u", static_cast<unsigned int>(tf)); | 1054 | 2.87k | } | 1055 | 2.87k | } | 1056 | 2.89k | FinalizeICCTag(&tags, &tag_offset, &tag_size); | 1057 | 2.89k | if (c.color_space == JXL_COLOR_SPACE_GRAY) { | 1058 | 23 | AddToICCTagTable("kTRC", tag_offset, tag_size, &tagtable, &offsets); | 1059 | 2.87k | } else { | 1060 | 2.87k | AddToICCTagTable("rTRC", tag_offset, tag_size, &tagtable, &offsets); | 1061 | 2.87k | AddToICCTagTable("gTRC", tag_offset, tag_size, &tagtable, &offsets); | 1062 | 2.87k | AddToICCTagTable("bTRC", tag_offset, tag_size, &tagtable, &offsets); | 1063 | 2.87k | } | 1064 | 2.89k | } | 1065 | | | 1066 | | // Tag count | 1067 | 2.90k | WriteICCUint32(offsets.size(), 0, &tagtable); | 1068 | 34.6k | for (size_t i = 0; i < offsets.size(); i++) { | 1069 | 31.7k | WriteICCUint32(offsets[i] + header.size() + tagtable.size(), 4 + 12 * i + 4, | 1070 | 31.7k | &tagtable); | 1071 | 31.7k | } | 1072 | | | 1073 | | // ICC profile size | 1074 | 2.90k | WriteICCUint32(header.size() + tagtable.size() + tags.size(), 0, &header); | 1075 | | | 1076 | 2.90k | *icc = header; | 1077 | 2.90k | Bytes(tagtable).AppendTo(*icc); | 1078 | 2.90k | Bytes(tags).AppendTo(*icc); | 1079 | | | 1080 | | // The MD5 checksum must be computed on the profile with profile flags, | 1081 | | // rendering intent, and region of the checksum itself, set to 0. | 1082 | | // TODO(lode): manually verify with a reliable tool that this creates correct | 1083 | | // signature (profile id) for ICC profiles. | 1084 | 2.90k | std::vector<uint8_t> icc_sum = *icc; | 1085 | 2.90k | if (icc_sum.size() >= 64 + 4) { | 1086 | 2.90k | memset(icc_sum.data() + 44, 0, 4); | 1087 | 2.90k | memset(icc_sum.data() + 64, 0, 4); | 1088 | 2.90k | } | 1089 | 2.90k | uint8_t checksum[16]; | 1090 | 2.90k | detail::ICCComputeMD5(icc_sum, checksum); | 1091 | | | 1092 | 2.90k | memcpy(icc->data() + 84, checksum, sizeof(checksum)); | 1093 | | | 1094 | 2.90k | return true; | 1095 | 2.90k | } |
Unexecuted instantiation: frame_header.cc:jxl::detail::MaybeCreateProfileImpl(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::detail::MaybeCreateProfileImpl(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
1096 | | |
1097 | | } // namespace detail |
1098 | | |
1099 | | // Returns a representation of the ColorEncoding fields (not icc). |
1100 | | // Example description: "RGB_D65_SRG_Rel_Lin" |
1101 | | static JXL_MAYBE_UNUSED std::string ColorEncodingDescription( |
1102 | 0 | const JxlColorEncoding& c) { |
1103 | 0 | return detail::ColorEncodingDescriptionImpl(c); |
1104 | 0 | } Unexecuted instantiation: fields_fuzzer.cc:jxl::ColorEncodingDescription(JxlColorEncoding const&) Unexecuted instantiation: color_encoding_internal.cc:jxl::ColorEncodingDescription(JxlColorEncoding const&) Unexecuted instantiation: frame_header.cc:jxl::ColorEncodingDescription(JxlColorEncoding const&) Unexecuted instantiation: image_metadata.cc:jxl::ColorEncodingDescription(JxlColorEncoding const&) |
1105 | | |
1106 | | // NOTE: for XYB colorspace, the created profile can be used to transform a |
1107 | | // *scaled* XYB image (created by ScaleXYB()) to another colorspace. |
1108 | | static JXL_MAYBE_UNUSED Status MaybeCreateProfile(const JxlColorEncoding& c, |
1109 | 2.93k | std::vector<uint8_t>* icc) { |
1110 | 2.93k | return detail::MaybeCreateProfileImpl(c, icc); |
1111 | 2.93k | } Unexecuted instantiation: fields_fuzzer.cc:jxl::MaybeCreateProfile(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) color_encoding_internal.cc:jxl::MaybeCreateProfile(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Line | Count | Source | 1109 | 2.93k | std::vector<uint8_t>* icc) { | 1110 | 2.93k | return detail::MaybeCreateProfileImpl(c, icc); | 1111 | 2.93k | } |
Unexecuted instantiation: frame_header.cc:jxl::MaybeCreateProfile(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) Unexecuted instantiation: image_metadata.cc:jxl::MaybeCreateProfile(JxlColorEncoding const&, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >*) |
1112 | | |
1113 | | } // namespace jxl |
1114 | | |
1115 | | #endif // LIB_JXL_CMS_JXL_CMS_INTERNAL_H_ |