+ # May want to use fewer components than there are channels in the data
+ # Most commonly used for single channel LUTs
+ components = min(3, components, channels)
+
+ with open(filename, 'w') as fp:
+ fp.write('Version 1\n')
+ fp.write('From %f %f\n' % (from_min, from_max))
+ fp.write('Length %d\n' % entries)
+ fp.write('Components %d\n' % components)
+ fp.write('{\n')
+ for i in range(0, entries):
+ entry = ''
+ for j in range(0, components):
+ entry = '%s %s' % (entry, data[i * channels + j])
+ fp.write(' %s\n' % entry)
+ fp.write('}\n')
+
+
+def write_CSP_1d(filename,
+ from_min,
+ from_max,
+ data,
+ entries,
+ channels,
+ components=3):
+ """
+ Object description.
+
+ Parameters
+ ----------
+ parameter : type
+ Parameter description.
+
+ Returns
+ -------
+ type
+ Return value description.
+ """
+
+ # May want to use fewer components than there are channels in the data
+ # Most commonly used for single channel LUTs
+ components = min(3, components, channels)
+
+ with open(filename, 'w') as fp:
+ fp.write('CSPLUTV100\n')
+ fp.write('1D\n')
+ fp.write('\n')
+ fp.write('BEGIN METADATA\n')
+ fp.write('END METADATA\n')
+
+ fp.write('\n')
+
+ fp.write('2\n')
+ fp.write('%f %f\n' % (from_min, from_max))
+ fp.write('0.0 1.0\n')
+ fp.write('2\n')
+ fp.write('%f %f\n' % (from_min, from_max))
+ fp.write('0.0 1.0\n')
+ fp.write('2\n')
+ fp.write('%f %f\n' % (from_min, from_max))
+ fp.write('0.0 1.0\n')
+
+ fp.write('\n')
+
+ fp.write('%d\n' % entries)
+ if components == 1:
+ for i in range(0, entries):
+ entry = ''
+ for j in range(3):
+ entry = '%s %s' % (entry, data[i * channels])
+ fp.write('%s\n' % entry)
+ else:
+ for i in range(entries):
+ entry = ''
+ for j in range(components):
+ entry = '%s %s' % (entry, data[i * channels + j])
+ fp.write('%s\n' % entry)
+ fp.write('\n')
+
+
+def write_CTL_1d(filename,
+ from_min,
+ from_max,
+ data,
+ entries,
+ channels,
+ components=3):
+ """
+ Object description.
+
+ Parameters
+ ----------
+ parameter : type
+ Parameter description.
+
+ Returns
+ -------
+ type
+ Return value description.
+ """
+
+ # May want to use fewer components than there are channels in the data
+ # Most commonly used for single channel LUTs
+ components = min(3, components, channels)
+
+ with open(filename, 'w') as fp:
+ fp.write('// %d x %d LUT generated by "generate_lut"\n' % (
+ entries, components))
+ fp.write('\n')
+ fp.write('const float min1d = %3.9f;\n' % from_min)
+ fp.write('const float max1d = %3.9f;\n' % from_max)
+ fp.write('\n')
+
+ # Write LUT
+ if components == 1:
+ fp.write('const float lut[] = {\n')
+ for i in range(0, entries):
+ fp.write('%s' % data[i * channels])
+ if i != (entries - 1):
+ fp.write(',')
+ fp.write('\n')
+ fp.write('};\n')
+ fp.write('\n')
+ else:
+ for j in range(components):
+ fp.write('const float lut%d[] = {\n' % j)
+ for i in range(0, entries):
+ fp.write('%s' % data[i * channels])
+ if i != (entries - 1):
+ fp.write(',')
+ fp.write('\n')
+ fp.write('};\n')
+ fp.write('\n')
+
+ fp.write('void main\n')
+ fp.write('(\n')
+ fp.write(' input varying float rIn,\n')
+ fp.write(' input varying float gIn,\n')
+ fp.write(' input varying float bIn,\n')
+ fp.write(' input varying float aIn,\n')
+ fp.write(' output varying float rOut,\n')
+ fp.write(' output varying float gOut,\n')
+ fp.write(' output varying float bOut,\n')
+ fp.write(' output varying float aOut\n')
+ fp.write(')\n')
+ fp.write('{\n')
+ fp.write(' float r = rIn;\n')
+ fp.write(' float g = gIn;\n')
+ fp.write(' float b = bIn;\n')
+ fp.write('\n')
+ fp.write(' // Apply LUT\n')
+ if components == 1:
+ fp.write(' r = lookup1D(lut, min1d, max1d, r);\n')
+ fp.write(' g = lookup1D(lut, min1d, max1d, g);\n')
+ fp.write(' b = lookup1D(lut, min1d, max1d, b);\n')
+ elif components == 3:
+ fp.write(' r = lookup1D(lut0, min1d, max1d, r);\n')
+ fp.write(' g = lookup1D(lut1, min1d, max1d, g);\n')
+ fp.write(' b = lookup1D(lut2, min1d, max1d, b);\n')
+ fp.write('\n')
+ fp.write(' rOut = r;\n')
+ fp.write(' gOut = g;\n')
+ fp.write(' bOut = b;\n')
+ fp.write(' aOut = aIn;\n')
+ fp.write('}\n')
+
+
+def write_1d(filename,
+ from_min,
+ from_max,
+ data,
+ data_entries,
+ data_channels,
+ lut_components=3,
+ format='spi1d'):
+ """
+ Object description.
+
+ Parameters
+ ----------
+ parameter : type
+ Parameter description.
+
+ Returns
+ -------
+ type
+ Return value description.
+ """
+
+ ocioFormatsToExtensions = {'cinespace': 'csp',
+ 'flame': '3dl',
+ 'icc': 'icc',
+ 'houdini': 'lut',
+ 'lustre': '3dl',
+ 'ctl': 'ctl'}
+
+ if format in ocioFormatsToExtensions:
+ if ocioFormatsToExtensions[format] == 'csp':
+ write_CSP_1d(filename,
+ from_min,
+ from_max,
+ data,
+ data_entries,
+ data_channels,
+ lut_components)
+ elif ocioFormatsToExtensions[format] == 'ctl':
+ write_CTL_1d(filename,
+ from_min,
+ from_max,
+ data,
+ data_entries,
+ data_channels,
+ lut_components)
+ else:
+ write_SPI_1d(filename,
+ from_min,
+ from_max,
+ data,
+ data_entries,
+ data_channels,
+ lut_components)