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 new file mode 100644 index 0000000000..f9e9882ad7 --- /dev/null +++ b/colour/models/rgb/datasets/ebu_3213_e.py @@ -0,0 +1,84 @@ +""" +EBU Tech. 3213-E Colourspace +============================ + +Defines the *EBU Tech. 3213-E* colourspace: + +- :attr:`colour.models.RGB_COLOURSPACE_EBU_3213_E`. + +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 +""" + +from __future__ import annotations + +import numpy as np + +from colour.hints import NDArray +from colour.models.rgb import ( + RGB_Colourspace, + linear_function, + 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", + "RGB_COLOURSPACE_EBU_3213_E", +] + +PRIMARIES_EBU_3213_E: NDArray = np.array( + [ + [0.64, 0.33], + [0.29, 0.60], + [0.15, 0.06], + ] +) +"""*EBU Tech. 3213-E* colourspace primaries.""" + +WHITEPOINT_NAME_EBU_3213_E: str = "D65" +"""*EBU Tech. 3213-E* colourspace whitepoint name.""" + +CCS_WHITEPOINT_EBU_3213_E: NDArray = np.array([0.313, 0.329]) +"""*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.""" + +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.""" + +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 new file mode 100644 index 0000000000..893c748709 --- /dev/null +++ b/colour/models/rgb/datasets/itut_h_273.py @@ -0,0 +1,214 @@ +""" +Recommendation ITU-T H.273 Colour Primaries (and Colourspaces) +============================================================== + +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:`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 +""" + +from __future__ import annotations + +import numpy as np + +from colour.hints import NDArray +from colour.models.rgb import ( + RGB_Colourspace, + linear_function, + 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_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_H273_GENERIC_FILM: NDArray = np.array( + [ + [0.681, 0.319], # Wratten 25 + [0.243, 0.692], # Wratten 58 + [0.145, 0.049], # Wratten 47 + ] +) +""" +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. + +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. + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +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, +) +RGB_COLOURSPACE_H273_GENERIC_FILM.__doc__ = """ +*Recommendation ITU-T H.273* *Generic Film* (colour filters using Illuminant C) +colourspace. + +References +---------- +:cite:`InternationalTelecommunicationUnion2021` +""" + + +PRIMARIES_H273_22_UNSPECIFIED: NDArray = np.array( + [ + [0.630, 0.340], + [0.295, 0.605], + [0.155, 0.077], + ] +) +""" +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` +""" + +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. + +References +---------- +- :cite:`InternationalTelecommunicationUnion2021` +""" + +MATRIX_XYZ_TO_H273_22_UNSPECIFIED_RGB: NDArray = np.linalg.inv( + MATRIX_H273_22_UNSPECIFIED_RGB_TO_XYZ +) +""" +*CIE XYZ* tristimulus values to row *22* colourspace as given in +*Table 2 - Interpretation of colour primaries (ColourPrimaries) value* matrix. + +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, +) +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..c4a8c0da52 --- /dev/null +++ b/colour/models/rgb/itut_h_273.py @@ -0,0 +1,1306 @@ +""" +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 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 +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 0d96f133ea..66c9435ba6 100644 --- a/colour/models/rgb/transfer_functions/__init__.py +++ b/colour/models/rgb/transfer_functions/__init__.py @@ -57,6 +57,7 @@ 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 .st_2084 import eotf_inverse_ST2084, eotf_ST2084 @@ -125,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", @@ -206,6 +217,10 @@ "oetf_BT709", "oetf_inverse_BT709", ] +__all__ += [ + "oetf_BT1361", + "oetf_inverse_BT1361", +] __all__ += [ "eotf_inverse_BT1886", "eotf_BT1886", @@ -312,6 +327,16 @@ "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( { @@ -628,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, } ) @@ -648,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, @@ -712,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__ = """ @@ -731,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", @@ -794,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, @@ -813,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", @@ -875,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, } @@ -893,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/itur_bt_1361.py b/colour/models/rgb/transfer_functions/itur_bt_1361.py new file mode 100644 index 0000000000..c6ee1a0866 --- /dev/null +++ b/colour/models/rgb/transfer_functions/itur_bt_1361.py @@ -0,0 +1,164 @@ +""" +Recommendation 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 (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, + domain_range_scale, + 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_BT1361", + "oetf_inverse_BT1361", +] + + +def oetf_BT1361(L): + """ + Define *Recommendation ITU-R BT.1361* extended color gamut system + opto-electronic transfer function (OETF). + + Parameters + ---------- + L + Scene *Luminance* :math:`L`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding non-linear primary signal :math:`E'`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+-------------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===================+ + | ``E_p'`` | [0, 1] | [0, 1] | + +------------+-----------------------+-------------------+ + + References + ---------- + :cite:`InternationalTelecommunicationUnion1998` + + Examples + -------- + >>> oetf_BT1361(0.18) # doctest: +ELLIPSIS + 0.4090077288641... + >>> oetf_BT1361(-0.25) # doctest: +ELLIPSIS + -0.25 + >>> oetf_BT1361(1.33) # doctest: +ELLIPSIS + 1.1504846663972... + """ + + 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 *Recommendation ITU-R BT.1361* extended color gamut system inverse + opto-electronic transfer functions (OETF). + + Parameters + ---------- + E_p + 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** | + +============+=======================+===================+ + | ``E_p`` | [0, 1] | [0, 1] | + +------------+-----------------------+-------------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + + References + ---------- + :cite:`InternationalTelecommunicationUnion1998` + + Examples + -------- + >>> oetf_inverse_BT1361(0.4090077288641) # doctest: +ELLIPSIS + 0.1799999... + >>> oetf_inverse_BT1361(-0.25) # doctest: +ELLIPSIS + -0.25 + >>> oetf_inverse_BT1361(1.1504846663972) # doctest: +ELLIPSIS + 1.3299999... + """ + + 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 new file mode 100644 index 0000000000..435e3028ec --- /dev/null +++ b/colour/models/rgb/transfer_functions/itut_h_273.py @@ -0,0 +1,523 @@ +""" +Recommendation ITU-T H.273 Transfer Characteristics +=================================================== + +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:`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, +) + +__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_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_H273_Log(L_c): + """ + Define *Recommendation ITU-T H.273* opto-electronic transfer function + (OETF) for L_ogarithmic encoding (100:1 range). + + Parameters + ---------- + L_c + Scene *Luminance* :math:`L_c`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_c`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain [0.01, np.inf]. + + Examples + -------- + >>> 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 + """ + + L_c = to_domain_1(L_c) + + 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_H273_Log(V): + """ + Define *Recommendation ITU-T H.273* inverse-opto-electronic transfer + function (OETF) for L_ogarithmic encoding (100:1 range). + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene *Luminance* :math:`L_c`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_c`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain + [:func:`colour.models.oetf_H273_Log`(0.01), np.inf]. + + Examples + -------- + >>> 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) + + 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(L_c)) + + +def oetf_H273_LogSqrt(L_c): + """ + Define *Recommendation ITU-T H.273* opto-electronic transfer function + (OETF) for L_ogarithmic encoding (100*Sqrt(10):1 range. + + Parameters + ---------- + L_c + Scene *Luminance* :math:`L_c`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_c`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain + [:func:`colour.models.oetf_H273_LogSqrt`(sqrt(10) / 1000), np.inf]. + + Examples + -------- + >>> oetf_H273_LogSqrt(0.18) # doctest: +ELLIPSIS + 0.702109002041... + >>> oetf_H273_LogSqrt(0.003162277660168) # doctest: +ELLIPSIS + 0.0 + >>> oetf_H273_LogSqrt(0.0001) # doctest: +ELLIPSIS + 0.0 + >>> oetf_H273_LogSqrt(1.0) # doctest: +ELLIPSIS + 1.0 + """ + + L_c = to_domain_1(L_c) + + V = np.where( + 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_H273_LogSqrt(V): + """ + Define *Recommendation ITU-T H.273* inverse-opto-electronic transfer + function (OETF) for L_ogarithmic encoding (100*Sqrt(10):1 range). + + Parameters + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding scene *Luminance* :math:`L_c`. + + Notes + ----- + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_c`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + :cite:`InternationalTelecommunicationUnion2021` + + Warnings + -------- + - The function is clamped to domain [sqrt(10) / 1000, np.inf]. + + Examples + -------- + >>> 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) + + 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(L_c)) + + +def oetf_H273_IEC61966_2(L_c): + """ + 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 + ---------- + L_c + Scene *Luminance* :math:`L_c`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + Corresponding electrical signal :math:`V`. + + 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** | + +============+=======================+===============+ + | ``L_c`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Range** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`InternationalTelecommunicationUnion2021` + + Examples + -------- + >>> oetf_H273_IEC61966_2(0.18) # doctest: +ELLIPSIS + 0.4613561295004... + >>> oetf_H273_IEC61966_2(-0.18) # doctest: +ELLIPSIS + -0.4613561295004... + """ + + V = np.where( + as_float_array(L_c) >= 0, + eotf_inverse_sRGB(L_c), + -eotf_inverse_sRGB(-L_c), + ) + + return as_float(V) + + +def oetf_inverse_H273_IEC61966_2(V): + """ + 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 + ---------- + V + Electrical signal :math:`V`. + + Returns + ------- + :class:`numpy.floating` or :class:`numpy.ndarray` + 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** | + +============+=======================+===============+ + | ``V`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + +------------+-----------------------+---------------+ + | **Domain** | **Scale - Reference** | **Scale - 1** | + +============+=======================+===============+ + | ``L_c`` | [0, 1] | [0, 1] | + +------------+-----------------------+---------------+ + + References + ---------- + - :cite:`InternationalTelecommunicationUnion2021` + + Examples + -------- + >>> oetf_inverse_H273_IEC61966_2(0.461356129500) # doctest: +ELLIPSIS + 0.1799999999... + >>> oetf_inverse_H273_IEC61966_2(-0.461356129500) # doctest: +ELLIPSIS + -0.1799999999... + """ + + L_c = np.where( + as_float_array(V) >= 0, + eotf_sRGB(V), + -eotf_sRGB(-V), + ) + + 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/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/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`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~