Coverage for models/rgb/transfer_functions/itur_bt_2100.py: 66%

160 statements  

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

1""" 

2Recommendation ITU-R BT.2100 

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

4 

5Define the *Recommendation ITU-R BT.2100* opto-electrical transfer functions 

6(OETF), opto-optical transfer functions (OOTF / OOCF) and electro-optical 

7transfer functions (EOTF) and their inverse. 

8 

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

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

11- :func:`colour.models.eotf_BT2100_PQ` 

12- :func:`colour.models.eotf_inverse_BT2100_PQ` 

13- :func:`colour.models.ootf_BT2100_PQ` 

14- :func:`colour.models.ootf_inverse_BT2100_PQ` 

15- :func:`colour.models.oetf_BT2100_HLG` 

16- :func:`colour.models.oetf_inverse_BT2100_HLG` 

17- :func:`colour.models.eotf_BT2100_HLG_1` 

18- :func:`colour.models.eotf_BT2100_HLG_2` 

19- :attr:`colour.models.BT2100_HLG_EOTF_METHODS` 

20- :func:`colour.models.eotf_BT2100_HLG` 

21- :func:`colour.models.eotf_inverse_BT2100_HLG_1` 

22- :func:`colour.models.eotf_inverse_BT2100_HLG_2` 

23- :attr:`colour.models.BT2100_HLG_EOTF_INVERSE_METHODS` 

24- :func:`colour.models.eotf_inverse_BT2100_HLG` 

25- :func:`colour.models.ootf_BT2100_HLG` 

26- :func:`colour.models.ootf_inverse_BT2100_HLG` 

27- :func:`colour.models.ootf_BT2100_HLG_1` 

28- :func:`colour.models.ootf_BT2100_HLG_2` 

29- :attr:`colour.models.BT2100_HLG_OOTF_METHODS` 

30- :func:`colour.models.ootf_BT2100_HLG` 

31- :func:`colour.models.ootf_inverse_BT2100_HLG_1` 

32- :func:`colour.models.ootf_inverse_BT2100_HLG_2` 

33- :attr:`colour.models.BT2100_HLG_OOTF_INVERSE_METHODS` 

34- :func:`colour.models.ootf_inverse_BT2100_HLG` 

35 

36References 

37---------- 

38- :cite:`Borer2017a` : Borer, T. (2017). Private Discussion with Mansencal, 

39 T. and Shaw, N. 

40- :cite:`InternationalTelecommunicationUnion2017` : International 

41 Telecommunication Union. (2017). Recommendation ITU-R BT.2100-1 - Image 

42 parameter values for high dynamic range television for use in production 

43 and international programme exchange. 

44 https://www.itu.int/dms_pubrec/itu-r/rec/bt/\ 

45R-REC-BT.2100-1-201706-I!!PDF-E.pdf 

46- :cite:`InternationalTelecommunicationUnion2018` : International 

47 Telecommunication Union. (2018). Recommendation ITU-R BT.2100-2 - Image 

48 parameter values for high dynamic range television for use in production 

49 and international programme exchange. 

50 https://www.itu.int/dms_pubrec/itu-r/rec/bt/\ 

51R-REC-BT.2100-2-201807-I!!PDF-E.pdf 

52""" 

53 

54from __future__ import annotations 

55 

56import typing 

57 

58import numpy as np 

59 

60from colour.algebra import spow 

61 

62if typing.TYPE_CHECKING: 

63 from colour.hints import Literal 

64 

65from colour.hints import ( # noqa: TC001 

66 ArrayLike, 

67 Domain1, 

68 NDArrayFloat, 

69 Range1, 

70) 

71from colour.models.rgb.transfer_functions import ( 

72 eotf_BT1886, 

73 eotf_inverse_BT1886, 

74 eotf_inverse_ST2084, 

75 eotf_ST2084, 

76 oetf_ARIBSTDB67, 

77 oetf_BT709, 

78 oetf_inverse_ARIBSTDB67, 

79 oetf_inverse_BT709, 

80) 

81from colour.models.rgb.transfer_functions.arib_std_b67 import CONSTANTS_ARIBSTDB67 

82from colour.utilities import ( 

83 CanonicalMapping, 

84 Structure, 

85 as_float, 

86 as_float_array, 

87 as_float_scalar, 

88 domain_range_scale, 

89 filter_kwargs, 

90 from_range_1, 

91 optional, 

92 to_domain_1, 

93 tsplit, 

94 tstack, 

95 usage_warning, 

96 validate_method, 

97) 

98 

99__author__ = "Colour Developers" 

100__copyright__ = "Copyright 2013 Colour Developers" 

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

102__maintainer__ = "Colour Developers" 

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

104__status__ = "Production" 

105 

106__all__ = [ 

107 "oetf_BT2100_PQ", 

108 "oetf_inverse_BT2100_PQ", 

109 "eotf_BT2100_PQ", 

110 "eotf_inverse_BT2100_PQ", 

111 "ootf_BT2100_PQ", 

112 "ootf_inverse_BT2100_PQ", 

113 "WEIGHTS_BT2100_HLG", 

114 "CONSTANTS_BT2100_HLG", 

115 "gamma_function_BT2100_HLG", 

116 "oetf_BT2100_HLG", 

117 "oetf_inverse_BT2100_HLG", 

118 "black_level_lift_BT2100_HLG", 

119 "eotf_BT2100_HLG_1", 

120 "eotf_BT2100_HLG_2", 

121 "BT2100_HLG_EOTF_METHODS", 

122 "eotf_BT2100_HLG", 

123 "eotf_inverse_BT2100_HLG_1", 

124 "eotf_inverse_BT2100_HLG_2", 

125 "BT2100_HLG_EOTF_INVERSE_METHODS", 

126 "eotf_inverse_BT2100_HLG", 

127 "ootf_BT2100_HLG_1", 

128 "ootf_BT2100_HLG_2", 

129 "BT2100_HLG_OOTF_METHODS", 

130 "ootf_BT2100_HLG", 

131 "ootf_inverse_BT2100_HLG_1", 

132 "ootf_inverse_BT2100_HLG_2", 

133 "BT2100_HLG_OOTF_INVERSE_METHODS", 

134 "ootf_inverse_BT2100_HLG", 

135] 

136 

137 

138def oetf_BT2100_PQ(E: ArrayLike) -> NDArrayFloat: 

139 """ 

140 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* opto-electronic 

141 transfer function (OETF). 

142 

143 Parameters 

144 ---------- 

145 E 

146 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

147 signal determined by scene light and scaled by camera exposure. 

148 

149 Returns 

150 ------- 

151 :class:`numpy.ndarray` 

152 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

153 

154 Notes 

155 ----- 

156 +------------+-----------------------+---------------+ 

157 | **Domain** | **Scale - Reference** | **Scale - 1** | 

158 +============+=======================+===============+ 

159 | ``E`` | ``UN`` | ``UN`` | 

160 +------------+-----------------------+---------------+ 

161 

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

163 | **Range** | **Scale - Reference** | **Scale - 1** | 

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

165 | ``E_p`` | ``UN`` | ``UN`` | 

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

167 

168 References 

169 ---------- 

170 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

171 

172 Examples 

173 -------- 

174 >>> oetf_BT2100_PQ(0.1) # doctest: +ELLIPSIS 

175 0.7247698... 

176 """ 

