Coverage for io/luts/sony_spimtx.py: 44%

1"""

2 Sony .spimtx LUT Format Input / Output Utilities

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

4

5 Define the *Sony* *.spimtx* *LUT* format related input / output utilities

6 objects:

7

8- :func:`colour.io.read_LUT_SonySPImtx`

9- :func:`colour.io.write_LUT_SonySPImtx`

10"""

11

12 from __future__ import annotations

13

14 import typing

15

16 import numpy as np

17

18 from colour.constants import DTYPE_FLOAT_DEFAULT

19

20 if typing.TYPE_CHECKING:

21 from colour.hints import PathLike

22

23 from colour.io.luts import LUTOperatorMatrix

24 from colour.io.luts.common import path_to_title

25

26 __author__ = "Colour Developers"

27 __copyright__ = "Copyright 2013 Colour Developers"

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

29 __maintainer__ = "Colour Developers"

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

31 __status__ = "Production"

32

33 __all__ = [

34 "read_LUT_SonySPImtx",

35 "write_LUT_SonySPImtx",

36]

37

38

39 def read_LUT_SonySPImtx(path: str | PathLike) -> LUTOperatorMatrix:

40 """

41 Read the specified *Sony* *.spimtx* *LUT* file.

42

43 Parse the *.spimtx* format which contains a 3x4 matrix stored as 12

44 values. Extract the 3x3 transformation matrix and offset vector from

45 the fourth column (scaled by 65535) to create a

46 :class:`colour.LUTOperatorMatrix` instance.

47

48 Parameters

49 ----------

50 path

51 *LUT* file path.

52

53 Returns

54 -------

55 :class:`colour.LUTOperatorMatrix`

56 *LUT* operator matrix instance containing the extracted 3x3 matrix

57 and offset vector.

58

59 Examples

60 --------

61 >>> import os

62 >>> path = os.path.join(

63 ... os.path.dirname(__file__),

64 ... "tests",

65 ... "resources",

66 ... "sony_spimtx",

67 ... "dt.spimtx",

68 ... )

69 >>> print(read_LUT_SonySPImtx(path))

70 LUTOperatorMatrix - dt

71 ----------------------

72 <BLANKLINE>

73 Matrix : [[ 0.864274 0. 0. 0. ]

74 [ 0. 0.864274 0. 0. ]

75 [ 0. 0. 0.864274 0. ]

76 [ 0. 0. 0. 1. ]]

77 Offset : [ 0. 0. 0. 0.]

78 """

79

80 path = str(path)

81

82 matrix = np.loadtxt(path, dtype=DTYPE_FLOAT_DEFAULT)

83 matrix = np.reshape(matrix, (3, 4))

84 offset = matrix[:, 3] / 65535

85 matrix = matrix[:3, :3]

86

87 title = path_to_title(path)

88

89 return LUTOperatorMatrix(matrix, offset, name=title)

90

91

92 def write_LUT_SonySPImtx(

93 LUT: LUTOperatorMatrix,

94 path: str | PathLike | typing.IO[typing.Any],

95 decimals: int = 7,

96) -> bool:

97 """

98 Write the specified *LUT* to the specified *Sony* *.spimtx* *LUT* file.

99

100 Parameters

101 ----------

102 LUT

103 :class:`LUTOperatorMatrix` class instance to write at the

104 specified path.

105 path

106 *LUT* file path.

107 decimals

108 Number of decimal places for formatting numeric values.

109

110 Returns

111 -------

112 :class:`bool`

113 Definition success.

114

115 Examples

116 --------

117 >>> matrix = np.array(

118 ... [

119 ... [1.45143932, -0.23651075, -0.21492857],

120 ... [-0.07655377, 1.1762297, -0.09967593],

121 ... [0.00831615, -0.00603245, 0.9977163],

122 ... ]

123 ... )

124 >>> M = LUTOperatorMatrix(matrix)

125 >>> write_LUT_SonySPImtx(M, "My_LUT.spimtx") # doctest: +SKIP

126 """

127

128 matrix, offset = LUT.matrix, LUT.offset

129 offset *= 65535

130

131 array = np.hstack(

132 [

133 np.reshape(matrix, (4, 4))[:3, :3],

134 np.transpose(np.array([offset[:3]])),

135 ]

136 )

137

138 np.savetxt(path, array, fmt=f"%.{decimals}f")

139

140 return True