package main import ( "image" "image/color" "image/draw" "image/png" "os" ) type XORMask struct { dst, src image.Image } func (m XORMask) ColorModel() color.Model { return color.Gray16Model } func (m XORMask) Bounds() image.Rectangle { return m.dst.Bounds() } func (m XORMask) At(x, y int) color.Color { srcColor := m.src.At(x, y) dstColor := m.dst.At(x, y) if ((dstColor == color.Black) || (srcColor == color.Black)) && !((dstColor == color.Black) && (srcColor == color.Black)) { return color.Black } return color.White } func main() { img, err := png.Decode(os.Stdin) if err != nil { panic(err) } grayImg := image.NewGray16(img.Bounds()) for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { c := img.At(x, y) grayImg.Set(x, y, color.Gray16Model.Convert(c)) } } canvas := image.NewRGBA(img.Bounds()) circle := Circles(canvas.Bounds(), canvas.Bounds().Dy()/6) for i := 0; i < 24; i++ { c := <-circle draw.Draw(canvas, c.Bounds(), xor{c, canvas}, c.Bounds().Min, draw.Src) } err = png.Encode( os.Stdout, XORMask{ grayImg, BlackAndWhite{ Exchange{ canvas, }, }, }, ) if err != nil { panic(err) } }