177 

178 return eotf_inverse_ST2084(ootf_BT2100_PQ(E), 10000) 

179 

180 

181def oetf_inverse_BT2100_PQ(E_p: ArrayLike) -> NDArrayFloat: 

182 """ 

183 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* inverse 

184 opto-electrical transfer function (OETF). 

185 

186 Parameters 

187 ---------- 

188 E_p 

189 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

190 

191 Returns 

192 ------- 

193 :class:`numpy.ndarray` 

194 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

195 signal determined by scene light and scaled by camera exposure. 

196 

197 Notes 

198 ----- 

199 +------------+-----------------------+---------------+ 

200 | **Domain** | **Scale - Reference** | **Scale - 1** | 

201 +============+=======================+===============+ 

202 | ``E_p`` | ``UN`` | ``UN`` | 

203 +------------+-----------------------+---------------+ 

204 

205 +------------+-----------------------+---------------+ 

206 | **Range** | **Scale - Reference** | **Scale - 1** | 

207 +============+=======================+===============+ 

208 | ``E`` | ``UN`` | ``UN`` | 

209 +------------+-----------------------+---------------+ 

210 

211 References 

212 ---------- 

213 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

214 

215 Examples 

216 -------- 

217 >>> oetf_inverse_BT2100_PQ(0.724769816665726) # doctest: +ELLIPSIS 

218 0.0999999... 

219 """ 

220 

221 return ootf_inverse_BT2100_PQ(eotf_ST2084(E_p, 10000)) 

222 

223 

224def eotf_BT2100_PQ(E_p: ArrayLike) -> NDArrayFloat: 

225 """ 

226 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* electro-optical 

227 transfer function (EOTF). 

228 

229 Parameters 

230 ---------- 

231 E_p 

232 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

233 

234 Returns 

235 ------- 

236 :class:`numpy.ndarray` 

237 Luminance :math:`F_D` of a displayed linear component 

238 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

239 :math:`cd/m^2`. 

240 

241 Notes 

242 ----- 

243 +------------+-----------------------+---------------+ 

244 | **Domain** | **Scale - Reference** | **Scale - 1** | 

245 +============+=======================+===============+ 

246 | ``E_p`` | ``UN`` | ``UN`` | 

247 +------------+-----------------------+---------------+ 

248 

249 +------------+-----------------------+---------------+ 

250 | **Range** | **Scale - Reference** | **Scale - 1** | 

251 +============+=======================+===============+ 

252 | ``F_D`` | ``UN`` | ``UN`` | 

253 +------------+-----------------------+---------------+ 

254 

255 References 

256 ---------- 

257 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

258 

259 Examples 

260 -------- 

261 >>> eotf_BT2100_PQ(0.724769816665726) # doctest: +ELLIPSIS 

262 779.9883608... 

263 """ 

264 

265 return eotf_ST2084(E_p, 10000) 

266 

267 

268def eotf_inverse_BT2100_PQ(F_D: ArrayLike) -> NDArrayFloat: 

269 """ 

270 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* inverse 

271 electro-optical transfer function (EOTF). 

272 

273 Parameters 

274 ---------- 

275 F_D 

276 Luminance :math:`F_D` of a displayed linear component 

277 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

278 :math:`cd/m^2`. 

279 

280 Returns 

281 ------- 

282 :class:`numpy.ndarray` 

283 :math:`E'` denotes a non-linear colour value :math:`\\{R', G', B'\\}` 

284 or :math:`\\{L', M', S'\\}`. 

285 

286 Notes 

287 ----- 

288 +------------+-----------------------+---------------+ 

289 | **Domain** | **Scale - Reference** | **Scale - 1** | 

290 +============+=======================+===============+ 

291 | ``F_D`` | ``UN`` | ``UN`` | 

292 +------------+-----------------------+---------------+ 

293 

294 +------------+-----------------------+---------------+ 

295 | **Range** | **Scale - Reference** | **Scale - 1** | 

296 +============+=======================+===============+ 

297 | ``E_p`` | ``UN`` | ``UN`` | 

298 +------------+-----------------------+---------------+ 

299 

300 References 

301 ---------- 

302 :cite:`Borer2017a`, 

303 :cite:`InternationalTelecommunicationUnion2017` 

304 

305 Examples 

306 -------- 

307 >>> eotf_inverse_BT2100_PQ(779.988360834085370) # doctest: +ELLIPSIS 

308 0.7247698... 

309 """ 

310 

311 return eotf_inverse_ST2084(F_D, 10000) 

312 

313 

314def ootf_BT2100_PQ(E: ArrayLike) -> NDArrayFloat: 

315 """ 

316 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* opto-optical 

317 transfer function (OOTF). 

318 

319 Parameters 

320 ---------- 

321 E 

322 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

323 signal determined by scene light and scaled by camera exposure. 

324 

325 Returns 

326 ------- 

327 :class:`numpy.ndarray` 

328 Luminance :math:`F_D` of a displayed linear component 

329 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

330 :math:`cd/m^2`. 

331 

332 Notes 

333 ----- 

334 +------------+-----------------------+---------------+ 

335 | **Domain** | **Scale - Reference** | **Scale - 1** | 

336 +============+=======================+===============+ 

337 | ``E`` | ``UN`` | ``UN`` | 

338 +------------+-----------------------+---------------+ 

339 

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

341 | **Range** | **Scale - Reference** | **Scale - 1** | 

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

343 | ``F_D`` | ``UN`` | ``UN`` | 

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

345 

346 References 

347 ---------- 

348 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

349 

350 Examples 

351 -------- 

352 >>> ootf_BT2100_PQ(0.1) # doctest: +ELLIPSIS 

353 779.9883608... 

354 """ 

355 

356 E = as_float_array(E) 

357 

358 with domain_range_scale("ignore"): 

359 return 100 * eotf_BT1886(oetf_BT709(59.5208 * E)) 

360 

361 

362def ootf_inverse_BT2100_PQ(F_D: ArrayLike) -> NDArrayFloat: 

363 """ 

364 Apply the *Recommendation ITU-R BT.2100* *Reference PQ* inverse 

365 opto-optical transfer function (OOTF). 

366 

367 Parameters 

368 ---------- 

369 F_D 

370 Luminance :math:`F_D` of a displayed linear component 

371 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

372 :math:`cd/m^2`. 

373 

374 Returns 

375 ------- 

376 :class:`numpy.ndarray` 

377 :math:`E = \\{R_S, G_S, B_S; Y_S; or I_S\\}` denotes the signal 

378 determined by scene light and scaled by camera exposure. 

379 

380 Notes 

381 ----- 

382 +------------+-----------------------+---------------+ 

383 | **Domain** | **Scale - Reference** | **Scale - 1** | 

384 +============+=======================+===============+ 

385 | ``F_D`` | ``UN`` | ``UN`` | 

386 +------------+-----------------------+---------------+ 

387 

388 +------------+-----------------------+---------------+ 

389 | **Range** | **Scale - Reference** | **Scale - 1** | 

390 +============+=======================+===============+ 

391 | ``E`` | ``UN`` | ``UN`` | 

392 +------------+-----------------------+---------------+ 

393 

394 References 

395 ---------- 

396 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

397 

398 Examples 

399 -------- 

400 >>> ootf_inverse_BT2100_PQ(779.988360834115840) # doctest: +ELLIPSIS 

401 0.1000000... 

402 """ 

