github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/gift/effects.go (about) 1 package gift 2 3 import ( 4 "image" 5 "image/draw" 6 ) 7 8 type pixelateFilter struct { 9 size int 10 } 11 12 func (p *pixelateFilter) Bounds(srcBounds image.Rectangle) (dstBounds image.Rectangle) { 13 dstBounds = image.Rect(0, 0, srcBounds.Dx(), srcBounds.Dy()) 14 return 15 } 16 17 func (p *pixelateFilter) Draw(dst draw.Image, src image.Image, options *Options) { 18 if options == nil { 19 options = &defaultOptions 20 } 21 22 blockSize := p.size 23 if blockSize <= 1 { 24 copyimage(dst, src, options) 25 return 26 } 27 28 srcb := src.Bounds() 29 dstb := dst.Bounds() 30 31 numBlocksX := srcb.Dx() / blockSize 32 if srcb.Dx()%blockSize > 0 { 33 numBlocksX++ 34 } 35 numBlocksY := srcb.Dy() / blockSize 36 if srcb.Dy()%blockSize > 0 { 37 numBlocksY++ 38 } 39 40 pixGetter := newPixelGetter(src) 41 pixSetter := newPixelSetter(dst) 42 43 parallelize(options.Parallelization, 0, numBlocksY, func(bmin, bmax int) { 44 for by := bmin; by < bmax; by++ { 45 for bx := 0; bx < numBlocksX; bx++ { 46 // calculate the block bounds 47 bb := image.Rect(bx*blockSize, by*blockSize, (bx+1)*blockSize, (by+1)*blockSize) 48 bbSrc := bb.Add(srcb.Min).Intersect(srcb) 49 bbDst := bbSrc.Sub(srcb.Min).Add(dstb.Min).Intersect(dstb) 50 51 // calculate average color of the block 52 var r, g, b, a float32 53 var cnt float32 54 for y := bbSrc.Min.Y; y < bbSrc.Max.Y; y++ { 55 for x := bbSrc.Min.X; x < bbSrc.Max.X; x++ { 56 px := pixGetter.getPixel(x, y) 57 r += px.R 58 g += px.G 59 b += px.B 60 a += px.A 61 cnt++ 62 } 63 } 64 if cnt > 0 { 65 r /= cnt 66 g /= cnt 67 b /= cnt 68 a /= cnt 69 } 70 71 // set the calculated color for all pixels in the block 72 for y := bbDst.Min.Y; y < bbDst.Max.Y; y++ { 73 for x := bbDst.Min.X; x < bbDst.Max.X; x++ { 74 pixSetter.setPixel(x, y, pixel{r, g, b, a}) 75 } 76 } 77 } 78 } 79 }) 80 } 81 82 // Pixelate creates a filter that applies a pixelation effect to an image. 83 func Pixelate(size int) Filter { 84 return &pixelateFilter{ 85 size: size, 86 } 87 }