1 package imagefn 2 3 import ( 4 "image" 5 "image/color" 6 ) 7 8 type flipX struct { 9 image.Image 10 dx int 11 } 12 13 type flipXSet struct { 14 flipX 15 setter 16 } 17 18 func FlipX(i image.Image) image.Image { 19 switch i := i.(type) { 20 case *flipX: 21 return i.Image 22 case *flipXSet: 23 return i.Image 24 case *flipY: 25 return Rotate180(i.Image) 26 case *flipYSet: 27 return Rotate180(i.Image) 28 case *rotate180: 29 return FlipY(i.Image) 30 case *rotate180Set: 31 return FlipY(i.Image) 32 } 33 b := i.Bounds() 34 f := flipX{ 35 Image: i, 36 dx: b.Max.X + b.Min.X, 37 } 38 if s, ok := i.(setter); ok { 39 return &flipXSet{ 40 flipX: f, 41 setter: s, 42 } 43 } 44 return &f 45 } 46 47 func (f *flipX) At(x, y int) color.Color { 48 return f.Image.At(f.dx-x-1, y) 49 } 50 51 func (f *flipX) SubImage(r image.Rectangle) image.Image { 52 r.Min.X = f.dx - r.Min.X 53 r.Max.X = f.dx - r.Max.X 54 return FlipX(SubImage(f.Image, r.Canon())) 55 } 56 57 func (f *flipXSet) Set(x, y int, c color.Color) { 58 f.setter.Set(f.dx-x-1, y, c) 59 } 60 61 type flipY struct { 62 image.Image 63 dy int 64 } 65 66 type flipYSet struct { 67 flipY 68 setter 69 } 70 71 func FlipY(i image.Image) image.Image { 72 switch i := i.(type) { 73 case *flipX: 74 return Rotate180(i.Image) 75 case *flipXSet: 76 return Rotate180(i.Image) 77 case *flipY: 78 return i.Image 79 case *flipYSet: 80 return i.Image 81 case *rotate180: 82 return FlipX(i.Image) 83 case *rotate180Set: 84 return FlipX(i.Image) 85 } 86 b := i.Bounds() 87 f := flipY{ 88 Image: i, 89 dy: b.Max.Y + b.Min.Y, 90 } 91 if s, ok := i.(setter); ok { 92 return &flipYSet{ 93 flipY: f, 94 setter: s, 95 } 96 } 97 return &f 98 } 99 100 func (f *flipY) At(x, y int) color.Color { 101 return f.Image.At(x, f.dy-y-1) 102 } 103 104 func (f *flipY) SubImage(r image.Rectangle) image.Image { 105 r.Min.Y = f.dy - r.Min.Y 106 r.Max.Y = f.dy - r.Max.Y 107 return FlipY(SubImage(f.Image, r.Canon())) 108 } 109 110 func (f *flipYSet) Set(x, y int, c color.Color) { 111 f.setter.Set(x, f.dy-y-1, c) 112 }