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

52 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2025-11-16 22:49 +1300

1""" 

2Fujifilm F-Log Log Encoding 

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

4 

5Define 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 

12References 

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 

20from __future__ import annotations 

21 

22import numpy as np 

23 

24from colour.hints import ( # noqa: TC001 

25 Domain1, 

26 Range1, 

27) 

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

29from 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 

47CONSTANTS_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 

59CONSTANTS_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 

72def 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 

159def 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 

239def 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 

308def 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 )