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

1"""

2 Panasonic V-Log Log Encoding

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

4

5 Define the *Panasonic V-Log* log encoding.

6

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

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

9

10 References

11----------

12- :cite:`Panasonic2014a` : Panasonic. (2014). VARICAM V-Log/V-Gamut (pp.

13 1-7).

14 http://pro-av.panasonic.net/en/varicam/common/pdf/VARICAM_V-Log_V-Gamut.pdf

15"""

16

17 from __future__ import annotations

18

19 import numpy as np

20

21 from colour.hints import ( # noqa: TC001

22 Domain1,

23 Range1,

24)

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

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

27

28 __author__ = "Colour Developers"

29 __copyright__ = "Copyright 2013 Colour Developers"

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

31 __maintainer__ = "Colour Developers"

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

33 __status__ = "Production"

34

35 __all__ = [

36 "CONSTANTS_VLOG",

37 "log_encoding_VLog",

38 "log_decoding_VLog",

39]

40

41 CONSTANTS_VLOG: Structure = Structure(

42 cut1=0.01, cut2=0.181, b=0.00873, c=0.241514, d=0.598206

43)

44"""*Panasonic V-Log* constants."""

45

46

47 def log_encoding_VLog(

48 L_in: Domain1,

49 bit_depth: int = 10,

50 out_normalised_code_value: bool = True,

51 in_reflection: bool = True,

52 constants: Structure | None = None,

53) -> Range1:

54 """

55 Apply the *Panasonic V-Log* log encoding opto-electronic transfer function (OETF).

56

57 Parameters

58 ----------

59 L_in

60 Linear reflection data :math:`L_{in}`.

61 bit_depth

62 Bit-depth used for conversion.

63 out_normalised_code_value

64 Whether the *Panasonic V-Log* non-linear data :math:`V_{out}` is

65 encoded as normalised code values.

66 in_reflection

67 Whether the light level :math:`L_{in}` to a camera is reflection.

68 constants

69 *Panasonic V-Log* constants.

70

71 Returns

72 -------

73 :class:`numpy.ndarray`

74 *Panasonic V-Log* mon-linear encoded data :math:`V_{out}`.

75

76 Notes

77 -----

78 +------------+-----------------------+---------------+

79 | **Domain** | **Scale - Reference** | **Scale - 1** |

80 +============+=======================+===============+

81 | ``L_in`` | 1 | 1 |

82 +------------+-----------------------+---------------+

83

84 +------------+-----------------------+---------------+

85 | **Range** | **Scale - Reference** | **Scale - 1** |

86 +============+=======================+===============+

87 | ``V_out`` | 1 | 1 |

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

89

90 References

91 ----------

92 :cite:`Panasonic2014a`

93

94 Examples

95 --------

96 >>> log_encoding_VLog(0.18) # doctest: +ELLIPSIS

97 0.4233114...

98

99 The values of *Fig.2.2 V-Log Code Value* table in :cite:`Panasonic2014a`

100 are obtained as follows:

101

102 >>> L_in = np.array([0, 18, 90]) / 100

103 >>> np.around(log_encoding_VLog(L_in, 10, False) * 100).astype(np.int_)

104 array([ 7, 42, 61])

105 >>> np.around(log_encoding_VLog(L_in) * (2**10 - 1)).astype(np.int_)

106 array([128, 433, 602])

107 >>> np.around(log_encoding_VLog(L_in) * (2**12 - 1)).astype(np.int_)

108 array([ 512, 1733, 2409])

109

110 Note that some values in the last column values of

111 *Fig.2.2 V-Log Code Value* table in :cite:`Panasonic2014a` are different

112 by a code: [512, 1732, 2408].

113 """

114

115 L_in = to_domain_1(L_in)

116 constants = optional(constants, CONSTANTS_VLOG)

117

118 if not in_reflection:

119 L_in = L_in * 0.9

120

121 cut1 = constants.cut1

122 b = constants.b

123 c = constants.c

124 d = constants.d

125

126 V_out = np.where(

127 L_in < cut1,

128 5.6 * L_in + 0.125,

129 c * np.log10(L_in + b) + d,

130 )

131

132 V_out_cv = V_out if out_normalised_code_value else legal_to_full(V_out, bit_depth)

133

134 return as_float(from_range_1(V_out_cv))

135

136

137 def log_decoding_VLog(

138 V_out: Domain1,

139 bit_depth: int = 10,

140 in_normalised_code_value: bool = True,

141 out_reflection: bool = True,

142 constants: Structure | None = None,

143) -> Range1:

144 """

145 Apply the *Panasonic V-Log* log decoding inverse opto-electronic transfer

146

147 function (OETF).

148

149 Parameters

150 ----------

151 V_out

152 *Panasonic V-Log* mon-linear encoded data :math:`V_{out}`.

153 bit_depth

154 Bit-depth used for conversion.

155 in_normalised_code_value

156 Whether the *Panasonic V-Log* non-linear data :math:`V_{out}` is

157 encoded as normalised code values.

158 out_reflection

159 Whether the light level :math:`L_{in}` to a camera is reflection.

160 constants

161 *Panasonic V-Log* constants.

162

163 Returns

164 -------

165 :class:`numpy.ndarray`

166 Linear reflection data :math:`L_{in}`.

167

168 Notes

169 -----

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

171 | **Domain** | **Scale - Reference** | **Scale - 1** |

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

173 | ``V_out`` | 1 | 1 |

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

175

176 +------------+-----------------------+---------------+

177 | **Range** | **Scale - Reference** | **Scale - 1** |

178 +============+=======================+===============+

179 | ``L_in`` | 1 | 1 |

180 +------------+-----------------------+---------------+

181

182 References

183 ----------

184 :cite:`Panasonic2014a`

185

186 Examples

187 --------

188 >>> log_decoding_VLog(0.423311448760136) # doctest: +ELLIPSIS

189 0.1799999...

190 """

191

192 V_out = to_domain_1(V_out)

193 constants = optional(constants, CONSTANTS_VLOG)

194

195 V_out = V_out if in_normalised_code_value else full_to_legal(V_out, bit_depth)

196

197 cut2 = constants.cut2

198 b = constants.b

199 c = constants.c

200 d = constants.d

201

202 L_in = np.where(

203 V_out < cut2,

204 (V_out - 0.125) / 5.6,

205 10 ** ((V_out - d) / c) - b,

206 )

207

208 if not out_reflection:

209 L_in = L_in / 0.9

210

211 return as_float(from_range_1(L_in))