Ejemplo n.º 1
0
def read_LUT_UnorderedSonySPI3D(path):
    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 0, 0]), np.array([1, 1, 1])
    size = 2
    indexes = []
    table = []
    comments = []
    with open(path) as spi3d_file:
        lines = filter(None, (line.strip() for line in spi3d_file.readlines()))
        for line in lines:
            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue
            tokens = line.split()
            if len(tokens) == 3:
                assert len(set(tokens)) == 1, (
                    'Non-uniform "LUT" shape is unsupported!')
                size = DEFAULT_INT_DTYPE(tokens[0])
            if len(tokens) == 6:
                indexes.append(as_int_array(tokens[:3]))
                table.append(as_float_array(tokens[3:]))
    indexes = as_int_array(indexes)
    sorting_indexes = np.lexsort((indexes[:, 2], indexes[:, 1], indexes[:, 0]))
    #print(sorting_indexes)
    assert np.array_equal(
        indexes[sorting_indexes],
        DEFAULT_INT_DTYPE(np.around(
            LUT3D.linear_table(size) * (size - 1))).reshape(
                (-1, 3))), 'Indexes do not match expected "LUT3D" indexes!'
    table = as_float_array(table)[sorting_indexes].reshape(
        [size, size, size, 3])
    return LUT3D(table,
                 title,
                 np.vstack([domain_min, domain_max]),
                 comments=comments)
Ejemplo n.º 2
0
    def test_path_to_title(self):
        """Test :func:`colour.io.luts.common.path_to_title` definition."""

        self.assertEqual(
            path_to_title(
                "colour/io/luts/tests/resources/cinespace/RGB_1_0.5_0.25.csp"),
            "RGB 1 0 5 0 25",
        )
Ejemplo n.º 3
0
    def test_path_to_title(self):
        """
        Tests :func:`colour.io.luts.common.path_to_title` definition.
        """

        self.assertEqual(
            path_to_title(
                'colour/io/luts/tests/resources/cinespace/RGB_1_0.5_0.25.csp'),
            'RGB 1 0 5 0 25')
