Coverage for models/rgb/transfer_functions/fujifilm_f_log.py: 62%

1"""

2 Fujifilm F-Log Log Encoding

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

4

5 Define the *Fujifilm F-Log* log encoding.

6

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

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

9- :func:`colour.models.log_encoding_FLog2`

10- :func:`colour.models.log_decoding_FLog2`

11

12 References

13----------

14- :cite:`Fujifilm2022` : Fujifilm. (2022). F-Log Data Sheet Ver.1.1 (pp.

15 1-4). https://dl.fujifilm-x.com/support/lut/F-Log_DataSheet_E_Ver.1.1.pdf

16- :cite:`Fujifilm2022a` : Fujifilm. (2022). F-Log2 Data Sheet Ver.1.0 (pp.

17 1-4). https://dl.fujifilm-x.com/support/lut/F-Log2_DataSheet_E_Ver.1.0.pdf

18"""

19

20 from __future__ import annotations

21

22 import numpy as np

23

24 from colour.hints import ( # noqa: TC001

25 Domain1,

26 Range1,

27)

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

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

30

31 __author__ = "Colour Developers"

32 __copyright__ = "Copyright 2013 Colour Developers"

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

34 __maintainer__ = "Colour Developers"

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

36 __status__ = "Production"

37

38 __all__ = [

39 "CONSTANTS_FLOG",

40 "CONSTANTS_FLOG2",

41 "log_encoding_FLog",

42 "log_decoding_FLog",

43 "log_encoding_FLog2",

44 "log_decoding_FLog2",

45]

46

47 CONSTANTS_FLOG: Structure = Structure(

48 cut1=0.00089,

49 cut2=0.100537775223865,

50 a=0.555556,

51 b=0.009468,

52 c=0.344676,

53 d=0.790453,

54 e=8.735631,

55 f=0.092864,

56)

57"""*Fujifilm F-Log* constants."""

58

59 CONSTANTS_FLOG2: Structure = Structure(

60 cut1=0.000889,

61 cut2=0.100686685370811,

62 a=5.555556,

63 b=0.064829,

64 c=0.245281,

65 d=0.384316,

66 e=8.799461,

67 f=0.092864,

68)

69"""*Fujifilm F-Log2* colourspace constants."""

70

71

72 def log_encoding_FLog(

73 in_r: Domain1,

74 bit_depth: int = 10,

75 out_normalised_code_value: bool = True,

76 in_reflection: bool = True,

77 constants: Structure | None = None,

78) -> Range1:

79 """

80 Apply the *Fujifilm F-Log* log encoding opto-electronic transfer function (OETF).

81

82 Parameters

83 ----------

84 in_r

85 Linear reflection data :math:`in`.

86 bit_depth

87 Bit-depth used for conversion.

88 out_normalised_code_value

89 Whether the *Fujifilm F-Log* non-linear data :math:`out` is encoded as

90 normalised code values.

91 in_reflection

92 Whether the light level :math:`in` to a camera is reflection.

93 constants

94 *Fujifilm F-Log* constants.

95

96 Returns

97 -------

98 :class:`numpy.ndarray`

99 *Fujifilm F-Log* non-linear encoded data :math:`out`.

100

101 Notes

102 -----

103 +------------+-----------------------+---------------+

104 | **Domain** | **Scale - Reference** | **Scale - 1** |

105 +============+=======================+===============+

106 | ``in_r`` | 1 | 1 |

107 +------------+-----------------------+---------------+

108

109 +------------+-----------------------+---------------+

110 | **Range** | **Scale - Reference** | **Scale - 1** |

111 +============+=======================+===============+

112 | ``out_r`` | 1 | 1 |

113 +------------+-----------------------+---------------+

114

115 References

116 ----------

117 :cite:`Fujifilm2022`

118

119 Examples

120 --------

121 >>> log_encoding_FLog(0.18) # doctest: +ELLIPSIS

122 0.4593184...

123

124 The values of *2-2. F-Log Code Value* table in :cite:`Fujifilm2022`

125 are obtained as follows:

126

127 >>> x = np.array([0, 18, 90]) / 100

128 >>> np.around(log_encoding_FLog(x, 10, False) * 100, 1)

129 array([ 3.5, 46.3, 73.2])

130 >>> np.around(log_encoding_FLog(x) * (2**10 - 1)).astype(np.int_)

131 array([ 95, 470, 705])

132 """

