9fans.net/go@v0.0.5/draw/pix.go (about) 1 package draw 2 3 import "fmt" 4 5 // A Color represents an RGBA value, 8 bits per element: 0xRRGGBBAA. 6 // 7 // The element values correspond to illumination, 8 // so 0x00000000 is transparent, 0x000000FF is opaque black, 9 // 0xFFFFFFFF is opaque white, 0xFF0000FF is opaque red, and so on. 10 // 11 // The R, G, B values have been pre-multiplied by A (alpha). 12 // For example, a 50% red is 0x7F00007F not 0xFF00007F. 13 // See also the WithAlpha method. 14 type Color uint32 15 16 // RGBA returns 16-bit r, g, b, a values for the color c, 17 // implementing the image/color package's Color interface. 18 func (c Color) RGBA() (r, g, b, a uint32) { 19 r = uint32(c >> 24) 20 g = uint32(c>>16) & 0xFF 21 b = uint32(c>>8) & 0xFF 22 a = uint32(c) & 0xFF 23 return r | r<<8, g | g<<8, b | b<<8, a | a<<8 24 } 25 26 const ( 27 Transparent Color = 0x00000000 28 Opaque Color = 0xFFFFFFFF 29 Black Color = 0x000000FF 30 White Color = 0xFFFFFFFF 31 Red Color = 0xFF0000FF 32 Green Color = 0x00FF00FF 33 Blue Color = 0x0000FFFF 34 Cyan Color = 0x00FFFFFF 35 Magenta Color = 0xFF00FFFF 36 Yellow Color = 0xFFFF00FF 37 PaleYellow Color = 0xFFFFAAFF 38 DarkYellow Color = 0xEEEE9EFF 39 DarkGreen Color = 0x448844FF 40 PaleGreen Color = 0xAAFFAAFF 41 MedGreen Color = 0x88CC88FF 42 DarkBlue Color = 0x000055FF 43 PaleBlueGreen Color = 0xAAFFFFFF 44 PaleBlue Color = 0x0000BBFF 45 BlueGreen Color = 0x008888FF 46 GreyGreen Color = 0x55AAAAFF 47 PaleGreyGreen Color = 0x9EEEEEFF 48 YellowGreen Color = 0x99994CFF 49 MedBlue Color = 0x000099FF 50 GreyBlue Color = 0x005DBBFF 51 PaleGreyBlue Color = 0x4993DDFF 52 PurpleBlue Color = 0x8888CCFF 53 54 // NoFill is a special value recognized by AllocImage. 55 NoFill Color = 0xFFFFFF00 56 ) 57 58 // WithAlpha performs the alpha computation for a color, 59 // ignoring its initial alpha value and multiplying the components 60 // by the supplied alpha. For example, Red.WithAlpha(0x7F) 61 // is a 50% red color value. 62 func (c Color) WithAlpha(alpha uint8) Color { 63 r := uint32(c >> 24) 64 g := uint32(c>>16) & 0xFF 65 b := uint32(c>>8) & 0xFF 66 r = (r * uint32(alpha)) / 255 67 g = (g * uint32(alpha)) / 255 68 b = (b * uint32(alpha)) / 255 69 return Color(r<<24 | g<<16 | b<<8 | uint32(alpha)) 70 } 71 72 // Pix represents a pixel format described simple notation: r8g8b8 for RGB24, m8 73 // for color-mapped 8 bits, etc. The representation is 8 bits per channel, 74 // starting at the low end, with each byte represnted as a channel specifier 75 // (CRed etc.) in the high 4 bits and the number of pixels in the low 4 bits. 76 type Pix uint32 77 78 const ( 79 CRed = iota 80 CGreen 81 CBlue 82 CGrey 83 CAlpha 84 CMap 85 CIgnore 86 NChan 87 ) 88 89 var ( 90 GREY1 Pix = MakePix(CGrey, 1) 91 GREY2 Pix = MakePix(CGrey, 2) 92 GREY4 Pix = MakePix(CGrey, 4) 93 GREY8 Pix = MakePix(CGrey, 8) 94 CMAP8 Pix = MakePix(CMap, 8) 95 RGB15 Pix = MakePix(CIgnore, 1, CRed, 5, CGreen, 5, CBlue, 5) 96 RGB16 = MakePix(CRed, 5, CGreen, 6, CBlue, 5) 97 RGB24 = MakePix(CRed, 8, CGreen, 8, CBlue, 8) 98 BGR24 = MakePix(CBlue, 8, CGreen, 8, CRed, 8) 99 RGBA32 = MakePix(CRed, 8, CGreen, 8, CBlue, 8, CAlpha, 8) 100 ARGB32 = MakePix(CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8) // stupid VGAs 101 ABGR32 = MakePix(CAlpha, 8, CBlue, 8, CGreen, 8, CRed, 8) 102 XRGB32 = MakePix(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8) 103 XBGR32 = MakePix(CIgnore, 8, CBlue, 8, CGreen, 8, CRed, 8) 104 ) 105 106 // MakePix returns a Pix by placing the successive integers into 4-bit nibbles. 107 func MakePix(list ...int) Pix { 108 var p Pix 109 for _, x := range list { 110 p <<= 4 111 p |= Pix(x) 112 } 113 return p 114 } 115 116 // Split returns the succesive integers making up p. 117 // That is, MakePix(p.Split()) == p. 118 // For example, RGB16.Split() is [CRed 5, CGreen, 6, CBlue, 5]. 119 func (p Pix) Split() []int { 120 var list []int 121 for p != 0 { 122 list = append(list, int(p&15), int(p>>4)&15) 123 p >>= 8 124 } 125 for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 { 126 list[i], list[j] = list[j], list[i] 127 } 128 return list 129 } 130 131 // ParsePix is the reverse of String, turning a pixel string such as "r8g8b8" into a Pix value. 132 func ParsePix(s string) (Pix, error) { 133 var p Pix 134 s0 := s 135 if len(s) > 8 { 136 goto Malformed 137 } 138 for ; len(s) > 0; s = s[2:] { 139 if len(s) == 1 { 140 goto Malformed 141 } 142 p <<= 4 143 switch s[0] { 144 default: 145 goto Malformed 146 case 'r': 147 p |= CRed 148 case 'g': 149 p |= CGreen 150 case 'b': 151 p |= CBlue 152 case 'a': 153 p |= CAlpha 154 case 'k': 155 p |= CGrey 156 case 'm': 157 p |= CMap 158 case 'x': 159 p |= CIgnore 160 } 161 p <<= 4 162 if s[1] < '1' || s[1] > '8' { 163 goto Malformed 164 } 165 p |= Pix(s[1] - '0') 166 } 167 return p, nil 168 169 Malformed: 170 return 0, fmt.Errorf("malformed pix descriptor %q", s0) 171 } 172 173 // String prints the pixel format as a string: "r8g8b8" for example. 174 func (p Pix) String() string { 175 var buf [8]byte 176 i := len(buf) 177 if p == 0 { 178 return "0" 179 } 180 for p > 0 { 181 i -= 2 182 buf[i] = "rgbkamxzzzzzzzzz"[(p>>4)&15] 183 buf[i+1] = "0123456789abcdef"[p&15] 184 p >>= 8 185 } 186 return string(buf[i:]) 187 } 188 189 func (p Pix) Depth() int { 190 n := 0 191 for p > 0 { 192 n += int(p & 15) 193 p >>= 8 194 } 195 return n 196 }