예제 #1
0
    def test_parse_array(self):
        """
        Tests :func:`colour.io.luts.common.parse_array` definition.
        """

        np.testing.assert_equal(
            parse_array('-0.25 0.5 0.75'),
            np.array([-0.25, 0.5, 0.75]),
        )

        np.testing.assert_equal(
            parse_array(['-0.25', '0.5', '0.75']),
            np.array([-0.25, 0.5, 0.75]),
        )

        a = np.linspace(0, 1, 10)
        np.testing.assert_almost_equal(parse_array(str(a.tolist()).replace(
            '[',
            '',
        ).replace(
            ']',
            '',
        ).replace(
            ' ',
            '',
        ),
                                                   separator=','),
                                       a,
                                       decimal=7)

        self.assertEqual(
            parse_array(['1', '2', '3'], dtype=DEFAULT_INT_DTYPE).dtype,
            DEFAULT_INT_DTYPE)
예제 #2
0
    def test_parse_array(self):
        """
        Tests :func:`colour.io.luts.common.parse_array` definition.
        """

        np.testing.assert_equal(
            parse_array('-0.25 0.5 0.75'),
            np.array([-0.25, 0.5, 0.75]),
        )

        np.testing.assert_equal(
            parse_array(['-0.25', '0.5', '0.75']),
            np.array([-0.25, 0.5, 0.75]),
        )

        a = np.linspace(0, 1, 10)
        np.testing.assert_almost_equal(
            parse_array(
                str(a.tolist()).replace(
                    '[',
                    '',
                ).replace(
                    ']',
                    '',
                ).replace(
                    ' ',
                    '',
                ),
                separator=','),
            a,
            decimal=7)

        self.assertEqual(
            parse_array(['1', '2', '3'], dtype=DEFAULT_INT_DTYPE).dtype,
            DEFAULT_INT_DTYPE)
예제 #3
0
    def _parse_table_section(lines):
        """
        Parses the table at given lines.
        """

        size = parse_array(lines[0]).astype(int)
        table = np.array([parse_array(line) for line in lines[1:]])

        return size, table
예제 #4
0
    def _parse_table_section(lines):
        """
        Parses the table at given lines.
        """

        size = parse_array(lines[0]).astype(int)
        table = np.array([parse_array(line) for line in lines[1:]])

        return size, table
예제 #5
0
    def _parse_domain_section(lines):
        """
        Parses the domain at given lines.
        """

        pre_LUT_size = max([int(lines[i]) for i in [0, 3, 6]])
        pre_LUT = [parse_array(lines[i]) for i in [1, 2, 4, 5, 7, 8]]
        pre_LUT_padded = []

        for row in pre_LUT:
            if len(row) != pre_LUT_size:
                pre_LUT_padded.append(
                    np.pad(
                        row, (0, pre_LUT_size - row.shape[0]),
                        mode='constant',
                        constant_values=np.nan))
            else:
                pre_LUT_padded.append(row)
        pre_LUT = np.asarray(pre_LUT_padded)

        return pre_LUT
예제 #6
0
    def _parse_domain_section(lines):
        """
        Parses the domain at given lines.
        """

        pre_LUT_size = max([int(lines[i]) for i in [0, 3, 6]])
        pre_LUT = [parse_array(lines[i]) for i in [1, 2, 4, 5, 7, 8]]
        pre_LUT_padded = []

        for row in pre_LUT:
            if len(row) != pre_LUT_size:
                pre_LUT_padded.append(
                    np.pad(
                        row, (0, pre_LUT_size - row.shape[0]),
                        mode='constant',
                        constant_values=np.nan))
            else:
                pre_LUT_padded.append(row)
        pre_LUT = np.asarray(pre_LUT_padded)

        return pre_LUT
