diff --git a/src/pkg/image/color.go b/src/pkg/image/color.go index 8a865a8a0c..c1345c0252 100644 --- a/src/pkg/image/color.go +++ b/src/pkg/image/color.go @@ -103,6 +103,27 @@ func (c Alpha16Color) RGBA() (r, g, b, a uint32) { return a, a, a, a } +// A GrayColor represents an 8-bit grayscale color. +type GrayColor struct { + Y uint8 +} + +func (c GrayColor) RGBA() (r, g, b, a uint32) { + y := uint32(c.Y) + y |= y << 8 + return y, y, y, 0xffff +} + +// A Gray16Color represents a 16-bit grayscale color. +type Gray16Color struct { + Y uint16 +} + +func (c Gray16Color) RGBA() (r, g, b, a uint32) { + y := uint32(c.Y) + return y, y, y, 0xffff +} + // A ColorModel can convert foreign Colors, with a possible loss of precision, // to a Color from its own color model. type ColorModel interface { @@ -187,6 +208,24 @@ func toAlpha16Color(c Color) Color { return Alpha16Color{uint16(a)} } +func toGrayColor(c Color) Color { + if _, ok := c.(GrayColor); ok { + return c + } + r, g, b, _ := c.RGBA() + y := (299*r + 587*g + 114*b + 500) / 1000 + return GrayColor{uint8(y >> 8)} +} + +func toGray16Color(c Color) Color { + if _, ok := c.(Gray16Color); ok { + return c + } + r, g, b, _ := c.RGBA() + y := (299*r + 587*g + 114*b + 500) / 1000 + return Gray16Color{uint16(y)} +} + // The ColorModel associated with RGBAColor. var RGBAColorModel ColorModel = ColorModelFunc(toRGBAColor) @@ -204,3 +243,9 @@ var AlphaColorModel ColorModel = ColorModelFunc(toAlphaColor) // The ColorModel associated with Alpha16Color. var Alpha16ColorModel ColorModel = ColorModelFunc(toAlpha16Color) + +// The ColorModel associated with GrayColor. +var GrayColorModel ColorModel = ColorModelFunc(toGrayColor) + +// The ColorModel associated with Gray16Color. +var Gray16ColorModel ColorModel = ColorModelFunc(toGray16Color) diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go index decf1ce43b..cfe44270c0 100644 --- a/src/pkg/image/image.go +++ b/src/pkg/image/image.go @@ -303,6 +303,78 @@ func NewAlpha16(w, h int) *Alpha16 { return &Alpha16{pix} } +// A Gray is an in-memory image backed by a 2-D slice of GrayColor values. +type Gray struct { + // The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x]. + Pixel [][]GrayColor +} + +func (p *Gray) ColorModel() ColorModel { return GrayColorModel } + +func (p *Gray) Width() int { + if len(p.Pixel) == 0 { + return 0 + } + return len(p.Pixel[0]) +} + +func (p *Gray) Height() int { return len(p.Pixel) } + +func (p *Gray) At(x, y int) Color { return p.Pixel[y][x] } + +func (p *Gray) Set(x, y int, c Color) { p.Pixel[y][x] = toGrayColor(c).(GrayColor) } + +// Opaque scans the entire image and returns whether or not it is fully opaque. +func (p *Gray) Opaque() bool { + return true +} + +// NewGray returns a new Gray with the given width and height. +func NewGray(w, h int) *Gray { + buf := make([]GrayColor, w*h) + pix := make([][]GrayColor, h) + for y := range pix { + pix[y] = buf[w*y : w*(y+1)] + } + return &Gray{pix} +} + +// A Gray16 is an in-memory image backed by a 2-D slice of Gray16Color values. +type Gray16 struct { + // The Pixel field's indices are y first, then x, so that At(x, y) == Pixel[y][x]. + Pixel [][]Gray16Color +} + +func (p *Gray16) ColorModel() ColorModel { return Gray16ColorModel } + +func (p *Gray16) Width() int { + if len(p.Pixel) == 0 { + return 0 + } + return len(p.Pixel[0]) +} + +func (p *Gray16) Height() int { return len(p.Pixel) } + +func (p *Gray16) At(x, y int) Color { return p.Pixel[y][x] } + +func (p *Gray16) Set(x, y int, c Color) { p.Pixel[y][x] = toGray16Color(c).(Gray16Color) } + +// Opaque scans the entire image and returns whether or not it is fully opaque. +func (p *Gray16) Opaque() bool { + return true +} + +// NewGray16 returns a new Gray16 with the given width and height. +func NewGray16(w, h int) *Gray16 { + buf := make([]Gray16Color, w*h) + pix := make([][]Gray16Color, h) + for y := range pix { + pix[y] = buf[w*y : w*(y+1)] + } + return &Gray16{pix} +} + // A PalettedColorModel represents a fixed palette of colors. type PalettedColorModel []Color diff --git a/src/pkg/image/names.go b/src/pkg/image/names.go index 0b621cff53..a5b4e48f4b 100644 --- a/src/pkg/image/names.go +++ b/src/pkg/image/names.go @@ -4,29 +4,11 @@ package image -// Colors from the HTML 4.01 specification: http://www.w3.org/TR/REC-html40/types.html#h-6.5 -// These names do not necessarily match those from other lists, such as the X11 color names. var ( - Aqua = ColorImage{RGBAColor{0x00, 0xff, 0xff, 0xff}} - Black = ColorImage{RGBAColor{0x00, 0x00, 0x00, 0xff}} - Blue = ColorImage{RGBAColor{0x00, 0x00, 0xff, 0xff}} - Fuchsia = ColorImage{RGBAColor{0xff, 0x00, 0xff, 0xff}} - Gray = ColorImage{RGBAColor{0x80, 0x80, 0x80, 0xff}} - Green = ColorImage{RGBAColor{0x00, 0x80, 0x00, 0xff}} - Lime = ColorImage{RGBAColor{0x00, 0xff, 0x00, 0xff}} - Maroon = ColorImage{RGBAColor{0x80, 0x00, 0x00, 0xff}} - Navy = ColorImage{RGBAColor{0x00, 0x00, 0x80, 0xff}} - Olive = ColorImage{RGBAColor{0x80, 0x80, 0x00, 0xff}} - Red = ColorImage{RGBAColor{0xff, 0x00, 0x00, 0xff}} - Purple = ColorImage{RGBAColor{0x80, 0x00, 0x80, 0xff}} - Silver = ColorImage{RGBAColor{0xc0, 0xc0, 0xc0, 0xff}} - Teal = ColorImage{RGBAColor{0x00, 0x80, 0x80, 0xff}} - White = ColorImage{RGBAColor{0xff, 0xff, 0xff, 0xff}} - Yellow = ColorImage{RGBAColor{0xff, 0xff, 0x00, 0xff}} - - // These synonyms are not in HTML 4.01. - Cyan = Aqua - Magenta = Fuchsia + // Black is an opaque black ColorImage. + Black = ColorImage{RGBAColor{0x00, 0x00, 0x00, 0xff}} + // White is an opaque white ColorImage. + White = ColorImage{RGBAColor{0xff, 0xff, 0xff, 0xff}} ) // A ColorImage is a practically infinite-sized Image of uniform Color.