403 

404 F_D = as_float_array(F_D) 

405 

406 with domain_range_scale("ignore"): 

407 return oetf_inverse_BT709(eotf_inverse_BT1886(F_D / 100)) / 59.5208 

408 

409 

410WEIGHTS_BT2100_HLG: NDArrayFloat = np.array([0.2627, 0.6780, 0.0593]) 

411"""Luminance weights for *Recommendation ITU-R BT.2100* *Reference HLG*.""" 

412 

413CONSTANTS_BT2100_HLG: Structure = Structure( 

414 a=CONSTANTS_ARIBSTDB67.a, 

415 b=1 - 4 * CONSTANTS_ARIBSTDB67.a, 

416 c=0.5 - CONSTANTS_ARIBSTDB67.a * np.log(4 * CONSTANTS_ARIBSTDB67.a), 

417) 

418""" 

419*Recommendation ITU-R BT.2100* *Reference HLG* constants expressed in their 

420analytical form in contrast to the *ARIB STD-B67 (Hybrid Log-Gamma)* numerical 

421reference. 

422 

423References 

424---------- 

425:cite:`InternationalTelecommunicationUnion2017` 

426""" 

427 

428 

429def gamma_function_BT2100_HLG(L_W: float = 1000) -> float: 

430 """ 

431 Compute the *Reference HLG* system gamma value for the specified display 

432 nominal peak luminance. 

433 

434 Parameters 

435 ---------- 

436 L_W 

437 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

438 achromatic pixels. 

439 

440 Returns 

441 ------- 

442 :class:`float` 

443 *Reference HLG* system gamma value. 

444 

445 Examples 

446 -------- 

447 >>> gamma_function_BT2100_HLG() 

448 1.2 

449 >>> gamma_function_BT2100_HLG(2000) # doctest: +ELLIPSIS 

450 1.3264325... 

451 >>> gamma_function_BT2100_HLG(4000) # doctest: +ELLIPSIS 

452 1.4528651... 

453 """ 

454 

455 gamma = 1.2 + 0.42 * np.log10(L_W / 1000) 

456 

457 return as_float_scalar(gamma) 

458 

459 

460def oetf_BT2100_HLG(E: Domain1, constants: Structure | None = None) -> Range1: 

461 """ 

462 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* opto-electrical 

463 transfer function (OETF). 

464 

465 The OETF maps relative scene linear light into the non-linear *HLG* signal 

466 

467 Parameters 

468 ---------- 

469 E 

470 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

471 signal determined by scene light and scaled by camera exposure. 

472 constants 

473 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

474 

475 Returns 

476 ------- 

477 :class:`numpy.ndarray` 

478 :math:`E'` is the resulting non-linear signal :math:`\\{R', G', B'\\}`. 

479 

480 Notes 

481 ----- 

482 +------------+-----------------------+---------------+ 

483 | **Domain** | **Scale - Reference** | **Scale - 1** | 

484 +============+=======================+===============+ 

485 | ``E`` | 1 | 1 | 

486 +------------+-----------------------+---------------+ 

487 

488 +------------+-----------------------+---------------+ 

489 | **Range** | **Scale - Reference** | **Scale - 1** | 

490 +============+=======================+===============+ 

491 | ``E_p`` | 1 | 1 | 

492 +------------+-----------------------+---------------+ 

493 

494 References 

495 ---------- 

496 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

497 

498 Examples 

499 -------- 

500 >>> oetf_BT2100_HLG(0.18 / 12) # doctest: +ELLIPSIS 

501 0.2121320... 

502 """ 

503 

504 E = as_float_array(E) 

505 constants = optional(constants, CONSTANTS_BT2100_HLG) 

506 

507 return oetf_ARIBSTDB67(12 * E, constants=constants) 

508 

509 

510def oetf_inverse_BT2100_HLG(E_p: Domain1, constants: Structure | None = None) -> Range1: 

511 """ 

512 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

513 opto-electrical transfer function (OETF). 

514 

515 Parameters 

516 ---------- 

517 E_p 

518 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

519 constants 

520 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

521 

522 Returns 

523 ------- 

524 :class:`numpy.ndarray` 

525 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

526 signal determined by scene light and scaled by camera exposure. 

527 

528 Notes 

529 ----- 

530 +------------+-----------------------+---------------+ 

531 | **Domain** | **Scale - Reference** | **Scale - 1** | 

532 +============+=======================+===============+ 

533 | ``E_p`` | 1 | 1 | 

534 +------------+-----------------------+---------------+ 

535 

536 +------------+-----------------------+---------------+ 

537 | **Range** | **Scale - Reference** | **Scale - 1** | 

538 +============+=======================+===============+ 

539 | ``E`` | 1 | 1 | 

540 +------------+-----------------------+---------------+ 

541 

542 References 

543 ---------- 

544 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

545 

546 Examples 

547 -------- 

548 >>> oetf_inverse_BT2100_HLG(0.212132034355964) # doctest: +ELLIPSIS 

549 0.0149999... 

550 """ 

551 

552 constants = optional(constants, CONSTANTS_BT2100_HLG) 

553 

554 return oetf_inverse_ARIBSTDB67(E_p, constants=constants) / 12 

555 

556 

557def black_level_lift_BT2100_HLG( 

558 L_B: float = 0, L_W: float = 1000, gamma: float | None = None 

559) -> float: 

560 """ 

561 Compute the *Reference HLG* black level lift :math:`\\beta` for the 

562 specified display luminance for black, nominal peak luminance, and system 

563 gamma value. 

564 

565 Parameters 

566 ---------- 

567 L_B 

568 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

569 L_W 

570 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

571 achromatic pixels. 

572 gamma 

573 System gamma value, defaults to 1.2 at the nominal display peak 

574 luminance of :math:`1000 cd/m^2`. 

575 

576 Returns 

577 ------- 

578 :class:`float` 

579 *Reference HLG* black level lift :math:`\\beta`. 

580 

581 Examples 

582 -------- 

583 >>> black_level_lift_BT2100_HLG() 

584 0.0 

585 >>> black_level_lift_BT2100_HLG(0.01) # doctest: +ELLIPSIS 

586 0.0142964... 

587 >>> black_level_lift_BT2100_HLG(0.001, 2000) # doctest: +ELLIPSIS 

588 0.0073009... 

589 >>> black_level_lift_BT2100_HLG(0.01, gamma=1.4) # doctest: +ELLIPSIS 

590 0.0283691... 

591 """ 

592 

593 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W)) 

594 

595 beta = np.sqrt(3 * spow((L_B / L_W), 1 / gamma)) 

596 

597 return as_float_scalar(beta) 

598 

599 

600def eotf_BT2100_HLG_1( 

601 E_p: Domain1, 

602 L_B: float = 0, 

603 L_W: float = 1000, 

604 gamma: float | None = None, 

605 constants: Structure | None = None, 

606) -> Range1: 

