Coverage for models/rgb/transfer_functions/red.py: 60%

78 statements  

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

1""" 

2RED Log Encodings 

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

4 

5Define the *RED* log encodings. 

6 

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

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

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

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

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

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

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

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

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

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

17- :attr:`colour.models.LOG3G10_ENCODING_METHODS` 

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

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

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

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

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

23 

24References 

25---------- 

26- :cite:`Nattress2016a` : Nattress, G. (2016). Private Discussion with Shaw, 

27 N. 

28- :cite:`REDDigitalCinema2017` : RED Digital Cinema. (2017). White Paper on 

29 REDWideGamutRGB and Log3G10. Retrieved January 16, 2021, from 

30 https://www.red.com/download/white-paper-on-redwidegamutrgb-and-log3g10 

31- :cite:`SonyImageworks2012a` : Sony Imageworks. (2012). make.py. Retrieved 

32 November 27, 2014, from 

33 https://github.com/imageworks/OpenColorIO-Configs/blob/master/\ 

34nuke-default/make.py 

35""" 

36 

37from __future__ import annotations 

38 

39import typing 

40 

41import numpy as np 

42 

43if typing.TYPE_CHECKING: 

44 from colour.hints import Literal 

45 

46from colour.hints import ( # noqa: TC001 

47 ArrayLike, 

48 Domain1, 

49 Range1, 

50) 

51from colour.models.rgb.transfer_functions import ( 

52 log_decoding_Cineon, 

53 log_encoding_Cineon, 

54) 

55from colour.utilities import ( 

56 CanonicalMapping, 

57 as_float, 

58 as_float_array, 

59 from_range_1, 

60 to_domain_1, 

61 validate_method, 

62) 

63 

64__author__ = "Colour Developers" 

65__copyright__ = "Copyright 2013 Colour Developers" 

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

67__maintainer__ = "Colour Developers" 

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

69__status__ = "Production" 

70 

71__all__ = [ 

72 "log_encoding_REDLog", 

73 "log_decoding_REDLog", 

74 "log_encoding_REDLogFilm", 

75 "log_decoding_REDLogFilm", 

76 "log_encoding_Log3G10_v1", 

77 "log_decoding_Log3G10_v1", 

78 "log_encoding_Log3G10_v2", 

79 "log_decoding_Log3G10_v2", 

80 "log_encoding_Log3G10_v3", 

81 "log_decoding_Log3G10_v3", 

82 "LOG3G10_ENCODING_METHODS", 

83 "log_encoding_Log3G10", 

84 "LOG3G10_DECODING_METHODS", 

85 "log_decoding_Log3G10", 

86 "log_encoding_Log3G12", 

87 "log_decoding_Log3G12", 

88] 

89 

90 

91def log_encoding_REDLog( 

92 x: Domain1, 

93 black_offset: ArrayLike = 10 ** ((0 - 1023) / 511), 

94) -> Range1: 

95 """ 

96 Apply the *REDLog* log encoding opto-electronic transfer function (OETF). 

97 

98 Parameters 

99 ---------- 

100 x 

101 Linear data :math:`x`. 

102 black_offset 

103 Black offset value. 

104 

105 Returns 

106 ------- 

107 :class:`numpy.ndarray` 

108 *REDLog* non-linear encoded data :math:`y`. 

109 

110 Notes 

111 ----- 

112 +------------+-----------------------+---------------+ 

113 | **Domain** | **Scale - Reference** | **Scale - 1** | 

114 +============+=======================+===============+ 

115 | ``x`` | 1 | 1 | 

116 +------------+-----------------------+---------------+ 

117 

118 +------------+-----------------------+---------------+ 

119 | **Range** | **Scale - Reference** | **Scale - 1** | 

120 +============+=======================+===============+ 

121 | ``y`` | 1 | 1 | 

122 +------------+-----------------------+---------------+ 

123 

124 References 

125 ---------- 

126 :cite:`SonyImageworks2012a` 

127 

128 Examples 

129 -------- 

130 >>> log_encoding_REDLog(0.18) # doctest: +ELLIPSIS 

131 0.6376218... 

132 """ 

