summaryrefslogtreecommitdiff
path: root/src/pkg/image/image.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/image/image.go')
-rw-r--r--src/pkg/image/image.go170
1 files changed, 136 insertions, 34 deletions
diff --git a/src/pkg/image/image.go b/src/pkg/image/image.go
index 222d21ade..f4c38d28a 100644
--- a/src/pkg/image/image.go
+++ b/src/pkg/image/image.go
@@ -38,26 +38,36 @@ func (p *RGBA) ColorModel() ColorModel { return RGBAColorModel }
func (p *RGBA) Bounds() Rectangle { return p.Rect }
func (p *RGBA) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return RGBAColor{}
}
return p.Pix[y*p.Stride+x]
}
func (p *RGBA) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toRGBAColor(c).(RGBAColor)
}
func (p *RGBA) SetRGBA(x, y int, c RGBAColor) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *RGBA) SubImage(r Rectangle) Image {
+ return &RGBA{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *RGBA) Opaque() bool {
if p.Rect.Empty() {
@@ -97,26 +107,36 @@ func (p *RGBA64) ColorModel() ColorModel { return RGBA64ColorModel }
func (p *RGBA64) Bounds() Rectangle { return p.Rect }
func (p *RGBA64) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return RGBA64Color{}
}
return p.Pix[y*p.Stride+x]
}
func (p *RGBA64) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toRGBA64Color(c).(RGBA64Color)
}
func (p *RGBA64) SetRGBA64(x, y int, c RGBA64Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *RGBA64) SubImage(r Rectangle) Image {
+ return &RGBA64{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *RGBA64) Opaque() bool {
if p.Rect.Empty() {
@@ -156,26 +176,36 @@ func (p *NRGBA) ColorModel() ColorModel { return NRGBAColorModel }
func (p *NRGBA) Bounds() Rectangle { return p.Rect }
func (p *NRGBA) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return NRGBAColor{}
}
return p.Pix[y*p.Stride+x]
}
func (p *NRGBA) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toNRGBAColor(c).(NRGBAColor)
}
func (p *NRGBA) SetNRGBA(x, y int, c NRGBAColor) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *NRGBA) SubImage(r Rectangle) Image {
+ return &NRGBA{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *NRGBA) Opaque() bool {
if p.Rect.Empty() {
@@ -215,26 +245,36 @@ func (p *NRGBA64) ColorModel() ColorModel { return NRGBA64ColorModel }
func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
func (p *NRGBA64) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return NRGBA64Color{}
}
return p.Pix[y*p.Stride+x]
}
func (p *NRGBA64) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toNRGBA64Color(c).(NRGBA64Color)
}
func (p *NRGBA64) SetNRGBA64(x, y int, c NRGBA64Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *NRGBA64) SubImage(r Rectangle) Image {
+ return &NRGBA64{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *NRGBA64) Opaque() bool {
if p.Rect.Empty() {
@@ -274,26 +314,36 @@ func (p *Alpha) ColorModel() ColorModel { return AlphaColorModel }
func (p *Alpha) Bounds() Rectangle { return p.Rect }
func (p *Alpha) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return AlphaColor{}
}
return p.Pix[y*p.Stride+x]
}
-func (p *Alpha) Set(x, y int, c AlphaColor) {
- if !p.Rect.Contains(Point{x, y}) {
+func (p *Alpha) Set(x, y int, c Color) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toAlphaColor(c).(AlphaColor)
}
func (p *Alpha) SetAlpha(x, y int, c AlphaColor) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *Alpha) SubImage(r Rectangle) Image {
+ return &Alpha{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *Alpha) Opaque() bool {
if p.Rect.Empty() {
@@ -333,26 +383,36 @@ func (p *Alpha16) ColorModel() ColorModel { return Alpha16ColorModel }
func (p *Alpha16) Bounds() Rectangle { return p.Rect }
func (p *Alpha16) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return Alpha16Color{}
}
return p.Pix[y*p.Stride+x]
}
func (p *Alpha16) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toAlpha16Color(c).(Alpha16Color)
}
func (p *Alpha16) SetAlpha16(x, y int, c Alpha16Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *Alpha16) SubImage(r Rectangle) Image {
+ return &Alpha16{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *Alpha16) Opaque() bool {
if p.Rect.Empty() {
@@ -392,26 +452,36 @@ func (p *Gray) ColorModel() ColorModel { return GrayColorModel }
func (p *Gray) Bounds() Rectangle { return p.Rect }
func (p *Gray) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return GrayColor{}
}
return p.Pix[y*p.Stride+x]
}
func (p *Gray) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toGrayColor(c).(GrayColor)
}
func (p *Gray) SetGray(x, y int, c GrayColor) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *Gray) SubImage(r Rectangle) Image {
+ return &Gray{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *Gray) Opaque() bool {
return true
@@ -437,26 +507,36 @@ func (p *Gray16) ColorModel() ColorModel { return Gray16ColorModel }
func (p *Gray16) Bounds() Rectangle { return p.Rect }
func (p *Gray16) At(x, y int) Color {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return Gray16Color{}
}
return p.Pix[y*p.Stride+x]
}
func (p *Gray16) Set(x, y int, c Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = toGray16Color(c).(Gray16Color)
}
func (p *Gray16) SetGray16(x, y int, c Gray16Color) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = c
}
+// 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 *Gray16) SubImage(r Rectangle) Image {
+ return &Gray16{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *Gray16) Opaque() bool {
return true
@@ -483,14 +563,19 @@ func (p PalettedColorModel) Convert(c Color) Color {
if len(p) == 0 {
return nil
}
+ return p[p.Index(c)]
+}
+
+// Index returns the index of the palette color closest to c in Euclidean
+// R,G,B space.
+func (p PalettedColorModel) Index(c Color) int {
cr, cg, cb, _ := c.RGBA()
// Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
cr >>= 1
cg >>= 1
cb >>= 1
- result := Color(nil)
- bestSSD := uint32(1<<32 - 1)
- for _, v := range p {
+ ret, bestSSD := 0, uint32(1<<32-1)
+ for i, v := range p {
vr, vg, vb, _ := v.RGBA()
vr >>= 1
vg >>= 1
@@ -498,11 +583,10 @@ func (p PalettedColorModel) Convert(c Color) Color {
dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
ssd := (dr * dr) + (dg * dg) + (db * db)
if ssd < bestSSD {
- bestSSD = ssd
- result = v
+ ret, bestSSD = i, ssd
}
}
- return result
+ return ret
}
// A Paletted is an in-memory image backed by a 2-D slice of uint8 values and a PalettedColorModel.
@@ -524,26 +608,44 @@ func (p *Paletted) At(x, y int) Color {
if len(p.Palette) == 0 {
return nil
}
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return p.Palette[0]
}
return p.Palette[p.Pix[y*p.Stride+x]]
}
+func (p *Paletted) Set(x, y int, c Color) {
+ if !(Point{x, y}.In(p.Rect)) {
+ return
+ }
+ p.Pix[y*p.Stride+x] = uint8(p.Palette.Index(c))
+}
+
func (p *Paletted) ColorIndexAt(x, y int) uint8 {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return 0
}
return p.Pix[y*p.Stride+x]
}
func (p *Paletted) SetColorIndex(x, y int, index uint8) {
- if !p.Rect.Contains(Point{x, y}) {
+ if !(Point{x, y}.In(p.Rect)) {
return
}
p.Pix[y*p.Stride+x] = index
}
+// 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 *Paletted) SubImage(r Rectangle) Image {
+ return &Paletted{
+ Pix: p.Pix,
+ Stride: p.Stride,
+ Rect: p.Rect.Intersect(r),
+ Palette: p.Palette,
+ }
+}
+
// Opaque scans the entire image and returns whether or not it is fully opaque.
func (p *Paletted) Opaque() bool {
for _, c := range p.Palette {