-
-
Notifications
You must be signed in to change notification settings - Fork 15
/
color_spaces.go
51 lines (45 loc) · 1.45 KB
/
color_spaces.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package dither
import (
"image/color"
"math"
)
// linearize1 linearizes an R, G, or B channel value from an sRGB color.
// Must be in the range [0, 1].
func linearize1(v float64) float64 {
if v <= 0.04045 {
return v / 12.92
}
return math.Pow((v+0.055)/1.055, 2.4)
}
func linearize65535(i uint16) uint16 {
v := float64(i) / 65535.0
return uint16(math.RoundToEven(linearize1(v) * 65535.0))
}
func linearize255to65535(i uint8) uint16 {
v := float64(i) / 255.0
return uint16(math.RoundToEven(linearize1(v) * 65535.0))
}
// toLinearRGB converts a non-linear sRGB color to a linear RGB color space.
// RGB values are taken directly and alpha value is ignored, so this will not
// handle non-opaque colors properly.
func toLinearRGB(c color.Color) (uint16, uint16, uint16) {
// Optimize for different color types
switch v := c.(type) {
case color.Gray:
g := linearize255to65535(v.Y)
return g, g, g
case color.Gray16:
g := linearize65535(v.Y)
return g, g, g
case color.NRGBA:
return linearize255to65535(v.R), linearize255to65535(v.G), linearize255to65535(v.B)
case color.NRGBA64:
return linearize65535(v.R), linearize65535(v.G), linearize65535(v.B)
case color.RGBA:
return linearize255to65535(v.R), linearize255to65535(v.G), linearize255to65535(v.B)
case color.RGBA64:
return linearize65535(v.R), linearize65535(v.G), linearize65535(v.B)
}
r, g, b, _ := c.RGBA()
return linearize65535(uint16(r)), linearize65535(uint16(g)), linearize65535(uint16(b))
}