607 """ 

608 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* electro-optical 

609 transfer function (EOTF) as specified in *ITU-R BT.2100-1*. 

610 

611 Parameters 

612 ---------- 

613 E_p 

614 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

615 L_B 

616 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

617 L_W 

618 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

619 achromatic pixels. 

620 gamma 

621 System gamma value, defaults to 1.2 at the nominal display peak 

622 luminance of :math:`1000 cd/m^2`. 

623 constants 

624 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

625 

626 Returns 

627 ------- 

628 :class:`numpy.ndarray` 

629 Luminance :math:`F_D` of a displayed linear component 

630 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

631 :math:`cd/m^2`. 

632 

633 Notes 

634 ----- 

635 +------------+-----------------------+---------------+ 

636 | **Domain** | **Scale - Reference** | **Scale - 1** | 

637 +============+=======================+===============+ 

638 | ``E_p`` | 1 | 1 | 

639 +------------+-----------------------+---------------+ 

640 

641 +------------+-----------------------+---------------+ 

642 | **Range** | **Scale - Reference** | **Scale - 1** | 

643 +============+=======================+===============+ 

644 | ``F_D`` | 1 | 1 | 

645 +------------+-----------------------+---------------+ 

646 

647 References 

648 ---------- 

649 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

650 

651 Examples 

652 -------- 

653 >>> eotf_BT2100_HLG_1(0.212132034355964) # doctest: +ELLIPSIS 

654 6.4760398... 

655 >>> eotf_BT2100_HLG_1(0.212132034355964, 0.01) # doctest: +ELLIPSIS 

656 6.4859750... 

657 """ 

658 

659 constants = optional(constants, CONSTANTS_BT2100_HLG) 

660 

661 return ootf_BT2100_HLG_1( 

662 oetf_inverse_ARIBSTDB67(E_p, constants=constants) / 12, L_B, L_W, gamma 

663 ) 

664 

665 

666def eotf_BT2100_HLG_2( 

667 E_p: Domain1, 

668 L_B: float = 0, 

669 L_W: float = 1000, 

670 gamma: float | None = None, 

671 constants: Structure | None = None, 

672) -> Range1: 

673 """ 

674 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* electro-optical 

675 transfer function (EOTF) as specified in *ITU-R BT.2100-2* with 

676 modified black level behaviour. 

677 

678 Parameters 

679 ---------- 

680 E_p 

681 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

682 L_B 

683 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

684 L_W 

685 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

686 achromatic pixels. 

687 gamma 

688 System gamma value, defaults to 1.2 at the nominal display peak 

689 luminance of :math:`1000 cd/m^2`. 

690 constants 

691 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

692 

693 Returns 

694 ------- 

695 :class:`numpy.ndarray` 

696 Luminance :math:`F_D` of a displayed linear component 

697 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

698 :math:`cd/m^2`. 

699 

700 Notes 

701 ----- 

702 +------------+-----------------------+---------------+ 

703 | **Domain** | **Scale - Reference** | **Scale - 1** | 

704 +============+=======================+===============+ 

705 | ``E_p`` | 1 | 1 | 

706 +------------+-----------------------+---------------+ 

707 

708 +------------+-----------------------+---------------+ 

709 | **Range** | **Scale - Reference** | **Scale - 1** | 

710 +============+=======================+===============+ 

711 | ``F_D`` | 1 | 1 | 

712 +------------+-----------------------+---------------+ 

713 

714 References 

715 ---------- 

716 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2018` 

717 

718 Examples 

719 -------- 

720 >>> eotf_BT2100_HLG_2(0.212132034355964) # doctest: +ELLIPSIS 

721 6.4760398... 

722 >>> eotf_BT2100_HLG_2(0.212132034355964, 0.01) # doctest: +ELLIPSIS 

723 7.3321975... 

724 """ 

725 

726 E_p = as_float_array(E_p) 

727 constants = optional(constants, CONSTANTS_BT2100_HLG) 

728 

729 beta = black_level_lift_BT2100_HLG(L_B, L_W, gamma) 

730 

731 return ootf_BT2100_HLG_2( 

732 oetf_inverse_ARIBSTDB67((1 - beta) * E_p + beta, constants=constants) / 12, 

733 L_W, 

734 gamma, 

735 ) 

736 

737 

738BT2100_HLG_EOTF_METHODS: CanonicalMapping = CanonicalMapping( 

739 { 

740 "ITU-R BT.2100-1": eotf_BT2100_HLG_1, 

741 "ITU-R BT.2100-2": eotf_BT2100_HLG_2, 

742 } 

743) 

744BT2100_HLG_EOTF_METHODS.__doc__ = """ 

745Define supported *ITU-R BT.2100* *Reference HLG* electro-optical transfer 

746function (EOTF) methods. 

747 

748References 

749---------- 

750:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

751:cite:`InternationalTelecommunicationUnion2018` 

752""" 

753 

754 

755def eotf_BT2100_HLG( 

756 E_p: Domain1, 

757 L_B: float = 0, 

758 L_W: float = 1000, 

759 gamma: float | None = None, 

760 constants: Structure | None = None, 

761 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2", 

762) -> Range1: 

763 """ 

764 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* 

765 electro-optical transfer function (EOTF). 

766 

767 Parameters 

768 ---------- 

769 E_p 

770 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

771 L_B 

772 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

773 L_W 

774 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

775 achromatic pixels. 

776 gamma 

777 System gamma value, defaults to 1.2 at the nominal display peak 

778 luminance of :math:`1000 cd/m^2`. 

779 constants 

780 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

781 method 

782 Computation method. 

783 

784 Returns 

785 ------- 

786 :class:`numpy.ndarray` 

787 Luminance :math:`F_D` of a displayed linear component 

788 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

789 :math:`cd/m^2`. 

790 

791 Notes 

792 ----- 

793 +------------+-----------------------+---------------+ 

794 | **Domain** | **Scale - Reference** | **Scale - 1** | 

795 +============+=======================+===============+ 

796 | ``E_p`` | 1 | 1 | 

797 +------------+-----------------------+---------------+ 

798 

799 +------------+-----------------------+---------------+ 

800 | **Range** | **Scale - Reference** | **Scale - 1** | 

801 +============+=======================+===============+ 

802 | ``F_D`` | 1 | 1 | 

803 +------------+-----------------------+---------------+ 

804 

805 References 

806 ---------- 

807 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

808 :cite:`InternationalTelecommunicationUnion2018` 

809 

810 Examples 

811 -------- 

812 >>> eotf_BT2100_HLG(0.212132034355964) # doctest: +ELLIPSIS 

813 6.4760398... 

814 >>> eotf_BT2100_HLG(0.212132034355964, method="ITU-R BT.2100-1") 

815 ... # doctest: +ELLIPSIS 

816 6.4760398... 

817 >>> eotf_BT2100_HLG(0.212132034355964, 0.01) 

818 ... # doctest: +ELLIPSIS 

819 7.3321975... 

820 """ 

821 

822 constants = optional(constants, CONSTANTS_BT2100_HLG) 

823 method = validate_method(method, tuple(BT2100_HLG_EOTF_METHODS)) 

824 

825 return BT2100_HLG_EOTF_METHODS[method](E_p, L_B, L_W, gamma, constants) 

826 

827 

