1/*Package adjust provides basic color correction functions.*/
2package adjust
3
4import (
5	"image"
6	"image/color"
7	"math"
8
9	"github.com/anthonynsimon/bild/math/f64"
10	"github.com/anthonynsimon/bild/util"
11)
12
13// Brightness returns a copy of the image with the adjusted brightness.
14// Change is the normalized amount of change to be applied (range -1.0 to 1.0).
15func Brightness(src image.Image, change float64) *image.RGBA {
16	lookup := make([]uint8, 256)
17
18	for i := 0; i < 256; i++ {
19		lookup[i] = uint8(f64.Clamp(float64(i)*(1+change), 0, 255))
20	}
21
22	fn := func(c color.RGBA) color.RGBA {
23		return color.RGBA{lookup[c.R], lookup[c.G], lookup[c.B], c.A}
24	}
25
26	img := Apply(src, fn)
27
28	return img
29}
30
31// Gamma returns a gamma corrected copy of the image. Provided gamma param must be larger than 0.
32func Gamma(src image.Image, gamma float64) *image.RGBA {
33	gamma = math.Max(0.00001, gamma)
34
35	lookup := make([]uint8, 256)
36
37	for i := 0; i < 256; i++ {
38		lookup[i] = uint8(f64.Clamp(math.Pow(float64(i)/255, 1.0/gamma)*255, 0, 255))
39	}
40
41	fn := func(c color.RGBA) color.RGBA {
42		return color.RGBA{lookup[c.R], lookup[c.G], lookup[c.B], c.A}
43	}
44
45	img := Apply(src, fn)
46
47	return img
48}
49
50// Contrast returns a copy of the image with its difference in high and low values adjusted by the change param.
51// Change is the normalized amount of change to be applied, in the range of -1.0 to 1.0.
52// If Change is set to 0.0, then the values remain the same, if it's set to 0.5, then all values will be moved 50% away from the middle value.
53func Contrast(src image.Image, change float64) *image.RGBA {
54	lookup := make([]uint8, 256)
55
56	for i := 0; i < 256; i++ {
57		lookup[i] = uint8(f64.Clamp(((((float64(i)/255)-0.5)*(1+change))+0.5)*255, 0, 255))
58	}
59
60	fn := func(c color.RGBA) color.RGBA {
61		return color.RGBA{lookup[c.R], lookup[c.G], lookup[c.B], c.A}
62	}
63
64	img := Apply(src, fn)
65
66	return img
67}
68
69// Hue adjusts the overall hue of the provided image and returns the result.
70// Parameter change is the amount of change to be applied and is of the range
71// -360 to 360. It corresponds to the hue angle in the HSL color model.
72func Hue(img image.Image, change int) *image.RGBA {
73	fn := func(c color.RGBA) color.RGBA {
74		h, s, l := util.RGBToHSL(c)
75		h = float64((int(h) + change) % 360)
76		outColor := util.HSLToRGB(h, s, l)
77		outColor.A = c.A
78		return outColor
79	}
80
81	return Apply(img, fn)
82}
83
84// Saturation adjusts the saturation of the image and returns the result.
85// Parameter change is the amount of change to be applied and is of the range
86// -1.0 to 1.0 (-1.0 being -100% and 1.0 being 100%).
87func Saturation(img image.Image, change float64) *image.RGBA {
88	fn := func(c color.RGBA) color.RGBA {
89		h, s, l := util.RGBToHSL(c)
90		s = f64.Clamp(s*(1+change), 0.0, 1.0)
91		outColor := util.HSLToRGB(h, s, l)
92		outColor.A = c.A
93		return outColor
94	}
95
96	return Apply(img, fn)
97}
98