Ejemplo n.º 1
0
func FillColumn(imagem *image.RGBA, x, y int) {
	preto := color.RGBA{0, 0, 0, 255}

	for h := y; h <= 513; h++ {
		imagem.Set(x, h, preto)
	}
}
Ejemplo n.º 2
0
/*
draws pixels to connect a line
*/
func (line Line) connect(img *image.RGBA) {
	points := line.generatePoints()
	black := color.RGBA{0, 0, 0, 255}
	for _, val := range points {
		img.SetRGBA(val.X, val.Y, black)
	}
}
Ejemplo n.º 3
0
Archivo: xgb.go Proyecto: Zwobot/go.wde
func (buffer Image) CopyRGBA(src *image.RGBA, r image.Rectangle) {
	// clip r against each image's bounds and move sp accordingly (see draw.clip())
	sp := image.ZP
	orig := r.Min
	r = r.Intersect(buffer.Bounds())
	r = r.Intersect(src.Bounds().Add(orig.Sub(sp)))
	dx := r.Min.X - orig.X
	dy := r.Min.Y - orig.Y
	(sp).X += dx
	(sp).Y += dy

	i0 := (r.Min.X - buffer.Rect.Min.X) * 4
	i1 := (r.Max.X - buffer.Rect.Min.X) * 4
	si0 := (sp.X - src.Rect.Min.X) * 4
	yMax := r.Max.Y - buffer.Rect.Min.Y

	y := r.Min.Y - buffer.Rect.Min.Y
	sy := sp.Y - src.Rect.Min.Y
	for ; y != yMax; y, sy = y+1, sy+1 {
		dpix := buffer.Pix[y*buffer.Stride:]
		spix := src.Pix[sy*src.Stride:]

		for i, si := i0, si0; i < i1; i, si = i+4, si+4 {
			dpix[i+0] = spix[si+2]
			dpix[i+1] = spix[si+1]
			dpix[i+2] = spix[si+0]
			dpix[i+3] = spix[si+3]
		}
	}
}
Ejemplo n.º 4
0
func drawCopySrc(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.Point) {
	n, dy := 4*r.Dx(), r.Dy()
	d0 := dst.PixOffset(r.Min.X, r.Min.Y)
	s0 := src.PixOffset(sp.X, sp.Y)
	var ddelta, sdelta int
	if r.Min.Y <= sp.Y {
		ddelta = dst.Stride
		sdelta = src.Stride
	} else {
		// If the source start point is higher than the destination start
		// point, then we compose the rows in bottom-up order instead of
		// top-down. Unlike the drawCopyOver function, we don't have to check
		// the x coordinates because the built-in copy function can handle
		// overlapping slices.
		d0 += (dy - 1) * dst.Stride
		s0 += (dy - 1) * src.Stride
		ddelta = -dst.Stride
		sdelta = -src.Stride
	}
	for ; dy > 0; dy-- {
		copy(dst.Pix[d0:d0+n], src.Pix[s0:s0+n])
		d0 += ddelta
		s0 += sdelta
	}
}
Ejemplo n.º 5
0
func cloneImage(i *image.RGBA) *image.RGBA {
	i2 := new(image.RGBA)
	*i2 = *i
	i2.Pix = make([]uint8, len(i.Pix))
	copy(i2.Pix, i.Pix)
	return i2
}
Ejemplo n.º 6
0
func fillPixels(avatar *image.RGBA, x, y int, pixelColor color.RGBA) {
	for i := x; i < x+PixelSize; i++ {
		for j := y; j < y+PixelSize; j++ {
			avatar.SetRGBA(i, j, pixelColor)
		}
	}
}
Ejemplo n.º 7
0
func NewTiledImage(img *image.RGBA, tileSize image.Point) *TiledImage {
	b := img.Bounds()
	nx := b.Dx() / tileSize.X
	ny := b.Dy() / tileSize.Y
	tiles := make([]TileInfo, nx*ny)

	for j := 0; j < ny; j++ {
		y := b.Min.Y + j*tileSize.Y
		for i := 0; i < nx; i++ {
			x := b.Min.X + i*tileSize.X
			rect := image.Rect(x, y, x+tileSize.X, y+tileSize.Y)
			k := i + j*nx
			tiles[k].subImage = img.SubImage(rect).(*image.RGBA)
			tiles[k].dist2 = math.MaxFloat32
		}
	}

	return &TiledImage{
		data: tiles,
		nx:   nx,
		ny:   ny,
		sx:   tileSize.X,
		sy:   tileSize.Y,
	}
}
Ejemplo n.º 8
0
// Fills a rectangle in the specified rgba with the given color.
func fillRect(rgba *image.RGBA, rect image.Rectangle, color color.Color) {
	for x := rect.Min.X; x <= rect.Max.X; x++ {
		for y := rect.Min.Y; y <= rect.Max.Y; y++ {
			rgba.Set(x, y, color)
		}
	}
}
Ejemplo n.º 9
0
func constructPixelArray(img *image.RGBA) []Rgb {
	rgbaImg := image.NewRGBA(img.Bounds())
	draw.Draw(rgbaImg, rgbaImg.Bounds(), img, image.ZP, draw.Src)

	pixelArray := make([]Rgb, 0, 50)
	var rgbVal = Rgb{}

	for i, pix := range rgbaImg.Pix {
		switch i % 4 {
		case 0:
			rgbVal.R = pix
		case 1:
			rgbVal.G = pix
		case 2:
			rgbVal.B = pix
		case 3:
			if pix >= minTransparency && isOpaque(rgbVal) {
				pixelArray = append(pixelArray, rgbVal)
				rgbVal = Rgb{}
			}
		}
	}

	return pixelArray
}
Ejemplo n.º 10
0
func fillpoint(c compl, img *image.RGBA, imagelength, imagewidth float64, fromc, toc compl) {
	transformedxcoord := int((imagelength * (c.re - fromc.re) / (toc.re - fromc.re)))
	transformedycoord := int(imagewidth - (imagewidth*(c.im-fromc.im))/(toc.im-fromc.im))
	col := colorFromEscapeTime(getEscapeTime(c))
	img.Set(transformedxcoord, transformedycoord, col)

}
Ejemplo n.º 11
0
func Start(im *image.RGBA, num int, vpx, vpy, d float64, ch chan<- point) {
	share := im.Height() / num
	for i := 0; i < num; i += 1 {
		go Mandelbrot(im, i*share, (i+1)*share, vpx, vpy, d, ch)
	}

}
Ejemplo n.º 12
0
func renderFloat(img *image.RGBA) {
	var yminF, ymaxMinF, heightF big.Float
	yminF.SetInt64(ymin)
	ymaxMinF.SetInt64(ymax - ymin)
	heightF.SetInt64(height)

	var xminF, xmaxMinF, widthF big.Float
	xminF.SetInt64(xmin)
	xmaxMinF.SetInt64(xmax - xmin)
	widthF.SetInt64(width)

	var y, x big.Float
	for py := int64(0); py < height; py++ {
		// y := float64(py)/height*(ymax-ymin) + ymin
		y.SetInt64(py)
		y.Quo(&y, &heightF)
		y.Mul(&y, &ymaxMinF)
		y.Add(&y, &yminF)

		for px := int64(0); px < width; px++ {
			// x := float64(px)/width*(xmax-xmin) + xmin
			x.SetInt64(px)
			x.Quo(&x, &widthF)
			x.Mul(&x, &xmaxMinF)
			x.Add(&x, &xminF)

			c := mandelbrotFloat(&x, &y)
			if c == nil {
				c = color.Black
			}
			img.Set(int(px), int(py), c)
		}
	}
}
Ejemplo n.º 13
0
func gaussianBlur(dst, src *image.RGBA, radius int) {
	boxes := determineBoxes(float64(radius), 3)
	tmp := image.NewRGBA(dst.Bounds())
	boxBlur3(dst, tmp, src, (boxes[0]-1)/2)
	boxBlur3(dst, tmp, dst, (boxes[1]-1)/2)
	boxBlur3(dst, tmp, dst, (boxes[2]-1)/2)
}
Ejemplo n.º 14
0
// Image builds an image.RGBA type with 6 by 6 quadrants of alternate colors.
func Image(m *image.RGBA, key string, colors []color.RGBA) {
	size := m.Bounds().Size()
	squares := 6
	quad := size.X / squares
	middle := math.Ceil(float64(squares) / float64(2))
	colorMap := make(map[int]color.RGBA)
	var currentYQuadrand = 0
	for y := 0; y < size.Y; y++ {
		yQuadrant := y / quad
		if yQuadrant != currentYQuadrand {
			// when y quadrant changes, clear map
			colorMap = make(map[int]color.RGBA)
			currentYQuadrand = yQuadrant
		}
		for x := 0; x < size.X; x++ {
			xQuadrant := x / quad
			if _, ok := colorMap[xQuadrant]; !ok {
				if float64(xQuadrant) < middle {
					colorMap[xQuadrant] = draw.PickColor(key, colors, xQuadrant+3*yQuadrant)
				} else if xQuadrant < squares {
					colorMap[xQuadrant] = colorMap[squares-xQuadrant-1]
				} else {
					colorMap[xQuadrant] = colorMap[0]
				}
			}
			m.Set(x, y, colorMap[xQuadrant])
		}
	}
}
Ejemplo n.º 15
0
// loadFont loads the given font data. This does not deal with font scaling.
// Scaling should be handled by the independent Bitmap/Truetype loaders.
// We therefore expect the supplied image and charset to already be adjusted
// to the correct font scale.
//
// The image should hold a sprite sheet, defining the graphical layout for
// every glyph. The config describes font metadata.
func loadFont(img *image.RGBA, config *FontConfig) (f *Font, err error) {
	f = new(Font)
	f.Config = config

	// Resize image to next power-of-two.
	img = glh.Pow2Image(img).(*image.RGBA)
	ib := img.Bounds()

	f.Width = ib.Dx()
	f.Height = ib.Dy()

	// Create the texture itself. It will contain all glyphs.
	// Individual glyph-quads display a subset of this texture.
	f.Texture = gl.GenTexture()
	f.Texture.Bind(gl.TEXTURE_2D)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
	gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
	gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, ib.Dx(), ib.Dy(), 0,
		gl.RGBA, gl.UNSIGNED_BYTE, img.Pix)

	// file, err := os.Create("font.png")
	// if err != nil {
	// 	log.Fatal(err)
	// }

	// err = png.Encode(file, img)
	// if err != nil {
	// 	log.Fatal(err)
	// }

	return
}
Ejemplo n.º 16
0
func getRGBA(src *image.RGBA, x, y, borderMethod int) (r, g, b, a uint8) {
	bound := src.Bounds()
	if x < 0 {
		switch borderMethod {
		case BORDER_COPY:
			x = 0
		default:
			return 0, 0, 0, 0
		}
	} else if x >= bound.Max.X {
		switch borderMethod {
		case BORDER_COPY:
			x = bound.Max.X - 1
		default:
			return 0, 0, 0, 0
		}
	}
	if y < 0 {
		switch borderMethod {
		case BORDER_COPY:
			y = 0
		default:
			return 0, 0, 0, 0
		}
	} else if y >= bound.Max.Y {
		switch borderMethod {
		case BORDER_COPY:
			y = bound.Max.Y - 1
		default:
			return 0, 0, 0, 0
		}
	}
	i := (y-bound.Min.Y)*src.Stride + (x-bound.Min.X)*4
	return src.Pix[i], src.Pix[i+1], src.Pix[i+2], src.Pix[i+3]
}
Ejemplo n.º 17
0
func renderWithSupersampling(img *image.RGBA) {
	const samplings = 4
	dy := [samplings]float64{+0.25, +0.25, -0.25, -0.25}
	dx := [samplings]float64{+0.25, -0.25, +0.25, -0.25}

	for py := 0; py < height; py++ {
		for px := 0; px < width; px++ {
			r, g, b, a := 0, 0, 0, 0
			for i := 0; i < samplings; i++ {
				sy := (dy[i]+float64(py))/height*(ymax-ymin) + ymin
				sx := (dx[i]+float64(px))/width*(xmax-xmin) + xmin
				sc := mandelbrot(complex(sx, sy))
				mr, mg, mb, ma := sc.RGBA()
				r += int(mr)
				g += int(mg)
				b += int(mb)
				a += int(ma)
			}
			c := color.RGBA{
				uint8((r >> 8) / samplings),
				uint8((g >> 8) / samplings),
				uint8((b >> 8) / samplings),
				uint8((a >> 8) / samplings),
			}
			img.Set(px, py, c)
		}
	}
}
Ejemplo n.º 18
0
func (sgImage *SgImage) loadAlphaMask(img *image.RGBA, buffer []byte) {
	width := img.Bounds().Dx()
	length := int(sgImage.workRecord.AlphaLength)
	var i, x, y int

	for i < length {
		c := int(buffer[i])
		i++
		if c == 255 {
			// The next byte is the number of pixels to skip
			x += int(buffer[i])
			i++
			for x >= width {
				y++
				x -= width
			}
		} else {
			// 'c' is the number of image data bytes
			for j := 0; j < c; j++ {
				sgImage.setAlphaPixel(img, x, y, buffer[i])
				x++
				if x >= width {
					y++
					x = 0
				}
				i += 2
			}
		}
	}
}
Ejemplo n.º 19
0
Archivo: img.go Proyecto: mabetle/mcore
// 将图片绘制到图片
func ImageDrawRGBA(img *image.RGBA, imgcode image.Image, x, y int) {
	// 绘制图像
	// image.Point A点的X,Y坐标,轴向右和向下增加{0,0}
	// image.ZP ZP is the zero Point
	// image.Pt Pt is shorthand for Point{X, Y}
	draw.Draw(img, img.Bounds(), imgcode, image.Pt(x, y), draw.Over)
}
Ejemplo n.º 20
0
func (sgImage *SgImage) writeIsometricBase(img *image.RGBA, buffer []byte) error {
	width := img.Bounds().Dx()
	height := (width + 2) / 2 /* 58 -> 30, 118 -> 60, etc */
	heightOffset := img.Bounds().Dy() - height
	var size int
	size = int(sgImage.workRecord.Flags[3])
	yOffset := heightOffset
	var xOffset, tileBytes, tileHeight, tileWidth int

	if size == 0 {
		/* Derive the tile size from the height (more regular than width)
		 * Note that this causes a problem with 4x4 regular vs 3x3 large:
		 * 4 * 30 = 120; 3 * 40 = 120 -- give precedence to regular */
		if height%ISOMETRIC_TILE_HEIGHT == 0 {
			size = height / ISOMETRIC_TILE_HEIGHT
		} else if height%ISOMETRIC_LARGE_TILE_HEIGHT == 0 {
			size = height / ISOMETRIC_LARGE_TILE_HEIGHT
		}
	}

	// Determine whether we should use the regular or large (emperor) tiles
	if ISOMETRIC_TILE_HEIGHT*size == height {
		// Regular tile
		tileBytes = ISOMETRIC_TILE_BYTES
		tileHeight = ISOMETRIC_TILE_HEIGHT
		tileWidth = ISOMETRIC_TILE_WIDTH
	} else if ISOMETRIC_LARGE_TILE_HEIGHT*size == height {
		// Large (emperor) tile
		tileBytes = ISOMETRIC_LARGE_TILE_BYTES
		tileHeight = ISOMETRIC_LARGE_TILE_HEIGHT
		tileWidth = ISOMETRIC_LARGE_TILE_WIDTH
	} else {
		return fmt.Errorf("Unknown tile size: %d (height %d, width %d, size %d)", 2*height/size, height, width, size)
	}

	// Check if buffer length is enough: (width + 2) * height / 2 * 2bpp
	if (width+2)*height != int(sgImage.workRecord.UncompressedLength) {
		return fmt.Errorf("Data length doesn't match footprint size: %d vs %d (%d) %d", (width+2)*height, sgImage.workRecord.UncompressedLength, sgImage.workRecord.Length, sgImage.workRecord.InvertOffset)
	}

	i := 0
	for y := 0; y < (size + (size - 1)); y++ {
		var xRange int
		if y < size {
			xOffset = size - y - 1
			xRange = y + 1
		} else {
			xOffset = y - size + 1
			xRange = 2*size - y - 1
		}
		xOffset *= tileHeight
		for x := 0; x < xRange; x++ {
			sgImage.writeIsometricTile(img, buffer[i*tileBytes:], xOffset, yOffset, tileWidth, tileHeight)
			xOffset += tileWidth + 2
			i++
		}
		yOffset += tileHeight / 2
	}
	return nil
}
Ejemplo n.º 21
0
func (t *Texture) FromImageRGBA(rgba *image.RGBA, level int) {
	With(t, func() {
		gl.TexImage2D(gl.TEXTURE_2D, level, gl.RGBA,
			rgba.Bounds().Dx(), rgba.Bounds().Dy(),
			0, gl.RGBA, gl.UNSIGNED_BYTE, rgba.Pix)
	})
}
Ejemplo n.º 22
0
func (sgImage *SgImage) writeTransparentImage(img *image.RGBA, buffer []byte, length int) {
	width := img.Bounds().Dx()

	var i, x, y int

	for i < length {
		c := int(buffer[i])
		i++
		if c == 255 {
			// The next byte is the number of pixels to skip
			x += int(buffer[i])
			i++
			for x >= width {
				y++
				x -= width
			}
		} else {
			// 'c' is the number of image data bytes
			for j := 0; j < c; j++ {
				sgImage.set555Pixel(img, x, y, uint16(buffer[i+1]<<8)|uint16(buffer[i]))
				x++
				if x >= width {
					y++
					x = 0
				}
				i += 2
			}
		}
	}
}
Ejemplo n.º 23
0
/*
 * Go-Portierung des unter
 * http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm
 * in C beschriebenen Bresenham-Algorithmus zur Darstellung gerasterter
 * Linien
 */
