From 7094fd29100b89f657191f05b4a31b9ffca317b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Thomas?= Date: Wed, 18 May 2022 18:26:00 +0200 Subject: [PATCH 1/6] Aliases for ITU-T H.273 video metadata (#982) This commit adds additional transfer function and primaries defined or referenced to by ITU-T H.273, as well as aliases to their corresponding video metadata tag values (ColourPrimaries, MatrixCoefficients and TransferCharacteristics). --- colour/models/rgb/datasets/ebu_3213_e.py | 64 ++ colour/models/rgb/datasets/itut_h_273.py | 96 +++ .../models/rgb/transfer_functions/__init__.py | 22 + .../rgb/transfer_functions/iec_61966_2.py | 84 +++ .../rgb/transfer_functions/itur_bt_1361.py | 81 +++ .../rgb/transfer_functions/itut_h_273.py | 183 +++++ .../models/rgb/transfer_functions/st_428.py | 68 ++ colour/models/rgb/video.py | 664 ++++++++++++++++++ 8 files changed, 1262 insertions(+) create mode 100644 colour/models/rgb/datasets/ebu_3213_e.py create mode 100644 colour/models/rgb/datasets/itut_h_273.py create mode 100644 colour/models/rgb/transfer_functions/iec_61966_2.py create mode 100644 colour/models/rgb/transfer_functions/itur_bt_1361.py create mode 100644 colour/models/rgb/transfer_functions/itut_h_273.py create mode 100644 colour/models/rgb/transfer_functions/st_428.py create mode 100644 colour/models/rgb/video.py diff --git a/colour/models/rgb/datasets/ebu_3213_e.py b/colour/models/rgb/datasets/ebu_3213_e.py new file mode 100644 index 0000000000..83fa5e2a82 --- /dev/null +++ b/colour/models/rgb/datasets/ebu_3213_e.py @@ -0,0 +1,64 @@ +""" +EBU Tech. 3213-E Primaries and White Point +========================================== + +Defines primaries and white point chromaticity coordinates from EBU Tech. +3213-E (:cite:`EuropeanBroadcastingUnion3213E`). + +References +---------- +- :cite:`EuropeanBroadcastingUnion3213E` : European Broadcasting Union + Tech. 3213-E (1975), Standard for Chromaticity Tolerances For Studio + Monitors. + https://tech.ebu.ch/docs/tech/tech3213.pdf +""" + +from __future__ import annotations + +import numpy as np + +from colour.hints import NDArray +from colour.models.rgb import normalised_primary_matrix + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "PRIMARIES_EBU_3213_E", + "WHITEPOINT_NAME_EBU_3213_E", + "CCS_WHITEPOINT_EBU_3213_E", + "MATRIX_EBU_3213_E_RGB_TO_XYZ", + "MATRIX_XYZ_TO_EBU_3213_E_RGB", +] + +PRIMARIES_EBU_3213_E: NDArray = np.array( + [ + [0.64, 0.33], + [0.29, 0.60], + [0.15, 0.06], + ] +) +"""Colourspace primaries for EBU Tech. 3213-E, as defined in +:cite:`EuropeanBroadcastingUnion3213E`.""" + +WHITEPOINT_NAME_EBU_3213_E: str = "D65" +"""Whitepoint name for EBU Tech. 3213-E, as defined in +:cite:`EuropeanBroadcastingUnion3213E`.""" + +CCS_WHITEPOINT_EBU_3213_E: NDArray = np.array([0.313, 0.329]) +"""Whitepoint chromaticity coordinates for EBU Tech. 3213-E, as defined in +:cite:`EuropeanBroadcastingUnion3213E`.""" + +MATRIX_EBU_3213_E_RGB_TO_XYZ: NDArray = normalised_primary_matrix( + PRIMARIES_EBU_3213_E, CCS_WHITEPOINT_EBU_3213_E +) +"""EBU Tech. 3213-E colourspace to *CIE XYZ* tristimulus values matrix.""" + +MATRIX_XYZ_TO_EBU_3213_E_RGB: NDArray = np.linalg.inv( + MATRIX_EBU_3213_E_RGB_TO_XYZ +) +"""*CIE XYZ* tristimulus values to EBU Tech. 3213-E colourspace matrix.""" diff --git a/colour/models/rgb/datasets/itut_h_273.py b/colour/models/rgb/datasets/itut_h_273.py new file mode 100644 index 0000000000..19230b1602 --- /dev/null +++ b/colour/models/rgb/datasets/itut_h_273.py @@ -0,0 +1,96 @@ +""" +ITU-T H.273 video primaries and whitepoints +=========================================== + +Contains several primaries and whitepoints that are defined in ITU-T H.273 +(:cite:`ITU2021`) but don't belong in another specification or standard. + +References +---------- +- :cite:`ITU2021` : International Telecommunication Union. (2021). Recommendation + ITU-T H.273 - Coding-independent code points for video signal type identification. + https://www.itu.int/rec/T-REC-H.273-202107-I/en +""" + +from __future__ import annotations + +import numpy as np + +from colour.hints import NDArray +from colour.models.rgb import normalised_primary_matrix + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "PRIMARIES_FILM_C", + "WHITEPOINT_NAME_FILM_C", + "CCS_WHITEPOINT_FILM_C", + "MATRIX_FILM_C_RGB_TO_XYZ", + "MATRIX_XYZ_TO_FILM_C_RGB", + "PRIMARIES_ITUT_H273_22", + "WHITEPOINT_NAME_ITUT_H273_22", + "CCS_WHITEPOINT_ITUT_H273_22", + "MATRIX_ITUT_H273_22_RGB_TO_XYZ", + "MATRIX_XYZ_TO_ITUT_H273_22_RGB", +] + +PRIMARIES_FILM_C: NDArray = np.array( + [ + [0.681, 0.319], + [0.243, 0.692], + [0.145, 0.049], + ] +) +"""Colourspace primaries for "colour filters using illuminant C", as defined in +:cite:`ITU2021`.""" + +WHITEPOINT_NAME_FILM_C: str = "C" +"""Whitepoint name for "colour filters using illuminant C", as defined in +:cite:`ITU2021`.""" + +# Note: ITU-T H.273 defines white point C as [0.310, 0.316], while colour +# has a slightly higher precision. +CCS_WHITEPOINT_FILM_C: NDArray = np.array([0.310, 0.316]) +"""Whitepoint chromaticity coordinates for "colour filters using illuminant C", as +defined in :cite:`ITU2021`.""" + +MATRIX_FILM_C_RGB_TO_XYZ: NDArray = normalised_primary_matrix( + PRIMARIES_FILM_C, CCS_WHITEPOINT_FILM_C +) +"""'Colour filters using Illuminant C' colourspace to *CIE XYZ* tristimulus values +matrix.""" + +MATRIX_XYZ_TO_FILM_C_RGB: NDArray = np.linalg.inv(MATRIX_FILM_C_RGB_TO_XYZ) +"""*CIE XYZ* tristimulus values to 'Colour filters using Illuminant C' colourspace +matrix.""" + +PRIMARIES_ITUT_H273_22: NDArray = np.array( + [ + [0.630, 0.340], + [0.295, 0.605], + [0.155, 0.077], + ] +) +"""Colourspace primaries for ColourPrimaries number 22 defined in :cite:`ITU2021`.""" + +WHITEPOINT_NAME_ITUT_H273_22: str = "D65" +"""Whitepoint name for ColourPrimaries number 22 defined in :cite:`ITU2021`.""" + +CCS_WHITEPOINT_ITUT_H273_22: NDArray = np.array([0.3127, 0.3290]) +"""Whitepoint chromaticity coordinates for ColourPrimaries number 22, as defined in +:cite:`ITU2021`.""" + +MATRIX_ITUT_H273_22_RGB_TO_XYZ: NDArray = normalised_primary_matrix( + PRIMARIES_ITUT_H273_22, CCS_WHITEPOINT_ITUT_H273_22 +) +"""ITU-T H.273 ColourPrimaries number 22 to *CIE XYZ* tristimulus values matrix.""" + +MATRIX_XYZ_TO_ITUT_H273_22_RGB: NDArray = np.linalg.inv( + MATRIX_ITUT_H273_22_RGB_TO_XYZ +) +"""*CIE XYZ* tristimulus values to ITU-T H.273 ColourPrimaries number 22 matrix.""" diff --git a/colour/models/rgb/transfer_functions/__init__.py b/colour/models/rgb/transfer_functions/__init__.py index 0d96f133ea..5776934b86 100644 --- a/colour/models/rgb/transfer_functions/__init__.py +++ b/colour/models/rgb/transfer_functions/__init__.py @@ -59,7 +59,15 @@ from .itur_bt_709 import oetf_BT709, oetf_inverse_BT709 from .itur_bt_1886 import eotf_inverse_BT1886, eotf_BT1886 from .itur_bt_2020 import oetf_BT2020, oetf_inverse_BT2020 +from .itur_bt_1361 import oetf_BT1361_extended from .st_2084 import eotf_inverse_ST2084, eotf_ST2084 +from .st_428 import eotf_inverse_ST428_1 +from .itut_h_273 import ( + oetf_linear, + oetf_log, + oetf_log_sqrt, +) +from .iec_61966_2 import oetf_iec_61966_2_unbounded from .itur_bt_2100 import ( oetf_BT2100_PQ, oetf_inverse_BT2100_PQ, @@ -308,6 +316,20 @@ "eotf_inverse_sRGB", "eotf_sRGB", ] +__all__ += [ + "oetf_linear", + "oetf_log", + "oetf_log_sqrt", +] +__all__ += [ + "oetf_iec_61966_2_unbounded", +] +__all__ += [ + "eotf_inverse_ST428_1", +] +__all__ += [ + "oetf_BT1361_extended", +] __all__ += [ "log_encoding_ViperLog", "log_decoding_ViperLog", diff --git a/colour/models/rgb/transfer_functions/iec_61966_2.py b/colour/models/rgb/transfer_functions/iec_61966_2.py new file mode 100644 index 0000000000..10299f9c1c --- /dev/null +++ b/colour/models/rgb/transfer_functions/iec_61966_2.py @@ -0,0 +1,84 @@ +""" +IEC 61966-2 +=========== + +Define transfer functions from *IEC 61966-2* (sRGB, sYCC, xvYCC). + +Note that this function uses the definition from :cite:`ITU2021` since IEC +61966-2 is not publicly accessible. + +References +---------- +- :cite:`ITU2021` : International Telecommunication Union. (2021). + Recommendation ITU-T H.273 - Coding-independent code points for video + signal type identification. + https://www.itu.int/rec/T-REC-H.273-202107-I/en +""" + +import numpy as np + +from colour.models.rgb.transfer_functions.srgb import eotf_inverse_sRGB + +from colour.utilities import ( + as_float, + from_range_1, + to_domain_1, +) + + +def oetf_iec_61966_2_unbounded(Lc): + """ + Define the unbounded opto-electronic transfer functions (OETF) for *IEC 61966-2* + family of transfer functions (*2-1 sRGB*, *2-1 sYCC*, *2-4 xvYCC*). + + Parameters + ---------- + Lc + Scene *Luminance* :math:`Lc`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + Usage in :cite:`ITU2021` is as follows: + + - For IEC 61966-2-1 sRGB (MatrixCoefficients=0), function is only defined + for Lc in [0-1] range. + + - For IEC 61966-2-1 sYCC (MatrixCoefficients=5) and IEC 61966-2-4 xvYCC, + function is defined for any real-valued Lc. + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [-inf, inf] | [-inf, inf] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [-inf, inf] | [-inf, inf] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`ITU2021` + + Examples + -------- + >>> oetf_iec_61966_2_unbounded(0.18) # doctest: +ELLIPSIS + 0.4613561295004... + """ + + Lc = to_domain_1(Lc) + + V = np.where( + Lc >= 0, + eotf_inverse_sRGB(Lc), + -eotf_inverse_sRGB(-Lc), + ) + + return as_float(from_range_1(V)) diff --git a/colour/models/rgb/transfer_functions/itur_bt_1361.py b/colour/models/rgb/transfer_functions/itur_bt_1361.py new file mode 100644 index 0000000000..f5babd85b9 --- /dev/null +++ b/colour/models/rgb/transfer_functions/itur_bt_1361.py @@ -0,0 +1,81 @@ +""" +ITU-R BT.1361 +============= + +Define transfer functions from *ITU-R BT.1361*. + +References +---------- +- :cite:`InternationalTelecommunicationUnion1998` : International + Telecommunication Union. (1998). Recommendation ITU-R BT.1361 - + Worldwide unified colorimetry and related characteristics of + future television and imaging systems + https://www.itu.int/dms_pubrec/itu-r/rec/bt/\ +R-REC-BT.1361-0-199802-W!!PDF-E.pdf +""" +import numpy as np + +from colour.algebra import spow +from colour.utilities import ( + as_float_array, + as_float, +) + + +def oetf_BT1361_extended(L): + """ + Define the opto-electronic transfer functions (OETF) for *ITU-R BT.1361* extended + color gamut. + + Parameters + ---------- + L + Scene *Luminance* :math:`L`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding non-linear primary signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L`` | [-0.25, 1.33] | [-0.25, 1.33] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``E`` | [-1, -1] | [-1, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`InternationalTelecommunicationUnion1998` + + Examples + -------- + >>> oetf_BT1361_extended(0.18) # doctest: +ELLIPSIS + 0.4090077288641... + """ + + L = as_float_array(L) + + E = np.where( + L >= 0, + np.where( + L >= 0.018, + 1.099 * spow(L, 0.45) - 0.099, # [0.018, 1.33] range + 4.500 * L, # [0, 0.018] range + ), + np.where( + L <= -0.0045, + 4.500 * L, # [-0.0045, 0] range + -(spow(1.099 * (-4 * L), 0.45) - 0.099) + / 4, # [-0.25, -0.0045] range + ), + ) + + return as_float(E) diff --git a/colour/models/rgb/transfer_functions/itut_h_273.py b/colour/models/rgb/transfer_functions/itut_h_273.py new file mode 100644 index 0000000000..875cf496ef --- /dev/null +++ b/colour/models/rgb/transfer_functions/itut_h_273.py @@ -0,0 +1,183 @@ +""" +ITU-T H.273 video transfer functions +==================================== + +Contains several transfer functions that are defined in ITU-T H.273 +(:cite:`ITU2021`) but don't belong in another specification or standard. + +References +---------- +- :cite:`ITU2021` : International Telecommunication Union. (2021). Recommendation + ITU-T H.273 - Coding-independent code points for video signal type identification. + https://www.itu.int/rec/T-REC-H.273-202107-I/en +""" + +import numpy as np + +from colour.utilities import ( + as_float, + from_range_1, + to_domain_1, +) + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "oetf_linear", + "oetf_log", + "oetf_log_sqrt", +] + + +def oetf_linear(Lc): + """ + Linear opto-electronic transfer function (OETF) defined in ITU-T H.273. + + Parameters + ---------- + Lc + Scene *Luminance* :math:`Lc`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`ITU2021` + + Examples + -------- + >>> oetf_linear(0.18) # doctest: +ELLIPSIS + 0.17999999... + """ + + Lc = to_domain_1(Lc) + + V = Lc + + return as_float(from_range_1(V)) + + +def oetf_log(Lc): + """ + Define the opto-electronic transfer functions (OETF) for Logarithmic + encoding (100:1 range) defined in ITU-T H.273. + + Parameters + ---------- + Lc + Scene *Luminance* :math:`Lc`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`ITU2021` + + Examples + -------- + >>> oetf_log(0.18) # doctest: +ELLIPSIS + 0.6276362525516... + """ + + Lc = to_domain_1(Lc) + + V = np.where( + Lc >= 0.01, + # Lc in [0.01, 1] range + 1.0 + np.log10(Lc) / 2.0, + # Lc in [0, 0.01] range + 0.0, + ) + + return as_float(from_range_1(V)) + + +def oetf_log_sqrt(Lc): + """ + Define the opto-electronic transfer functions (OETF) for Logarithmic + encoding (100*Sqrt(10):1 range) defined in ITU-T H.273. + + Parameters + ---------- + Lc + Scene *Luminance* :math:`Lc`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`ITU2021` + + Examples + -------- + >>> oetf_log_sqrt(0.18) # doctest: +ELLIPSIS + 0.702109002041... + """ + + Lc = to_domain_1(Lc) + + V = np.where( + Lc >= np.sqrt(10) / 1000, + # Lc in [0.01, 1] range + 1.0 + np.log10(Lc) / 2.5, + # Lc in [0, 0.01] range + 0.0, + ) + + return as_float(from_range_1(V)) diff --git a/colour/models/rgb/transfer_functions/st_428.py b/colour/models/rgb/transfer_functions/st_428.py new file mode 100644 index 0000000000..64b660631d --- /dev/null +++ b/colour/models/rgb/transfer_functions/st_428.py @@ -0,0 +1,68 @@ +""" +SMPTE ST 428-1 (2019) +===================== + +Defines *SMPTE ST 428-1 (2019)* inverse electro-optical transfer function (EOTF). + +Note that this function uses the definition from :cite:`ITU2021` since SMPTE ST +428-1 is not publicly accessible. + +References +---------- +- :cite:`ITU2021` : International Telecommunication Union. (2021). + Recommendation ITU-T H.273 - Coding-independent code points for video + signal type identification. + https://www.itu.int/rec/T-REC-H.273-202107-I/en +""" + +from colour.algebra import spow +from colour.utilities import ( + as_float, + from_range_1, + to_domain_1, +) + + +def eotf_inverse_ST428_1(Lo): + """ + Define the *SMPTE ST 428-1 (2019)* inverse electro-optical transfer function (EOTF). + + Parameters + ---------- + Lo + Output display *Luminance* :math:`Lo` of the image. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`ITU2021` + + Examples + -------- + >>> eotf_inverse_ST428_1(0.18) # doctest: +ELLIPSIS + 0.5000483377172... + """ + + Lo = to_domain_1(Lo) + + V = spow(48 * Lo / 52.37, 1 / 2.6) + + return as_float(from_range_1(V)) diff --git a/colour/models/rgb/video.py b/colour/models/rgb/video.py new file mode 100644 index 0000000000..e09660a015 --- /dev/null +++ b/colour/models/rgb/video.py @@ -0,0 +1,664 @@ +""" +ITU-T H.273 video colour metadata +================================= + +Defines aliases to a set of standard colour primaries, transfer functions and +YUV to RGB matrix coefficients used in video metadata. + +These metadata were historically defined in ISO/IEC 23001-8 (:cite:`ISO2013`) then +superseded and duplicated by other standards (among others: :cite:`ISO2020`, +:cite:`ISO2021`, :cite:`ITU2021`). They are widely in use to define color-related +properties in video encoding and decoding software libraries, including ffmpeg. + +References +---------- +- :cite:`ITU2021` : International Telecommunication Union. (2021). + Recommendation ITU-T H.273 - Coding-independent code points for video + signal type identification. + https://www.itu.int/rec/T-REC-H.273-202107-I/en +- :cite:`ISO2013` : International Organization for Standardization. (2013). + INTERNATIONAL STANDARD ISO/IEC 23001-8:2013 - Information technology - MPEG + systems technologies - Part 8: Coding-independent code points, §7.1 "Colour + primaries" +- :cite:`ISO2021` : International Organization for Standardization. (2021). + INTERNATIONAL STANDARD ISO/IEC 23091-2:2021 - Information technology - + Coding-independent code points - Part 2: Video, §8.1 "Colour primaries" +- :cite:`ISO2020` : International Organization for Standardization. (2020). + INTERNATIONAL STANDARD ISO/IEC 14496-10:2020 - Information technology - + Coding of audio-visual objects - Part 10: Advanced video coding" +""" + +import functools +import enum + +import numpy as np + +import colour + +import colour.models.rgb.datasets.itut_h_273 +from colour.models.rgb.transfer_functions.gamma import gamma_function +from colour.models.rgb.transfer_functions.itur_bt_709 import oetf_BT709 +from colour.models.rgb.transfer_functions.itur_bt_1886 import eotf_BT1886 +from colour.models.rgb.transfer_functions.itur_bt_2020 import oetf_BT2020 +from colour.models.rgb.transfer_functions.itur_bt_1361 import ( + oetf_BT1361_extended, +) +from colour.models.rgb.transfer_functions.itur_bt_2100 import oetf_BT2100_HLG +from colour.models.rgb.transfer_functions.st_428 import eotf_inverse_ST428_1 +from colour.models.rgb.transfer_functions.st_2084 import eotf_inverse_ST2084 +from colour.models.rgb.transfer_functions.iec_61966_2 import ( + oetf_iec_61966_2_unbounded, +) +from colour.models.rgb.transfer_functions.itur_bt_601 import oetf_BT601 +from colour.models.rgb.transfer_functions.smpte_240m import oetf_SMPTE240M +from colour.models.rgb.transfer_functions.itut_h_273 import ( + oetf_linear, + oetf_log, + oetf_log_sqrt, +) + +__all__ = [ + "CCS_WHITEPOINTS_ISO14496_10", + "CCS_WHITEPOINTS_ISO23001_8", + "CCS_WHITEPOINTS_ISO23091_2", + "CCS_WHITEPOINTS_ITU_T_H273", + "ColourPrimaries_ISO14496_10", + "ColourPrimaries_ISO23001_8", + "ColourPrimaries_ISO23091_2", + "ColourPrimaries_ITU_T_H273", + "MATRICES_ISO14496_10_RGB_TO_XYZ", + "MATRICES_ISO23001_8_RGB_TO_XYZ", + "MATRICES_ISO23091_2_RGB_TO_XYZ", + "MATRICES_ITU_T_H273_RGB_TO_XYZ", + "MATRICES_XYZ_TO_ISO14496_10_RGB", + "MATRICES_XYZ_TO_ISO23001_8_RGB", + "MATRICES_XYZ_TO_ISO23091_2_RGB", + "MATRICES_XYZ_TO_ITU_T_H273_RGB", + "MatrixCoefficients_ISO14496_10", + "MatrixCoefficients_ISO23001_8", + "MatrixCoefficients_ISO23091_2", + "MatrixCoefficients_ITU_T_H273", + "PRIMARIES_ISO14496_10", + "PRIMARIES_ISO23001_8", + "PRIMARIES_ISO23091_2", + "PRIMARIES_ITU_T_H273", + "TRANSFER_FUNCTIONS_ISO14496_10", + "TRANSFER_FUNCTIONS_ISO23001_8", + "TRANSFER_FUNCTIONS_ISO23091_2", + "TRANSFER_FUNCTIONS_ITU_T_H273", + "TransferCharacteristics_ISO14496_10", + "TransferCharacteristics_ISO23001_8", + "TransferCharacteristics_ISO23091_2", + "TransferCharacteristics_ITU_T_H273", + "WEIGHTS_YCBCR_ISO14496_10", + "WEIGHTS_YCBCR_ISO23001_8", + "WEIGHTS_YCBCR_ISO23091_2", + "WEIGHTS_YCBCR_ITU_T_H273", + "WHITEPOINTS_NAMES_ISO14496_10", + "WHITEPOINTS_NAMES_ISO23001_8", + "WHITEPOINTS_NAMES_ISO23091_2", + "WHITEPOINTS_NAMES_ITU_T_H273", + "eotf_BT1886", + "eotf_inverse_ST2084", + "eotf_inverse_ST428_1", + "eotf_inverse_gamma22", + "eotf_inverse_gamma28", + "oetf_BT1361_extended", + "oetf_BT2020_10bit", + "oetf_BT2020_12bit", + "oetf_BT2100_HLG", + "oetf_BT601", + "oetf_BT709", + "oetf_SMPTE240M", + "oetf_iec_61966_2_1", + "oetf_iec_61966_2_4", + "oetf_linear", + "oetf_log", + "oetf_log_sqrt", +] + +oetf_BT2020_12bit = functools.partial(oetf_BT2020, is_12_bits_system=True) +oetf_BT2020_10bit = functools.partial(oetf_BT2020, is_12_bits_system=False) +eotf_inverse_gamma22 = functools.partial(gamma_function, exponent=1 / 2.2) +eotf_inverse_gamma28 = functools.partial(gamma_function, exponent=1 / 2.8) +oetf_iec_61966_2_4 = oetf_iec_61966_2_unbounded +oetf_iec_61966_2_1 = oetf_iec_61966_2_unbounded + + +@enum.unique +class ColourPrimaries_ITU_T_H273(enum.IntEnum): + """ColourPrimaries tags as defined in ITU-T H.273 § 8.1. + + The enumeration members use the same names as ffmpeg `AVCOL_PRI_*` constants. + """ + + BT709 = 1 # also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + BT470M = 4 # also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + # also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + BT470BG = 5 + + SMPTE170M = ( + 6 # also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + ) + SMPTE240M = 7 # functionally identical to above + FILM = 8 # colour filters using Illuminant C + BT2020 = 9 # ITU-R BT2020 + SMPTE428 = 10 # SMPTE ST 428-1 (CIE 1931 XYZ) + SMPTE431 = 11 # SMPTE ST 431-2 (2011) / DCI P3 + SMPTE432 = 12 # SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + + # Note: This corresponds to "AVCOL_PRI_EBU3213" in ffmpeg, but neither ITU-T + # H.273:2021 nor ISO/IEC 23091-2:2021 contain the same values as EBU Tech. 3213, nor + # do they refer to it directly (ColourPrimaries=22 contains the remark "No + # corresponding industry specification identified" in both cases). + # + # Since both ISO/IEC 23001-8:2013 and 14497-10:2020 do refer to EBU Tech 3213-E + # (1975) but contain the same primaries and whitepoint as the 2021 revisions, this + # is likely a error in the initial standards that was later discovered and + # corrected. + UNKNOWN22 = 22 + + +@enum.unique +class TransferCharacteristics_ITU_T_H273(enum.IntEnum): + """TransferCharacteristics tags as defined in ITU-T H.273 § 8.2. + + The enumeration members use the same names as ffmpeg `AVCOL_TRC_*` constants. + """ + + BT709 = 1 # also ITU-R BT1361 + GAMMA22 = 4 # also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM + GAMMA28 = 5 # also ITU-R BT470BG + + # also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC + SMPTE170M = 6 + + SMPTE240M = 7 + LINEAR = 8 # "Linear transfer characteristics" + LOG = 9 # "Logarithmic transfer characteristic (100:1 range)" + + # "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" + LOG_SQRT = 10 + + IEC61966_2_4 = 11 # IEC 61966-2-4 + BT1361_ECG = 12 # ITU-R BT1361 Extended Colour Gamut + IEC61966_2_1 = 13 # IEC 61966-2-1 (sRGB or sYCC) + BT2020_10 = 14 # ITU-R BT2020 for 10-bit system + BT2020_12 = 15 # ITU-R BT2020 for 12-bit system + SMPTE2084 = 16 # SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems + SMPTE428 = 17 # SMPTE ST 428-1 + ARIB_STD_B67 = 18 # ARIB STD-B67, known as "Hybrid log-gamma" + + +@enum.unique +class MatrixCoefficients_ITU_T_H273(enum.IntEnum): + """MatrixCoefficients tags as defined in ITU-T H.273 § 8.3 + + The enumeration members use the same names as ffmpeg `AVCOL_SPC_*` constants. + """ + + RGB = 0 # order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) + BT709 = ( + 1 # also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B + ) + FCC = 4 # FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + # also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + # / IEC 61966-2-4 xvYCC601 + BT470BG = 5 + + SMPTE170M = ( + 6 # also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + ) + SMPTE240M = 7 # functionally identical to above + YCGCO = 8 # Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 + BT2020_NCL = 9 # ITU-R BT2020 non-constant luminance system + BT2020_CL = 10 # ITU-R BT2020 constant luminance system + SMPTE2085 = 11 # SMPTE 2085, Y'D'zD'x + CHROMA_DERIVED_NCL = ( + 12 # Chromaticity-derived non-constant luminance system + ) + CHROMA_DERIVED_CL = 13 # Chromaticity-derived constant luminance system + ICTCP = 14 # ITU-R BT.2100-0, ICtCp + + +PRIMARIES_ITU_T_H273 = { + # 0: Reserved for future use + # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B + ColourPrimaries_ITU_T_H273.BT709: ( + colour.models.rgb.datasets.itur_bt_709.PRIMARIES_BT709 + ), + # 2: Unspecified + # 3: Reserved for future use + # 4: ITU-R BT.470-6 System M + ColourPrimaries_ITU_T_H273.BT470M: ( + colour.models.rgb.datasets.itur_bt_470.PRIMARIES_BT470_525 + ), + # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 + ColourPrimaries_ITU_T_H273.BT470BG: ( + colour.models.rgb.datasets.itur_bt_470.PRIMARIES_BT470_625 + ), + # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) + ColourPrimaries_ITU_T_H273.SMPTE170M: ( + colour.models.rgb.datasets.smpte_240m.PRIMARIES_SMPTE_240M + ), + # 7: SMPTE 240M (same as 6) + ColourPrimaries_ITU_T_H273.SMPTE240M: ( + colour.models.rgb.datasets.smpte_240m.PRIMARIES_SMPTE_240M + ), + # 8: Generic film (colour filters using Illuminant C) + ColourPrimaries_ITU_T_H273.FILM: ( + colour.models.rgb.datasets.itut_h_273.PRIMARIES_FILM_C + ), + # 9: ITU-R BT.2020 + ColourPrimaries_ITU_T_H273.BT2020: ( + colour.models.rgb.datasets.itur_bt_2020.PRIMARIES_BT2020 + ), + # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) + ColourPrimaries_ITU_T_H273.SMPTE428: ( + colour.models.rgb.datasets.dcdm_xyz.PRIMARIES_DCDM_XYZ + ), + # 11: SMPTE RP 431-2 (2011) + ColourPrimaries_ITU_T_H273.SMPTE431: ( + colour.models.rgb.datasets.dci_p3.PRIMARIES_DCI_P3 + ), + # 12: SMPTE EG 432-1 (2010) + ColourPrimaries_ITU_T_H273.SMPTE432: ( + colour.models.rgb.datasets.p3_d65.PRIMARIES_P3_D65 + ), + # 13-21: Reserved for future use + # 22: No corresponding industry specification + ColourPrimaries_ITU_T_H273.UNKNOWN22: ( + colour.models.rgb.datasets.itut_h_273.PRIMARIES_ITUT_H273_22 + ), + # 23-255: Reserved for future use +} +"""ColourPrimaries tag to colour primaries mapping defined in ITU-T H.273 § +8.1""" + + +CCS_WHITEPOINTS_ITU_T_H273 = { + # 0: Reserved for future use + # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B + ColourPrimaries_ITU_T_H273.BT709: ( + colour.models.rgb.datasets.itur_bt_709.CCS_WHITEPOINT_BT709 + ), + # 2: Unspecified + # 3: Reserved for future use + # 4: ITU-R BT.470-6 System M + ColourPrimaries_ITU_T_H273.BT470M: ( + # Note: ITU-T H.273 defines white point C as [0.310, 0.316], while this + # has a slightly higher precision. + colour.models.rgb.datasets.itur_bt_470.CCS_WHITEPOINT_BT470_525 + ), + # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 + ColourPrimaries_ITU_T_H273.BT470BG: ( + colour.models.rgb.datasets.itur_bt_470.CCS_WHITEPOINT_BT470_625 + ), + # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) + ColourPrimaries_ITU_T_H273.SMPTE170M: ( + colour.models.rgb.datasets.smpte_240m.CCS_WHITEPOINT_SMPTE_240M + ), + # 7: SMPTE 240M (same as 6) + ColourPrimaries_ITU_T_H273.SMPTE240M: ( + colour.models.rgb.datasets.smpte_240m.CCS_WHITEPOINT_SMPTE_240M + ), + # 8: Generic film (colour filters using Illuminant C) + ColourPrimaries_ITU_T_H273.FILM: ( + colour.models.rgb.datasets.itut_h_273.CCS_WHITEPOINT_FILM_C + ), + # 9: ITU-R BT.2020 + ColourPrimaries_ITU_T_H273.BT2020: ( + colour.models.rgb.datasets.itur_bt_2020.CCS_WHITEPOINT_BT2020 + ), + # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) + ColourPrimaries_ITU_T_H273.SMPTE428: ( + colour.models.rgb.datasets.dcdm_xyz.CCS_WHITEPOINT_DCDM_XYZ + ), + # 11: SMPTE RP 431-2 (2011) + ColourPrimaries_ITU_T_H273.SMPTE431: ( + colour.models.rgb.datasets.dci_p3.CCS_WHITEPOINT_DCI_P3 + ), + # 12: SMPTE EG 432-1 (2010) + ColourPrimaries_ITU_T_H273.SMPTE432: ( + colour.models.rgb.datasets.p3_d65.CCS_WHITEPOINT_P3_D65 + ), + # 13-21: Reserved for future use + # 22: No corresponding industry specification + ColourPrimaries_ITU_T_H273.UNKNOWN22: ( + colour.models.rgb.datasets.itut_h_273.CCS_WHITEPOINT_ITUT_H273_22 + ), + # 23-255: Reserved for future use +} +"""ColourPrimaries tag to whitepoint chromaticity coordinates mapping defined +in ITU-T H.273 § 8.1""" + + +WHITEPOINTS_NAMES_ITU_T_H273 = { + # 0: Reserved for future use + # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B + ColourPrimaries_ITU_T_H273.BT709: ( + colour.models.rgb.datasets.itur_bt_709.WHITEPOINT_NAME_BT709 + ), + # 2: Unspecified + # 3: Reserved for future use + # 4: ITU-R BT.470-6 System M + ColourPrimaries_ITU_T_H273.BT470M: ( + colour.models.rgb.datasets.itur_bt_470.WHITEPOINT_NAME_BT470_525 + ), + # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 + ColourPrimaries_ITU_T_H273.BT470BG: ( + colour.models.rgb.datasets.itur_bt_470.WHITEPOINT_NAME_BT470_625 + ), + # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) + ColourPrimaries_ITU_T_H273.SMPTE170M: ( + colour.models.rgb.datasets.smpte_240m.WHITEPOINT_NAME_SMPTE_240M + ), + # 7: SMPTE 240M (same as 6) + ColourPrimaries_ITU_T_H273.SMPTE240M: ( + colour.models.rgb.datasets.smpte_240m.WHITEPOINT_NAME_SMPTE_240M + ), + # 8: Generic film (colour filters using Illuminant C) + ColourPrimaries_ITU_T_H273.FILM: ( + colour.models.rgb.datasets.itut_h_273.WHITEPOINT_NAME_FILM_C + ), + # 9: ITU-R BT.2020 + ColourPrimaries_ITU_T_H273.BT2020: ( + colour.models.rgb.datasets.itur_bt_2020.WHITEPOINT_NAME_BT2020 + ), + # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) + ColourPrimaries_ITU_T_H273.SMPTE428: ( + colour.models.rgb.datasets.dcdm_xyz.WHITEPOINT_NAME_DCDM_XYZ + ), + # 11: SMPTE RP 431-2 (2011) + ColourPrimaries_ITU_T_H273.SMPTE431: ( + colour.models.rgb.datasets.dci_p3.WHITEPOINT_NAME_DCI_P3 + ), + # 12: SMPTE EG 432-1 (2010) + ColourPrimaries_ITU_T_H273.SMPTE432: ( + colour.models.rgb.datasets.p3_d65.WHITEPOINT_NAME_P3_D65 + ), + # 13-21: Reserved for future use + # 22: No corresponding industry specification + ColourPrimaries_ITU_T_H273.UNKNOWN22: ( + colour.models.rgb.datasets.itut_h_273.WHITEPOINT_NAME_ITUT_H273_22 + ), + # 23-255: Reserved for future use +} +"""ColourPrimaries tag to whitepoint names mapping defined in ITU-T H.273 § +8.1""" + + +MATRICES_ITU_T_H273_RGB_TO_XYZ = { + # 0: Reserved for future use + # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B + ColourPrimaries_ITU_T_H273.BT709: ( + colour.models.rgb.datasets.itur_bt_709.MATRIX_BT709_TO_XYZ + ), + # 2: Unspecified + # 3: Reserved for future use + # 4: ITU-R BT.470-6 System M + ColourPrimaries_ITU_T_H273.BT470M: ( + colour.models.rgb.datasets.itur_bt_470.MATRIX_BT470_525_TO_XYZ + ), + # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 + ColourPrimaries_ITU_T_H273.BT470BG: ( + colour.models.rgb.datasets.itur_bt_470.MATRIX_BT470_625_TO_XYZ + ), + # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) + ColourPrimaries_ITU_T_H273.SMPTE170M: ( + colour.models.rgb.datasets.smpte_240m.MATRIX_SMPTE_240M_TO_XYZ + ), + # 7: SMPTE 240M (same as 6) + ColourPrimaries_ITU_T_H273.SMPTE240M: ( + colour.models.rgb.datasets.smpte_240m.MATRIX_SMPTE_240M_TO_XYZ + ), + # 8: Generic film (colour filters using Illuminant C) + ColourPrimaries_ITU_T_H273.FILM: ( + colour.models.rgb.datasets.itut_h_273.MATRIX_FILM_C_RGB_TO_XYZ + ), + # 9: ITU-R BT.2020 + ColourPrimaries_ITU_T_H273.BT2020: ( + colour.models.rgb.datasets.itur_bt_2020.MATRIX_BT2020_TO_XYZ + ), + # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) + ColourPrimaries_ITU_T_H273.SMPTE428: ( + colour.models.rgb.datasets.dcdm_xyz.MATRIX_DCDM_XYZ_TO_XYZ + ), + # 11: SMPTE RP 431-2 (2011) + ColourPrimaries_ITU_T_H273.SMPTE431: ( + colour.models.rgb.datasets.dci_p3.MATRIX_DCI_P3_TO_XYZ + ), + # 12: SMPTE EG 432-1 (2010) + ColourPrimaries_ITU_T_H273.SMPTE432: ( + colour.models.rgb.datasets.p3_d65.MATRIX_P3_D65_TO_XYZ + ), + # 13-21: Reserved for future use + # 22: No corresponding industry specification + ColourPrimaries_ITU_T_H273.UNKNOWN22: ( + colour.models.rgb.datasets.itut_h_273.MATRIX_ITUT_H273_22_RGB_TO_XYZ + ), + # 23-255: Reserved for future use +} +"""ColourPrimaries tag to RGB to XYZ matrices determined from primaries and +whitepoints defined in ITU-T H.273 § 8.1""" + + +MATRICES_XYZ_TO_ITU_T_H273_RGB = { + # 0: Reserved for future use + # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B + ColourPrimaries_ITU_T_H273.BT709: ( + colour.models.rgb.datasets.itur_bt_709.MATRIX_XYZ_TO_BT709 + ), + # 2: Unspecified + # 3: Reserved for future use + # 4: ITU-R BT.470-6 System M + ColourPrimaries_ITU_T_H273.BT470M: ( + colour.models.rgb.datasets.itur_bt_470.MATRIX_XYZ_TO_BT470_525 + ), + # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 + ColourPrimaries_ITU_T_H273.BT470BG: ( + colour.models.rgb.datasets.itur_bt_470.MATRIX_XYZ_TO_BT470_625 + ), + # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) + ColourPrimaries_ITU_T_H273.SMPTE170M: ( + colour.models.rgb.datasets.smpte_240m.MATRIX_XYZ_TO_SMPTE_240M + ), + # 7: SMPTE 240M (same as 6) + ColourPrimaries_ITU_T_H273.SMPTE240M: ( + colour.models.rgb.datasets.smpte_240m.MATRIX_XYZ_TO_SMPTE_240M + ), + # 8: Generic film (colour filters using Illuminant C) + ColourPrimaries_ITU_T_H273.FILM: ( + colour.models.rgb.datasets.itut_h_273.MATRIX_XYZ_TO_FILM_C_RGB + ), + # 9: ITU-R BT.2020 + ColourPrimaries_ITU_T_H273.BT2020: ( + colour.models.rgb.datasets.itur_bt_2020.MATRIX_XYZ_TO_BT2020 + ), + # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) + ColourPrimaries_ITU_T_H273.SMPTE428: ( + colour.models.rgb.datasets.dcdm_xyz.MATRIX_XYZ_TO_DCDM_XYZ + ), + # 11: SMPTE RP 431-2 (2011) + ColourPrimaries_ITU_T_H273.SMPTE431: ( + colour.models.rgb.datasets.dci_p3.MATRIX_XYZ_TO_DCI_P3 + ), + # 12: SMPTE EG 432-1 (2010) + ColourPrimaries_ITU_T_H273.SMPTE432: ( + colour.models.rgb.datasets.p3_d65.MATRIX_XYZ_TO_P3_D65 + ), + # 13-21: Reserved for future use + # 22: No corresponding industry specification + ColourPrimaries_ITU_T_H273.UNKNOWN22: ( + colour.models.rgb.datasets.itut_h_273.MATRIX_XYZ_TO_ITUT_H273_22_RGB + ), + # 23-255: Reserved for future use +} +"""ColourPrimaries tag to XYZ to RGB matrices determined from primaries and +whitepoints defined in ITU-T H.273 § 8.1""" + + +TRANSFER_FUNCTIONS_ITU_T_H273 = { + # 0: Reserved for future use + # 1: ITU-R BT.709 + TransferCharacteristics_ITU_T_H273.BT709: oetf_BT709, + # 2: Unspecified + # 3: Reserved for future use + # 4: Gamma 2.2 (also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM) (this is + # an inverse-EOTF) + TransferCharacteristics_ITU_T_H273.GAMMA22: eotf_inverse_gamma22, + # 5: Gamma 2.8 (also ITU-R BT470BG) (this is an inverse-EOTF) + TransferCharacteristics_ITU_T_H273.GAMMA28: eotf_inverse_gamma28, + # 6: SMPTE 170M (also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / + # ITU-R BT1700 NTSC) + TransferCharacteristics_ITU_T_H273.SMPTE170M: oetf_BT601, + # 7: SMPTE 240M + TransferCharacteristics_ITU_T_H273.SMPTE240M: oetf_SMPTE240M, + # 8: Linear transfer characteristics (this is an OETF) + TransferCharacteristics_ITU_T_H273.LINEAR: oetf_linear, + # 9: Logarithmic transfer characteristic (100:1 range) + TransferCharacteristics_ITU_T_H273.LOG: oetf_log, + # 10: Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range) + TransferCharacteristics_ITU_T_H273.LOG_SQRT: oetf_log_sqrt, + # 11: IEC 61966-2-4 + TransferCharacteristics_ITU_T_H273.IEC61966_2_4: oetf_iec_61966_2_4, + # 12: ITU-R BT1361 Extended Colour Gamut + TransferCharacteristics_ITU_T_H273.BT1361_ECG: oetf_BT1361_extended, + # 13: IEC 61966-2-1 (sRGB or sYCC) + TransferCharacteristics_ITU_T_H273.IEC61966_2_1: oetf_iec_61966_2_1, + # 14: ITU-R BT2020 for 10-bit system + TransferCharacteristics_ITU_T_H273.BT2020_10: oetf_BT2020_10bit, + # 15: ITU-R BT2020 for 12-bit system + TransferCharacteristics_ITU_T_H273.BT2020_12: oetf_BT2020_12bit, + # 16: SMPTE ST 2084 (PQ, Perceptual Quantizer) for 10-, 12-, 14- and 16-bit systems + TransferCharacteristics_ITU_T_H273.SMPTE2084: eotf_inverse_ST2084, + # 17: SMPTE ST 428-1 + TransferCharacteristics_ITU_T_H273.SMPTE428: eotf_inverse_ST428_1, + # 18: ARIB STD B67, also ITU-R BT.2100 HLG (Hybrid Log-Gamma), in [0-1] range + TransferCharacteristics_ITU_T_H273.ARIB_STD_B67: oetf_BT2100_HLG, +} +"""Mapping from TransferCharacteristics tag to transfer functions defined in +ITU-T H.273 § 8.2 + +Note that the standard contains both OETFs or inverse-EOTFs.""" + + +WEIGHTS_YCBCR_ITU_T_H273 = {} +"""K_R and K_B coefficients for YCbCr conversion defined in ITU-T H.273 §8.3 + +Notes +----- + +Several values of MatrixCoefficients don't directly correspond to K_R and +K_B values but instead have separate equations, which are not included in +this mapping: + +- MatrixCoefficients_ITU_T_H273.YCGCO +- MatrixCoefficients_ITU_T_H273.SMPTE2085 +- MatrixCoefficients_ITU_T_H273.CHROMA_DERIVED_NCL +- MatrixCoefficients_ITU_T_H273.CHROMA_DERIVED_CL +- MatrixCoefficients_ITU_T_H273.ICTCP +""" + +WEIGHTS_YCBCR_ITU_T_H273[MatrixCoefficients_ITU_T_H273.RGB] = np.array( + [1.0, 1.0] +) +WEIGHTS_YCBCR_ITU_T_H273[ + MatrixCoefficients_ITU_T_H273.BT709 +] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.709"] +WEIGHTS_YCBCR_ITU_T_H273[MatrixCoefficients_ITU_T_H273.FCC] = np.array( + [0.30, 0.11] +) +WEIGHTS_YCBCR_ITU_T_H273[ + MatrixCoefficients_ITU_T_H273.BT470BG +] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.601"] +WEIGHTS_YCBCR_ITU_T_H273[ + MatrixCoefficients_ITU_T_H273.SMPTE170M +] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.601"] +# Note: The precision is different from WEIGHTS_YCBCR["ITU-R SMPTE-240M"] +WEIGHTS_YCBCR_ITU_T_H273[MatrixCoefficients_ITU_T_H273.SMPTE240M] = np.array( + [0.212, 0.087] +) +WEIGHTS_YCBCR_ITU_T_H273[ + MatrixCoefficients_ITU_T_H273.BT2020_NCL +] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.2020"] +WEIGHTS_YCBCR_ITU_T_H273[ + MatrixCoefficients_ITU_T_H273.BT2020_CL +] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.2020"] + + +# Aliases for ISO/IEC 23091-2:2021. Verified to be functionally identical to ITU-T H.273 +# for the values defined here. +ColourPrimaries_ISO23091_2 = ColourPrimaries_ITU_T_H273 +TransferCharacteristics_ISO23091_2 = TransferCharacteristics_ITU_T_H273 +MatrixCoefficients_ISO23091_2 = MatrixCoefficients_ITU_T_H273 +PRIMARIES_ISO23091_2 = PRIMARIES_ITU_T_H273 +WHITEPOINTS_NAMES_ISO23091_2 = WHITEPOINTS_NAMES_ITU_T_H273 +CCS_WHITEPOINTS_ISO23091_2 = CCS_WHITEPOINTS_ITU_T_H273 +MATRICES_ISO23091_2_RGB_TO_XYZ = MATRICES_ITU_T_H273_RGB_TO_XYZ +MATRICES_XYZ_TO_ISO23091_2_RGB = MATRICES_XYZ_TO_ITU_T_H273_RGB +TRANSFER_FUNCTIONS_ISO23091_2 = TRANSFER_FUNCTIONS_ITU_T_H273 +WEIGHTS_YCBCR_ISO23091_2 = WEIGHTS_YCBCR_ITU_T_H273 + + +@enum.unique +class ColourPrimaries_ISO23001_8(enum.IntEnum): + """ColourPrimaries tags as defined in ISO/IEC 23001-8:2013 § 7.1. + + The enumeration members use the same names as ffmpeg `AVCOL_PRI_*` constants. + """ + + BT709 = 1 # also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B + BT470M = 4 # also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) + + # also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM + BT470BG = 5 + + SMPTE170M = ( + 6 # also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC + ) + SMPTE240M = 7 # functionally identical to above + FILM = 8 # colour filters using Illuminant C + BT2020 = 9 # ITU-R BT2020 + SMPTE428 = 10 # SMPTE ST 428-1 (CIE 1931 XYZ) + SMPTE431 = 11 # SMPTE ST 431-2 (2011) / DCI P3 + SMPTE432 = 12 # SMPTE ST 432-1 (2010) / P3 D65 / Display P3 + + # Note: This corresponds to "AVCOL_PRI_EBU3213" in ffmpeg, but neither ITU-T + # H.273:2021 nor ISO/IEC 23091-2:2021 contain the same values as EBU Tech. 3213, nor + # do they refer to it directly (ColourPrimaries=22 contains the remark "No + # corresponding industry specification identified" in both cases). + # + # Since both ISO/IEC 23001-8:2013 and 14497-10:2020 do refer to EBU Tech 3213-E + # (1975) but contain the same primaries and whitepoint as the 2021 revisions, this + # is likely a error in the initial standards that was later discovered and + # corrected. + EBU3213 = 22 + + +# Aliases for ISO/IEC 23001-8:2013. Verified to be functionally identical to ITU-T H.273 +# for the values defined here, except for the remark regarding EBU Tech. 3213-E. +TransferCharacteristics_ISO23001_8 = TransferCharacteristics_ITU_T_H273 +MatrixCoefficients_ISO23001_8 = MatrixCoefficients_ITU_T_H273 +PRIMARIES_ISO23001_8 = PRIMARIES_ITU_T_H273 +WHITEPOINTS_NAMES_ISO23001_8 = WHITEPOINTS_NAMES_ITU_T_H273 +CCS_WHITEPOINTS_ISO23001_8 = CCS_WHITEPOINTS_ITU_T_H273 +MATRICES_ISO23001_8_RGB_TO_XYZ = MATRICES_ITU_T_H273_RGB_TO_XYZ +MATRICES_XYZ_TO_ISO23001_8_RGB = MATRICES_XYZ_TO_ITU_T_H273_RGB +TRANSFER_FUNCTIONS_ISO23001_8 = TRANSFER_FUNCTIONS_ITU_T_H273 +WEIGHTS_YCBCR_ISO23001_8 = WEIGHTS_YCBCR_ITU_T_H273 + +# Aliases for ISO/IEC 14496-10:2020. Verified to be functionally identical to ITU-T +# H.273 for the values defined here, except for the remark regarding EBU Tech. 3213-E. +ColourPrimaries_ISO14496_10 = ColourPrimaries_ISO23001_8 +TransferCharacteristics_ISO14496_10 = TransferCharacteristics_ITU_T_H273 +MatrixCoefficients_ISO14496_10 = MatrixCoefficients_ITU_T_H273 +PRIMARIES_ISO14496_10 = PRIMARIES_ITU_T_H273 +WHITEPOINTS_NAMES_ISO14496_10 = WHITEPOINTS_NAMES_ITU_T_H273 +CCS_WHITEPOINTS_ISO14496_10 = CCS_WHITEPOINTS_ITU_T_H273 +MATRICES_ISO14496_10_RGB_TO_XYZ = MATRICES_ITU_T_H273_RGB_TO_XYZ +MATRICES_XYZ_TO_ISO14496_10_RGB = MATRICES_XYZ_TO_ITU_T_H273_RGB +TRANSFER_FUNCTIONS_ISO14496_10 = TRANSFER_FUNCTIONS_ITU_T_H273 +WEIGHTS_YCBCR_ISO14496_10 = WEIGHTS_YCBCR_ITU_T_H273 From f90462c6bbaec97ba0af9e49c321433f83f8a86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Thomas?= Date: Sun, 7 Aug 2022 11:56:14 +0200 Subject: [PATCH 2/6] Fix typo in ITU-R BT.1361 implementation + added doctest cases --- .../rgb/transfer_functions/itur_bt_1361.py | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/colour/models/rgb/transfer_functions/itur_bt_1361.py b/colour/models/rgb/transfer_functions/itur_bt_1361.py index f5babd85b9..f1cfefee1c 100644 --- a/colour/models/rgb/transfer_functions/itur_bt_1361.py +++ b/colour/models/rgb/transfer_functions/itur_bt_1361.py @@ -22,6 +22,10 @@ ) +L_LINEAR_THRESHOLD_POSITIVE = 0.018 +L_LINEAR_THRESHOLD_NEGATIVE = -0.0045 + + def oetf_BT1361_extended(L): """ Define the opto-electronic transfer functions (OETF) for *ITU-R BT.1361* extended @@ -35,7 +39,7 @@ def oetf_BT1361_extended(L): Returns ------- :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding non-linear primary signal :math:`V`. + Corresponding non-linear primary signal :math:`E'`. Notes ----- @@ -45,11 +49,11 @@ def oetf_BT1361_extended(L): | ``L`` | [-0.25, 1.33] | [-0.25, 1.33] | +------------+-----------------------+---------------+ - +------------+-----------------------+---------------+ - | **Range** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``E`` | [-1, -1] | [-1, 1] | - +------------+-----------------------+---------------+ + +------------+-----------------------+-------------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===================+ + | ``Ep'`` | [-0.25, 1.152...] | [-0.25, 1.152...] | + +------------+-----------------------+-------------------+ References ---------- @@ -59,23 +63,31 @@ def oetf_BT1361_extended(L): -------- >>> oetf_BT1361_extended(0.18) # doctest: +ELLIPSIS 0.4090077288641... + >>> oetf_BT1361_extended(-0.25) # doctest: +ELLIPSIS + -0.25 + >>> oetf_BT1361_extended(1.33) # doctest: +ELLIPSIS + 1.1504846663972... """ L = as_float_array(L) - E = np.where( + Ep = np.where( L >= 0, np.where( - L >= 0.018, - 1.099 * spow(L, 0.45) - 0.099, # [0.018, 1.33] range - 4.500 * L, # [0, 0.018] range + L >= L_LINEAR_THRESHOLD_POSITIVE, + # L in [0.018, 1.33] range + 1.099 * spow(L, 0.45) - 0.099, + # L in [0, 0.018] range + 4.500 * L, ), np.where( - L <= -0.0045, - 4.500 * L, # [-0.0045, 0] range - -(spow(1.099 * (-4 * L), 0.45) - 0.099) - / 4, # [-0.25, -0.0045] range + L <= L_LINEAR_THRESHOLD_NEGATIVE, + # L in [-0.25, -0.0045] range + -(1.099 * spow(-4 * L, 0.45) - 0.099) + / 4, + # L in [-0.0045, 0] range + 4.500 * L, ), ) - return as_float(E) + return as_float(Ep) From 542bf8e24536c39e8630a48067498b4ce7d473ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Thomas?= Date: Sun, 7 Aug 2022 11:56:56 +0200 Subject: [PATCH 3/6] Add inverse-OETFs to video transfer functions from ITU-T H.273 --- .../rgb/transfer_functions/iec_61966_2.py | 64 +++++++ .../rgb/transfer_functions/itur_bt_1361.py | 81 ++++++++ .../rgb/transfer_functions/itut_h_273.py | 178 +++++++++++++++++- .../models/rgb/transfer_functions/st_428.py | 59 +++++- 4 files changed, 379 insertions(+), 3 deletions(-) diff --git a/colour/models/rgb/transfer_functions/iec_61966_2.py b/colour/models/rgb/transfer_functions/iec_61966_2.py index 10299f9c1c..dba1905a4e 100644 --- a/colour/models/rgb/transfer_functions/iec_61966_2.py +++ b/colour/models/rgb/transfer_functions/iec_61966_2.py @@ -18,6 +18,7 @@ import numpy as np from colour.models.rgb.transfer_functions.srgb import eotf_inverse_sRGB +from colour.models.rgb.transfer_functions.srgb import eotf_sRGB from colour.utilities import ( as_float, @@ -71,6 +72,8 @@ def oetf_iec_61966_2_unbounded(Lc): -------- >>> oetf_iec_61966_2_unbounded(0.18) # doctest: +ELLIPSIS 0.4613561295004... + >>> oetf_iec_61966_2_unbounded(-0.18) # doctest: +ELLIPSIS + -0.4613561295004... """ Lc = to_domain_1(Lc) @@ -82,3 +85,64 @@ def oetf_iec_61966_2_unbounded(Lc): ) return as_float(from_range_1(V)) + + +def oetf_inverse_iec_61966_2_unbounded(V): + """ + Define the unbounded inverse-opto-electronic transfer functions (OETF) for + *IEC 61966-2* family of transfer functions (*2-1 sRGB*, *2-1 sYCC*, *2-4 + xvYCC*). + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene luminance :math:`Lc`. + + Notes + ----- + Usage in :cite:`ITU2021` is as follows: + + - For IEC 61966-2-1 sRGB (MatrixCoefficients=0), function is only defined + for Lc in [0-1] range. + + - For IEC 61966-2-1 sYCC (MatrixCoefficients=5) and IEC 61966-2-4 xvYCC, + function is defined for any real-valued Lc. + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [-inf, inf] | [-inf, inf] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [-inf, inf] | [-inf, inf] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`ITU2021` + + Examples + -------- + >>> oetf_inverse_iec_61966_2_unbounded(0.461356129500) # doctest: +ELLIPSIS + 0.1799999999... + >>> oetf_inverse_iec_61966_2_unbounded(-0.461356129500) # doctest: +ELLIPSIS + -0.1799999999... + """ + + V = to_domain_1(V) + + Lc = np.where( + V >= 0, + eotf_sRGB(V), + -eotf_sRGB(-V), + ) + + return as_float(from_range_1(Lc)) diff --git a/colour/models/rgb/transfer_functions/itur_bt_1361.py b/colour/models/rgb/transfer_functions/itur_bt_1361.py index f1cfefee1c..7ffbe6ed0c 100644 --- a/colour/models/rgb/transfer_functions/itur_bt_1361.py +++ b/colour/models/rgb/transfer_functions/itur_bt_1361.py @@ -21,9 +21,23 @@ as_float, ) +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "oetf_BT1361_extended", + "oetf_inverse_BT1361_extended", +] + L_LINEAR_THRESHOLD_POSITIVE = 0.018 L_LINEAR_THRESHOLD_NEGATIVE = -0.0045 +EP_LINEAR_THRESHOLD_POSITIVE = 4.500 * L_LINEAR_THRESHOLD_POSITIVE +EP_LINEAR_THRESHOLD_NEGATIVE = 4.500 * L_LINEAR_THRESHOLD_NEGATIVE def oetf_BT1361_extended(L): @@ -91,3 +105,70 @@ def oetf_BT1361_extended(L): ) return as_float(Ep) + + +def oetf_inverse_BT1361_extended(Ep): + """ + Define the inverse-opto-electronic transfer functions (OETF) for *ITU-R + BT.1361* extended color gamut. + + Parameters + ---------- + Ep + Non-linear primary signal :math:`E'`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene *Luminance* :math:`L`. + + Notes + ----- + +------------+-----------------------+-------------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===================+ + | ``Ep'`` | [-0.25, 1.152...] | [-0.25, 1.152...] | + +------------+-----------------------+-------------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L`` | [-0.25, 1.33] | [-0.25, 1.33] | + +------------+-----------------------+---------------+ + + + References + ---------- + :cite:`InternationalTelecommunicationUnion1998` + + Examples + -------- + >>> oetf_inverse_BT1361_extended(0.4090077288641) # doctest: +ELLIPSIS + 0.1799999... + >>> oetf_inverse_BT1361_extended(-0.25) # doctest: +ELLIPSIS + -0.25 + >>> oetf_inverse_BT1361_extended(1.1504846663972) # doctest: +ELLIPSIS + 1.3299999... + """ + + Ep = as_float_array(Ep) + + L = np.where( + Ep >= 0, + np.where( + Ep >= EP_LINEAR_THRESHOLD_POSITIVE, + # L in [0.018, 1.33] range + spow((Ep + 0.099)/1.099, 1/0.45), + # L in [0, 0.018] range + Ep / 4.500, + ), + np.where( + Ep <= EP_LINEAR_THRESHOLD_NEGATIVE, + # L in [-0.25, -0.0045] range + -spow((-4*Ep + 0.099)/1.099, 1/0.45)/4, + # L in [-0.0045, 0] range + Ep / 4.500, + ), + ) + + return as_float(L) diff --git a/colour/models/rgb/transfer_functions/itut_h_273.py b/colour/models/rgb/transfer_functions/itut_h_273.py index 875cf496ef..121fd32d27 100644 --- a/colour/models/rgb/transfer_functions/itut_h_273.py +++ b/colour/models/rgb/transfer_functions/itut_h_273.py @@ -14,6 +14,7 @@ import numpy as np +from colour.algebra import spow from colour.utilities import ( as_float, from_range_1, @@ -31,6 +32,9 @@ "oetf_linear", "oetf_log", "oetf_log_sqrt", + "oetf_inverse_linear", + "oetf_inverse_log", + "oetf_inverse_log_sqrt", ] @@ -79,6 +83,52 @@ def oetf_linear(Lc): return as_float(from_range_1(V)) +def oetf_inverse_linear(V): + """ + Linear inverse-opto-electronic transfer function (OETF) defined in ITU-T + H.273. + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene *Luminance* :math:`Lc`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`ITU2021` + + Examples + -------- + >>> oetf_inverse_linear(0.18) # doctest: +ELLIPSIS + 0.17999999... + """ + + V = to_domain_1(V) + + Lc = V + + return as_float(from_range_1(Lc)) + + def oetf_log(Lc): """ Define the opto-electronic transfer functions (OETF) for Logarithmic @@ -116,6 +166,12 @@ def oetf_log(Lc): -------- >>> oetf_log(0.18) # doctest: +ELLIPSIS 0.6276362525516... + >>> oetf_log(0.01) # doctest: +ELLIPSIS + 0.0 + >>> oetf_log(0.001) # doctest: +ELLIPSIS + 0.0 + >>> oetf_log(1.0) # doctest: +ELLIPSIS + 1.0 """ Lc = to_domain_1(Lc) @@ -131,6 +187,62 @@ def oetf_log(Lc): return as_float(from_range_1(V)) +def oetf_inverse_log(V): + """ + Define the inverse-opto-electronic transfer functions (OETF) for + Logarithmic encoding (100:1 range) defined in ITU-T H.273. + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene *Luminance* :math:`Lc`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`ITU2021` + + Examples + -------- + >>> oetf_inverse_log(0.6276362525516) # doctest: +ELLIPSIS + 0.17999999... + >>> oetf_inverse_log(0.0) # doctest: +ELLIPSIS + 0.01 + >>> oetf_inverse_log(1.0) # doctest: +ELLIPSIS + 1.0 + """ + + V = to_domain_1(V) + + Lc = np.where( + V >= 0.0, + # Lc in [0.01, 1] range + spow(10, (V-1.0)*2.0), + # Lc in [0, 0.01] range + 0.01, + ) + + return as_float(from_range_1(Lc)) + + def oetf_log_sqrt(Lc): """ Define the opto-electronic transfer functions (OETF) for Logarithmic @@ -168,16 +280,78 @@ def oetf_log_sqrt(Lc): -------- >>> oetf_log_sqrt(0.18) # doctest: +ELLIPSIS 0.702109002041... + >>> oetf_log_sqrt(0.003162277660168) # doctest: +ELLIPSIS + 0.0 + >>> oetf_log_sqrt(0.0001) # doctest: +ELLIPSIS + 0.0 + >>> oetf_log_sqrt(1.0) # doctest: +ELLIPSIS + 1.0 """ Lc = to_domain_1(Lc) V = np.where( Lc >= np.sqrt(10) / 1000, - # Lc in [0.01, 1] range + # Lc in [sqrt(10)/1000, 1] range 1.0 + np.log10(Lc) / 2.5, - # Lc in [0, 0.01] range + # Lc in [0, sqrt(10)/1000] range 0.0, ) return as_float(from_range_1(V)) + + +def oetf_inverse_log_sqrt(V): + """ + Define the inverse-opto-electronic transfer functions (OETF) for + Logarithmic encoding (100*Sqrt(10):1 range) defined in ITU-T H.273. + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene *Luminance* :math:`Lc`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lc`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`ITU2021` + + Examples + -------- + >>> oetf_inverse_log_sqrt(0.702109002041) # doctest: +ELLIPSIS + 0.1799999999... + >>> oetf_inverse_log_sqrt(0.0) # doctest: +ELLIPSIS + 0.00316227766... + >>> oetf_inverse_log_sqrt(1.0) # doctest: +ELLIPSIS + 1.0 + """ + + V = to_domain_1(V) + + Lc = np.where( + V >= 0.0, + # Lc in [sqrt(10)/1000, 1] range + spow(10, (V-1.0)*2.5), + # Lc in [0, sqrt(10)/1000] range + np.sqrt(10) / 1000, + ) + + return as_float(from_range_1(Lc)) diff --git a/colour/models/rgb/transfer_functions/st_428.py b/colour/models/rgb/transfer_functions/st_428.py index 64b660631d..62fb53f164 100644 --- a/colour/models/rgb/transfer_functions/st_428.py +++ b/colour/models/rgb/transfer_functions/st_428.py @@ -22,6 +22,63 @@ to_domain_1, ) +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "eotf_ST428_1", + "eotf_inverse_ST428_1", +] + + +def eotf_ST428_1(V): + """ + Define the *SMPTE ST 428-1 (2019)* electro-optical transfer function (EOTF). + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding output display *Luminance* :math:`Lo` of the image. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``Lo`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`ITU2021` + + Examples + -------- + >>> eotf_ST428_1(0.5000483377172) # doctest: +ELLIPSIS + 0.179999999... + """ + + V = to_domain_1(V) + + Lo = 52.37 * spow(V, 2.6) / 48 + + return as_float(from_range_1(Lo)) + def eotf_inverse_ST428_1(Lo): """ @@ -42,7 +99,7 @@ def eotf_inverse_ST428_1(Lo): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``L`` | [0, 1] | [0, 1] | + | ``Lo`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ From 92f0c641e964b690f177bfebec4939fa0f5dfc6e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 7 Aug 2022 09:59:10 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- colour/models/rgb/transfer_functions/itur_bt_1361.py | 7 +++---- colour/models/rgb/transfer_functions/itut_h_273.py | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/colour/models/rgb/transfer_functions/itur_bt_1361.py b/colour/models/rgb/transfer_functions/itur_bt_1361.py index 7ffbe6ed0c..4afec42f19 100644 --- a/colour/models/rgb/transfer_functions/itur_bt_1361.py +++ b/colour/models/rgb/transfer_functions/itur_bt_1361.py @@ -97,8 +97,7 @@ def oetf_BT1361_extended(L): np.where( L <= L_LINEAR_THRESHOLD_NEGATIVE, # L in [-0.25, -0.0045] range - -(1.099 * spow(-4 * L, 0.45) - 0.099) - / 4, + -(1.099 * spow(-4 * L, 0.45) - 0.099) / 4, # L in [-0.0045, 0] range 4.500 * L, ), @@ -158,14 +157,14 @@ def oetf_inverse_BT1361_extended(Ep): np.where( Ep >= EP_LINEAR_THRESHOLD_POSITIVE, # L in [0.018, 1.33] range - spow((Ep + 0.099)/1.099, 1/0.45), + spow((Ep + 0.099) / 1.099, 1 / 0.45), # L in [0, 0.018] range Ep / 4.500, ), np.where( Ep <= EP_LINEAR_THRESHOLD_NEGATIVE, # L in [-0.25, -0.0045] range - -spow((-4*Ep + 0.099)/1.099, 1/0.45)/4, + -spow((-4 * Ep + 0.099) / 1.099, 1 / 0.45) / 4, # L in [-0.0045, 0] range Ep / 4.500, ), diff --git a/colour/models/rgb/transfer_functions/itut_h_273.py b/colour/models/rgb/transfer_functions/itut_h_273.py index 121fd32d27..e055604850 100644 --- a/colour/models/rgb/transfer_functions/itut_h_273.py +++ b/colour/models/rgb/transfer_functions/itut_h_273.py @@ -235,7 +235,7 @@ def oetf_inverse_log(V): Lc = np.where( V >= 0.0, # Lc in [0.01, 1] range - spow(10, (V-1.0)*2.0), + spow(10, (V - 1.0) * 2.0), # Lc in [0, 0.01] range 0.01, ) @@ -349,7 +349,7 @@ def oetf_inverse_log_sqrt(V): Lc = np.where( V >= 0.0, # Lc in [sqrt(10)/1000, 1] range - spow(10, (V-1.0)*2.5), + spow(10, (V - 1.0) * 2.5), # Lc in [0, sqrt(10)/1000] range np.sqrt(10) / 1000, ) From f72019e0365019cfa8a9b8a9d1a37012cc52720e Mon Sep 17 00:00:00 2001 From: Thomas Mansencal Date: Sat, 13 Aug 2022 19:09:20 +1200 Subject: [PATCH 5/6] Improve "ITU-T H.273" implementation consistency. --- BIBLIOGRAPHY.bib | 68 + README.rst | 68 +- colour/__init__.py | 6 + colour/examples/models/examples_rgb.py | 29 + colour/models/__init__.py | 42 + colour/models/rgb/__init__.py | 42 + colour/models/rgb/datasets/__init__.py | 12 +- colour/models/rgb/datasets/ebu_3213_e.py | 54 +- colour/models/rgb/datasets/itut_h_273.py | 220 ++- colour/models/rgb/itut_h_273.py | 1302 +++++++++++++++++ colour/models/rgb/tests/test_itut_h_273.py | 76 + .../models/rgb/transfer_functions/__init__.py | 63 +- colour/models/rgb/transfer_functions/dcdm.py | 3 + .../rgb/transfer_functions/iec_61966_2.py | 148 -- .../rgb/transfer_functions/itur_bt_1361.py | 145 +- .../rgb/transfer_functions/itut_h_273.py | 386 +++-- .../models/rgb/transfer_functions/st_428.py | 125 -- .../transfer_functions/tests/test__init__.py | 14 +- .../tests/test_itur_bt_1361.py | 183 +++ .../tests/test_itut_h_273.py | 657 +++++++++ colour/models/rgb/video.py | 664 --------- docs/colour.models.rst | 38 + docs/index.rst | 70 +- 23 files changed, 3191 insertions(+), 1224 deletions(-) create mode 100644 colour/models/rgb/itut_h_273.py create mode 100644 colour/models/rgb/tests/test_itut_h_273.py delete mode 100644 colour/models/rgb/transfer_functions/iec_61966_2.py delete mode 100644 colour/models/rgb/transfer_functions/st_428.py create mode 100644 colour/models/rgb/transfer_functions/tests/test_itur_bt_1361.py create mode 100644 colour/models/rgb/transfer_functions/tests/test_itut_h_273.py delete mode 100644 colour/models/rgb/video.py diff --git a/BIBLIOGRAPHY.bib b/BIBLIOGRAPHY.bib index 95599a7427..82cdc15da8 100644 --- a/BIBLIOGRAPHY.bib +++ b/BIBLIOGRAPHY.bib @@ -1052,11 +1052,36 @@ @misc{Erdogana adhere to the official terms assigned to the CIE system to avoid any ambiguity.}, } +@misc{EuropeanBroadcastingUnion1975, + title = {{{EBU Tech}} 3213 - {{EBU Standard}} for + {{Chromaticity Tolerances}} for {{Studio Monitors}}}, + author = {{European Broadcasting Union}}, + year = 1975, + month = aug, +} @misc{EuropeanColorInitiative2002a, title = {{{ECI RGB}} V2}, author = {{European Color Initiative}}, year = 2002, } +@misc{FFmpegDevelopers2022, + title = {{{FFmpeg}}::{{AVColorPrimaries}}}, + author = {{FFmpeg Developers}}, + year = 2022, + month = aug, +} +@misc{FFmpegDevelopers2022a, + title = {{{FFmpeg}}::{{AVColorTransferCharacteristic}}}, + author = {{FFmpeg Developers}}, + year = 2022, + month = aug, +} +@misc{FFmpegDevelopers2022b, + title = {{{FFmpeg}}::{{AVColorSpace}}}, + author = {{FFmpeg Developers}}, + year = 2022, + month = aug, +} @article{Fairchild1991a, title = {Formulation and Testing of an Incomplete-Chromatic-Adaptation Model}, @@ -1719,6 +1744,35 @@ @misc{InternationalOrganizationforStandardization2012 author = {{International Organization for Standardization}}, year = 2012, } +@misc{InternationalOrganizationforStandardization2013, + title = {{{INTERNATIONAL STANDARD ISO}}/{{IEC}} 23001-8 - + {{Information}} Technology - {{MPEG}} Systems Technologies - + {{Part}} 8: {{Coding-independent}} Code Points}, + author = {{International Organization for Standardization}}, + year = 2013, +} +@misc{InternationalOrganizationforStandardization2020, + title = {{{INTERNATIONAL STANDARD ISO}}/{{IEC}} 14496-10 - + {{Information}} Technology - {{Coding}} of Audio-Visual Objects - + {{Part}} 10: {{Advanced}} Video Coding}, + author = {{International Organization for Standardization}}, + year = 2020, +} +@misc{InternationalOrganizationforStandardization2021, + title = {{{INTERNATIONAL STANDARD ISO}}/{{IEC}} 23091-2 - + {{Information}} Technology - {{Coding-}} Independent Code Points - + {{Part}} 2: {{Video}}}, + author = {{International Organization for Standardization}}, + year = 2021, +} +@misc{InternationalTelecommunicationUnion1998, + title = {Recommendation {{ITU-R BT}}.1361 - {{Worldwide}} + Unified Colorimetry and Related Characteristics of Future + Television and Imaging Systems}, + author = {{International Telecommunication Union}}, + year = 1998, + pages = {1--32}, +} @misc{InternationalTelecommunicationUnion1998a, title = {Recommendation {{ITU-R BT}}.470-6 - {{CONVENTIONAL TELEVISION SYSTEMS}}}, @@ -1803,6 +1857,13 @@ @misc{InternationalTelecommunicationUnion2019 year = 2019, pages = {1--36}, } +@misc{InternationalTelecommunicationUnion2021, + title = {Recommendation {{ITU-T H}}.273 - + {{Coding-independent}} Code Points for Video Signal Type + Identification}, + author = {{International Telecommunication Union}}, + year = 2021, +} @article{Jakob2019, ids = {Jakob}, title = {A {{Low}}-{{Dimensional Function Space}} for @@ -3054,6 +3115,13 @@ @misc{SocietyofMotionPictureandTelevisionEngineers2014a non-broadcast content. This standard also specifies an Inverse-EOTF derived from the EOTF.}, } +@misc{SocietyofMotionPictureandTelevisionEngineers2019, + title = {{{ST}} 428-1:2019 - {{D-Cinema Distribution Master}} + \textemdash{} {{Image Characteristic}}}, + author = {{Society of Motion Picture and Television Engineers}}, + year = 2019, + doi = {10.5594/SMPTE.ST428-1.2019}, +} @misc{SonyCorporation, title = {S-{{Log Whitepaper}}}, author = {{Sony Corporation}}, diff --git a/README.rst b/README.rst index 6453c632bd..7fc19b0fd6 100644 --- a/README.rst +++ b/README.rst @@ -911,15 +911,16 @@ RGB Colourspaces 'CIE RGB', 'Cinema Gamut', 'ColorMatch RGB', - 'DaVinci Wide Gamut', 'DCDM XYZ', 'DCI-P3', - 'DCI-P3+', + 'DCI-P3-P', 'DJI D-Gamut', 'DRAGONcolor', 'DRAGONcolor2', + 'DaVinci Wide Gamut', 'Display P3', 'Don RGB 4', + 'EBU Tech. 3213-E', 'ECI RGB v2', 'ERIMM RGB', 'Ekta Space PS 5', @@ -929,7 +930,10 @@ RGB Colourspaces 'ITU-R BT.470 - 525', 'ITU-R BT.470 - 625', 'ITU-R BT.709', + 'ITU-T H.273 - 22 Unspecified', + 'ITU-T H.273 - Generic Film', 'Max RGB', + 'N-Gamut', 'NTSC (1953)', 'NTSC (1987)', 'P3-D65', @@ -957,6 +961,8 @@ RGB Colourspaces 'aces', 'adobe1998', 'prophoto', + 'sRGB'] + OETFs ***** @@ -972,8 +978,12 @@ OETFs 'ITU-R BT.2100 PQ', 'ITU-R BT.601', 'ITU-R BT.709', + 'ITU-T H.273 IEC 61966-2', + 'ITU-T H.273 Log', + 'ITU-T H.273 Log Sqrt', 'SMPTE 240M'] + EOTFs ***** @@ -985,6 +995,7 @@ EOTFs 'ITU-R BT.1886', 'ITU-R BT.2100 HLG', 'ITU-R BT.2100 PQ', + 'ITU-T H.273 ST.428-1', 'SMPTE 240M', 'ST 2084', 'sRGB'] @@ -1083,6 +1094,59 @@ CCTFs Encoding / Decoding 'ViperLog', 'sRGB'] +Recommendation ITU-T H.273 Code points for Video Signal Type Identification +*************************************************************************** + +.. code-block:: python + + >>> colour.COLOUR_PRIMARIES_ITUTH273.keys() + dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 22, 23]) + >>> colour.COLOUR_PRIMARIES_ITUTH273.keys() + >>> description = colour.models.describe_video_signal_colour_primaries(1) + =============================================================================== + * * + * Colour Primaries: 1 * + * ------------------- * + * * + * Primaries : [[ 0.64 0.33] * + * [ 0.3 0.6 ] * + * [ 0.15 0.06]] * + * Whitepoint : [ 0.3127 0.329 ] * + * Whitepoint Name : D65 * + * NPM : [[ 0.4123908 0.35758434 0.18048079] * + * [ 0.21263901 0.71516868 0.07219232] * + * [ 0.01933082 0.11919478 0.95053215]] * + * NPM -1 : [[ 3.24096994 -1.53738318 -0.49861076] * + * [-0.96924364 1.8759675 0.04155506] * + * [ 0.05563008 -0.20397696 1.05697151]] * + * FFmpeg Constants : ['AVCOL_PRI_BT709', 'BT709'] * + * * + =============================================================================== + >>> colour.TRANSFER_CHARACTERISTICS_ITUTH273.keys() + dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]) + >>> description = colour.models.describe_video_signal_transfer_characteristics(1) + =============================================================================== + * * + * Transfer Characteristics: 1 * + * --------------------------- * + * * + * Function : * + * FFmpeg Constants : ['AVCOL_TRC_BT709', 'BT709'] * + * * + =============================================================================== + >>> colour.MATRIX_COEFFICIENTS_ITUTH273.keys() + dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) + >>> description = colour.models.describe_video_signal_matrix_coefficients(1) + =============================================================================== + * * + * Matrix Coefficients: 1 * + * ---------------------- * + * * + * Matrix Coefficients : [ 0.2126 0.0722] * + * FFmpeg Constants : ['AVCOL_SPC_BT709', 'BT709'] * + * * + =============================================================================== + Colour Notation Systems - ``colour.notation`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/colour/__init__.py b/colour/__init__.py index 278089283e..50d7dc0b5e 100644 --- a/colour/__init__.py +++ b/colour/__init__.py @@ -238,6 +238,7 @@ CMY_to_CMYK, CMY_to_RGB, COLOURSPACE_MODELS, + COLOUR_PRIMARIES_ITUTH273, CV_range, DATA_MACADAM_1942_ELLIPSES, DIN99_to_Lab, @@ -277,6 +278,7 @@ Luv_to_XYZ, Luv_to_uv, Luv_uv_to_xy, + MATRIX_COEFFICIENTS_ITUTH273, OETFS, OETF_INVERSES, OOTFS, @@ -301,6 +303,7 @@ RGB_to_YCbCr, RGB_to_YCoCg, RGB_to_YcCbcCrc, + TRANSFER_CHARACTERISTICS_ITUTH273, UCS_to_XYZ, UCS_to_uv, UCS_uv_to_xy, @@ -657,6 +660,7 @@ def __getattr__(self, attribute) -> Any: "CMY_to_CMYK", "CMY_to_RGB", "COLOURSPACE_MODELS", + "COLOUR_PRIMARIES_ITUTH273", "CV_range", "DATA_MACADAM_1942_ELLIPSES", "DIN99_to_Lab", @@ -696,6 +700,7 @@ def __getattr__(self, attribute) -> Any: "Luv_to_XYZ", "Luv_to_uv", "Luv_uv_to_xy", + "MATRIX_COEFFICIENTS_ITUTH273", "OETFS", "OETF_INVERSES", "OOTFS", @@ -720,6 +725,7 @@ def __getattr__(self, attribute) -> Any: "RGB_to_YCbCr", "RGB_to_YCoCg", "RGB_to_YcCbcCrc", + "TRANSFER_CHARACTERISTICS_ITUTH273", "UCS_to_XYZ", "UCS_to_uv", "UCS_uv_to_xy", diff --git a/colour/examples/models/examples_rgb.py b/colour/examples/models/examples_rgb.py index 175ee66532..9cb77791ed 100644 --- a/colour/examples/models/examples_rgb.py +++ b/colour/examples/models/examples_rgb.py @@ -65,3 +65,32 @@ colour.RGB_COLOURSPACES["ACEScg"], ) ) + +print("\n") + +message_box( + '"Recommendation ITU-T H.273" ' + "Code points for Video Signal Type Identification" +) + +message_box( + f"Colour Primaries: {list(colour.COLOUR_PRIMARIES_ITUTH273.keys())}" +) +colour.models.describe_video_signal_colour_primaries(1) + +print("\n") + +message_box( + f"Transfer Characteristics: " + f"{list(colour.TRANSFER_CHARACTERISTICS_ITUTH273.keys())}" +) +colour.models.describe_video_signal_transfer_characteristics(1) + +print("\n") + +message_box( + f"Matrix Coefficients: " + f"{list(colour.MATRIX_COEFFICIENTS_ITUTH273.keys())}" +) + +colour.models.describe_video_signal_matrix_coefficients(1) diff --git a/colour/models/__init__.py b/colour/models/__init__.py index 9b30e7000a..75ae6e1363 100644 --- a/colour/models/__init__.py +++ b/colour/models/__init__.py @@ -160,6 +160,8 @@ oetf_inverse_BT601, oetf_BT709, oetf_inverse_BT709, + oetf_BT1361, + oetf_inverse_BT1361, eotf_inverse_BT1886, eotf_BT1886, eotf_inverse_ST2084, @@ -180,6 +182,14 @@ ootf_BT2100_HLG, BT2100_HLG_OOTF_INVERSE_METHODS, ootf_inverse_BT2100_HLG, + oetf_H273_Log, + oetf_inverse_H273_Log, + oetf_H273_LogSqrt, + oetf_inverse_H273_LogSqrt, + oetf_H273_IEC61966_2, + oetf_inverse_H273_IEC61966_2, + eotf_H273_ST428_1, + eotf_inverse_H273_ST428_1, linear_function, logarithmic_function_basic, logarithmic_function_quasilog, @@ -279,9 +289,12 @@ RGB_COLOURSPACE_DISPLAY_P3, RGB_COLOURSPACE_DJI_D_GAMUT, RGB_COLOURSPACE_DON_RGB_4, + RGB_COLOURSPACE_EBU_3213_E, RGB_COLOURSPACE_ECI_RGB_V2, RGB_COLOURSPACE_EKTA_SPACE_PS_5, RGB_COLOURSPACE_FILMLIGHT_E_GAMUT, + RGB_COLOURSPACE_H273_GENERIC_FILM, + RGB_COLOURSPACE_H273_22_UNSPECIFIED, RGB_COLOURSPACE_PROTUNE_NATIVE, RGB_COLOURSPACE_MAX_RGB, RGB_COLOURSPACE_N_GAMUT, @@ -338,6 +351,14 @@ ) from .rgb import RGB_to_YCoCg, YCoCg_to_RGB from .rgb import RGB_to_ICtCp, ICtCp_to_RGB, XYZ_to_ICtCp, ICtCp_to_XYZ +from .rgb import ( + COLOUR_PRIMARIES_ITUTH273, + TRANSFER_CHARACTERISTICS_ITUTH273, + MATRIX_COEFFICIENTS_ITUTH273, + describe_video_signal_colour_primaries, + describe_video_signal_transfer_characteristics, + describe_video_signal_matrix_coefficients, +) __all__ = [ "COLOURSPACE_MODELS", @@ -537,6 +558,8 @@ "oetf_inverse_BT601", "oetf_BT709", "oetf_inverse_BT709", + "oetf_BT1361", + "oetf_inverse_BT1361", "eotf_inverse_BT1886", "eotf_BT1886", "eotf_inverse_ST2084", @@ -557,6 +580,14 @@ "ootf_BT2100_HLG", "BT2100_HLG_OOTF_INVERSE_METHODS", "ootf_inverse_BT2100_HLG", + "oetf_H273_Log", + "oetf_inverse_H273_Log", + "oetf_H273_LogSqrt", + "oetf_inverse_H273_LogSqrt", + "oetf_H273_IEC61966_2", + "oetf_inverse_H273_IEC61966_2", + "eotf_H273_ST428_1", + "eotf_inverse_H273_ST428_1", "linear_function", "logarithmic_function_basic", "logarithmic_function_quasilog", @@ -656,9 +687,12 @@ "RGB_COLOURSPACE_DISPLAY_P3", "RGB_COLOURSPACE_DJI_D_GAMUT", "RGB_COLOURSPACE_DON_RGB_4", + "RGB_COLOURSPACE_EBU_3213_E", "RGB_COLOURSPACE_ECI_RGB_V2", "RGB_COLOURSPACE_EKTA_SPACE_PS_5", "RGB_COLOURSPACE_FILMLIGHT_E_GAMUT", + "RGB_COLOURSPACE_H273_GENERIC_FILM", + "RGB_COLOURSPACE_H273_22_UNSPECIFIED", "RGB_COLOURSPACE_PROTUNE_NATIVE", "RGB_COLOURSPACE_MAX_RGB", "RGB_COLOURSPACE_N_GAMUT", @@ -715,6 +749,14 @@ ] __all__ += ["RGB_to_YCoCg", "YCoCg_to_RGB"] __all__ += ["RGB_to_ICtCp", "ICtCp_to_RGB", "XYZ_to_ICtCp", "ICtCp_to_XYZ"] +__all__ += [ + "COLOUR_PRIMARIES_ITUTH273", + "TRANSFER_CHARACTERISTICS_ITUTH273", + "MATRIX_COEFFICIENTS_ITUTH273", + "describe_video_signal_colour_primaries", + "describe_video_signal_transfer_characteristics", + "describe_video_signal_matrix_coefficients", +] # ----------------------------------------------------------------------------# diff --git a/colour/models/rgb/__init__.py b/colour/models/rgb/__init__.py index 7bb192dc6f..967eaf0921 100644 --- a/colour/models/rgb/__init__.py +++ b/colour/models/rgb/__init__.py @@ -55,6 +55,8 @@ oetf_inverse_BT601, oetf_BT709, oetf_inverse_BT709, + oetf_BT1361, + oetf_inverse_BT1361, eotf_inverse_BT1886, eotf_BT1886, eotf_inverse_ST2084, @@ -75,6 +77,14 @@ ootf_BT2100_HLG, BT2100_HLG_OOTF_INVERSE_METHODS, ootf_inverse_BT2100_HLG, + oetf_H273_Log, + oetf_inverse_H273_Log, + oetf_H273_LogSqrt, + oetf_inverse_H273_LogSqrt, + oetf_H273_IEC61966_2, + oetf_inverse_H273_IEC61966_2, + eotf_H273_ST428_1, + eotf_inverse_H273_ST428_1, linear_function, logarithmic_function_basic, logarithmic_function_quasilog, @@ -174,9 +184,12 @@ RGB_COLOURSPACE_DISPLAY_P3, RGB_COLOURSPACE_DJI_D_GAMUT, RGB_COLOURSPACE_DON_RGB_4, + RGB_COLOURSPACE_EBU_3213_E, RGB_COLOURSPACE_ECI_RGB_V2, RGB_COLOURSPACE_EKTA_SPACE_PS_5, RGB_COLOURSPACE_FILMLIGHT_E_GAMUT, + RGB_COLOURSPACE_H273_GENERIC_FILM, + RGB_COLOURSPACE_H273_22_UNSPECIFIED, RGB_COLOURSPACE_PROTUNE_NATIVE, RGB_COLOURSPACE_MAX_RGB, RGB_COLOURSPACE_N_GAMUT, @@ -233,6 +246,14 @@ ) from .ycocg import RGB_to_YCoCg, YCoCg_to_RGB from .ictcp import RGB_to_ICtCp, ICtCp_to_RGB, XYZ_to_ICtCp, ICtCp_to_XYZ +from .itut_h_273 import ( + COLOUR_PRIMARIES_ITUTH273, + TRANSFER_CHARACTERISTICS_ITUTH273, + MATRIX_COEFFICIENTS_ITUTH273, + describe_video_signal_colour_primaries, + describe_video_signal_transfer_characteristics, + describe_video_signal_matrix_coefficients, +) __all__ = [ "normalised_primary_matrix", @@ -299,6 +320,8 @@ "oetf_inverse_BT601", "oetf_BT709", "oetf_inverse_BT709", + "oetf_BT1361", + "oetf_inverse_BT1361", "eotf_inverse_BT1886", "eotf_BT1886", "eotf_inverse_ST2084", @@ -319,6 +342,14 @@ "ootf_BT2100_HLG", "BT2100_HLG_OOTF_INVERSE_METHODS", "ootf_inverse_BT2100_HLG", + "oetf_H273_Log", + "oetf_inverse_H273_Log", + "oetf_H273_LogSqrt", + "oetf_inverse_H273_LogSqrt", + "oetf_H273_IEC61966_2", + "oetf_inverse_H273_IEC61966_2", + "eotf_H273_ST428_1", + "eotf_inverse_H273_ST428_1", "linear_function", "logarithmic_function_basic", "logarithmic_function_quasilog", @@ -419,8 +450,11 @@ "RGB_COLOURSPACE_DJI_D_GAMUT", "RGB_COLOURSPACE_DON_RGB_4", "RGB_COLOURSPACE_ECI_RGB_V2", + "RGB_COLOURSPACE_EBU_3213_E", "RGB_COLOURSPACE_EKTA_SPACE_PS_5", "RGB_COLOURSPACE_FILMLIGHT_E_GAMUT", + "RGB_COLOURSPACE_H273_GENERIC_FILM", + "RGB_COLOURSPACE_H273_22_UNSPECIFIED", "RGB_COLOURSPACE_PROTUNE_NATIVE", "RGB_COLOURSPACE_MAX_RGB", "RGB_COLOURSPACE_N_GAMUT", @@ -498,3 +532,11 @@ "XYZ_to_ICtCp", "ICtCp_to_XYZ", ] +__all__ += [ + "COLOUR_PRIMARIES_ITUTH273", + "TRANSFER_CHARACTERISTICS_ITUTH273", + "MATRIX_COEFFICIENTS_ITUTH273", + "describe_video_signal_colour_primaries", + "describe_video_signal_transfer_characteristics", + "describe_video_signal_matrix_coefficients", +] diff --git a/colour/models/rgb/datasets/__init__.py b/colour/models/rgb/datasets/__init__.py index f7438923f7..eb07d5ef04 100644 --- a/colour/models/rgb/datasets/__init__.py +++ b/colour/models/rgb/datasets/__init__.py @@ -22,9 +22,9 @@ from .dcdm_xyz import RGB_COLOURSPACE_DCDM_XYZ from .dci_p3 import RGB_COLOURSPACE_DCI_P3, RGB_COLOURSPACE_DCI_P3_P from .display_p3 import RGB_COLOURSPACE_DISPLAY_P3 -from .p3_d65 import RGB_COLOURSPACE_P3_D65 -from .don_rgb_4 import RGB_COLOURSPACE_DON_RGB_4 from .dji_dgamut import RGB_COLOURSPACE_DJI_D_GAMUT +from .don_rgb_4 import RGB_COLOURSPACE_DON_RGB_4 +from .ebu_3213_e import RGB_COLOURSPACE_EBU_3213_E from .eci_rgb_v2 import RGB_COLOURSPACE_ECI_RGB_V2 from .ekta_space_ps5 import RGB_COLOURSPACE_EKTA_SPACE_PS_5 from .fujifilm_f_gamut import RGB_COLOURSPACE_F_GAMUT @@ -33,8 +33,13 @@ from .itur_bt_470 import RGB_COLOURSPACE_BT470_525, RGB_COLOURSPACE_BT470_625 from .itur_bt_709 import RGB_COLOURSPACE_BT709 from .itur_bt_2020 import RGB_COLOURSPACE_BT2020 +from .itut_h_273 import ( + RGB_COLOURSPACE_H273_GENERIC_FILM, + RGB_COLOURSPACE_H273_22_UNSPECIFIED, +) from .max_rgb import RGB_COLOURSPACE_MAX_RGB from .nikon_n_gamut import RGB_COLOURSPACE_N_GAMUT +from .p3_d65 import RGB_COLOURSPACE_P3_D65 from .pal_secam import RGB_COLOURSPACE_PAL_SECAM from .red import ( RGB_COLOURSPACE_RED_COLOR, @@ -117,6 +122,8 @@ "RGB_COLOURSPACE_BT470_625", "RGB_COLOURSPACE_BT709", "RGB_COLOURSPACE_BT2020", + "RGB_COLOURSPACE_H273_GENERIC_FILM", + "RGB_COLOURSPACE_H273_22_UNSPECIFIED", "RGB_COLOURSPACE_CIE_RGB", "RGB_COLOURSPACE_CINEMA_GAMUT", "RGB_COLOURSPACE_COLOR_MATCH_RGB", @@ -126,6 +133,7 @@ "RGB_COLOURSPACE_DCI_P3_P", "RGB_COLOURSPACE_DISPLAY_P3", "RGB_COLOURSPACE_DJI_D_GAMUT", + "RGB_COLOURSPACE_EBU_3213_E", "RGB_COLOURSPACE_DON_RGB_4", "RGB_COLOURSPACE_ECI_RGB_V2", "RGB_COLOURSPACE_EKTA_SPACE_PS_5", diff --git a/colour/models/rgb/datasets/ebu_3213_e.py b/colour/models/rgb/datasets/ebu_3213_e.py index 83fa5e2a82..f9e9882ad7 100644 --- a/colour/models/rgb/datasets/ebu_3213_e.py +++ b/colour/models/rgb/datasets/ebu_3213_e.py @@ -1,16 +1,16 @@ """ -EBU Tech. 3213-E Primaries and White Point -========================================== +EBU Tech. 3213-E Colourspace +============================ -Defines primaries and white point chromaticity coordinates from EBU Tech. -3213-E (:cite:`EuropeanBroadcastingUnion3213E`). +Defines the *EBU Tech. 3213-E* colourspace: + +- :attr:`colour.models.RGB_COLOURSPACE_EBU_3213_E`. References ---------- -- :cite:`EuropeanBroadcastingUnion3213E` : European Broadcasting Union - Tech. 3213-E (1975), Standard for Chromaticity Tolerances For Studio - Monitors. - https://tech.ebu.ch/docs/tech/tech3213.pdf +- :cite:`EuropeanBroadcastingUnion1975` : European Broadcasting Union. + (1975). EBU Tech 3213 - EBU Standard for Chromaticity Tolerances for Studio + Monitors. https://tech.ebu.ch/docs/tech/tech3213.pdf """ from __future__ import annotations @@ -18,7 +18,11 @@ import numpy as np from colour.hints import NDArray -from colour.models.rgb import normalised_primary_matrix +from colour.models.rgb import ( + RGB_Colourspace, + linear_function, + normalised_primary_matrix, +) __author__ = "Colour Developers" __copyright__ = "Copyright 2013 Colour Developers" @@ -33,6 +37,7 @@ "CCS_WHITEPOINT_EBU_3213_E", "MATRIX_EBU_3213_E_RGB_TO_XYZ", "MATRIX_XYZ_TO_EBU_3213_E_RGB", + "RGB_COLOURSPACE_EBU_3213_E", ] PRIMARIES_EBU_3213_E: NDArray = np.array( @@ -42,23 +47,38 @@ [0.15, 0.06], ] ) -"""Colourspace primaries for EBU Tech. 3213-E, as defined in -:cite:`EuropeanBroadcastingUnion3213E`.""" +"""*EBU Tech. 3213-E* colourspace primaries.""" WHITEPOINT_NAME_EBU_3213_E: str = "D65" -"""Whitepoint name for EBU Tech. 3213-E, as defined in -:cite:`EuropeanBroadcastingUnion3213E`.""" +"""*EBU Tech. 3213-E* colourspace whitepoint name.""" CCS_WHITEPOINT_EBU_3213_E: NDArray = np.array([0.313, 0.329]) -"""Whitepoint chromaticity coordinates for EBU Tech. 3213-E, as defined in -:cite:`EuropeanBroadcastingUnion3213E`.""" +"""*EBU Tech. 3213-E* colourspace whitepoint chromaticity coordinates.""" MATRIX_EBU_3213_E_RGB_TO_XYZ: NDArray = normalised_primary_matrix( PRIMARIES_EBU_3213_E, CCS_WHITEPOINT_EBU_3213_E ) -"""EBU Tech. 3213-E colourspace to *CIE XYZ* tristimulus values matrix.""" +"""*EBU Tech. 3213-E* colourspace to *CIE XYZ* tristimulus values matrix.""" MATRIX_XYZ_TO_EBU_3213_E_RGB: NDArray = np.linalg.inv( MATRIX_EBU_3213_E_RGB_TO_XYZ ) -"""*CIE XYZ* tristimulus values to EBU Tech. 3213-E colourspace matrix.""" +"""*CIE XYZ* tristimulus values to *EBU Tech. 3213-E* colourspace matrix.""" + +RGB_COLOURSPACE_EBU_3213_E: RGB_Colourspace = RGB_Colourspace( + "EBU Tech. 3213-E", + PRIMARIES_EBU_3213_E, + CCS_WHITEPOINT_EBU_3213_E, + WHITEPOINT_NAME_EBU_3213_E, + MATRIX_EBU_3213_E_RGB_TO_XYZ, + MATRIX_XYZ_TO_EBU_3213_E_RGB, + linear_function, + linear_function, +) +RGB_COLOURSPACE_EBU_3213_E.__doc__ = """ +*EBU Tech. 3213-E* colourspace. + +References +---------- +:cite:`EuropeanBroadcastingUnion1975` +""" diff --git a/colour/models/rgb/datasets/itut_h_273.py b/colour/models/rgb/datasets/itut_h_273.py index 19230b1602..893c748709 100644 --- a/colour/models/rgb/datasets/itut_h_273.py +++ b/colour/models/rgb/datasets/itut_h_273.py @@ -1,14 +1,18 @@ """ -ITU-T H.273 video primaries and whitepoints -=========================================== +Recommendation ITU-T H.273 Colour Primaries (and Colourspaces) +============================================================== -Contains several primaries and whitepoints that are defined in ITU-T H.273 -(:cite:`ITU2021`) but don't belong in another specification or standard. +Defines the *Recommendation ITU-T H.273* colourspaces that do not belong in +another specification or standard, or have been modified for inclusion: + +- :attr:`colour.models.RGB_COLOURSPACE_H273_GENERIC_FILM`. +- :attr:`colour.models.RGB_COLOURSPACE_H273_22_UNSPECIFIED`. References ---------- -- :cite:`ITU2021` : International Telecommunication Union. (2021). Recommendation - ITU-T H.273 - Coding-independent code points for video signal type identification. +- :cite:`InternationalTelecommunicationUnion2021` : International + Telecommunication Union. (2021). Recommendation ITU-T H.273 - + Coding-independent code points for video signal type identification. https://www.itu.int/rec/T-REC-H.273-202107-I/en """ @@ -17,7 +21,11 @@ import numpy as np from colour.hints import NDArray -from colour.models.rgb import normalised_primary_matrix +from colour.models.rgb import ( + RGB_Colourspace, + linear_function, + normalised_primary_matrix, +) __author__ = "Colour Developers" __copyright__ = "Copyright 2013 Colour Developers" @@ -27,70 +35,180 @@ __status__ = "Production" __all__ = [ - "PRIMARIES_FILM_C", - "WHITEPOINT_NAME_FILM_C", - "CCS_WHITEPOINT_FILM_C", - "MATRIX_FILM_C_RGB_TO_XYZ", - "MATRIX_XYZ_TO_FILM_C_RGB", - "PRIMARIES_ITUT_H273_22", - "WHITEPOINT_NAME_ITUT_H273_22", - "CCS_WHITEPOINT_ITUT_H273_22", - "MATRIX_ITUT_H273_22_RGB_TO_XYZ", - "MATRIX_XYZ_TO_ITUT_H273_22_RGB", + "PRIMARIES_H273_GENERIC_FILM", + "WHITEPOINT_NAME_H273_GENERIC_FILM", + "CCS_WHITEPOINT_H273_GENERIC_FILM", + "MATRIX_H273_GENERIC_FILM_RGB_TO_XYZ", + "MATRIX_XYZ_TO_H273_GENERIC_FILM_RGB", + "RGB_COLOURSPACE_H273_GENERIC_FILM", + "PRIMARIES_H273_22_UNSPECIFIED", + "WHITEPOINT_NAME_H273_22_UNSPECIFIED", + "CCS_WHITEPOINT_H273_22_UNSPECIFIED", + "MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ", + "MATRIX_XYZ_TO_H273_22_UNSPECIFIED_RGB", + "RGB_COLOURSPACE_H273_22_UNSPECIFIED", ] -PRIMARIES_FILM_C: NDArray = np.array( +PRIMARIES_H273_GENERIC_FILM: NDArray = np.array( [ - [0.681, 0.319], - [0.243, 0.692], - [0.145, 0.049], + [0.681, 0.319], # Wratten 25 + [0.243, 0.692], # Wratten 58 + [0.145, 0.049], # Wratten 47 ] ) -"""Colourspace primaries for "colour filters using illuminant C", as defined in -:cite:`ITU2021`.""" +""" +Colourspace primaries for *Generic Film* (colour filters using Illuminant C). + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +WHITEPOINT_NAME_H273_GENERIC_FILM: str = "C" +""" +Whitepoint name for *Generic Film* (colour filters using Illuminant C). + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +CCS_WHITEPOINT_H273_GENERIC_FILM: NDArray = np.array([0.310, 0.316]) +""" +Whitepoint chromaticity coordinates for *Generic Film* (colour filters using +Illuminant C). + +Notes +----- + +- *Recommendation ITU-T H.273* defines whitepoint *C* as [0.310, 0.316], + while *Colour* has a slightly higher precision. + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +MATRIX_H273_GENERIC_FILM_RGB_TO_XYZ: NDArray = normalised_primary_matrix( + PRIMARIES_H273_GENERIC_FILM, CCS_WHITEPOINT_H273_GENERIC_FILM +) +""" +*Generic Film* (colour filters using Illuminant C) colourspace to *CIE XYZ* +tristimulus values matrix. -WHITEPOINT_NAME_FILM_C: str = "C" -"""Whitepoint name for "colour filters using illuminant C", as defined in -:cite:`ITU2021`.""" +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +MATRIX_XYZ_TO_H273_GENERIC_FILM_RGB: NDArray = np.linalg.inv( + MATRIX_H273_GENERIC_FILM_RGB_TO_XYZ +) +""" +*CIE XYZ* tristimulus values to *Generic Film* (colour filters using +Illuminant C) colourspace matrix. -# Note: ITU-T H.273 defines white point C as [0.310, 0.316], while colour -# has a slightly higher precision. -CCS_WHITEPOINT_FILM_C: NDArray = np.array([0.310, 0.316]) -"""Whitepoint chromaticity coordinates for "colour filters using illuminant C", as -defined in :cite:`ITU2021`.""" +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" -MATRIX_FILM_C_RGB_TO_XYZ: NDArray = normalised_primary_matrix( - PRIMARIES_FILM_C, CCS_WHITEPOINT_FILM_C +RGB_COLOURSPACE_H273_GENERIC_FILM: RGB_Colourspace = RGB_Colourspace( + "ITU-T H.273 - Generic Film", + PRIMARIES_H273_GENERIC_FILM, + CCS_WHITEPOINT_H273_GENERIC_FILM, + WHITEPOINT_NAME_H273_GENERIC_FILM, + MATRIX_H273_GENERIC_FILM_RGB_TO_XYZ, + MATRIX_XYZ_TO_H273_GENERIC_FILM_RGB, + linear_function, + linear_function, ) -"""'Colour filters using Illuminant C' colourspace to *CIE XYZ* tristimulus values -matrix.""" +RGB_COLOURSPACE_H273_GENERIC_FILM.__doc__ = """ +*Recommendation ITU-T H.273* *Generic Film* (colour filters using Illuminant C) +colourspace. + +References +---------- +:cite:`InternationalTelecommunicationUnion2021` +""" -MATRIX_XYZ_TO_FILM_C_RGB: NDArray = np.linalg.inv(MATRIX_FILM_C_RGB_TO_XYZ) -"""*CIE XYZ* tristimulus values to 'Colour filters using Illuminant C' colourspace -matrix.""" -PRIMARIES_ITUT_H273_22: NDArray = np.array( +PRIMARIES_H273_22_UNSPECIFIED: NDArray = np.array( [ [0.630, 0.340], [0.295, 0.605], [0.155, 0.077], ] ) -"""Colourspace primaries for ColourPrimaries number 22 defined in :cite:`ITU2021`.""" +""" +Colourspace primaries for row *22* as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value*. + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +WHITEPOINT_NAME_H273_22_UNSPECIFIED: str = "D65" +""" +Whitepoint name for row *22* as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value*. + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +CCS_WHITEPOINT_H273_22_UNSPECIFIED: NDArray = np.array([0.3127, 0.3290]) +""" +Whitepoint chromaticity coordinates for row *22* as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value*. + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" -WHITEPOINT_NAME_ITUT_H273_22: str = "D65" -"""Whitepoint name for ColourPrimaries number 22 defined in :cite:`ITU2021`.""" +MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ: NDArray = normalised_primary_matrix( + PRIMARIES_H273_22_UNSPECIFIED, CCS_WHITEPOINT_H273_22_UNSPECIFIED +) +""" +Row *22* colourspace as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value* to +*CIE XYZ* tristimulus values matrix. -CCS_WHITEPOINT_ITUT_H273_22: NDArray = np.array([0.3127, 0.3290]) -"""Whitepoint chromaticity coordinates for ColourPrimaries number 22, as defined in -:cite:`ITU2021`.""" +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" -MATRIX_ITUT_H273_22_RGB_TO_XYZ: NDArray = normalised_primary_matrix( - PRIMARIES_ITUT_H273_22, CCS_WHITEPOINT_ITUT_H273_22 +MATRIX_XYZ_TO_H273_22_UNSPECIFIED_RGB: NDArray = np.linalg.inv( + MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ ) -"""ITU-T H.273 ColourPrimaries number 22 to *CIE XYZ* tristimulus values matrix.""" +""" +*CIE XYZ* tristimulus values to row *22* colourspace as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value* matrix. -MATRIX_XYZ_TO_ITUT_H273_22_RGB: NDArray = np.linalg.inv( - MATRIX_ITUT_H273_22_RGB_TO_XYZ +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +RGB_COLOURSPACE_H273_22_UNSPECIFIED: RGB_Colourspace = RGB_Colourspace( + "ITU-T H.273 - 22 Unspecified", + PRIMARIES_H273_22_UNSPECIFIED, + CCS_WHITEPOINT_H273_22_UNSPECIFIED, + WHITEPOINT_NAME_H273_22_UNSPECIFIED, + MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ, + MATRIX_XYZ_TO_H273_22_UNSPECIFIED_RGB, + linear_function, + linear_function, ) -"""*CIE XYZ* tristimulus values to ITU-T H.273 ColourPrimaries number 22 matrix.""" +RGB_COLOURSPACE_H273_22_UNSPECIFIED.__doc__ = """ +*Recommendation ITU-T H.273* row *22* colourspace as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value*. + +References +---------- +:cite:`InternationalTelecommunicationUnion2021` +""" diff --git a/colour/models/rgb/itut_h_273.py b/colour/models/rgb/itut_h_273.py new file mode 100644 index 0000000000..98489454dd --- /dev/null +++ b/colour/models/rgb/itut_h_273.py @@ -0,0 +1,1302 @@ +""" +Recommendation ITU-T H.273 Code points for Video Signal Type Identification +=========================================================================== + +Defines a set of standard video signal colour primaries, transfer functions and +matrix coefficients used in deriving luma and chroma signals: + +- :attr:`colour.COLOUR_PRIMARIES_ITUTH273` +- :attr:`colour.TRANSFER_CHARACTERISTICS_ITUTH273` +- :attr:`colour.MATRIX_COEFFICIENTS_ITUTH273` + +These values were historically defined in +:cite:`InternationalOrganizationforStandardization2013` then +superseded and duplicated by other standards such as +:cite:`InternationalOrganizationforStandardization2020`, +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021`. They are widely in use to +define colour-related properties in video encoding and decoding software +libraries, including *FFmpeg*. + +References +---------- +- :cite:`EuropeanBroadcastingUnion1975` : European Broadcasting Union. + (1975). EBU Tech 3213 - EBU Standard for Chromaticity Tolerances for Studio + Monitors. https://tech.ebu.ch/docs/tech/tech3213.pdf +- :cite:`FFmpegDevelopers2022` : FFmpeg Developers. (2022). + FFmpeg::AVColorPrimaries. https://github.com/FFmpeg/FFmpeg/\ +blob/c469c3c3b18fbacd6ee0165573034d2a0408b83f/libavutil/pixfmt.h#L478 +- :cite:`FFmpegDevelopers2022a` : FFmpeg Developers. (2022). + FFmpeg::AVColorTransferCharacteristic. https://github.com/FFmpeg/FFmpeg/\ +blob/c469c3c3b18fbacd6ee0165573034d2a0408b83f/libavutil/pixfmt.h#L503 +- :cite:`FFmpegDevelopers2022b` : FFmpeg Developers. (2022). + FFmpeg::AVColorSpace. https://github.com/FFmpeg/FFmpeg/\ +blob/c469c3c3b18fbacd6ee0165573034d2a0408b83f/libavutil/pixfmt.h#L532 +- :cite:`InternationalOrganizationforStandardization2013` : International + Organization for Standardization. (2013). INTERNATIONAL STANDARD ISO/IEC + 23001-8 - Information technology - MPEG systems technologies - Part 8: + Coding-independent code points. +- :cite:`InternationalOrganizationforStandardization2020` : International + Organization for Standardization. (2020). INTERNATIONAL STANDARD ISO/IEC + 14496-10 - Information technology - Coding of audio-visual objects - Part + 10: Advanced video coding. +- :cite:`InternationalOrganizationforStandardization2021` : International + Organization for Standardization. (2021). INTERNATIONAL STANDARD ISO/IEC + 23091-2 - Information technology - Coding- independent code points - + Part 2: Video. +- :cite:`InternationalTelecommunicationUnion2021` : International + Telecommunication Union. (2021). Recommendation ITU-T H.273 - + Coding-independent code points for video signal type identification. + https://www.itu.int/rec/T-REC-H.273-202107-I/en +""" + +import functools +import numpy as np +from dataclasses import dataclass +from enum import IntEnum, auto + +from colour.models.rgb.datasets.dcdm_xyz import ( + PRIMARIES_DCDM_XYZ, + WHITEPOINT_NAME_DCDM_XYZ, + CCS_WHITEPOINT_DCDM_XYZ, + MATRIX_DCDM_XYZ_TO_XYZ, + MATRIX_XYZ_TO_DCDM_XYZ, +) +from colour.models.rgb.datasets.dci_p3 import ( + PRIMARIES_DCI_P3, + WHITEPOINT_NAME_DCI_P3, + CCS_WHITEPOINT_DCI_P3, + MATRIX_DCI_P3_TO_XYZ, + MATRIX_XYZ_TO_DCI_P3, +) +from colour.models.rgb.datasets.itur_bt_2020 import ( + PRIMARIES_BT2020, + WHITEPOINT_NAME_BT2020, + CCS_WHITEPOINT_BT2020, + MATRIX_BT2020_TO_XYZ, + MATRIX_XYZ_TO_BT2020, +) +from colour.models.rgb.datasets.itur_bt_470 import ( + PRIMARIES_BT470_525, + CCS_WHITEPOINT_BT470_525, + WHITEPOINT_NAME_BT470_525, + MATRIX_BT470_525_TO_XYZ, + MATRIX_XYZ_TO_BT470_525, + PRIMARIES_BT470_625, + CCS_WHITEPOINT_BT470_625, + WHITEPOINT_NAME_BT470_625, + MATRIX_BT470_625_TO_XYZ, + MATRIX_XYZ_TO_BT470_625, +) +from colour.models.rgb.datasets.itur_bt_709 import ( + PRIMARIES_BT709, + CCS_WHITEPOINT_BT709, + WHITEPOINT_NAME_BT709, + MATRIX_BT709_TO_XYZ, + MATRIX_XYZ_TO_BT709, +) +from colour.models.rgb.datasets.itut_h_273 import ( + PRIMARIES_H273_GENERIC_FILM, + WHITEPOINT_NAME_H273_GENERIC_FILM, + CCS_WHITEPOINT_H273_GENERIC_FILM, + MATRIX_H273_GENERIC_FILM_RGB_TO_XYZ, + MATRIX_XYZ_TO_H273_GENERIC_FILM_RGB, + PRIMARIES_H273_22_UNSPECIFIED, + WHITEPOINT_NAME_H273_22_UNSPECIFIED, + CCS_WHITEPOINT_H273_22_UNSPECIFIED, + MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ, + MATRIX_XYZ_TO_H273_22_UNSPECIFIED_RGB, +) +from colour.models.rgb.datasets.p3_d65 import ( + PRIMARIES_P3_D65, + WHITEPOINT_NAME_P3_D65, + CCS_WHITEPOINT_P3_D65, + MATRIX_P3_D65_TO_XYZ, + MATRIX_XYZ_TO_P3_D65, +) +from colour.models.rgb.datasets.smpte_240m import ( + PRIMARIES_SMPTE_240M, + WHITEPOINT_NAME_SMPTE_240M, + CCS_WHITEPOINT_SMPTE_240M, + MATRIX_SMPTE_240M_TO_XYZ, + MATRIX_XYZ_TO_SMPTE_240M, +) +from colour.models.rgb.transfer_functions import ( + eotf_inverse_H273_ST428_1, + eotf_inverse_ST2084, + gamma_function, + linear_function, + oetf_BT1361, + oetf_BT2020, + oetf_BT2100_HLG, + oetf_BT601, + oetf_BT709, + oetf_H273_IEC61966_2, + oetf_H273_Log, + oetf_H273_LogSqrt, + oetf_SMPTE240M, +) +from colour.hints import ( + Any, + Boolean, + Callable, + Dict, + Integer, + List, + NDArray, + Tuple, + Union, +) +from colour.utilities import message_box, multiline_str +from colour.utilities.documentation import ( + DocstringDict, + is_documentation_building, +) + +__all__ = [ + "COLOUR_PRIMARIES_ITUTH273", + "FFmpegConstantsColourPrimaries_ITUTH273", + "TRANSFER_CHARACTERISTICS_ITUTH273", + "FFmpegConstantsTransferCharacteristics_ITUTH273", + "MATRIX_COEFFICIENTS_ITUTH273", + "FFmpegConstantsMatrixCoefficients_ITUTH273", + "CCS_WHITEPOINTS_ITUTH273", + "WHITEPOINT_NAMES_ITUTH273", + "MATRICES_ITUTH273_RGB_TO_XYZ", + "MATRICES_XYZ_TO_ITUTH273_RGB", + "COLOUR_PRIMARIES_ISO23091_2", + "TRANSFER_CHARACTERISTICS_ISO23091_2", + "MATRIX_COEFFICIENTS_ISO23091_2", + "CCS_WHITEPOINTS_ISO23091_2", + "WHITEPOINT_NAMES_ISO23091_2", + "MATRICES_ISO23091_2_RGB_TO_XYZ", + "MATRICES_XYZ_TO_ISO23091_2_RGB", + "COLOUR_PRIMARIES_23001_8", + "TRANSFER_CHARACTERISTICS_23001_8", + "MATRIX_COEFFICIENTS_23001_8", + "CCS_WHITEPOINTS_23001_8", + "WHITEPOINT_NAMES_23001_8", + "MATRICES_23001_8_RGB_TO_XYZ", + "MATRICES_XYZ_TO_23001_8_RGB", + "COLOUR_PRIMARIES_ISO14496_10", + "TRANSFER_CHARACTERISTICS_ISO14496_10", + "MATRIX_COEFFICIENTS_ISO14496_10", + "CCS_WHITEPOINTS_ISO14496_10", + "WHITEPOINT_NAMES_ISO14496_10", + "MATRICES_ISO14496_10_RGB_TO_XYZ", + "MATRICES_XYZ_TO_ISO14496_10_RGB", + "describe_video_signal_colour_primaries", + "describe_video_signal_transfer_characteristics", + "describe_video_signal_matrix_coefficients", +] + + +def _clipped_domain_function( + function: Callable, domain: Union[List, Tuple] = (0, 1) +) -> Callable: + """ + Wrap given function and produce a new callable clipping the input value to + given domain. + + Parameters + ---------- + function + Function to wrap. + domain + Domain to use for clipping. + + Examples + -------- + >>> linear_clipped = _clipped_domain_function(linear_function, (0.1, 0.9)) + >>> linear_clipped(1) # doctest: +ELLIPSIS + 0.9000000... + """ + + @functools.wraps(function) + def wrapped(x, *args: Any, **kwargs: Any) -> Any: + """Wrap given function.""" + + return function(np.clip(x, *domain), *args, **kwargs) + + return wrapped + + +def _reserved(*args: Any): + """ + Define a reserved function. + + Examples + -------- + >>> try: + ... _reserved() + ... except RuntimeError: + ... pass + """ + + raise RuntimeError("Reserved; For future use by ITU-T | ISO/IEC.") + + +def _unspecified(*args: Any): + """ + Define an unspecified function. + + Examples + -------- + >>> try: + ... _unspecified() + ... except RuntimeError: + ... pass + """ + + raise RuntimeError( + "Unspecified; Image characteristics are unknown or are determined by " + "the application." + ) + + +COLOUR_PRIMARIES_ITUTH273: Dict[Integer, NDArray] = { + 0: np.array("Reserved"), + # For future use by ITU-T | ISO/IEC. + # + 1: PRIMARIES_BT709, + # Rec. ITU-R BT.709-6 Rec. ITU-R BT.1361-0 conventional colour gamut + # system and extended colour gamut system (historical) IEC 61966-2-1 sRGB + # or sYCC IEC 61966-2-4 Society of Motion Picture and Television Engineers + # (SMPTE) RP 177 (1993) Annex B. + # + 2: np.array("Unspecified"), + # Image characteristics are unknown or are determined by the + # application. + # + 3: np.array("Reserved"), + # For future use by ITU-T | ISO/IEC. + # + 4: PRIMARIES_BT470_525, + # Rec. ITU-R BT.470-6 System M (historical) United States National + # Television System Committee 1953 Recommendation for transmission + # standards for color television United States Federal Communication + # Commission (2003) Title 47 Code of Federal Regulations 73.682 (a) (20). + # + 5: PRIMARIES_BT470_625, + # 5: Rec. ITU-R BT.470-6 System B, G (historical) Rec. ITU-R BT.601-7 625 + # Rec. ITU-R BT.1358-0 625 (historical) Rec. ITU-R BT.1700-0 625 PAL and + # 625 SECAM. + # + 6: PRIMARIES_SMPTE_240M, + # 6: Rec. ITU-R BT.601-7 525 Rec. ITU-R BT.1358-1 525 or 625 (historical) + # Rec. ITU-R BT.1700-0 NTSC SMPTE ST 170 (2004) (functionally the same as + # the value 7). + # + 7: PRIMARIES_SMPTE_240M, + # SMPTE ST 240 (1999) (functionally the same as the value 6). + # + 8: PRIMARIES_H273_GENERIC_FILM, + # Generic film (colour filters using Illuminant C), Red: Wratten 25, + # Green: Wratten 58, Blue: Wratten 47. + # + 9: PRIMARIES_BT2020, + # Rec. ITU-R BT.2020-2 Rec. ITU-R BT.2100-2. + # + 10: PRIMARIES_DCDM_XYZ, + # SMPTE ST 428-1 (2019) (CIE 1931 XYZ as in ISO 11664-1). + # + 11: PRIMARIES_DCI_P3, + # SMPTE RP 431-2 (2011). + # + 12: PRIMARIES_P3_D65, + # SMPTE EG 432-1 (2010). + # + # 13-21: + # For future use by ITU-T | ISO/IEC. + # + 22: PRIMARIES_H273_22_UNSPECIFIED, + # No corresponding industry specification identified. + # + 23: np.array("Reserved"), + # 23-255: + # For future use by ITU-T | ISO/IEC. + # +} +if is_documentation_building(): # pragma: no cover + COLOUR_PRIMARIES_ITUTH273 = DocstringDict(COLOUR_PRIMARIES_ITUTH273) + COLOUR_PRIMARIES_ITUTH273.__doc__ = """ +*ColourPrimaries* indicates the chromaticity coordinates of the source colour +primaries as specified in Table 3 of +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021` in terms of the CIE 1931 +definition of x and y, which shall be interpreted as specified by +*ISO/ CIE 11664-1*. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` +""" + + +class FFmpegConstantsColourPrimaries_ITUTH273(IntEnum): + """ + Define the constant names used by *FFmpeg* in the `AVColorPrimaries` enum. + + Notes + ----- + - *AVCOL_PRI_JEDEC_P22* is equal to `AVCOL_PRI_EBU3213` in *FFmpeg* + but neither *Recommendation ITU-T H.273* (2021) nor *ISO/IEC 23091-2* + (2021) define the same primaries as *EBU Tech 3213*, nor do they refer + to it. *ColourPrimaries 22* in both standards specifies the + informative remark *No corresponding industry specification identified*. + However, *ISO/IEC 23001-8* (2013) and *ISO/IEC 14497-10* (2020) + specify the *JEDEC P22 phosphors* and *EBU Tech. 3213-E (1975)* + informative remarks respectively while defining the same primaries and + whitepoint as the 2021 standards. This is likely an error in the + earlier standards that was discovered and corrected. + + References + ---------- + :cite:`FFmpegDevelopers2022`, + :cite:`InternationalOrganizationforStandardization2013`, + :cite:`InternationalOrganizationforStandardization2021`, + :cite:`InternationalOrganizationforStandardization2020`, + :cite:`InternationalTelecommunicationUnion2021` + """ + + AVCOL_PRI_RESERVED0 = 0 + AVCOL_PRI_BT709 = 1 + AVCOL_PRI_UNSPECIFIED = 2 + AVCOL_PRI_RESERVED = 3 + AVCOL_PRI_BT470M = 4 + AVCOL_PRI_BT470BG = 5 + AVCOL_PRI_SMPTE170M = 6 + AVCOL_PRI_SMPTE240M = 7 + AVCOL_PRI_FILM = 8 + AVCOL_PRI_BT2020 = 9 + AVCOL_PRI_SMPTE428 = 10 + AVCOL_PRI_SMPTEST428_1 = AVCOL_PRI_SMPTE428 + AVCOL_PRI_SMPTE431 = 11 + AVCOL_PRI_SMPTE432 = 12 + AVCOL_PRI_EBU3213 = 22 + AVCOL_PRI_JEDEC_P22 = AVCOL_PRI_EBU3213 + AVCOL_PRI_NB = auto() + + RESERVED0 = AVCOL_PRI_RESERVED0 + BT709 = AVCOL_PRI_BT709 + UNSPECIFIED = AVCOL_PRI_UNSPECIFIED + RESERVED = AVCOL_PRI_RESERVED + BT470M = AVCOL_PRI_BT470M + BT470BG = AVCOL_PRI_BT470BG + SMPTE170M = AVCOL_PRI_SMPTE170M + SMPTE240M = AVCOL_PRI_SMPTE240M + FILM = AVCOL_PRI_FILM + BT2020 = AVCOL_PRI_BT2020 + SMPTE428 = AVCOL_PRI_SMPTE428 + SMPTEST428_1 = AVCOL_PRI_SMPTEST428_1 + SMPTE431 = AVCOL_PRI_SMPTE431 + SMPTE432 = AVCOL_PRI_SMPTE432 + EBU3213 = AVCOL_PRI_EBU3213 + JEDEC_P22 = AVCOL_PRI_JEDEC_P22 + NB = AVCOL_PRI_NB + + +TRANSFER_CHARACTERISTICS_ITUTH273: Dict[Integer, Callable] = { + 0: _reserved, + # For future use by ITU-T | ISO/IEC. + # + 1: _clipped_domain_function(oetf_BT709), + # Rec. ITU-R BT.709-6 Rec. ITU-R BT.1361-0 conventional colour gamut + # system (historical) (functionally the same as the values 6, 14 and 15). + # + 2: _unspecified, + # Image characteristics are unknown or are determined by the + # application. + # + 3: _reserved, + # For future use by ITU-T | ISO/IEC. + # + 4: _clipped_domain_function( + functools.partial(gamma_function, exponent=1 / 2.2) + ), + # Assumed display gamma 2.2 Rec. ITU-R BT.470-6 System M (historical) + # United States National Television System Committee 1953 Recommendation + # for transmission standards for color television United States Federal + # Communications Commission (2003) Title 47 Code of Federal Regulations + # 73.682 (a) (20) Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM. + # + 5: _clipped_domain_function( + functools.partial(gamma_function, exponent=1 / 2.8) + ), + # 5: Assumed display gamma 2.8 Rec. ITU-R BT.470-6 System B, G (historical). + # + 6: _clipped_domain_function(oetf_BT601), + # Rec. ITU-R BT.601-7 525 or 625 Rec. ITU-R BT.1358-1 525 or 625 + # (historical) Rec. ITU-R BT.1700-0 NTSC SMPTE ST 170 (2004) (functionally + # the same as the values 1, 14 and 15). + # + 7: _clipped_domain_function(oetf_SMPTE240M), + # SMPTE ST 240 (1999). + # + 8: _clipped_domain_function(linear_function), + # Linear transfer characteristics. + # + 9: _clipped_domain_function(oetf_H273_Log), + # Logarithmic transfer characteristic (100:1 range). + # + 10: _clipped_domain_function(oetf_H273_LogSqrt), + # Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range). + # + 11: oetf_H273_IEC61966_2, + # IEC 61966-2-4. + # + 12: _clipped_domain_function(oetf_BT1361, (-0.25, 1.33)), + # Rec. ITU-R BT.1361-0 extended colour gamut system (historical). + # + 13: oetf_H273_IEC61966_2, + # IEC 61966-2-1 sRGB (with MatrixCoefficients equal to 0) + # IEC 61966-2-1 sYCC (with MatrixCoefficients equal to 5). + # + 14: _clipped_domain_function( + functools.partial(oetf_BT2020, is_12_bits_system=False) + ), + # Rec. ITU-R BT.2020-2 (10-bit system) (functionally the same as the values + # 1, 6 and 15). + # + 15: _clipped_domain_function( + functools.partial(oetf_BT2020, is_12_bits_system=True) + ), + # Rec. ITU-R BT.2020-2 (12-bit system) (functionally the same as the values + # 1, 6 and 14). + # + 16: eotf_inverse_ST2084, + # SMPTE ST 2084 (2014) for 10-, 12-, 14- and 16-bit systems Rec. + # ITU-R BT.2100-2 perceptual quantization (PQ) system. + # + 17: eotf_inverse_H273_ST428_1, + # SMPTE ST 428-1 (2019). + # + 18: oetf_BT2100_HLG, + # ARIB STD-B67 (2015) Rec. ITU-R BT.2100-2 hybrid log-gamma (HLG) system. + # + 19: _reserved, + # 19-255: + # For future use by ITU-T | ISO/IEC. + # +} +if is_documentation_building(): # pragma: no cover + TRANSFER_CHARACTERISTICS_ITUTH273 = DocstringDict( + TRANSFER_CHARACTERISTICS_ITUTH273 + ) + TRANSFER_CHARACTERISTICS_ITUTH273.__doc__ = """ +*TransferCharacteristics*, as specified in Table 3 of +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021`, either indicates the reference +opto-electronic transfer characteristic function of the source picture as a +function of a source input linear optical intensity input Lc with a nominal +real-valued range of 0 to 1 or indicates the inverse of the reference +electro-optical transfer characteristic function as a function of an output +linear optical intensity Lo with a nominal real-valued range of 0 to 1. + +Notes +----- +- For simplicity, no clipping is implemented for *TransferCharacteristics 13* + as it is a function of whether the context is *sRGB* or *sYCC*. +- For TransferCharacteristics equal to 18, the equations given in Table 3 are + normalized for a source input linear optical intensity Lc with a nominal + real-valued range of 0 to 1. An alternative scaling that is mathematically + equivalent is used in ARIB STD-B67 (2015) with the source input linear + optical intensity having a nominal real-valued range of 0 to 12. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` +""" + + +class FFmpegConstantsTransferCharacteristics_ITUTH273(IntEnum): + """ + Define the constant names used by *FFmpeg* in the + `AVColorTransferCharacteristic` enum. + + References + ---------- + :cite:`FFmpegDevelopers2022a`, + :cite:`InternationalOrganizationforStandardization2013`, + :cite:`InternationalOrganizationforStandardization2021`, + :cite:`InternationalOrganizationforStandardization2020`, + :cite:`InternationalTelecommunicationUnion2021` + """ + + AVCOL_TRC_RESERVED0 = 0 + AVCOL_TRC_BT709 = 1 + AVCOL_TRC_UNSPECIFIED = 2 + AVCOL_TRC_RESERVED = 3 + AVCOL_TRC_GAMMA22 = 4 + AVCOL_TRC_GAMMA28 = 5 + AVCOL_TRC_SMPTE170M = 6 + AVCOL_TRC_SMPTE240M = 7 + AVCOL_TRC_LINEAR = 8 + AVCOL_TRC_LOG = 9 + AVCOL_TRC_LOG_SQRT = 10 + AVCOL_TRC_IEC61966_2_4 = 11 + AVCOL_TRC_BT1361_ECG = 12 + AVCOL_TRC_IEC61966_2_1 = 13 + AVCOL_TRC_BT2020_10 = 14 + AVCOL_TRC_BT2020_12 = 15 + AVCOL_TRC_SMPTE2084 = 16 + AVCOL_TRC_SMPTEST2084 = AVCOL_TRC_SMPTE2084 + AVCOL_TRC_SMPTE428 = 17 + AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428 + AVCOL_TRC_ARIB_STD_B67 = 18 + AVCOL_TRC_NB = auto() + + RESERVED0 = AVCOL_TRC_RESERVED0 + BT709 = AVCOL_TRC_BT709 + UNSPECIFIED = AVCOL_TRC_UNSPECIFIED + RESERVED = AVCOL_TRC_RESERVED + GAMMA22 = AVCOL_TRC_GAMMA22 + GAMMA28 = AVCOL_TRC_GAMMA28 + SMPTE170M = AVCOL_TRC_SMPTE170M + SMPTE240M = AVCOL_TRC_SMPTE240M + LINEAR = AVCOL_TRC_LINEAR + LOG = AVCOL_TRC_LOG + LOG_SQRT = AVCOL_TRC_LOG_SQRT + IEC61966_2_4 = AVCOL_TRC_IEC61966_2_4 + BT1361_ECG = AVCOL_TRC_BT1361_ECG + IEC61966_2_1 = AVCOL_TRC_IEC61966_2_1 + BT2020_10 = AVCOL_TRC_BT2020_10 + BT2020_12 = AVCOL_TRC_BT2020_12 + SMPTE2084 = AVCOL_TRC_SMPTE2084 + SMPTEST2084 = AVCOL_TRC_SMPTEST2084 + SMPTE428 = AVCOL_TRC_SMPTE428 + SMPTEST428_1 = AVCOL_TRC_SMPTEST428_1 + ARIB_STD_B67 = AVCOL_TRC_ARIB_STD_B67 + NB = AVCOL_TRC_NB + + +MATRIX_COEFFICIENTS_ITUTH273: Dict[Integer, NDArray] = { + 0: np.array("Identity"), + # The identity matrix. Typically used for GBR (often referred to as RGB); + # however, may also be used for YZX (often referred to as XYZ); + # IEC 61966-2-1 sRGB SMPTE ST 428-1 (2019) See equations 41 to 43. + # + 1: np.array([0.2126, 0.0722]), + # Rec. ITU-R BT.709-6 Rec. ITU-R BT.1361-0 conventional colour gamut system + # and extended colour gamut system (historical) IEC 61966-2-4 xvYCC709 + # SMPTE RP 177 (1993) Annex B See equations 38 to 40. + # + 2: np.array("Unspecified"), + # Image characteristics are unknown or are determined by the application. + # + 3: np.array("Reserved"), + # For future use by ITU-T | ISO/IEC. + # + 4: np.array([0.30, 0.11]), + # United States Federal Communications Commission (2003) Title 47 Code of + # Federal Regulations 73.682 (a) (20) See equations 38 to 40. + # + 5: np.array([0.299, 0.114]), + # Rec. ITU-R BT.470-6 System B, G (historical) Rec. ITU-R BT.601-7 625 + # Rec. ITU-R BT.1358-0 625 (historical) Rec. ITU-R BT.1700-0 625 PAL and + # 625 SECAM IEC 61966-2-1 sYCC IEC 61966-2-4 xvYCC601 (functionally the + # same as the value 6) See equations 38 to 40. + # + 6: np.array([0.299, 0.114]), + # Rec. ITU-R BT.601-7 525 Rec. ITU-R BT.1358-1 525 or 625 (historical) + # Rec. ITU-R BT.1700-0 NTSC SMPTE ST 170 (2004) (functionally the same as + # the value 5) See equations 38 to 40. + # + 7: np.array([0.212, 0.087]), + # SMPTE ST 240 (1999) See equations 38 to 40. + # + 8: np.array("YCgCo"), + # See equations 44 to 58. + # + 9: np.array([0.2627, 0.0593]), + # Rec. ITU-R BT.2020-2 (non-constant luminance) Rec. ITU-R BT.2100-2 + # Y'CbCr See equations 38 to 40. + # + 10: np.array([0.2627, 0.0593]), + # Rec. ITU-R BT.2020-2 (constant luminance) See equations 59 to 68. + # + 11: np.array("Y'D'ZD'X"), + # SMPTE ST 2085 (2015) See equations 69 to 71. + # + 12: np.array("See equations 32 to 37"), + # Chromaticity-derived non-constant luminance system See equations 38 to 40. + # + 13: np.array("See equations 32 to 37"), + # Chromaticity-derived constant luminance system See equations 59 to 68. + # + 14: np.array("ICTCP"), + # Rec. ITU-R BT.2100-2 ICTCP See equations 72 to 74 for + # TransferCharacteristics value 16 (PQ) See equations 75 to 77 for + # TransferCharacteristics value 18 (HLG). + # + 15: np.array("Reserved"), + # 15-255: + # For future use by ITU-T | ISO/IEC. + # +} +if is_documentation_building(): # pragma: no cover + MATRIX_COEFFICIENTS_ITUTH273 = DocstringDict(MATRIX_COEFFICIENTS_ITUTH273) + MATRIX_COEFFICIENTS_ITUTH273.__doc__ = """ +*MatrixCoefficients* describes the matrix coefficients used in deriving luma +and chroma signals from the green, blue and red or X, Y and Z primaries, as +specified in Table 4 and equations 11 to 77 of +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021`. + +Notes +----- +- See :attr:`colour.WEIGHTS_YCBCR` attribute and the + :func:`colour.matrix_YCbCr`, :func:`colour.offset_YCbCr`, + :func:`colour.RGB_to_YCbCr`, :func:`colour.YCbCr_to_RGB`, + :func:`colour.RGB_to_YcCbcCrc`, :func:`colour.YcCbcCrc_to_RGB` definitions + for an implementation. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` +""" + + +class FFmpegConstantsMatrixCoefficients_ITUTH273(IntEnum): + """ + Define the constant names used by *FFmpeg* in the `AVColorSpace` enum. + + References + ---------- + :cite:`FFmpegDevelopers2022b`, + :cite:`InternationalOrganizationforStandardization2013`, + :cite:`InternationalOrganizationforStandardization2021`, + :cite:`InternationalOrganizationforStandardization2020`, + :cite:`InternationalTelecommunicationUnion2021` + """ + + AVCOL_SPC_RGB = 0 + AVCOL_SPC_BT709 = 1 + AVCOL_SPC_UNSPECIFIED = 2 + AVCOL_SPC_RESERVED = 3 + AVCOL_SPC_FCC = 4 + AVCOL_SPC_BT470BG = 5 + AVCOL_SPC_SMPTE170M = 6 + AVCOL_SPC_SMPTE240M = 7 + AVCOL_SPC_YCGCO = 8 + AVCOL_SPC_YCOCG = AVCOL_SPC_YCGCO + AVCOL_SPC_BT2020_NCL = 9 + AVCOL_SPC_BT2020_CL = 10 + AVCOL_SPC_SMPTE2085 = 11 + AVCOL_SPC_CHROMA_DERIVED_NCL = 12 + AVCOL_SPC_CHROMA_DERIVED_CL = 13 + AVCOL_SPC_ICTCP = 14 + AVCOL_SPC_NB = auto() + + RGB = AVCOL_SPC_RGB + BT709 = AVCOL_SPC_BT709 + UNSPECIFIED = AVCOL_SPC_UNSPECIFIED + RESERVED = AVCOL_SPC_RESERVED + FCC = AVCOL_SPC_FCC + BT470BG = AVCOL_SPC_BT470BG + SMPTE170M = AVCOL_SPC_SMPTE170M + SMPTE240M = AVCOL_SPC_SMPTE240M + YCGCO = AVCOL_SPC_YCGCO + YCOCG = AVCOL_SPC_YCOCG + BT2020_NCL = AVCOL_SPC_BT2020_NCL + BT2020_CL = AVCOL_SPC_BT2020_CL + SMPTE2085 = AVCOL_SPC_SMPTE2085 + CHROMA_DERIVED_NCL = AVCOL_SPC_CHROMA_DERIVED_NCL + CHROMA_DERIVED_CL = AVCOL_SPC_CHROMA_DERIVED_CL + ICTCP = AVCOL_SPC_ICTCP + NB = AVCOL_SPC_NB + + +CCS_WHITEPOINTS_ITUTH273: Dict[Integer, NDArray] = { + 0: np.array("Reserved"), + 1: CCS_WHITEPOINT_BT709, + 2: np.array("Unspecified"), + 3: np.array("Reserved"), + 4: np.around(CCS_WHITEPOINT_BT470_525, 3), + 5: CCS_WHITEPOINT_BT470_625, + 6: CCS_WHITEPOINT_SMPTE_240M, + 7: CCS_WHITEPOINT_SMPTE_240M, + 8: CCS_WHITEPOINT_H273_GENERIC_FILM, + 9: CCS_WHITEPOINT_BT2020, + 10: CCS_WHITEPOINT_DCDM_XYZ, + 11: CCS_WHITEPOINT_DCI_P3, + 12: CCS_WHITEPOINT_P3_D65, + 22: CCS_WHITEPOINT_H273_22_UNSPECIFIED, + 23: np.array("Reserved"), +} +if is_documentation_building(): # pragma: no cover + CCS_WHITEPOINTS_ITUTH273 = DocstringDict(CCS_WHITEPOINTS_ITUTH273) + CCS_WHITEPOINTS_ITUTH273.__doc__ = """ +Chromaticity coordinates of the whitepoints associated with the source colour +primaries as specified in Table 3 of +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021` in terms of the CIE 1931 +definition of x and y, which shall be interpreted as specified by +*ISO/ CIE 11664-1*. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` + +Notes +----- +- :cite:`InternationalTelecommunicationUnion2021` defines + *CIE Illuminant C* as [0.310, 0.316], while *Colour* definition has a + slightly higher precision. +""" + + +WHITEPOINT_NAMES_ITUTH273: Dict[Integer, str] = { + 0: "Reserved", + 1: WHITEPOINT_NAME_BT709, + 2: "Unspecified", + 3: "Reserved", + 4: WHITEPOINT_NAME_BT470_525, + 5: WHITEPOINT_NAME_BT470_625, + 6: WHITEPOINT_NAME_SMPTE_240M, + 7: WHITEPOINT_NAME_SMPTE_240M, + 8: WHITEPOINT_NAME_H273_GENERIC_FILM, + 9: WHITEPOINT_NAME_BT2020, + 10: WHITEPOINT_NAME_DCDM_XYZ, + 11: WHITEPOINT_NAME_DCI_P3, + 12: WHITEPOINT_NAME_P3_D65, + 22: WHITEPOINT_NAME_H273_22_UNSPECIFIED, + 23: "Reserved", +} +if is_documentation_building(): # pragma: no cover + WHITEPOINT_NAMES_ITUTH273 = DocstringDict(WHITEPOINT_NAMES_ITUTH273) + WHITEPOINT_NAMES_ITUTH273.__doc__ = """ +Whitepoint names associated with the source colour primaries as specified in +Table 3 of :cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021`. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` +""" + + +MATRICES_ITUTH273_RGB_TO_XYZ = { + 0: np.array("Reserved"), + 1: MATRIX_BT709_TO_XYZ, + 2: np.array("Unspecified"), + 3: np.array("Reserved"), + 4: MATRIX_BT470_525_TO_XYZ, + 5: MATRIX_BT470_625_TO_XYZ, + 6: MATRIX_SMPTE_240M_TO_XYZ, + 7: MATRIX_SMPTE_240M_TO_XYZ, + 8: MATRIX_H273_GENERIC_FILM_RGB_TO_XYZ, + 9: MATRIX_BT2020_TO_XYZ, + 10: MATRIX_DCDM_XYZ_TO_XYZ, + 11: MATRIX_DCI_P3_TO_XYZ, + 12: MATRIX_P3_D65_TO_XYZ, + 22: MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ, + 23: np.array("Reserved"), +} +if is_documentation_building(): # pragma: no cover + WHITEPOINT_NAMES_ITUTH273 = DocstringDict(WHITEPOINT_NAMES_ITUTH273) + WHITEPOINT_NAMES_ITUTH273.__doc__ = """ +*RGB* to *CIE XYZ* tristimulus values matrices associated with the source +colour primaries as specified in Table 3 of +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021`. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` +""" + +MATRICES_XYZ_TO_ITUTH273_RGB = { + 0: np.array("Reserved"), + 1: MATRIX_XYZ_TO_BT709, + 2: np.array("Unspecified"), + 3: np.array("Reserved"), + 4: MATRIX_XYZ_TO_BT470_525, + 5: MATRIX_XYZ_TO_BT470_625, + 6: MATRIX_XYZ_TO_SMPTE_240M, + 7: MATRIX_XYZ_TO_SMPTE_240M, + 8: MATRIX_XYZ_TO_H273_GENERIC_FILM_RGB, + 9: MATRIX_XYZ_TO_BT2020, + 10: MATRIX_XYZ_TO_DCDM_XYZ, + 11: MATRIX_XYZ_TO_DCI_P3, + 12: MATRIX_XYZ_TO_P3_D65, + 22: MATRIX_XYZ_TO_H273_22_UNSPECIFIED_RGB, + 23: np.array("Reserved"), +} +if is_documentation_building(): # pragma: no cover + WHITEPOINT_NAMES_ITUTH273 = DocstringDict(WHITEPOINT_NAMES_ITUTH273) + WHITEPOINT_NAMES_ITUTH273.__doc__ = """ +*CIE XYZ* tristimulus values to *RGB* matrices associated with the source +colour primaries as specified in Table 3 of +:cite:`InternationalOrganizationforStandardization2021` and +:cite:`InternationalTelecommunicationUnion2021`. + +References +---------- +:cite:`InternationalOrganizationforStandardization2013` +:cite:`InternationalOrganizationforStandardization2020` +:cite:`InternationalOrganizationforStandardization2021`, +:cite:`InternationalTelecommunicationUnion2021` +""" + + +# Aliases for *ISO/IEC 23091-2* (2021). +# +# Verified to be functionally identical to *Recommendation ITU-T H.273* for +# the values defined here. +COLOUR_PRIMARIES_ISO23091_2 = COLOUR_PRIMARIES_ITUTH273 +TRANSFER_CHARACTERISTICS_ISO23091_2 = TRANSFER_CHARACTERISTICS_ITUTH273 +MATRIX_COEFFICIENTS_ISO23091_2 = MATRIX_COEFFICIENTS_ITUTH273 +CCS_WHITEPOINTS_ISO23091_2 = CCS_WHITEPOINTS_ITUTH273 +WHITEPOINT_NAMES_ISO23091_2 = WHITEPOINT_NAMES_ITUTH273 +MATRICES_ISO23091_2_RGB_TO_XYZ = MATRICES_ITUTH273_RGB_TO_XYZ +MATRICES_XYZ_TO_ISO23091_2_RGB = MATRICES_XYZ_TO_ITUTH273_RGB + +# Aliases for *ISO/IEC 23001-8* (2013). +# +# Verified to be functionally identical to *Recommendation ITU-T H.273* for +# the values defined here except for the note regarding *EBU Tech 3213* and +# *ColourPrimaries 22*. +COLOUR_PRIMARIES_23001_8 = COLOUR_PRIMARIES_ITUTH273 +TRANSFER_CHARACTERISTICS_23001_8 = TRANSFER_CHARACTERISTICS_ITUTH273 +MATRIX_COEFFICIENTS_23001_8 = MATRIX_COEFFICIENTS_ITUTH273 +CCS_WHITEPOINTS_23001_8 = CCS_WHITEPOINTS_ITUTH273 +WHITEPOINT_NAMES_23001_8 = WHITEPOINT_NAMES_ITUTH273 +MATRICES_23001_8_RGB_TO_XYZ = MATRICES_ITUTH273_RGB_TO_XYZ +MATRICES_XYZ_TO_23001_8_RGB = MATRICES_XYZ_TO_ITUTH273_RGB + +# Aliases for *ISO/IEC 14496-10* (2020). +# +# Verified to be functionally identical to *Recommendation ITU-T H.273* for +# the values defined here except for the note regarding *EBU Tech 3213* and +# *ColourPrimaries 22*. +COLOUR_PRIMARIES_ISO14496_10 = COLOUR_PRIMARIES_ITUTH273 +TRANSFER_CHARACTERISTICS_ISO14496_10 = TRANSFER_CHARACTERISTICS_ITUTH273 +MATRIX_COEFFICIENTS_ISO14496_10 = MATRIX_COEFFICIENTS_ITUTH273 +CCS_WHITEPOINTS_ISO14496_10 = CCS_WHITEPOINTS_ITUTH273 +WHITEPOINT_NAMES_ISO14496_10 = WHITEPOINT_NAMES_ITUTH273 +MATRICES_ISO14496_10_RGB_TO_XYZ = MATRICES_ITUTH273_RGB_TO_XYZ +MATRICES_XYZ_TO_ISO14496_10_RGB = MATRICES_XYZ_TO_ITUTH273_RGB + + +def describe_video_signal_colour_primaries( + code_point: Integer, print_description: Boolean = True, **kwargs +) -> str: + """ + Describe given video signal colour primaries code point. + + Parameters + ---------- + code_point + Video signal colour primaries code point to describe from + :attr:`colour.COLOUR_PRIMARIES_ITUTH273` attribute. + print_description + Whether to print the description. + + Other Parameters + ---------------- + padding + {:func:`colour.utilities.message_box`}, + Padding on each side of the message. + print_callable + {:func:`colour.utilities.message_box`}, + Callable used to print the message box. + width + {:func:`colour.utilities.message_box`}, + Message box width. + + Returns + ------- + str + Video signal colour primaries code point description. + + References + ---------- + :cite:`FFmpegDevelopers2022`, + :cite:`InternationalOrganizationforStandardization2013`, + :cite:`InternationalOrganizationforStandardization2021`, + :cite:`InternationalOrganizationforStandardization2020`, + :cite:`InternationalTelecommunicationUnion2021` + + Examples + -------- + >>> description = describe_video_signal_colour_primaries(1, width=75) + =========================================================================== + * * + * Colour Primaries: 1 * + * ------------------- * + * * + * Primaries : [[ 0.64 0.33] * + * [ 0.3 0.6 ] * + * [ 0.15 0.06]] * + * Whitepoint : [ 0.3127 0.329 ] * + * Whitepoint Name : D65 * + * NPM : [[ 0.4123908 0.35758434 0.18048079] * + * [ 0.21263901 0.71516868 0.07219232] * + * [ 0.01933082 0.11919478 0.95053215]] * + * NPM -1 : [[ 3.24096994 -1.53738318 -0.49861076] * + * [-0.96924364 1.8759675 0.04155506] * + * [ 0.05563008 -0.20397696 1.05697151]] * + * FFmpeg Constants : ['AVCOL_PRI_BT709', 'BT709'] * + * * + =========================================================================== + >>> description = describe_video_signal_colour_primaries(2, width=75) + =========================================================================== + * * + * Colour Primaries: 2 * + * ------------------- * + * * + * Primaries : Unspecified * + * Whitepoint : Unspecified * + * Whitepoint Name : Unspecified * + * NPM : Unspecified * + * NPM -1 : Unspecified * + * FFmpeg Constants : ['AVCOL_PRI_UNSPECIFIED', 'UNSPECIFIED'] * + * * + =========================================================================== + >>> description = describe_video_signal_colour_primaries( + ... FFmpegConstantsColourPrimaries_ITUTH273.JEDEC_P22, width=75 + ... ) + =========================================================================== + * * + * Colour Primaries: 22 * + * -------------------- * + * * + * Primaries : [[ 0.63 0.34 ] * + * [ 0.295 0.605] * + * [ 0.155 0.077]] * + * Whitepoint : [ 0.3127 0.329 ] * + * Whitepoint Name : D65 * + * NPM : [[ 0.42942013 0.3277917 0.1932441 ] * + * [ 0.23175055 0.67225077 0.09599868] * + * [ 0.02044858 0.11111583 0.95749334]] * + * NPM -1 : [[ 3.13288278 -1.44707454 -0.48720324] * + * [-1.08850877 2.01538781 0.01762239] * + * [ 0.05941301 -0.20297883 1.05275352]] * + * FFmpeg Constants : ['AVCOL_PRI_EBU3213', 'AVCOL_PRI_JEDEC_P22', * + * 'EBU3213', 'JEDEC_P22'] * + * * + =========================================================================== + """ + + @dataclass + class SpecificationColourPrimaries: + """Specification for video signal colour primaries code point.""" + + code_point: Integer + primaries: NDArray + whitepoint: NDArray + whitepoint_name: str + matrix_RGB_to_XYZ: NDArray + matrix_XYZ_to_RGB: NDArray + ffmpeg_constants: List + + members = FFmpegConstantsColourPrimaries_ITUTH273.__members__.items() + ffmpeg_constants = [ + name + for name, member in members + if member.name.startswith("AVCOL_PRI_") and member.value == code_point + ] + + description = SpecificationColourPrimaries( + code_point, + COLOUR_PRIMARIES_ITUTH273[code_point], + CCS_WHITEPOINTS_ITUTH273[code_point], + WHITEPOINT_NAMES_ITUTH273[code_point], + MATRICES_ITUTH273_RGB_TO_XYZ[code_point], + MATRICES_XYZ_TO_ITUTH273_RGB[code_point], + ffmpeg_constants, + ) + + message = multiline_str( + description, + [ + { + "name": "code_point", + "section": True, + "formatter": lambda x: f"Colour Primaries: {x}", + }, + {"line_break": True}, + {"name": "primaries", "label": "Primaries"}, + {"name": "whitepoint", "label": "Whitepoint"}, + {"name": "whitepoint_name", "label": "Whitepoint Name"}, + {"name": "matrix_RGB_to_XYZ", "label": "NPM"}, + {"name": "matrix_XYZ_to_RGB", "label": "NPM -1"}, + {"name": "ffmpeg_constants", "label": "FFmpeg Constants"}, + ], + ) + + if print_description: + message_box( + message, + **kwargs, + ) + + return message + + +def describe_video_signal_transfer_characteristics( + code_point: Integer, print_description: Boolean = True, **kwargs +) -> str: + """ + Describe given video signal transfer characteristics code point. + + Parameters + ---------- + code_point + Video signal transfer characteristics code point to describe from + :attr:`colour.TRANSFER_CHARACTERISTICS_ITUTH273` attribute. + print_description + Whether to print the description. + + Other Parameters + ---------------- + padding + {:func:`colour.utilities.message_box`}, + Padding on each side of the message. + print_callable + {:func:`colour.utilities.message_box`}, + Callable used to print the message box. + width + {:func:`colour.utilities.message_box`}, + Message box width. + + Returns + ------- + str + Video signal colour primaries code point description. + + References + ---------- + :cite:`FFmpegDevelopers2022a`, + :cite:`InternationalOrganizationforStandardization2013`, + :cite:`InternationalOrganizationforStandardization2021`, + :cite:`InternationalOrganizationforStandardization2020`, + :cite:`InternationalTelecommunicationUnion2021` + + Examples + -------- + >>> description = describe_video_signal_transfer_characteristics(1, width=75) + ... # doctest: +ELLIPSIS + =========================================================================== + * * + * Transfer Characteristics: 1 * + * --------------------------- * + * * + * Function : ...* + * FFmpeg Constants : ['AVCOL_TRC_BT709', 'BT709'] * + * * + =========================================================================== + >>> description = describe_video_signal_transfer_characteristics(2, width=75) + ... # doctest: +ELLIPSIS + =========================================================================== + * * + * Transfer Characteristics: 2 * + * --------------------------- * + * * + * Function : ...* + * FFmpeg Constants : ['AVCOL_TRC_UNSPECIFIED', 'UNSPECIFIED'] * + * * + =========================================================================== + >>> description = describe_video_signal_transfer_characteristics( + ... FFmpegConstantsTransferCharacteristics_ITUTH273.SMPTE428, width=75 + ... ) + ... # doctest: +ELLIPSIS + =========================================================================== + * * + * Transfer Characteristics: 17 * + * ---------------------------- * + * * + * Function : ...* + * FFmpeg Constants : ['AVCOL_TRC_SMPTE428', 'AVCOL_TRC_SMPTEST428_1', * + * 'SMPTE428', 'SMPTEST428_1'] * + * * + =========================================================================== + """ + + @dataclass + class SpecificationTransferCharacteristics: + """Specification for video signal transfer characteristics code point.""" + + code_point: Integer + function: Callable + ffmpeg_constants: List + + members = ( + FFmpegConstantsTransferCharacteristics_ITUTH273.__members__.items() + ) + ffmpeg_constants = [ + name + for name, member in members + if member.name.startswith("AVCOL_TRC_") and member.value == code_point + ] + + description = SpecificationTransferCharacteristics( + code_point, + TRANSFER_CHARACTERISTICS_ITUTH273[code_point], + ffmpeg_constants, + ) + + message = multiline_str( + description, + [ + { + "name": "code_point", + "section": True, + "formatter": lambda x: f"Transfer Characteristics: {x}", + }, + {"line_break": True}, + {"name": "function", "label": "Function"}, + {"name": "ffmpeg_constants", "label": "FFmpeg Constants"}, + ], + ) + + if print_description: + message_box( + message, + **kwargs, + ) + + return message + + +def describe_video_signal_matrix_coefficients( + code_point: Integer, print_description: Boolean = True, **kwargs +) -> str: + """ + Describe given video signal matrix coefficients code point. + + Parameters + ---------- + code_point + Video signal matrix coefficients code point to describe from + :attr:`colour.MATRIX_COEFFICIENTS_ITUTH273` attribute. + print_description + Whether to print the description. + + Other Parameters + ---------------- + padding + {:func:`colour.utilities.message_box`}, + Padding on each side of the message. + print_callable + {:func:`colour.utilities.message_box`}, + Callable used to print the message box. + width + {:func:`colour.utilities.message_box`}, + Message box width. + + Returns + ------- + str + Video signal colour primaries code point description. + + References + ---------- + :cite:`FFmpegDevelopers2022b`, + :cite:`InternationalOrganizationforStandardization2013`, + :cite:`InternationalOrganizationforStandardization2021`, + :cite:`InternationalOrganizationforStandardization2020`, + :cite:`InternationalTelecommunicationUnion2021` + + Examples + -------- + >>> description = describe_video_signal_matrix_coefficients(1, width=75) + =========================================================================== + * * + * Matrix Coefficients: 1 * + * ---------------------- * + * * + * Matrix Coefficients : [ 0.2126 0.0722] * + * FFmpeg Constants : ['AVCOL_SPC_BT709', 'BT709'] * + * * + =========================================================================== + >>> description = describe_video_signal_matrix_coefficients(2, width=75) + =========================================================================== + * * + * Matrix Coefficients: 2 * + * ---------------------- * + * * + * Matrix Coefficients : Unspecified * + * FFmpeg Constants : ['AVCOL_SPC_UNSPECIFIED', 'UNSPECIFIED'] * + * * + =========================================================================== + >>> description = describe_video_signal_matrix_coefficients( + ... FFmpegConstantsMatrixCoefficients_ITUTH273.ICTCP, width=75 + ... ) + ... # doctest: +ELLIPSIS + =========================================================================== + * * + * Matrix Coefficients: 14 * + * ----------------------- * + * * + * Matrix Coefficients : ICTCP * + * FFmpeg Constants : ['AVCOL_SPC_ICTCP', 'ICTCP'] * + * * + =========================================================================== + """ + + @dataclass + class SpecificationMatrixCoefficients: + """Specification for video signal matrix coefficients code point.""" + + code_point: Integer + matrix_coefficients: NDArray + ffmpeg_constants: List + + members = FFmpegConstantsMatrixCoefficients_ITUTH273.__members__.items() + ffmpeg_constants = [ + name + for name, member in members + if member.name.startswith("AVCOL_SPC_") and member.value == code_point + ] + + description = SpecificationMatrixCoefficients( + code_point, + MATRIX_COEFFICIENTS_ITUTH273[code_point], + ffmpeg_constants, + ) + + message = multiline_str( + description, + [ + { + "name": "code_point", + "section": True, + "formatter": lambda x: f"Matrix Coefficients: {x}", + }, + {"line_break": True}, + { + "name": "matrix_coefficients", + "label": "Matrix Coefficients", + }, + {"name": "ffmpeg_constants", "label": "FFmpeg Constants"}, + ], + ) + + if print_description: + message_box( + message, + **kwargs, + ) + + return message diff --git a/colour/models/rgb/tests/test_itut_h_273.py b/colour/models/rgb/tests/test_itut_h_273.py new file mode 100644 index 0000000000..e0f51f4dcb --- /dev/null +++ b/colour/models/rgb/tests/test_itut_h_273.py @@ -0,0 +1,76 @@ +# !/usr/bin/env python +"""Define the unit tests for the :mod:`colour.models.rgb.itut_h_273` module.""" + +import unittest + +from colour.models import ( + describe_video_signal_colour_primaries, + describe_video_signal_transfer_characteristics, + describe_video_signal_matrix_coefficients, +) + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "TestDescribeVideoSignalColourPrimaries", + "TestDescribeVideoSignalTransferCharacteristics", + "TestDescribeVideoSignalMatrixCoefficients", +] + + +class TestDescribeVideoSignalColourPrimaries(unittest.TestCase): + """ + Define :func:`colour.models.rgb.itut_h_273.\ +describe_video_signal_colour_primaries` definition unit tests methods. + """ + + def test_describe_video_signal_colour_primaries(self): + """ + Test + :func:`colour.models.rgb.itut_h_273.\ +describe_video_signal_colour_primaries` definition. + """ + + description = describe_video_signal_colour_primaries(1) + self.assertIsInstance(description, str) + + +class TestDescribeVideoSignalTransferCharacteristics(unittest.TestCase): + """ + Define :func:`colour.models.rgb.itut_h_273.\ +describe_video_signal_transfer_characteristics` definition unit tests methods. + """ + + def test_describe_video_signal_transfer_characteristics(self): + """ + Test :func:`colour.models.rgb.itut_h_273.\ +describe_video_signal_transfer_characteristics` definition. + """ + + description = describe_video_signal_transfer_characteristics(1) + self.assertIsInstance(description, str) + + +class TestDescribeVideoSignalMatrixCoefficients(unittest.TestCase): + """ + Define :func:`colour.models.rgb.itut_h_273.\ +describe_video_signal_matrix_coefficients` definition unit tests methods. + """ + + def test_describe_video_signal_matrix_coefficients(self): + """ + Test :func:`colour.models.rgb.itut_h_273.\ +describe_video_signal_matrix_coefficients` definition. + """ + + description = describe_video_signal_matrix_coefficients(1) + self.assertIsInstance(description, str) + + +if __name__ == "__main__": + unittest.main() diff --git a/colour/models/rgb/transfer_functions/__init__.py b/colour/models/rgb/transfer_functions/__init__.py index 5776934b86..66c9435ba6 100644 --- a/colour/models/rgb/transfer_functions/__init__.py +++ b/colour/models/rgb/transfer_functions/__init__.py @@ -57,17 +57,10 @@ from .gopro import log_encoding_Protune, log_decoding_Protune from .itur_bt_601 import oetf_BT601, oetf_inverse_BT601 from .itur_bt_709 import oetf_BT709, oetf_inverse_BT709 +from .itur_bt_1361 import oetf_BT1361, oetf_inverse_BT1361 from .itur_bt_1886 import eotf_inverse_BT1886, eotf_BT1886 from .itur_bt_2020 import oetf_BT2020, oetf_inverse_BT2020 -from .itur_bt_1361 import oetf_BT1361_extended from .st_2084 import eotf_inverse_ST2084, eotf_ST2084 -from .st_428 import eotf_inverse_ST428_1 -from .itut_h_273 import ( - oetf_linear, - oetf_log, - oetf_log_sqrt, -) -from .iec_61966_2 import oetf_iec_61966_2_unbounded from .itur_bt_2100 import ( oetf_BT2100_PQ, oetf_inverse_BT2100_PQ, @@ -133,6 +126,16 @@ ) from .srgb import eotf_inverse_sRGB, eotf_sRGB from .viper_log import log_encoding_ViperLog, log_decoding_ViperLog +from .itut_h_273 import ( + oetf_H273_Log, + oetf_inverse_H273_Log, + oetf_H273_LogSqrt, + oetf_inverse_H273_LogSqrt, + oetf_H273_IEC61966_2, + oetf_inverse_H273_IEC61966_2, + eotf_inverse_H273_ST428_1, + eotf_H273_ST428_1, +) __all__ = [ "CV_range", @@ -214,6 +217,10 @@ "oetf_BT709", "oetf_inverse_BT709", ] +__all__ += [ + "oetf_BT1361", + "oetf_inverse_BT1361", +] __all__ += [ "eotf_inverse_BT1886", "eotf_BT1886", @@ -316,24 +323,20 @@ "eotf_inverse_sRGB", "eotf_sRGB", ] -__all__ += [ - "oetf_linear", - "oetf_log", - "oetf_log_sqrt", -] -__all__ += [ - "oetf_iec_61966_2_unbounded", -] -__all__ += [ - "eotf_inverse_ST428_1", -] -__all__ += [ - "oetf_BT1361_extended", -] __all__ += [ "log_encoding_ViperLog", "log_decoding_ViperLog", ] +__all__ += [ + "oetf_H273_Log", + "oetf_inverse_H273_Log", + "oetf_H273_LogSqrt", + "oetf_inverse_H273_LogSqrt", + "oetf_H273_IEC61966_2", + "oetf_inverse_H273_IEC61966_2", + "eotf_inverse_H273_ST428_1", + "eotf_H273_ST428_1", +] LOG_ENCODINGS: CanonicalMapping = CanonicalMapping( { @@ -650,6 +653,9 @@ def log_decoding( "ITU-R BT.2100 PQ": oetf_BT2100_PQ, "ITU-R BT.601": oetf_BT601, "ITU-R BT.709": oetf_BT709, + "ITU-T H.273 Log": oetf_H273_Log, + "ITU-T H.273 Log Sqrt": oetf_H273_LogSqrt, + "ITU-T H.273 IEC 61966-2": oetf_H273_IEC61966_2, "SMPTE 240M": oetf_SMPTE240M, } ) @@ -670,6 +676,9 @@ def oetf( "ITU-R BT.2100 PQ", "ITU-R BT.601", "ITU-R BT.709", + "ITU-T H.273 Log", + "ITU-T H.273 Log Sqrt", + "ITU-T H.273 IEC 61966-2", "SMPTE 240M", ], str, @@ -734,6 +743,9 @@ def oetf( "ITU-R BT.2100 PQ": oetf_inverse_BT2100_PQ, "ITU-R BT.601": oetf_inverse_BT601, "ITU-R BT.709": oetf_inverse_BT709, + "ITU-T H.273 Log": oetf_inverse_H273_Log, + "ITU-T H.273 Log Sqrt": oetf_inverse_H273_LogSqrt, + "ITU-T H.273 IEC 61966-2": oetf_inverse_H273_IEC61966_2, } ) OETF_INVERSES.__doc__ = """ @@ -753,6 +765,9 @@ def oetf_inverse( "ITU-R BT.2100 PQ", "ITU-R BT.601", "ITU-R BT.709", + "ITU-T H.273 Log", + "ITU-T H.273 Log Sqrt", + "ITU-T H.273 IEC 61966-2", ], str, ] = "ITU-R BT.709", @@ -816,6 +831,7 @@ def oetf_inverse( "ITU-R BT.1886": eotf_BT1886, "ITU-R BT.2100 HLG": eotf_BT2100_HLG, "ITU-R BT.2100 PQ": eotf_BT2100_PQ, + "ITU-T H.273 ST.428-1": eotf_H273_ST428_1, "SMPTE 240M": eotf_SMPTE240M, "ST 2084": eotf_ST2084, "sRGB": eotf_sRGB, @@ -835,6 +851,7 @@ def eotf( "ITU-R BT.1886", "ITU-R BT.2100 HLG", "ITU-R BT.2100 PQ", + "ITU-T H.273 ST.428-1", "SMPTE 240M", "ST 2084", "sRGB", @@ -897,6 +914,7 @@ def eotf( "ITU-R BT.1886": eotf_inverse_BT1886, "ITU-R BT.2100 HLG": eotf_inverse_BT2100_HLG, "ITU-R BT.2100 PQ": eotf_inverse_BT2100_PQ, + "ITU-T H.273 ST.428-1": eotf_inverse_H273_ST428_1, "ST 2084": eotf_inverse_ST2084, "sRGB": eotf_inverse_sRGB, } @@ -915,6 +933,7 @@ def eotf_inverse( "ITU-R BT.1886", "ITU-R BT.2100 HLG", "ITU-R BT.2100 PQ", + "ITU-T H.273 ST.428-1", "ST 2084", "sRGB", ], diff --git a/colour/models/rgb/transfer_functions/dcdm.py b/colour/models/rgb/transfer_functions/dcdm.py index a0b5cc4866..05ce0797a7 100644 --- a/colour/models/rgb/transfer_functions/dcdm.py +++ b/colour/models/rgb/transfer_functions/dcdm.py @@ -14,6 +14,9 @@ Digital Cinema System Specification - Version 1.1. http://www.dcimovies.com/archives/spec_v1_1/\ DCI_DCinema_System_Spec_v1_1.pdf +- :cite:`SocietyofMotionPictureandTelevisionEngineers2019` : Society of + Motion Picture and Television Engineers. (2019). ST 428-1:2019 - D-Cinema + Distribution Master — Image Characteristic. doi:10.5594/SMPTE.ST428-1.2019 """ from __future__ import annotations diff --git a/colour/models/rgb/transfer_functions/iec_61966_2.py b/colour/models/rgb/transfer_functions/iec_61966_2.py deleted file mode 100644 index dba1905a4e..0000000000 --- a/colour/models/rgb/transfer_functions/iec_61966_2.py +++ /dev/null @@ -1,148 +0,0 @@ -""" -IEC 61966-2 -=========== - -Define transfer functions from *IEC 61966-2* (sRGB, sYCC, xvYCC). - -Note that this function uses the definition from :cite:`ITU2021` since IEC -61966-2 is not publicly accessible. - -References ----------- -- :cite:`ITU2021` : International Telecommunication Union. (2021). - Recommendation ITU-T H.273 - Coding-independent code points for video - signal type identification. - https://www.itu.int/rec/T-REC-H.273-202107-I/en -""" - -import numpy as np - -from colour.models.rgb.transfer_functions.srgb import eotf_inverse_sRGB -from colour.models.rgb.transfer_functions.srgb import eotf_sRGB - -from colour.utilities import ( - as_float, - from_range_1, - to_domain_1, -) - - -def oetf_iec_61966_2_unbounded(Lc): - """ - Define the unbounded opto-electronic transfer functions (OETF) for *IEC 61966-2* - family of transfer functions (*2-1 sRGB*, *2-1 sYCC*, *2-4 xvYCC*). - - Parameters - ---------- - Lc - Scene *Luminance* :math:`Lc`. - - Returns - ------- - :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding electrical signal :math:`V`. - - Notes - ----- - Usage in :cite:`ITU2021` is as follows: - - - For IEC 61966-2-1 sRGB (MatrixCoefficients=0), function is only defined - for Lc in [0-1] range. - - - For IEC 61966-2-1 sYCC (MatrixCoefficients=5) and IEC 61966-2-4 xvYCC, - function is defined for any real-valued Lc. - - +------------+-----------------------+---------------+ - | **Domain** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``Lc`` | [-inf, inf] | [-inf, inf] | - +------------+-----------------------+---------------+ - - +------------+-----------------------+---------------+ - | **Range** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``V`` | [-inf, inf] | [-inf, inf] | - +------------+-----------------------+---------------+ - - References - ---------- - - :cite:`ITU2021` - - Examples - -------- - >>> oetf_iec_61966_2_unbounded(0.18) # doctest: +ELLIPSIS - 0.4613561295004... - >>> oetf_iec_61966_2_unbounded(-0.18) # doctest: +ELLIPSIS - -0.4613561295004... - """ - - Lc = to_domain_1(Lc) - - V = np.where( - Lc >= 0, - eotf_inverse_sRGB(Lc), - -eotf_inverse_sRGB(-Lc), - ) - - return as_float(from_range_1(V)) - - -def oetf_inverse_iec_61966_2_unbounded(V): - """ - Define the unbounded inverse-opto-electronic transfer functions (OETF) for - *IEC 61966-2* family of transfer functions (*2-1 sRGB*, *2-1 sYCC*, *2-4 - xvYCC*). - - Parameters - ---------- - V - Electrical signal :math:`V`. - - Returns - ------- - :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding scene luminance :math:`Lc`. - - Notes - ----- - Usage in :cite:`ITU2021` is as follows: - - - For IEC 61966-2-1 sRGB (MatrixCoefficients=0), function is only defined - for Lc in [0-1] range. - - - For IEC 61966-2-1 sYCC (MatrixCoefficients=5) and IEC 61966-2-4 xvYCC, - function is defined for any real-valued Lc. - - +------------+-----------------------+---------------+ - | **Range** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``V`` | [-inf, inf] | [-inf, inf] | - +------------+-----------------------+---------------+ - - +------------+-----------------------+---------------+ - | **Domain** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``Lc`` | [-inf, inf] | [-inf, inf] | - +------------+-----------------------+---------------+ - - References - ---------- - - :cite:`ITU2021` - - Examples - -------- - >>> oetf_inverse_iec_61966_2_unbounded(0.461356129500) # doctest: +ELLIPSIS - 0.1799999999... - >>> oetf_inverse_iec_61966_2_unbounded(-0.461356129500) # doctest: +ELLIPSIS - -0.1799999999... - """ - - V = to_domain_1(V) - - Lc = np.where( - V >= 0, - eotf_sRGB(V), - -eotf_sRGB(-V), - ) - - return as_float(from_range_1(Lc)) diff --git a/colour/models/rgb/transfer_functions/itur_bt_1361.py b/colour/models/rgb/transfer_functions/itur_bt_1361.py index 4afec42f19..c6ee1a0866 100644 --- a/colour/models/rgb/transfer_functions/itur_bt_1361.py +++ b/colour/models/rgb/transfer_functions/itur_bt_1361.py @@ -1,24 +1,31 @@ """ -ITU-R BT.1361 -============= +Recommendation ITU-R BT.1361 +============================ -Define transfer functions from *ITU-R BT.1361*. +Defines the *Recommendation ITU-R BT.1361* opto-electrical transfer function +(OETF) and its inverse: + +- :func:`colour.models.oetf_BT1361` +- :func:`colour.models.oetf_inverse_BT1361` References ---------- - :cite:`InternationalTelecommunicationUnion1998` : International - Telecommunication Union. (1998). Recommendation ITU-R BT.1361 - - Worldwide unified colorimetry and related characteristics of - future television and imaging systems - https://www.itu.int/dms_pubrec/itu-r/rec/bt/\ + Telecommunication Union. (1998). Recommendation ITU-R BT.1361 - Worldwide + unified colorimetry and related characteristics of future television and + imaging systems (pp. 1-32). https://www.itu.int/dms_pubrec/itu-r/rec/bt/\ R-REC-BT.1361-0-199802-W!!PDF-E.pdf """ + import numpy as np from colour.algebra import spow +from colour.models.rgb.transfer_functions import oetf_BT709, oetf_inverse_BT709 from colour.utilities import ( - as_float_array, as_float, + domain_range_scale, + from_range_1, + to_domain_1, ) __author__ = "Colour Developers" @@ -29,21 +36,15 @@ __status__ = "Production" __all__ = [ - "oetf_BT1361_extended", - "oetf_inverse_BT1361_extended", + "oetf_BT1361", + "oetf_inverse_BT1361", ] -L_LINEAR_THRESHOLD_POSITIVE = 0.018 -L_LINEAR_THRESHOLD_NEGATIVE = -0.0045 -EP_LINEAR_THRESHOLD_POSITIVE = 4.500 * L_LINEAR_THRESHOLD_POSITIVE -EP_LINEAR_THRESHOLD_NEGATIVE = 4.500 * L_LINEAR_THRESHOLD_NEGATIVE - - -def oetf_BT1361_extended(L): +def oetf_BT1361(L): """ - Define the opto-electronic transfer functions (OETF) for *ITU-R BT.1361* extended - color gamut. + Define *Recommendation ITU-R BT.1361* extended color gamut system + opto-electronic transfer function (OETF). Parameters ---------- @@ -60,13 +61,13 @@ def oetf_BT1361_extended(L): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``L`` | [-0.25, 1.33] | [-0.25, 1.33] | + | ``L`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+-------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===================+ - | ``Ep'`` | [-0.25, 1.152...] | [-0.25, 1.152...] | + | ``E_p'`` | [0, 1] | [0, 1] | +------------+-----------------------+-------------------+ References @@ -75,45 +76,40 @@ def oetf_BT1361_extended(L): Examples -------- - >>> oetf_BT1361_extended(0.18) # doctest: +ELLIPSIS + >>> oetf_BT1361(0.18) # doctest: +ELLIPSIS 0.4090077288641... - >>> oetf_BT1361_extended(-0.25) # doctest: +ELLIPSIS + >>> oetf_BT1361(-0.25) # doctest: +ELLIPSIS -0.25 - >>> oetf_BT1361_extended(1.33) # doctest: +ELLIPSIS + >>> oetf_BT1361(1.33) # doctest: +ELLIPSIS 1.1504846663972... """ - L = as_float_array(L) - - Ep = np.where( - L >= 0, - np.where( - L >= L_LINEAR_THRESHOLD_POSITIVE, - # L in [0.018, 1.33] range - 1.099 * spow(L, 0.45) - 0.099, - # L in [0, 0.018] range - 4.500 * L, - ), - np.where( - L <= L_LINEAR_THRESHOLD_NEGATIVE, - # L in [-0.25, -0.0045] range - -(1.099 * spow(-4 * L, 0.45) - 0.099) / 4, - # L in [-0.0045, 0] range - 4.500 * L, - ), - ) - - return as_float(Ep) - - -def oetf_inverse_BT1361_extended(Ep): + L = to_domain_1(L) + + with domain_range_scale("ignore"): + E_p = np.where( + L >= 0, + oetf_BT709(L), + np.where( + L <= -0.0045, + # L in [-0.25, -0.0045] range + -(1.099 * spow(-4 * L, 0.45) - 0.099) / 4, + # L in [-0.0045, 0] range + 4.500 * L, + ), + ) + + return as_float(from_range_1(E_p)) + + +def oetf_inverse_BT1361(E_p): """ - Define the inverse-opto-electronic transfer functions (OETF) for *ITU-R - BT.1361* extended color gamut. + Define *Recommendation ITU-R BT.1361* extended color gamut system inverse + opto-electronic transfer functions (OETF). Parameters ---------- - Ep + E_p Non-linear primary signal :math:`E'`. Returns @@ -126,13 +122,13 @@ def oetf_inverse_BT1361_extended(Ep): +------------+-----------------------+-------------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===================+ - | ``Ep'`` | [-0.25, 1.152...] | [-0.25, 1.152...] | + | ``E_p`` | [0, 1] | [0, 1] | +------------+-----------------------+-------------------+ +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``L`` | [-0.25, 1.33] | [-0.25, 1.33] | + | ``L`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ @@ -142,32 +138,27 @@ def oetf_inverse_BT1361_extended(Ep): Examples -------- - >>> oetf_inverse_BT1361_extended(0.4090077288641) # doctest: +ELLIPSIS + >>> oetf_inverse_BT1361(0.4090077288641) # doctest: +ELLIPSIS 0.1799999... - >>> oetf_inverse_BT1361_extended(-0.25) # doctest: +ELLIPSIS + >>> oetf_inverse_BT1361(-0.25) # doctest: +ELLIPSIS -0.25 - >>> oetf_inverse_BT1361_extended(1.1504846663972) # doctest: +ELLIPSIS + >>> oetf_inverse_BT1361(1.1504846663972) # doctest: +ELLIPSIS 1.3299999... """ - Ep = as_float_array(Ep) - - L = np.where( - Ep >= 0, - np.where( - Ep >= EP_LINEAR_THRESHOLD_POSITIVE, - # L in [0.018, 1.33] range - spow((Ep + 0.099) / 1.099, 1 / 0.45), - # L in [0, 0.018] range - Ep / 4.500, - ), - np.where( - Ep <= EP_LINEAR_THRESHOLD_NEGATIVE, - # L in [-0.25, -0.0045] range - -spow((-4 * Ep + 0.099) / 1.099, 1 / 0.45) / 4, - # L in [-0.0045, 0] range - Ep / 4.500, - ), - ) - - return as_float(L) + E_p = to_domain_1(E_p) + + with domain_range_scale("ignore"): + L = np.where( + E_p >= 0, + oetf_inverse_BT709(E_p), + np.where( + E_p <= 4.500 * -0.0045, + # L in [-0.25, -0.0045] range + -spow((-4 * E_p + 0.099) / 1.099, 1 / 0.45) / 4, + # L in [-0.0045, 0] range + E_p / 4.500, + ), + ) + + return as_float(from_range_1(L)) diff --git a/colour/models/rgb/transfer_functions/itut_h_273.py b/colour/models/rgb/transfer_functions/itut_h_273.py index e055604850..435e3028ec 100644 --- a/colour/models/rgb/transfer_functions/itut_h_273.py +++ b/colour/models/rgb/transfer_functions/itut_h_273.py @@ -1,22 +1,42 @@ """ -ITU-T H.273 video transfer functions -==================================== +Recommendation ITU-T H.273 Transfer Characteristics +=================================================== -Contains several transfer functions that are defined in ITU-T H.273 -(:cite:`ITU2021`) but don't belong in another specification or standard. +Defines the *Recommendation ITU-T H.273* transfer functions that do not belong +in another specification or standard, or have been modified for inclusion: + +- :func:`colour.models.oetf_H273_Log` +- :func:`colour.models.oetf_inverse_H273_Log` +- :func:`colour.models.oetf_H273_LogSqrt` +- :func:`colour.models.oetf_inverse_H273_LogSqrt` +- :func:`colour.models.oetf_H273_IEC61966_2` +- :func:`colour.models.oetf_inverse_H273_IEC61966_2` +- :func:`colour.models.eotf_H273_ST428_1` +- :func:`colour.models.eotf_inverse_H273_ST428_1` References ---------- -- :cite:`ITU2021` : International Telecommunication Union. (2021). Recommendation - ITU-T H.273 - Coding-independent code points for video signal type identification. +- :cite:`InternationalTelecommunicationUnion2021` : International + Telecommunication Union. (2021). Recommendation ITU-T H.273 - + Coding-independent code points for video signal type identification. https://www.itu.int/rec/T-REC-H.273-202107-I/en +- :cite:`SocietyofMotionPictureandTelevisionEngineers2019` : Society of + Motion Picture and Television Engineers. (2019). ST 428-1:2019 - D-Cinema + Distribution Master — Image Characteristic. doi:10.5594/SMPTE.ST428-1.2019 """ import numpy as np from colour.algebra import spow +from colour.models.rgb.transfer_functions import ( + eotf_inverse_DCDM, + eotf_DCDM, + eotf_inverse_sRGB, + eotf_sRGB, +) from colour.utilities import ( as_float, + as_float_array, from_range_1, to_domain_1, ) @@ -29,23 +49,26 @@ __status__ = "Production" __all__ = [ - "oetf_linear", - "oetf_log", - "oetf_log_sqrt", - "oetf_inverse_linear", - "oetf_inverse_log", - "oetf_inverse_log_sqrt", + "oetf_H273_Log", + "oetf_inverse_H273_Log", + "oetf_H273_LogSqrt", + "oetf_inverse_H273_LogSqrt", + "oetf_H273_IEC61966_2", + "oetf_inverse_H273_IEC61966_2", + "eotf_inverse_H273_ST428_1", + "eotf_H273_ST428_1", ] -def oetf_linear(Lc): +def oetf_H273_Log(L_c): """ - Linear opto-electronic transfer function (OETF) defined in ITU-T H.273. + Define *Recommendation ITU-T H.273* opto-electronic transfer function + (OETF) for L_ogarithmic encoding (100:1 range). Parameters ---------- - Lc - Scene *Luminance* :math:`Lc`. + L_c + Scene *Luminance* :math:`L_c`. Returns ------- @@ -57,7 +80,7 @@ def oetf_linear(Lc): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``Lc`` | [0, 1] | [0, 1] | + | ``L_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ @@ -68,25 +91,41 @@ def oetf_linear(Lc): References ---------- - :cite:`ITU2021` + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain [0.01, np.inf]. Examples -------- - >>> oetf_linear(0.18) # doctest: +ELLIPSIS - 0.17999999... + >>> oetf_H273_Log(0.18) # doctest: +ELLIPSIS + 0.6276362525516... + >>> oetf_H273_Log(0.01) # doctest: +ELLIPSIS + 0.0 + >>> oetf_H273_Log(0.001) # doctest: +ELLIPSIS + 0.0 + >>> oetf_H273_Log(1.0) # doctest: +ELLIPSIS + 1.0 """ - Lc = to_domain_1(Lc) + L_c = to_domain_1(L_c) - V = Lc + V = np.where( + L_c >= 0.01, + # L_c in [0.01, 1] range + 1 + np.log10(L_c) / 2, + # L_c in [0, 0.01] range + 0, + ) return as_float(from_range_1(V)) -def oetf_inverse_linear(V): +def oetf_inverse_H273_Log(V): """ - Linear inverse-opto-electronic transfer function (OETF) defined in ITU-T - H.273. + Define *Recommendation ITU-T H.273* inverse-opto-electronic transfer + function (OETF) for L_ogarithmic encoding (100:1 range). Parameters ---------- @@ -96,7 +135,7 @@ def oetf_inverse_linear(V): Returns ------- :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding scene *Luminance* :math:`Lc`. + Corresponding scene *Luminance* :math:`L_c`. Notes ----- @@ -109,35 +148,50 @@ def oetf_inverse_linear(V): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``Lc`` | [0, 1] | [0, 1] | + | ``L_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- - :cite:`ITU2021` + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain + [:func:`colour.models.oetf_H273_Log`(0.01), np.inf]. Examples -------- - >>> oetf_inverse_linear(0.18) # doctest: +ELLIPSIS + >>> oetf_inverse_H273_Log(0.6276362525516) # doctest: +ELLIPSIS 0.17999999... + >>> oetf_inverse_H273_Log(0.0) # doctest: +ELLIPSIS + 0.01 + >>> oetf_inverse_H273_Log(1.0) # doctest: +ELLIPSIS + 1.0 """ V = to_domain_1(V) - Lc = V + L_c = np.where( + V >= oetf_H273_Log(0.01), + # L_c in [0.01, 1] range + spow(10, (V - 1) * 2), + # L_c in [0, 0.01] range + 0, + ) - return as_float(from_range_1(Lc)) + return as_float(from_range_1(L_c)) -def oetf_log(Lc): +def oetf_H273_LogSqrt(L_c): """ - Define the opto-electronic transfer functions (OETF) for Logarithmic - encoding (100:1 range) defined in ITU-T H.273. + Define *Recommendation ITU-T H.273* opto-electronic transfer function + (OETF) for L_ogarithmic encoding (100*Sqrt(10):1 range. Parameters ---------- - Lc - Scene *Luminance* :math:`Lc`. + L_c + Scene *Luminance* :math:`L_c`. Returns ------- @@ -149,7 +203,7 @@ def oetf_log(Lc): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``Lc`` | [0, 1] | [0, 1] | + | ``L_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ @@ -160,37 +214,42 @@ def oetf_log(Lc): References ---------- - :cite:`ITU2021` + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain + [:func:`colour.models.oetf_H273_LogSqrt`(sqrt(10) / 1000), np.inf]. Examples -------- - >>> oetf_log(0.18) # doctest: +ELLIPSIS - 0.6276362525516... - >>> oetf_log(0.01) # doctest: +ELLIPSIS + >>> oetf_H273_LogSqrt(0.18) # doctest: +ELLIPSIS + 0.702109002041... + >>> oetf_H273_LogSqrt(0.003162277660168) # doctest: +ELLIPSIS 0.0 - >>> oetf_log(0.001) # doctest: +ELLIPSIS + >>> oetf_H273_LogSqrt(0.0001) # doctest: +ELLIPSIS 0.0 - >>> oetf_log(1.0) # doctest: +ELLIPSIS + >>> oetf_H273_LogSqrt(1.0) # doctest: +ELLIPSIS 1.0 """ - Lc = to_domain_1(Lc) + L_c = to_domain_1(L_c) V = np.where( - Lc >= 0.01, - # Lc in [0.01, 1] range - 1.0 + np.log10(Lc) / 2.0, - # Lc in [0, 0.01] range - 0.0, + L_c >= np.sqrt(10) / 1000, + # L_c in [sqrt(10)/1000, 1] range + 1 + np.log10(L_c) / 2.5, + # L_c in [0, sqrt(10)/1000] range + 0, ) return as_float(from_range_1(V)) -def oetf_inverse_log(V): +def oetf_inverse_H273_LogSqrt(V): """ - Define the inverse-opto-electronic transfer functions (OETF) for - Logarithmic encoding (100:1 range) defined in ITU-T H.273. + Define *Recommendation ITU-T H.273* inverse-opto-electronic transfer + function (OETF) for L_ogarithmic encoding (100*Sqrt(10):1 range). Parameters ---------- @@ -200,7 +259,7 @@ def oetf_inverse_log(V): Returns ------- :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding scene *Luminance* :math:`Lc`. + Corresponding scene *Luminance* :math:`L_c`. Notes ----- @@ -213,45 +272,50 @@ def oetf_inverse_log(V): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``Lc`` | [0, 1] | [0, 1] | + | ``L_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- - :cite:`ITU2021` + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain [sqrt(10) / 1000, np.inf]. Examples -------- - >>> oetf_inverse_log(0.6276362525516) # doctest: +ELLIPSIS - 0.17999999... - >>> oetf_inverse_log(0.0) # doctest: +ELLIPSIS - 0.01 - >>> oetf_inverse_log(1.0) # doctest: +ELLIPSIS + >>> oetf_inverse_H273_LogSqrt(0.702109002041) # doctest: +ELLIPSIS + 0.1799999999... + >>> oetf_inverse_H273_LogSqrt(0.0) # doctest: +ELLIPSIS + 0.00316227766... + >>> oetf_inverse_H273_LogSqrt(1.0) # doctest: +ELLIPSIS 1.0 """ V = to_domain_1(V) - Lc = np.where( - V >= 0.0, - # Lc in [0.01, 1] range - spow(10, (V - 1.0) * 2.0), - # Lc in [0, 0.01] range - 0.01, + L_c = np.where( + V >= oetf_H273_LogSqrt(np.sqrt(10) / 1000), + # L_c in [sqrt(10)/1000, 1] range + spow(10, (V - 1) * 2.5), + # L_c in [0, sqrt(10)/1000] range + 0, ) - return as_float(from_range_1(Lc)) + return as_float(from_range_1(L_c)) -def oetf_log_sqrt(Lc): +def oetf_H273_IEC61966_2(L_c): """ - Define the opto-electronic transfer functions (OETF) for Logarithmic - encoding (100*Sqrt(10):1 range) defined in ITU-T H.273. + Define *Recommendation ITU-T H.273* opto-electronic transfer function + (OETF) for *IEC 61966-2* family of transfer functions (*2-1 sRGB*, + *2-1 sYCC*, *2-4 xvYCC*). Parameters ---------- - Lc - Scene *Luminance* :math:`Lc`. + L_c + Scene *Luminance* :math:`L_c`. Returns ------- @@ -260,10 +324,18 @@ def oetf_log_sqrt(Lc): Notes ----- + Usage in :cite:`InternationalTelecommunicationUnion2021` is as follows: + + - For *IEC 61966-2-1 sRGB (MatrixCoefficients=0)*, the function is only + defined for :math:`L_c` in [0-1] range. + - For *IEC 61966-2-1 sYCC (MatrixCoefficients=5)* and + *IEC 61966-2-4 xvYCC*, the function is defined for any real-valued + :math:`L_c`. + +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``Lc`` | [0, 1] | [0, 1] | + | ``L_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ +------------+-----------------------+---------------+ @@ -274,37 +346,30 @@ def oetf_log_sqrt(Lc): References ---------- - :cite:`ITU2021` + - :cite:`InternationalTelecommunicationUnion2021` Examples -------- - >>> oetf_log_sqrt(0.18) # doctest: +ELLIPSIS - 0.702109002041... - >>> oetf_log_sqrt(0.003162277660168) # doctest: +ELLIPSIS - 0.0 - >>> oetf_log_sqrt(0.0001) # doctest: +ELLIPSIS - 0.0 - >>> oetf_log_sqrt(1.0) # doctest: +ELLIPSIS - 1.0 + >>> oetf_H273_IEC61966_2(0.18) # doctest: +ELLIPSIS + 0.4613561295004... + >>> oetf_H273_IEC61966_2(-0.18) # doctest: +ELLIPSIS + -0.4613561295004... """ - Lc = to_domain_1(Lc) - V = np.where( - Lc >= np.sqrt(10) / 1000, - # Lc in [sqrt(10)/1000, 1] range - 1.0 + np.log10(Lc) / 2.5, - # Lc in [0, sqrt(10)/1000] range - 0.0, + as_float_array(L_c) >= 0, + eotf_inverse_sRGB(L_c), + -eotf_inverse_sRGB(-L_c), ) - return as_float(from_range_1(V)) + return as_float(V) -def oetf_inverse_log_sqrt(V): +def oetf_inverse_H273_IEC61966_2(V): """ - Define the inverse-opto-electronic transfer functions (OETF) for - Logarithmic encoding (100*Sqrt(10):1 range) defined in ITU-T H.273. + Define *Recommendation ITU-T H.273* inverse opto-electronic transfer + function (OETF) for *IEC 61966-2* family of transfer functions (*2-1 sRGB*, + *2-1 sYCC*, *2-4 xvYCC*). Parameters ---------- @@ -314,10 +379,18 @@ def oetf_inverse_log_sqrt(V): Returns ------- :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding scene *Luminance* :math:`Lc`. + Corresponding scene luminance :math:`L_c`. Notes ----- + Usage in :cite:`InternationalTelecommunicationUnion2021` is as follows: + + - For *IEC 61966-2-1 sRGB (MatrixCoefficients=0)*, the function is only + defined for :math:`L_c` in [0-1] range. + - For *IEC 61966-2-1 sYCC (MatrixCoefficients=5)* and + *IEC 61966-2-4 xvYCC*, the function is defined for any real-valued + :math:`L_c`. + +------------+-----------------------+---------------+ | **Range** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ @@ -327,31 +400,124 @@ def oetf_inverse_log_sqrt(V): +------------+-----------------------+---------------+ | **Domain** | **Scale - Reference** | **Scale - 1** | +============+=======================+===============+ - | ``Lc`` | [0, 1] | [0, 1] | + | ``L_c`` | [0, 1] | [0, 1] | +------------+-----------------------+---------------+ References ---------- - :cite:`ITU2021` + - :cite:`InternationalTelecommunicationUnion2021` Examples -------- - >>> oetf_inverse_log_sqrt(0.702109002041) # doctest: +ELLIPSIS + >>> oetf_inverse_H273_IEC61966_2(0.461356129500) # doctest: +ELLIPSIS 0.1799999999... - >>> oetf_inverse_log_sqrt(0.0) # doctest: +ELLIPSIS - 0.00316227766... - >>> oetf_inverse_log_sqrt(1.0) # doctest: +ELLIPSIS - 1.0 + >>> oetf_inverse_H273_IEC61966_2(-0.461356129500) # doctest: +ELLIPSIS + -0.1799999999... """ - V = to_domain_1(V) - - Lc = np.where( - V >= 0.0, - # Lc in [sqrt(10)/1000, 1] range - spow(10, (V - 1.0) * 2.5), - # Lc in [0, sqrt(10)/1000] range - np.sqrt(10) / 1000, + L_c = np.where( + as_float_array(V) >= 0, + eotf_sRGB(V), + -eotf_sRGB(-V), ) - return as_float(from_range_1(Lc)) + return as_float(L_c) + + +def eotf_inverse_H273_ST428_1(L_o): + """ + Define *Recommendation ITU-T H.273* inverse electro-optical transfer + function (EOTF) for *SMPTE ST 428-1 (2019)*. + + Parameters + ---------- + L_o + Output display *Luminance* :math:`L_o` of the image. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + - The function given in :cite:`InternationalTelecommunicationUnion2021` + multiplies :math:`L_o` by 48 contrary to what is given in + :cite:`SocietyofMotionPictureandTelevisionEngineers2019` and + :func:`colour.models.eotf_inverse_DCDM`. + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_o`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`InternationalTelecommunicationUnion2021`, + :cite:`SocietyofMotionPictureandTelevisionEngineers2019` + + Examples + -------- + >>> eotf_inverse_H273_ST428_1(0.18) # doctest: +ELLIPSIS + 0.5000483... + """ + + L_o = to_domain_1(L_o) + + return as_float(from_range_1(eotf_inverse_DCDM(L_o * 48))) + + +def eotf_H273_ST428_1(V): + """ + Define the *SMPTE ST 428-1 (2019)* electro-optical transfer function (EOTF). + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding output display *Luminance* :math:`L_o` of the image. + + Notes + ----- + - The function given in :cite:`InternationalTelecommunicationUnion2021` + divides :math:`L_o` by 48 contrary to what is given in + :cite:`SocietyofMotionPictureandTelevisionEngineers2019` and + :func:`colour.models.eotf_DCDM`. + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_o`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`InternationalTelecommunicationUnion2021`, + :cite:`SocietyofMotionPictureandTelevisionEngineers2019` + + Examples + -------- + >>> eotf_H273_ST428_1(0.5000483377172) # doctest: +ELLIPSIS + 0.1799999... + """ + + V = to_domain_1(V) + + return as_float(from_range_1(eotf_DCDM(V) / 48)) diff --git a/colour/models/rgb/transfer_functions/st_428.py b/colour/models/rgb/transfer_functions/st_428.py deleted file mode 100644 index 62fb53f164..0000000000 --- a/colour/models/rgb/transfer_functions/st_428.py +++ /dev/null @@ -1,125 +0,0 @@ -""" -SMPTE ST 428-1 (2019) -===================== - -Defines *SMPTE ST 428-1 (2019)* inverse electro-optical transfer function (EOTF). - -Note that this function uses the definition from :cite:`ITU2021` since SMPTE ST -428-1 is not publicly accessible. - -References ----------- -- :cite:`ITU2021` : International Telecommunication Union. (2021). - Recommendation ITU-T H.273 - Coding-independent code points for video - signal type identification. - https://www.itu.int/rec/T-REC-H.273-202107-I/en -""" - -from colour.algebra import spow -from colour.utilities import ( - as_float, - from_range_1, - to_domain_1, -) - -__author__ = "Colour Developers" -__copyright__ = "Copyright 2013 Colour Developers" -__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" -__maintainer__ = "Colour Developers" -__email__ = "colour-developers@colour-science.org" -__status__ = "Production" - -__all__ = [ - "eotf_ST428_1", - "eotf_inverse_ST428_1", -] - - -def eotf_ST428_1(V): - """ - Define the *SMPTE ST 428-1 (2019)* electro-optical transfer function (EOTF). - - Parameters - ---------- - V - Electrical signal :math:`V`. - - Returns - ------- - :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding output display *Luminance* :math:`Lo` of the image. - - Notes - ----- - +------------+-----------------------+---------------+ - | **Range** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``V`` | [0, 1] | [0, 1] | - +------------+-----------------------+---------------+ - - +------------+-----------------------+---------------+ - | **Domain** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``Lo`` | [0, 1] | [0, 1] | - +------------+-----------------------+---------------+ - - References - ---------- - - :cite:`ITU2021` - - Examples - -------- - >>> eotf_ST428_1(0.5000483377172) # doctest: +ELLIPSIS - 0.179999999... - """ - - V = to_domain_1(V) - - Lo = 52.37 * spow(V, 2.6) / 48 - - return as_float(from_range_1(Lo)) - - -def eotf_inverse_ST428_1(Lo): - """ - Define the *SMPTE ST 428-1 (2019)* inverse electro-optical transfer function (EOTF). - - Parameters - ---------- - Lo - Output display *Luminance* :math:`Lo` of the image. - - Returns - ------- - :class:`numpy.floating` or :class:`numpy.ndarray` - Corresponding electrical signal :math:`V`. - - Notes - ----- - +------------+-----------------------+---------------+ - | **Domain** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``Lo`` | [0, 1] | [0, 1] | - +------------+-----------------------+---------------+ - - +------------+-----------------------+---------------+ - | **Range** | **Scale - Reference** | **Scale - 1** | - +============+=======================+===============+ - | ``V`` | [0, 1] | [0, 1] | - +------------+-----------------------+---------------+ - - References - ---------- - - :cite:`ITU2021` - - Examples - -------- - >>> eotf_inverse_ST428_1(0.18) # doctest: +ELLIPSIS - 0.5000483377172... - """ - - Lo = to_domain_1(Lo) - - V = spow(48 * Lo / 52.37, 1 / 2.6) - - return as_float(from_range_1(V)) diff --git a/colour/models/rgb/transfer_functions/tests/test__init__.py b/colour/models/rgb/transfer_functions/tests/test__init__.py index 90e91f476e..813ec3e4a1 100644 --- a/colour/models/rgb/transfer_functions/tests/test__init__.py +++ b/colour/models/rgb/transfer_functions/tests/test__init__.py @@ -119,11 +119,19 @@ def test_transfer_functions(self): if name in ignored_transfer_functions: continue - encoded_s = CCTF_ENCODINGS[name](samples) - decoded_s = CCTF_DECODINGS[name](encoded_s) + samples_r = np.copy(samples) + + if name == "ITU-T H.273 Log": + samples_r = np.clip(samples_r, 0.1, np.inf) + + if name == "ITU-T H.273 Log Sqrt": + samples_r = np.clip(samples_r, np.sqrt(10) / 1000, np.inf) + + samples_e = CCTF_ENCODINGS[name](samples_r) + samples_d = CCTF_DECODINGS[name](samples_e) np.testing.assert_array_almost_equal( - samples, decoded_s, decimal=decimals.get(name, 7) + samples_r, samples_d, decimal=decimals.get(name, 7) ) diff --git a/colour/models/rgb/transfer_functions/tests/test_itur_bt_1361.py b/colour/models/rgb/transfer_functions/tests/test_itur_bt_1361.py new file mode 100644 index 0000000000..287392747c --- /dev/null +++ b/colour/models/rgb/transfer_functions/tests/test_itur_bt_1361.py @@ -0,0 +1,183 @@ +""" +Define the unit tests for the +:mod:`colour.models.rgb.transfer_functions.itur_bt_1361` module. +""" + +import numpy as np +import unittest + +from colour.models.rgb.transfer_functions import ( + oetf_BT1361, + oetf_inverse_BT1361, +) +from colour.utilities import domain_range_scale, ignore_numpy_errors + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "TestOetf_BT1361", + "TestOetf_inverse_BT1361", +] + + +class TestOetf_BT1361(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itur_bt_1361.oetf_BT1361` + definition unit tests methods. + """ + + def test_oetf_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_BT1361` definition. + """ + + self.assertAlmostEqual( + oetf_BT1361(-0.18), -0.212243985492969, places=7 + ) + + self.assertAlmostEqual(oetf_BT1361(0.0), 0.0, places=7) + + self.assertAlmostEqual(oetf_BT1361(0.015), 0.067500000000000, places=7) + + self.assertAlmostEqual(oetf_BT1361(0.18), 0.409007728864150, places=7) + + self.assertAlmostEqual(oetf_BT1361(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_BT1361` definition n-dimensional arrays support. + """ + + L = 0.18 + V = oetf_BT1361(L) + + L = np.tile(L, 6) + V = np.tile(V, 6) + np.testing.assert_array_almost_equal(oetf_BT1361(L), V, decimal=7) + + L = np.reshape(L, (2, 3)) + V = np.reshape(V, (2, 3)) + np.testing.assert_array_almost_equal(oetf_BT1361(L), V, decimal=7) + + L = np.reshape(L, (2, 3, 1)) + V = np.reshape(V, (2, 3, 1)) + np.testing.assert_array_almost_equal(oetf_BT1361(L), V, decimal=7) + + def test_domain_range_scale_oetf_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_BT1361` definition domain and range scale support. + """ + + L = 0.18 + V = oetf_BT1361(L) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_BT1361(L * factor), V * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_oetf_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_BT1361` definition nan support. + """ + + oetf_BT1361(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan])) + + +class TestOetf_inverse_BT1361(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_inverse_BT1361` definition unit tests methods. + """ + + def test_oetf_inverse_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_inverse_BT1361` definition. + """ + + self.assertAlmostEqual( + oetf_inverse_BT1361(-0.212243985492969), -0.18, places=7 + ) + + self.assertAlmostEqual(oetf_inverse_BT1361(0.0), 0.0, places=7) + + self.assertAlmostEqual( + oetf_inverse_BT1361(0.067500000000000), 0.015, places=7 + ) + + self.assertAlmostEqual( + oetf_inverse_BT1361(0.409007728864150), 0.18, places=7 + ) + + self.assertAlmostEqual(oetf_inverse_BT1361(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_inverse_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_inverse_BT1361` definition n-dimensional arrays support. + """ + + V = 0.409007728864150 + L = oetf_inverse_BT1361(V) + + V = np.tile(V, 6) + L = np.tile(L, 6) + np.testing.assert_array_almost_equal( + oetf_inverse_BT1361(V), L, decimal=7 + ) + + V = np.reshape(V, (2, 3)) + L = np.reshape(L, (2, 3)) + np.testing.assert_array_almost_equal( + oetf_inverse_BT1361(V), L, decimal=7 + ) + + V = np.reshape(V, (2, 3, 1)) + L = np.reshape(L, (2, 3, 1)) + np.testing.assert_array_almost_equal( + oetf_inverse_BT1361(V), L, decimal=7 + ) + + def test_domain_range_scale_oetf_inverse_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_inverse_BT1361` definition domain and range scale support. + """ + + V = 0.409007728864150 + L = oetf_inverse_BT1361(V) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_inverse_BT1361(V * factor), L * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_oetf_inverse_BT1361(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itur_bt_1361.\ +oetf_inverse_BT1361` definition nan support. + """ + + oetf_inverse_BT1361( + np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]) + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/colour/models/rgb/transfer_functions/tests/test_itut_h_273.py b/colour/models/rgb/transfer_functions/tests/test_itut_h_273.py new file mode 100644 index 0000000000..a6aa469a3a --- /dev/null +++ b/colour/models/rgb/transfer_functions/tests/test_itut_h_273.py @@ -0,0 +1,657 @@ +""" +Define the unit tests for the +:mod:`colour.models.rgb.transfer_functions.itut_h_273` module. +""" + +import numpy as np +import unittest + +from colour.models.rgb.transfer_functions import ( + oetf_H273_Log, + oetf_inverse_H273_Log, + oetf_H273_LogSqrt, + oetf_inverse_H273_LogSqrt, + oetf_H273_IEC61966_2, + oetf_inverse_H273_IEC61966_2, + eotf_inverse_H273_ST428_1, + eotf_H273_ST428_1, +) +from colour.utilities import domain_range_scale, ignore_numpy_errors + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "TestOetf_H273_Log", + "TestOetf_inverse_H273_Log", + "TestOetf_H273_LogSqrt", + "TestOetf_inverse_H273_LogSqrt", + "TestOetf_H273_IEC61966_2", + "TestOetf_inverse_H273_IEC61966_2", + "TestEotf_inverse_H273_ST428_1", + "TestEotf_H273_ST428_1", +] + + +class TestOetf_H273_Log(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273. + oetf_H273_Log` definition unit tests methods. + """ + + def test_oetf_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_Log` definition. + """ + + self.assertAlmostEqual(oetf_H273_Log(0.0), 0.0, places=7) + + self.assertAlmostEqual( + oetf_H273_Log(0.18), 0.627636252551653, places=7 + ) + + self.assertAlmostEqual(oetf_H273_Log(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_Log` definition n-dimensional arrays support. + """ + + E = 0.18 + E_p = oetf_H273_Log(E) + + E = np.tile(E, 6) + E_p = np.tile(E_p, 6) + np.testing.assert_array_almost_equal(oetf_H273_Log(E), E_p, decimal=7) + + E = np.reshape(E, (2, 3)) + E_p = np.reshape(E_p, (2, 3)) + np.testing.assert_array_almost_equal(oetf_H273_Log(E), E_p, decimal=7) + + E = np.reshape(E, (2, 3, 1)) + E_p = np.reshape(E_p, (2, 3, 1)) + np.testing.assert_array_almost_equal(oetf_H273_Log(E), E_p, decimal=7) + + def test_domain_range_scale_oetf_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_Log` definition domain and range scale support. + """ + + E = 0.18 + E_p = oetf_H273_Log(E) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_H273_Log(E * factor), E_p * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_oetf_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_Log` definition nan support. + """ + + oetf_H273_Log(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan])) + + +class TestOetf_inverse_H273_Log(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_Log` definition unit tests methods. + """ + + def test_oetf_inverse_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_Log` definition. + """ + + # NOTE: The function is unfortunately clamped and cannot roundtrip + # properly. + self.assertAlmostEqual(oetf_inverse_H273_Log(0.0), 0.01, places=7) + + self.assertAlmostEqual( + oetf_inverse_H273_Log(0.627636252551653), 0.18, places=7 + ) + + self.assertAlmostEqual(oetf_inverse_H273_Log(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_inverse_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_Log` definition n-dimensional arrays support. + """ + + E_p = 0.627636252551653 + E = oetf_inverse_H273_Log(E_p) + + E_p = np.tile(E_p, 6) + E = np.tile(E, 6) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_Log(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3)) + E = np.reshape(E, (2, 3)) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_Log(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3, 1)) + E = np.reshape(E, (2, 3, 1)) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_Log(E_p), E, decimal=7 + ) + + def test_domain_range_scale_oetf_inverse_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_Log` definition domain and range scale support. + """ + + E_p = 0.627636252551653 + E = oetf_inverse_H273_Log(E_p) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_inverse_H273_Log(E_p * factor), E * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_oetf_inverse_H273_Log(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_Log` definition nan support. + """ + + oetf_inverse_H273_Log( + np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]) + ) + + +class TestOetf_H273_LogSqrt(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273. + oetf_H273_LogSqrt` definition unit tests methods. + """ + + def test_oetf_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_LogSqrt` definition. + """ + + self.assertAlmostEqual(oetf_H273_LogSqrt(0.0), 0.0, places=7) + + self.assertAlmostEqual( + oetf_H273_LogSqrt(0.18), 0.702109002041322, places=7 + ) + + self.assertAlmostEqual(oetf_H273_LogSqrt(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_LogSqrt` definition n-dimensional arrays support. + """ + + E = 0.18 + E_p = oetf_H273_LogSqrt(E) + + E = np.tile(E, 6) + E_p = np.tile(E_p, 6) + np.testing.assert_array_almost_equal( + oetf_H273_LogSqrt(E), E_p, decimal=7 + ) + + E = np.reshape(E, (2, 3)) + E_p = np.reshape(E_p, (2, 3)) + np.testing.assert_array_almost_equal( + oetf_H273_LogSqrt(E), E_p, decimal=7 + ) + + E = np.reshape(E, (2, 3, 1)) + E_p = np.reshape(E_p, (2, 3, 1)) + np.testing.assert_array_almost_equal( + oetf_H273_LogSqrt(E), E_p, decimal=7 + ) + + def test_domain_range_scale_oetf_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_LogSqrt` definition domain and range scale support. + """ + + E = 0.18 + E_p = oetf_H273_LogSqrt(E) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_H273_LogSqrt(E * factor), E_p * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_oetf_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_LogSqrt` definition nan support. + """ + + oetf_H273_LogSqrt(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan])) + + +class TestOetf_inverse_H273_LogSqrt(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_LogSqrt` definition unit tests methods. + """ + + def test_oetf_inverse_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_LogSqrt` definition. + """ + + # NOTE: The function is unfortunately clamped and cannot roundtrip + # properly. + self.assertAlmostEqual( + oetf_inverse_H273_LogSqrt(0.0), 0.003162277660168, places=7 + ) + + self.assertAlmostEqual( + oetf_inverse_H273_LogSqrt(0.702109002041322), 0.18, places=7 + ) + + self.assertAlmostEqual(oetf_inverse_H273_LogSqrt(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_inverse_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_LogSqrt` definition n-dimensional arrays support. + """ + + E_p = 0.702109002041322 + E = oetf_inverse_H273_LogSqrt(E_p) + + E_p = np.tile(E_p, 6) + E = np.tile(E, 6) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_LogSqrt(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3)) + E = np.reshape(E, (2, 3)) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_LogSqrt(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3, 1)) + E = np.reshape(E, (2, 3, 1)) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_LogSqrt(E_p), E, decimal=7 + ) + + def test_domain_range_scale_oetf_inverse_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_LogSqrt` definition domain and range scale support. + """ + + E_p = 0.702109002041322 + E = oetf_inverse_H273_LogSqrt(E_p) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_inverse_H273_LogSqrt(E_p * factor), + E * factor, + decimal=7, + ) + + @ignore_numpy_errors + def test_nan_oetf_inverse_H273_LogSqrt(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_LogSqrt` definition nan support. + """ + + oetf_inverse_H273_LogSqrt( + np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]) + ) + + +class TestOetf_H273_IEC61966_2(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273. + oetf_H273_IEC61966_2` definition unit tests methods. + """ + + def test_oetf_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_IEC61966_2` definition. + """ + + self.assertAlmostEqual( + oetf_H273_IEC61966_2(-0.18), -0.461356129500442, places=7 + ) + + self.assertAlmostEqual(oetf_H273_IEC61966_2(0.0), 0.0, places=7) + + self.assertAlmostEqual( + oetf_H273_IEC61966_2(0.18), 0.461356129500442, places=7 + ) + + self.assertAlmostEqual(oetf_H273_IEC61966_2(1.0), 1.0, places=7) + + def test_n_dimensional_oetf_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_IEC61966_2` definition n-dimensional arrays support. + """ + + E = 0.18 + E_p = oetf_H273_IEC61966_2(E) + + E = np.tile(E, 6) + E_p = np.tile(E_p, 6) + np.testing.assert_array_almost_equal( + oetf_H273_IEC61966_2(E), E_p, decimal=7 + ) + + E = np.reshape(E, (2, 3)) + E_p = np.reshape(E_p, (2, 3)) + np.testing.assert_array_almost_equal( + oetf_H273_IEC61966_2(E), E_p, decimal=7 + ) + + E = np.reshape(E, (2, 3, 1)) + E_p = np.reshape(E_p, (2, 3, 1)) + np.testing.assert_array_almost_equal( + oetf_H273_IEC61966_2(E), E_p, decimal=7 + ) + + def test_domain_range_scale_oetf_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_IEC61966_2` definition domain and range scale support. + """ + + E = 0.18 + E_p = oetf_H273_IEC61966_2(E) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_H273_IEC61966_2(E * factor), E_p * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_oetf_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_H273_IEC61966_2` definition nan support. + """ + + oetf_H273_IEC61966_2( + np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]) + ) + + +class TestOetf_inverse_H273_IEC61966_2(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_IEC61966_2` definition unit tests methods. + """ + + def test_oetf_inverse_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_IEC61966_2` definition. + """ + + self.assertAlmostEqual( + oetf_inverse_H273_IEC61966_2(-0.461356129500442), -0.18, places=7 + ) + + self.assertAlmostEqual( + oetf_inverse_H273_IEC61966_2(0.0), 0.0, places=7 + ) + + self.assertAlmostEqual( + oetf_inverse_H273_IEC61966_2(0.461356129500442), 0.18, places=7 + ) + + self.assertAlmostEqual( + oetf_inverse_H273_IEC61966_2(1.0), 1.0, places=7 + ) + + def test_n_dimensional_oetf_inverse_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_IEC61966_2` definition n-dimensional arrays support. + """ + + E_p = 0.627636252551653 + E = oetf_inverse_H273_IEC61966_2(E_p) + + E_p = np.tile(E_p, 6) + E = np.tile(E, 6) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_IEC61966_2(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3)) + E = np.reshape(E, (2, 3)) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_IEC61966_2(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3, 1)) + E = np.reshape(E, (2, 3, 1)) + np.testing.assert_array_almost_equal( + oetf_inverse_H273_IEC61966_2(E_p), E, decimal=7 + ) + + def test_domain_range_scale_oetf_inverse_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_IEC61966_2` definition domain and range scale support. + """ + + E_p = 0.627636252551653 + E = oetf_inverse_H273_IEC61966_2(E_p) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + oetf_inverse_H273_IEC61966_2(E_p * factor), + E * factor, + decimal=7, + ) + + @ignore_numpy_errors + def test_nan_oetf_inverse_H273_IEC61966_2(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +oetf_inverse_H273_IEC61966_2` definition nan support. + """ + + oetf_inverse_H273_IEC61966_2( + np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]) + ) + + +class TestEotf_inverse_H273_ST428_1(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273. + eotf_inverse_H273_ST428_1` definition unit tests methods. + """ + + def test_eotf_inverse_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_inverse_H273_ST428_1` definition. + """ + + self.assertAlmostEqual(eotf_inverse_H273_ST428_1(0.0), 0.0, places=7) + + self.assertAlmostEqual( + eotf_inverse_H273_ST428_1(0.18), 0.500048337717236, places=7 + ) + + self.assertAlmostEqual( + eotf_inverse_H273_ST428_1(1.0), 0.967042675317934, places=7 + ) + + def test_n_dimensional_eotf_inverse_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_inverse_H273_ST428_1` definition n-dimensional arrays support. + """ + + E = 0.18 + E_p = eotf_inverse_H273_ST428_1(E) + + E = np.tile(E, 6) + E_p = np.tile(E_p, 6) + np.testing.assert_array_almost_equal( + eotf_inverse_H273_ST428_1(E), E_p, decimal=7 + ) + + E = np.reshape(E, (2, 3)) + E_p = np.reshape(E_p, (2, 3)) + np.testing.assert_array_almost_equal( + eotf_inverse_H273_ST428_1(E), E_p, decimal=7 + ) + + E = np.reshape(E, (2, 3, 1)) + E_p = np.reshape(E_p, (2, 3, 1)) + np.testing.assert_array_almost_equal( + eotf_inverse_H273_ST428_1(E), E_p, decimal=7 + ) + + def test_domain_range_scale_eotf_inverse_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_inverse_H273_ST428_1` definition domain and range scale support. + """ + + E = 0.18 + E_p = eotf_inverse_H273_ST428_1(E) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + eotf_inverse_H273_ST428_1(E * factor), + E_p * factor, + decimal=7, + ) + + @ignore_numpy_errors + def test_nan_eotf_inverse_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_inverse_H273_ST428_1` definition nan support. + """ + + eotf_inverse_H273_ST428_1( + np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan]) + ) + + +class TestEotf_H273_ST428_1(unittest.TestCase): + """ + Define :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_H273_ST428_1` definition unit tests methods. + """ + + def test_eotf_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_H273_ST428_1` definition. + """ + + self.assertAlmostEqual(eotf_H273_ST428_1(0.0), 0.0, places=7) + + self.assertAlmostEqual( + eotf_H273_ST428_1(0.500048337717236), 0.18, places=7 + ) + + self.assertAlmostEqual( + eotf_H273_ST428_1(0.967042675317934), 1.0, places=7 + ) + + def test_n_dimensional_eotf_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_H273_ST428_1` definition n-dimensional arrays support. + """ + + E_p = 0.500048337717236 + E = eotf_H273_ST428_1(E_p) + + E_p = np.tile(E_p, 6) + E = np.tile(E, 6) + np.testing.assert_array_almost_equal( + eotf_H273_ST428_1(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3)) + E = np.reshape(E, (2, 3)) + np.testing.assert_array_almost_equal( + eotf_H273_ST428_1(E_p), E, decimal=7 + ) + + E_p = np.reshape(E_p, (2, 3, 1)) + E = np.reshape(E, (2, 3, 1)) + np.testing.assert_array_almost_equal( + eotf_H273_ST428_1(E_p), E, decimal=7 + ) + + def test_domain_range_scale_eotf_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_H273_ST428_1` definition domain and range scale support. + """ + + E_p = 0.500048337717236 + E = eotf_H273_ST428_1(E_p) + + d_r = (("reference", 1), ("1", 1), ("100", 100)) + for scale, factor in d_r: + with domain_range_scale(scale): + np.testing.assert_array_almost_equal( + eotf_H273_ST428_1(E_p * factor), E * factor, decimal=7 + ) + + @ignore_numpy_errors + def test_nan_eotf_H273_ST428_1(self): + """ + Test :func:`colour.models.rgb.transfer_functions.itut_h_273.\ +eotf_H273_ST428_1` definition nan support. + """ + + eotf_H273_ST428_1(np.array([-1.0, 0.0, 1.0, -np.inf, np.inf, np.nan])) + + +if __name__ == "__main__": + unittest.main() diff --git a/colour/models/rgb/video.py b/colour/models/rgb/video.py deleted file mode 100644 index e09660a015..0000000000 --- a/colour/models/rgb/video.py +++ /dev/null @@ -1,664 +0,0 @@ -""" -ITU-T H.273 video colour metadata -================================= - -Defines aliases to a set of standard colour primaries, transfer functions and -YUV to RGB matrix coefficients used in video metadata. - -These metadata were historically defined in ISO/IEC 23001-8 (:cite:`ISO2013`) then -superseded and duplicated by other standards (among others: :cite:`ISO2020`, -:cite:`ISO2021`, :cite:`ITU2021`). They are widely in use to define color-related -properties in video encoding and decoding software libraries, including ffmpeg. - -References ----------- -- :cite:`ITU2021` : International Telecommunication Union. (2021). - Recommendation ITU-T H.273 - Coding-independent code points for video - signal type identification. - https://www.itu.int/rec/T-REC-H.273-202107-I/en -- :cite:`ISO2013` : International Organization for Standardization. (2013). - INTERNATIONAL STANDARD ISO/IEC 23001-8:2013 - Information technology - MPEG - systems technologies - Part 8: Coding-independent code points, §7.1 "Colour - primaries" -- :cite:`ISO2021` : International Organization for Standardization. (2021). - INTERNATIONAL STANDARD ISO/IEC 23091-2:2021 - Information technology - - Coding-independent code points - Part 2: Video, §8.1 "Colour primaries" -- :cite:`ISO2020` : International Organization for Standardization. (2020). - INTERNATIONAL STANDARD ISO/IEC 14496-10:2020 - Information technology - - Coding of audio-visual objects - Part 10: Advanced video coding" -""" - -import functools -import enum - -import numpy as np - -import colour - -import colour.models.rgb.datasets.itut_h_273 -from colour.models.rgb.transfer_functions.gamma import gamma_function -from colour.models.rgb.transfer_functions.itur_bt_709 import oetf_BT709 -from colour.models.rgb.transfer_functions.itur_bt_1886 import eotf_BT1886 -from colour.models.rgb.transfer_functions.itur_bt_2020 import oetf_BT2020 -from colour.models.rgb.transfer_functions.itur_bt_1361 import ( - oetf_BT1361_extended, -) -from colour.models.rgb.transfer_functions.itur_bt_2100 import oetf_BT2100_HLG -from colour.models.rgb.transfer_functions.st_428 import eotf_inverse_ST428_1 -from colour.models.rgb.transfer_functions.st_2084 import eotf_inverse_ST2084 -from colour.models.rgb.transfer_functions.iec_61966_2 import ( - oetf_iec_61966_2_unbounded, -) -from colour.models.rgb.transfer_functions.itur_bt_601 import oetf_BT601 -from colour.models.rgb.transfer_functions.smpte_240m import oetf_SMPTE240M -from colour.models.rgb.transfer_functions.itut_h_273 import ( - oetf_linear, - oetf_log, - oetf_log_sqrt, -) - -__all__ = [ - "CCS_WHITEPOINTS_ISO14496_10", - "CCS_WHITEPOINTS_ISO23001_8", - "CCS_WHITEPOINTS_ISO23091_2", - "CCS_WHITEPOINTS_ITU_T_H273", - "ColourPrimaries_ISO14496_10", - "ColourPrimaries_ISO23001_8", - "ColourPrimaries_ISO23091_2", - "ColourPrimaries_ITU_T_H273", - "MATRICES_ISO14496_10_RGB_TO_XYZ", - "MATRICES_ISO23001_8_RGB_TO_XYZ", - "MATRICES_ISO23091_2_RGB_TO_XYZ", - "MATRICES_ITU_T_H273_RGB_TO_XYZ", - "MATRICES_XYZ_TO_ISO14496_10_RGB", - "MATRICES_XYZ_TO_ISO23001_8_RGB", - "MATRICES_XYZ_TO_ISO23091_2_RGB", - "MATRICES_XYZ_TO_ITU_T_H273_RGB", - "MatrixCoefficients_ISO14496_10", - "MatrixCoefficients_ISO23001_8", - "MatrixCoefficients_ISO23091_2", - "MatrixCoefficients_ITU_T_H273", - "PRIMARIES_ISO14496_10", - "PRIMARIES_ISO23001_8", - "PRIMARIES_ISO23091_2", - "PRIMARIES_ITU_T_H273", - "TRANSFER_FUNCTIONS_ISO14496_10", - "TRANSFER_FUNCTIONS_ISO23001_8", - "TRANSFER_FUNCTIONS_ISO23091_2", - "TRANSFER_FUNCTIONS_ITU_T_H273", - "TransferCharacteristics_ISO14496_10", - "TransferCharacteristics_ISO23001_8", - "TransferCharacteristics_ISO23091_2", - "TransferCharacteristics_ITU_T_H273", - "WEIGHTS_YCBCR_ISO14496_10", - "WEIGHTS_YCBCR_ISO23001_8", - "WEIGHTS_YCBCR_ISO23091_2", - "WEIGHTS_YCBCR_ITU_T_H273", - "WHITEPOINTS_NAMES_ISO14496_10", - "WHITEPOINTS_NAMES_ISO23001_8", - "WHITEPOINTS_NAMES_ISO23091_2", - "WHITEPOINTS_NAMES_ITU_T_H273", - "eotf_BT1886", - "eotf_inverse_ST2084", - "eotf_inverse_ST428_1", - "eotf_inverse_gamma22", - "eotf_inverse_gamma28", - "oetf_BT1361_extended", - "oetf_BT2020_10bit", - "oetf_BT2020_12bit", - "oetf_BT2100_HLG", - "oetf_BT601", - "oetf_BT709", - "oetf_SMPTE240M", - "oetf_iec_61966_2_1", - "oetf_iec_61966_2_4", - "oetf_linear", - "oetf_log", - "oetf_log_sqrt", -] - -oetf_BT2020_12bit = functools.partial(oetf_BT2020, is_12_bits_system=True) -oetf_BT2020_10bit = functools.partial(oetf_BT2020, is_12_bits_system=False) -eotf_inverse_gamma22 = functools.partial(gamma_function, exponent=1 / 2.2) -eotf_inverse_gamma28 = functools.partial(gamma_function, exponent=1 / 2.8) -oetf_iec_61966_2_4 = oetf_iec_61966_2_unbounded -oetf_iec_61966_2_1 = oetf_iec_61966_2_unbounded - - -@enum.unique -class ColourPrimaries_ITU_T_H273(enum.IntEnum): - """ColourPrimaries tags as defined in ITU-T H.273 § 8.1. - - The enumeration members use the same names as ffmpeg `AVCOL_PRI_*` constants. - """ - - BT709 = 1 # also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B - BT470M = 4 # also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) - - # also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM - BT470BG = 5 - - SMPTE170M = ( - 6 # also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC - ) - SMPTE240M = 7 # functionally identical to above - FILM = 8 # colour filters using Illuminant C - BT2020 = 9 # ITU-R BT2020 - SMPTE428 = 10 # SMPTE ST 428-1 (CIE 1931 XYZ) - SMPTE431 = 11 # SMPTE ST 431-2 (2011) / DCI P3 - SMPTE432 = 12 # SMPTE ST 432-1 (2010) / P3 D65 / Display P3 - - # Note: This corresponds to "AVCOL_PRI_EBU3213" in ffmpeg, but neither ITU-T - # H.273:2021 nor ISO/IEC 23091-2:2021 contain the same values as EBU Tech. 3213, nor - # do they refer to it directly (ColourPrimaries=22 contains the remark "No - # corresponding industry specification identified" in both cases). - # - # Since both ISO/IEC 23001-8:2013 and 14497-10:2020 do refer to EBU Tech 3213-E - # (1975) but contain the same primaries and whitepoint as the 2021 revisions, this - # is likely a error in the initial standards that was later discovered and - # corrected. - UNKNOWN22 = 22 - - -@enum.unique -class TransferCharacteristics_ITU_T_H273(enum.IntEnum): - """TransferCharacteristics tags as defined in ITU-T H.273 § 8.2. - - The enumeration members use the same names as ffmpeg `AVCOL_TRC_*` constants. - """ - - BT709 = 1 # also ITU-R BT1361 - GAMMA22 = 4 # also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM - GAMMA28 = 5 # also ITU-R BT470BG - - # also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC - SMPTE170M = 6 - - SMPTE240M = 7 - LINEAR = 8 # "Linear transfer characteristics" - LOG = 9 # "Logarithmic transfer characteristic (100:1 range)" - - # "Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range)" - LOG_SQRT = 10 - - IEC61966_2_4 = 11 # IEC 61966-2-4 - BT1361_ECG = 12 # ITU-R BT1361 Extended Colour Gamut - IEC61966_2_1 = 13 # IEC 61966-2-1 (sRGB or sYCC) - BT2020_10 = 14 # ITU-R BT2020 for 10-bit system - BT2020_12 = 15 # ITU-R BT2020 for 12-bit system - SMPTE2084 = 16 # SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems - SMPTE428 = 17 # SMPTE ST 428-1 - ARIB_STD_B67 = 18 # ARIB STD-B67, known as "Hybrid log-gamma" - - -@enum.unique -class MatrixCoefficients_ITU_T_H273(enum.IntEnum): - """MatrixCoefficients tags as defined in ITU-T H.273 § 8.3 - - The enumeration members use the same names as ffmpeg `AVCOL_SPC_*` constants. - """ - - RGB = 0 # order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB) - BT709 = ( - 1 # also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / SMPTE RP177 Annex B - ) - FCC = 4 # FCC Title 47 Code of Federal Regulations 73.682 (a)(20) - - # also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM - # / IEC 61966-2-4 xvYCC601 - BT470BG = 5 - - SMPTE170M = ( - 6 # also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC - ) - SMPTE240M = 7 # functionally identical to above - YCGCO = 8 # Used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16 - BT2020_NCL = 9 # ITU-R BT2020 non-constant luminance system - BT2020_CL = 10 # ITU-R BT2020 constant luminance system - SMPTE2085 = 11 # SMPTE 2085, Y'D'zD'x - CHROMA_DERIVED_NCL = ( - 12 # Chromaticity-derived non-constant luminance system - ) - CHROMA_DERIVED_CL = 13 # Chromaticity-derived constant luminance system - ICTCP = 14 # ITU-R BT.2100-0, ICtCp - - -PRIMARIES_ITU_T_H273 = { - # 0: Reserved for future use - # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B - ColourPrimaries_ITU_T_H273.BT709: ( - colour.models.rgb.datasets.itur_bt_709.PRIMARIES_BT709 - ), - # 2: Unspecified - # 3: Reserved for future use - # 4: ITU-R BT.470-6 System M - ColourPrimaries_ITU_T_H273.BT470M: ( - colour.models.rgb.datasets.itur_bt_470.PRIMARIES_BT470_525 - ), - # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 - ColourPrimaries_ITU_T_H273.BT470BG: ( - colour.models.rgb.datasets.itur_bt_470.PRIMARIES_BT470_625 - ), - # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) - ColourPrimaries_ITU_T_H273.SMPTE170M: ( - colour.models.rgb.datasets.smpte_240m.PRIMARIES_SMPTE_240M - ), - # 7: SMPTE 240M (same as 6) - ColourPrimaries_ITU_T_H273.SMPTE240M: ( - colour.models.rgb.datasets.smpte_240m.PRIMARIES_SMPTE_240M - ), - # 8: Generic film (colour filters using Illuminant C) - ColourPrimaries_ITU_T_H273.FILM: ( - colour.models.rgb.datasets.itut_h_273.PRIMARIES_FILM_C - ), - # 9: ITU-R BT.2020 - ColourPrimaries_ITU_T_H273.BT2020: ( - colour.models.rgb.datasets.itur_bt_2020.PRIMARIES_BT2020 - ), - # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) - ColourPrimaries_ITU_T_H273.SMPTE428: ( - colour.models.rgb.datasets.dcdm_xyz.PRIMARIES_DCDM_XYZ - ), - # 11: SMPTE RP 431-2 (2011) - ColourPrimaries_ITU_T_H273.SMPTE431: ( - colour.models.rgb.datasets.dci_p3.PRIMARIES_DCI_P3 - ), - # 12: SMPTE EG 432-1 (2010) - ColourPrimaries_ITU_T_H273.SMPTE432: ( - colour.models.rgb.datasets.p3_d65.PRIMARIES_P3_D65 - ), - # 13-21: Reserved for future use - # 22: No corresponding industry specification - ColourPrimaries_ITU_T_H273.UNKNOWN22: ( - colour.models.rgb.datasets.itut_h_273.PRIMARIES_ITUT_H273_22 - ), - # 23-255: Reserved for future use -} -"""ColourPrimaries tag to colour primaries mapping defined in ITU-T H.273 § -8.1""" - - -CCS_WHITEPOINTS_ITU_T_H273 = { - # 0: Reserved for future use - # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B - ColourPrimaries_ITU_T_H273.BT709: ( - colour.models.rgb.datasets.itur_bt_709.CCS_WHITEPOINT_BT709 - ), - # 2: Unspecified - # 3: Reserved for future use - # 4: ITU-R BT.470-6 System M - ColourPrimaries_ITU_T_H273.BT470M: ( - # Note: ITU-T H.273 defines white point C as [0.310, 0.316], while this - # has a slightly higher precision. - colour.models.rgb.datasets.itur_bt_470.CCS_WHITEPOINT_BT470_525 - ), - # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 - ColourPrimaries_ITU_T_H273.BT470BG: ( - colour.models.rgb.datasets.itur_bt_470.CCS_WHITEPOINT_BT470_625 - ), - # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) - ColourPrimaries_ITU_T_H273.SMPTE170M: ( - colour.models.rgb.datasets.smpte_240m.CCS_WHITEPOINT_SMPTE_240M - ), - # 7: SMPTE 240M (same as 6) - ColourPrimaries_ITU_T_H273.SMPTE240M: ( - colour.models.rgb.datasets.smpte_240m.CCS_WHITEPOINT_SMPTE_240M - ), - # 8: Generic film (colour filters using Illuminant C) - ColourPrimaries_ITU_T_H273.FILM: ( - colour.models.rgb.datasets.itut_h_273.CCS_WHITEPOINT_FILM_C - ), - # 9: ITU-R BT.2020 - ColourPrimaries_ITU_T_H273.BT2020: ( - colour.models.rgb.datasets.itur_bt_2020.CCS_WHITEPOINT_BT2020 - ), - # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) - ColourPrimaries_ITU_T_H273.SMPTE428: ( - colour.models.rgb.datasets.dcdm_xyz.CCS_WHITEPOINT_DCDM_XYZ - ), - # 11: SMPTE RP 431-2 (2011) - ColourPrimaries_ITU_T_H273.SMPTE431: ( - colour.models.rgb.datasets.dci_p3.CCS_WHITEPOINT_DCI_P3 - ), - # 12: SMPTE EG 432-1 (2010) - ColourPrimaries_ITU_T_H273.SMPTE432: ( - colour.models.rgb.datasets.p3_d65.CCS_WHITEPOINT_P3_D65 - ), - # 13-21: Reserved for future use - # 22: No corresponding industry specification - ColourPrimaries_ITU_T_H273.UNKNOWN22: ( - colour.models.rgb.datasets.itut_h_273.CCS_WHITEPOINT_ITUT_H273_22 - ), - # 23-255: Reserved for future use -} -"""ColourPrimaries tag to whitepoint chromaticity coordinates mapping defined -in ITU-T H.273 § 8.1""" - - -WHITEPOINTS_NAMES_ITU_T_H273 = { - # 0: Reserved for future use - # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B - ColourPrimaries_ITU_T_H273.BT709: ( - colour.models.rgb.datasets.itur_bt_709.WHITEPOINT_NAME_BT709 - ), - # 2: Unspecified - # 3: Reserved for future use - # 4: ITU-R BT.470-6 System M - ColourPrimaries_ITU_T_H273.BT470M: ( - colour.models.rgb.datasets.itur_bt_470.WHITEPOINT_NAME_BT470_525 - ), - # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 - ColourPrimaries_ITU_T_H273.BT470BG: ( - colour.models.rgb.datasets.itur_bt_470.WHITEPOINT_NAME_BT470_625 - ), - # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) - ColourPrimaries_ITU_T_H273.SMPTE170M: ( - colour.models.rgb.datasets.smpte_240m.WHITEPOINT_NAME_SMPTE_240M - ), - # 7: SMPTE 240M (same as 6) - ColourPrimaries_ITU_T_H273.SMPTE240M: ( - colour.models.rgb.datasets.smpte_240m.WHITEPOINT_NAME_SMPTE_240M - ), - # 8: Generic film (colour filters using Illuminant C) - ColourPrimaries_ITU_T_H273.FILM: ( - colour.models.rgb.datasets.itut_h_273.WHITEPOINT_NAME_FILM_C - ), - # 9: ITU-R BT.2020 - ColourPrimaries_ITU_T_H273.BT2020: ( - colour.models.rgb.datasets.itur_bt_2020.WHITEPOINT_NAME_BT2020 - ), - # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) - ColourPrimaries_ITU_T_H273.SMPTE428: ( - colour.models.rgb.datasets.dcdm_xyz.WHITEPOINT_NAME_DCDM_XYZ - ), - # 11: SMPTE RP 431-2 (2011) - ColourPrimaries_ITU_T_H273.SMPTE431: ( - colour.models.rgb.datasets.dci_p3.WHITEPOINT_NAME_DCI_P3 - ), - # 12: SMPTE EG 432-1 (2010) - ColourPrimaries_ITU_T_H273.SMPTE432: ( - colour.models.rgb.datasets.p3_d65.WHITEPOINT_NAME_P3_D65 - ), - # 13-21: Reserved for future use - # 22: No corresponding industry specification - ColourPrimaries_ITU_T_H273.UNKNOWN22: ( - colour.models.rgb.datasets.itut_h_273.WHITEPOINT_NAME_ITUT_H273_22 - ), - # 23-255: Reserved for future use -} -"""ColourPrimaries tag to whitepoint names mapping defined in ITU-T H.273 § -8.1""" - - -MATRICES_ITU_T_H273_RGB_TO_XYZ = { - # 0: Reserved for future use - # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B - ColourPrimaries_ITU_T_H273.BT709: ( - colour.models.rgb.datasets.itur_bt_709.MATRIX_BT709_TO_XYZ - ), - # 2: Unspecified - # 3: Reserved for future use - # 4: ITU-R BT.470-6 System M - ColourPrimaries_ITU_T_H273.BT470M: ( - colour.models.rgb.datasets.itur_bt_470.MATRIX_BT470_525_TO_XYZ - ), - # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 - ColourPrimaries_ITU_T_H273.BT470BG: ( - colour.models.rgb.datasets.itur_bt_470.MATRIX_BT470_625_TO_XYZ - ), - # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) - ColourPrimaries_ITU_T_H273.SMPTE170M: ( - colour.models.rgb.datasets.smpte_240m.MATRIX_SMPTE_240M_TO_XYZ - ), - # 7: SMPTE 240M (same as 6) - ColourPrimaries_ITU_T_H273.SMPTE240M: ( - colour.models.rgb.datasets.smpte_240m.MATRIX_SMPTE_240M_TO_XYZ - ), - # 8: Generic film (colour filters using Illuminant C) - ColourPrimaries_ITU_T_H273.FILM: ( - colour.models.rgb.datasets.itut_h_273.MATRIX_FILM_C_RGB_TO_XYZ - ), - # 9: ITU-R BT.2020 - ColourPrimaries_ITU_T_H273.BT2020: ( - colour.models.rgb.datasets.itur_bt_2020.MATRIX_BT2020_TO_XYZ - ), - # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) - ColourPrimaries_ITU_T_H273.SMPTE428: ( - colour.models.rgb.datasets.dcdm_xyz.MATRIX_DCDM_XYZ_TO_XYZ - ), - # 11: SMPTE RP 431-2 (2011) - ColourPrimaries_ITU_T_H273.SMPTE431: ( - colour.models.rgb.datasets.dci_p3.MATRIX_DCI_P3_TO_XYZ - ), - # 12: SMPTE EG 432-1 (2010) - ColourPrimaries_ITU_T_H273.SMPTE432: ( - colour.models.rgb.datasets.p3_d65.MATRIX_P3_D65_TO_XYZ - ), - # 13-21: Reserved for future use - # 22: No corresponding industry specification - ColourPrimaries_ITU_T_H273.UNKNOWN22: ( - colour.models.rgb.datasets.itut_h_273.MATRIX_ITUT_H273_22_RGB_TO_XYZ - ), - # 23-255: Reserved for future use -} -"""ColourPrimaries tag to RGB to XYZ matrices determined from primaries and -whitepoints defined in ITU-T H.273 § 8.1""" - - -MATRICES_XYZ_TO_ITU_T_H273_RGB = { - # 0: Reserved for future use - # 1: ITU-R BT.709-5, IEC 61966-2-1 sRGB or sYCC, IEC 61966-2-4, SMPTE RP177 Annex B - ColourPrimaries_ITU_T_H273.BT709: ( - colour.models.rgb.datasets.itur_bt_709.MATRIX_XYZ_TO_BT709 - ), - # 2: Unspecified - # 3: Reserved for future use - # 4: ITU-R BT.470-6 System M - ColourPrimaries_ITU_T_H273.BT470M: ( - colour.models.rgb.datasets.itur_bt_470.MATRIX_XYZ_TO_BT470_525 - ), - # 5: ITU-R BT.470-6 Systems BG, ITU-R BT.601-6 625 - ColourPrimaries_ITU_T_H273.BT470BG: ( - colour.models.rgb.datasets.itur_bt_470.MATRIX_XYZ_TO_BT470_625 - ), - # 6: SMPTE 170M, ITU-R BT.601-6 525 (same as 7) - ColourPrimaries_ITU_T_H273.SMPTE170M: ( - colour.models.rgb.datasets.smpte_240m.MATRIX_XYZ_TO_SMPTE_240M - ), - # 7: SMPTE 240M (same as 6) - ColourPrimaries_ITU_T_H273.SMPTE240M: ( - colour.models.rgb.datasets.smpte_240m.MATRIX_XYZ_TO_SMPTE_240M - ), - # 8: Generic film (colour filters using Illuminant C) - ColourPrimaries_ITU_T_H273.FILM: ( - colour.models.rgb.datasets.itut_h_273.MATRIX_XYZ_TO_FILM_C_RGB - ), - # 9: ITU-R BT.2020 - ColourPrimaries_ITU_T_H273.BT2020: ( - colour.models.rgb.datasets.itur_bt_2020.MATRIX_XYZ_TO_BT2020 - ), - # 10: SMPTE ST 428-1 (DCDM, CIE 1931 XYZ as in ISO 11664-1) - ColourPrimaries_ITU_T_H273.SMPTE428: ( - colour.models.rgb.datasets.dcdm_xyz.MATRIX_XYZ_TO_DCDM_XYZ - ), - # 11: SMPTE RP 431-2 (2011) - ColourPrimaries_ITU_T_H273.SMPTE431: ( - colour.models.rgb.datasets.dci_p3.MATRIX_XYZ_TO_DCI_P3 - ), - # 12: SMPTE EG 432-1 (2010) - ColourPrimaries_ITU_T_H273.SMPTE432: ( - colour.models.rgb.datasets.p3_d65.MATRIX_XYZ_TO_P3_D65 - ), - # 13-21: Reserved for future use - # 22: No corresponding industry specification - ColourPrimaries_ITU_T_H273.UNKNOWN22: ( - colour.models.rgb.datasets.itut_h_273.MATRIX_XYZ_TO_ITUT_H273_22_RGB - ), - # 23-255: Reserved for future use -} -"""ColourPrimaries tag to XYZ to RGB matrices determined from primaries and -whitepoints defined in ITU-T H.273 § 8.1""" - - -TRANSFER_FUNCTIONS_ITU_T_H273 = { - # 0: Reserved for future use - # 1: ITU-R BT.709 - TransferCharacteristics_ITU_T_H273.BT709: oetf_BT709, - # 2: Unspecified - # 3: Reserved for future use - # 4: Gamma 2.2 (also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM) (this is - # an inverse-EOTF) - TransferCharacteristics_ITU_T_H273.GAMMA22: eotf_inverse_gamma22, - # 5: Gamma 2.8 (also ITU-R BT470BG) (this is an inverse-EOTF) - TransferCharacteristics_ITU_T_H273.GAMMA28: eotf_inverse_gamma28, - # 6: SMPTE 170M (also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / - # ITU-R BT1700 NTSC) - TransferCharacteristics_ITU_T_H273.SMPTE170M: oetf_BT601, - # 7: SMPTE 240M - TransferCharacteristics_ITU_T_H273.SMPTE240M: oetf_SMPTE240M, - # 8: Linear transfer characteristics (this is an OETF) - TransferCharacteristics_ITU_T_H273.LINEAR: oetf_linear, - # 9: Logarithmic transfer characteristic (100:1 range) - TransferCharacteristics_ITU_T_H273.LOG: oetf_log, - # 10: Logarithmic transfer characteristic (100 * Sqrt(10) : 1 range) - TransferCharacteristics_ITU_T_H273.LOG_SQRT: oetf_log_sqrt, - # 11: IEC 61966-2-4 - TransferCharacteristics_ITU_T_H273.IEC61966_2_4: oetf_iec_61966_2_4, - # 12: ITU-R BT1361 Extended Colour Gamut - TransferCharacteristics_ITU_T_H273.BT1361_ECG: oetf_BT1361_extended, - # 13: IEC 61966-2-1 (sRGB or sYCC) - TransferCharacteristics_ITU_T_H273.IEC61966_2_1: oetf_iec_61966_2_1, - # 14: ITU-R BT2020 for 10-bit system - TransferCharacteristics_ITU_T_H273.BT2020_10: oetf_BT2020_10bit, - # 15: ITU-R BT2020 for 12-bit system - TransferCharacteristics_ITU_T_H273.BT2020_12: oetf_BT2020_12bit, - # 16: SMPTE ST 2084 (PQ, Perceptual Quantizer) for 10-, 12-, 14- and 16-bit systems - TransferCharacteristics_ITU_T_H273.SMPTE2084: eotf_inverse_ST2084, - # 17: SMPTE ST 428-1 - TransferCharacteristics_ITU_T_H273.SMPTE428: eotf_inverse_ST428_1, - # 18: ARIB STD B67, also ITU-R BT.2100 HLG (Hybrid Log-Gamma), in [0-1] range - TransferCharacteristics_ITU_T_H273.ARIB_STD_B67: oetf_BT2100_HLG, -} -"""Mapping from TransferCharacteristics tag to transfer functions defined in -ITU-T H.273 § 8.2 - -Note that the standard contains both OETFs or inverse-EOTFs.""" - - -WEIGHTS_YCBCR_ITU_T_H273 = {} -"""K_R and K_B coefficients for YCbCr conversion defined in ITU-T H.273 §8.3 - -Notes ------ - -Several values of MatrixCoefficients don't directly correspond to K_R and -K_B values but instead have separate equations, which are not included in -this mapping: - -- MatrixCoefficients_ITU_T_H273.YCGCO -- MatrixCoefficients_ITU_T_H273.SMPTE2085 -- MatrixCoefficients_ITU_T_H273.CHROMA_DERIVED_NCL -- MatrixCoefficients_ITU_T_H273.CHROMA_DERIVED_CL -- MatrixCoefficients_ITU_T_H273.ICTCP -""" - -WEIGHTS_YCBCR_ITU_T_H273[MatrixCoefficients_ITU_T_H273.RGB] = np.array( - [1.0, 1.0] -) -WEIGHTS_YCBCR_ITU_T_H273[ - MatrixCoefficients_ITU_T_H273.BT709 -] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.709"] -WEIGHTS_YCBCR_ITU_T_H273[MatrixCoefficients_ITU_T_H273.FCC] = np.array( - [0.30, 0.11] -) -WEIGHTS_YCBCR_ITU_T_H273[ - MatrixCoefficients_ITU_T_H273.BT470BG -] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.601"] -WEIGHTS_YCBCR_ITU_T_H273[ - MatrixCoefficients_ITU_T_H273.SMPTE170M -] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.601"] -# Note: The precision is different from WEIGHTS_YCBCR["ITU-R SMPTE-240M"] -WEIGHTS_YCBCR_ITU_T_H273[MatrixCoefficients_ITU_T_H273.SMPTE240M] = np.array( - [0.212, 0.087] -) -WEIGHTS_YCBCR_ITU_T_H273[ - MatrixCoefficients_ITU_T_H273.BT2020_NCL -] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.2020"] -WEIGHTS_YCBCR_ITU_T_H273[ - MatrixCoefficients_ITU_T_H273.BT2020_CL -] = colour.models.rgb.ycbcr.WEIGHTS_YCBCR["ITU-R BT.2020"] - - -# Aliases for ISO/IEC 23091-2:2021. Verified to be functionally identical to ITU-T H.273 -# for the values defined here. -ColourPrimaries_ISO23091_2 = ColourPrimaries_ITU_T_H273 -TransferCharacteristics_ISO23091_2 = TransferCharacteristics_ITU_T_H273 -MatrixCoefficients_ISO23091_2 = MatrixCoefficients_ITU_T_H273 -PRIMARIES_ISO23091_2 = PRIMARIES_ITU_T_H273 -WHITEPOINTS_NAMES_ISO23091_2 = WHITEPOINTS_NAMES_ITU_T_H273 -CCS_WHITEPOINTS_ISO23091_2 = CCS_WHITEPOINTS_ITU_T_H273 -MATRICES_ISO23091_2_RGB_TO_XYZ = MATRICES_ITU_T_H273_RGB_TO_XYZ -MATRICES_XYZ_TO_ISO23091_2_RGB = MATRICES_XYZ_TO_ITU_T_H273_RGB -TRANSFER_FUNCTIONS_ISO23091_2 = TRANSFER_FUNCTIONS_ITU_T_H273 -WEIGHTS_YCBCR_ISO23091_2 = WEIGHTS_YCBCR_ITU_T_H273 - - -@enum.unique -class ColourPrimaries_ISO23001_8(enum.IntEnum): - """ColourPrimaries tags as defined in ISO/IEC 23001-8:2013 § 7.1. - - The enumeration members use the same names as ffmpeg `AVCOL_PRI_*` constants. - """ - - BT709 = 1 # also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP177 Annex B - BT470M = 4 # also FCC Title 47 Code of Federal Regulations 73.682 (a)(20) - - # also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM - BT470BG = 5 - - SMPTE170M = ( - 6 # also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC - ) - SMPTE240M = 7 # functionally identical to above - FILM = 8 # colour filters using Illuminant C - BT2020 = 9 # ITU-R BT2020 - SMPTE428 = 10 # SMPTE ST 428-1 (CIE 1931 XYZ) - SMPTE431 = 11 # SMPTE ST 431-2 (2011) / DCI P3 - SMPTE432 = 12 # SMPTE ST 432-1 (2010) / P3 D65 / Display P3 - - # Note: This corresponds to "AVCOL_PRI_EBU3213" in ffmpeg, but neither ITU-T - # H.273:2021 nor ISO/IEC 23091-2:2021 contain the same values as EBU Tech. 3213, nor - # do they refer to it directly (ColourPrimaries=22 contains the remark "No - # corresponding industry specification identified" in both cases). - # - # Since both ISO/IEC 23001-8:2013 and 14497-10:2020 do refer to EBU Tech 3213-E - # (1975) but contain the same primaries and whitepoint as the 2021 revisions, this - # is likely a error in the initial standards that was later discovered and - # corrected. - EBU3213 = 22 - - -# Aliases for ISO/IEC 23001-8:2013. Verified to be functionally identical to ITU-T H.273 -# for the values defined here, except for the remark regarding EBU Tech. 3213-E. -TransferCharacteristics_ISO23001_8 = TransferCharacteristics_ITU_T_H273 -MatrixCoefficients_ISO23001_8 = MatrixCoefficients_ITU_T_H273 -PRIMARIES_ISO23001_8 = PRIMARIES_ITU_T_H273 -WHITEPOINTS_NAMES_ISO23001_8 = WHITEPOINTS_NAMES_ITU_T_H273 -CCS_WHITEPOINTS_ISO23001_8 = CCS_WHITEPOINTS_ITU_T_H273 -MATRICES_ISO23001_8_RGB_TO_XYZ = MATRICES_ITU_T_H273_RGB_TO_XYZ -MATRICES_XYZ_TO_ISO23001_8_RGB = MATRICES_XYZ_TO_ITU_T_H273_RGB -TRANSFER_FUNCTIONS_ISO23001_8 = TRANSFER_FUNCTIONS_ITU_T_H273 -WEIGHTS_YCBCR_ISO23001_8 = WEIGHTS_YCBCR_ITU_T_H273 - -# Aliases for ISO/IEC 14496-10:2020. Verified to be functionally identical to ITU-T -# H.273 for the values defined here, except for the remark regarding EBU Tech. 3213-E. -ColourPrimaries_ISO14496_10 = ColourPrimaries_ISO23001_8 -TransferCharacteristics_ISO14496_10 = TransferCharacteristics_ITU_T_H273 -MatrixCoefficients_ISO14496_10 = MatrixCoefficients_ITU_T_H273 -PRIMARIES_ISO14496_10 = PRIMARIES_ITU_T_H273 -WHITEPOINTS_NAMES_ISO14496_10 = WHITEPOINTS_NAMES_ITU_T_H273 -CCS_WHITEPOINTS_ISO14496_10 = CCS_WHITEPOINTS_ITU_T_H273 -MATRICES_ISO14496_10_RGB_TO_XYZ = MATRICES_ITU_T_H273_RGB_TO_XYZ -MATRICES_XYZ_TO_ISO14496_10_RGB = MATRICES_XYZ_TO_ITU_T_H273_RGB -TRANSFER_FUNCTIONS_ISO14496_10 = TRANSFER_FUNCTIONS_ITU_T_H273 -WEIGHTS_YCBCR_ISO14496_10 = WEIGHTS_YCBCR_ITU_T_H273 diff --git a/docs/colour.models.rst b/docs/colour.models.rst index c99c76d7aa..94cb678d6f 100644 --- a/docs/colour.models.rst +++ b/docs/colour.models.rst @@ -432,9 +432,12 @@ RGB Colourspaces RGB_COLOURSPACE_DCI_P3_P RGB_COLOURSPACE_DISPLAY_P3 RGB_COLOURSPACE_DON_RGB_4 + RGB_COLOURSPACE_EBU_3213_E RGB_COLOURSPACE_ECI_RGB_V2 RGB_COLOURSPACE_EKTA_SPACE_PS_5 RGB_COLOURSPACE_F_GAMUT + RGB_COLOURSPACE_H273_GENERIC_FILM + RGB_COLOURSPACE_H273_22_UNSPECIFIED RGB_COLOURSPACE_PROTUNE_NATIVE RGB_COLOURSPACE_MAX_RGB RGB_COLOURSPACE_NTSC1953 @@ -558,6 +561,12 @@ Opto-Electronic Transfer Functions oetf_inverse_BT601 oetf_BT709 oetf_inverse_BT709 + oetf_H273_Log + oetf_inverse_H273_Log + oetf_H273_LogSqrt + oetf_inverse_H273_LogSqrt + oetf_H273_IEC61966_2 + oetf_inverse_H273_IEC61966_2 oetf_SMPTE240M Electro-Optical Transfer Functions @@ -594,6 +603,8 @@ Electro-Optical Transfer Functions eotf_inverse_BT2100_HLG eotf_BT2100_PQ eotf_inverse_BT2100_PQ + eotf_H273_ST428_1 + eotf_inverse_H273_ST428_1 eotf_SMPTE240M eotf_ST2084 eotf_inverse_ST2084 @@ -850,6 +861,33 @@ IHLS - Hanbury (2003) RGB_to_IHLS IHLS_to_RGB +Recommendation ITU-T H.273 Code points for Video Signal Type Identification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``colour`` + +.. currentmodule:: colour + +.. autosummary:: + :toctree: generated/ + + COLOUR_PRIMARIES_ITUTH273 + TRANSFER_CHARACTERISTICS_ITUTH273 + MATRIX_COEFFICIENTS_ITUTH273 + +**Ancillary Objects** + +``colour.models`` + +.. currentmodule:: colour.models + +.. autosummary:: + :toctree: generated/ + + describe_video_signal_colour_primaries + describe_video_signal_transfer_characteristics + describe_video_signal_matrix_coefficients + Pointer's Gamut --------------- diff --git a/docs/index.rst b/docs/index.rst index 13c03c7c6a..1d29f33d92 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -688,19 +688,20 @@ RGB Colourspaces 'Apple RGB', 'Best RGB', 'Beta RGB', - 'Blackmagic Wide Gamut' + 'Blackmagic Wide Gamut', 'CIE RGB', 'Cinema Gamut', 'ColorMatch RGB', - 'DaVinci Wide Gamut', 'DCDM XYZ', 'DCI-P3', - 'DCI-P3+', + 'DCI-P3-P', 'DJI D-Gamut', 'DRAGONcolor', 'DRAGONcolor2', + 'DaVinci Wide Gamut', 'Display P3', 'Don RGB 4', + 'EBU Tech. 3213-E', 'ECI RGB v2', 'ERIMM RGB', 'Ekta Space PS 5', @@ -710,7 +711,10 @@ RGB Colourspaces 'ITU-R BT.470 - 525', 'ITU-R BT.470 - 625', 'ITU-R BT.709', + 'ITU-T H.273 - 22 Unspecified', + 'ITU-T H.273 - Generic Film', 'Max RGB', + 'N-Gamut', 'NTSC (1953)', 'NTSC (1987)', 'P3-D65', @@ -738,6 +742,8 @@ RGB Colourspaces 'aces', 'adobe1998', 'prophoto', + 'sRGB'] + OETFs ***** @@ -753,8 +759,12 @@ OETFs 'ITU-R BT.2100 PQ', 'ITU-R BT.601', 'ITU-R BT.709', + 'ITU-T H.273 IEC 61966-2', + 'ITU-T H.273 Log', + 'ITU-T H.273 Log Sqrt', 'SMPTE 240M'] + EOTFs ***** @@ -766,6 +776,7 @@ EOTFs 'ITU-R BT.1886', 'ITU-R BT.2100 HLG', 'ITU-R BT.2100 PQ', + 'ITU-T H.273 ST.428-1', 'SMPTE 240M', 'ST 2084', 'sRGB'] @@ -865,6 +876,59 @@ CCTFs Encoding / Decoding 'ViperLog', 'sRGB'] +Recommendation ITU-T H.273 Code points for Video Signal Type Identification +*************************************************************************** + +.. code-block:: python + + >>> colour.COLOUR_PRIMARIES_ITUTH273.keys() + dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 22, 23]) + >>> colour.COLOUR_PRIMARIES_ITUTH273.keys() + >>> description = colour.models.describe_video_signal_colour_primaries(1) + =============================================================================== + * * + * Colour Primaries: 1 * + * ------------------- * + * * + * Primaries : [[ 0.64 0.33] * + * [ 0.3 0.6 ] * + * [ 0.15 0.06]] * + * Whitepoint : [ 0.3127 0.329 ] * + * Whitepoint Name : D65 * + * NPM : [[ 0.4123908 0.35758434 0.18048079] * + * [ 0.21263901 0.71516868 0.07219232] * + * [ 0.01933082 0.11919478 0.95053215]] * + * NPM -1 : [[ 3.24096994 -1.53738318 -0.49861076] * + * [-0.96924364 1.8759675 0.04155506] * + * [ 0.05563008 -0.20397696 1.05697151]] * + * FFmpeg Constants : ['AVCOL_PRI_BT709', 'BT709'] * + * * + =============================================================================== + >>> colour.TRANSFER_CHARACTERISTICS_ITUTH273.keys() + dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]) + >>> description = colour.models.describe_video_signal_transfer_characteristics(1) + =============================================================================== + * * + * Transfer Characteristics: 1 * + * --------------------------- * + * * + * Function : * + * FFmpeg Constants : ['AVCOL_TRC_BT709', 'BT709'] * + * * + =============================================================================== + >>> colour.MATRIX_COEFFICIENTS_ITUTH273.keys() + dict_keys([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) + >>> description = colour.models.describe_video_signal_matrix_coefficients(1) + =============================================================================== + * * + * Matrix Coefficients: 1 * + * ---------------------- * + * * + * Matrix Coefficients : [ 0.2126 0.0722] * + * FFmpeg Constants : ['AVCOL_SPC_BT709', 'BT709'] * + * * + =============================================================================== + Colour Notation Systems - ``colour.notation`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 243e8e4baf551dbe01c76c42a339540720f60669 Mon Sep 17 00:00:00 2001 From: Thomas Mansencal Date: Tue, 23 Aug 2022 21:14:50 +1200 Subject: [PATCH 6/6] Update various docstrings. --- colour/models/rgb/itut_h_273.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/colour/models/rgb/itut_h_273.py b/colour/models/rgb/itut_h_273.py index 98489454dd..c4a8c0da52 100644 --- a/colour/models/rgb/itut_h_273.py +++ b/colour/models/rgb/itut_h_273.py @@ -3,11 +3,15 @@ =========================================================================== Defines a set of standard video signal colour primaries, transfer functions and -matrix coefficients used in deriving luma and chroma signals: +matrix coefficients used in deriving luma and chroma signals along with +related definitions: - :attr:`colour.COLOUR_PRIMARIES_ITUTH273` - :attr:`colour.TRANSFER_CHARACTERISTICS_ITUTH273` - :attr:`colour.MATRIX_COEFFICIENTS_ITUTH273` +- :attr:`colour.models.describe_video_signal_colour_primaries` +- :attr:`colour.models.describe_video_signal_transfer_characteristics` +- :attr:`colour.models.describe_video_signal_matrix_coefficients` These values were historically defined in :cite:`InternationalOrganizationforStandardization2013` then