display_to_hlg.cc (3366B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include <stdio.h> 7 #include <stdlib.h> 8 9 #include "lib/extras/codec.h" 10 #include "lib/extras/hlg.h" 11 #include "lib/extras/tone_mapping.h" 12 #include "lib/jxl/base/span.h" 13 #include "tools/args.h" 14 #include "tools/cmdline.h" 15 #include "tools/file_io.h" 16 #include "tools/hdr/image_utils.h" 17 #include "tools/thread_pool_internal.h" 18 19 int main(int argc, const char** argv) { 20 jpegxl::tools::ThreadPoolInternal pool; 21 22 jpegxl::tools::CommandLineParser parser; 23 float max_nits = 0; 24 auto max_nits_option = parser.AddOptionValue( 25 'm', "max_nits", "nits", "maximum luminance of the display", &max_nits, 26 &jpegxl::tools::ParseFloat, 0); 27 float surround_nits = 5; 28 parser.AddOptionValue( 29 's', "surround_nits", "nits", 30 "surround luminance of the viewing environment (default: 5)", 31 &surround_nits, &jpegxl::tools::ParseFloat, 0); 32 float preserve_saturation = .1f; 33 parser.AddOptionValue( 34 '\0', "preserve_saturation", "0..1", 35 "to what extent to try and preserve saturation over luminance if an " 36 "inverse gamma < 1 generates out-of-gamut colors", 37 &preserve_saturation, &jpegxl::tools::ParseFloat, 0); 38 const char* input_filename = nullptr; 39 auto input_filename_option = parser.AddPositionalOption( 40 "input", true, "input image", &input_filename, 0); 41 const char* output_filename = nullptr; 42 auto output_filename_option = parser.AddPositionalOption( 43 "output", true, "output image", &output_filename, 0); 44 45 if (!parser.Parse(argc, argv)) { 46 fprintf(stderr, "See -h for help.\n"); 47 return EXIT_FAILURE; 48 } 49 50 if (parser.HelpFlagPassed()) { 51 parser.PrintHelp(); 52 return EXIT_SUCCESS; 53 } 54 55 if (!parser.GetOption(max_nits_option)->matched()) { 56 fprintf(stderr, 57 "Missing required argument --max_nits.\nSee -h for help.\n"); 58 return EXIT_FAILURE; 59 } 60 if (!parser.GetOption(input_filename_option)->matched()) { 61 fprintf(stderr, "Missing input filename.\nSee -h for help.\n"); 62 return EXIT_FAILURE; 63 } 64 if (!parser.GetOption(output_filename_option)->matched()) { 65 fprintf(stderr, "Missing output filename.\nSee -h for help.\n"); 66 return EXIT_FAILURE; 67 } 68 69 std::vector<uint8_t> encoded; 70 JXL_CHECK(jpegxl::tools::ReadFile(input_filename, &encoded)); 71 jxl::CodecInOut image; 72 JXL_CHECK(jxl::SetFromBytes(jxl::Bytes(encoded), jxl::extras::ColorHints(), 73 &image, &pool)); 74 image.metadata.m.SetIntensityTarget(max_nits); 75 JXL_CHECK(jxl::HlgInverseOOTF( 76 &image.Main(), jxl::GetHlgGamma(max_nits, surround_nits), &pool)); 77 JXL_CHECK(jxl::GamutMap(&image, preserve_saturation, &pool)); 78 image.metadata.m.SetIntensityTarget(301); 79 80 jxl::ColorEncoding hlg; 81 hlg.SetColorSpace(jxl::ColorSpace::kRGB); 82 JXL_CHECK(hlg.SetPrimariesType(jxl::Primaries::k2100)); 83 JXL_CHECK(hlg.SetWhitePointType(jxl::WhitePoint::kD65)); 84 hlg.Tf().SetTransferFunction(jxl::TransferFunction::kHLG); 85 JXL_CHECK(hlg.CreateICC()); 86 JXL_CHECK(jpegxl::tools::TransformCodecInOutTo(image, hlg, &pool)); 87 image.metadata.m.color_encoding = hlg; 88 JXL_CHECK(jpegxl::tools::Encode(image, output_filename, &encoded, &pool)); 89 JXL_CHECK(jpegxl::tools::WriteFile(output_filename, encoded)); 90 }