Skip to content

Commit 6ea32f9

Browse files
committed
icc: update tone mapping
- update tone mapping to reflect the implementation in api-0. - update the icc profile to output results in xyz D50 instead of Lab. - update the icc profile to output tonemap results in api-0 only. - add chad tag. Test: ./ultrahdr_unit_test
1 parent 4cb4626 commit 6ea32f9

File tree

4 files changed

+169
-268
lines changed

4 files changed

+169
-268
lines changed

lib/include/ultrahdr/icc.h

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ static constexpr uint32_t kTAG_wtpt = SetFourByteTag('w', 't', 'p', 't');
121121
static constexpr uint32_t kTAG_rTRC = SetFourByteTag('r', 'T', 'R', 'C');
122122
static constexpr uint32_t kTAG_gTRC = SetFourByteTag('g', 'T', 'R', 'C');
123123
static constexpr uint32_t kTAG_bTRC = SetFourByteTag('b', 'T', 'R', 'C');
124+
static constexpr uint32_t kTAG_chad = SetFourByteTag('c', 'h', 'a', 'd');
124125
static constexpr uint32_t kTAG_cicp = SetFourByteTag('c', 'i', 'c', 'p');
125126
static constexpr uint32_t kTAG_cprt = SetFourByteTag('c', 'p', 'r', 't');
126127
static constexpr uint32_t kTAG_A2B0 = SetFourByteTag('A', '2', 'B', '0');
@@ -130,27 +131,32 @@ static constexpr uint32_t kTAG_CurveType = SetFourByteTag('c', 'u', 'r', 'v');
130131
static constexpr uint32_t kTAG_mABType = SetFourByteTag('m', 'A', 'B', ' ');
131132
static constexpr uint32_t kTAG_mBAType = SetFourByteTag('m', 'B', 'A', ' ');
132133
static constexpr uint32_t kTAG_ParaCurveType = SetFourByteTag('p', 'a', 'r', 'a');
134+
static constexpr uint32_t kTAG_s15Fixed16ArrayType = SetFourByteTag('s', 'f', '3', '2');
133135

136+
// All these tables are derived using function skcms_PrimariesToXYZD50() at
137+
// https://cs.android.com/android/platform/superproject/main/+/main:external/skia/modules/skcms/skcms.cc
134138
static constexpr Matrix3x3 kSRGB = {{
135-
// ICC fixed-point (16.16) representation, taken from skcms. Please keep them exactly in sync.
136-
// 0.436065674f, 0.385147095f, 0.143066406f,
137-
// 0.222488403f, 0.716873169f, 0.060607910f,
138-
// 0.013916016f, 0.097076416f, 0.714096069f,
139-
{FixedToFloat(0x6FA2), FixedToFloat(0x6299), FixedToFloat(0x24A0)},
140-
{FixedToFloat(0x38F5), FixedToFloat(0xB785), FixedToFloat(0x0F84)},
141-
{FixedToFloat(0x0390), FixedToFloat(0x18DA), FixedToFloat(0xB6CF)},
139+
{0.43606575f, 0.38515151f, 0.14307842f},
140+
{0.22249318f, 0.71688701f, 0.06061981f},
141+
{0.01392392f, 0.09708132f, 0.71409936f},
142142
}};
143143

144144
static constexpr Matrix3x3 kDisplayP3 = {{
145-
{0.515102f, 0.291965f, 0.157153f},
146-
{0.241182f, 0.692236f, 0.0665819f},
147-
{-0.00104941f, 0.0418818f, 0.784378f},
145+
{0.51514644f, 0.29200998f, 0.15713925f},
146+
{0.24120032f, 0.69222254f, 0.06657714f},
147+
{-0.00105014f, 0.04187827f, 0.78427647f},
148148
}};
149149

150150
static constexpr Matrix3x3 kRec2020 = {{
151-
{0.673459f, 0.165661f, 0.125100f},
152-
{0.279033f, 0.675338f, 0.0456288f},
153-
{-0.00193139f, 0.0299794f, 0.797162f},
151+
{0.67351546f, 0.16569726f, 0.12508295f},
152+
{0.27905901f, 0.67531801f, 0.04562299f},
153+
{-0.00193243f, 0.02997783f, 0.7970592f},
154+
}};
155+
156+
static constexpr Matrix3x3 adaptation_matrix = {{
157+
{1.04792979f, 0.02294687f, -0.05019227f},
158+
{0.02962781f, 0.99043443f, -0.0170738f},
159+
{-0.00924304f, 0.01505519f, 0.75187428f},
154160
}};
155161

156162
static constexpr uint32_t kCICPPrimariesUnSpecified = 2;
@@ -185,19 +191,14 @@ static inline Fixed float_round_to_fixed(float x) {
185191
return float_saturate2int((float)floor((double)x * Fixed1 + 0.5));
186192
}
187193

