Skip to content

Colour 0.3.14

Compare
Choose a tag to compare
@KelSolaar KelSolaar released this 26 Oct 10:06
· 2169 commits to develop since this release

Colour 0.3.14 - Alpha Milestone

We would like to thanks all the contributors as usual!

With this release we are getting close to have a beta candidate in the coming months. It will likely be the last version to support Python 2.x.

NumFOCUS

Colour is now a NumFOCUS affiliated project:

image

Hacktoberfest - 2019

We had a few new contributors for the 2019 edition of the Hacktoberfest. Thanks to @Chinmayrane16, @evalevanto, @feralpoosum, @BPearlstine and, @pavithraes for their contributions!

Automatic Colour Conversion Graph

Colour now implements an automatic colour conversion graph based on NetworkX and enabling easier colour conversions:

>>> sd = colour.COLOURCHECKERS_SDS['ColorChecker N Ohta']['dark skin']
>>> convert(sd, 'Spectral Distribution', 'sRGB', verbose={'mode': 'Short'})

Image Input and Output

Imageio is now a requirement for reading and writing images, it will be used if OpenImageIO is not available. If you wish to read OpenEXR files or develop Colour, you will need to install the FreeImage plugin as follows:

$ python -c "import imageio;imageio.plugins.freeimage.download()"

Support for OpenImageIO 2.x has also been implemented.

Name and Signature Changes

Various colour component transfer functions objects have been either renamed or their signature changed, most notably the sRGB transfer functions and the colour.oetf definition.

All the reverse words have been replaced with inverse in object names, file names and, docstrings.

Coverage

Coverage was raised to 100%. It does not mean that all the possible code paths are covered but it certainly strengthen the API.

Dependency Management

We have adopted Poetry to manage the development dependencies, the setup.py file has been replaced with a standardized pyproject.toml file.

Continuous Integration

Travis-ci and Azure Pipelines have been replaced with Github Actions.

Documentation

The README and the Manual have been slightly reorganised to create a better separation between the tutorials, API reference and, the new How-To Guide.

Features

colour.colorimetry

  • Add colour.sds_and_multi_sds_to_sds definition that converts given spectral and multi-spectral distributions to a flat list of spectral distributions. (@KelSolaar)
  • Implement support for ICC D50 illuminant computed from the following CIE XYZ tristimulus values [96.42, 100.00, 82.49]. (@KelSolaar)
  • Add colour.colorimetry.multi_sds_to_XYZ_ASTME308 definition that converts given multi-spectral distributions to CIE XYZ tristimulus values according to to practise ASTM E308-15 method. (@KelSolaar)
  • Implement support for ICC D50 illuminant computed from the following CIE XYZ tristimulus values [96.42, 100.00, 82.49]. (@KelSolaar)

colour.corresponding

  • colour.corresponding_chromaticities_prediction definition can now use a colour.CorrespondingColourDataset class instance as argument. (@KelSolaar)

colour.io

  • The colour.read_image and colour.write_image definitions support Imageio and will fallback to it if OpenImageIO is not available.
  • OpenImageIO 2.x is now supported.

colour.graph

  • The new colour.convert definition leverages an automatic colour conversion graph enabling easier colour conversions:
>>> sd = colour.COLOURCHECKERS_SDS['ColorChecker N Ohta']['dark skin']
>>> convert(sd, 'Spectral Distribution', 'sRGB', verbose={'mode': 'Short'})
===============================================================================
*                                                                             *
*   [ Conversion Path ]                                                       *
*                                                                             *
*   "sd_to_XYZ" --> "XYZ_to_sRGB"                                             *
*                                                                             *
===============================================================================
array([ 0.45675795,  0.30986982,  0.24861924])
>>> illuminant = colour.ILLUMINANTS_SDS['FL2']
>>> convert(sd, 'Spectral Distribution', 'sRGB', sd_to_XYZ={'illuminant': illuminant})
array([ 0.47924575,  0.31676968,  0.17362725])

image

colour.models

  • Implement support for Recommendation ITU-R BT.2100-2 with the modified black lift handling of HLG EOTF. (@KelSolaar, @nick-shaw)
  • Implement support for Fujifilm F-Gamut RGB colourspace with colour.models.F_GAMUT_COLOURSPACE class and Fujifilm F-Log with colour.models.log_encoding_FLog and colour.models.log_decoding_FLog transfer functions. (@sobotka, @KelSolaar, @nick-shaw)
  • Re-implement support for SMPTE C RGB colourspace with colour.models.SMPTE_C_COLOURSPACE class and related NTSC (1987) RGB colourspace with colour.models.NTSC_1987_COLOURSPACE class. (@KelSolaar)

