Coverage for colour/models/rgb/transfer_functions/sony.py: 100%
46 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
« prev ^ index » next coverage.py v7.11.0, created at 2025-11-15 19:01 +1300
1"""
2Sony Encodings
3==============
5Define the *Sony* log encodings.
7- :func:`colour.models.log_encoding_SLog`
8- :func:`colour.models.log_decoding_SLog`
9- :func:`colour.models.log_encoding_SLog2`
10- :func:`colour.models.log_decoding_SLog2`
11- :func:`colour.models.log_encoding_SLog3`
12- :func:`colour.models.log_decoding_SLog3`
14References
15----------
16- :cite:`SonyCorporation2012a` : Sony Corporation. (2012). S-Log2 Technical
17 Paper (pp. 1-9). https://drive.google.com/file/d/\
181Q1RYri6BaxtYYxX0D4zVD6lAmbwmgikc/view?usp=sharing
19- :cite:`SonyCorporationd` : Sony Corporation. (n.d.). Technical Summary
20 for S-Gamut3.Cine/S-Log3 and S-Gamut3/S-Log3 (pp. 1-7).
21 http://community.sony.com/sony/attachments/sony/\
22large-sensor-camera-F5-F55/12359/2/TechnicalSummary_for_S-Gamut3Cine_S-Gamut3_S-Log3_V1_00.pdf
23"""
25from __future__ import annotations
27import numpy as np
29from colour.hints import ( # noqa: TC001
30 Domain1,
31 Range1,
32)
33from colour.models.rgb.transfer_functions import full_to_legal, legal_to_full
34from colour.utilities import (
35 as_float,
36 as_float_array,
37 domain_range_scale,
38 from_range_1,
39 to_domain_1,
40)
42__author__ = "Colour Developers"
43__copyright__ = "Copyright 2013 Colour Developers"
44__license__ = "BSD-3-Clause - https://opensource.org/licenses/BSD-3-Clause"
45__maintainer__ = "Colour Developers"
46__email__ = "colour-developers@colour-science.org"
47__status__ = "Production"
49__all__ = [
50 "log_encoding_SLog",
51 "log_decoding_SLog",
52 "log_encoding_SLog2",
53 "log_decoding_SLog2",
54 "log_encoding_SLog3",
55 "log_decoding_SLog3",
56]
59def log_encoding_SLog(
60 x: Domain1,
61 bit_depth: int = 10,
62 out_normalised_code_value: bool = True,
63 in_reflection: bool = True,
64) -> Range1:
65 """
66 Apply the *Sony S-Log* log encoding opto-electronic transfer function
67 (OETF).
69 Parameters
70 ----------
71 x
72 Reflection or :math:`IRE / 100` input light level :math:`x` to a
73 camera.
74 bit_depth
75 Bit-depth used for conversion.
76 out_normalised_code_value
77 Whether the *Sony S-Log* non-linear data :math:`y` is encoded as
78 normalised code values.
79 in_reflection
80 Whether the light level :math:`x` to a camera is reflection.
82 Returns
83 -------
84 :class:`numpy.ndarray`
85 *Sony S-Log* non-linear encoded data :math:`y`.
87 Notes
88 -----
89 +------------+-----------------------+---------------+
90 | **Domain** | **Scale - Reference** | **Scale - 1** |
91 +============+=======================+===============+
92 | ``x`` | 1 | 1 |
93 +------------+-----------------------+---------------+
95 +------------+-----------------------+---------------+
96 | **Range** | **Scale - Reference** | **Scale - 1** |
97 +============+=======================+===============+
98 | ``y`` | 1 | 1 |
99 +------------+-----------------------+---------------+
101 References
102 ----------
103 :cite:`SonyCorporation2012a`
105 Examples
106 --------
107 >>> log_encoding_SLog(0.18) # doctest: +ELLIPSIS
108 0.3849708...
110 The values of *IRE and CV of S-Log2 @ISO800* table in
111 :cite:`SonyCorporation2012a` are obtained as follows:
113 >>> x = np.array([0, 18, 90]) / 100
114 >>> np.around(log_encoding_SLog(x, 10, False) * 100).astype(np.int_)
115 array([ 3, 38, 65])
116 >>> np.around(log_encoding_SLog(x) * (2**10 - 1)).astype(np.int_)
117 array([ 90, 394, 636])
118 """
120 x = to_domain_1(x)
122 if in_reflection:
123 x = x / 0.9
125 y = np.where(
126 x >= 0,
127 ((0.432699 * np.log10(x + 0.037584) + 0.616596) + 0.03),
128 x * 5 + 0.030001222851889303,
129 )
131 y_cv = full_to_legal(y, bit_depth) if out_normalised_code_value else y
133 return as_float(from_range_1(y_cv))
136def log_decoding_SLog(
137 y: Domain1,
138 bit_depth: int = 10,
139 in_normalised_code_value: bool = True,
140 out_reflection: bool = True,
141) -> Range1:
142 """
143 Apply the *Sony S-Log* log decoding inverse opto-electronic transfer
144 function (OETF).
146 Parameters
147 ----------
148 y
149 *Sony S-Log* non-linear encoded data :math:`y`.
150 bit_depth
151 Bit-depth used for conversion.
152 in_normalised_code_value
153 Whether the *Sony S-Log* non-linear data :math:`y` is encoded as
154 normalised code values.
155 out_reflection
156 Whether the output light level :math:`x` represents reflection.
158 Returns
159 -------
160 :class:`numpy.ndarray`
161 Reflection or :math:`IRE / 100` input light level :math:`x` to a
162 camera.
164 Notes
165 -----
166 +------------+-----------------------+---------------+
167 | **Domain** | **Scale - Reference** | **Scale - 1** |
168 +============+=======================+===============+
169 | ``y`` | 1 | 1 |
170 +------------+-----------------------+---------------+
172 +------------+-----------------------+---------------+
173 | **Range** | **Scale - Reference** | **Scale - 1** |
174 +============+=======================+===============+
175 | ``x`` | 1 | 1 |
176 +------------+-----------------------+---------------+
178 References
179 ----------
180 :cite:`SonyCorporation2012a`
182 Examples
183 --------
184 >>> log_decoding_SLog(0.384970815928670) # doctest: +ELLIPSIS
185 0.1...
186 """
188 y = to_domain_1(y)
190 x = legal_to_full(y, bit_depth) if in_normalised_code_value else y
192 with domain_range_scale("ignore"):
193 x = np.where(
194 y >= log_encoding_SLog(0.0, bit_depth, in_normalised_code_value),
195 10 ** ((x - 0.616596 - 0.03) / 0.432699) - 0.037584,
196 (x - 0.030001222851889303) / 5.0,
197 )
199 if out_reflection:
200 x = x * 0.9
202 return as_float(from_range_1(x))
205def log_encoding_SLog2(
206 x: Domain1,
207 bit_depth: int = 10,
208 out_normalised_code_value: bool = True,
209 in_reflection: bool = True,
210) -> Range1:
211 """
212 Apply the *Sony S-Log2* log encoding opto-electronic transfer function
213 (OETF).
215 Parameters
216 ----------
217 x
218 Reflection or :math:`IRE / 100` input light level :math:`x` to a
219 camera.
220 bit_depth
221 Bit-depth used for conversion.
222 out_normalised_code_value
223 Whether the *Sony S-Log2* non-linear data :math:`y` is encoded as
224 normalised code values.
225 in_reflection
226 Whether the light level :math:`x` to a camera is reflection.
228 Returns
229 -------
230 :class:`numpy.ndarray`
231 *Sony S-Log2* non-linear encoded data :math:`y`.
233 Notes
234 -----
235 +------------+-----------------------+---------------+
236 | **Domain** | **Scale - Reference** | **Scale - 1** |
237 +============+=======================+===============+
238 | ``x`` | 1 | 1 |
239 +------------+-----------------------+---------------+
241 +------------+-----------------------+---------------+
242 | **Range** | **Scale - Reference** | **Scale - 1** |
243 +============+=======================+===============+
244 | ``y`` | 1 | 1 |
245 +------------+-----------------------+---------------+
247 References
248 ----------
249 :cite:`SonyCorporation2012a`
251 Examples
252 --------
253 >>> log_encoding_SLog2(0.18) # doctest: +ELLIPSIS
254 0.3395325...
256 The values of *IRE and CV of S-Log2 @ISO800* table in
257 :cite:`SonyCorporation2012a` are obtained as follows:
259 >>> x = np.array([0, 18, 90]) / 100
260 >>> np.around(log_encoding_SLog2(x, 10, False) * 100).astype(np.int_)
261 array([ 3, 32, 59])
262 >>> np.around(log_encoding_SLog2(x) * (2**10 - 1)).astype(np.int_)
263 array([ 90, 347, 582])
264 """
266 x = as_float_array(x)
268 return log_encoding_SLog(
269 x * 155 / 219, bit_depth, out_normalised_code_value, in_reflection
270 )
273def log_decoding_SLog2(
274 y: Domain1,
275 bit_depth: int = 10,
276 in_normalised_code_value: bool = True,
277 out_reflection: bool = True,
278) -> Range1:
279 """
280 Apply the *Sony S-Log2* log decoding inverse opto-electronic transfer
281 function (OETF).
283 Parameters
284 ----------
285 y
286 *Sony S-Log2* non-linear encoded data :math:`y`.
287 bit_depth
288 Bit-depth used for conversion.
289 in_normalised_code_value
290 Whether the *Sony S-Log2* non-linear data :math:`y` is encoded as
291 normalised code values.
292 out_reflection
293 Whether the output light level :math:`x` represents reflection.
295 Returns
296 -------
297 :class:`numpy.ndarray`
298 Reflection or :math:`IRE / 100` input light level :math:`x` to a
299 camera.
301 Notes
302 -----
303 +------------+-----------------------+---------------+
304 | **Domain** | **Scale - Reference** | **Scale - 1** |
305 +============+=======================+===============+
306 | ``y`` | 1 | 1 |
307 +------------+-----------------------+---------------+
309 +------------+-----------------------+---------------+
310 | **Range** | **Scale - Reference** | **Scale - 1** |
311 +============+=======================+===============+
312 | ``x`` | 1 | 1 |
313 +------------+-----------------------+---------------+
315 References
316 ----------
317 :cite:`SonyCorporation2012a`
319 Examples
320 --------
321 >>> log_decoding_SLog2(0.339532524633774) # doctest: +ELLIPSIS
322 0.1...
323 """
325 return (
326 219
327 * log_decoding_SLog(y, bit_depth, in_normalised_code_value, out_reflection)
328 / 155
329 )
332def log_encoding_SLog3(
333 x: Domain1,
334 bit_depth: int = 10,
335 out_normalised_code_value: bool = True,
336 in_reflection: bool = True,
337) -> Range1:
338 """
339 Apply the *Sony S-Log3* log encoding opto-electronic transfer function
340 (OETF).
342 Parameters
343 ----------
344 x
345 Reflection or :math:`IRE / 100` input light level :math:`x` to a
346 camera.
347 bit_depth
348 Bit-depth used for conversion.
349 out_normalised_code_value
350 Whether the *Sony S-Log3* non-linear data data :math:`y` is encoded as
351 normalised code values.
352 in_reflection
353 Whether the light level :math:`x` to a camera is reflection.
355 Returns
356 -------
357 :class:`numpy.ndarray`
358 *Sony S-Log3* non-linear encoded data :math:`y`.
360 Notes
361 -----
362 +------------+-----------------------+---------------+
363 | **Domain** | **Scale - Reference** | **Scale - 1** |
364 +============+=======================+===============+
365 | ``x`` | 1 | 1 |
366 +------------+-----------------------+---------------+
368 +------------+-----------------------+---------------+
369 | **Range** | **Scale - Reference** | **Scale - 1** |
370 +============+=======================+===============+
371 | ``y`` | 1 | 1 |
372 +------------+-----------------------+---------------+
374 References
375 ----------
376 :cite:`SonyCorporationd`
378 Examples
379 --------
380 >>> log_encoding_SLog3(0.18) # doctest: +ELLIPSIS
381 0.4105571...
383 The values of *S-Log3 10bit code values (18%, 90%)* table in
384 :cite:`SonyCorporationd` are obtained as follows:
386 >>> x = np.array([0, 18, 90]) / 100
387 >>> np.around(log_encoding_SLog3(x, 10, False) * 100).astype(np.int_)
388 array([ 4, 41, 61])
389 >>> np.around(log_encoding_SLog3(x) * (2**10 - 1)).astype(np.int_)
390 array([ 95, 420, 598])
391 """
393 x = to_domain_1(x)
395 if not in_reflection:
396 x = x * 0.9
398 y = np.where(
399 x >= 0.01125000,
400 (420 + np.log10((x + 0.01) / (0.18 + 0.01)) * 261.5) / 1023,
401 (x * (171.2102946929 - 95) / 0.01125000 + 95) / 1023,
402 )
404 y_cv = y if out_normalised_code_value else legal_to_full(y, bit_depth)
406 return as_float(from_range_1(y_cv))
409def log_decoding_SLog3(
410 y: Domain1,
411 bit_depth: int = 10,
412 in_normalised_code_value: bool = True,
413 out_reflection: bool = True,
414) -> Range1:
415 """
416 Apply the *Sony S-Log3* log decoding inverse opto-electronic transfer
417 function (OETF).
419 Parameters
420 ----------
421 y
422 *Sony S-Log3* non-linear encoded data :math:`y`.
423 bit_depth
424 Bit-depth used for conversion.
425 in_normalised_code_value
426 Whether the *Sony S-Log3* non-linear data :math:`y` is encoded as
427 normalised code values.
428 out_reflection
429 Whether the output light level :math:`x` represents reflection.
431 Returns
432 -------
433 :class:`numpy.ndarray`
434 Reflection or :math:`IRE / 100` input light level :math:`x` to a
435 camera.
437 Notes
438 -----
439 +------------+-----------------------+---------------+
440 | **Domain** | **Scale - Reference** | **Scale - 1** |
441 +============+=======================+===============+
442 | ``y`` | 1 | 1 |
443 +------------+-----------------------+---------------+
445 +------------+-----------------------+---------------+
446 | **Range** | **Scale - Reference** | **Scale - 1** |
447 +============+=======================+===============+
448 | ``x`` | 1 | 1 |
449 +------------+-----------------------+---------------+
451 References
452 ----------
453 :cite:`SonyCorporationd`
455 Examples
456 --------
457 >>> log_decoding_SLog3(0.410557184750733) # doctest: +ELLIPSIS
458 0.1...
459 """
461 y = to_domain_1(y)
463 y = y if in_normalised_code_value else full_to_legal(y, bit_depth)
465 x = np.where(
466 y >= 171.2102946929 / 1023,
467 ((10 ** ((y * 1023 - 420) / 261.5)) * (0.18 + 0.01) - 0.01),
468 (y * 1023 - 95) * 0.01125000 / (171.2102946929 - 95),
469 )
471 if not out_reflection:
472 x = x / 0.9
474 return as_float(from_range_1(x))