133 

134 x = to_domain_1(x) 

135 black_offset = as_float_array(black_offset) 

136 

137 y = (1023 + 511 * np.log10(x * (1 - black_offset) + black_offset)) / 1023 

138 

139 return as_float(from_range_1(y)) 

140 

141 

142def log_decoding_REDLog( 

143 y: Domain1, 

144 black_offset: ArrayLike = 10 ** ((0 - 1023) / 511), 

145) -> Range1: 

146 """ 

147 Apply the *REDLog* log decoding inverse opto-electronic transfer function (OETF). 

148 

149 Parameters 

150 ---------- 

151 y 

152 *REDLog* non-linear encoded data :math:`y`. 

153 black_offset 

154 Black offset value. 

155 

156 Returns 

157 ------- 

158 :class:`numpy.ndarray` 

159 Linear data :math:`x`. 

160 

161 Notes 

162 ----- 

163 +------------+-----------------------+---------------+ 

164 | **Domain** | **Scale - Reference** | **Scale - 1** | 

165 +============+=======================+===============+ 

166 | ``y`` | 1 | 1 | 

167 +------------+-----------------------+---------------+ 

168 

169 +------------+-----------------------+---------------+ 

170 | **Range** | **Scale - Reference** | **Scale - 1** | 

171 +============+=======================+===============+ 

172 | ``x`` | 1 | 1 | 

173 +------------+-----------------------+---------------+ 

174 

175 References 

176 ---------- 

177 :cite:`SonyImageworks2012a` 

178 

179 Examples 

180 -------- 

181 >>> log_decoding_REDLog(0.637621845988175) # doctest: +ELLIPSIS 

182 0.1... 

183 """ 

184 

185 y = to_domain_1(y) 

186 black_offset = as_float_array(black_offset) 

187 

188 x = ((10 ** ((1023 * y - 1023) / 511)) - black_offset) / (1 - black_offset) 

189 

190 return as_float(from_range_1(x)) 

191 

192 

193def log_encoding_REDLogFilm( 

194 x: Domain1, 

195 black_offset: ArrayLike = 10 ** ((95 - 685) / 300), 

196) -> Range1: 

197 """ 

198 Apply the *REDLogFilm* log encoding opto-electronic transfer function (OETF). 

199 

200 Parameters 

201 ---------- 

202 x 

203 Linear data :math:`x`. 

204 black_offset 

205 Black offset value. 

206 

207 Returns 

208 ------- 

209 :class:`numpy.ndarray` 

210 *REDLogFilm* non-linear encoded data :math:`y`. 

211 

212 Notes 

213 ----- 

214 +------------+-----------------------+---------------+ 

215 | **Domain** | **Scale - Reference** | **Scale - 1** | 

216 +============+=======================+===============+ 

217 | ``x`` | 1 | 1 | 

218 +------------+-----------------------+---------------+ 

219 

220 +------------+-----------------------+---------------+ 

221 | **Range** | **Scale - Reference** | **Scale - 1** | 

222 +============+=======================+===============+ 

223 | ``y`` | 1 | 1 | 

224 +------------+-----------------------+---------------+ 

225 

226 References 

227 ---------- 

228 :cite:`SonyImageworks2012a` 

229 

230 Examples 

231 -------- 

232 >>> log_encoding_REDLogFilm(0.18) # doctest: +ELLIPSIS 

233 0.4573196... 

234 """ 

235 

236 return log_encoding_Cineon(x, black_offset) 

237 

238 

239def log_decoding_REDLogFilm( 

240 y: Domain1, 

241 black_offset: ArrayLike = 10 ** ((95 - 685) / 300), 

242) -> Range1: 

