def convertCLFtoLUT(clfPath, lutPath, lutFileFormat, lutDataFormat=LUTDATAFORMAT_1D, lutResolution1d=1024, lutResolution3d=33, lutResolution1d3d1d=[1024, 33, 2], inputMin=0.0, inputMax=1.0, shaperIn=['linear', 0.0, 1.0], shaperOut=['linear', 0.0, 1.0]): # Load CLF print("Reading CLF : %s" % clfPath) processList = clf.ProcessList(clfPath) # For each data format, do something different if lutDataFormat == LUTDATAFORMAT_1D: sampleAndWrite1D(processList, lutPath, lutFileFormat, lutResolution1d, inputMin, inputMax) elif lutDataFormat == LUTDATAFORMAT_3D: sampleAndWrite3D(processList, lutPath, lutFileFormat, lutResolution3d, inputMin, inputMax) elif lutDataFormat == LUTDATAFORMAT_1D_3D_1D: sampleAndWrite1D3D1D(processList, lutPath, lutFileFormat, lutResolution1d3d1d, shaperIn, shaperOut) else: print("Unsupported LUT data format : %s" % lutDataFormat)
def convertLUTtoCLF(lutPath, clfPath, inverse=False, inversesUseIndexMaps=False, inversesUseHalfDomain=True): direction = 'forward' if inverse: direction = 'inverse' # Load the LUT and convert to a CLF ProcessNode lutpns = convertLUTToProcessNode( lutPath, direction=direction, inversesUseIndexMaps=inversesUseIndexMaps, inversesUseHalfDomain=inversesUseHalfDomain) # Create a CLF ProcessList and populate contents if lutpns != []: pl = clf.ProcessList() # Populate pl.setID('Converted lut') pl.setCompCLFversion(1.0) pl.setName('Converted lut') for lutpn in lutpns: pl.addProcess(lutpn) # Write CLF to disk pl.writeFile(clfPath)
def convertCLFtoLUT(clfPath, lutPath, lutFileFormat, lutDataFormat=lutFormats.LUTDATAFORMAT_1D, lutResolution1d=1024, lutResolution3d=33, lutResolution1d3d1d=[1024, 33, 2], inputMin=0.0, inputMax=1.0, shaperIn=['linear', 0.0, 1.0], shaperOut=['linear', 0.0, 1.0]): # Load CLF print("Reading CLF : %s" % clfPath) processList = clf.ProcessList(clfPath) # Write new LUT format print("Writing LUT : %s" % lutPath) lutFormats.Registry.write( processList, lutPath, #lutFileFormat, # Currently not used lutDataFormat, lutResolution1d, lutResolution3d, lutResolution1d3d1d, inputMin, inputMax, shaperIn, shaperOut)
def read(lutPath, inverse=False, interpolation='linear', inversesUseIndexMaps=True, inversesUseHalfDomain=True, returnProcessNodes=False): extension = os.path.splitext(lutPath)[1][1:].strip().lower() #print( "Reading lut %s" % lutPath ) # Step through each of the lut format classes for cls in Registry.getFormats(): #print( "Lut format class %s can load extensions %s" % ( # cls, cls.extensions()) ) # If the class can read files and it can read this extension # Note: More than one format may use the same extension if extension in cls.extensions() and cls.canRead(extension): #print( "Reading lut %s" % lutPath ) # Call reader class read method lutProcessNodes = cls.read(lutPath, inverse, interpolation, inversesUseIndexMaps, inversesUseHalfDomain) #print( "Read lut %s" % lutPath ) # Create the CLF/ProcessList if lutProcessNodes: # Return the list of ProcessNodes if returnProcessNodes: return lutProcessNodes else: # Wrap the ProcessNodes in a ProcessList # Initialize pl = clf.ProcessList() # Populate pl.setID('Converted lut') pl.setCompCLFversion(1.0) pl.setName('Converted lut') for lutpn in lutProcessNodes: pl.addProcess(lutpn) return pl # Or warn the user and keep trying else: print( "Reading failed for some reason. We'll keep trying." ) print( "Reading LUTs in the %s format is not currently supported" % extension ) return None
def convertOCIOtoCLF(configPath, sourceColorSpaceNames, destColorSpaceNames, clfPath, inversesUseIndexMaps, inversesUseHalfDomain): # Load the config config = OCIO.Config.CreateFromFile(configPath) configBasePath = os.path.split(configPath)[0] configLUTPath = os.path.join(configBasePath, config.getSearchPath()) description = "CLF converted from OCIO config.\n" description += "Config Path : %s\n" % configPath #print( configLUTPath ) # List that process nodes will be appended to lutpns = [] # Generate the source color space to reference color space transforms for sourceColorSpaceName in sourceColorSpaceNames: # Get the OCIO transforms sourceColorSpace = config.getColorSpace(sourceColorSpaceName) sourceTransform = sourceColorSpace.getTransform( OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE) # Convert to CLF ProcessNodes pns = convertTransformsToProcessNodes( sourceTransform, lutSearchPath=configLUTPath, inversesUseIndexMaps=inversesUseIndexMaps, inversesUseHalfDomain=inversesUseHalfDomain) # Rename and add a description to each ProcessNode specificDescription = "Convert %s to reference" % sourceColorSpaceName count = 0 for pn in pns: ds2 = clf.Description(specificDescription) pn.addElement(ds2) name = "%s to reference - node %d" % (sourceColorSpaceName, count) pn.setAttribute("name", name) count += 1 # Append to the overall CLF ProcessNode list lutpns.extend(pns) # Extend the overall description description += "Source color space : %s\n" % sourceColorSpaceName # Generate the reference color space to destination color space transforms for destColorSpaceName in destColorSpaceNames: # Get the OCIO transforms destColorSpace = config.getColorSpace(destColorSpaceName) destTransform = destColorSpace.getTransform( OCIO.Constants.COLORSPACE_DIR_FROM_REFERENCE) # Convert to CLF ProcessNodes pns = convertTransformsToProcessNodes( destTransform, lutSearchPath=configLUTPath, inversesUseIndexMaps=inversesUseIndexMaps, inversesUseHalfDomain=inversesUseHalfDomain) # Rename and add a description to each ProcessNode specificDescription = "Convert reference to %s" % destColorSpaceName count = 0 for pn in pns: ds2 = clf.Description(specificDescription) pn.addElement(ds2) name = "reference to %s - node %d" % (destColorSpaceName, count) pn.setAttribute("name", name) count += 1 # Append to the overall CLF ProcessNode list lutpns.extend(pns) # Extend the overall description description += "Destination color space name : %s\n" % destColorSpaceName # Create a CLF ProcessList and populate contents if lutpns != []: print("Creating ProcessList") pl = clf.ProcessList() # Populate pl.setID('Converted lut') pl.setCompCLFversion(1.0) pl.setName('Converted lut') ds1 = clf.Description(description) pl.addElement(ds1) for lutpn in lutpns: pl.addProcess(lutpn) # Write CLF to disk print("Writing CLF : %s" % clfPath) pl.writeFile(clfPath) else: print( "No ProcessNodes created for this transform. Skipping writing CLF." )
def createShaper(shaperType, shaperMin, shaperMax): # # Create the forward and inverse input shaper ProcessLists # shaperPL = clf.ProcessList() shaperPLInverse = clf.ProcessList() # Log shaper if shaperType == 'log2': #print( "log shaper - %f, %f" % (shaperMin, shaperMax)) # Forward ProcessNodes logPn = clf.Log(style='log2') shaperPL.addProcess(logPn) rangePn = clf.Range() rangePn.setMinInValue(shaperMin) rangePn.setMaxInValue(shaperMax) rangePn.setMinOutValue(0.0) rangePn.setMaxOutValue(1.0) shaperPL.addProcess(rangePn) # Input min and max inputMin = pow(2, shaperMin) inputMax = pow(2, shaperMax) # Inverse ProcessNodes rangePn2 = clf.Range() rangePn2.setMinInValue(0.0) rangePn2.setMaxInValue(1.0) rangePn2.setMinOutValue(shaperMin) rangePn2.setMaxOutValue(shaperMax) shaperPLInverse.addProcess(rangePn2) logPn2 = clf.Log(style='antiLog2') shaperPLInverse.addProcess(logPn2) # Linear shaper elif shaperType == 'linear': #print( "linear shaper - %f, %f" % (shaperMin, shaperMax)) # Forward ProcessNodes rangePn = clf.Range() rangePn.setMinInValue(shaperMin) rangePn.setMaxInValue(shaperMax) rangePn.setMinOutValue(0.0) rangePn.setMaxOutValue(1.0) shaperPL.addProcess(rangePn) # Input min and max inputMin = shaperMin inputMax = shaperMax # Inverse ProcessNodes rangePn2 = clf.Range() rangePn2.setMinInValue(0.0) rangePn2.setMaxInValue(1.0) rangePn2.setMinOutValue(shaperMin) rangePn2.setMaxOutValue(shaperMax) shaperPLInverse.addProcess(rangePn2) # No shaper else: inputMin = 0.0 inputMax = 1.0 return (shaperPL, shaperPLInverse, inputMin, inputMax)
def main(): import optparse usage = "%prog [options]\n" usage += "\n" usage += "compression options:\n" usage += " exr format compression options : none, rle, zip, zips(default), piz, pxr24, b44, b44a, dwaa, or dwab\n" usage += " dwaa and dwab compression support depends on the version of OpenImageIO that you're using." usage += " tiff format compression options : none, lzw, zip(default), packbits\n" usage += " tga format compression options : none, rle\n" usage += " sgi format compression options : none, rle\n" usage += "\n" usage += "compression quality options:\n" usage += " jpg format compression quality options : 0 to 100\n" p = optparse.OptionParser( description='Filter an image using the Common LUT Format', prog='clfFilter', version='clfFilter', usage=usage) p.add_option('--input', '-i', default=None) p.add_option('--output', '-o', default=None) p.add_option('--clf', '-c', default=None) p.add_option('--verbose', '-v', action="store_true") p.add_option('--outputBitDepth', '', default=None) p.add_option('--multithreaded', '-m', type='int', default=cpu_count()) p.add_option("--compression") p.add_option("--quality", type="int", dest="quality", default=-1) options, arguments = p.parse_args() # # Get options # clfPath = options.clf inputPath = options.input outputPath = options.output verbose = options.verbose == True outputBitDepth = options.outputBitDepth multithreaded = options.multithreaded multithreaded = min(cpu_count(), max(1, multithreaded)) compression = options.compression compressionQuality = options.quality try: argsStart = sys.argv.index('--') + 1 args = sys.argv[argsStart:] except: argsStart = len(sys.argv) + 1 args = [] if verbose: print("command line : \n%s\n" % " ".join(sys.argv)) if outputBitDepth and not (outputBitDepth in clf.bitDepths.values()): print( "Output bit depth %s is not a valid CLF bit depth. It will be ignored." % outputBitDepth) print("Valid values are %s." % ", ".join(clf.bitDepths.values())) outputBitDepth = None return # # Load a CLF # processList = None if clfPath != None: processList = clf.ProcessList(clfPath) print("Loaded CLF - title: %s, path: %s" % (processList.getName(), clfPath)) # # Filter an image # if processList != None and outputPath != None and inputPath != None: filterImageWithCLF(inputPath, outputPath, processList, verbose, outBitDepth=outputBitDepth, multithreaded=multithreaded, compression=compression, compressionQuality=compressionQuality)
def write_CLF_1d_3d_1d(lutPath, samples1dIn, lutResolution1dIn, inputMin, inputMax, samples3d, lutResolution3d, samples1dOut, lutResolution1dOut, outputMin, outputMax, inversesUseIndexMaps=True, inversesUseHalfDomain=True): lutpns = [] # Create the input shaper if samples1dIn: if inversesUseIndexMaps: print("Generating inverse of 1D LUT using Index Maps") lutpnInverses = convertLUTtoCLF.generateLUT1DInverseIndexMap( [lutResolution1dIn, 3], samples1dIn, inputMin, inputMax) elif inversesUseHalfDomain: print("Generating full half-domain inverse of 1D LUT") lutpnInverses = convertLUTtoCLF.generateLUT1DInverseHalfDomain( [lutResolution1dIn, 3], samples1dIn, inputMin, inputMax, rawHalfs=True) else: print("Generating resampled inverse of 1D LUT") lutpnInverses = convertLUTtoCLF.generateLUT1DInverseResampled( [lutResolution1dIn, 3], samples1dIn, inputMin, inputMax) lutpns.extend(lutpnInverses) # Create the 3D LUT clfSamples = [0.0] * (lutResolution3d[0] * lutResolution3d[1] * lutResolution3d[2]) * 3 index = 0 for r in range(lutResolution3d[0]): for g in range(lutResolution3d[1]): for b in range(lutResolution3d[2]): for c in range(3): clfSamples[index] = samples3d[r][g][b][c] index += 1 interpolation = 'trilinear' lut3dpn = clf.LUT3D(clf.bitDepths["FLOAT16"], clf.bitDepths["FLOAT16"], "lut3d", "lut3d", interpolation=interpolation) lut3dpn.setArray( [lutResolution3d[0], lutResolution3d[1], lutResolution3d[2]], clfSamples) lutpns.append(lut3dpn) # Create the output shaper if samples1dOut: interpolation = 'linear' lutpn = clf.LUT1D(clf.bitDepths["FLOAT16"], clf.bitDepths["FLOAT16"], "lut1d", "lut1d", interpolation=interpolation) lutpn.setArray(3, samples1dOut) lutpns.append(lutpn) # Wrap in a ProcessList and write to disk pl = clf.ProcessList() # Populate pl.setID('Converted lut') pl.setCompCLFversion(1.0) pl.setName('Converted lut') for lutpn in lutpns: pl.addProcess(lutpn) # Write CLF to disk pl.writeFile(lutPath)
def main(): import optparse p = optparse.OptionParser( description='Filter an image using the Common LUT Format', prog='clfFilter', version='clfFilter', usage='%prog [options]') p.add_option('--input', '-i', default=None) p.add_option('--output', '-o', default=None) p.add_option('--clf', '-c', default=None) p.add_option('--verbose', '-v', action="store_true") p.add_option('--outputBitDepth', '', default=None) options, arguments = p.parse_args() # # Get options # clfPath = options.clf inputPath = options.input outputPath = options.output verbose = options.verbose == True outputBitDepth = options.outputBitDepth try: argsStart = sys.argv.index('--') + 1 args = sys.argv[argsStart:] except: argsStart = len(sys.argv) + 1 args = [] if verbose: print("command line : \n%s\n" % " ".join(sys.argv)) if not outputBitDepth in clf.bitDepths.values(): print( "Output bit depth %s is not a valid CLF bit depth. It will be ignored." % outputBitDepth) print("Valid values are %s." % ", ".join(clf.bitDepths.values())) outputBitDepth = None return # # Load a CLF # processList = None if clfPath != None: processList = clf.ProcessList(clfPath) print("Loaded CLF - title: %s, path: %s" % (processList.getName(), clfPath)) # # Filter an image # if processList != None and outputPath != None and inputPath != None: filterImageWithCLF(inputPath, outputPath, processList, verbose, outBitDepth=outputBitDepth)