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  }