243 """ 

244 Apply the *REDLogFilm* log decoding inverse opto-electronic transfer 

245 function (OETF). 

246 

247 Parameters 

248 ---------- 

249 y 

250 *REDLogFilm* non-linear encoded data :math:`y`. 

251 black_offset 

252 Black offset value. 

253 

254 Returns 

255 ------- 

256 :class:`numpy.ndarray` 

257 Linear data :math:`x`. 

258 

259 Notes 

260 ----- 

261 +------------+-----------------------+---------------+ 

262 | **Domain** | **Scale - Reference** | **Scale - 1** | 

263 +============+=======================+===============+ 

264 | ``y`` | 1 | 1 | 

265 +------------+-----------------------+---------------+ 

266 

267 +------------+-----------------------+---------------+ 

268 | **Range** | **Scale - Reference** | **Scale - 1** | 

269 +============+=======================+===============+ 

270 | ``x`` | 1 | 1 | 

271 +------------+-----------------------+---------------+ 

272 

273 References 

274 ---------- 

275 :cite:`SonyImageworks2012a` 

276 

277 Examples 

278 -------- 

279 >>> log_decoding_REDLogFilm(0.457319613085418) # doctest: +ELLIPSIS 

280 0.1799999... 

281 """ 

282 

283 return log_decoding_Cineon(y, black_offset) 

284 

285 

286def log_encoding_Log3G10_v1(x: Domain1) -> Range1: 

287 """ 

288 Apply the *Log3G10* *v1* log encoding opto-electronic transfer function (OETF). 

289 

290 From *REDCINE-X PRO Beta 42* and *Resolve 12.5.2*. 

291 

292 Parameters 

293 ---------- 

294 x 

295 Linear data :math:`x`. 

296 

297 Returns 

298 ------- 

299 :class:`numpy.ndarray` 

300 *Log3G10* *v1* non-linear encoded data :math:`y`. 

301 

302 Notes 

303 ----- 

304 +------------+-----------------------+---------------+ 

305 | **Domain** | **Scale - Reference** | **Scale - 1** | 

306 +============+=======================+===============+ 

307 | ``x`` | 1 | 1 | 

308 +------------+-----------------------+---------------+ 

309 

310 +------------+-----------------------+---------------+ 

311 | **Range** | **Scale - Reference** | **Scale - 1** | 

312 +============+=======================+===============+ 

313 | ``y`` | 1 | 1 | 

314 +------------+-----------------------+---------------+ 

315 

316 References 

317 ---------- 

318 :cite:`Nattress2016a` 

319 

320 Examples 

321 -------- 

322 >>> log_encoding_Log3G10_v1(0.18) # doctest: +ELLIPSIS 

323 0.3333336... 

324 """ 

325 

326 x = to_domain_1(x) 

327 

328 y = np.sign(x) * 0.222497 * np.log10((np.abs(x) * 169.379333) + 1) 

329 

330 return as_float(from_range_1(y)) 

331 

332 

333def log_decoding_Log3G10_v1(y: Domain1) -> Range1: 

334 """ 

335 Apply the *Log3G10* *v1* log decoding inverse opto-electronic transfer 

336 function (OETF). 

337 

338 From *REDCINE-X PRO Beta 42* and *Resolve 12.5.2*. 

339 

340 Parameters 

341 ---------- 

342 y 

343 *Log3G10* *v1* non-linear encoded data :math:`y`. 

344 

345 Returns 

346 ------- 

347 :class:`numpy.ndarray` 

348 Linear data :math:`x`. 

349 

350 Notes 

351 ----- 

352 +------------+-----------------------+---------------+ 

353 | **Domain** | **Scale - Reference** | **Scale - 1** | 

354 +============+=======================+===============+ 

355 | ``y`` | 1 | 1 | 

356 +------------+-----------------------+---------------+ 

357 

358 +------------+-----------------------+---------------+ 

359 | **Range** | **Scale - Reference** | **Scale - 1** | 

360 +============+=======================+===============+ 

361 | ``x`` | 1 | 1 | 

362 +------------+-----------------------+---------------+ 

363 

364 References 

365 ---------- 

366 :cite:`Nattress2016a` 

367 

368 Examples 

369 -------- 

370 >>> log_decoding_Log3G10_v1(1.0 / 3) # doctest: +ELLIPSIS 

371 0.1799994... 

372 """ 

