1 /* 2 * Copyright 2023 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkGainmapInfo_DEFINED 9 #define SkGainmapInfo_DEFINED 10 11 #include "include/core/SkColor.h" 12 13 /** 14 * Gainmap rendering parameters. Suppose our display has HDR to SDR ratio of H and we wish to 15 * display an image with gainmap on this display. Let B be the pixel value from the base image 16 * in a color space that has the primaries of the base image and a linear transfer function. Let 17 * G be the pixel value from the gainmap. Let D be the output pixel in the same color space as B. 18 * The value of D is computed as follows: 19 * 20 * First, let W be a weight parameter determing how much the gainmap will be applied. 21 * W = clamp((log(H) - log(fDisplayRatioSdr)) / 22 * (log(fDisplayRatioHdr) - log(fDisplayRatioSdr), 0, 1) 23 * 24 * Next, let L be the gainmap value in log space. We compute this from the value G that was 25 * sampled from the texture as follows: 26 * L = mix(log(fGainmapRatioMin), log(fGainmapRatioMax), pow(G, fGainmapGamma)) 27 * 28 * Finally, apply the gainmap to compute D, the displayed pixel. If the base image is SDR then 29 * compute: 30 * D = (B + fEpsilonSdr) * exp(L * W) - fEpsilonHdr 31 * If the base image is HDR then compute: 32 * D = (B + fEpsilonHdr) * exp(L * (W - 1)) - fEpsilonSdr 33 * 34 * In the above math, log() is a natural logarithm and exp() is natural exponentiation. Note, 35 * however, that the base used for the log() and exp() functions does not affect the results of 36 * the computation (it cancels out, as long as the same base is used throughout). 37 */ 38 struct SkGainmapInfo { 39 /** 40 * Parameters for converting the gainmap from its image encoding to log space. These are 41 * specified per color channel. The alpha value is unused. 42 */ 43 SkColor4f fGainmapRatioMin = {1.f, 1.f, 1.f, 1.0}; 44 SkColor4f fGainmapRatioMax = {2.f, 2.f, 2.f, 1.0}; 45 SkColor4f fGainmapGamma = {1.f, 1.f, 1.f, 1.f}; 46 47 /** 48 * Parameters sometimes used in gainmap computation to avoid numerical instability. 49 */ 50 SkColor4f fEpsilonSdr = {0.f, 0.f, 0.f, 1.0}; 51 SkColor4f fEpsilonHdr = {0.f, 0.f, 0.f, 1.0}; 52 53 /** 54 * If the output display's HDR to SDR ratio is less or equal than fDisplayRatioSdr then the SDR 55 * rendition is displayed. If the output display's HDR to SDR ratio is greater or equal than 56 * fDisplayRatioHdr then the HDR rendition is displayed. If the output display's HDR to SDR 57 * ratio is between these values then an interpolation between the two is displayed using the 58 * math above. 59 */ 60 float fDisplayRatioSdr = 1.f; 61 float fDisplayRatioHdr = 2.f; 62 63 /** 64 * Whether the base image is the SDR image or the HDR image. 65 */ 66 enum class BaseImageType { 67 kSDR, 68 kHDR, 69 }; 70 BaseImageType fBaseImageType = BaseImageType::kSDR; 71 72 inline bool operator==(const SkGainmapInfo& other) { 73 return fGainmapRatioMin == other.fGainmapRatioMin && 74 fGainmapRatioMax == other.fGainmapRatioMax && fGainmapGamma == other.fGainmapGamma && 75 fEpsilonSdr == other.fEpsilonSdr && fEpsilonHdr == other.fEpsilonHdr && 76 fDisplayRatioSdr == other.fDisplayRatioSdr && 77 fDisplayRatioHdr == other.fDisplayRatioHdr && fBaseImageType == other.fBaseImageType; 78 } 79 inline bool operator!=(const SkGainmapInfo& other) { return !(*this == other); } 80 81 // TODO(ccameron): Remove these parameters once we are certain they are not used in Android. 82 enum class Type { 83 kUnknown, 84 kMultiPicture, 85 kJpegR_Linear, 86 kJpegR_HLG, 87 kJpegR_PQ, 88 kHDRGM, 89 }; 90 SkColor4f fLogRatioMin = {0.f, 0.f, 0.f, 1.0}; 91 SkColor4f fLogRatioMax = {1.f, 1.f, 1.f, 1.0}; 92 float fHdrRatioMin = 1.f; 93 float fHdrRatioMax = 50.f; 94 Type fType = Type::kUnknown; 95 }; 96 97 #endif 98