Ejemplo n.º 4
0
def read_unordered_LUT_SonySPI3D(path):
    """
    Reads given unordered *.spi3d* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3D or LUT3x1D
        :class:`LUT3D` or :class:`LUT3x1D` class instance.
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 0, 0]), np.array([1, 1, 1])
    indexes = []
    comments = []
    table_unordered = []
    table_ordered = []

    with open(path) as spi3d_file:
        lines = filter(None, (line.strip() for line in spi3d_file.readlines()))
        for line in lines:
            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if len(tokens) == 3:
                size = DEFAULT_INT_DTYPE(tokens[0])

            if len(tokens) == 6:
                indexes.append(as_int_array(tokens[:3]))
                table_unordered.append(as_float_array(tokens[3:]))

    test_indexes = np.around(LUT3D.linear_table(size) * (size - 1)).reshape(
        (-1, 3))
    for i in range(64):
        for j in range(64):
            if (np.array_equal(test_indexes[i], indexes[j])):
                table_ordered.append(table_unordered[j])

    table_ordered = as_float_array(table_ordered).reshape(
        [size, size, size, 3])

    return LUT3D(table_ordered,
                 title,
                 np.vstack([domain_min, domain_max]),
                 comments=comments)
Ejemplo n.º 5
0
def read_LUT_SonySPImtx(path: str) -> LUTOperatorMatrix:
    """
    Read given *Sony* *.spimtx* *LUT* file.

    Parameters
    ----------
    path
        *LUT* path.

    Returns
    -------
    :class:`colour.LUTOperatorMatrix`
        :class:`colour.io.Matrix` class instance.

    Examples
    --------
    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spimtx',
    ...     'dt.spimtx')
    >>> print(read_LUT_SonySPImtx(path))
    LUTOperatorMatrix - dt
    ----------------------
    <BLANKLINE>
    Matrix     : [[ 0.864274  0.        0.        0.      ]
                  [ 0.        0.864274  0.        0.      ]
                  [ 0.        0.        0.864274  0.      ]
                  [ 0.        0.        0.        1.      ]]
    Offset     : [ 0.  0.  0.  0.]
    """

    matrix = np.loadtxt(path, dtype=DEFAULT_FLOAT_DTYPE)
    matrix = np.reshape(matrix, (3, 4))
    offset = matrix[:, 3] / 65535
    matrix = matrix[:3, :3]

    title = path_to_title(path)

    return LUTOperatorMatrix(matrix, offset, name=title)
Ejemplo n.º 6
0
def read_LUT_IridasCube(path):
    """
    Reads given *Iridas* *.cube* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3x1D or LUT3d
        :class:`LUT3x1D` or :class:`LUT3D` class instance.

    References
    ----------
    :cite:`AdobeSystems2013b`

    Examples
    --------
    Reading a 3x1D *Iridas* *.cube* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'iridas_cube',
    ...     'ACES_Proxy_10_to_ACES.cube')
    >>> print(read_LUT_IridasCube(path))
    LUT3x1D - ACES Proxy 10 to ACES
    -------------------------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (32, 3)

    Reading a 3D *Iridas* *.cube* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'iridas_cube',
    ...     'ColourCorrect.cube')
    >>> print(read_LUT_IridasCube(path))
    LUT3D - Generated by Foundry::LUT
    ---------------------------------
    <BLANKLINE>
    Dimensions : 3
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (4, 4, 4, 3)

    Reading a 3D *Iridas* *.cube* *LUT* with comments:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'iridas_cube',
    ...     'Demo.cube')
    >>> print(read_LUT_IridasCube(path))
    LUT3x1D - Demo
    --------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 1.  2.  3.]]
    Size       : (3, 3)
    Comment 01 : Comments can go anywhere
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 0, 0]), np.array([1, 1, 1])
    dimensions = 3
    size = 2
    table = []
    comments = []

    with open(path) as cube_file:
        lines = cube_file.readlines()
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if tokens[0] == 'TITLE':
                title = ' '.join(tokens[1:])[1:-1]
            elif tokens[0] == 'DOMAIN_MIN':
                domain_min = parse_array(tokens[1:])
            elif tokens[0] == 'DOMAIN_MAX':
                domain_max = parse_array(tokens[1:])
            elif tokens[0] == 'LUT_1D_SIZE':
                dimensions = 2
                size = DEFAULT_INT_DTYPE(tokens[1])
            elif tokens[0] == 'LUT_3D_SIZE':
                dimensions = 3
                size = DEFAULT_INT_DTYPE(tokens[1])
            else:
                table.append(parse_array(tokens))

    table = as_float_array(table)
    if dimensions == 2:
        return LUT3x1D(table,
                       title,
                       np.vstack([domain_min, domain_max]),
                       comments=comments)
    elif dimensions == 3:
        # The lines of table data shall be in ascending index order,
        # with the first component index (Red) changing most rapidly,
        # and the last component index (Blue) changing least rapidly.
        table = table.reshape([size, size, size, 3], order='F')

        return LUT3D(table,
                     title,
                     np.vstack([domain_min, domain_max]),
                     comments=comments)
