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  }