373 

374 y = to_domain_1(y) 

375 

376 x = np.sign(y) * (10.0 ** (np.abs(y) / 0.222497) - 1) / 169.379333 

377 

378 return as_float(from_range_1(x)) 

379 

380 

381def log_encoding_Log3G10_v2(x: Domain1) -> Range1: 

382 """ 

383 Apply the *Log3G10* *v2* log encoding opto-electronic transfer function (OETF). 

384 

385 Current curve used in *REDCINE-X PRO*. 

386 

387 Parameters 

388 ---------- 

389 x 

390 Linear data :math:`x`. 

391 

392 Returns 

393 ------- 

394 :class:`numpy.ndarray` 

395 *Log3G10* *v2* non-linear encoded data :math:`y`. 

396 

397 Notes 

398 ----- 

399 +------------+-----------------------+---------------+ 

400 | **Domain** | **Scale - Reference** | **Scale - 1** | 

401 +============+=======================+===============+ 

402 | ``x`` | 1 | 1 | 

403 +------------+-----------------------+---------------+ 

404 

405 +------------+-----------------------+---------------+ 

406 | **Range** | **Scale - Reference** | **Scale - 1** | 

407 +============+=======================+===============+ 

408 | ``y`` | 1 | 1 | 

409 +------------+-----------------------+---------------+ 

410 

411 References 

412 ---------- 

413 :cite:`Nattress2016a` 

414 

415 Examples 

416 -------- 

417 >>> log_encoding_Log3G10_v2(0.0) # doctest: +ELLIPSIS 

418 0.0915514... 

419 """ 

420 

421 x = to_domain_1(x) 

422 

423 y = np.sign(x + 0.01) * 0.224282 * np.log10((np.abs(x + 0.01) * 155.975327) + 1) 

424 

425 return as_float(from_range_1(y)) 

426 

427 

428def log_decoding_Log3G10_v2(y: Domain1) -> Range1: 

429 """ 

430 Apply the *Log3G10* *v2* log decoding inverse opto-electronic transfer 

431 function (OETF). 

432 

433 Current curve used in *REDCINE-X PRO*. 

434 

435 Parameters 

436 ---------- 

437 y 

438 *Log3G10* *v2* non-linear encoded data :math:`y`. 

439 

440 Returns 

441 ------- 

442 :class:`numpy.ndarray` 

443 Linear data :math:`x`. 

444 

445 Notes 

446 ----- 

447 +------------+-----------------------+---------------+ 

448 | **Domain** | **Scale - Reference** | **Scale - 1** | 

449 +============+=======================+===============+ 

450 | ``y`` | 1 | 1 | 

451 +------------+-----------------------+---------------+ 

452 

453 +------------+-----------------------+---------------+ 

454 | **Range** | **Scale - Reference** | **Scale - 1** | 

455 +============+=======================+===============+ 

456 | ``x`` | 1 | 1 | 

457 +------------+-----------------------+---------------+ 

458 

459 References 

460 ---------- 

461 :cite:`Nattress2016a` 

462 

463 Examples 

464 -------- 

465 >>> log_decoding_Log3G10_v2(1.0) # doctest: +ELLIPSIS 

466 184.3223476... 

467 """ 

468 

469 y = to_domain_1(y) 

470 

471 x = (np.sign(y) * (10.0 ** (np.abs(y) / 0.224282) - 1) / 155.975327) - 0.01 

472 

473 return as_float(from_range_1(x)) 

474 

475 

476def log_encoding_Log3G10_v3(x: Domain1) -> Range1: 

