From 7c17cf553711c8911940bc578fa6dfa1de12840a Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 16 Mar 2014 21:32:46 +0100 Subject: switch overloading sentinel from None to ... and improve sigmoid, manipulate, cie_manipulate and lower_resolution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- src/curve.py | 265 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 141 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/curve.py b/src/curve.py index b8a7491..36b4346 100644 --- a/src/curve.py +++ b/src/curve.py @@ -242,32 +242,32 @@ def clip_whitepoint(rgb): return [min(max(0, x), 1) for x in rgb] -def rgb_contrast(r, g = None, b = None): +def rgb_contrast(r, g = ..., b = ...): ''' Apply contrast correction on the colour curves using sRGB - @param r:float The contrast parameter for the red curve - @param g:float? The contrast parameter for the green curve, defaults to `r` if `None` - @param b:float? The contrast parameter for the blue curve, defaults to `r` if `None` + @param r:float The contrast parameter for the red curve + @param g:float|... The contrast parameter for the green curve, defaults to `r` if `...` + @param b:float|... The contrast parameter for the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for (curve, level) in curves(r, g, b): if not level == 1.0: for i in range(i_size): curve[i] = (curve[i] - 0.5) * level + 0.5 -def cie_contrast(r, g = None, b = None): +def cie_contrast(r, g = ..., b = ...): ''' Apply contrast correction on the colour curves using CIE xyY - @param r:float The contrast parameter for the red curve - @param g:float? The contrast parameter for the green curve, defaults to `r` if `None` - @param b:float? The contrast parameter for the blue curve, defaults to `r` if `None` + @param r:float The contrast parameter for the red curve + @param g:float|... The contrast parameter for the green curve, defaults to `r` if `...` + @param b:float|... The contrast parameter for the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g same = r == g == b if any([not level == 1.0 for level in (r, g, b)]): if same: @@ -282,30 +282,32 @@ def cie_contrast(r, g = None, b = None): (_r, _g, b_curve[i]) = ciexyy_to_srgb(x, y, (Y - 0.5) * b + 0.5) -def rgb_brightness(r, g = None, b = None): +def rgb_brightness(r, g = ..., b = ...): ''' Apply brightness correction on the colour curves using sRGB - @param r:float The brightness parameter for the red curve - @param g:float? The brightness parameter for the green curve, defaults to `r` if `None` - @param b:float? The brightness parameter for the blue curve, defaults to `r` if `None` + @param r:float The brightness parameter for the red curve + @param g:float|... The brightness parameter for the green curve, defaults to `r` if `...` + @param b:float|... The brightness parameter for the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = r for (curve, level) in curves(r, g, b): if not level == 1.0: for i in range(i_size): curve[i] *= level -def cie_brightness(r, g = None, b = None): +def cie_brightness(r, g = ..., b = ...): ''' Apply brightness correction on the colour curves using CIE xyY - @param level:float The brightness parameter + @param r:float The brightness parameter for the red curve + @param g:float|... The brightness parameter for the green curve, defaults to `r` if `...` + @param b:float|... The brightness parameter for the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g same = r == g == b if any([not level == 1.0 for level in (r, g, b)]): if same: @@ -320,64 +322,64 @@ def cie_brightness(r, g = None, b = None): (_r, _g, b_curve[i]) = ciexyy_to_srgb(x, y, Y * b) -def linearise(r = True, g = None, b = None): +def linearise(r = True, g = ..., b = ...): ''' Convert the curves from formatted in standard RGB to linear RGB - @param r:bool Whether to convert the red colour curve - @param g:bool? Whether to convert the green colour curve, defaults to `r` if `None` - @param b:bool? Whether to convert the blue colour curve, defaults to `r` if `None` + @param r:bool Whether to convert the red colour curve + @param g:bool|... Whether to convert the green colour curve, defaults to `r` if `...` + @param b:bool|... Whether to convert the blue colour curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for i in range(i_size): sr, sg, sb = r_curve[i], g_curve[i], b_curve[i] (lr, lg, lb) = standard_to_linear(sr, sg, sb) r_curve[i], g_curve[i], b_curve[i] = (lr if r else sr), (lg if g else sg), (lb if b else sb) -def standardise(r = True, g = None, b = None): +def standardise(r = True, g = ..., b = ...): ''' Convert the curves from formatted in linear RGB to standard RGB - @param r:bool Whether to convert the red colour curve - @param g:bool? Whether to convert the green colour curve, defaults to `r` if `None` - @param b:bool? Whether to convert the blue colour curve, defaults to `r` if `None` + @param r:bool Whether to convert the red colour curve + @param g:bool|... Whether to convert the green colour curve, defaults to `r` if `...` + @param b:bool|... Whether to convert the blue colour curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for i in range(i_size): lr, lg, lb = r_curve[i], g_curve[i], b_curve[i] (sr, sg, sb) = linear_to_standard(lr, lg, lb) r_curve[i], g_curve[i], b_curve[i] = (sr if r else lr), (sg if g else lg), (sb if b else lb) -def gamma(r, g = None, b = None): +def gamma(r, g = ..., b = ...): ''' Apply gamma correction on the colour curves - @param r:float The gamma parameter for the red curve - @param g:float? The gamma parameter for the green curve, defaults to `r` if `None` - @param b:float? The gamma parameter for the blue curve, defaults to `r` if `None` + @param r:float The gamma parameter for the red curve + @param g:float|... The gamma parameter for the green curve, defaults to `r` if `...` + @param b:float|... The gamma parameter for the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for (curve, level) in curves(r, g, b): if not level == 1.0: for i in range(i_size): curve[i] **= 1 / level -def negative(r = True, g = None, b = None): +def negative(r = True, g = ..., b = ...): ''' Revese the colour curves (negative image with gamma preservation) - @param r:bool Whether to invert the red curve - @param g:bool? Whether to invert the green curve, defaults to `r` if `None` - @param b:bool? Whether to invert the blue curve, defaults to `r` if `None` + @param r:bool Whether to invert the red curve + @param g:bool|... Whether to invert the green curve, defaults to `r` if `...` + @param b:bool|... Whether to invert the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for (curve, setting) in curves(r, g, b): if setting: for i in range(i_size // 2): @@ -385,32 +387,32 @@ def negative(r = True, g = None, b = None): curve[i], curve[j] = curve[j], curve[i] -def rgb_invert(r = True, g = None, b = None): +def rgb_invert(r = True, g = ..., b = ...): ''' Invert the colour curves (negative image with gamma invertion), using sRGB - @param r:bool Whether to invert the red curve - @param g:bool? Whether to invert the green curve, defaults to `r` if `None` - @param b:bool? Whether to invert the blue curve, defaults to `r` if `None` + @param r:bool Whether to invert the red curve + @param g:bool|... Whether to invert the green curve, defaults to `r` if `...` + @param b:bool|... Whether to invert the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for (curve, setting) in curves(r, g, b): if setting: for i in range(i_size): curve[i] = 1 - curve[i] -def cie_invert(r = True, g = None, b = None): +def cie_invert(r = True, g = ..., b = ...): ''' Invert the colour curves (negative image with gamma invertion), using CIE xyY - @param r:bool Whether to invert the red curve - @param g:bool? Whether to invert the green curve, defaults to `r` if `None` - @param b:bool? Whether to invert the blue curve, defaults to `r` if `None` + @param r:bool Whether to invert the red curve + @param g:bool|... Whether to invert the green curve, defaults to `r` if `...` + @param b:bool|... Whether to invert the blue curve, defaults to `g` if `...` ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g if r or g or b: for i in range(i_size): (x, y, Y) = srgb_to_ciexyy(r_curve[i], g_curve[i], b_curve[i]) @@ -420,7 +422,7 @@ def cie_invert(r = True, g = None, b = None): if b: b_curve[i] = b_ -def sigmoid(r, g, b): +def sigmoid(r, g = ..., b = ...): ''' Apply S-curve correction on the colour curves. This is intended for fine tuning LCD monitors, @@ -430,10 +432,12 @@ def sigmoid(r, g, b): only why to adjust the black point on many LCD monitors. - @param r:float? The sigmoid parameter for the red curve - @param g:float? The sigmoid parameter for the green curve - @param b:float? The sigmoid parameter for the blue curve + @param r:float? The sigmoid parameter for the red curve + @param g:float|...? The sigmoid parameter for the green curve, defaults to `r` if `...` + @param b:float|...? The sigmoid parameter for the blue curve, defaults to `g` if `...` ''' + if g is ...: g = r + if b is ...: b = g for (curve, level) in curves(r, g, b): if level is not None: for i in range(i_size): @@ -443,42 +447,42 @@ def sigmoid(r, g, b): curve[i] = curve[i]; -def rgb_limits(r_min, r_max, g_min = None, g_max = None, b_min = None, b_max = None): +def rgb_limits(r_min, r_max, g_min = ..., g_max = ..., b_min = ..., b_max = ...): ''' Changes the black point and the white point, using sRGB - @param r_min:float The red component value of the black point - @param r_max:float The red component value of the white point - @param g_min:float? The green component value of the black point, defaults to `r_min` - @param g_max:float? The green component value of the white point, defaults to `r_max` - @param b_min:float? The blue component value of the black point, defaults to `r_min` - @param b_max:float? The blue component value of the white point, defaults to `r_max` - ''' - if g_min is None: g_min = r_min - if g_max is None: g_max = r_max - if b_min is None: b_min = r_min - if b_max is None: b_max = r_max + @param r_min:float The red component value of the black point + @param r_max:float The red component value of the white point + @param g_min:float|... The green component value of the black point, defaults to `r_min` + @param g_max:float|... The green component value of the white point, defaults to `r_max` + @param b_min:float|... The blue component value of the black point, defaults to `g_min` + @param b_max:float|... The blue component value of the white point, defaults to `g_max` + ''' + if g_min is ...: g_min = r_min + if g_max is ...: g_max = r_max + if b_min is ...: b_min = g_min + if b_max is ...: b_max = g_max for (curve, (level_min, level_max)) in curves((r_min, r_max), (g_min, g_max), (b_min, b_max)): if (level_min != 0) or (level_max != 1): for i in range(i_size): curve[i] = curve[i] * (level_max - level_min) + level_min -def cie_limits(r_min, r_max, g_min = None, g_max = None, b_min = None, b_max = None): +def cie_limits(r_min, r_max, g_min = ..., g_max = ..., b_min = ..., b_max = ...): ''' Changes the black point and the white point, using CIE xyY - @param r_min:float The red component value of the black point - @param r_max:float The red component value of the white point - @param g_min:float? The green component value of the black point, defaults to `r_min` - @param g_max:float? The green component value of the white point, defaults to `r_max` - @param b_min:float? The blue component value of the black point, defaults to `r_min` - @param b_max:float? The blue component value of the white point, defaults to `r_max` - ''' - if g_min is None: g_min = r_min - if g_max is None: g_max = r_max - if b_min is None: b_min = r_min - if b_max is None: b_max = r_max + @param r_min:float The red component value of the black point + @param r_max:float The red component value of the white point + @param g_min:float|... The green component value of the black point, defaults to `r_min` + @param g_max:float|... The green component value of the white point, defaults to `r_max` + @param b_min:float|... The blue component value of the black point, defaults to `g_min` + @param b_max:float|... The blue component value of the white point, defaults to `g_max` + ''' + if g_min is ...: g_min = r_min + if g_max is ...: g_max = r_max + if b_min is ...: b_min = g_min + if b_max is ...: b_max = g_max same = (r_min == g_min == b_min) and (r_max == g_max == b_max) if any([lvl != 0 for lvl in (r_min, g_min, b_min)]) or any([lvl != 1 for lvl in (r_max, g_max, b_max)]): if same: @@ -497,71 +501,82 @@ def cie_limits(r_min, r_max, g_min = None, g_max = None, b_min = None, b_max = N (_r, _g, b_curve[i]) = ciexyy_to_srgb(x, y, bY) -def manipulate(r, g = None, b = None): +def manipulate(r, g = ..., b = ...): ''' - Manipulate the colour curves using a lambda function + Manipulate the colour curves using a (lambda) function - @param r:(float)?→float Lambda function to manipulate the red colour curve, nothing is done if `None` - @param g:(float)?→float Lambda function to manipulate the green colour curve, defaults to `r` if `None` - @param b:(float)?→float Lambda function to manipulate the blue colour curve, defaults to `r` if `None` + @param r:(float)?→float Function to manipulate the red colour curve + @param g:(float)?→float|... Function to manipulate the green colour curve, defaults to `r` if `...` + @param b:(float)?→float|... Function to manipulate the blue colour curve, defaults to `g` if `...` + + `None` means that nothing is done for that subpixel The lambda functions thats a colour value and maps it to a new colour value. For example, if the red value 0.5 is already mapped to 0.25, then if the function maps 0.25 to 0.5, the red value 0.5 will revert back to being mapped to 0.5. ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g for (curve, f) in curves(r, g, b): if f is not None: for i in range(i_size): curve[i] = f(curve[i]) -def cie_manipulate(r, g = None, b = None): +def cie_manipulate(r, g = ..., b = ...): ''' - Manipulate the colour curves using a lambda function on the CIE xyY colour space + Manipulate the colour curves using a (lambda) function on the CIE xyY colour space + + @param r:(float)?→float Function to manipulate the red colour curve + @param g:(float)?→float|... Function to manipulate the green colour curve, defaults to `r` if `...` + @param b:(float)?→float|... Function to manipulate the blue colour curve, defaults to `g` if `...` - @param r:(float)?→float Lambda function to manipulate the red colour curve, nothing is done if `None` - @param g:(float)?→float Lambda function to manipulate the green colour curve, defaults to `r` if `None` - @param b:(float)?→float Lambda function to manipulate the blue colour curve, defaults to `r` if `None` + `None` means that nothing is done for that subpixel The lambda functions thats a colour value and maps it to a new illumination value. For example, if the value 0.5 is already mapped to 0.25, then if the function maps 0.25 to 0.5, the value 0.5 will revert back to being mapped to 0.5. ''' - if g is None: g = r - if b is None: b = r + if g is ...: g = r + if b is ...: b = g same = (r is g) and (g is b) - if r is not None: - if same: + if same: + if r is not None: for i in range(i_size): (x, y, Y) = srgb_to_ciexyy(r_curve[i], g_curve[i], b_curve[i]) (r_curve[i], g_curve[i], b_curve[i]) = ciexyy_to_srgb(x, y, r(Y)) - else: - for i in range(i_size): - (x, y, Y) = srgb_to_ciexyy(r_curve[i], g_curve[i], b_curve[i]) - (r_curve[i], _g, _b) = ciexyy_to_srgb(x, y, r(Y)) - (_r, g_curve[i], _b) = ciexyy_to_srgb(x, y, g(Y)) - (_r, _g, b_curve[i]) = ciexyy_to_srgb(x, y, b(Y)) + elif any(f is not None for f in (r, g, b)): + for i in range(i_size): + (x, y, Y) = srgb_to_ciexyy(r_curve[i], g_curve[i], b_curve[i]) + if r is not None: (r_curve[i], _g, _b) = ciexyy_to_srgb(x, y, r(Y)) + if g is not None: (_r, g_curve[i], _b) = ciexyy_to_srgb(x, y, g(Y)) + if b is not None: (_r, _g, b_curve[i]) = ciexyy_to_srgb(x, y, b(Y)) -def lower_resolution(rx_colours = None, ry_colours = None, gx_colours = None, gy_colours = None, bx_colours = None, by_colours = None): +def lower_resolution(rx_colours = None, ry_colours = None, gx_colours = ..., gy_colours = ..., bx_colours = ..., by_colours = ...): ''' Emulates low colour resolution - @param rx_colours:int? The number of colours to emulate on the red encoding axis, `i_size` if `None` - @param ry_colours:int? The number of colours to emulate on the red output axis, `o_size` if `None` - @param gx_colours:int? The number of colours to emulate on the green encoding axis, `rx_colours` of `None` - @param gy_colours:int? The number of colours to emulate on the green output axis, `ry_colours` if `None` - @param bx_colours:int? The number of colours to emulate on the blue encoding axis, `rx_colours` if `None` - @param by_colours:int? The number of colours to emulate on the blue output axis, `rg_colours` if `None` + @param rx_colours:int? The number of colours to emulate on the red encoding axis + @param ry_colours:int? The number of colours to emulate on the red output axis + @param gx_colours:int|...? The number of colours to emulate on the green encoding axis, `rx_colours` if `...` + @param gy_colours:int|...? The number of colours to emulate on the green output axis, `ry_colours` if `...` + @param bx_colours:int|...? The number of colours to emulate on the blue encoding axis, `gx_colours` if `...` + @param by_colours:int|...? The number of colours to emulate on the blue output axis, `gy_colours` if `...` + + Where `None` is used the default value will be used, for *x_colours:es that is `i_size`, + and for *y_colours:es that is `o_size` ''' + if gx_colours is ...: gx_colours = rx_colours + if gy_colours is ...: gy_colours = ry_colours + if bx_colours is ...: bx_colours = gx_colours + if by_colours is ...: by_colours = gy_colours if rx_colours is None: rx_colours = i_size if ry_colours is None: ry_colours = o_size - if gx_colours is None: gx_colours = rx_colours - if gy_colours is None: gy_colours = ry_colours - if bx_colours is None: bx_colours = rx_colours - if by_colours is None: by_colours = ry_colours + if gx_colours is None: gx_colours = i_size + if gy_colours is None: gy_colours = o_size + if bx_colours is None: bx_colours = i_size + if by_colours is None: by_colours = o_size r_colours = (rx_colours, ry_colours) g_colours = (gx_colours, gy_colours) b_colours = (bx_colours, by_colours) @@ -593,15 +608,17 @@ def start_over(): b_curve[i] = v -def clip(r = True, g = None, b = None): +def clip(r = True, g = ..., b = ...): ''' Clip all values below the actual minimum and above actual maximums - @param r:bool Whether to clip the red colour curve - @param g:bool? Whether to clip the green colour curve, defaults to `r` if `None` - @param b:bool? Whether to clip the blue colour curve, defaults to `r` if `None` + @param r:bool Whether to clip the red colour curve + @param g:bool|... Whether to clip the green colour curve, defaults to `r` if `...` + @param b:bool|... Whether to clip the blue colour curve, defaults to `g` if `...` ''' - for curve, action in curves(r, r if g is None else g, r if b is None else b): + if g is ...: g = r + if b is ...: b = g + for curve, action in curves(r, g, b): if action: for i in range(i_size): curve[i] = min(max(0.0, curve[i]), 1.0) -- cgit v1.2.3-70-g09d2