Example #1
0
// Halves the width of the double-width image created by hxl to produce nice
// smooth edges.
func halveWidth(img image.Image) image.Image {
	b := img.Bounds()
	o := image.NewRGBA(image.Rect(0, 0, b.Dx()/2, b.Dy()))

	for y := 0; y < b.Dy(); y++ {
		for x := 0; x < b.Dx()/2; x++ {
			l := img.At(x*2, y)
			r := img.At(x*2+1, y)

			o.Set(x, y, utils.Average(l, r))
		}
	}

	return o
}
Example #2
0
// Pixelate takes an Image and pixelates it into rectangles with the dimensions
// given. The colour values in each region are averaged to produce the resulting
// colours.
func Pixelate(img image.Image, size utils.Dimension) image.Image {
	b := img.Bounds()

	cols := b.Dx() / size.W
	rows := b.Dy() / size.H

	o := image.NewRGBA(image.Rect(0, 0, size.W*cols, size.H*rows))

	for col := 0; col < cols; col++ {
		for row := 0; row < rows; row++ {

			values := make([]color.Color, size.H*size.W)
			count := 0

			for y := 0; y < size.H; y++ {
				for x := 0; x < size.W; x++ {

					realY := row*size.H + y
					realX := col*size.W + x

					values[count] = img.At(realX, realY)
					count++
				}
			}

			avg := utils.Average(values...)

			for y := 0; y < size.H; y++ {
				for x := 0; x < size.W; x++ {

					realY := row*size.H + y
					realX := col*size.W + x

					o.Set(realX, realY, avg)
				}
			}

		}
	}

	return o
}
Example #3
0
func halve(img image.Image, size utils.Dimension) image.Image {
	b := img.Bounds()
	o := image.NewRGBA(image.Rect(0, 0, b.Dx()/2, b.Dy()/2))

	for y := 0; y < b.Dy()/2; y++ {
		for x := 0; x < b.Dx()/2; x++ {
			tl := img.At(x*2, y*2)
			tr := img.At(x*2+1, y*2)
			br := img.At(x*2+1, y*2-1)
			bl := img.At(x*2, y*2-1)

			if y%size.H == 0 {
				o.Set(x, y, tl)
			} else if x%size.W == 0 {
				o.Set(x, y, tl)
			} else {
				o.Set(x, y, utils.Average(tl, tr, bl, br))
			}
		}
	}

	return o
}
Example #4
0
// Vxl pixelates the Image into isometric cubes. It averages the colours and
// naïvely darkens and lightens the colours to mimic highlight and shade.
func Vxl(img image.Image, height int, flip bool, top, left, right float64) image.Image {
	b := img.Bounds()

	pixelHeight := height
	pixelWidth := int(math.Sqrt(3.0) * float64(pixelHeight) / 2.0)

	cols := b.Dx() / pixelWidth
	rows := b.Dy() / pixelHeight

	// intersection of lines
	c := float64(pixelHeight) / 2
	// gradient of lines
	k := math.Sqrt(3.0) / 3.0
	o := image.NewRGBA(image.Rect(0, 0, pixelWidth*cols, pixelHeight*rows))

	// See: http://www.flickr.com/photos/hawx-/8466236036/
	inTopSquare := func(x, y float64) bool {
		if !flip {
			y *= -1
		}
		return y <= -k*x+c && y >= k*x && y >= -k*x && y <= k*x+c
	}

	inBottomRight := func(x, y float64) bool {
		if !flip {
			y *= -1
		}
		return x >= 0 && y <= k*x && y >= k*x-c
	}

	inBottomLeft := func(x, y float64) bool {
		if !flip {
			y *= -1
		}
		return x <= 0 && y <= -k*x && y >= -k*x-c
	}

	inHexagon := func(x, y float64) bool {
		return inTopSquare(x, y) || inBottomRight(x, y) || inBottomLeft(x, y)
	}

	topL := channel.LightnessC(utils.Multiplier(top))
	rightL := channel.LightnessC(utils.Multiplier(right))
	leftL := channel.LightnessC(utils.Multiplier(left))

	for col := 0; col < cols; col++ {
		for row := 0; row < rows; row++ {
			seen := []color.Color{}

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth; x++ {
					realY := row*(pixelHeight+int(c)) + y
					realX := col*pixelWidth + x
					pixel := img.At(realX, realY)

					y_origin := float64(y - pixelHeight/2)
					x_origin := float64(x - pixelWidth/2)

					if inHexagon(x_origin, y_origin) {
						seen = append(seen, pixel)
					}
				}
			}

			average := utils.Average(seen...)

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth; x++ {
					realY := row*(pixelHeight+int(c)) + y
					realX := col*pixelWidth + x

					y_origin := float64(y - pixelHeight/2)
					x_origin := float64(x - pixelWidth/2)

					// This stops white bits showing above the top squares. It does mean
					// the dimensions aren't perfect, but what did you expect with pixels
					// and trig. It is inefficient though, maybe fix that later?
					if (!flip && y_origin < 0) || (flip && y_origin > 0) {
						o.Set(realX, realY, topL(average))
					} else {
						if x_origin > 0 {
							o.Set(realX, realY, rightL(average))
						} else {
							o.Set(realX, realY, leftL(average))
						}
					}

					if inTopSquare(x_origin, y_origin) {
						o.Set(realX, realY, topL(average))
					}
					if inBottomRight(x_origin, y_origin) {
						o.Set(realX, realY, rightL(average))
					}
					if inBottomLeft(x_origin, y_origin) {
						o.Set(realX, realY, leftL(average))
					}
				}
			}
		}
	}

	offsetY := (pixelHeight + int(c)) / 2.0
	offsetX := pixelWidth / 2

	for col := -1; col < cols; col++ {
		for row := -1; row < rows; row++ {
			seen := []color.Color{}

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth; x++ {
					realY := row*(pixelHeight+int(c)) + y + offsetY
					realX := col*pixelWidth + x + offsetX

					if image.Pt(realX, realY).In(b) {
						pixel := img.At(realX, realY)

						y_origin := float64(y - pixelHeight/2)
						x_origin := float64(x - pixelWidth/2)

						if inHexagon(x_origin, y_origin) {
							seen = append(seen, pixel)
						}
					}
				}
			}

			if len(seen) <= 0 {
				continue
			}
			average := utils.Average(seen...)

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth; x++ {
					realY := row*(pixelHeight+int(c)) + y + offsetY
					realX := col*pixelWidth + x + offsetX

					y_origin := float64(y - pixelHeight/2)
					x_origin := float64(x - pixelWidth/2)

					if inTopSquare(x_origin, y_origin) {
						o.Set(realX, realY, topL(average))
					}
					if inBottomRight(x_origin, y_origin) {
						o.Set(realX, realY, rightL(average))
					}
					if inBottomLeft(x_origin, y_origin) {
						o.Set(realX, realY, leftL(average))
					}
				}
			}
		}
	}

	return o
}
Example #5
0
func pxlDo(img image.Image, triangle int, size utils.Dimension, scaleFactor int) image.Image {

	b := img.Bounds()

	cols := b.Dx() / size.W
	rows := b.Dy() / size.H
	ratio := float64(size.H) / float64(size.W)

	o := image.NewRGBA(image.Rect(0, 0, size.W*cols*scaleFactor, size.H*rows*scaleFactor))

	inTop := func(x, y float64) bool {
		return (y > ratio*x) && (y > ratio*-x)
	}

	inRight := func(x, y float64) bool {
		return (y < ratio*x) && (y > ratio*-x)
	}

	inBottom := func(x, y float64) bool {
		return (y < ratio*x) && (y < ratio*-x)
	}

	inLeft := func(x, y float64) bool {
		return (y > ratio*x) && (y < ratio*-x)
	}

	for col := 0; col < cols; col++ {
		for row := 0; row < rows; row++ {

			to := []color.Color{}
			ri := []color.Color{}
			bo := []color.Color{}
			le := []color.Color{}

			for y := 0; y < size.H; y++ {
				for x := 0; x < size.W; x++ {

					realY := row*size.H + y
					realX := col*size.W + x

					y_origin := float64(y - size.H/2)
					x_origin := float64(x - size.W/2)

					if inTop(x_origin, y_origin) {
						to = append(to, img.At(realX, realY))

					} else if inRight(x_origin, y_origin) {
						ri = append(ri, img.At(realX, realY))

					} else if inBottom(x_origin, y_origin) {
						bo = append(bo, img.At(realX, realY))

					} else if inLeft(x_origin, y_origin) {
						le = append(le, img.At(realX, realY))

					}
				}
			}

			ato := utils.Average(to...)
			ari := utils.Average(ri...)
			abo := utils.Average(bo...)
			ale := utils.Average(le...)

			if (triangle != LEFT) && (triangle == RIGHT ||
				utils.Closeness(ato, ari) > utils.Closeness(ato, ale)) {

				top_right := utils.Average(ato, ari)
				bottom_left := utils.Average(abo, ale)

				for y := 0; y < size.H*scaleFactor; y++ {
					for x := 0; x < size.W*scaleFactor; x++ {

						realY := row*size.H*scaleFactor + y
						realX := col*size.W*scaleFactor + x

						y_origin := float64(y - size.H*scaleFactor/2)
						x_origin := float64(x - size.W*scaleFactor/2)

						if y_origin > ratio*x_origin {
							o.Set(realX, realY, top_right)
						} else {
							o.Set(realX, realY, bottom_left)
						}
					}
				}

			} else {

				top_left := utils.Average(ato, ale)
				bottom_right := utils.Average(abo, ari)

				for y := 0; y < size.H*scaleFactor; y++ {
					for x := 0; x < size.W*scaleFactor; x++ {

						realY := row*size.H*scaleFactor + y
						realX := col*size.W*scaleFactor + x

						y_origin := float64(y - size.H*scaleFactor/2)
						x_origin := float64(x - size.W*scaleFactor/2)

						if y_origin >= ratio*-x_origin {
							o.Set(realX, realY, top_left)
						} else {
							o.Set(realX, realY, bottom_right)
						}
					}
				}
			}
		}
	}

	return o
}
Example #6
0
// Hxl pixelates the Image into equilateral triangles with the width
// given. These are arranged into hexagonal shapes.
func Hxl(img image.Image, width int) image.Image {
	b := img.Bounds()

	pixelHeight := width * 2
	pixelWidth := width

	cols := b.Dx() / pixelWidth
	rows := b.Dy() / pixelHeight

	o := image.NewRGBA(image.Rect(0, 0, pixelWidth*cols*2, pixelHeight*rows))

	// Note: "Top" doesn't mean above the x-axis, it means in the triangle
	// pointing towards the x-axis.
	inTop := func(x, y float64) bool {
		return (x >= 0 && y >= x) || (x <= 0 && y >= -x)
	}

	// Same for "Bottom" this is the triangle below and pointing towards the
	// x-axis.
	inBottom := func(x, y float64) bool {
		return (x >= 0 && y <= -x) || (x <= 0 && y <= x)
	}

	for col := 0; col < cols; col++ {
		for row := 0; row < rows; row++ {
			north := []color.Color{}
			south := []color.Color{}

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth; x++ {
					realY := row*pixelHeight + y
					realX := col*pixelWidth + x
					pixel := img.At(realX, realY)

					y_origin := float64(y - pixelHeight/2)
					x_origin := float64(x - pixelWidth/2)

					if inTop(x_origin, y_origin) {
						north = append(north, pixel)
					} else if inBottom(x_origin, y_origin) {
						south = append(south, pixel)
					}
				}
			}

			top := utils.Average(north...)
			bot := utils.Average(south...)

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth*2; x++ {
					realY := row*pixelHeight + y
					realX := col*pixelWidth*2 + x

					y_origin := float64(y - pixelHeight/2)
					x_origin := float64(x - pixelWidth*2/2)

					if inTop(x_origin, y_origin) {
						o.Set(realX, realY, top)
					} else if inBottom(x_origin, y_origin) {
						o.Set(realX, realY, bot)
					}
				}
			}
		}
	}

	// Now for the shifted version

	offsetY := pixelHeight / 2
	offsetX := pixelWidth / 2

	for col := -1; col < cols; col++ {
		for row := -1; row < rows; row++ {
			north := []color.Color{}
			south := []color.Color{}

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth; x++ {
					realY := row*pixelHeight + y + offsetY
					realX := col*pixelWidth + x + offsetX

					if realX >= 0 && realX < b.Dx() {
						pixel := img.At(realX, realY)

						y_origin := float64(y - pixelHeight/2)
						x_origin := float64(x - pixelWidth/2)

						if inTop(x_origin, y_origin) {
							north = append(north, pixel)
						} else if inBottom(x_origin, y_origin) {
							south = append(south, pixel)
						}
					}
				}
			}

			top := utils.Average(north...)
			bot := utils.Average(south...)

			for y := 0; y < pixelHeight; y++ {
				for x := 0; x < pixelWidth*2; x++ {
					realY := row*pixelHeight + y + offsetY
					realX := col*pixelWidth*2 + x + offsetX*2

					y_origin := float64(y - pixelHeight/2)
					x_origin := float64(x - pixelWidth*2/2)

					if inTop(x_origin, y_origin) {
						o.Set(realX, realY, top)
					} else if inBottom(x_origin, y_origin) {
						o.Set(realX, realY, bot)
					}
				}
			}
		}
	}

	return halveWidth(o)
}