828def eotf_inverse_BT2100_HLG_1( 

829 F_D: Domain1, 

830 L_B: float = 0, 

831 L_W: float = 1000, 

832 gamma: float | None = None, 

833 constants: Structure | None = None, 

834) -> Range1: 

835 """ 

836 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

837 electro-optical transfer function (EOTF) as specified in 

838 *ITU-R BT.2100-1*. 

839 

840 Parameters 

841 ---------- 

842 F_D 

843 Luminance :math:`F_D` of a displayed linear component 

844 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

845 :math:`cd/m^2`. 

846 L_B 

847 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

848 L_W 

849 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

850 achromatic pixels. 

851 gamma 

852 System gamma value, defaults to 1.2 at the nominal display peak 

853 luminance of :math:`1000 cd/m^2`. 

854 constants 

855 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

856 

857 Returns 

858 ------- 

859 :class:`numpy.ndarray` 

860 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

861 

862 Notes 

863 ----- 

864 +------------+-----------------------+---------------+ 

865 | **Domain** | **Scale - Reference** | **Scale - 1** | 

866 +============+=======================+===============+ 

867 | ``F_D`` | 1 | 1 | 

868 +------------+-----------------------+---------------+ 

869 

870 +------------+-----------------------+---------------+ 

871 | **Range** | **Scale - Reference** | **Scale - 1** | 

872 +============+=======================+===============+ 

873 | ``E_p`` | 1 | 1 | 

874 +------------+-----------------------+---------------+ 

875 

876 References 

877 ---------- 

878 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

879 

880 Examples 

881 -------- 

882 >>> eotf_inverse_BT2100_HLG_1(6.476039825649814) # doctest: +ELLIPSIS 

883 0.2121320... 

884 >>> eotf_inverse_BT2100_HLG_1(6.485975065251558, 0.01) 

885 ... # doctest: +ELLIPSIS 

886 0.2121320... 

887 """ 

888 

889 constants = optional(constants, CONSTANTS_BT2100_HLG) 

890 

891 return oetf_ARIBSTDB67( 

892 ootf_inverse_BT2100_HLG_1(F_D, L_B, L_W, gamma) * 12, 

893 constants=constants, 

894 ) 

895 

896 

897def eotf_inverse_BT2100_HLG_2( 

898 F_D: Domain1, 

899 L_B: float = 0, 

900 L_W: float = 1000, 

901 gamma: float | None = None, 

902 constants: Structure | None = None, 

903) -> Range1: 

904 """ 

905 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

906 electro-optical transfer function (EOTF) as specified in *ITU-R BT.2100-2* 

907 with modified black level behaviour. 

908 

909 Parameters 

910 ---------- 

911 F_D 

912 Luminance :math:`F_D` of a displayed linear component 

913 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

914 :math:`cd/m^2`. 

915 L_B 

916 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

917 L_W 

918 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

919 achromatic pixels. 

920 gamma 

921 System gamma value, defaults to 1.2 at the nominal display peak 

922 luminance of :math:`1000 cd/m^2`. 

923 constants 

924 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

925 

926 Returns 

927 ------- 

928 :class:`numpy.ndarray` 

929 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

930 

931 Notes 

932 ----- 

933 +------------+-----------------------+---------------+ 

934 | **Domain** | **Scale - Reference** | **Scale - 1** | 

935 +============+=======================+===============+ 

936 | ``F_D`` | 1 | 1 | 

937 +------------+-----------------------+---------------+ 

938 

939 +------------+-----------------------+---------------+ 

940 | **Range** | **Scale - Reference** | **Scale - 1** | 

941 +============+=======================+===============+ 

942 | ``E_p`` | 1 | 1 | 

943 +------------+-----------------------+---------------+ 

944 

945 References 

946 ---------- 

947 :cite:`Borer2017a`, 

948 :cite:`InternationalTelecommunicationUnion2018` 

949 

950 Examples 

951 -------- 

952 >>> eotf_inverse_BT2100_HLG_2(6.476039825649814) # doctest: +ELLIPSIS 

953 0.2121320... 

954 >>> eotf_inverse_BT2100_HLG_2(7.332197528353875, 0.01) 

955 ... # doctest: +ELLIPSIS 

956 0.2121320... 

957 """ 

958 

959 constants = optional(constants, CONSTANTS_BT2100_HLG) 

960 

961 beta = black_level_lift_BT2100_HLG(L_B, L_W, gamma) 

962 

963 return ( 

964 oetf_ARIBSTDB67( 

965 ootf_inverse_BT2100_HLG_2(F_D, L_W, gamma) * 12, 

966 constants=constants, 

967 ) 

968 - beta 

969 ) / (1 - beta) 

970 

971 

972BT2100_HLG_EOTF_INVERSE_METHODS: CanonicalMapping = CanonicalMapping( 

973 { 

974 "ITU-R BT.2100-1": eotf_inverse_BT2100_HLG_1, 

975 "ITU-R BT.2100-2": eotf_inverse_BT2100_HLG_2, 

976 } 

977) 

978BT2100_HLG_EOTF_INVERSE_METHODS.__doc__ = """ 

979Define the supported *ITU-R BT.2100* *Reference HLG* inverse 

980electro-optical transfer function (EOTF) methods. 

981 

982References 

983---------- 

984:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

985:cite:`InternationalTelecommunicationUnion2018` 

986""" 

987 

988 

989def eotf_inverse_BT2100_HLG( 

990 F_D: Domain1, 

991 L_B: float = 0, 

992 L_W: float = 1000, 

993 gamma: float | None = None, 

994 constants: Structure | None = None, 

995 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2", 

996) -> Range1: 

997 """ 

998 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

999 electro-optical transfer function (EOTF). 

1000 

1001 Parameters 

1002 ---------- 

1003 F_D 

1004 Luminance :math:`F_D` of a displayed linear component 

1005 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1006 :math:`cd/m^2`. 

1007 L_B 

1008 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

1009 L_W 

1010 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

1011 achromatic pixels. 

1012 gamma 

1013 System gamma value, defaults to 1.2 at the nominal display peak 

1014 luminance of :math:`1000 cd/m^2`. 

1015 constants 

1016 *Recommendation ITU-R BT.2100* *Reference HLG* constants. 

1017 method 

1018 Computation method. 

1019 

1020 Returns 

1021 ------- 

1022 :class:`numpy.ndarray` 

1023 :math:`E'` denotes the non-linear signal :math:`\\{R', G', B'\\}`. 

1024 

1025 Notes 

1026 ----- 

1027 +------------+-----------------------+---------------+ 

1028 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1029 +============+=======================+===============+ 

1030 | ``F_D`` | 1 | 1 | 

1031 +------------+-----------------------+---------------+ 

1032 

1033 +------------+-----------------------+---------------+ 

1034 | **Range** | **Scale - Reference** | **Scale - 1** | 

1035 +============+=======================+===============+ 

1036 | ``E_p`` | 1 | 1 | 

1037 +------------+-----------------------+---------------+ 

1038 

1039 References 

1040 ---------- 

1041 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

1042 :cite:`InternationalTelecommunicationUnion2018` 

1043 

1044 Examples 

1045 -------- 

1046 >>> eotf_inverse_BT2100_HLG(6.476039825649814) # doctest: +ELLIPSIS 

1047 0.2121320... 

1048 >>> eotf_inverse_BT2100_HLG(6.476039825649814, method="ITU-R BT.2100-1") 

1049 ... # doctest: +ELLIPSIS 

1050 0.2121320... 

1051 >>> eotf_inverse_BT2100_HLG(7.332197528353875, 0.01) # doctest: +ELLIPSIS 

1052 0.2121320... 

1053 """ 

