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)
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)
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
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
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
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
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)
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)
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]
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]
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)
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)
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], ]))
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)