133

134 in_r = to_domain_1(in_r)

135 constants = optional(constants, CONSTANTS_FLOG)

136

137 if not in_reflection:

138 in_r = in_r * 0.9

139

140 cut1 = constants.cut1

141 a = constants.a

142 b = constants.b

143 c = constants.c

144 d = constants.d

145 e = constants.e

146 f = constants.f

147

148 out_r = np.where(

149 in_r < cut1,

150 e * in_r + f,

151 c * np.log10(a * in_r + b) + d,

152 )

153

154 out_r_cv = out_r if out_normalised_code_value else legal_to_full(out_r, bit_depth)

155

156 return as_float(from_range_1(out_r_cv))

157

158

159 def log_decoding_FLog(

160 out_r: Domain1,

161 bit_depth: int = 10,

162 in_normalised_code_value: bool = True,

163 out_reflection: bool = True,

164 constants: Structure | None = None,

165) -> Range1:

166 """

167 Apply the *Fujifilm F-Log* log decoding inverse opto-electronic transfer

168

169 function (OETF).

170

171 Parameters

172 ----------

173 out_r

174 *Fujifilm F-Log* non-linear encoded data :math:`out`.

175 bit_depth

176 Bit-depth used for conversion.

177 in_normalised_code_value

178 Whether the *Fujifilm F-Log* non-linear data :math:`out` is encoded as

179 normalised code values.

180 out_reflection

181 Whether the light level :math:`in` to a camera is reflection.

182 constants

183 *Fujifilm F-Log* constants.

184

185 Returns

186 -------

187 :class:`numpy.ndarray`

188 Linear reflection data :math:`in`.

189

190 Notes

191 -----

192 +------------+-----------------------+---------------+

193 | **Domain** | **Scale - Reference** | **Scale - 1** |

194 +============+=======================+===============+

195 | ``out_r`` | 1 | 1 |

196 +------------+-----------------------+---------------+

197

198 +------------+-----------------------+---------------+

199 | **Range** | **Scale - Reference** | **Scale - 1** |

200 +============+=======================+===============+

201 | ``in_r`` | 1 | 1 |

202 +------------+-----------------------+---------------+

203

204 References

205 ----------

206 :cite:`Fujifilm2022`

207

208 Examples

209 --------

210 >>> log_decoding_FLog(0.45931845866162124) # doctest: +ELLIPSIS

211 0.1800000...

212 """

213

214 out_r = to_domain_1(out_r)

215 constants = optional(constants, CONSTANTS_FLOG)

216

217 out_r = out_r if in_normalised_code_value else full_to_legal(out_r, bit_depth)

218

219 cut2 = constants.cut2

220 a = constants.a

221 b = constants.b

222 c = constants.c

223 d = constants.d

224 e = constants.e

225 f = constants.f

226

227 in_r = np.where(

228 out_r < cut2,

229 (out_r - f) / e,

230 (10 ** ((out_r - d) / c)) / a - b / a,

231 )

232

233 if not out_reflection:

234 in_r = in_r / 0.9

235

236 return as_float(from_range_1(in_r))

237

238

239 def log_encoding_FLog2(

240 in_r: Domain1,

241 bit_depth: int = 10,

242 out_normalised_code_value: bool = True,

243 in_reflection: bool = True,

244 constants: Structure | None = None,

245) -> Range1:

