Coverage for models/rgb/transfer_functions/nikon_n_log.py: 59%

1"""

2 Nikon N-Log Log Encoding

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

4

5 Define the *Nikon N-Log* log encoding.

6

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

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

9

10 References

11----------

12- :cite:`Nikon2018` : Nikon. (2018). N-Log Specification Document - Version

13 1.0.0 (pp. 1-5). Retrieved September 9, 2019, from

14 http://download.nikonimglib.com/archive3/hDCmK00m9JDI03RPruD74xpoU905/\

15 N-Log_Specification_(En)01.pdf

16"""

17

18 from __future__ import annotations

19

20 import numpy as np

21

22 from colour.algebra import spow

23 from colour.hints import ( # noqa: TC001

24 Domain1,

25 Range1,

26)

27 from colour.models.rgb.transfer_functions import full_to_legal, legal_to_full

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

29

30 __author__ = "Colour Developers"

31 __copyright__ = "Copyright 2013 Colour Developers"

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

33 __maintainer__ = "Colour Developers"

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

35 __status__ = "Production"

36

37 __all__ = [

38 "CONSTANTS_NLOG",

39 "log_encoding_NLog",

40 "log_decoding_NLog",

41]

42

43 CONSTANTS_NLOG: Structure = Structure(

44 cut1=0.328,

45 cut2=(452 / 1023),

46 a=(650 / 1023),

47 b=0.0075,

48 c=(150 / 1023),

49 d=(619 / 1023),

50)

51"""*Nikon N-Log* constants."""

52

53

54 def log_encoding_NLog(

55 y: Domain1,

56 bit_depth: int = 10,

57 out_normalised_code_value: bool = True,

58 in_reflection: bool = True,

59 constants: Structure | None = None,

60) -> Range1:

61 """

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

63

64 Parameters

65 ----------

66 y

67 Linear light reflectance :math:`y`, where :math:`y = 0.18` represents

68 middle grey at Stop 0.

69 bit_depth

70 Bit-depth used for conversion.

71 out_normalised_code_value

72 Whether to return the *Nikon N-Log* encoded data :math:`x` as

73 normalised code values.

74 in_reflection

75 Whether the input light level represents reflected light.

76 constants

77 *Nikon N-Log* constants.

78

79 Returns

80 -------

81 :class:`numpy.ndarray`

82 *N-Log* 10-bit equivalent code value :math:`x`.

83

84 Notes

85 -----

86 +------------+-----------------------+---------------+

87 | **Domain** | **Scale - Reference** | **Scale - 1** |

88 +============+=======================+===============+

89 | ``y`` | 1 | 1 |

90 +------------+-----------------------+---------------+

91

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

93 | **Range** | **Scale - Reference** | **Scale - 1** |

94 +============+=======================+===============+

95 | ``x`` | 1 | 1 |

96 +------------+-----------------------+---------------+

97

98 References

99 ----------

100 :cite:`Nikon2018`

101

102 Examples

103 --------

104 >>> log_encoding_NLog(0.18) # doctest: +ELLIPSIS

105 0.3636677...

106 """

107

108 y = to_domain_1(y)

109 constants = optional(constants, CONSTANTS_NLOG)

110

111 if not in_reflection:

112 y = y * 0.9

113

114 cut1 = constants.cut1

115 a = constants.a

116 b = constants.b

117 c = constants.c

118 d = constants.d

119

120 x = np.where(

121 y < cut1,

122 a * spow(y + b, 1 / 3),

123 c * np.log(y) + d,

124 )

125

126 x_cv = x if out_normalised_code_value else legal_to_full(x, bit_depth)

127

128 return as_float(from_range_1(x_cv))

129

130

131 def log_decoding_NLog(

132 x: Domain1,

133 bit_depth: int = 10,

134 in_normalised_code_value: bool = True,

135 out_reflection: bool = True,

136 constants: Structure | None = None,

137) -> Range1:

138 """

139 Apply the *Nikon N-Log* log decoding inverse opto-electronic transfer

140 function (OETF).

141

142 Parameters

143 ----------

144 x

145 *N-Log* 10-bit equivalent code value :math:`x`.

146 bit_depth

147 Bit-depth used for conversion.

148 in_normalised_code_value

149 Whether the non-linear *Nikon N-Log* data :math:`x` is encoded as

150 normalised code values.

151 out_reflection

152 Whether the light level :math:`y` to a camera is reflection.

153 constants

154 *Nikon N-Log* constants.

155

156 Returns

157 -------

158 :class:`numpy.ndarray`

159 Linear light reflectance :math:`y`, where :math:`y = 0.18` represents

160 middle grey at Stop 0.

161

162 Notes

163 -----

164 +------------+-----------------------+---------------+

165 | **Domain** | **Scale - Reference** | **Scale - 1** |

166 +============+=======================+===============+

167 | ``x`` | 1 | 1 |

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

169

170 +------------+-----------------------+---------------+

171 | **Range** | **Scale - Reference** | **Scale - 1** |

172 +============+=======================+===============+

173 | ``y`` | 1 | 1 |

174 +------------+-----------------------+---------------+

175

176 References

177 ----------

178 :cite:`Nikon2018`

179

180 Examples

181 --------

182 >>> log_decoding_NLog(0.36366777011713869) # doctest: +ELLIPSIS

183 0.1799999...

184 """

185

186 x = to_domain_1(x)

187 constants = optional(constants, CONSTANTS_NLOG)

188

189 x = x if in_normalised_code_value else full_to_legal(x, bit_depth)

190

191 cut2 = constants.cut2

192 a = constants.a

193 b = constants.b

194 c = constants.c

195 d = constants.d

196

197 y = np.where(

198 x < cut2,

199 spow(x / a, 3) - b,

200 np.exp((x - d) / c),

201 )

202

203 if not out_reflection:

204 y = y / 0.9

205

206 return as_float(from_range_1(y))