Coverage Report

Created: 2024-05-20 07:14

/src/skia/include/private/SkGainmapInfo.h
Line
Count
Source (jump to first uncovered line)
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
#include "include/core/SkColorSpace.h"
13
#include "include/core/SkRefCnt.h"
14
class SkData;
15
16
/**
17
 *  Gainmap rendering parameters. Suppose our display has HDR to SDR ratio of H and we wish to
18
 *  display an image with gainmap on this display. Let B be the pixel value from the base image
19
 *  in a color space that has the primaries of the base image and a linear transfer function. Let
20
 *  G be the pixel value from the gainmap. Let D be the output pixel in the same color space as B.
21
 *  The value of D is computed as follows:
22
 *
23
 *  First, let W be a weight parameter determing how much the gainmap will be applied.
24
 *    W = clamp((log(H)                - log(fDisplayRatioSdr)) /
25
 *              (log(fDisplayRatioHdr) - log(fDisplayRatioSdr), 0, 1)
26
 *
27
 *  Next, let L be the gainmap value in log space. We compute this from the value G that was
28
 *  sampled from the texture as follows:
29
 *    L = mix(log(fGainmapRatioMin), log(fGainmapRatioMax), pow(G, fGainmapGamma))
30
 *
31
 *  Finally, apply the gainmap to compute D, the displayed pixel. If the base image is SDR then
32
 *  compute:
33
 *    D = (B + fEpsilonSdr) * exp(L * W) - fEpsilonHdr
34
 *  If the base image is HDR then compute:
35
 *    D = (B + fEpsilonHdr) * exp(L * (W - 1)) - fEpsilonSdr
36
 *
37
 *  In the above math, log() is a natural logarithm and exp() is natural exponentiation. Note,
38
 *  however, that the base used for the log() and exp() functions does not affect the results of
39
 *  the computation (it cancels out, as long as the same base is used throughout).
40
 *
41
 *  This product includes Gain Map technology under license by Adobe.
42
 */
43
struct SkGainmapInfo {
44
    /**
45
     *  Parameters for converting the gainmap from its image encoding to log space. These are
46
     *  specified per color channel. The alpha value is unused.
47
     */
48
    SkColor4f fGainmapRatioMin = {1.f, 1.f, 1.f, 1.0};
49
    SkColor4f fGainmapRatioMax = {2.f, 2.f, 2.f, 1.0};
50
    SkColor4f fGainmapGamma = {1.f, 1.f, 1.f, 1.f};
51
52
    /**
53
     *  Parameters sometimes used in gainmap computation to avoid numerical instability.
54
     */
55
    SkColor4f fEpsilonSdr = {0.f, 0.f, 0.f, 1.0};
56
    SkColor4f fEpsilonHdr = {0.f, 0.f, 0.f, 1.0};
57
58
    /**
59
     *  If the output display's HDR to SDR ratio is less or equal than fDisplayRatioSdr then the SDR
60
     *  rendition is displayed. If the output display's HDR to SDR ratio is greater or equal than
61
     *  fDisplayRatioHdr then the HDR rendition is displayed. If the output display's HDR to SDR
62
     *  ratio is between these values then an interpolation between the two is displayed using the
63
     *  math above.
64
     */
65
    float fDisplayRatioSdr = 1.f;
66
    float fDisplayRatioHdr = 2.f;
67
68
    /**
69
     *  Whether the base image is the SDR image or the HDR image.
70
     */
71
    enum class BaseImageType {
72
        kSDR,
73
        kHDR,
74
    };
75
    BaseImageType fBaseImageType = BaseImageType::kSDR;
76
77
    /**
78
     *  The type of the gainmap image. If the type is kApple, then the gainmap image was originally
79
     *  encoded according to the specification at [0], and can be converted to the kDefault type by
80
     *  applying the transformation described at [1].
81
     *  [0] https://developer.apple.com/documentation/appkit/images_and_pdf/
82
     *      applying_apple_hdr_effect_to_your_photos
83
     *  [1] https://docs.google.com/document/d/1iUpYAThVV_FuDdeiO3t0vnlfoA1ryq0WfGS9FuydwKc
84
     */
85
    enum class Type {
86
        kDefault,
87
        kApple,
88
    };
89
    Type fType = Type::kDefault;
90
91
    /**
92
     * If specified, color space to apply the gainmap in, otherwise the base image's color space
93
     * is used. Only the color primaries are used, the transfer function is irrelevant.
94
     */
95
    sk_sp<SkColorSpace> fGainmapMathColorSpace = nullptr;
96
97
    /**
98
     * If |data| contains an ISO 21496-1 version that is supported, return true. Otherwise return
99
     * false.
100
     */
101
    static bool ParseVersion(const SkData* data);
102
103
    /**
104
     * If |data| constains ISO 21496-1 metadata then parse that metadata then use it to populate
105
     * |info| and return true, otherwise return false. If |data| indicates that that the base image
106
     * color space primaries should be used for gainmap application then set
107
     * |fGainmapMathColorSpace| to nullptr, otherwise set |fGainmapMathColorSpace| to sRGB (the
108
     * default, to be overwritten by the image decoder).
109
     */
110
    static bool Parse(const SkData* data, SkGainmapInfo& info);
111
112
    /**
113
     * Serialize an ISO 21496-1 version 0 blob containing only the version structure.
114
     */
115
    static sk_sp<SkData> SerializeVersion();
116
117
    /**
118
     * Serialize an ISO 21496-1 version 0 blob containing this' gainmap parameters.
119
     */
120
    sk_sp<SkData> serialize() const;
121
122
0
    inline bool operator==(const SkGainmapInfo& other) const {
123
0
        return fGainmapRatioMin == other.fGainmapRatioMin &&
124
0
               fGainmapRatioMax == other.fGainmapRatioMax && fGainmapGamma == other.fGainmapGamma &&
125
0
               fEpsilonSdr == other.fEpsilonSdr && fEpsilonHdr == other.fEpsilonHdr &&
126
0
               fDisplayRatioSdr == other.fDisplayRatioSdr &&
127
0
               fDisplayRatioHdr == other.fDisplayRatioHdr &&
128
0
               fBaseImageType == other.fBaseImageType && fType == other.fType &&
129
0
               SkColorSpace::Equals(fGainmapMathColorSpace.get(),
130
0
                                    other.fGainmapMathColorSpace.get());
131
0
    }
132
0
    inline bool operator!=(const SkGainmapInfo& other) const { return !(*this == other); }
133
};
134
135
#endif