246 """

247 Apply the *Fujifilm F-Log2* log encoding opto-electronic transfer function (OETF).

248

249 Parameters

250 ----------

251 in_r

252 Linear reflection data :math:`in`.

253 bit_depth

254 Bit-depth used for conversion.

255 out_normalised_code_value

256 Whether the *Fujifilm F-Log2* non-linear data :math:`out` is encoded as

257 normalised code values.

258 in_reflection

259 Whether the light level :math:`in` to a camera is reflection.

260 constants

261 *Fujifilm F-Log2* constants.

262

263 Returns

264 -------

265 :class:`numpy.floating` or :class:`numpy.ndarray`

266 *Fujifilm F-Log2* non-linear encoded data :math:`out`.

267

268 Notes

269 -----

270 +------------+-----------------------+---------------+

271 | **Domain** | **Scale - Reference** | **Scale - 1** |

272 +============+=======================+===============+

273 | ``in_r`` | 1 | 1 |

274 +------------+-----------------------+---------------+

275

276 +------------+-----------------------+---------------+

277 | **Range** | **Scale - Reference** | **Scale - 1** |

278 +============+=======================+===============+

279 | ``out_r`` | 1 | 1 |

280 +------------+-----------------------+---------------+

281

282 References

283 ----------

284 :cite:`Fujifilm2022a`

285

286 Examples

287 --------

288 >>> log_encoding_FLog2(0.18) # doctest: +ELLIPSIS

289 0.3910072...

290

291 The values of *2-2. F-Log2 Code Value* table in

292 :cite:`Fujifilm2022a` are obtained as follows:

293

294 >>> x = np.array([0, 18, 90]) / 100

295 >>> np.around(log_encoding_FLog2(x, 10, False) * 100, 1)

296 array([ 3.5, 38.4, 57.8])

297 >>> np.around(log_encoding_FLog2(x) * (2**10 - 1)).astype(np.int_)

298 array([ 95, 400, 570])

299 """

300

301 constants = optional(constants, CONSTANTS_FLOG2)

302

303 return log_encoding_FLog(

304 in_r, bit_depth, out_normalised_code_value, in_reflection, constants

305 )

306

307

308 def log_decoding_FLog2(

309 out_r: Domain1,

310 bit_depth: int = 10,

311 in_normalised_code_value: bool = True,

312 out_reflection: bool = True,

313 constants: Structure | None = None,

314) -> Range1:

315 """

316 Apply the *Fujifilm F-Log2* log decoding inverse opto-electronic transfer

317 function (OETF).

318

319 Parameters

320 ----------

321 out_r

322 *Fujifilm F-Log2* non-linear encoded data :math:`out`.

323 bit_depth

324 Bit-depth used for conversion.

325 in_normalised_code_value

326 Whether the *Fujifilm F-Log2* non-linear data :math:`out` is encoded as

327 normalised code values.

328 out_reflection

329 Whether the light level :math:`in` to a camera is reflection.

330 constants

331 *Fujifilm F-Log2* constants.

332

333 Returns

334 -------

335 :class:`numpy.floating` or :class:`numpy.ndarray`

336 Linear reflection data :math:`in`.

337

338 Notes

339 -----

340 +------------+-----------------------+---------------+

341 | **Domain** | **Scale - Reference** | **Scale - 1** |

342 +============+=======================+===============+

343 | ``out_r`` | 1 | 1 |

344 +------------+-----------------------+---------------+

345

346 +------------+-----------------------+---------------+

347 | **Range** | **Scale - Reference** | **Scale - 1** |

348 +============+=======================+===============+

349 | ``in_r`` | 1 | 1 |

350 +------------+-----------------------+---------------+

351

352 References

353 ----------

354 :cite:`Fujifilm2022a`

355

356 Examples

357 --------

358 >>> log_decoding_FLog2(0.39100724189123004) # doctest: +ELLIPSIS

359 0.1799999...

360 """

361

362 constants = optional(constants, CONSTANTS_FLOG2)

363

364 return log_decoding_FLog(

365 out_r, bit_depth, in_normalised_code_value, out_reflection, constants

366 )