1054 

1055 constants = optional(constants, CONSTANTS_BT2100_HLG) 

1056 method = validate_method(method, tuple(BT2100_HLG_EOTF_INVERSE_METHODS)) 

1057 

1058 return BT2100_HLG_EOTF_INVERSE_METHODS[method](F_D, L_B, L_W, gamma, constants) 

1059 

1060 

1061def ootf_BT2100_HLG_1( 

1062 E: Domain1, 

1063 L_B: float = 0, 

1064 L_W: float = 1000, 

1065 gamma: float | None = None, 

1066) -> Range1: 

1067 """ 

1068 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* 

1069 

1070 opto-optical transfer function 

1071 (OOTF) as specified in *ITU-R BT.2100-1*. 

1072 

1073 The OOTF maps relative scene linear light to display linear light. 

1074 

1075 Parameters 

1076 ---------- 

1077 E 

1078 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

1079 signal determined by scene light and scaled by camera exposure. 

1080 L_B 

1081 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

1082 L_W 

1083 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

1084 achromatic pixels. 

1085 gamma 

1086 System gamma value, defaults to 1.2 at the nominal display peak 

1087 luminance of :math:`1000 cd/m^2`. 

1088 

1089 Returns 

1090 ------- 

1091 :class:`numpy.ndarray` 

1092 Luminance :math:`F_D` of a displayed linear component 

1093 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1094 :math:`cd/m^2`. 

1095 

1096 Notes 

1097 ----- 

1098 +------------+-----------------------+---------------+ 

1099 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1100 +============+=======================+===============+ 

1101 | ``E`` | 1 | 1 | 

1102 +------------+-----------------------+---------------+ 

1103 

1104 +------------+-----------------------+---------------+ 

1105 | **Range** | **Scale - Reference** | **Scale - 1** | 

1106 +============+=======================+===============+ 

1107 | ``F_D`` | 1 | 1 | 

1108 +------------+-----------------------+---------------+ 

1109 

1110 References 

1111 ---------- 

1112 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

1113 

1114 Examples 

1115 -------- 

1116 >>> ootf_BT2100_HLG_1(0.1) # doctest: +ELLIPSIS 

1117 63.0957344... 

1118 >>> ootf_BT2100_HLG_1(0.1, 0.01) 

1119 ... # doctest: +ELLIPSIS 

1120 63.1051034... 

1121 """ 

1122 

1123 E = to_domain_1(E) 

1124 

1125 is_single_channel = np.atleast_1d(E).shape[-1] != 3 

1126 

1127 if is_single_channel: 

1128 usage_warning( 

1129 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses ' 

1130 "RGB Luminance in computations and expects a vector input, thus " 

1131 "the specified input array will be stacked to compose a vector for " 

1132 "internal computations but a single component will be output." 

1133 ) 

1134 R_S = G_S = B_S = E 

1135 else: 

1136 R_S, G_S, B_S = tsplit(E) 

1137 

1138 alpha = L_W - L_B 

1139 beta = L_B 

1140 

1141 Y_S = np.sum(WEIGHTS_BT2100_HLG * tstack([R_S, G_S, B_S]), axis=-1) 

1142 

1143 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W)) 

1144 

1145 R_D = alpha * R_S * np.abs(Y_S) ** (gamma - 1) + beta 

1146 G_D = alpha * G_S * np.abs(Y_S) ** (gamma - 1) + beta 

1147 B_D = alpha * B_S * np.abs(Y_S) ** (gamma - 1) + beta 

1148 

1149 if is_single_channel: 

1150 return as_float(from_range_1(R_D)) 

1151 

1152 RGB_D = tstack([R_D, G_D, B_D]) 

1153 

1154 return from_range_1(RGB_D) 

1155 

1156 

1157def ootf_BT2100_HLG_2( 

1158 E: Domain1, 

1159 L_W: float = 1000, 

1160 gamma: float | None = None, 

1161) -> Range1: 

1162 """ 

1163 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* opto-optical 

1164 transfer function (OOTF) as specified in *ITU-R BT.2100-2*. 

1165 

1166 The OOTF maps relative scene linear light to display linear light. 

1167 

1168 Parameters 

1169 ---------- 

1170 E 

1171 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

1172 signal determined by scene light and scaled by camera exposure. 

1173 L_W 

1174 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

1175 achromatic pixels. 

1176 gamma 

1177 System gamma value, defaults to 1.2 at the nominal display peak 

1178 luminance of :math:`1000 cd/m^2`. 

1179 

1180 Returns 

1181 ------- 

1182 :class:`numpy.ndarray` 

1183 Luminance :math:`F_D` of a displayed linear component 

1184 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1185 :math:`cd/m^2`. 

1186 

1187 Notes 

1188 ----- 

1189 +------------+-----------------------+---------------+ 

1190 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1191 +============+=======================+===============+ 

1192 | ``E`` | 1 | 1 | 

1193 +------------+-----------------------+---------------+ 

1194 

1195 +------------+-----------------------+---------------+ 

1196 | **Range** | **Scale - Reference** | **Scale - 1** | 

1197 +============+=======================+===============+ 

1198 | ``F_D`` | 1 | 1 | 

1199 +------------+-----------------------+---------------+ 

1200 

1201 References 

1202 ---------- 

1203 :cite:`InternationalTelecommunicationUnion2018` 

1204 

1205 Examples 

1206 -------- 

1207 >>> ootf_BT2100_HLG_2(0.1) # doctest: +ELLIPSIS 

1208 63.0957344... 

1209 """ 

1210 

1211 E = to_domain_1(E) 

1212 

1213 is_single_channel = np.atleast_1d(E).shape[-1] != 3 

1214 

1215 if is_single_channel: 

1216 usage_warning( 

1217 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses ' 

1218 "RGB Luminance in computations and expects a vector input, thus " 

1219 "the specified input array will be stacked to compose a vector for " 

1220 "internal computations but a single component will be output." 

1221 ) 

1222 R_S = G_S = B_S = E 

1223 else: 

1224 R_S, G_S, B_S = tsplit(E) 

1225 

1226 alpha = L_W 

1227 

1228 Y_S = np.sum(WEIGHTS_BT2100_HLG * tstack([R_S, G_S, B_S]), axis=-1) 

1229 

1230 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W)) 

1231 

1232 R_D = alpha * R_S * np.abs(Y_S) ** (gamma - 1) 

1233 G_D = alpha * G_S * np.abs(Y_S) ** (gamma - 1) 

1234 B_D = alpha * B_S * np.abs(Y_S) ** (gamma - 1) 

1235 

1236 if is_single_channel: 

1237 return as_float(from_range_1(R_D)) 

1238 

1239 RGB_D = tstack([R_D, G_D, B_D]) 

1240 

1241 return from_range_1(RGB_D) 

1242 

1243 

