9fans.net/go@v0.0.5/draw/color.go (about) 1 package draw 2 3 import "image/color" 4 5 /* 6 * Support for the Image type so it can satisfy the standard Color and Image interfaces. 7 */ 8 9 // At returns the standard Color value for the pixel at (x, y). 10 // If the location is outside the clipping rectangle, it returns color.Transparent. 11 // This operation does a round trip to the image server and can be expensive. 12 func (i *Image) At(x, y int) color.Color { 13 if !(Point{x, y}.In(i.Clipr)) { 14 return color.Transparent 15 } 16 if i.Repl && !(Point{x, y}.In(i.R)) { 17 // Translate (x, y) to be within i.R. 18 x = (x-i.R.Min.X)%(i.R.Max.X-i.R.Min.X) + i.R.Min.X 19 y = (y-i.R.Min.Y)%(i.R.Max.Y-i.R.Min.Y) + i.R.Min.Y 20 } 21 var buf [4]byte 22 _, err := i.Unload(Rect(x, y, x+1, y+1), buf[:]) 23 if err != nil { 24 println("image.At: error in Unload: ", err.Error()) 25 return color.Transparent // As good a value as any. 26 } 27 // For multi-byte pixels, the ordering is little-endian. 28 // For sub-byte pixels, the ordering is big-endian (0x80 is the first bit). 29 // Three cheers for PCs. 30 switch i.Pix { 31 case GREY1: 32 // CGrey, 1 33 mask := uint8(1 << uint8(7-x&7)) 34 return Gray1{(buf[0] & mask) != 0} 35 case GREY2: 36 // CGrey, 2 37 shift := uint(x&3) << 1 38 // Place pixel at top of word. 39 y := buf[0] << shift 40 y &= 0xC0 41 // Replicate throughout. 42 y |= y >> 2 43 y |= y >> 4 44 return Gray2{y} 45 case GREY4: 46 // CGrey, 4 47 shift := uint(x&1) << 2 48 // Place pixel at top of word. 49 y := buf[0] << shift 50 y &= 0xF0 51 // Replicate throughout. 52 y |= y >> 4 53 return Gray4{y} 54 case GREY8: 55 // CGrey, 8 56 return color.Gray{buf[0]} 57 case CMAP8: 58 // CMap, 8 59 return CMap8{buf[0]} 60 case RGB15: 61 v := uint16(buf[0]) | uint16(buf[1])<<8 62 return CRGB15{v} 63 case RGB16: 64 v := uint16(buf[0]) | uint16(buf[1])<<8 65 return CRGB16{v} 66 case RGB24: 67 // CRed, 8, CGreen, 8, CBlue, 8 68 return color.RGBA{buf[2], buf[1], buf[0], 0xFF} 69 case BGR24: 70 // CBlue, 8, CGreen, 8, CRed, 8 71 return color.RGBA{buf[0], buf[1], buf[2], 0xFF} 72 case RGBA32: 73 // CRed, 8, CGreen, 8, CBlue, 8, CAlpha, 8 74 return color.RGBA{buf[3], buf[2], buf[1], buf[0]} 75 case ARGB32: 76 // CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8 // stupid VGAs 77 return color.RGBA{buf[2], buf[1], buf[0], buf[3]} 78 case ABGR32: 79 // CAlpha, 8, CBlue, 8, CGreen, 8, CRed, 8 80 return color.RGBA{buf[0], buf[1], buf[2], buf[3]} 81 case XRGB32: 82 // CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8 83 return color.RGBA{buf[2], buf[1], buf[0], 0xFF} 84 case XBGR32: 85 // CIgnore, 8, CBlue, 8, CGreen, 8, CRed, 8 86 return color.RGBA{buf[0], buf[1], buf[2], 0xFF} 87 default: 88 panic("unknown color") 89 } 90 } 91 92 func (i *Image) Bounds() Rectangle { 93 return i.Clipr 94 } 95 96 var ( 97 Gray1Model color.Model = color.ModelFunc(gray1Model) 98 Gray2Model color.Model = color.ModelFunc(gray2Model) 99 Gray4Model color.Model = color.ModelFunc(gray4Model) 100 CMap8Model color.Model = color.ModelFunc(cmapModel) 101 CRGB15Model color.Model = color.ModelFunc(crgb15Model) 102 CRGB16Model color.Model = color.ModelFunc(crgb16Model) 103 ) 104 105 // Gray1 represents a 1-bit black/white color. 106 type Gray1 struct { 107 White bool 108 } 109 110 func (c Gray1) RGBA() (r, g, b, a uint32) { 111 if c.White { 112 return 0xffff, 0xffff, 0xffff, 0xffff 113 } 114 return 0, 0, 0, 0xffff 115 } 116 117 func gray1Model(c color.Color) color.Color { 118 if _, ok := c.(Gray1); ok { 119 return c 120 } 121 r, g, b, _ := c.RGBA() 122 y := (299*r + 587*g + 114*b + 500) / 1000 123 if y >= 128 { 124 return color.Gray16{0xFFFF} 125 } 126 return color.Gray16{0} 127 } 128 129 // Gray2 represents a 2-bit grayscale color. 130 type Gray2 struct { 131 Y uint8 132 } 133 134 func (c Gray2) RGBA() (r, g, b, a uint32) { 135 y := uint32(c.Y) >> 6 136 y |= y << 2 137 y |= y << 4 138 y |= y << 8 139 return y, y, y, 0xffff 140 } 141 142 func gray2Model(c color.Color) color.Color { 143 if _, ok := c.(Gray2); ok { 144 return c 145 } 146 r, g, b, _ := c.RGBA() 147 y := (299*r + 587*g + 114*b + 500) / 1000 148 y >>= 6 149 y |= y << 2 150 y |= y << 4 151 y |= y << 8 152 return color.Gray16{uint16(0)} 153 } 154 155 // Gray4 represents a 4-bit grayscale color. 156 type Gray4 struct { 157 Y uint8 158 } 159 160 func (c Gray4) RGBA() (r, g, b, a uint32) { 161 y := uint32(c.Y) >> 4 162 y |= y << 4 163 y |= y << 8 164 return y, y, y, 0xffff 165 } 166 167 func gray4Model(c color.Color) color.Color { 168 if _, ok := c.(Gray4); ok { 169 return c 170 } 171 r, g, b, _ := c.RGBA() 172 y := (299*r + 587*g + 114*b + 500) / 1000 173 y >>= 4 174 y |= y << 4 175 y |= y << 8 176 return color.Gray16{uint16(0)} 177 } 178 179 // CMap8 represents an 8-bit color-mapped color with the standard Plan 9 color map. 180 type CMap8 struct { 181 I uint8 182 } 183 184 func (c CMap8) RGBA() (r, g, b, a uint32) { 185 ri, gi, bi := cmap2rgb(int(c.I)) 186 return uint32(ri), uint32(gi), uint32(bi), 0xffff 187 } 188 189 func cmapModel(c color.Color) color.Color { 190 if _, ok := c.(CMap8); ok { 191 return c 192 } 193 r32, g32, b32, a32 := c.RGBA() 194 // Move to closest color. 195 index := rgb2cmap(int(r32), int(g32), int(b32)) 196 r, g, b := cmap2rgb(index) 197 // Lift alpha if necessary to keep premultiplication invariant. 198 // The color is still in the map (there's no alpha in CMAP8). 199 a := int(a32) 200 if a < r { 201 a = r 202 } 203 if a < g { 204 a = g 205 } 206 if a < b { 207 a = b 208 } 209 return color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)} 210 } 211 212 // CRGB15 represents a 15-bit 5-5-5 RGB color. 213 type CRGB15 struct { 214 // CIgnore, 1, CRed, 5, CGreen, 5, CBlue, 5 215 V uint16 216 } 217 218 func (c CRGB15) RGBA() (r, g, b, a uint32) { 219 // Build a 5-bit value at the top of the low byte of each component. 220 red := (c.V & 0x7C00) >> 7 221 grn := (c.V & 0x03E0) >> 2 222 blu := (c.V & 0x001F) << 3 223 // Duplicate the high bits in the low bits. 224 red |= red >> 5 225 grn |= grn >> 5 226 blu |= blu >> 5 227 // Duplicate the whole value in the high byte. 228 red |= red << 8 229 grn |= grn << 8 230 blu |= blu << 8 231 return uint32(red), uint32(grn), uint32(blu), 0xffff 232 } 233 234 func crgb15Model(c color.Color) color.Color { 235 if _, ok := c.(CRGB15); ok { 236 return c 237 } 238 r, g, b, _ := c.RGBA() 239 r = (r & 0xF800) >> 1 240 g = (g & 0xF800) >> 6 241 b = (b & 0xF800) >> 11 242 return CRGB15{uint16(r | g | b)} 243 } 244 245 // CRGB16 represents a 16-bit 5-6-5 RGB color. 246 type CRGB16 struct { 247 // CRed, 5, CGreen, 6, CBlue, 5 248 V uint16 249 } 250 251 func (c CRGB16) RGBA() (r, g, b, a uint32) { 252 // Build a 5- or 6-bit value at the top of the low byte of each component. 253 red := (c.V & 0xF800) >> 8 254 grn := (c.V & 0x07E0) >> 3 255 blu := (c.V & 0x001F) << 3 256 // Duplicate the high bits in the low bits. 257 red |= red >> 5 258 grn |= grn >> 6 259 blu |= blu >> 5 260 // Duplicate the whole value in the high byte. 261 red |= red << 8 262 grn |= grn << 8 263 blu |= blu << 8 264 return uint32(red), uint32(grn), uint32(blu), 0xffff 265 } 266 267 func crgb16Model(c color.Color) color.Color { 268 if _, ok := c.(CRGB16); ok { 269 return c 270 } 271 r, g, b, _ := c.RGBA() 272 r = (r & 0xF800) 273 g = (g & 0xFC00) >> 5 274 b = (b & 0xF800) >> 11 275 return CRGB15{uint16(r | g | b)} 276 } 277 278 // ColorModel returns the standard color model of the Image. 279 func (i *Image) ColorModel() color.Model { 280 switch i.Pix { 281 case GREY1: 282 return Gray1Model 283 case GREY2: 284 return Gray2Model 285 case GREY4: 286 return Gray4Model 287 case GREY8: 288 return color.GrayModel 289 case CMAP8: 290 return CMap8Model 291 case RGB15: 292 return CRGB15Model 293 case RGB16: 294 return CRGB16Model 295 case RGB24, RGBA32, ARGB32, ABGR32, XRGB32, XBGR32: 296 return color.RGBAModel 297 } 298 panic("unknown image Pix type") 299 }