477 """ 

478 Apply the *Log3G10* *v3* log encoding opto-electronic transfer function (OETF). 

479 

480 As described in the *RedLog3G10* whitepaper. 

481 

482 Parameters 

483 ---------- 

484 x 

485 Linear data :math:`x`. 

486 

487 Returns 

488 ------- 

489 :class:`numpy.ndarray` 

490 *Log3G10* *v3* non-linear encoded data :math:`y`. 

491 

492 Notes 

493 ----- 

494 +------------+-----------------------+---------------+ 

495 | **Domain** | **Scale - Reference** | **Scale - 1** | 

496 +============+=======================+===============+ 

497 | ``x`` | 1 | 1 | 

498 +------------+-----------------------+---------------+ 

499 

500 +------------+-----------------------+---------------+ 

501 | **Range** | **Scale - Reference** | **Scale - 1** | 

502 +============+=======================+===============+ 

503 | ``y`` | 1 | 1 | 

504 +------------+-----------------------+---------------+ 

505 

506 References 

507 ---------- 

508 :cite:`REDDigitalCinema2017` 

509 

510 Examples 

511 -------- 

512 >>> log_encoding_Log3G10_v3(0.0) # doctest: +ELLIPSIS 

513 0.09155148... 

514 """ 

515 

516 a = 0.224282 

517 b = 155.975327 

518 c = 0.01 

519 g = 15.1927 

520 

521 x = to_domain_1(x) 

522 

523 x = x + c 

524 

525 y = np.where(x < 0.0, x * g, np.sign(x) * a * np.log10((np.abs(x) * b) + 1.0)) 

526 

527 return as_float(from_range_1(y)) 

528 

529 

530def log_decoding_Log3G10_v3(y: Domain1) -> Range1: 

531 """ 

532 Apply the *Log3G10* *v3* log decoding inverse opto-electronic transfer 

533 function (OETF). 

534 

535 As described in the *RedLog3G10* whitepaper. 

536 

537 Parameters 

538 ---------- 

539 y 

540 *Log3G10* *v3* non-linear encoded data :math:`y`. 

541 

542 Returns 

543 ------- 

544 :class:`numpy.ndarray` 

545 Linear *Log3G10* *v3* data :math:`x`. 

546 

547 Notes 

548 ----- 

549 +------------+-----------------------+---------------+ 

550 | **Domain** | **Scale - Reference** | **Scale - 1** | 

551 +============+=======================+===============+ 

552 | ``y`` | 1 | 1 | 

553 +------------+-----------------------+---------------+ 

554 

555 +------------+-----------------------+---------------+ 

556 | **Range** | **Scale - Reference** | **Scale - 1** | 

557 +============+=======================+===============+ 

558 | ``x`` | 1 | 1 | 

559 +------------+-----------------------+---------------+ 

560 

561 References 

562 ---------- 

563 :cite:`REDDigitalCinema2017` 

564 

565 Examples 

566 -------- 

567 >>> log_decoding_Log3G10_v3(1.0) # doctest: +ELLIPSIS 

568 184.32234764... 

569 """ 

570 

571 a = 0.224282 

572 b = 155.975327 

573 c = 0.01 

574 g = 15.1927 

575 

576 y = to_domain_1(y) 

577 

578 x = np.where( 

579 y < 0.0, 

580 (y / g) - c, 

581 np.sign(y) * (10 ** (np.abs(y) / a) - 1.0) / b - c, 

582 ) 

583 

584 return as_float(from_range_1(x)) 

585 

586 

587LOG3G10_ENCODING_METHODS: CanonicalMapping = CanonicalMapping( 

588 { 

589 "v1": log_encoding_Log3G10_v1, 

590 "v2": log_encoding_Log3G10_v2, 

591 "v3": log_encoding_Log3G10_v3, 

592 } 

593) 

594LOG3G10_ENCODING_METHODS.__doc__ = """ 

595Supported *Log3G10* log encoding curve / opto-electronic transfer (OETF) 

596function methods. 

597 

598References 

599---------- 

600:cite:`Nattress2016a`, :cite:`REDDigitalCinema2017` 

601""" 

602 

603 

604def log_encoding_Log3G10( 

605 x: Domain1, 

606 method: Literal["v1", "v2", "v3"] | str = "v3", 

607) -> Range1: 