Ejemplo n.º 7
0
def read_LUT_SonySPI3D(path):
    """
    Reads given *Sony* *.spi3d* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3D or LUT3x1D
        :class:`LUT3D` or :class:`LUT3x1D` class instance.

    Examples
    --------
    Reading a 3D *Sony* *.spi3d* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spi3d',
    ...     'ColourCorrect.spi3d')
    >>> print(read_LUT_SonySPI3D(path))
    LUT3D - ColourCorrect
    ---------------------
    <BLANKLINE>
    Dimensions : 3
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (4, 4, 4, 3)
    Comment 01 : Adapted from a LUT generated by Foundry::LUT.
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 0, 0]), np.array([1, 1, 1])
    size = 2
    indexes = []
    table = []
    comments = []

    with open(path) as spi3d_file:
        lines = spi3d_file.readlines()
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if len(tokens) == 3:
                assert len(set(tokens)) == 1, (
                    'Non-uniform "LUT" shape is unsupported!')

                size = DEFAULT_INT_DTYPE(tokens[0])
            if len(tokens) == 6:
                indexes.append(parse_array(tokens[:3]))
                table.append(parse_array(tokens[3:]))

    assert np.array_equal(
        indexes,
        DEFAULT_INT_DTYPE(LUT3D.linear_table(size) * (size - 1)).reshape(
            (-1, 3))), 'Indexes do not match expected "LUT3D" indexes!'

    table = as_float_array(table).reshape([size, size, size, 3])

    return LUT3D(table,
                 title,
                 np.vstack([domain_min, domain_max]),
                 comments=comments)
Ejemplo n.º 8
0
def read_LUT_ResolveCube(path):
    """
    Reads given *Resolve* *.cube* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3x1D or LUT3D or LUTSequence
        :class:`LUT3x1D` or :class:`LUT3D` or :class:`LUTSequence` class
        instance.

    References
    ----------
    :cite:`Chamberlain2015`

    Examples
    --------
    Reading a 3x1D *Resolve* *.cube* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'ACES_Proxy_10_to_ACES.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT3x1D - ACES Proxy 10 to ACES
    -------------------------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (32, 3)

    Reading a 3D *Resolve* *.cube* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'Colour_Correct.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT3D - Generated by Foundry::LUT
    ---------------------------------
    <BLANKLINE>
    Dimensions : 3
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (4, 4, 4, 3)

    Reading a 3D *Resolve* *.cube* *LUT* with comments:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'Demo.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT3x1D - Demo
    --------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 3.  3.  3.]]
    Size       : (3, 3)
    Comment 01 : Comments can't go anywhere

    Reading a 3x1D + 3D *Resolve* *.cube* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'Three_Dimensional_Table_With_Shaper.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT Sequence
    ------------
    <BLANKLINE>
    Overview
    <BLANKLINE>
        LUT3x1D ---> LUT3D
    <BLANKLINE>
    Operations
    <BLANKLINE>
        LUT3x1D - LUT3D with My Shaper - Shaper
        ---------------------------------------
    <BLANKLINE>
        Dimensions : 2
        Domain     : [[-0.1 -0.1 -0.1]
                      [ 3.   3.   3. ]]
        Size       : (10, 3)
    <BLANKLINE>
        LUT3D - LUT3D with My Shaper - Cube
        -----------------------------------
    <BLANKLINE>
        Dimensions : 3
        Domain     : [[-0.1 -0.1 -0.1]
                      [ 3.   3.   3. ]]
        Size       : (3, 3, 3, 3)
        Comment 01 : A first "Shaper" comment.
        Comment 02 : A second "Shaper" comment.
        Comment 03 : A first "LUT3D" comment.
        Comment 04 : A second "LUT3D" comment.
    """

    title = path_to_title(path)
    size_3x1D = size_3D = 2
    table = []
    comments = []
    has_3x1D, has_3D = False, False

    with open(path) as cube_file:
        lines = cube_file.readlines()
        LUT = LUTSequence(LUT3x1D(), LUT3D())
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if tokens[0] == 'TITLE':
                title = ' '.join(tokens[1:])[1:-1]
            elif tokens[0] == 'LUT_1D_INPUT_RANGE':
                domain = parse_array(tokens[1:])
                LUT[0].domain = tstack([domain, domain, domain])
            elif tokens[0] == 'LUT_3D_INPUT_RANGE':
                domain = parse_array(tokens[1:])
                LUT[1].domain = tstack([domain, domain, domain])
            elif tokens[0] == 'LUT_1D_SIZE':
                has_3x1D = True
                size_3x1D = np.int_(tokens[1])
            elif tokens[0] == 'LUT_3D_SIZE':
                has_3D = True
                size_3D = np.int_(tokens[1])
            else:
                table.append(parse_array(tokens))

    table = as_float_array(table)
    if has_3x1D and has_3D:
        LUT[0].name = '{0} - Shaper'.format(title)
        LUT[1].name = '{0} - Cube'.format(title)
        LUT[1].comments = comments
        LUT[0].table = table[:size_3x1D]
        # The lines of table data shall be in ascending index order,
        # with the first component index (Red) changing most rapidly,
        # and the last component index (Blue) changing least rapidly.
        LUT[1].table = table[size_3x1D:].reshape(
            (size_3D, size_3D, size_3D, 3), order='F')
        return LUT
    elif has_3x1D:
        LUT[0].name = title
        LUT[0].comments = comments
        LUT[0].table = table
        return LUT[0]
    elif has_3D:
        LUT[1].name = title
        LUT[1].comments = comments
        # The lines of table data shall be in ascending index order,
        # with the first component index (Red) changing most rapidly,
        # and the last component index (Blue) changing least rapidly.
        table = table.reshape([size_3D, size_3D, size_3D, 3], order='F')
        LUT[1].table = table
        return LUT[1]
Ejemplo n.º 9
0
def read_LUT_ResolveCube(path):
    """
    Reads given *Resolve* *.cube* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3x1D or LUT3D or LUTSequence
        :class:`LUT3x1D` or :class:`LUT3D` or :class:`LUTSequence` class
        instance.

    References
    ----------
    :cite:`Chamberlain2015`

    Examples
    --------
    Reading a 3x1D *Resolve* *.cube* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'ACES_Proxy_10_to_ACES.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT3x1D - ACES Proxy 10 to ACES
    -------------------------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (32, 3)

    Reading a 3D *Resolve* *.cube* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'ColourCorrect.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT3D - Generated by Foundry::LUT
    ---------------------------------
    <BLANKLINE>
    Dimensions : 3
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (4, 4, 4, 3)

    Reading a 3D *Resolve* *.cube* *LUT* with comments:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'resolve_cube',
    ...     'Demo.cube')
    >>> print(read_LUT_ResolveCube(path))
    LUT3x1D - Demo
    --------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 3.  3.  3.]]
    Size       : (3, 3)
    Comment 01 : Comments can't go anywhere
    """

    title = path_to_title(path)
    size_3x1D = size_3D = 2
    table = []
    comments = []
    has_3x1D, has_3D = False, False

    with open(path) as cube_file:
        lines = cube_file.readlines()
        LUT = LUTSequence(LUT3x1D(), LUT3D())
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if tokens[0] == 'TITLE':
                title = ' '.join(tokens[1:])[1:-1]
            elif tokens[0] == 'LUT_1D_INPUT_RANGE':
                domain = parse_array(tokens[1:])
                LUT[0].domain = tstack([domain, domain, domain])
            elif tokens[0] == 'LUT_3D_INPUT_RANGE':
                domain = parse_array(tokens[1:])
                LUT[1].domain = tstack([domain, domain, domain])
            elif tokens[0] == 'LUT_1D_SIZE':
                has_3x1D = True
                size_3x1D = np.int_(tokens[1])
            elif tokens[0] == 'LUT_3D_SIZE':
                has_3D = True
                size_3D = np.int_(tokens[1])
            else:
                table.append(parse_array(tokens))

    table = as_float_array(table)
    if has_3x1D and has_3D:
        LUT[0].name = '{0} - Shaper'.format(title)
        LUT[1].name = '{0} - Cube'.format(title)
        LUT[1].comments = comments
        LUT[0].table = table[:size_3x1D]
        # The lines of table data shall be in ascending index order,
        # with the first component index (Red) changing most rapidly,
        # and the last component index (Blue) changing least rapidly.
        LUT[1].table = table[size_3x1D:].reshape(
            (size_3D, size_3D, size_3D, 3), order='F')
        return LUT
    elif has_3x1D:
        LUT[0].name = title
        LUT[0].comments = comments
        LUT[0].table = table
        return LUT[0]
    elif has_3D:
        LUT[1].name = title
        LUT[1].comments = comments
        # The lines of table data shall be in ascending index order,
        # with the first component index (Red) changing most rapidly,
        # and the last component index (Blue) changing least rapidly.
        table = table.reshape([size_3D, size_3D, size_3D, 3], order='F')
        LUT[1].table = table
        return LUT[1]
Ejemplo n.º 10
0
def read_LUT_SonySPI3D(path):
    """
    Reads given *Sony* *.spi3d* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3D or LUT3x1D
        :class:`LUT3D` or :class:`LUT3x1D` class instance.

    Examples
    --------
    Reading a 3D *Sony* *.spi3d* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spi3d',
    ...     'ColourCorrect.spi3d')
    >>> print(read_LUT_SonySPI3D(path))
    LUT3D - ColourCorrect
    ---------------------
    <BLANKLINE>
    Dimensions : 3
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (4, 4, 4, 3)
    Comment 01 : Adapted from a LUT generated by Foundry::LUT.
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 0, 0]), np.array([1, 1, 1])
    size = 2
    indexes = []
    table = []
    comments = []

    with open(path) as spi3d_file:
        lines = spi3d_file.readlines()
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if len(tokens) == 3:
                assert len(set(tokens)) == 1, (
                    'Non-uniform "LUT" shape is unsupported!')

                size = DEFAULT_INT_DTYPE(tokens[0])
            if len(tokens) == 6:
                indexes.append(parse_array(tokens[:3]))
                table.append(parse_array(tokens[3:]))

    assert np.array_equal(
        indexes,
        DEFAULT_INT_DTYPE(LUT3D.linear_table(size) * (size - 1)).reshape(
            (-1, 3))), 'Indexes do not match expected "LUT3D" indexes!'

    table = as_float_array(table).reshape([size, size, size, 3])

    return LUT3D(
        table, title, np.vstack([domain_min, domain_max]), comments=comments)
