Coverage for models/rgb/transfer_functions/apple_log_profile.py: 58%

1"""

2 Apple Log Profile Log Encoding

3==============================

4

5 Define the *Apple Log Profile* log encoding.

6

7- :func:`colour.models.log_encoding_AppleLogProfile`

8- :func:`colour.models.log_decoding_AppleLogProfile`

9

10 References

11----------

12- :cite:`AppleInc.2023` : Apple Inc. (2023). Apple Log Profile White Paper.

13 https://developer.apple.com/download/all/?q=Apple%20log%20profile

14- :cite:`TheAcademyofMotionPictureArtsandSciences2023` : The Academy of

15 Motion Picture Arts and Sciences. (2023). IDT.Apple.AppleLog_BT2020.ctl.

16 Retrieved December 17, 2023, from

17 https://github.com/ampas/aces-dev/blob/\

18 528c78fe2c0f4e7eb322581e98aba05de79466cb/transforms/ctl/idt/vendorSupplied/\

19 apple/IDT.Apple.AppleLog_BT2020.ctl

20

21"""

22

23 from __future__ import annotations

24

25 import numpy as np

26

27 from colour.hints import ( # noqa: TC001

28 Domain1,

29 Range1,

30)

31 from colour.utilities import Structure, as_float, from_range_1, optional, to_domain_1

32

33 __author__ = "Colour Developers"

34 __copyright__ = "Copyright 2013 Colour Developers"

35 __license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"

36 __maintainer__ = "Colour Developers"

37 __email__ = "colour-developers@colour-science.org"

38 __status__ = "Production"

39

40 __all__ = [

41 "CONSTANTS_APPLE_LOG_PROFILE",

42 "log_encoding_AppleLogProfile",

43 "log_decoding_AppleLogProfile",

44]

45

46 CONSTANTS_APPLE_LOG_PROFILE: Structure = Structure(

47 R_0=-0.05641088,

48 R_t=0.01,

49 sigma=47.28711236,

50 beta=0.00964052,

51 gamma=0.08550479,

52 delta=0.69336945,

53)

54"""*Apple Log Profile* constants."""

55

56

57 def log_encoding_AppleLogProfile(

58 R: Domain1,

59 constants: Structure | None = None,

60) -> Range1:

61 """

62 Apply the *Apple Log Profile* log encoding opto-electronic transfer function (OETF).

63

64 Parameters

65 ----------

66 R

67 Linear reflection data :math:`R`.

68 constants

69 *Apple Log Profile* constants.

70

71 Returns

72 -------

73 :class:`numpy.ndarray`

74 Logarithmically encoded value :math:`P`.

75

76 References

77 ----------

78 :cite:`AppleInc.2023`,

79 :cite:`TheAcademyofMotionPictureArtsandSciences2023`

80

81 Notes

82 -----

83 - The scene reflection signal :math:`R` captured by the camera is

84 represented using a floating point encoding. The :math:`R` value

85 of 0.18 corresponds to the signal produced by an 18% reflectance

86 reference gray chart.

87

88 +------------+-----------------------+---------------+

89 | **Domain** | **Scale - Reference** | **Scale - 1** |

90 +============+=======================+===============+

91 | ``R`` | 1 | 1 |

92 +------------+-----------------------+---------------+

93

94 +------------+-----------------------+---------------+

95 | **Range** | **Scale - Reference** | **Scale - 1** |

96 +============+=======================+===============+

97 | ``P`` | 1 | 1 |

98 +------------+-----------------------+---------------+

99

100 Examples

101 --------

102 >>> log_encoding_AppleLogProfile(0.18) # doctest: +ELLIPSIS

103 0.4882724...

104 """

105

106 R = to_domain_1(R)

107 constants = optional(constants, CONSTANTS_APPLE_LOG_PROFILE)

108

109 R_0 = constants.R_0

110 R_t = constants.R_t

111 sigma = constants.sigma

112 beta = constants.beta

113 gamma = constants.gamma

114 delta = constants.delta

115

116 P = np.select(

117 [

118 R >= R_t, # noqa: SIM300

119 np.logical_and(R_0 <= R, R < R_t), # noqa: SIM300

120 R < R_0,

121 ],

122 [

123 gamma * np.log2(R + beta) + delta,

124 sigma * (R - R_0) ** 2,

125 0,

126 ],

127 )

128

129 return as_float(from_range_1(P))

130

131

132 def log_decoding_AppleLogProfile(

133 P: Domain1,

134 constants: Structure | None = None,

135) -> Range1:

136 """

137 Apply the *Apple Log Profile* log decoding inverse opto-electronic transfer

138 function (OETF).

139

140 Parameters

141 ----------

142 P

143 Logarithmically encoded value :math:`P`.

144 constants

145 *Apple Log Profile* constants.

146

147 Returns

148 -------

149 :class:`numpy.ndarray`

150 Linear reflection data :math:`R`.

151

152 References

153 ----------

154 :cite:`AppleInc.2023`,

155 :cite:`TheAcademyofMotionPictureArtsandSciences2023`

156

157 Notes

158 -----

159 - The captured pixel :math:`P` value uses floating point encoding

160 normalized to the [0, 1] range.

161

162 +------------+-----------------------+---------------+

163 | **Domain** | **Scale - Reference** | **Scale - 1** |

164 +============+=======================+===============+

165 | ``P`` | 1 | 1 |

166 +------------+-----------------------+---------------+

167

168 +------------+-----------------------+---------------+

169 | **Range** | **Scale - Reference** | **Scale - 1** |

170 +============+=======================+===============+

171 | ``R`` | 1 | 1 |

172 +------------+-----------------------+---------------+

173

174 Examples

175 --------

176 >>> log_decoding_AppleLogProfile(0.48827245852686763) # doctest: +ELLIPSIS

177 0.1800000...

178 """

179

180 P = to_domain_1(P)

181 constants = optional(constants, CONSTANTS_APPLE_LOG_PROFILE)

182

183 R_0 = constants.R_0

184 R_t = constants.R_t

185 sigma = constants.sigma

186 beta = constants.beta

187 gamma = constants.gamma

188 delta = constants.delta

189

190 P_t = sigma * (R_t - R_0) ** 2

191

192 R = np.select(

193 [

194 P >= P_t, # noqa: SIM300

195 np.logical_and(0 <= P, P < P_t), # noqa: SIM300

196 P < 0,

197 ],

198 [

199 2 ** ((P - delta) / gamma) - beta,

200 np.sqrt(P / sigma) + R_0,

201 R_0,

202 ],

203 )

204

205 return as_float(from_range_1(R))