• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ULTRAHDR_JPEGR_H
18 #define ULTRAHDR_JPEGR_H
19 
20 #include <array>
21 #include <cfloat>
22 
23 #include "ultrahdr/ultrahdr.h"
24 #include "ultrahdr/jpegdecoderhelper.h"
25 #include "ultrahdr/jpegencoderhelper.h"
26 
27 namespace ultrahdr {
28 
29 // The current JPEGR version that we encode to
30 static const char* const kJpegrVersion = kGainMapVersion;
31 
32 // Map is quarter res / sixteenth size
33 static const size_t kMapDimensionScaleFactor = 4;
34 
35 // Gain Map width is (image_width / kMapDimensionScaleFactor). If we were to
36 // compress 420 GainMap in jpeg, then we need at least 2 samples. For Grayscale
37 // 1 sample is sufficient. We are using 2 here anyways
38 static const int kMinWidth = 2 * kMapDimensionScaleFactor;
39 static const int kMinHeight = 2 * kMapDimensionScaleFactor;
40 
41 /*
42  * Holds information of jpeg image
43  */
44 struct jpeg_info_struct {
45   std::vector<uint8_t> imgData = std::vector<uint8_t>(0);
46   std::vector<uint8_t> iccData = std::vector<uint8_t>(0);
47   std::vector<uint8_t> exifData = std::vector<uint8_t>(0);
48   std::vector<uint8_t> xmpData = std::vector<uint8_t>(0);
49   size_t width;
50   size_t height;
51 };
52 
53 /*
54  * Holds information of jpegr image
55  */
56 struct jpegr_info_struct {
57   size_t width;   // copy of primary image width (for easier access)
58   size_t height;  // copy of primary image height (for easier access)
59   jpeg_info_struct* primaryImgInfo = nullptr;
60   jpeg_info_struct* gainmapImgInfo = nullptr;
61 };
62 
63 /*
64  * Holds information for uncompressed image or gain map.
65  */
66 struct jpegr_uncompressed_struct {
67   // Pointer to the data location.
68   void* data;
69   // Width of the gain map or the luma plane of the image in pixels.
70   size_t width;
71   // Height of the gain map or the luma plane of the image in pixels.
72   size_t height;
73   // Color gamut.
74   ultrahdr_color_gamut colorGamut;
75 
76   // Values below are optional
77   // Pointer to chroma data, if it's NULL, chroma plane is considered to be immediately
78   // after the luma plane.
79   void* chroma_data = nullptr;
80   // Stride of Y plane in number of pixels. 0 indicates the member is uninitialized. If
81   // non-zero this value must be larger than or equal to luma width. If stride is
82   // uninitialized then it is assumed to be equal to luma width.
83   size_t luma_stride = 0;
84   // Stride of UV plane in number of pixels.
85   // 1. If this handle points to P010 image then this value must be larger than
86   //    or equal to luma width.
87   // 2. If this handle points to 420 image then this value must be larger than
88   //    or equal to (luma width / 2).
89   // NOTE: if chroma_data is nullptr, chroma_stride is irrelevant. Just as the way,
90   // chroma_data is derived from luma ptr, chroma stride is derived from luma stride.
91   size_t chroma_stride = 0;
92   // Pixel format.
93   uhdr_img_fmt_t pixelFormat = UHDR_IMG_FMT_UNSPECIFIED;
94 };
95 
96 /*
97  * Holds information for compressed image or gain map.
98  */
99 struct jpegr_compressed_struct {
100   // Pointer to the data location.
101   void* data;
102   // Used data length in bytes.
103   int length;
104   // Maximum available data length in bytes.
105   int maxLength;
106   // Color gamut.
107   ultrahdr_color_gamut colorGamut;
108 };
109 
110 /*
111  * Holds information for EXIF metadata.
112  */
113 struct jpegr_exif_struct {
114   // Pointer to the data location.
115   void* data;
116   // Data length;
117   size_t length;
118 };
119 
120 typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr;
121 typedef struct jpegr_compressed_struct* jr_compressed_ptr;
122 typedef struct jpegr_exif_struct* jr_exif_ptr;
123 typedef struct jpeg_info_struct* j_info_ptr;
124 typedef struct jpegr_info_struct* jr_info_ptr;
125 
126 class JpegR {
127  public:
128   /*
129    * Experimental only
130    *
131    * Encode API-0
132    * Compress JPEGR image from 10-bit HDR YUV.
133    *
134    * Tonemap the HDR input to a SDR image, generate gain map from the HDR and SDR images,
135    * compress SDR YUV to 8-bit JPEG and append the gain map to the end of the compressed
136    * JPEG.
137    * @param p010_image_ptr uncompressed HDR image in P010 color format
138    * @param hdr_tf transfer function of the HDR image
139    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
140    *             represents the maximum available size of the destination buffer, and it must be
141    *             set before calling this method. If the encoded JPEGR size exceeds
142    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
143    * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
144    *                the highest quality
145    * @param exif pointer to the exif metadata.
146    * @return NO_ERROR if encoding succeeds, error code if error occurs.
147    */
148   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, ultrahdr_transfer_function hdr_tf,
149                        jr_compressed_ptr dest, int quality, jr_exif_ptr exif);
150 
151   /*
152    * Encode API-1
153    * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
154    *
155    * Generate gain map from the HDR and SDR inputs, compress SDR YUV to 8-bit JPEG and append
156    * the gain map to the end of the compressed JPEG. HDR and SDR inputs must be the same
157    * resolution. SDR input is assumed to use the sRGB transfer function.
158    * @param p010_image_ptr uncompressed HDR image in P010 color format
159    * @param yuv420_image_ptr uncompressed SDR image in YUV_420 color format
160    * @param hdr_tf transfer function of the HDR image
161    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
162    *             represents the maximum available size of the desitination buffer, and it must be
163    *             set before calling this method. If the encoded JPEGR size exceeds
164    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
165    * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
166    *                the highest quality
167    * @param exif pointer to the exif metadata.
168    * @return NO_ERROR if encoding succeeds, error code if error occurs.
169    */
170   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, jr_uncompressed_ptr yuv420_image_ptr,
171                        ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest, int quality,
172                        jr_exif_ptr exif);
173 
174   /*
175    * Encode API-2
176    * Compress JPEGR image from 10-bit HDR YUV, 8-bit SDR YUV and compressed 8-bit JPEG.
177    *
178    * This method requires HAL Hardware JPEG encoder.
179    *
180    * Generate gain map from the HDR and SDR inputs, append the gain map to the end of the
181    * compressed JPEG. Adds an ICC profile if one isn't present in the input JPEG image. HDR and
182    * SDR inputs must be the same resolution and color space. SDR image is assumed to use the sRGB
183    * transfer function.
184    * @param p010_image_ptr uncompressed HDR image in P010 color format
185    * @param yuv420_image_ptr uncompressed SDR image in YUV_420 color format
186    * @param yuv420jpg_image_ptr SDR image compressed in jpeg format
187    * @param hdr_tf transfer function of the HDR image
188    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
189    *             represents the maximum available size of the desitination buffer, and it must be
190    *             set before calling this method. If the encoded JPEGR size exceeds
191    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
192    * @return NO_ERROR if encoding succeeds, error code if error occurs.
193    */
194   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, jr_uncompressed_ptr yuv420_image_ptr,
195                        jr_compressed_ptr yuv420jpg_image_ptr, ultrahdr_transfer_function hdr_tf,
196                        jr_compressed_ptr dest);
197 
198   /*
199    * Encode API-3
200    * Compress JPEGR image from 10-bit HDR YUV and 8-bit SDR YUV.
201    *
202    * This method requires HAL Hardware JPEG encoder.
203    *
204    * Decode the compressed 8-bit JPEG image to YUV SDR, generate gain map from the HDR input
205    * and the decoded SDR result, append the gain map to the end of the compressed JPEG. Adds an
206    * ICC profile if one isn't present in the input JPEG image. HDR and SDR inputs must be the same
207    * resolution. JPEG image is assumed to use the sRGB transfer function.
208    * @param p010_image_ptr uncompressed HDR image in P010 color format
209    * @param yuv420jpg_image_ptr SDR image compressed in jpeg format
210    * @param hdr_tf transfer function of the HDR image
211    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
212    *             represents the maximum available size of the desitination buffer, and it must be
213    *             set before calling this method. If the encoded JPEGR size exceeds
214    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
215    * @return NO_ERROR if encoding succeeds, error code if error occurs.
216    */
217   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, jr_compressed_ptr yuv420jpg_image_ptr,
218                        ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest);
219 
220   /*
221    * Encode API-4
222    * Assemble JPEGR image from SDR JPEG and gainmap JPEG.
223    *
224    * Assemble the primary JPEG image, the gain map and the metadata to JPEG/R format. Adds an ICC
225    * profile if one isn't present in the input JPEG image.
226    * @param yuv420jpg_image_ptr SDR image compressed in jpeg format
227    * @param gainmapjpg_image_ptr gain map image compressed in jpeg format
228    * @param metadata metadata to be written in XMP of the primary jpeg
229    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
230    *             represents the maximum available size of the desitination buffer, and it must be
231    *             set before calling this method. If the encoded JPEGR size exceeds
232    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
233    * @return NO_ERROR if encoding succeeds, error code if error occurs.
234    */
235   status_t encodeJPEGR(jr_compressed_ptr yuv420jpg_image_ptr,
236                        jr_compressed_ptr gainmapjpg_image_ptr, ultrahdr_metadata_ptr metadata,
237                        jr_compressed_ptr dest);
238 
239   /*
240    * Decode API
241    * Decompress JPEGR image.
242    *
243    * This method assumes that the JPEGR image contains an ICC profile with primaries that match
244    * those of a color gamut that this library is aware of; Bt.709, Display-P3, or Bt.2100. It also
245    * assumes the base image uses the sRGB transfer function.
246    *
247    * This method only supports single gain map metadata values for fields that allow multi-channel
248    * metadata values.
249    * @param jpegr_image_ptr compressed JPEGR image.
250    * @param dest destination of the uncompressed JPEGR image.
251    * @param max_display_boost (optional) the maximum available boost supported by a display,
252    *                          the value must be greater than or equal to 1.0.
253    * @param exif destination of the decoded EXIF metadata. The default value is NULL where the
254                  decoder will do nothing about it. If configured not NULL the decoder will write
255                  EXIF data into this structure. The format is defined in {@code jpegr_exif_struct}
256    * @param output_format flag for setting output color format. Its value configures the output
257                           color format. The default value is {@code JPEGR_OUTPUT_HDR_LINEAR}.
258                           ----------------------------------------------------------------------
259                           |      output_format       |    decoded color format to be written   |
260                           ----------------------------------------------------------------------
261                           |     JPEGR_OUTPUT_SDR     |                RGBA_8888                |
262                           ----------------------------------------------------------------------
263                           | JPEGR_OUTPUT_HDR_LINEAR  |        (default)RGBA_F16 linear         |
264                           ----------------------------------------------------------------------
265                           |   JPEGR_OUTPUT_HDR_PQ    |             RGBA_1010102 PQ             |
266                           ----------------------------------------------------------------------
267                           |   JPEGR_OUTPUT_HDR_HLG   |            RGBA_1010102 HLG             |
268                           ----------------------------------------------------------------------
269    * @param gainmap_image_ptr destination of the decoded gain map. The default value is NULL
270                               where the decoder will do nothing about it. If configured not NULL
271                               the decoder will write the decoded gain_map data into this
272                               structure. The format is defined in
273                               {@code jpegr_uncompressed_struct}.
274    * @param metadata destination of the decoded metadata. The default value is NULL where the
275                      decoder will do nothing about it. If configured not NULL the decoder will
276                      write metadata into this structure. the format of metadata is defined in
277                      {@code ultrahdr_metadata_struct}.
278    * @return NO_ERROR if decoding succeeds, error code if error occurs.
279    */
280   status_t decodeJPEGR(jr_compressed_ptr jpegr_image_ptr, jr_uncompressed_ptr dest,
281                        float max_display_boost = FLT_MAX, jr_exif_ptr exif = nullptr,
282                        ultrahdr_output_format output_format = ULTRAHDR_OUTPUT_HDR_LINEAR,
283                        jr_uncompressed_ptr gainmap_image_ptr = nullptr,
284                        ultrahdr_metadata_ptr metadata = nullptr);
285 
286   /*
287    * Gets Info from JPEGR file without decoding it.
288    *
289    * This method only supports single gain map metadata values for fields that allow multi-channel
290    * metadata values.
291    *
292    * The output is filled jpegr_info structure
293    * @param jpegr_image_ptr compressed JPEGR image
294    * @param jpeg_image_info_ptr pointer to jpegr info struct. Members of jpegr_info
295    *                            are owned by the caller
296    * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise
297    */
298   status_t getJPEGRInfo(jr_compressed_ptr jpegr_image_ptr, jr_info_ptr jpeg_image_info_ptr);
299 
300  protected:
301   /*
302    * This method is called in the encoding pipeline. It will take the uncompressed 8-bit and
303    * 10-bit yuv images as input, and calculate the uncompressed gain map. The input images
304    * must be the same resolution. The SDR input is assumed to use the sRGB transfer function.
305    *
306    * @param yuv420_image_ptr uncompressed SDR image in YUV_420 color format
307    * @param p010_image_ptr uncompressed HDR image in P010 color format
308    * @param hdr_tf transfer function of the HDR image
309    * @param metadata everything but "version" is filled in this struct
310    * @param dest location at which gain map image is stored (caller responsible for memory
311                  of data).
312    * @param sdr_is_601 if true, then use BT.601 decoding of YUV regardless of SDR image gamut
313    * @return NO_ERROR if calculation succeeds, error code if error occurs.
314    */
315   status_t generateGainMap(jr_uncompressed_ptr yuv420_image_ptr, jr_uncompressed_ptr p010_image_ptr,
316                            ultrahdr_transfer_function hdr_tf, ultrahdr_metadata_ptr metadata,
317                            jr_uncompressed_ptr dest, bool sdr_is_601 = false);
318 
319   /*
320    * This method is called in the decoding pipeline. It will take the uncompressed (decoded)
321    * 8-bit yuv image, the uncompressed (decoded) gain map, and extracted JPEG/R metadata as
322    * input, and calculate the 10-bit recovered image. The recovered output image is the same
323    * color gamut as the SDR image, with HLG transfer function, and is in RGBA1010102 data format.
324    * The SDR image is assumed to use the sRGB transfer function. The SDR image is also assumed to
325    * be a decoded JPEG for the purpose of YUV interpration.
326    *
327    * @param yuv420_image_ptr uncompressed SDR image in YUV_420 color format
328    * @param gainmap_image_ptr pointer to uncompressed gain map image struct.
329    * @param metadata JPEG/R metadata extracted from XMP.
330    * @param output_format flag for setting output color format. if set to
331    *                      {@code JPEGR_OUTPUT_SDR}, decoder will only decode the primary image
332    *                      which is SDR. Default value is JPEGR_OUTPUT_HDR_LINEAR.
333    * @param max_display_boost the maximum available boost supported by a display
334    * @param dest reconstructed HDR image
335    * @return NO_ERROR if calculation succeeds, error code if error occurs.
336    */
337   status_t applyGainMap(jr_uncompressed_ptr yuv420_image_ptr, jr_uncompressed_ptr gainmap_image_ptr,
338                         ultrahdr_metadata_ptr metadata, ultrahdr_output_format output_format,
339                         float max_display_boost, jr_uncompressed_ptr dest);
340 
341  private:
342   /*
343    * This method is called in the encoding pipeline. It will encode the gain map.
344    *
345    * @param gainmap_image_ptr pointer to uncompressed gain map image struct
346    * @param jpeg_enc_obj_ptr helper resource to compress gain map
347    * @return NO_ERROR if encoding succeeds, error code if error occurs.
348    */
349   status_t compressGainMap(jr_uncompressed_ptr gainmap_image_ptr,
350                            JpegEncoderHelper* jpeg_enc_obj_ptr);
351 
352   /*
353    * This method is called to separate primary image and gain map image from JPEGR
354    *
355    * @param jpegr_image_ptr pointer to compressed JPEGR image.
356    * @param primary_jpg_image_ptr destination of primary image
357    * @param gainmap_jpg_image_ptr destination of compressed gain map image
358    * @return NO_ERROR if calculation succeeds, error code if error occurs.
359    */
360   status_t extractPrimaryImageAndGainMap(jr_compressed_ptr jpegr_image_ptr,
361                                          jr_compressed_ptr primary_jpg_image_ptr,
362                                          jr_compressed_ptr gainmap_jpg_image_ptr);
363 
364   /*
365    * Gets Info from JPEG image without decoding it.
366    *
367    * The output is filled jpeg_info structure
368    * @param jpegr_image_ptr compressed JPEG image
369    * @param jpeg_image_info_ptr pointer to jpeg info struct. Members of jpeg_info_struct
370    *                            are owned by the caller
371    * @param img_width (optional) pointer to store width of jpeg image
372    * @param img_height (optional) pointer to store height of jpeg image
373    * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise
374    */
375   status_t parseJpegInfo(jr_compressed_ptr jpeg_image_ptr, j_info_ptr jpeg_image_info_ptr,
376                          size_t* img_width = nullptr, size_t* img_height = nullptr);
377 
378   /*
379    * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image,
380    * the compressed gain map and optionally the exif package as inputs, and generate the XMP
381    * metadata, and finally append everything in the order of:
382    *     SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, gain map
383    *
384    * Note that in the final JPEG/R output, EXIF package will appear if ONLY ONE of the following
385    * conditions is fulfilled:
386    *  (1) EXIF package is available from outside input. I.e. pExif != nullptr.
387    *  (2) Input JPEG has EXIF.
388    * If both conditions are fulfilled, this method will return ERROR_JPEGR_INVALID_INPUT_TYPE
389    *
390    * @param primary_jpg_image_ptr destination of primary image
391    * @param gainmap_jpg_image_ptr destination of compressed gain map image
392    * @param (nullable) pExif EXIF package
393    * @param (nullable) pIcc ICC package
394    * @param icc_size length in bytes of ICC package
395    * @param metadata JPEG/R metadata to encode in XMP of the jpeg
396    * @param dest compressed JPEGR image
397    * @return NO_ERROR if calculation succeeds, error code if error occurs.
398    */
399   status_t appendGainMap(jr_compressed_ptr primary_jpg_image_ptr,
400                          jr_compressed_ptr gainmap_jpg_image_ptr, jr_exif_ptr pExif, void* pIcc,
401                          size_t icc_size, ultrahdr_metadata_ptr metadata, jr_compressed_ptr dest);
402 
403   /*
404    * This method will tone map a HDR image to an SDR image.
405    *
406    * @param src pointer to uncompressed HDR image struct. HDR image is expected to be
407    *            in p010 color format
408    * @param dest pointer to store tonemapped SDR image
409    * @param hdr_tf transfer function of the HDR image
410    * @return NO_ERROR if calculation succeeds, error code if error occurs.
411    */
412   status_t toneMap(jr_uncompressed_ptr src, jr_uncompressed_ptr dest,
413                    ultrahdr_transfer_function hdr_tf);
414 
415   /*
416    * This method will convert a YUV420 image from one YUV encoding to another in-place (eg.
417    * Bt.709 to Bt.601 YUV encoding).
418    *
419    * src_encoding and dest_encoding indicate the encoding via the YUV conversion defined for that
420    * gamut. P3 indicates Rec.601, since this is how DataSpace encodes Display-P3 YUV data.
421    *
422    * @param image the YUV420 image to convert
423    * @param src_encoding input YUV encoding
424    * @param dest_encoding output YUV encoding
425    * @return NO_ERROR if calculation succeeds, error code if error occurs.
426    */
427   status_t convertYuv(jr_uncompressed_ptr image, ultrahdr_color_gamut src_encoding,
428                       ultrahdr_color_gamut dest_encoding);
429 
430   /*
431    * This method will check the validity of the input arguments.
432    *
433    * @param p010_image_ptr uncompressed HDR image in P010 color format
434    * @param yuv420_image_ptr pointer to uncompressed SDR image struct. HDR image is expected to
435    *                         be in 420p color format
436    * @param hdr_tf transfer function of the HDR image
437    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
438    *             represents the maximum available size of the desitination buffer, and it must be
439    *             set before calling this method. If the encoded JPEGR size exceeds
440    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
441    * @return NO_ERROR if the input args are valid, error code is not valid.
442    */
443   status_t areInputArgumentsValid(jr_uncompressed_ptr p010_image_ptr,
444                                   jr_uncompressed_ptr yuv420_image_ptr,
445                                   ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest_ptr);
446 
447   /*
448    * This method will check the validity of the input arguments.
449    *
450    * @param p010_image_ptr uncompressed HDR image in P010 color format
451    * @param yuv420_image_ptr pointer to uncompressed SDR image struct. HDR image is expected to
452    *                         be in 420p color format
453    * @param hdr_tf transfer function of the HDR image
454    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
455    *             represents the maximum available size of the destination buffer, and it must be
456    *             set before calling this method. If the encoded JPEGR size exceeds
457    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
458    * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
459    *                the highest quality
460    * @return NO_ERROR if the input args are valid, error code is not valid.
461    */
462   status_t areInputArgumentsValid(jr_uncompressed_ptr p010_image_ptr,
463                                   jr_uncompressed_ptr yuv420_image_ptr,
464                                   ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest,
465                                   int quality);
466 };
467 
468 struct GlobalTonemapOutputs {
469   std::array<float, 3> rgb_out;
470   float y_hdr;
471   float y_sdr;
472 };
473 
474 // Applies a global tone mapping, based on Chrome's HLG/PQ rendering implemented
475 // at
476 // https://source.chromium.org/chromium/chromium/src/+/main:ui/gfx/color_transform.cc;l=1198-1232;drc=ac505aff1d29ec3bfcf317cb77d5e196a3664e92
477 // `rgb_in` is expected to be in the normalized range of [0.0, 1.0] and
478 // `rgb_out` is returned in this same range. `headroom` describes the ratio
479 // between the HDR and SDR peak luminances and must be > 1. The `y_sdr` output
480 // is in the range [0.0, 1.0] while `y_hdr` is in the range [0.0, headroom].
481 GlobalTonemapOutputs hlgGlobalTonemap(const std::array<float, 3>& rgb_in, float headroom);
482 
483 }  // namespace ultrahdr
484 
485 #endif  // ULTRAHDR_JPEGR_H
486