github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/image/color/color.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package color implements a basic color library. 6 package color 7 8 // Color can convert itself to alpha-premultiplied 16-bits per channel RGBA. 9 // The conversion may be lossy. 10 type Color interface { 11 // RGBA returns the alpha-premultiplied red, green, blue and alpha values 12 // for the color. Each value ranges within [0, 0xFFFF], but is represented 13 // by a uint32 so that multiplying by a blend factor up to 0xFFFF will not 14 // overflow. 15 RGBA() (r, g, b, a uint32) 16 } 17 18 // RGBA represents a traditional 32-bit alpha-premultiplied color, 19 // having 8 bits for each of red, green, blue and alpha. 20 type RGBA struct { 21 R, G, B, A uint8 22 } 23 24 func (c RGBA) RGBA() (r, g, b, a uint32) { 25 r = uint32(c.R) 26 r |= r << 8 27 g = uint32(c.G) 28 g |= g << 8 29 b = uint32(c.B) 30 b |= b << 8 31 a = uint32(c.A) 32 a |= a << 8 33 return 34 } 35 36 // RGBA64 represents a 64-bit alpha-premultiplied color, 37 // having 16 bits for each of red, green, blue and alpha. 38 type RGBA64 struct { 39 R, G, B, A uint16 40 } 41 42 func (c RGBA64) RGBA() (r, g, b, a uint32) { 43 return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A) 44 } 45 46 // NRGBA represents a non-alpha-premultiplied 32-bit color. 47 type NRGBA struct { 48 R, G, B, A uint8 49 } 50 51 func (c NRGBA) RGBA() (r, g, b, a uint32) { 52 r = uint32(c.R) 53 r |= r << 8 54 r *= uint32(c.A) 55 r /= 0xff 56 g = uint32(c.G) 57 g |= g << 8 58 g *= uint32(c.A) 59 g /= 0xff 60 b = uint32(c.B) 61 b |= b << 8 62 b *= uint32(c.A) 63 b /= 0xff 64 a = uint32(c.A) 65 a |= a << 8 66 return 67 } 68 69 // NRGBA64 represents a non-alpha-premultiplied 64-bit color, 70 // having 16 bits for each of red, green, blue and alpha. 71 type NRGBA64 struct { 72 R, G, B, A uint16 73 } 74 75 func (c NRGBA64) RGBA() (r, g, b, a uint32) { 76 r = uint32(c.R) 77 r *= uint32(c.A) 78 r /= 0xffff 79 g = uint32(c.G) 80 g *= uint32(c.A) 81 g /= 0xffff 82 b = uint32(c.B) 83 b *= uint32(c.A) 84 b /= 0xffff 85 a = uint32(c.A) 86 return 87 } 88 89 // Alpha represents an 8-bit alpha color. 90 type Alpha struct { 91 A uint8 92 } 93 94 func (c Alpha) RGBA() (r, g, b, a uint32) { 95 a = uint32(c.A) 96 a |= a << 8 97 return a, a, a, a 98 } 99 100 // Alpha16 represents a 16-bit alpha color. 101 type Alpha16 struct { 102 A uint16 103 } 104 105 func (c Alpha16) RGBA() (r, g, b, a uint32) { 106 a = uint32(c.A) 107 return a, a, a, a 108 } 109 110 // Gray represents an 8-bit grayscale color. 111 type Gray struct { 112 Y uint8 113 } 114 115 func (c Gray) RGBA() (r, g, b, a uint32) { 116 y := uint32(c.Y) 117 y |= y << 8 118 return y, y, y, 0xffff 119 } 120 121 // Gray16 represents a 16-bit grayscale color. 122 type Gray16 struct { 123 Y uint16 124 } 125 126 func (c Gray16) RGBA() (r, g, b, a uint32) { 127 y := uint32(c.Y) 128 return y, y, y, 0xffff 129 } 130 131 // Model can convert any Color to one from its own color model. The conversion 132 // may be lossy. 133 type Model interface { 134 Convert(c Color) Color 135 } 136 137 // ModelFunc returns a Model that invokes f to implement the conversion. 138 func ModelFunc(f func(Color) Color) Model { 139 // Note: using *modelFunc as the implementation 140 // means that callers can still use comparisons 141 // like m == RGBAModel. This is not possible if 142 // we use the func value directly, because funcs 143 // are no longer comparable. 144 return &modelFunc{f} 145 } 146 147 type modelFunc struct { 148 f func(Color) Color 149 } 150 151 func (m *modelFunc) Convert(c Color) Color { 152 return m.f(c) 153 } 154 155 // Models for the standard color types. 156 var ( 157 RGBAModel Model = ModelFunc(rgbaModel) 158 RGBA64Model Model = ModelFunc(rgba64Model) 159 NRGBAModel Model = ModelFunc(nrgbaModel) 160 NRGBA64Model Model = ModelFunc(nrgba64Model) 161 AlphaModel Model = ModelFunc(alphaModel) 162 Alpha16Model Model = ModelFunc(alpha16Model) 163 GrayModel Model = ModelFunc(grayModel) 164 Gray16Model Model = ModelFunc(gray16Model) 165 ) 166 167 func rgbaModel(c Color) Color { 168 if _, ok := c.(RGBA); ok { 169 return c 170 } 171 r, g, b, a := c.RGBA() 172 return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)} 173 } 174 175 func rgba64Model(c Color) Color { 176 if _, ok := c.(RGBA64); ok { 177 return c 178 } 179 r, g, b, a := c.RGBA() 180 return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} 181 } 182 183 func nrgbaModel(c Color) Color { 184 if _, ok := c.(NRGBA); ok { 185 return c 186 } 187 r, g, b, a := c.RGBA() 188 if a == 0xffff { 189 return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff} 190 } 191 if a == 0 { 192 return NRGBA{0, 0, 0, 0} 193 } 194 // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a. 195 r = (r * 0xffff) / a 196 g = (g * 0xffff) / a 197 b = (b * 0xffff) / a 198 return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)} 199 } 200 201 func nrgba64Model(c Color) Color { 202 if _, ok := c.(NRGBA64); ok { 203 return c 204 } 205 r, g, b, a := c.RGBA() 206 if a == 0xffff { 207 return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff} 208 } 209 if a == 0 { 210 return NRGBA64{0, 0, 0, 0} 211 } 212 // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a. 213 r = (r * 0xffff) / a 214 g = (g * 0xffff) / a 215 b = (b * 0xffff) / a 216 return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)} 217 } 218 219 func alphaModel(c Color) Color { 220 if _, ok := c.(Alpha); ok { 221 return c 222 } 223 _, _, _, a := c.RGBA() 224 return Alpha{uint8(a >> 8)} 225 } 226 227 func alpha16Model(c Color) Color { 228 if _, ok := c.(Alpha16); ok { 229 return c 230 } 231 _, _, _, a := c.RGBA() 232 return Alpha16{uint16(a)} 233 } 234 235 func grayModel(c Color) Color { 236 if _, ok := c.(Gray); ok { 237 return c 238 } 239 r, g, b, _ := c.RGBA() 240 y := (299*r + 587*g + 114*b + 500) / 1000 241 return Gray{uint8(y >> 8)} 242 } 243 244 func gray16Model(c Color) Color { 245 if _, ok := c.(Gray16); ok { 246 return c 247 } 248 r, g, b, _ := c.RGBA() 249 y := (299*r + 587*g + 114*b + 500) / 1000 250 return Gray16{uint16(y)} 251 } 252 253 // Palette is a palette of colors. 254 type Palette []Color 255 256 // Convert returns the palette color closest to c in Euclidean R,G,B space. 257 func (p Palette) Convert(c Color) Color { 258 if len(p) == 0 { 259 return nil 260 } 261 return p[p.Index(c)] 262 } 263 264 // Index returns the index of the palette color closest to c in Euclidean 265 // R,G,B space. 266 func (p Palette) Index(c Color) int { 267 // A batch version of this computation is in image/draw/draw.go. 268 269 cr, cg, cb, _ := c.RGBA() 270 ret, bestSSD := 0, uint32(1<<32-1) 271 for i, v := range p { 272 vr, vg, vb, _ := v.RGBA() 273 // We shift by 1 bit to avoid potential uint32 overflow in 274 // sum-squared-difference. 275 delta := (int32(cr) - int32(vr)) >> 1 276 ssd := uint32(delta * delta) 277 delta = (int32(cg) - int32(vg)) >> 1 278 ssd += uint32(delta * delta) 279 delta = (int32(cb) - int32(vb)) >> 1 280 ssd += uint32(delta * delta) 281 if ssd < bestSSD { 282 if ssd == 0 { 283 return i 284 } 285 ret, bestSSD = i, ssd 286 } 287 } 288 return ret 289 } 290 291 // Standard colors. 292 var ( 293 Black = Gray16{0} 294 White = Gray16{0xffff} 295 Transparent = Alpha16{0} 296 Opaque = Alpha16{0xffff} 297 )