colour.plotting

  • Add colour.plotting.plot_constant_hue_loci definition plotting Constant Hue Loci as given by Hung and Berns (1995) or Ebner and Fairchild (1998). It is intended to be used with Colour - Datasets as follows:
from colour_datasets import load
from colour.plotting import plot_constant_hue_loci

plot_constant_hue_loci(load('3362536'), 'IPT')

image

colour.temperature

  • Add various optimization based correlated colour temperature computation definitions: (@KelSolaar)
    • colour.temperature.xy_to_CCT_CIE_D
    • colour.temperature.CCT_to_xy_Hernandez1999, this definition is not a bijective function and might produce unexpected results. It is given for consistency with other correlated colour temperature computation methods but should be avoided for practical applications.
    • colour.temperature.xy_to_CCT_Kang2002
    • colour.temperature.uv_to_CCT_Krystek1985
    • colour.temperature.CCT_to_xy_McCamy1992, this definition is not a bijective function and might produce unexpected results. It is given for consistency with other correlated colour temperature computation methods but should be avoided for practical applications.

Fixes

colour.quality

  • The individual colour scales returned by colour.colour_quality_scale definition when using the additional_data argument were incorrectly scaled and have been fixed. (@KelSolaar)

Changes

colour.adaptation

  • colour.adaptation.chromatic_adaptation_reverse_CMCCAT2000: (@KelSolaar)
    • Name: chromatic_adaptation_inverse_CMCCAT2000

colour.appearance

  • yield based tests dependent on nosetests have been replaced. (@MichaelMauderer)

colour.characterisation

  • The following colour checkers now use ICC D50 illuminant instead of D50: (@KelSolaar)
    • ColorChecker 2005
    • BabelColor Average
    • ColorChecker24 - Before November 2014
    • ColorChecker24 - After November 2014