func drawLine(img image.RGBA, a, b Point, c image.RGBAColor) {
	// Go-Portierung des Bresenham-Algoritmus
	x0, x1, y0, y1 := a.x, b.x, a.y, b.y
	steep := abs(y1-y0) > abs(x1-x0)
	if steep {
		x0, x1, y0, y1 = y0, y1, x0, x1
	}
	if x0 > x1 {
		x0, y0, x1, y1 = x1, y1, x0, y0
	}
	deltax := x1 - x0
	deltay := abs(y1 - y0)
	error := deltax / 2
	y := y0
	var ystep int
	if y0 < y1 {
		ystep = 1
	} else {
		ystep = -1
	}
	for x := x0; x <= x1; x++ {
		if steep {
			img.Set(y, x, c)
		} else {
			img.Set(x, y, c)
		}
		error = error - deltay
		if error < 0 {
			y += ystep
			error += deltax
		}
	}
}
Ejemplo n.º 24
0
// Gradient.
func gradient(img *image.RGBA, from, to color.RGBA, x, y int, horizontal bool) {
	s := [3]float32{
		(float32(to.R) - float32(from.R)) / float32(x),
		(float32(to.G) - float32(from.G)) / float32(x),
		(float32(to.B) - float32(from.B)) / float32(x),
	}

	for i := 0; i < x; i++ {
		for j := 0; j < y; j++ {
			a, b := i, j
			if horizontal {
				a, b = j, i
			}
			img.SetRGBA(
				a,
				b,
				color.RGBA{
					uint8(float32(from.R) + float32(i)*s[0]),
					uint8(float32(from.G) + float32(i)*s[1]),
					uint8(float32(from.B) + float32(i)*s[2]),
					255,
				})
		}
	}
}
Ejemplo n.º 25
0
//func loadSize(ctxt *fs.Context, name string, max int) *image.RGBA
func loadSize(name string, max int) *image.RGBA {
	//data, _, err := ctxt.Read("qr/upload/" + name + ".png")
	f1, err := os.Open(name + ".png")
	fmt.Println(name + ".png")
	if err != nil {
		panic(err)
	}
	i, err := png.Decode(f1)
	if err != nil {
		panic(err)
	}
	b := i.Bounds()
	fmt.Printf("%v, %v,max%v", b.Dx(), b.Dy(), max)
	dx, dy := max, max
	if b.Dx() > b.Dy() {
		dy = b.Dy() * dx / b.Dx()
	} else {
		dx = b.Dx() * dy / b.Dy()
	}
	fmt.Printf("%v, %v,", dx, dy)
	var irgba *image.RGBA
	switch i := i.(type) {
	case *image.RGBA:
		irgba = resize.ResizeRGBA(i, i.Bounds(), dx, dy)
	case *image.NRGBA:
		irgba = resize.ResizeNRGBA(i, i.Bounds(), dx, dy)
	default:
		fmt.Println("default")

	}
	fmt.Println("prereturnload")
	fmt.Printf("%v, %v,", irgba.Bounds().Dx(), irgba.Bounds().Dy())
	return irgba
}
Ejemplo n.º 26
0
// Rectangle.
func rectangle(img *image.RGBA, rect image.Rectangle, c color.RGBA) {
	for i := rect.Min.X; i <= rect.Max.X; i++ {
		for j := rect.Min.Y; j <= rect.Max.Y; j++ {
			img.SetRGBA(i, j, c)
		}
	}
}
Ejemplo n.º 27
0
func PaintBG(avatar *image.RGBA, bgColor color.RGBA) {
	for y := 0; y < AvatarSize; y++ {
		for x := 0; x < AvatarSize; x++ {
			avatar.SetRGBA(x, y, bgColor)
		}
	}
}
Ejemplo n.º 28
0
// Polygon.
func (avatar *Avatar) polygon(img *image.RGBA, points []image.Point, c color.RGBA) {
	// For each row
	for j := 0; j <= avatar.Y; j++ {

		// Build the list of Xs at which the row crosses a polygon edge
		intersect := make([]int, 0, len(points))
		adj := len(points) - 1
		for i, p := range points {
			q := points[adj]

			if (j > p.Y && j <= q.Y) || (j > q.Y && j <= p.Y) {
				x := int(float64(p.X) + (float64(j)-float64(p.Y))/(float64(q.Y)-float64(p.Y))*(float64(q.X)-float64(p.X)))
				intersect = append(intersect, x)
			}

			adj = i
		}

		// Sort the list f Xs
		sort.Ints(intersect)

		// Fill the pixels between node pairs
		for i := 0; i < len(intersect); i += 2 {
			for k := intersect[i]; k < intersect[i+1]; k++ {
				img.SetRGBA(k, j, c)
			}
		}
	}
}
Ejemplo n.º 29
0
Archivo: draw.go Proyecto: h8liu/golang
func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
	i0 := dst.PixOffset(r.Min.X, r.Min.Y)
	i1 := i0 + r.Dx()*4
	mi0 := mask.PixOffset(mp.X, mp.Y)
	sr, sg, sb, sa := src.RGBA()
	for y, my := r.Min.Y, mp.Y; y != r.Max.Y; y, my = y+1, my+1 {
		for i, mi := i0, mi0; i < i1; i, mi = i+4, mi+1 {
			ma := uint32(mask.Pix[mi])
			if ma == 0 {
				continue
			}
			ma |= ma << 8

			dr := uint32(dst.Pix[i+0])
			dg := uint32(dst.Pix[i+1])
			db := uint32(dst.Pix[i+2])
			da := uint32(dst.Pix[i+3])

			// The 0x101 is here for the same reason as in drawRGBA.
			a := (m - (sa * ma / m)) * 0x101

			dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
			dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
			dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
			dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
		}
		i0 += dst.Stride
		i1 += dst.Stride
		mi0 += mask.Stride
	}
}
Ejemplo n.º 30
0
//downsamples a source image as close as possible to a desired size, while also
//maintaining a linear downsampling ratio.
func downsample(img *image.RGBA, size image.Rectangle) *image.RGBA {

	xratio := int(img.Bounds().Max.X / size.Max.X)
	yratio := int(img.Bounds().Max.Y / size.Max.Y)

	minratio := xratio

	if yratio < xratio {
		minratio = yratio
	}

	xoffset := int((img.Bounds().Max.X - size.Max.X*minratio) / 2)
	yoffset := int((img.Bounds().Max.Y - size.Max.Y*minratio) / 2)

	out := image.NewRGBA(size)
	pixels := out.Pix

	for i := 0; i < size.Max.X; i++ {
		for j := 0; j < size.Max.Y; j++ {
			offset := 4 * (j*size.Max.X + i)
			r := image.Rect(i*minratio+xoffset, j*minratio+yoffset, (i+1)*minratio+xoffset, (j+1)*minratio+yoffset)

			c := averageColor(img, r)

			pixels[offset] = c.R
			pixels[offset+1] = c.G
			pixels[offset+2] = c.B
			pixels[offset+3] = 255
		}
	}
	return out
}