def readSPI1D(lutPath, inverse=False, interpolation='linear', inversesUseIndexMaps=True, inversesUseHalfDomain=True): with open(lutPath) as f: lines = f.read().splitlines() # # Read LUT data # resolution = [0, 0] samples = [] indexMap = [] minInputValue = 0.0 maxInputValue = 1.0 for line in lines: #print( "line : %s" % line ) tokens = line.split() if tokens[0] == "Version": version = int(tokens[1]) if version != 1: break elif tokens[0] == "From": minInputValue = float(tokens[1]) maxInputValue = float(tokens[2]) elif tokens[0] == "Length": resolution[0] = int(tokens[1]) elif tokens[0] == "Components": resolution[1] = int(tokens[1]) elif tokens[0] in ["{", "}"]: continue else: samples.extend(map(float, tokens)) #else: # print( "Skipping line : %s" % tokens ) # # Create ProcessNodes # lutpns = [] # Forward transform, pretty straightforward if not inverse: # Remap input range if minInputValue != 0.0 or maxInputValue != 1.0: rangepn = clf.Range(clf.bitDepths["FLOAT16"], clf.bitDepths["FLOAT16"], "range", "range") rangepn.setMinInValue(minInputValue) rangepn.setMaxInValue(maxInputValue) rangepn.setMinOutValue(0.0) rangepn.setMaxOutValue(1.0) lutpns.append(rangepn) # LUT node lutpn = clf.LUT1D(clf.bitDepths["FLOAT16"], clf.bitDepths["FLOAT16"], "lut1d", "lut1d", interpolation=interpolation) lutpn.setArray(resolution[1], samples) lutpns.append(lutpn) # Inverse transform, LUT has to be resampled else: if inversesUseIndexMaps: print( "Generating inverse of 1D LUT using Index Maps") lutpnInverses = Sampling.generateLUT1DInverseIndexMap(resolution, samples, minInputValue, maxInputValue) elif inversesUseHalfDomain: print( "Generating full half-domain inverse of 1D LUT") lutpnInverses = Sampling.generateLUT1DInverseHalfDomain(resolution, samples, minInputValue, maxInputValue, rawHalfs=True) else: print( "Generating resampled inverse of 1D LUT") lutpnInverses = Sampling.generateLUT1DInverseResampled(resolution, samples, minInputValue, maxInputValue) lutpns.extend(lutpnInverses) return lutpns
def writeCLF1D3D1D(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 = Sampling.generateLUT1DInverseIndexMap([lutResolution1dIn, 3], samples1dIn, inputMin, inputMax) elif inversesUseHalfDomain: #print( "Generating full half-domain inverse of 1D LUT") lutpnInverses = Sampling.generateLUT1DInverseHalfDomain([lutResolution1dIn, 3], samples1dIn, inputMin, inputMax, rawHalfs=True) else: #print( "Generating resampled inverse of 1D LUT") lutpnInverses = Sampling.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) return True