colour.colorimetry

  • colour.ASTME30815_PRACTISE_SHAPE: (@KelSolaar)
    • Name: ASTME308_PRACTISE_SHAPE
  • colour.MultiSpectralDistribution: (@KelSolaar)
    • Name: MultiSpectralDistributions
  • colour.multi_sds_to_XYZ: (@KelSolaar)
    • Signature: multi_sds_to_XYZ(msds, cmfs=STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy().trim(DEFAULT_SPECTRAL_SHAPE), illuminant=sd_ones(), k=None, method='ASTM E308-15', **kwargs)
  • colour.colorimetry.multi_sds_to_XYZ_integration: (@KelSolaar)
    • Signature: multi_sds_to_XYZ_integration(msds, cmfs=STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer']. copy().trim(DEFAULT_SPECTRAL_SHAPE), illuminant=sd_ones(), k=None, shape=DEFAULT_SPECTRAL_SHAPE)
  • colour.colorimetry.adjust_tristimulus_weighting_factors_ASTME30815: (@KelSolaar)
    • Name: adjust_tristimulus_weighting_factors_ASTME308
  • colour.colorimetry.lagrange_coefficients_ASTME202211: (@KelSolaar)
    • Name: lagrange_coefficients_ASTME2022
  • colour.colorimetry.luminance_ASTMD153508: (@KelSolaar)
    • Name: luminance_ASTMD1535
  • colour.colorimetry.sd_to_XYZ_ASTME30815: (@KelSolaar)
    • Name: sd_to_XYZ_ASTME308
  • colour.colorimetry.sd_to_XYZ_tristimulus_weighting_factors_ASTME30815: (@KelSolaar)
    • Name: sd_to_XYZ_tristimulus_weighting_factors_ASTME308
  • colour.colorimetry.tristimulus_weighting_factors_ASTME202211: (@KelSolaar)
    • Name: tristimulus_weighting_factors_ASTME2022

colour.continuous

  • colour.continuous.MultiSignal: (@KelSolaar)
    • Name: MultiSignals

colour.io

  • colour.read_image: (@KelSolaar)
    • Signature: read_image(path, method='OpenImageIO', **kwargs)
  • colour.write_image: (@KelSolaar)
    • Signature: write_image(image, path, method='OpenImageIO', **kwargs)

colour.models

  • Various CCTF related objects, signatures and properties have been renamed for consistency purposes:
  • colour.ENCODING_CCTFS: (@KelSolaar)
    • Name: CCTF_ENCODINGS
  • colour.encoding_cctf: (@KelSolaar)
    • Name: cctf_encoding
  • colour.DECODING_CCTFS: (@KelSolaar)
    • Name: CCTF_DECODINGS
  • colour.decoding_cctf: (@KelSolaar)
    • Name: cctf_decoding
  • colour.RGB_Colourspace.encoding_cctf: (@KelSolaar)
    • Name: cctf_encoding
  • colour.RGB_Colourspace.decoding_cctf: (@KelSolaar)
    • Name: decoding_cctf
  • colour.XYZ_to_RGB: (@KelSolaar)
    • Signature: XYZ_to_RGB(XYZ, illuminant_XYZ, illuminant_RGB, XYZ_to_RGB_matrix, chromatic_adaptation_transform='CAT02', cctf_encoding=None, **kwargs)
  • colour.XYZ_to_RGB: (@KelSolaar)
    • Signature: RGB_to_XYZ(RGB, illuminant_RGB, illuminant_XYZ, RGB_to_XYZ_matrix, chromatic_adaptation_transform='CAT02', cctf_decoding=None, **kwargs)
  • colour.XYZ_to_sRGB: (@KelSolaar)
    • Signature: XYZ_to_sRGB(XYZ, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'], chromatic_adaptation_transform='CAT02', apply_cctf_encoding=True, **kwargs)
  • colour.XYZ_to_sRGB: (@KelSolaar)
    • Signature: sRGB_to_XYZ(RGB, illuminant=ILLUMINANTS['CIE 1931 2 Degree Standard Observer']['D65'], chromatic_adaptation_method='CAT02', apply_cctf_decoding=True, **kwargs)

The colour.RGB_to_RGB definition now accepts keyword arguments, they are filtered and passed accordingly to the decoding and encoding colour component transfer functions:

  • colour.RGB_to_RGB: (@KelSolaar)

    • Signature: RGB_to_RGB(RGB, input_colourspace, output_colourspace, chromatic_adaptation_transform='CAT02', apply_decoding_cctf=False, apply_encoding_cctf=False, **kwargs)
  • Various log related objects and signatures have been renamed for consistency purposes:

  • colour.log_decoding_curve: (@KelSolaar)

    • Name: colour.log_decoding
    • Signature: log_decoding(value, function='Cineon', **kwargs)
  • colour.LOG_DECODING_CURVES: (@KelSolaar)

    • Name: colour.LOG_DECODINGS
  • colour.log_encoding_curve: (@KelSolaar)

    • Name: colour.log_encoding
    • Signature: log_encoding(value, function='Cineon', **kwargs)
  • colour.LOG_ENCODING_CURVES: (@KelSolaar)

    • Name: colour.LOG_ENCODINGS

The IEC 61966-2-1:1999 standard does not actually define an OETF but and EOTF so the sRGB related definitions have been renamed accordingly:

  • colour.models.oetf_sRGB: (@KelSolaar)
    • Name: eotf_inverse_sRGB
  • colour.models.oetf_reverse_sRGB: (@KelSolaar)
    • Name: eotf_sRGB

Various other colour component transfer functions objects have been either renamed or their signature changed:

  • colour.eotf: (@KelSolaar)

    • Signature: eotf(value, function='ITU-R BT.1886', **kwargs)
  • colour.EOTFS_REVERSE: (@KelSolaar)

    • Name: EOTF_INVERSES
  • colour.eotf_reverse: (@KelSolaar)

    • Signature: eotf_inverse(value, function='ITU-R BT.1886', **kwargs)
  • colour.oetf: (@KelSolaar)

    • Signature: oetf(value, function='ITU-R BT.709', **kwargs)
  • colour.OETFS_REVERSE: (@KelSolaar)

    • Name: OETF_INVERSES
  • colour.oetf_reverse: (@KelSolaar)

    • Signature: oetf_inverse(value, function='ITU-R BT.709', **kwargs)
  • colour.OOTFS_REVERSE: (@KelSolaar)

    • Name: OOTF_INVERSES
  • colour.models.oetf_DICOMGSDF: (@KelSolaar)

    • Name: eotf_inverse_DICOMGSDF
  • colour.models.eotf_reverse_BT1886: (@KelSolaar)

    • Name: eotf_inverse_BT1886
  • colour.models.eotf_reverse_DCDM: (@KelSolaar)

    • Name: eotf_inverse_DCDM
  • colour.models.oetf_ST2084: (@KelSolaar)

    • Name: eotf_inverse_ST2084
  • colour.models.oetf_reverse_ARIBSTDB67: (@KelSolaar)

    • Name: oetf_inverse_ARIBSTDB67
  • colour.models.oetf_reverse_BT601: (@KelSolaar)

    • Name: oetf_inverse_BT601
  • colour.models.oetf_reverse_BT709: (@KelSolaar)

    • Name: oetf_inverse_BT709
  • colour.models.oetf_BT2100_HLG: (@KelSolaar, @nick-shaw)

    • Name: oetf_HLG_BT2100
    • Signature: oetf_HLG_BT2100(E, constants=BT2100_HLG_CONSTANTS)
  • colour.models.oetf_reverse_BT2100_HLG: (@KelSolaar, @nick-shaw)

    • Name: oetf_inverse_HLG_BT2100
    • Signature: oetf_inverse_HLG_BT2100(E_p, constants=BT2100_HLG_CONSTANTS)
  • colour.models.eotf_BT2100_HLG: (@KelSolaar, @nick-shaw)

    • Name: eotf_HLG_BT2100
    • Signature: eotf_HLG_BT2100(E_p, L_B=0, L_W=1000, gamma=None, constants=BT2100_HLG_CONSTANTS, method='ITU-R BT.2100-2')
  • colour.models.eotf_reverse_BT2100_HLG: (@KelSolaar, @nick-shaw)

    • Name: eotf_inverse_HLG_BT2100
    • Signature: eotf_inverse_HLG_BT2100(F_D, L_B=0, L_W=1000, gamma=None, constants=BT2100_HLG_CONSTANTS, method='ITU-R BT.2100-2')
  • colour.models.ootf_BT2100_HLG: (@KelSolaar, @nick-shaw)

    • Name: ootf_HLG_BT2100
    • Signature: ootf_HLG_BT2100(E, L_B=0, L_W=1000, gamma=None, method='ITU-R BT.2100-2')
  • colour.models.ootf_reverse_BT2100_HLG: (@KelSolaar, @nick-shaw)

    • Name: ootf_inverse_HLG_BT2100
    • Signature: ootf_inverse_HLG_BT2100(F_D, L_B=0, gamma=None, method='ITU-R BT.2100-2')
  • colour.models.oetf_BT2100_PQ: (@KelSolaar, @nick-shaw)

    • Name: oetf_PQ_BT2100
  • colour.models.oetf_reverse_BT2100_PQ: (@KelSolaar, @nick-shaw)

    • Name: oetf_inverse_PQ_BT2100
  • colour.models.eotf_BT2100_PQ: (@KelSolaar, @nick-shaw)

    • Name: eotf_PQ_BT2100
  • colour.models.eotf_reverse_BT2100_PQ: (@KelSolaar, @nick-shaw)

    • Name: eotf_inverse_PQ_BT2100
  • colour.models.ootf_BT2100_PQ: (@KelSolaar, @nick-shaw)

    • Name: ootf_PQ_BT2100
  • colour.models.ootf_reverse_BT2100_PQ: (@KelSolaar, @nick-shaw)

    • Name: ootf_inverse_PQ_BT2100
  • colour.models.log_encoding_Log3G10: (@KelSolaar)

    • Signature: log_encoding_Log3G10(x, method='v2', **kwargs)
  • colour.models.log_decoding_Log3G10: (@KelSolaar)

    • Signature: log_decoding_Log3G10(y, method='v2', **kwargs)
  • colour.models.log_encoding_CanonLog: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_CanonLog(x, bit_depth=10, out_normalised_code_value=True, in_reflection=True, **kwargs)
  • colour.models.log_decoding_CanonLog: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_CanonLog(clog, bit_depth=10, in_normalised_code_value=True, out_reflection=True, **kwargs)
  • colour.models.log_encoding_CanonLog2: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_CanonLog2(x, bit_depth=10, out_normalised_code_value=True, in_reflection=True, **kwargs)
  • colour.models.log_decoding_CanonLog2: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_CanonLog2(clog2, bit_depth=10, in_normalised_code_value=True, out_reflection=True, **kwargs)
  • colour.models.log_encoding_CanonLog3: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_CanonLog3(x, bit_depth=10, out_normalised_code_value=True, in_reflection=True, **kwargs)
  • colour.models.log_decoding_CanonLog3: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_CanonLog3(clog3, bit_depth=10, in_normalised_code_value=True, out_reflection=True, **kwargs)
  • colour.models.log_encoding_VLog: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_VLog(L_in, bit_depth=10, out_normalised_code_value=True, in_reflection=True, constants=VLOG_CONSTANTS, **kwargs)
  • colour.models.log_decoding_VLog: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_VLog(V_out, bit_depth=10, in_normalised_code_value=True, out_reflection=True, constants=VLOG_CONSTANTS, **kwargs)
  • colour.models.log_encoding_SLog: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_SLog(x, bit_depth=10, out_normalised_code_value=True, in_reflection=True, **kwargs)
  • colour.models.log_decoding_SLog: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_SLog(y, bit_depth=10, in_normalised_code_value=True, out_reflection=True, **kwargs)
  • colour.models.log_encoding_SLog2: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_SLog2(x, bit_depth=10, out_normalised_code_value=True, in_reflection=True, **kwargs)
  • colour.models.log_decoding_SLog2: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_SLog2(y, bit_depth=10, in_normalised_code_value=True, out_reflection=True, **kwargs)
  • colour.models.log_encoding_SLog3: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_encoding_SLog3(x, bit_depth=10, out_normalised_code_value=True, in_reflection=True, **kwargs)
  • colour.models.log_decoding_SLog3: (@KelSolaar, @nick-shaw, @KevinJW)

    • Signature: log_decoding_SLog3(y, bit_depth=10, in_normalised_code_value=True, out_reflection=True, **kwargs)
  • colour.models.oetf_ROMMRGB: (@KelSolaar)

    • Name: cctf_encoding_ROMMRGB
  • colour.models.eotf_ROMMRGB: (@KelSolaar)

    • Name: cctf_decoding_ROMMRGB
  • colour.models.oetf_ProPhotoRGB: (@KelSolaar)

    • Name: cctf_encoding_ProPhotoRGB
  • colour.models.eotf_ProPhotoRGB: (@KelSolaar)

    • Name: cctf_decoding_ProPhotoRGB
  • colour.models.oetf_RIMMRGB: (@KelSolaar)

    • Name: cctf_encoding_RIMMRGB
  • colour.models.eotf_RIMMRGB: (@KelSolaar)

    • Name: cctf_decoding_RIMMRGB
  • colour.models.XYZ_to_colourspace_model: (@feralpoosum)

    • Deprecated
  • colour.models.NTSC_COLOURSPACE: (@KelSolaar)

    • Name: NTSC_1953_COLOURSPACE

colour.notation

  • colour.notation.munsell_value_ASTMD153508: (@KelSolaar)
    • Name: munsell_value_ASTMD1535

colour.plotting

  • colour.plotting.ASTM_G_173_DIRECT_CIRCUMSOLAR: (@KelSolaar)
    • Name: ASTMG173_DIRECT_CIRCUMSOLAR
  • colour.plotting.ASTM_G_173_ETR: (@KelSolaar)
    • Name: ASTMG173_ETR
  • colour.plotting.ASTM_G_173_GLOBAL_TILT: (@KelSolaar)
    • Name: ASTMG173_GLOBAL_TILT
  • colour.plotting.plot_single_sd_colour_quality_scale_bars: (@KelSolaar)
    • Signature: plot_single_sd_colour_quality_scale_bars(sd, method='NIST CQS 9.0', **kwargs)
  • colour.plotting.plot_multi_sds_colour_quality_scales_bars: (@KelSolaar)
    • Signature: plot_multi_sds_colour_quality_scales_bars(sds, method='NIST CQS 9.0', **kwargs)
  • colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1931: (@KelSolaar)
    • Signature: plot_planckian_locus_in_chromaticity_diagram_CIE1931(illuminants=None, annotate_parameters=None, chromaticity_diagram_callable_CIE1931=plot_chromaticity_diagram_CIE1931, planckian_locus_callable_CIE1931=plot_planckian_locus_CIE1931, **kwargs)
  • colour.plotting.plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS: (@KelSolaar)
    • Signature: plot_planckian_locus_in_chromaticity_diagram_CIE1960UCS(illuminants=None, annotate_parameters=None, chromaticity_diagram_callable_CIE1960UCS=plot_chromaticity_diagram_CIE1960UCS, planckian_locus_callable_CIE1960UCS=plot_planckian_locus_CIE1960UCS, **kwargs)

colour.recovery

  • colour.recovery.XYZ_to_sd_Meng2015: (@KelSolaar)
    • Signature: XYZ_to_sd_Meng2015(XYZ, cmfs=STANDARD_OBSERVERS_CMFS['CIE 1931 2 Degree Standard Observer'].copy().align(DEFAULT_SPECTRAL_SHAPE_MENG_2015), illuminant=sd_ones(DEFAULT_SPECTRAL_SHAPE_MENG_2015), optimisation_parameters=None)

colour.temperature

  • colour.xy_to_CCT: (@KelSolaar)
    • Signature: xy_to_CCT(xy, method='CIE Illuminant D Series')
  • colour.CCT_to_xy: (@KelSolaar)
    • Signature: CCT_to_xy(CCT, method='CIE Illuminant D Series')