608 """ 

609 Apply the *Log3G10* log encoding opto-electronic transfer function (OETF). 

610 

611 Parameters 

612 ---------- 

613 x 

614 Linear data :math:`x`. 

615 method 

616 Computation method. 

617 

618 Returns 

619 ------- 

620 :class:`numpy.ndarray` 

621 *Log3G10* non-linear encoded data :math:`y`. 

622 

623 Notes 

624 ----- 

625 +------------+-----------------------+---------------+ 

626 | **Domain** | **Scale - Reference** | **Scale - 1** | 

627 +============+=======================+===============+ 

628 | ``x`` | 1 | 1 | 

629 +------------+-----------------------+---------------+ 

630 

631 +------------+-----------------------+---------------+ 

632 | **Range** | **Scale - Reference** | **Scale - 1** | 

633 +============+=======================+===============+ 

634 | ``y`` | 1 | 1 | 

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

636 

637 - The *Log3G10* *v1* log encoding curve is the one used in 

638 *REDCINE-X Beta 42*. *Resolve 12.5.2* also uses the *v1* curve. 

639 *RED* is planning to use the *Log3G10* *v2* log encoding curve in 

640 the release version of the *RED SDK*. 

641 - The intent of the *Log3G10* *v1* log encoding curve is that zero 

642 maps to zero, 0.18 maps to 1/3, and 10 stops above 0.18 maps to 

643 1.0. The name indicates this in a similar way to the naming 

644 conventions of *Sony HyperGamma* curves. 

645 

646 The constants used in the functions do not in fact quite hit these 

647 values, but rather than use corrected constants, the functions here 

648 use the official *RED* values, in order to match the output of the 

649 *RED SDK*. 

650 

651 For those interested, solving for constants which exactly hit 1/3 

652 and 1.0 yields the following values:: 

653 

654 B = 25 * (np.sqrt(4093.0) - 3) / 9 

655 A = 1 / np.log10(B * 184.32 + 1) 

656 

657 where the function takes the form:: 

658 

659 Log3G10(x) = A * np.log10(B * x + 1) 

660 

661 Similarly for *Log3G12*, the values which hit exactly 1/3 and 1.0 

662 are:: 

663 

664 B = 25 * (np.sqrt(16381.0) - 3) / 9 

665 A = 1 / np.log10(B * 737.28 + 1) 

666 

667 References 

668 ---------- 

669 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017` 

670 

671 Examples 

672 -------- 

673 >>> log_encoding_Log3G10(0.0) # doctest: +ELLIPSIS 

674 0.09155148... 

675 >>> log_encoding_Log3G10(0.18, method="v1") # doctest: +ELLIPSIS 

676 0.3333336... 

677 """ 

678 

679 method = validate_method(method, tuple(LOG3G10_ENCODING_METHODS)) 

680 

681 return LOG3G10_ENCODING_METHODS[method](x) 

682 

683 

684LOG3G10_DECODING_METHODS = CanonicalMapping( 

685 { 

686 "v1": log_decoding_Log3G10_v1, 

687 "v2": log_decoding_Log3G10_v2, 

688 "v3": log_decoding_Log3G10_v3, 

689 } 

690) 

691LOG3G10_DECODING_METHODS.__doc__ = """ 

692Supported *Log3G10* log decoding curve / electro-optical transfer (EOTF) 

693function methods. 

694 

695References 

696---------- 

697:cite:`Nattress2016a`, :cite:`REDDigitalCinema2017` 

698""" 

699 

700 

701def log_decoding_Log3G10( 

702 y: Domain1, method: Literal["v1", "v2", "v3"] | str = "v3" 

703) -> Range1: 

