Example #1
0
// HalveInplace downsamples the image by 50% using averaging interpolation.
func HalveInplace(m image.Image) image.Image {
	b := m.Bounds()
	switch m := m.(type) {
	case *image.YCbCr:
		for y := b.Min.Y; y < b.Max.Y/2; y++ {
			for x := b.Min.X; x < b.Max.X/2; x++ {
				y00 := uint32(m.Y[m.YOffset(2*x, 2*y)])
				y10 := uint32(m.Y[m.YOffset(2*x+1, 2*y)])
				y01 := uint32(m.Y[m.YOffset(2*x, 2*y+1)])
				y11 := uint32(m.Y[m.YOffset(2*x+1, 2*y+1)])
				// Add before divide with uint32 or we get errors in the least
				// significant bits.
				m.Y[m.YOffset(x, y)] = uint8((y00 + y10 + y01 + y11) >> 2)

				cb00 := uint32(m.Cb[m.COffset(2*x, 2*y)])
				cb10 := uint32(m.Cb[m.COffset(2*x+1, 2*y)])
				cb01 := uint32(m.Cb[m.COffset(2*x, 2*y+1)])
				cb11 := uint32(m.Cb[m.COffset(2*x+1, 2*y+1)])
				m.Cb[m.COffset(x, y)] = uint8((cb00 + cb10 + cb01 + cb11) >> 2)

				cr00 := uint32(m.Cr[m.COffset(2*x, 2*y)])
				cr10 := uint32(m.Cr[m.COffset(2*x+1, 2*y)])
				cr01 := uint32(m.Cr[m.COffset(2*x, 2*y+1)])
				cr11 := uint32(m.Cr[m.COffset(2*x+1, 2*y+1)])
				m.Cr[m.COffset(x, y)] = uint8((cr00 + cr10 + cr01 + cr11) >> 2)
			}
		}
		b.Max = b.Min.Add(b.Size().Div(2))
		return subImage(m, b)
	case draw.Image:
		for y := b.Min.Y; y < b.Max.Y/2; y++ {
			for x := b.Min.X; x < b.Max.X/2; x++ {
				r00, g00, b00, a00 := m.At(2*x, 2*y).RGBA()
				r10, g10, b10, a10 := m.At(2*x+1, 2*y).RGBA()
				r01, g01, b01, a01 := m.At(2*x, 2*y+1).RGBA()
				r11, g11, b11, a11 := m.At(2*x+1, 2*y+1).RGBA()

				// Add before divide with uint32 or we get errors in the least
				// significant bits.
				r := (r00 + r10 + r01 + r11) >> 2
				g := (g00 + g10 + g01 + g11) >> 2
				b := (b00 + b10 + b01 + b11) >> 2
				a := (a00 + a10 + a01 + a11) >> 2

				m.Set(x, y, color.RGBA{
					R: uint8(r >> 8),
					G: uint8(g >> 8),
					B: uint8(b >> 8),
					A: uint8(a >> 8),
				})
			}
		}
		b.Max = b.Min.Add(b.Size().Div(2))
		return subImage(m, b)
	default:
		// TODO(wathiede): fallback to generic Resample somehow?
		panic("Unhandled image type")
	}
}
Example #2
0
// ResampleInplace will resample m inplace, overwritting existing pixel data,
// and return a subimage of m sized to w and h.
func ResampleInplace(m image.Image, r image.Rectangle, w, h int) image.Image {
	// We don't support scaling up.
	if r.Dx() < w || r.Dy() < h {
		return m
	}

	switch m := m.(type) {
	case *image.YCbCr:
		xStep := float64(r.Dx()) / float64(w)
		yStep := float64(r.Dy()) / float64(h)
		for y := r.Min.Y; y < r.Min.Y+h; y++ {
			for x := r.Min.X; x < r.Min.X+w; x++ {
				xSrc := int(float64(x) * xStep)
				ySrc := int(float64(y) * yStep)
				cSrc := m.COffset(xSrc, ySrc)
				cDst := m.COffset(x, y)
				m.Y[m.YOffset(x, y)] = m.Y[m.YOffset(xSrc, ySrc)]
				m.Cb[cDst] = m.Cb[cSrc]
				m.Cr[cDst] = m.Cr[cSrc]
			}
		}
	case draw.Image:
		xStep := float64(r.Dx()) / float64(w)
		yStep := float64(r.Dy()) / float64(h)
		for y := r.Min.Y; y < r.Min.Y+h; y++ {
			for x := r.Min.X; x < r.Min.X+w; x++ {
				xSrc := int(float64(x) * xStep)
				ySrc := int(float64(y) * yStep)
				r, g, b, a := m.At(xSrc, ySrc).RGBA()
				m.Set(x, y, color.RGBA{
					R: uint8(r >> 8),
					G: uint8(g >> 8),
					B: uint8(b >> 8),
					A: uint8(a >> 8),
				})
			}
		}
	default:
		// TODO fallback to generic Resample somehow?
		panic("Unhandled image type")
	}
	r.Max.X = r.Min.X + w
	r.Max.Y = r.Min.Y + h
	return subImage(m, r)
}