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  }