예제 #7
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)
예제 #8
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)
예제 #9
0
파일: resolve_cube.py 프로젝트: yixw/colour
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]
예제 #10
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]
예제 #11
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)
예제 #12
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)
예제 #13
0
    def test_write_LUT_SonySPI3D(self):
        """
        Tests :func:`colour.io.luts.sony_spi3d.write_LUT_SonySPI3D` definition.
        """

        LUT_r = read_LUT_SonySPI3D(
            os.path.join(LUTS_DIRECTORY, 'Colour_Correct.spi3d'))

        write_LUT_SonySPI3D(
            LUT_r,
            os.path.join(self._temporary_directory, 'Colour_Correct.spi3d'))
        LUT_t = read_LUT_SonySPI3D(
            os.path.join(self._temporary_directory, 'Colour_Correct.spi3d'))
        self.assertEqual(LUT_r, LUT_t)

        write_LUT_SonySPI3D(
            LUTSequence(LUT_r),
            os.path.join(self._temporary_directory, 'Colour_Correct.spi3d'))
        self.assertEqual(LUT_r, LUT_t)

        # Test for proper indexes sequentiality.
        path = os.path.join(self._temporary_directory, 'Size_10_Indexes.spi3d')
        write_LUT_SonySPI3D(LUT3D(size=10), path)
        indexes = []

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

                tokens = line.split()
                if len(tokens) == 6:
                    indexes.append(parse_array(tokens[:3], DEFAULT_INT_DTYPE))

        np.testing.assert_array_equal(
            as_int_array(indexes)[:200, ...],
            np.array([
                [0, 0, 0],
                [0, 0, 1],
                [0, 0, 2],
                [0, 0, 3],
                [0, 0, 4],
                [0, 0, 5],
                [0, 0, 6],
                [0, 0, 7],
                [0, 0, 8],
                [0, 0, 9],
                [0, 1, 0],
                [0, 1, 1],
                [0, 1, 2],
                [0, 1, 3],
                [0, 1, 4],
                [0, 1, 5],
                [0, 1, 6],
                [0, 1, 7],
                [0, 1, 8],
                [0, 1, 9],
                [0, 2, 0],
                [0, 2, 1],
                [0, 2, 2],
                [0, 2, 3],
                [0, 2, 4],
                [0, 2, 5],
                [0, 2, 6],
                [0, 2, 7],
                [0, 2, 8],
                [0, 2, 9],
                [0, 3, 0],
                [0, 3, 1],
                [0, 3, 2],
                [0, 3, 3],
                [0, 3, 4],
                [0, 3, 5],
                [0, 3, 6],
                [0, 3, 7],
                [0, 3, 8],
                [0, 3, 9],
                [0, 4, 0],
                [0, 4, 1],
                [0, 4, 2],
                [0, 4, 3],
                [0, 4, 4],
                [0, 4, 5],
                [0, 4, 6],
                [0, 4, 7],
                [0, 4, 8],
                [0, 4, 9],
                [0, 5, 0],
                [0, 5, 1],
                [0, 5, 2],
                [0, 5, 3],
                [0, 5, 4],
                [0, 5, 5],
                [0, 5, 6],
                [0, 5, 7],
                [0, 5, 8],
                [0, 5, 9],
                [0, 6, 0],
                [0, 6, 1],
                [0, 6, 2],
                [0, 6, 3],
                [0, 6, 4],
                [0, 6, 5],
                [0, 6, 6],
                [0, 6, 7],
                [0, 6, 8],
                [0, 6, 9],
                [0, 7, 0],
                [0, 7, 1],
                [0, 7, 2],
                [0, 7, 3],
                [0, 7, 4],
                [0, 7, 5],
                [0, 7, 6],
                [0, 7, 7],
                [0, 7, 8],
                [0, 7, 9],
                [0, 8, 0],
                [0, 8, 1],
                [0, 8, 2],
                [0, 8, 3],
                [0, 8, 4],
                [0, 8, 5],
                [0, 8, 6],
                [0, 8, 7],
                [0, 8, 8],
                [0, 8, 9],
                [0, 9, 0],
                [0, 9, 1],
                [0, 9, 2],
                [0, 9, 3],
                [0, 9, 4],
                [0, 9, 5],
                [0, 9, 6],
                [0, 9, 7],
                [0, 9, 8],
                [0, 9, 9],
                [1, 0, 0],
                [1, 0, 1],
                [1, 0, 2],
                [1, 0, 3],
                [1, 0, 4],
                [1, 0, 5],
                [1, 0, 6],
                [1, 0, 7],
                [1, 0, 8],
                [1, 0, 9],
                [1, 1, 0],
                [1, 1, 1],
                [1, 1, 2],
                [1, 1, 3],
                [1, 1, 4],
                [1, 1, 5],
                [1, 1, 6],
                [1, 1, 7],
                [1, 1, 8],
                [1, 1, 9],
                [1, 2, 0],
                [1, 2, 1],
                [1, 2, 2],
                [1, 2, 3],
                [1, 2, 4],
                [1, 2, 5],
                [1, 2, 6],
                [1, 2, 7],
                [1, 2, 8],
                [1, 2, 9],
                [1, 3, 0],
                [1, 3, 1],
                [1, 3, 2],
                [1, 3, 3],
                [1, 3, 4],
                [1, 3, 5],
                [1, 3, 6],
                [1, 3, 7],
                [1, 3, 8],
                [1, 3, 9],
                [1, 4, 0],
                [1, 4, 1],
                [1, 4, 2],
                [1, 4, 3],
                [1, 4, 4],
                [1, 4, 5],
                [1, 4, 6],
                [1, 4, 7],
                [1, 4, 8],
                [1, 4, 9],
                [1, 5, 0],
                [1, 5, 1],
                [1, 5, 2],
                [1, 5, 3],
                [1, 5, 4],
                [1, 5, 5],
                [1, 5, 6],
                [1, 5, 7],
                [1, 5, 8],
                [1, 5, 9],
                [1, 6, 0],
                [1, 6, 1],
                [1, 6, 2],
                [1, 6, 3],
                [1, 6, 4],
                [1, 6, 5],
                [1, 6, 6],
                [1, 6, 7],
                [1, 6, 8],
                [1, 6, 9],
                [1, 7, 0],
                [1, 7, 1],
                [1, 7, 2],
                [1, 7, 3],
                [1, 7, 4],
                [1, 7, 5],
                [1, 7, 6],
                [1, 7, 7],
                [1, 7, 8],
                [1, 7, 9],
                [1, 8, 0],
                [1, 8, 1],
                [1, 8, 2],
                [1, 8, 3],
                [1, 8, 4],
                [1, 8, 5],
                [1, 8, 6],
                [1, 8, 7],
                [1, 8, 8],
                [1, 8, 9],
                [1, 9, 0],
                [1, 9, 1],
                [1, 9, 2],
                [1, 9, 3],
                [1, 9, 4],
                [1, 9, 5],
                [1, 9, 6],
                [1, 9, 7],
                [1, 9, 8],
                [1, 9, 9],
            ]))
예제 #14
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)