1244BT2100_HLG_OOTF_METHODS: CanonicalMapping = CanonicalMapping( 

1245 { 

1246 "ITU-R BT.2100-1": ootf_BT2100_HLG_1, 

1247 "ITU-R BT.2100-2": ootf_BT2100_HLG_2, 

1248 } 

1249) 

1250BT2100_HLG_OOTF_METHODS.__doc__ = """ 

1251Map *Recommendation ITU-R BT.2100* *Reference HLG* opto-optical transfer 

1252function (OOTF) methods. 

1253 

1254References 

1255---------- 

1256:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

1257:cite:`InternationalTelecommunicationUnion2018` 

1258""" 

1259 

1260 

1261def ootf_BT2100_HLG( 

1262 E: Domain1, 

1263 L_B: float = 0, 

1264 L_W: float = 1000, 

1265 gamma: float | None = None, 

1266 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2", 

1267) -> Range1: 

1268 """ 

1269 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* opto-optical 

1270 transfer function (OOTF). 

1271 

1272 The OOTF maps relative scene linear light to display linear light. 

1273 

1274 Parameters 

1275 ---------- 

1276 E 

1277 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

1278 signal determined by scene light and scaled by camera exposure. 

1279 L_B 

1280 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

1281 L_W 

1282 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` 

1283 for achromatic pixels. 

1284 gamma 

1285 System gamma value, defaults to 1.2 at the nominal display peak 

1286 luminance of :math:`1000 cd/m^2`. 

1287 

1288 Returns 

1289 ------- 

1290 :class:`numpy.ndarray` 

1291 Luminance :math:`F_D` of a displayed linear component 

1292 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1293 :math:`cd/m^2`. 

1294 

1295 Notes 

1296 ----- 

1297 +------------+-----------------------+---------------+ 

1298 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1299 +============+=======================+===============+ 

1300 | ``E`` | 1 | 1 | 

1301 +------------+-----------------------+---------------+ 

1302 

1303 +------------+-----------------------+---------------+ 

1304 | **Range** | **Scale - Reference** | **Scale - 1** | 

1305 +============+=======================+===============+ 

1306 | ``F_D`` | 1 | 1 | 

1307 +------------+-----------------------+---------------+ 

1308 

1309 References 

1310 ---------- 

1311 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

1312 

1313 Examples 

1314 -------- 

1315 >>> ootf_BT2100_HLG(0.1) # doctest: +ELLIPSIS 

1316 63.0957344... 

1317 >>> ootf_BT2100_HLG(0.1, 0.01, method="ITU-R BT.2100-1") 

1318 ... # doctest: +ELLIPSIS 

1319 63.1051034... 

1320 """ 

1321 

1322 method = validate_method(method, tuple(BT2100_HLG_OOTF_METHODS)) 

1323 

1324 function = BT2100_HLG_OOTF_METHODS[method] 

1325 

1326 return function( 

1327 E, 

1328 **filter_kwargs(function, L_B=L_B, L_W=L_W, gamma=gamma), 

1329 ) 

1330 

1331 

1332def ootf_inverse_BT2100_HLG_1( 

1333 F_D: Domain1, 

1334 L_B: float = 0, 

1335 L_W: float = 1000, 

1336 gamma: float | None = None, 

1337) -> Range1: 

1338 """ 

1339 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

1340 opto-optical transfer function (OOTF) as defined in *ITU-R BT.2100-1*. 

1341 

1342 The inverse OOTF maps display linear light to relative scene linear light. 

1343 

1344 Parameters 

1345 ---------- 

1346 F_D 

1347 Luminance :math:`F_D` of a displayed linear component 

1348 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1349 :math:`cd/m^2`. 

1350 L_B 

1351 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

1352 L_W 

1353 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

1354 achromatic pixels. 

1355 gamma 

1356 System gamma value, defaults to 1.2 at the nominal display peak 

1357 luminance of :math:`1000 cd/m^2`. 

1358 

1359 Returns 

1360 ------- 

1361 :class:`numpy.ndarray` 

1362 :math:`E = \\{R_S, G_S, B_S; Y_S; \\text{or } I_S\\}` denotes the 

1363 signal determined by scene light and scaled by camera exposure. 

1364 

1365 Notes 

1366 ----- 

1367 +------------+-----------------------+---------------+ 

1368 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1369 +============+=======================+===============+ 

1370 | ``F_D`` | 1 | 1 | 

1371 +------------+-----------------------+---------------+ 

1372 

1373 +------------+-----------------------+---------------+ 

1374 | **Range** | **Scale - Reference** | **Scale - 1** | 

1375 +============+=======================+===============+ 

1376 | ``E`` | 1 | 1 | 

1377 +------------+-----------------------+---------------+ 

1378 

1379 References 

1380 ---------- 

1381 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017` 

1382 

1383 Examples 

1384 -------- 

1385 >>> ootf_inverse_BT2100_HLG_1(63.095734448019336) # doctest: +ELLIPSIS 

1386 0.1000000... 

1387 >>> ootf_inverse_BT2100_HLG_1(63.105103490674857, 0.01) 

1388 ... # doctest: +ELLIPSIS 

1389 0.0999999... 

1390 """ 

1391 

1392 F_D = to_domain_1(F_D) 

1393 

1394 is_single_channel = np.atleast_1d(F_D).shape[-1] != 3 

1395 

1396 if is_single_channel: 

1397 usage_warning( 

1398 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses ' 

1399 "RGB Luminance in computations and expects a vector input, thus " 

1400 "the specified input array will be stacked to compose a vector for " 

1401 "internal computations but a single component will be output." 

1402 ) 

1403 R_D = G_D = B_D = F_D 

1404 else: 

1405 R_D, G_D, B_D = tsplit(F_D) 

1406 

1407 Y_D = np.sum(WEIGHTS_BT2100_HLG * tstack([R_D, G_D, B_D]), axis=-1) 

1408 

1409 alpha = L_W - L_B 

1410 beta = L_B 

1411 

1412 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W)) 

1413 

1414 Y_D_beta = np.abs((Y_D - beta) / alpha) ** ((1 - gamma) / gamma) 

1415 

1416 R_S = np.where( 

1417 beta == Y_D, 

1418 0.0, 

1419 Y_D_beta * (R_D - beta) / alpha, 

1420 ) 

1421 G_S = np.where( 

1422 beta == Y_D, 

1423 0.0, 

1424 Y_D_beta * (G_D - beta) / alpha, 

1425 ) 

1426 B_S = np.where( 

1427 beta == Y_D, 

1428 0.0, 

1429 Y_D_beta * (B_D - beta) / alpha, 

1430 ) 

1431 

1432 if is_single_channel: 

1433 return as_float(from_range_1(R_S)) 

1434 

1435 RGB_S = tstack([R_S, G_S, B_S]) 

1436 

1437 return from_range_1(RGB_S) 

1438 

1439 

1440def ootf_inverse_BT2100_HLG_2( 

1441 F_D: Domain1, 

1442 L_W: float = 1000, 

1443 gamma: float | None = None, 

1444) -> Range1: 