188-
static inline uint16_t float_round_to_unorm16(float x) {
189-
x = x * 65535.f + 0.5f;
190-
if (x > 65535) return 65535;
194+
// Convert a float to a uInt16Number, with 0.0 mapping go 0 and 1.0 mapping to |one|.
195+
static inline uint16_t float_to_uInt16Number(float x, uint16_t one) {
196+
x = x * one + 0.5;
197+
if (x > one) return one;
191198
if (x < 0) return 0;
192199
return static_cast<uint16_t>(x);
193200
}
194201

195-
static inline void float_to_table16(const float f, uint8_t* table_16) {
196-
*reinterpret_cast<uint16_t*>(table_16) = Endian_SwapBE16(float_round_to_unorm16(f));
197-
}
198-
199-
static inline bool isfinitef_(float x) { return 0 == x * 0; }
200-
201202
struct ICCHeader {
202203
// Size of the profile (computed)
203204
uint32_t size;
@@ -243,24 +244,26 @@ struct ICCHeader {
243244

244245
class IccHelper {
245246
private:
246-
static constexpr uint32_t kTrcTableSize = 65;
247247
static constexpr uint32_t kGridSize = 17;
248248
static constexpr size_t kNumChannels = 3;
249249

250+
static std::shared_ptr<DataStruct> make_empty() { return std::make_shared<DataStruct>(0); }
250251
static std::shared_ptr<DataStruct> write_text_tag(const char* text);
251252
static std::string get_desc_string(const uhdr_color_transfer_t tf,
252253
const uhdr_color_gamut_t gamut);
253254
static std::shared_ptr<DataStruct> write_xyz_tag(float x, float y, float z);
254255
static std::shared_ptr<DataStruct> write_trc_tag(const int table_entries, const void* table_16);
255256
static std::shared_ptr<DataStruct> write_trc_tag(const TransferFunction& fn);
256-
static float compute_tone_map_gain(const uhdr_color_transfer_t tf, float L);
257+
static std::shared_ptr<DataStruct> write_chad_tag();
257258
static std::shared_ptr<DataStruct> write_cicp_tag(uint32_t color_primaries,
258259
uint32_t transfer_characteristics);
259260
static std::shared_ptr<DataStruct> write_mAB_or_mBA_tag(uint32_t type, bool has_a_curves,
260261
const uint8_t* grid_points,
261-
const uint8_t* grid_16);
262-
static void compute_lut_entry(const Matrix3x3& src_to_XYZD50, float rgb[3]);
262+
const uint8_t* grid_16, bool has_m_curves,
263+
Matrix3x3* toXYZD50);
264+
static void compute_lut_entry(uhdr_color_transfer_t tf, uhdr_color_gamut_t cg, float rgb[3]);
263265
static std::shared_ptr<DataStruct> write_clut(const uint8_t* grid_points, const uint8_t* grid_16);
266+
static std::shared_ptr<DataStruct> write_matrix(const Matrix3x3* matrix);
264267

265268
// Checks if a set of xyz tags is equivalent to a 3x3 Matrix. Each input
266269
// tag buffer assumed to be at least kColorantTagSize in size.
@@ -271,7 +274,8 @@ class IccHelper {
271274
// Output includes JPEG embedding identifier and chunk information, but not
272275
// APPx information.
273276
static std::shared_ptr<DataStruct> writeIccProfile(const uhdr_color_transfer_t tf,
274-
const uhdr_color_gamut_t gamut);
277+
const uhdr_color_gamut_t gamut,
278+
bool write_tonemap_icc = false);
275279
// NOTE: this function is not robust; it can infer gamuts that IccHelper
276280
// writes out but should not be considered a reference implementation for
277281
// robust parsing of ICC profiles or their gamuts.

lib/include/ultrahdr/jpegr.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,12 @@ class JpegR {
486486
*
487487
* \param[in] gainmap_img gainmap image descriptor
488488
* \param[in] jpeg_enc_obj jpeg encoder object handle
489+
* \param[in] write_tonemap_icc write tonemap details in icc header
489490
*
490491
* \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
491492
*/
492-
uhdr_error_info_t compressGainMap(uhdr_raw_image_t* gainmap_img, JpegEncoderHelper* jpeg_enc_obj);
493+
uhdr_error_info_t compressGainMap(uhdr_raw_image_t* gainmap_img, JpegEncoderHelper* jpeg_enc_obj,
494+
bool write_tonemap_icc = false);
493495

494496
/*!\brief This method is called to separate base image and gain map image from compressed
495497
* ultrahdr image

0 commit comments

Comments
 (0)