xref: /aosp_15_r20/external/libultrahdr/lib/include/ultrahdr/jpegr.h (revision 89a0ef05262152531a00a15832a2d3b1e3990773)
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_api.h"
24 #include "ultrahdr/ultrahdr.h"
25 #include "ultrahdr/ultrahdrcommon.h"
26 #include "ultrahdr/jpegdecoderhelper.h"
27 #include "ultrahdr/jpegencoderhelper.h"
28 
29 namespace ultrahdr {
30 
31 // Default configurations
32 // gainmap image downscale factor
33 static const int kMapDimensionScaleFactorDefault = 1;
34 static const int kMapDimensionScaleFactorAndroidDefault = 4;
35 
36 // JPEG compress quality (0 ~ 100) for base image
37 static const int kBaseCompressQualityDefault = 95;
38 
39 // JPEG compress quality (0 ~ 100) for gain map
40 static const int kMapCompressQualityDefault = 95;
41 static const int kMapCompressQualityAndroidDefault = 85;
42 
43 // Gain map calculation
44 static const bool kUseMultiChannelGainMapDefault = true;
45 static const bool kUseMultiChannelGainMapAndroidDefault = false;
46 
47 // encoding preset
48 static const uhdr_enc_preset_t kEncSpeedPresetDefault = UHDR_USAGE_BEST_QUALITY;
49 static const uhdr_enc_preset_t kEncSpeedPresetAndroidDefault = UHDR_USAGE_REALTIME;
50 
51 // Default gamma value for gain map
52 static const float kGainMapGammaDefault = 1.0f;
53 
54 // The current JPEGR version that we encode to
55 static const char* const kJpegrVersion = "1.0";
56 
57 /*
58  * Holds information of jpeg image
59  */
60 struct jpeg_info_struct {
61   std::vector<uint8_t> imgData = std::vector<uint8_t>(0);
62   std::vector<uint8_t> iccData = std::vector<uint8_t>(0);
63   std::vector<uint8_t> exifData = std::vector<uint8_t>(0);
64   std::vector<uint8_t> xmpData = std::vector<uint8_t>(0);
65   std::vector<uint8_t> isoData = std::vector<uint8_t>(0);
66   unsigned int width;
67   unsigned int height;
68   unsigned int numComponents;
69 };
70 
71 /*
72  * Holds information of jpegr image
73  */
74 struct jpegr_info_struct {
75   unsigned int width;   // copy of primary image width (for easier access)
76   unsigned int height;  // copy of primary image height (for easier access)
77   jpeg_info_struct* primaryImgInfo = nullptr;
78   jpeg_info_struct* gainmapImgInfo = nullptr;
79 };
80 
81 typedef struct jpeg_info_struct* j_info_ptr;
82 typedef struct jpegr_info_struct* jr_info_ptr;
83 
84 class JpegR {
85  public:
86   JpegR(void* uhdrGLESCtxt = nullptr,
87         int mapDimensionScaleFactor = kMapDimensionScaleFactorAndroidDefault,
88         int mapCompressQuality = kMapCompressQualityAndroidDefault,
89         bool useMultiChannelGainMap = kUseMultiChannelGainMapAndroidDefault,
90         float gamma = kGainMapGammaDefault,
91         uhdr_enc_preset_t preset = kEncSpeedPresetAndroidDefault, float minContentBoost = FLT_MIN,
92         float maxContentBoost = FLT_MAX, float targetDispPeakBrightness = -1.0f);
93 
94   /*!\brief Encode API-0.
95    *
96    * Create ultrahdr jpeg image from raw hdr intent.
97    *
98    * Experimental only.
99    *
100    * Input hdr image is tonemapped to sdr image. A gainmap coefficient is computed between hdr and
101    * sdr intent. sdr intent and gain map coefficient are compressed using jpeg encoding. compressed
102    * gainmap is appended at the end of compressed sdr image.
103    *
104    * \param[in]       hdr_intent        hdr intent raw input image descriptor
105    * \param[in, out]  dest              output image descriptor to store compressed ultrahdr image
106    * \param[in]       quality           quality factor for sdr intent jpeg compression
107    * \param[in]       exif              optional exif metadata that needs to be inserted in
108    *                                    compressed output
109    *
110    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
111    */
112   uhdr_error_info_t encodeJPEGR(uhdr_raw_image_t* hdr_intent, uhdr_compressed_image_t* dest,
113                                 int quality, uhdr_mem_block_t* exif);
114 
115   /*!\brief Encode API-1.
116    *
117    * Create ultrahdr jpeg image from raw hdr intent and raw sdr intent.
118    *
119    * A gainmap coefficient is computed between hdr and sdr intent. sdr intent and gain map
120    * coefficient are compressed using jpeg encoding. compressed gainmap is appended at the end of
121    * compressed sdr image.
122    * NOTE: Color transfer of sdr intent is expected to be sRGB.
123    *
124    * \param[in]       hdr_intent        hdr intent raw input image descriptor
125    * \param[in]       sdr_intent        sdr intent raw input image descriptor
126    * \param[in, out]  dest              output image descriptor to store compressed ultrahdr image
127    * \param[in]       quality           quality factor for sdr intent jpeg compression
128    * \param[in]       exif              optional exif metadata that needs to be inserted in
129    *                                    compressed output
130    *
131    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
132    */
133   uhdr_error_info_t encodeJPEGR(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent,
134                                 uhdr_compressed_image_t* dest, int quality, uhdr_mem_block_t* exif);
135 
136   /*!\brief Encode API-2.
137    *
138    * Create ultrahdr jpeg image from raw hdr intent, raw sdr intent and compressed sdr intent.
139    *
140    * A gainmap coefficient is computed between hdr and sdr intent. gain map coefficient is
141    * compressed using jpeg encoding. compressed gainmap is appended at the end of compressed sdr
142    * intent. ICC profile is added if one isn't present in the sdr intent JPEG image.
143    * NOTE: Color transfer of sdr intent is expected to be sRGB.
144    * NOTE: sdr intent raw and compressed inputs are expected to be related via compress/decompress
145    * operations.
146    *
147    * \param[in]       hdr_intent               hdr intent raw input image descriptor
148    * \param[in]       sdr_intent               sdr intent raw input image descriptor
149    * \param[in]       sdr_intent_compressed    sdr intent compressed input image descriptor
150    * \param[in, out]  dest                     output image descriptor to store compressed ultrahdr
151    *                                           image
152    *
153    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
154    */
155   uhdr_error_info_t encodeJPEGR(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent,
156                                 uhdr_compressed_image_t* sdr_intent_compressed,
157                                 uhdr_compressed_image_t* dest);
158 
159   /*!\brief Encode API-3.
160    *
161    * Create ultrahdr jpeg image from raw hdr intent and compressed sdr intent.
162    *
163    * The sdr intent is decoded and a gainmap coefficient is computed between hdr and sdr intent.
164    * gain map coefficient is compressed using jpeg encoding. compressed gainmap is appended at the
165    * end of compressed sdr image. ICC profile is added if one isn't present in the sdr intent JPEG
166    * image.
167    * NOTE: Color transfer of sdr intent is expected to be sRGB.
168    *
169    * \param[in]       hdr_intent               hdr intent raw input image descriptor
170    * \param[in]       sdr_intent_compressed    sdr intent compressed input image descriptor
171    * \param[in, out]  dest                     output image descriptor to store compressed ultrahdr
172    *                                           image
173    *
174    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
175    */
176   uhdr_error_info_t encodeJPEGR(uhdr_raw_image_t* hdr_intent,
177                                 uhdr_compressed_image_t* sdr_intent_compressed,
178                                 uhdr_compressed_image_t* dest);
179 
180   /*!\brief Encode API-4.
181    *
182    * Create ultrahdr jpeg image from compressed sdr image and compressed gainmap image
183    *
184    * compressed gainmap image is added at the end of compressed sdr image. ICC profile is added if
185    * one isn't present in the sdr intent compressed image.
186    *
187    * \param[in]       base_img_compressed      sdr intent compressed input image descriptor
188    * \param[in]       gainmap_img_compressed   gainmap compressed image descriptor
189    * \param[in]       metadata                 gainmap metadata descriptor
190    * \param[in, out]  dest                     output image descriptor to store compressed ultrahdr
191    *                                           image
192    *
193    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
194    */
195   uhdr_error_info_t encodeJPEGR(uhdr_compressed_image_t* base_img_compressed,
196                                 uhdr_compressed_image_t* gainmap_img_compressed,
197                                 uhdr_gainmap_metadata_ext_t* metadata,
198                                 uhdr_compressed_image_t* dest);
199 
200   /*!\brief Decode API.
201    *
202    * Decompress ultrahdr jpeg image.
203    *
204    * NOTE: This method requires that the ultrahdr input image contains an ICC profile with primaries
205    * that match those of a color gamut that this library is aware of; Bt.709, Display-P3, or
206    * Bt.2100. It also assumes the base image color transfer characteristics are sRGB.
207    *
208    * \param[in]       uhdr_compressed_img      compressed ultrahdr image descriptor
209    * \param[in, out]  dest                     output image descriptor to store decoded output
210    * \param[in]       max_display_boost        (optional) the maximum available boost supported by a
211    *                                           display, the value must be greater than or equal
212    *                                           to 1.0
213    * \param[in]       output_ct                (optional) output color transfer
214    * \param[in]       output_format            (optional) output pixel format
215    * \param[in, out]  gainmap_img              (optional) output image descriptor to store decoded
216    *                                           gainmap image
217    * \param[in, out]  gainmap_metadata         (optional) descriptor to store gainmap metadata
218    *
219    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
220    *
221    * NOTE: This method only supports single gain map metadata values for fields that allow
222    * multi-channel metadata values.
223    *
224    * NOTE: Not all combinations of output color transfer and output pixel format are supported.
225    * Refer below table for supported combinations.
226    *         ----------------------------------------------------------------------
227    *         |           color transfer	       |          color format            |
228    *         ----------------------------------------------------------------------
229    *         |                 SDR             |          32bppRGBA8888           |
230    *         ----------------------------------------------------------------------
231    *         |             HDR_LINEAR          |          64bppRGBAHalfFloat      |
232    *         ----------------------------------------------------------------------
233    *         |               HDR_PQ            |          32bppRGBA1010102        |
234    *         ----------------------------------------------------------------------
235    *         |               HDR_HLG           |          32bppRGBA1010102        |
236    *         ----------------------------------------------------------------------
237    */
238   uhdr_error_info_t decodeJPEGR(uhdr_compressed_image_t* uhdr_compressed_img,
239                                 uhdr_raw_image_t* dest, float max_display_boost = FLT_MAX,
240                                 uhdr_color_transfer_t output_ct = UHDR_CT_LINEAR,
241                                 uhdr_img_fmt_t output_format = UHDR_IMG_FMT_64bppRGBAHalfFloat,
242                                 uhdr_raw_image_t* gainmap_img = nullptr,
243                                 uhdr_gainmap_metadata_t* gainmap_metadata = nullptr);
244 
245   /*!\brief This function parses the bitstream and returns information that is useful for actual
246    * decoding. This does not decode the image. That is handled by decodeJPEGR
247    *
248    * \param[in]       uhdr_compressed_img      compressed ultrahdr image descriptor
249    * \param[in, out]  uhdr_image_info          image info descriptor
250    *
251    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
252    */
253   uhdr_error_info_t getJPEGRInfo(uhdr_compressed_image_t* uhdr_compressed_img,
254                                  jr_info_ptr uhdr_image_info);
255 
256   /*!\brief set gain map dimension scale factor
257    * NOTE: Applicable only in encoding scenario
258    *
259    * \param[in]       mapDimensionScaleFactor      scale factor
260    *
261    * \return none
262    */
setMapDimensionScaleFactor(int mapDimensionScaleFactor)263   void setMapDimensionScaleFactor(int mapDimensionScaleFactor) {
264     this->mMapDimensionScaleFactor = mapDimensionScaleFactor;
265   }
266 
267   /*!\brief get gain map dimension scale factor
268    * NOTE: Applicable only in encoding scenario
269    *
270    * \return mapDimensionScaleFactor
271    */
getMapDimensionScaleFactor()272   int getMapDimensionScaleFactor() { return this->mMapDimensionScaleFactor; }
273 
274   /*!\brief set gain map compression quality factor
275    * NOTE: Applicable only in encoding scenario
276    *
277    * \param[in]       mapCompressQuality      quality factor for gain map image compression
278    *
279    * \return none
280    */
setMapCompressQuality(int mapCompressQuality)281   void setMapCompressQuality(int mapCompressQuality) {
282     this->mMapCompressQuality = mapCompressQuality;
283   }
284 
285   /*!\brief get gain map quality factor
286    * NOTE: Applicable only in encoding scenario
287    *
288    * \return quality factor
289    */
getMapCompressQuality()290   int getMapCompressQuality() { return this->mMapCompressQuality; }
291 
292   /*!\brief set gain map gamma
293    * NOTE: Applicable only in encoding scenario
294    *
295    * \param[in]       gamma      gamma parameter that is used for gain map calculation
296    *
297    * \return none
298    */
setGainMapGamma(float gamma)299   void setGainMapGamma(float gamma) { this->mGamma = gamma; }
300 
301   /*!\brief get gain map gamma
302    * NOTE: Applicable only in encoding scenario
303    *
304    * \return gamma parameter
305    */
getGainMapGamma()306   float getGainMapGamma() { return this->mGamma; }
307 
308   /*!\brief enable / disable multi channel gain map
309    * NOTE: Applicable only in encoding scenario
310    *
311    * \param[in]       useMultiChannelGainMap      enable / disable multi channel gain map
312    *
313    * \return none
314    */
setUseMultiChannelGainMap(bool useMultiChannelGainMap)315   void setUseMultiChannelGainMap(bool useMultiChannelGainMap) {
316     this->mUseMultiChannelGainMap = useMultiChannelGainMap;
317   }
318 
319   /*!\brief check if multi channel gain map is enabled
320    * NOTE: Applicable only in encoding scenario
321    *
322    * \return true if multi channel gain map is enabled, false otherwise
323    */
isUsingMultiChannelGainMap()324   bool isUsingMultiChannelGainMap() { return this->mUseMultiChannelGainMap; }
325 
326   /*!\brief set gain map min and max content boost
327    * NOTE: Applicable only in encoding scenario
328    *
329    * \param[in]       minBoost      gain map min content boost
330    * \param[in]       maxBoost      gain map max content boost
331    *
332    * \return none
333    */
setGainMapMinMaxContentBoost(float minBoost,float maxBoost)334   void setGainMapMinMaxContentBoost(float minBoost, float maxBoost) {
335     this->mMinContentBoost = minBoost;
336     this->mMaxContentBoost = maxBoost;
337   }
338 
339   /*!\brief get gain map min max content boost
340    * NOTE: Applicable only in encoding scenario
341    *
342    * \param[out]       minBoost      gain map min content boost
343    * \param[out]       maxBoost      gain map max content boost
344    *
345    * \return none
346    */
getGainMapMinMaxContentBoost(float & minBoost,float & maxBoost)347   void getGainMapMinMaxContentBoost(float& minBoost, float& maxBoost) {
348     minBoost = this->mMinContentBoost;
349     maxBoost = this->mMaxContentBoost;
350   }
351 
352   /* \brief Alias of Encode API-0.
353    *
354    * \deprecated This function is deprecated. Use its alias
355    */
356   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, ultrahdr_transfer_function hdr_tf,
357                        jr_compressed_ptr dest, int quality, jr_exif_ptr exif);
358 
359   /* \brief Alias of Encode API-1.
360    *
361    * \deprecated This function is deprecated. Use its actual
362    */
363   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, jr_uncompressed_ptr yuv420_image_ptr,
364                        ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest, int quality,
365                        jr_exif_ptr exif);
366 
367   /* \brief Alias of Encode API-2.
368    *
369    * \deprecated This function is deprecated. Use its actual
370    */
371   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, jr_uncompressed_ptr yuv420_image_ptr,
372                        jr_compressed_ptr yuv420jpg_image_ptr, ultrahdr_transfer_function hdr_tf,
373                        jr_compressed_ptr dest);
374 
375   /* \brief Alias of Encode API-3.
376    *
377    * \deprecated This function is deprecated. Use its actual
378    */
379   status_t encodeJPEGR(jr_uncompressed_ptr p010_image_ptr, jr_compressed_ptr yuv420jpg_image_ptr,
380                        ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest);
381 
382   /* \brief Alias of Encode API-4.
383    *
384    * \deprecated This function is deprecated. Use its actual
385    */
386   status_t encodeJPEGR(jr_compressed_ptr yuv420jpg_image_ptr,
387                        jr_compressed_ptr gainmapjpg_image_ptr, ultrahdr_metadata_ptr metadata,
388                        jr_compressed_ptr dest);
389 
390   /* \brief Alias of Decode API
391    *
392    * \deprecated This function is deprecated. Use its actual
393    */
394   status_t decodeJPEGR(jr_compressed_ptr jpegr_image_ptr, jr_uncompressed_ptr dest,
395                        float max_display_boost = FLT_MAX, jr_exif_ptr exif = nullptr,
396                        ultrahdr_output_format output_format = ULTRAHDR_OUTPUT_HDR_LINEAR,
397                        jr_uncompressed_ptr gainmap_image_ptr = nullptr,
398                        ultrahdr_metadata_ptr metadata = nullptr);
399 
400   /* \brief Alias of getJPEGRInfo
401    *
402    * \deprecated This function is deprecated. Use its actual
403    */
404   status_t getJPEGRInfo(jr_compressed_ptr jpegr_image_ptr, jr_info_ptr jpegr_image_info_ptr);
405 
406   /*!\brief This function receives iso block and / or xmp block and parses gainmap metadata and fill
407    * the output descriptor. If both iso block and xmp block are available, then iso block is
408    * preferred over xmp.
409    *
410    * \param[in]       iso_data                  iso memory block
411    * \param[in]       iso_size                  iso block size
412    * \param[in]       xmp_data                  xmp memory block
413    * \param[in]       xmp_size                  xmp block size
414    * \param[in, out]  gainmap_metadata          gainmap metadata descriptor
415    *
416    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
417    */
418   uhdr_error_info_t parseGainMapMetadata(uint8_t* iso_data, size_t iso_size, uint8_t* xmp_data,
419                                          size_t xmp_size,
420                                          uhdr_gainmap_metadata_ext_t* uhdr_metadata);
421 
422   /*!\brief This method is used to tone map a hdr image
423    *
424    * \param[in]            hdr_intent      hdr image descriptor
425    * \param[in, out]       sdr_intent      sdr image descriptor
426    *
427    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
428    */
429   uhdr_error_info_t toneMap(uhdr_raw_image_t* hdr_intent, uhdr_raw_image_t* sdr_intent);
430 
431   /*!\brief This method takes hdr intent and sdr intent and computes gainmap coefficient.
432    *
433    * This method is called in the encoding pipeline. It takes uncompressed 8-bit and 10-bit yuv
434    * images as input and calculates gainmap.
435    *
436    * NOTE: The input images must be the same resolution.
437    * NOTE: The SDR input is assumed to use the sRGB transfer function.
438    *
439    * \param[in]       sdr_intent               sdr intent raw input image descriptor
440    * \param[in]       hdr_intent               hdr intent raw input image descriptor
441    * \param[in, out]  gainmap_metadata         gainmap metadata descriptor
442    * \param[in, out]  gainmap_img              gainmap image descriptor
443    * \param[in]       sdr_is_601               (optional) if sdr_is_601 is true, then use BT.601
444    *                                           gamut to represent sdr intent regardless of the value
445    *                                           present in the sdr intent image descriptor
446    * \param[in]       use_luminance            (optional) used for single channel gainmap. If
447    *                                           use_luminance is true, gainmap calculation is based
448    *                                           on the pixel's luminance which is a weighted
449    *                                           combination of r, g, b channels; otherwise, gainmap
450    *                                           calculation is based of the maximun value of r, g, b
451    *                                           channels.
452    *
453    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
454    */
455   uhdr_error_info_t generateGainMap(uhdr_raw_image_t* sdr_intent, uhdr_raw_image_t* hdr_intent,
456                                     uhdr_gainmap_metadata_ext_t* gainmap_metadata,
457                                     std::unique_ptr<uhdr_raw_image_ext_t>& gainmap_img,
458                                     bool sdr_is_601 = false, bool use_luminance = true);
459 
460  protected:
461   /*!\brief This method takes sdr intent, gainmap image and gainmap metadata and computes hdr
462    * intent. This method is called in the decoding pipeline. The output hdr intent image will have
463    * same color gamut as sdr intent.
464    *
465    * NOTE: The SDR input is assumed to use the sRGB transfer function.
466    *
467    * \param[in]       sdr_intent               sdr intent raw input image descriptor
468    * \param[in]       gainmap_img              gainmap image descriptor
469    * \param[in]       gainmap_metadata         gainmap metadata descriptor
470    * \param[in]       output_ct                output color transfer
471    * \param[in]       output_format            output pixel format
472    * \param[in]       max_display_boost        the maximum available boost supported by a
473    *                                           display, the value must be greater than or equal
474    *                                           to 1.0
475    * \param[in, out]  dest                     output image descriptor to store output
476    *
477    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
478    */
479   uhdr_error_info_t applyGainMap(uhdr_raw_image_t* sdr_intent, uhdr_raw_image_t* gainmap_img,
480                                  uhdr_gainmap_metadata_ext_t* gainmap_metadata,
481                                  uhdr_color_transfer_t output_ct, uhdr_img_fmt_t output_format,
482                                  float max_display_boost, uhdr_raw_image_t* dest);
483 
484  private:
485   /*!\brief compress gainmap image
486    *
487    * \param[in]       gainmap_img              gainmap image descriptor
488    * \param[in]       jpeg_enc_obj             jpeg encoder object handle
489    *
490    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
491    */
492   uhdr_error_info_t compressGainMap(uhdr_raw_image_t* gainmap_img, JpegEncoderHelper* jpeg_enc_obj);
493 
494   /*!\brief This method is called to separate base image and gain map image from compressed
495    * ultrahdr image
496    *
497    * \param[in]            jpegr_image               compressed ultrahdr image descriptor
498    * \param[in, out]       primary_image             sdr image descriptor
499    * \param[in, out]       gainmap_image             gainmap image descriptor
500    *
501    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
502    */
503   uhdr_error_info_t extractPrimaryImageAndGainMap(uhdr_compressed_image_t* jpegr_image,
504                                                   uhdr_compressed_image_t* primary_image,
505                                                   uhdr_compressed_image_t* gainmap_image);
506 
507   /*!\brief This function parses the bitstream and returns metadata that is useful for actual
508    * decoding. This does not decode the image. That is handled by decompressImage().
509    *
510    * \param[in]            jpeg_image      compressed jpeg image descriptor
511    * \param[in, out]       image_info      image info descriptor
512    * \param[in, out]       img_width       (optional) image width
513    * \param[in, out]       img_height      (optional) image height
514    *
515    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
516    */
517   uhdr_error_info_t parseJpegInfo(uhdr_compressed_image_t* jpeg_image, j_info_ptr image_info,
518                                   unsigned int* img_width = nullptr,
519                                   unsigned int* img_height = nullptr);
520 
521   /*!\brief This method takes compressed sdr intent, compressed gainmap coefficient, gainmap
522    * metadata and creates a ultrahdr image. This is done by first generating XMP packet from gainmap
523    * metadata, then appending in the order,
524    *    SOI, APP2 (Exif is present), APP2 (XMP), base image, gain map image.
525    *
526    * NOTE: In the final output, EXIF package will appear if ONLY ONE of the following conditions is
527    * fulfilled:
528    * (1) EXIF package is available from outside input. I.e. pExif != nullptr.
529    * (2) Compressed sdr intent has EXIF.
530    * If both conditions are fulfilled, this method will return error indicating that it is unable to
531    * choose which exif to be placed in the bitstream.
532    *
533    * \param[in]       sdr_intent_compressed    sdr intent image descriptor
534    * \param[in]       gainmap_compressed       gainmap intent input image descriptor
535    * \param[in]       pExif                    exif block to be placed in the bitstream
536    * \param[in]       pIcc                     pointer to icc segment that needs to be added to the
537    *                                           compressed image
538    * \param[in]       icc_size                 size of icc segment
539    * \param[in]       metadata                 gainmap metadata descriptor
540    * \param[in, out]  dest                     output image descriptor to store compressed ultrahdr
541    *                                           image
542    *
543    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
544    */
545   uhdr_error_info_t appendGainMap(uhdr_compressed_image_t* sdr_intent_compressed,
546                                   uhdr_compressed_image_t* gainmap_compressed,
547                                   uhdr_mem_block_t* pExif, void* pIcc, size_t icc_size,
548                                   uhdr_gainmap_metadata_ext_t* metadata,
549                                   uhdr_compressed_image_t* dest);
550 
551   /*!\brief This method is used to convert a raw image from one gamut space to another gamut space
552    * in-place.
553    *
554    * \param[in, out]  image              raw image descriptor
555    * \param[in]       src_encoding       input gamut space
556    * \param[in]       dst_encoding       destination gamut space
557    *
558    * \return uhdr_error_info_t #UHDR_CODEC_OK if operation succeeds, uhdr_codec_err_t otherwise.
559    */
560   uhdr_error_info_t convertYuv(uhdr_raw_image_t* image, uhdr_color_gamut_t src_encoding,
561                                uhdr_color_gamut_t dst_encoding);
562 
563   /*
564    * This method will check the validity of the input arguments.
565    *
566    * @param p010_image_ptr uncompressed HDR image in P010 color format
567    * @param yuv420_image_ptr pointer to uncompressed SDR image struct. HDR image is expected to
568    *                         be in 420p color format
569    * @param hdr_tf transfer function of the HDR image
570    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
571    *             represents the maximum available size of the desitination buffer, and it must be
572    *             set before calling this method. If the encoded JPEGR size exceeds
573    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
574    * @return NO_ERROR if the input args are valid, error code is not valid.
575    */
576   status_t areInputArgumentsValid(jr_uncompressed_ptr p010_image_ptr,
577                                   jr_uncompressed_ptr yuv420_image_ptr,
578                                   ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest_ptr);
579 
580   /*
581    * This method will check the validity of the input arguments.
582    *
583    * @param p010_image_ptr uncompressed HDR image in P010 color format
584    * @param yuv420_image_ptr pointer to uncompressed SDR image struct. HDR image is expected to
585    *                         be in 420p color format
586    * @param hdr_tf transfer function of the HDR image
587    * @param dest destination of the compressed JPEGR image. Please note that {@code maxLength}
588    *             represents the maximum available size of the destination buffer, and it must be
589    *             set before calling this method. If the encoded JPEGR size exceeds
590    *             {@code maxLength}, this method will return {@code ERROR_JPEGR_BUFFER_TOO_SMALL}.
591    * @param quality target quality of the JPEG encoding, must be in range of 0-100 where 100 is
592    *                the highest quality
593    * @return NO_ERROR if the input args are valid, error code is not valid.
594    */
595   status_t areInputArgumentsValid(jr_uncompressed_ptr p010_image_ptr,
596                                   jr_uncompressed_ptr yuv420_image_ptr,
597                                   ultrahdr_transfer_function hdr_tf, jr_compressed_ptr dest,
598                                   int quality);
599 
600   // Configurations
601   void* mUhdrGLESCtxt;              // opengl es context
602   int mMapDimensionScaleFactor;     // gain map scale factor
603   int mMapCompressQuality;          // gain map quality factor
604   bool mUseMultiChannelGainMap;     // enable multichannel gain map
605   float mGamma;                     // gain map gamma parameter
606   uhdr_enc_preset_t mEncPreset;     // encoding speed preset
607   float mMinContentBoost;           // min content boost recommendation
608   float mMaxContentBoost;           // max content boost recommendation
609   float mTargetDispPeakBrightness;  // target display max luminance in nits
610 };
611 
612 /*
613  * Holds tonemapping results of a pixel
614  */
615 struct GlobalTonemapOutputs {
616   std::array<float, 3> rgb_out;
617   float y_hdr;
618   float y_sdr;
619 };
620 
621 /*!\brief Applies a global tone mapping, based on Chrome's HLG/PQ rendering implemented at
622  *  https://source.chromium.org/chromium/chromium/src/+/main:ui/gfx/color_transform.cc;l=1197-1252;drc=ac505aff1d29ec3bfcf317cb77d5e196a3664e92
623  *
624  * \param[in]       rgb_in              hdr intent pixel in array format.
625  * \param[in]       headroom            ratio between hdr and sdr peak luminances. Must be greater
626  *                                      than 1. If the input is normalized, then this is used to
627  *                                      stretch it linearly from [0.0..1.0] to [0.0..headroom]
628  * \param[in]       is_normalized       marker to differentiate, if the input is normalized.
629  *
630  * \return tonemapped pixel in the normalized range [0.0..1.0]
631  */
632 GlobalTonemapOutputs globalTonemap(const std::array<float, 3>& rgb_in, float headroom,
633                                    bool is_normalized);
634 
635 }  // namespace ultrahdr
636 
637 #endif  // ULTRAHDR_JPEGR_H
638