"""This is a python script to concatenate two Photoshop curves.That is, if you have an acv file called CURVE and another calledDELTA, you runpython catacv.py CURVE DELTA NEWand it applies DELTA first, then CURVE, yielding a new curve called NEW.You might use it when working on curves with QTR. If you know your base curve is pretty good, but you want to tweak it with another knowncurve, you can use this to concatenate the two curves. I use it withcurves generated by David Eisenlord's script for digital negatives.The sample points on the new curve - that is, the x-coordinates of the new curve -come from the main CURVE, not the DELTA. Resampling curves is an exerciseleft to the reader. The script won't behave well if the curves aren'tfor the same number of channels (grayscale is all I've used.)The extraction of the curves from the acv files are from here: https://github.com/vbalnt/filterizer"""from struct import unpack, packfrom scipy import interpolateimport numpyimport scipyimport sysclass Filter: def __init__(self, name):   self.name = name   self.curves = [] def read_from_file(self, acv_file_path):   with open(acv_file_path, 'rb') as acv_file:	 self.curves = self._read_curves(acv_file)   self.polynomials = self._find_coefficients() def write_to_file(self, acv_file_path): 	with open(acv_file_path, 'wb') as acv_file: 		acv_file.write(pack('!hh', 4, len(self.curves))) 		for curve in self.curves: 			acv_file.write(pack('!h', len(curve))) 			for (x, y) in curve: 				acv_file.write(pack('!hh', y, x)) def _read_curves(self, acv_file):   _, nr_curves = unpack('!hh', acv_file.read(4))   curves = []   for i in xrange(0, nr_curves):	 curve = []	 num_curve_points, = unpack('!h', acv_file.read(2))	 for j in xrange(0, num_curve_points):	   y, x = unpack('!hh', acv_file.read(4))	   curve.append((x,y))	 curves.append(curve)   return curves def _find_coefficients(self):   polynomials = []   for curve in self.curves:	 xdata = [x[0] for x in curve]	 ydata = [x[1] for x in curve]	 p = interpolate.interp1d(xdata, ydata, kind='cubic')	 polynomials.append(p)   return polynomials def get_r(self):   return self.polynomials[1] def get_g(self):   return self.polynomials[2] def get_b(self):   return self.polynomials[3] def get_c(self):   return self.polynomials[0] def apply_filter(self, apply_to, new_filter):	ncurves = len(apply_to.curves)	curveno = 0	for curve in apply_to.curves:		newcurve = []		p = self.polynomials[curveno]		for (x,y) in curve:			newcurve.append((x, numpy.floor(p(y)+0.5).clip(0,255)))		curveno += 1		new_filter.curves.append(newcurve)		return #something if necessary filter_array.astype(numpy.uint8) def print_filter(self):	print self.name	for curve in self.curves:		for (x, y) in curve:			print x, yclass FilterManager: def __init__(self):   self.filters = {}   #add some stuff here def add_filter(self,filter_obj):   # Overwrites if such a filter already exists   # NOTE: Fix or not to fix?   self.filters[filter_obj.name] = filter_obj if __name__ == '__main__': if len(sys.argv) < 4:	print "Wrong number of arguments"	print """  Usage: \			python catacv.py curvefile deltacurve resultcurve """ else:	img_filter = Filter('crgb')	img_filter.read_from_file(sys.argv[1])	delta_filter = Filter('delta')	delta_filter.read_from_file(sys.argv[2])	new_filter = Filter('new')	filter_manager = FilterManager()	filter_manager.add_filter(img_filter)	filter_manager.add_filter(delta_filter)	filter_manager.add_filter(new_filter)		delta_filter.apply_filter(img_filter, new_filter)	img_filter.print_filter()	new_filter.print_filter()	new_filter.write_to_file(sys.argv[3])