2009-08-26 22:51:03 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package image
|
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
// TODO(nigeltao): Think about how floating-point color models work.
|
2009-08-26 22:51:03 -06:00
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
// All Colors can convert themselves, with a possible loss of precision, to 128-bit alpha-premultiplied RGBA.
|
2009-08-26 22:51:03 -06:00
|
|
|
type Color interface {
|
|
|
|
RGBA() (r, g, b, a uint32);
|
|
|
|
}
|
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
// An RGBAColor represents a traditional 32-bit alpha-premultiplied color, having 8 bits for each of red, green, blue and alpha.
|
2009-08-26 22:51:03 -06:00
|
|
|
type RGBAColor struct {
|
|
|
|
R, G, B, A uint8;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c RGBAColor) RGBA() (r, g, b, a uint32) {
|
|
|
|
r = uint32(c.R);
|
|
|
|
r |= r<<8;
|
|
|
|
r |= r<<16;
|
|
|
|
g = uint32(c.G);
|
|
|
|
g |= g<<8;
|
|
|
|
g |= g<<16;
|
|
|
|
b = uint32(c.B);
|
|
|
|
b |= b<<8;
|
|
|
|
b |= b<<16;
|
|
|
|
a = uint32(c.A);
|
|
|
|
a |= a<<8;
|
|
|
|
a |= a<<16;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
// An RGBA64Color represents a 64-bit alpha-premultiplied color, having 16 bits for each of red, green, blue and alpha.
|
2009-08-26 22:51:03 -06:00
|
|
|
type RGBA64Color struct {
|
|
|
|
R, G, B, A uint16;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
|
|
|
|
r = uint32(c.R);
|
|
|
|
r |= r<<16;
|
|
|
|
g = uint32(c.G);
|
|
|
|
g |= g<<16;
|
|
|
|
b = uint32(c.B);
|
|
|
|
b |= b<<16;
|
|
|
|
a = uint32(c.A);
|
|
|
|
a |= a<<16;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
// An NRGBAColor represents a non-alpha-premultiplied 32-bit color.
|
|
|
|
type NRGBAColor struct {
|
|
|
|
R, G, B, A uint8;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
|
|
|
|
r = uint32(c.R);
|
|
|
|
r |= r<<8;
|
|
|
|
r *= uint32(c.A);
|
|
|
|
r /= 0xff;
|
|
|
|
r |= r<<16;
|
|
|
|
g = uint32(c.G);
|
|
|
|
g |= g<<8;
|
|
|
|
g *= uint32(c.A);
|
|
|
|
g /= 0xff;
|
|
|
|
g |= g<<16;
|
|
|
|
b = uint32(c.B);
|
|
|
|
b |= b<<8;
|
|
|
|
b *= uint32(c.A);
|
|
|
|
b /= 0xff;
|
|
|
|
b |= b<<16;
|
|
|
|
a = uint32(c.A);
|
|
|
|
a |= a<<8;
|
|
|
|
a |= a<<16;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// An NRGBA64Color represents a non-alpha-premultiplied 64-bit color, having 16 bits for each of red, green, blue and alpha.
|
|
|
|
type NRGBA64Color struct {
|
|
|
|
R, G, B, A uint16;
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
|
|
|
|
r = uint32(c.R);
|
|
|
|
r *= uint32(c.A);
|
|
|
|
r /= 0xffff;
|
|
|
|
r |= r<<16;
|
|
|
|
g = uint32(c.G);
|
|
|
|
g *= uint32(c.A);
|
|
|
|
g /= 0xffff;
|
|
|
|
g |= g<<16;
|
|
|
|
b = uint32(c.B);
|
|
|
|
b *= uint32(c.A);
|
|
|
|
b /= 0xffff;
|
|
|
|
b |= b<<16;
|
|
|
|
a = uint32(c.A);
|
|
|
|
a |= a<<8;
|
|
|
|
a |= a<<16;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-26 22:51:03 -06:00
|
|
|
// A ColorModel can convert foreign Colors, with a possible loss of precision, to a Color
|
|
|
|
// from its own color model.
|
|
|
|
type ColorModel interface {
|
|
|
|
Convert(c Color) Color;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The ColorModelFunc type is an adapter to allow the use of an ordinary
|
|
|
|
// color conversion function as a ColorModel. If f is such a function,
|
|
|
|
// ColorModelFunc(f) is a ColorModel object that invokes f to implement
|
|
|
|
// the conversion.
|
|
|
|
type ColorModelFunc func(Color) Color
|
|
|
|
|
|
|
|
func (f ColorModelFunc) Convert(c Color) Color {
|
|
|
|
return f(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
func toRGBAColor(c Color) Color {
|
|
|
|
if _, ok := c.(RGBAColor); ok { // no-op conversion
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
r, g, b, a := c.RGBA();
|
|
|
|
return RGBAColor{ uint8(r>>24), uint8(g>>24), uint8(b>>24), uint8(a>>24) };
|
|
|
|
}
|
|
|
|
|
|
|
|
func toRGBA64Color(c Color) Color {
|
|
|
|
if _, ok := c.(RGBA64Color); ok { // no-op conversion
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
r, g, b, a := c.RGBA();
|
|
|
|
return RGBA64Color{ uint16(r>>16), uint16(g>>16), uint16(b>>16), uint16(a>>16) };
|
|
|
|
}
|
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
func toNRGBAColor(c Color) Color {
|
|
|
|
if _, ok := c.(NRGBAColor); ok { // no-op conversion
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
r, g, b, a := c.RGBA();
|
|
|
|
a >>= 16;
|
|
|
|
if a == 0xffff {
|
|
|
|
return NRGBAColor{ uint8(r>>24), uint8(g>>24), uint8(b>>24), 0xff };
|
|
|
|
}
|
|
|
|
if a == 0 {
|
|
|
|
return NRGBAColor{ 0, 0, 0, 0 };
|
|
|
|
}
|
|
|
|
r >>= 16;
|
|
|
|
g >>= 16;
|
|
|
|
b >>= 16;
|
|
|
|
// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
|
|
|
|
r = (r * 0xffff) / a;
|
|
|
|
g = (g * 0xffff) / a;
|
|
|
|
b = (b * 0xffff) / a;
|
|
|
|
return NRGBAColor{ uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8) };
|
|
|
|
}
|
|
|
|
|
|
|
|
func toNRGBA64Color(c Color) Color {
|
|
|
|
if _, ok := c.(NRGBA64Color); ok { // no-op conversion
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
r, g, b, a := c.RGBA();
|
|
|
|
a >>= 16;
|
|
|
|
r >>= 16;
|
|
|
|
g >>= 16;
|
|
|
|
b >>= 16;
|
|
|
|
if a == 0xffff {
|
|
|
|
return NRGBA64Color{ uint16(r), uint16(g), uint16(b), 0xffff };
|
|
|
|
}
|
|
|
|
if a == 0 {
|
|
|
|
return NRGBA64Color{ 0, 0, 0, 0 };
|
|
|
|
}
|
|
|
|
// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
|
|
|
|
r = (r * 0xffff) / a;
|
|
|
|
g = (g * 0xffff) / a;
|
|
|
|
b = (b * 0xffff) / a;
|
|
|
|
return NRGBA64Color{ uint16(r), uint16(g), uint16(b), uint16(a) };
|
|
|
|
}
|
|
|
|
|
2009-08-26 22:51:03 -06:00
|
|
|
// The ColorModel associated with RGBAColor.
|
|
|
|
var RGBAColorModel ColorModel = ColorModelFunc(toRGBAColor);
|
|
|
|
|
|
|
|
// The ColorModel associated with RGBA64Color.
|
|
|
|
var RGBA64ColorModel ColorModel = ColorModelFunc(toRGBA64Color);
|
|
|
|
|
2009-09-10 22:33:44 -06:00
|
|
|
// The ColorModel associated with NRGBAColor.
|
|
|
|
var NRGBAColorModel ColorModel = ColorModelFunc(toNRGBAColor);
|
|
|
|
|
|
|
|
// The ColorModel associated with NRGBA64Color.
|
|
|
|
var NRGBA64ColorModel ColorModel = ColorModelFunc(toNRGBA64Color);
|
|
|
|
|