package downscale import ( "image" "image/color" ) type sub struct { image.Image image.Rectangle } func (sub sub) ColorModel() color.Model { return sub.Image.ColorModel() } func (sub sub) Bounds() image.Rectangle { return sub.Rectangle } func (sub sub) At(x, y int) color.Color { return sub.Image.At(x, y) } type GridDownscale struct { image.Image NewBounds image.Rectangle } func blend(c1, c2 color.Color) color.RGBA { r1, g1, b1, a1 := c1.RGBA() r2, g2, b2, a2 := c2.RGBA() r := r1/2 + r2/2 g := g1/2 + g2/2 b := b1/2 + b2/2 a := a1/2 + a2/2 return color.RGBA{ R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: uint8(a >> 8), } } func avgColor(img image.Image) (c color.Color) { b := img.Bounds() c = img.At(b.Min.X, b.Min.Y) for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X + 1; x < b.Max.X; x++ { c = blend(c, img.At(x, y)) } } return } func (grid GridDownscale) ColorModel() color.Model { return grid.Image.ColorModel() } func (grid GridDownscale) Bounds() image.Rectangle { return grid.NewBounds } func (grid GridDownscale) At(x, y int) color.Color { b := grid.Image.Bounds() dx, dy := b.Dx(), b.Dy() cellBounds := image.Rect( 0, 0, dx/grid.NewBounds.Dx(), dy/grid.NewBounds.Dy(), ) r := grid.Image.Bounds().Intersect( // move cell cellBounds.Add( image.Point{ x * cellBounds.Dx(), y * cellBounds.Dy(), }, ), ) println(r.Min.X, r.Min.Y) return avgColor(sub{grid.Image, r}) }