Ejemplo n.º 11
0
def read_LUT_SonySPI1D(path):
    """
    Reads given *Sony* *.spi1d* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT1D or LUT2D
        :class:`LUT1D` or :class:`LUT2D` class instance.

    Examples
    --------
    Reading a 1D *Sony* *.spi1d* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spi1d',
    ...     'oetf_reverse_sRGB_1D.spi1d')
    >>> print(read_LUT_SonySPI1D(path))
    LUT1D - oetf reverse sRGB 1D
    ----------------------------
    <BLANKLINE>
    Dimensions : 1
    Domain     : [-0.1  1.5]
    Size       : (16,)
    Comment 01 : Generated by "Colour 0.3.11".
    Comment 02 : "colour.models.oetf_reverse_sRGB".

    Reading a 2D *Sony* *.spi1d* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spi1d',
    ...     'oetf_reverse_sRGB_2D.spi1d')
    >>> print(read_LUT_SonySPI1D(path))
    LUT2D - oetf reverse sRGB 2D
    ----------------------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[-0.1 -0.1 -0.1]
                  [ 1.5  1.5  1.5]]
    Size       : (16, 3)
    Comment 01 : Generated by "Colour 0.3.11".
    Comment 02 : "colour.models.oetf_reverse_sRGB".
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 1])
    dimensions = 1
    table = []

    comments = []

    with open(path) as spi1d_file:
        lines = spi1d_file.readlines()
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if tokens[0] == 'Version':
                continue
            if tokens[0] == 'From':
                domain_min, domain_max = parse_array(tokens[1:])
            elif tokens[0] == 'Length':
                continue
            elif tokens[0] == 'Components':
                component = DEFAULT_INT_DTYPE(tokens[1])
                assert component in (1, 3), (
                    'Only 1 or 3 components are supported!')

                dimensions = 1 if component == 1 else 2
            elif tokens[0] in ('{', '}'):
                continue
            else:
                table.append(parse_array(tokens))

    table = as_float_array(table)
    if dimensions == 1:
        return LUT1D(np.squeeze(table),
                     title,
                     np.array([domain_min, domain_max]),
                     comments=comments)
    elif dimensions == 2:
        return LUT2D(table,
                     title,
                     np.array([[domain_min, domain_min, domain_min],
                               [domain_max, domain_max, domain_max]]),
                     comments=comments)
Ejemplo n.º 12
0
def read_LUT_SonySPI1D(path: str) -> Union[LUT1D, LUT3x1D]:
    """
    Read given *Sony* *.spi1d* *LUT* file.

    Parameters
    ----------
    path
        *LUT* path.

    Returns
    -------
    :class:`colour.LUT1D` or :class:`colour.LUT3x1D`
        :class:`LUT1D` or :class:`LUT3x1D` class instance.

    Examples
    --------
    Reading a 1D *Sony* *.spi1d* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spi1d',
    ...     'eotf_sRGB_1D.spi1d')
    >>> print(read_LUT_SonySPI1D(path))
    LUT1D - eotf sRGB 1D
    --------------------
    <BLANKLINE>
    Dimensions : 1
    Domain     : [-0.1  1.5]
    Size       : (16,)
    Comment 01 : Generated by "Colour 0.3.11".
    Comment 02 : "colour.models.eotf_sRGB".

    Reading a 3x1D *Sony* *.spi1d* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'sony_spi1d',
    ...     'eotf_sRGB_3x1D.spi1d')
    >>> print(read_LUT_SonySPI1D(path))
    LUT3x1D - eotf sRGB 3x1D
    ------------------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[-0.1 -0.1 -0.1]
                  [ 1.5  1.5  1.5]]
    Size       : (16, 3)
    Comment 01 : Generated by "Colour 0.3.11".
    Comment 02 : "colour.models.eotf_sRGB".
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 1])
    dimensions = 1
    data = []

    comments = []

    with open(path) as spi1d_file:
        lines = filter(None, (line.strip() for line in spi1d_file.readlines()))
        for line in lines:
            if line.startswith("#"):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if tokens[0] == "Version":
                continue
            if tokens[0] == "From":
                domain_min, domain_max = as_float_array(tokens[1:])
            elif tokens[0] == "Length":
                continue
            elif tokens[0] == "Components":
                component = as_int_scalar(tokens[1])
                attest(
                    component in (1, 3),
                    "Only 1 or 3 components are supported!",
                )

                dimensions = 1 if component == 1 else 2
            elif tokens[0] in ("{", "}"):
                continue
            else:
                data.append(tokens)

    table = as_float_array(data)

    LUT: Union[LUT1D, LUT3x1D]
    if dimensions == 1:
        LUT = LUT1D(
            np.squeeze(table),
            title,
            np.array([domain_min, domain_max]),
            comments=comments,
        )
    elif dimensions == 2:
        LUT = LUT3x1D(
            table,
            title,
            np.array([
                [domain_min, domain_min, domain_min],
                [domain_max, domain_max, domain_max],
            ]),
            comments=comments,
        )

    return LUT