704 """ 

705 Apply the *Log3G10* log decoding inverse opto-electronic transfer function (OETF). 

706 

707 Parameters 

708 ---------- 

709 y 

710 *Log3G10* non-linear encoded data :math:`y`. 

711 method 

712 Computation method. 

713 

714 Returns 

715 ------- 

716 :class:`numpy.ndarray` 

717 Linear data :math:`x`. 

718 

719 Notes 

720 ----- 

721 +------------+-----------------------+---------------+ 

722 | **Domain** | **Scale - Reference** | **Scale - 1** | 

723 +============+=======================+===============+ 

724 | ``y`` | 1 | 1 | 

725 +------------+-----------------------+---------------+ 

726 

727 +------------+-----------------------+---------------+ 

728 | **Range** | **Scale - Reference** | **Scale - 1** | 

729 +============+=======================+===============+ 

730 | ``x`` | 1 | 1 | 

731 +------------+-----------------------+---------------+ 

732 

733 References 

734 ---------- 

735 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017` 

736 

737 Examples 

738 -------- 

739 >>> log_decoding_Log3G10(1.0) # doctest: +ELLIPSIS 

740 184.3223476... 

741 >>> log_decoding_Log3G10(1.0 / 3, method="v1") # doctest: +ELLIPSIS 

742 0.1799994... 

743 """ 

744 

745 method = validate_method(method, tuple(LOG3G10_DECODING_METHODS)) 

746 

747 return LOG3G10_DECODING_METHODS[method](y) 

748 

749 

750def log_encoding_Log3G12(x: Domain1) -> Range1: 

751 """ 

752 Apply the *Log3G12* log encoding opto-electronic transfer function (OETF). 

753 

754 Parameters 

755 ---------- 

756 x 

757 Linear data :math:`x`. 

758 

759 Returns 

760 ------- 

761 :class:`numpy.ndarray` 

762 *Log3G12* non-linear encoded data :math:`y`. 

763 

764 Notes 

765 ----- 

766 +------------+-----------------------+---------------+ 

767 | **Domain** | **Scale - Reference** | **Scale - 1** | 

768 +============+=======================+===============+ 

769 | ``x`` | 1 | 1 | 

770 +------------+-----------------------+---------------+ 

771 

772 +------------+-----------------------+---------------+ 

773 | **Range** | **Scale - Reference** | **Scale - 1** | 

774 +============+=======================+===============+ 

775 | ``y`` | 1 | 1 | 

776 +------------+-----------------------+---------------+ 

777 

778 References 

779 ---------- 

780 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017` 

781 

782 Examples 

783 -------- 

784 >>> log_encoding_Log3G12(0.18) # doctest: +ELLIPSIS 

785 0.3333326... 

786 """ 

787 

788 x = to_domain_1(x) 

789 

790 y = np.sign(x) * 0.184904 * np.log10((np.abs(x) * 347.189667) + 1) 

791 

792 return as_float(from_range_1(y)) 

793 

794 

795def log_decoding_Log3G12(y: Domain1) -> Range1: 

796 """ 

797 Apply the *Log3G12* log decoding inverse opto-electronic transfer function (OETF). 

798 

799 Parameters 

800 ---------- 

801 y 

802 *Log3G12* non-linear encoded data :math:`y`. 

803 

804 Returns 

805 ------- 

806 :class:`numpy.ndarray` 

807 Linear data :math:`x`. 

808 

809 Notes 

810 ----- 

811 +------------+-----------------------+---------------+ 

812 | **Domain** | **Scale - Reference** | **Scale - 1** | 

813 +============+=======================+===============+ 

814 | ``y`` | 1 | 1 | 

815 +------------+-----------------------+---------------+ 

816 

817 +------------+-----------------------+---------------+ 

818 | **Range** | **Scale - Reference** | **Scale - 1** | 

819 +============+=======================+===============+ 

820 | ``x`` | 1 | 1 | 

821 +------------+-----------------------+---------------+ 

822 

823 References 

824 ---------- 

825 :cite:`Nattress2016a`, :cite:`REDDigitalCinema2017` 

826 

827 Examples 

828 -------- 

829 >>> log_decoding_Log3G12(1.0 / 3) # doctest: +ELLIPSIS 

830 0.1800015... 

831 """ 

832 

833 y = to_domain_1(y) 

834 

835 x = np.sign(y) * (10.0 ** (np.abs(y) / 0.184904) - 1) / 347.189667 

836 

837 return as_float(from_range_1(x))