1 package imagefn 2 3 import ( 4 "image" 5 "image/color" 6 ) 7 8 type setter interface { 9 Set(int, int, color.Color) 10 } 11 12 type subimage interface { 13 SubImage(image.Rectangle) image.Image 14 } 15 16 func SubImage(i image.Image, r image.Rectangle) image.Image { 17 if si, ok := i.(subimage); ok { 18 return si.SubImage(r) 19 } 20 if s, ok := i.(setter); ok { 21 return &windowSet{ 22 window: window{ 23 Image: i, 24 Rectangle: r, 25 }, 26 setter: s, 27 } 28 } 29 return &window{ 30 Image: i, 31 Rectangle: r, 32 } 33 } 34 35 type window struct { 36 image.Image 37 Rectangle image.Rectangle 38 } 39 40 func (w *window) At(x, y int) color.Color { 41 if !image.Pt(x, y).In(w.Rectangle) { 42 return color.Transparent 43 } 44 return w.Image.At(x, y) 45 } 46 47 func (w *window) Bounds() image.Rectangle { 48 return w.Rectangle 49 } 50 51 func (w *window) SubImage(r image.Rectangle) image.Image { 52 r = r.Intersect(w.Rectangle) 53 return &window{ 54 Image: w.Image, 55 Rectangle: r, 56 } 57 } 58 59 type windowSet struct { 60 window 61 setter 62 } 63 64 func (w *windowSet) Set(x, y int, c color.Color) { 65 if !image.Pt(x, y).In(w.Rectangle) { 66 return 67 } 68 w.setter.Set(x, y, c) 69 }