Ejemplo n.º 13
0
def read_LUT_IridasCube(path):
    """
    Reads given *Iridas* *.cube* *LUT* file.

    Parameters
    ----------
    path : unicode
        *LUT* path.

    Returns
    -------
    LUT3x1D or LUT3d
        :class:`LUT3x1D` or :class:`LUT3D` class instance.

    References
    ----------
    :cite:`AdobeSystems2013b`

    Examples
    --------
    Reading a 3x1D *Iridas* *.cube* *LUT*:

    >>> import os
    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'iridas_cube',
    ...     'ACES_Proxy_10_to_ACES.cube')
    >>> print(read_LUT_IridasCube(path))
    LUT3x1D - ACES Proxy 10 to ACES
    -------------------------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (32, 3)

    Reading a 3D *Iridas* *.cube* *LUT*:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'iridas_cube',
    ...     'ColourCorrect.cube')
    >>> print(read_LUT_IridasCube(path))
    LUT3D - Generated by Foundry::LUT
    ---------------------------------
    <BLANKLINE>
    Dimensions : 3
    Domain     : [[ 0.  0.  0.]
                  [ 1.  1.  1.]]
    Size       : (4, 4, 4, 3)

    Reading a 3D *Iridas* *.cube* *LUT* with comments:

    >>> path = os.path.join(
    ...     os.path.dirname(__file__), 'tests', 'resources', 'iridas_cube',
    ...     'Demo.cube')
    >>> print(read_LUT_IridasCube(path))
    LUT3x1D - Demo
    --------------
    <BLANKLINE>
    Dimensions : 2
    Domain     : [[ 0.  0.  0.]
                  [ 1.  2.  3.]]
    Size       : (3, 3)
    Comment 01 : Comments can go anywhere
    """

    title = path_to_title(path)
    domain_min, domain_max = np.array([0, 0, 0]), np.array([1, 1, 1])
    dimensions = 3
    size = 2
    table = []
    comments = []

    with open(path) as cube_file:
        lines = cube_file.readlines()
        for line in lines:
            line = line.strip()

            if len(line) == 0:
                continue

            if line.startswith('#'):
                comments.append(line[1:].strip())
                continue

            tokens = line.split()
            if tokens[0] == 'TITLE':
                title = ' '.join(tokens[1:])[1:-1]
            elif tokens[0] == 'DOMAIN_MIN':
                domain_min = parse_array(tokens[1:])
            elif tokens[0] == 'DOMAIN_MAX':
                domain_max = parse_array(tokens[1:])
            elif tokens[0] == 'LUT_1D_SIZE':
                dimensions = 2
                size = DEFAULT_INT_DTYPE(tokens[1])
            elif tokens[0] == 'LUT_3D_SIZE':
                dimensions = 3
                size = DEFAULT_INT_DTYPE(tokens[1])
            else:
                table.append(parse_array(tokens))

    table = as_float_array(table)
    if dimensions == 2:
        return LUT3x1D(
            table,
            title,
            np.vstack([domain_min, domain_max]),
            comments=comments)
    elif dimensions == 3:
        # The lines of table data shall be in ascending index order,
        # with the first component index (Red) changing most rapidly,
        # and the last component index (Blue) changing least rapidly.
        table = table.reshape([size, size, size, 3], order='F')

        return LUT3D(
            table,
            title,
            np.vstack([domain_min, domain_max]),
            comments=comments)