1445 """ 

1446 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

1447 opto-optical transfer function (OOTF) according to *ITU-R BT.2100-2*. 

1448 

1449 The inverse OOTF maps display linear light to relative scene linear light. 

1450 

1451 Parameters 

1452 ---------- 

1453 F_D 

1454 Luminance :math:`F_D` of a displayed linear component 

1455 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1456 :math:`cd/m^2`. 

1457 L_W 

1458 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

1459 achromatic pixels. 

1460 gamma 

1461 System gamma value, defaults to 1.2 at the nominal display peak 

1462 luminance of :math:`1000 cd/m^2`. 

1463 

1464 Returns 

1465 ------- 

1466 :class:`numpy.ndarray` 

1467 :math:`E` denotes the signal for each colour component 

1468 :math:`\\{R_S, G_S, B_S\\}` proportional to scene linear light and 

1469 scaled by camera exposure. 

1470 

1471 Notes 

1472 ----- 

1473 +------------+-----------------------+---------------+ 

1474 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1475 +============+=======================+===============+ 

1476 | ``F_D`` | 1 | 1 | 

1477 +------------+-----------------------+---------------+ 

1478 

1479 +------------+-----------------------+---------------+ 

1480 | **Range** | **Scale - Reference** | **Scale - 1** | 

1481 +============+=======================+===============+ 

1482 | ``E`` | 1 | 1 | 

1483 +------------+-----------------------+---------------+ 

1484 

1485 References 

1486 ---------- 

1487 :cite:`InternationalTelecommunicationUnion2018` 

1488 

1489 Examples 

1490 -------- 

1491 >>> ootf_inverse_BT2100_HLG_2(63.095734448019336) # doctest: +ELLIPSIS 

1492 0.1000000... 

1493 """ 

1494 

1495 F_D = to_domain_1(F_D) 

1496 

1497 is_single_channel = np.atleast_1d(F_D).shape[-1] != 3 

1498 

1499 if is_single_channel: 

1500 usage_warning( 

1501 '"Recommendation ITU-R BT.2100" "Reference HLG OOTF" uses ' 

1502 "RGB Luminance in computations and expects a vector input, thus " 

1503 "the specified input array will be stacked to compose a vector for " 

1504 "internal computations but a single component will be output." 

1505 ) 

1506 R_D = G_D = B_D = F_D 

1507 else: 

1508 R_D, G_D, B_D = tsplit(F_D) 

1509 

1510 Y_D = np.sum(WEIGHTS_BT2100_HLG * tstack([R_D, G_D, B_D]), axis=-1) 

1511 

1512 alpha = L_W 

1513 

1514 gamma = optional(gamma, gamma_function_BT2100_HLG(L_W)) 

1515 

1516 Y_D_alpha = np.abs(Y_D / alpha) ** ((1 - gamma) / gamma) 

1517 

1518 R_S = np.where( 

1519 Y_D == 0, 

1520 0.0, 

1521 Y_D_alpha * R_D / alpha, 

1522 ) 

1523 G_S = np.where( 

1524 Y_D == 0, 

1525 0.0, 

1526 Y_D_alpha * G_D / alpha, 

1527 ) 

1528 B_S = np.where( 

1529 Y_D == 0, 

1530 0.0, 

1531 Y_D_alpha * B_D / alpha, 

1532 ) 

1533 

1534 if is_single_channel: 

1535 return as_float(from_range_1(R_S)) 

1536 

1537 RGB_S = tstack([R_S, G_S, B_S]) 

1538 

1539 return from_range_1(RGB_S) 

1540 

1541 

1542BT2100_HLG_OOTF_INVERSE_METHODS: CanonicalMapping = CanonicalMapping( 

1543 { 

1544 "ITU-R BT.2100-1": ootf_inverse_BT2100_HLG_1, 

1545 "ITU-R BT.2100-2": ootf_inverse_BT2100_HLG_2, 

1546 } 

1547) 

1548BT2100_HLG_OOTF_INVERSE_METHODS.__doc__ = """ 

1549Support methods for the *ITU-R BT.2100* *Reference HLG* inverse 

1550opto-optical transfer function (OOTF). 

1551 

1552References 

1553---------- 

1554:cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

1555:cite:`InternationalTelecommunicationUnion2018` 

1556""" 

1557 

1558 

1559def ootf_inverse_BT2100_HLG( 

1560 F_D: Domain1, 

1561 L_B: float = 0, 

1562 L_W: float = 1000, 

1563 gamma: float | None = None, 

1564 method: (Literal["ITU-R BT.2100-1", "ITU-R BT.2100-2"] | str) = "ITU-R BT.2100-2", 

1565) -> Range1: 

1566 """ 

1567 Apply the *Recommendation ITU-R BT.2100* *Reference HLG* inverse 

1568 opto-optical transfer function (OOTF). 

1569 

1570 The inverse OOTF maps display linear light to relative scene linear light. 

1571 

1572 Parameters 

1573 ---------- 

1574 F_D 

1575 Luminance :math:`F_D` of a displayed linear component 

1576 :math:`\\{R_D, G_D, B_D\\}` or :math:`Y_D` or :math:`I_D`, in 

1577 :math:`cd/m^2`. 

1578 L_B 

1579 Display luminance for black :math:`L_B` in :math:`cd/m^2`. 

1580 L_W 

1581 Nominal peak luminance :math:`L_W` of the display in :math:`cd/m^2` for 

1582 achromatic pixels. 

1583 gamma 

1584 System gamma value, defaults to 1.2 at the nominal display peak 

1585 luminance of :math:`1000 cd/m^2`. 

1586 method 

1587 Computation method. 

1588 

1589 Returns 

1590 ------- 

1591 :class:`numpy.ndarray` 

1592 :math:`E` denotes the signal for each colour component 

1593 :math:`\\{R_S, G_S, B_S\\}` proportional to scene linear light and 

1594 scaled by camera exposure. 

1595 

1596 Notes 

1597 ----- 

1598 +------------+-----------------------+---------------+ 

1599 | **Domain** | **Scale - Reference** | **Scale - 1** | 

1600 +============+=======================+===============+ 

1601 | ``F_D`` | 1 | 1 | 

1602 +------------+-----------------------+---------------+ 

1603 

1604 +------------+-----------------------+---------------+ 

1605 | **Range** | **Scale - Reference** | **Scale - 1** | 

1606 +============+=======================+===============+ 

1607 | ``E`` | 1 | 1 | 

1608 +------------+-----------------------+---------------+ 

1609 

1610 References 

1611 ---------- 

1612 :cite:`Borer2017a`, :cite:`InternationalTelecommunicationUnion2017`, 

1613 :cite:`InternationalTelecommunicationUnion2018` 

1614 

1615 Examples 

1616 -------- 

1617 >>> ootf_inverse_BT2100_HLG(63.095734448019336) # doctest: +ELLIPSIS 

1618 0.1000000... 

1619 >>> ootf_inverse_BT2100_HLG(63.105103490674857, 0.01, method="ITU-R BT.2100-1") 

1620 ... # doctest: +ELLIPSIS 

1621 0.0999999... 

1622 """ 

1623 

1624 method = validate_method(method, tuple(BT2100_HLG_OOTF_INVERSE_METHODS)) 

1625 

1626 function = BT2100_HLG_OOTF_INVERSE_METHODS[method] 

1627 

1628 return function( 

1629 F_D, 

1630 **filter_kwargs(function, L_B=L_B, L_W=L_W, gamma=gamma), 

1631 )