RGBA() (r, g, b, a uint32)
}
-// RGB represents a traditional 24-bit fully opaque color,
-// having 8 bits for each of red, green and blue.
-type RGB struct {
- R, G, B uint8
-}
-
-func (c RGB) RGBA() (r, g, b, a uint32) {
- r = uint32(c.R)
- r |= r << 8
- g = uint32(c.G)
- g |= g << 8
- b = uint32(c.B)
- b |= b << 8
- a = 0xFFFF
- return
-}
-
-// RGB48 represents a 48-bit fully opaque color,
-// having 16 bits for each of red, green and blue.
-type RGB48 struct {
- R, G, B uint16
-}
-
-func (c RGB48) RGBA() (r, g, b, a uint32) {
- return uint32(c.R), uint32(c.G), uint32(c.B), 0xFFFF
-}
-
// RGBA represents a traditional 32-bit alpha-premultiplied color,
// having 8 bits for each of red, green, blue and alpha.
type RGBA struct {
// Models for the standard color types.
var (
- RGBModel Model = ModelFunc(rgbModel)
- RGB48Model Model = ModelFunc(rgb48Model)
RGBAModel Model = ModelFunc(rgbaModel)
RGBA64Model Model = ModelFunc(rgba64Model)
NRGBAModel Model = ModelFunc(nrgbaModel)
Gray16Model Model = ModelFunc(gray16Model)
)
-func rgbModel(c Color) Color {
- if _, ok := c.(RGB); ok {
- return c
- }
- r, g, b, _ := c.RGBA()
- return RGB{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8)}
-}
-
-func rgb48Model(c Color) Color {
- if _, ok := c.(RGB48); ok {
- return c
- }
- r, g, b, _ := c.RGBA()
- return RGB48{uint16(r), uint16(g), uint16(b)}
-}
-
func rgbaModel(c Color) Color {
if _, ok := c.(RGBA); ok {
return c
Image
}
-// RGB is an in-memory image whose At method returns color.RGB values.
-type RGB struct {
- // Pix holds the image's pixels, in R, G, B order. The pixel at
- // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*3].
- Pix []uint8
- // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
- Stride int
- // Rect is the image's bounds.
- Rect Rectangle
-}
-
-func (p *RGB) ColorModel() color.Model { return color.RGBModel }
-
-func (p *RGB) Bounds() Rectangle { return p.Rect }
-
-func (p *RGB) At(x, y int) color.Color {
- if !(Point{x, y}.In(p.Rect)) {
- return color.RGB{}
- }
- i := p.PixOffset(x, y)
- return color.RGB{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2]}
-}
-
-// PixOffset returns the index of the first element of Pix that corresponds to
-// the pixel at (x, y).
-func (p *RGB) PixOffset(x, y int) int {
- return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*3
-}
-
-func (p *RGB) Set(x, y int, c color.Color) {
- if !(Point{x, y}.In(p.Rect)) {
- return
- }
- i := p.PixOffset(x, y)
- c1 := color.RGBModel.Convert(c).(color.RGB)
- p.Pix[i+0] = c1.R
- p.Pix[i+1] = c1.G
- p.Pix[i+2] = c1.B
-}
-
-func (p *RGB) SetRGB(x, y int, c color.RGB) {
- if !(Point{x, y}.In(p.Rect)) {
- return
- }
- i := p.PixOffset(x, y)
- p.Pix[i+0] = c.R
- p.Pix[i+1] = c.G
- p.Pix[i+2] = c.B
-}
-
-// SubImage returns an image representing the portion of the image p visible
-// through r. The returned value shares pixels with the original image.
-func (p *RGB) SubImage(r Rectangle) Image {
- r = r.Intersect(p.Rect)
- // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
- // either r1 or r2 if the intersection is empty. Without explicitly checking for
- // this, the Pix[i:] expression below can panic.
- if r.Empty() {
- return &RGB{}
- }
- i := p.PixOffset(r.Min.X, r.Min.Y)
- return &RGB{
- Pix: p.Pix[i:],
- Stride: p.Stride,
- Rect: r,
- }
-}
-
-// Opaque scans the entire image and reports whether it is fully opaque.
-func (p *RGB) Opaque() bool {
- return true
-}
-
-// NewRGB returns a new RGB with the given bounds.
-func NewRGB(r Rectangle) *RGB {
- w, h := r.Dx(), r.Dy()
- buf := make([]uint8, 3*w*h)
- return &RGB{buf, 3 * w, r}
-}
-
-// RGB48 is an in-memory image whose At method returns color.RGB48 values.
-type RGB48 struct {
- // Pix holds the image's pixels, in R, G, B order and big-endian format. The pixel at
- // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*6].
- Pix []uint8
- // Stride is the Pix stride (in bytes) between vertically adjacent pixels.
- Stride int
- // Rect is the image's bounds.
- Rect Rectangle
-}
-
-func (p *RGB48) ColorModel() color.Model { return color.RGB48Model }
-
-func (p *RGB48) Bounds() Rectangle { return p.Rect }
-
-func (p *RGB48) At(x, y int) color.Color {
- if !(Point{x, y}.In(p.Rect)) {
- return color.RGB48{}
- }
- i := p.PixOffset(x, y)
- return color.RGB48{
- uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
- uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
- uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
- }
-}
-
-// PixOffset returns the index of the first element of Pix that corresponds to
-// the pixel at (x, y).
-func (p *RGB48) PixOffset(x, y int) int {
- return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*6
-}
-
-func (p *RGB48) Set(x, y int, c color.Color) {
- if !(Point{x, y}.In(p.Rect)) {
- return
- }
- i := p.PixOffset(x, y)
- c1 := color.RGB48Model.Convert(c).(color.RGB48)
- p.Pix[i+0] = uint8(c1.R >> 8)
- p.Pix[i+1] = uint8(c1.R)
- p.Pix[i+2] = uint8(c1.G >> 8)
- p.Pix[i+3] = uint8(c1.G)
- p.Pix[i+4] = uint8(c1.B >> 8)
- p.Pix[i+5] = uint8(c1.B)
-}
-
-func (p *RGB48) SetRGB48(x, y int, c color.RGB48) {
- if !(Point{x, y}.In(p.Rect)) {
- return
- }
- i := p.PixOffset(x, y)
- p.Pix[i+0] = uint8(c.R >> 8)
- p.Pix[i+1] = uint8(c.R)
- p.Pix[i+2] = uint8(c.G >> 8)
- p.Pix[i+3] = uint8(c.G)
- p.Pix[i+4] = uint8(c.B >> 8)
- p.Pix[i+5] = uint8(c.B)
-}
-
-// SubImage returns an image representing the portion of the image p visible
-// through r. The returned value shares pixels with the original image.
-func (p *RGB48) SubImage(r Rectangle) Image {
- r = r.Intersect(p.Rect)
- // If r1 and r2 are Rectangles, r1.Intersect(r2) is not guaranteed to be inside
- // either r1 or r2 if the intersection is empty. Without explicitly checking for
- // this, the Pix[i:] expression below can panic.
- if r.Empty() {
- return &RGB48{}
- }
- i := p.PixOffset(r.Min.X, r.Min.Y)
- return &RGB48{
- Pix: p.Pix[i:],
- Stride: p.Stride,
- Rect: r,
- }
-}
-
-// Opaque scans the entire image and reports whether it is fully opaque.
-func (p *RGB48) Opaque() bool {
- return true
-}
-
-// NewRGB48 returns a new RGB48 with the given bounds.
-func NewRGB48(r Rectangle) *RGB48 {
- w, h := r.Dx(), r.Dy()
- pix := make([]uint8, 6*w*h)
- return &RGB48{pix, 6 * w, r}
-}
-
// RGBA is an in-memory image whose At method returns color.RGBA values.
type RGBA struct {
// Pix holds the image's pixels, in R, G, B, A order. The pixel at
func TestImage(t *testing.T) {
testImage := []image{
- NewRGB(Rect(0, 0, 10, 10)),
- NewRGB48(Rect(0, 0, 10, 10)),
NewRGBA(Rect(0, 0, 10, 10)),
NewRGBA64(Rect(0, 0, 10, 10)),
NewNRGBA(Rect(0, 0, 10, 10)),
}
}
testImage := []image{
- NewRGB48(Rect(0, 0, 10, 10)),
NewRGBA64(Rect(0, 0, 10, 10)),
NewNRGBA64(Rect(0, 0, 10, 10)),
NewAlpha16(Rect(0, 0, 10, 10)),