Example #1
0
func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Point) {
	// A YCbCr image is always fully opaque, and so if the mask is implicitly nil
	// (i.e. fully opaque) then the op is effectively always Src.
	var (
		yy, cb, cr uint8
	)
	x0 := (r.Min.X - dst.Rect.Min.X) * 4
	x1 := (r.Max.X - dst.Rect.Min.X) * 4
	y0 := r.Min.Y - dst.Rect.Min.Y
	y1 := r.Max.Y - dst.Rect.Min.Y
	switch src.SubsampleRatio {
	case ycbcr.SubsampleRatio422:
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
				i := sx / 2
				yy = src.Y[sy*src.YStride+sx]
				cb = src.Cb[sy*src.CStride+i]
				cr = src.Cr[sy*src.CStride+i]
				rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
				dpix[x+0] = rr
				dpix[x+1] = gg
				dpix[x+2] = bb
				dpix[x+3] = 255
			}
		}
	case ycbcr.SubsampleRatio420:
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
				i, j := sx/2, sy/2
				yy = src.Y[sy*src.YStride+sx]
				cb = src.Cb[j*src.CStride+i]
				cr = src.Cr[j*src.CStride+i]
				rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
				dpix[x+0] = rr
				dpix[x+1] = gg
				dpix[x+2] = bb
				dpix[x+3] = 255
			}
		}
	default:
		// Default to 4:4:4 subsampling.
		for y, sy := y0, sp.Y; y != y1; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride:]
			for x, sx := x0, sp.X; x != x1; x, sx = x+4, sx+1 {
				yy = src.Y[sy*src.YStride+sx]
				cb = src.Cb[sy*src.CStride+sx]
				cr = src.Cr[sy*src.CStride+sx]
				rr, gg, bb := ycbcr.YCbCrToRGB(yy, cb, cr)
				dpix[x+0] = rr
				dpix[x+1] = gg
				dpix[x+2] = bb
				dpix[x+3] = 255
			}
		}
	}
}
Example #2
0
File: draw.go Project: ssrl/go
func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Point) {
	// A YCbCr image is always fully opaque, and so if the mask is implicitly nil
	// (i.e. fully opaque) then the op is effectively always Src.
	var (
		yy, cb, cr uint8
		rr, gg, bb uint8
	)
	switch src.SubsampleRatio {
	case ycbcr.SubsampleRatio422:
		for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
			for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
				i := sx / 2
				yy = src.Y[sy*src.YStride+sx]
				cb = src.Cb[sy*src.CStride+i]
				cr = src.Cr[sy*src.CStride+i]
				rr, gg, bb = ycbcr.YCbCrToRGB(yy, cb, cr)
				dpix[x] = image.RGBAColor{rr, gg, bb, 255}
			}
		}
	case ycbcr.SubsampleRatio420:
		for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
			for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
				i, j := sx/2, sy/2
				yy = src.Y[sy*src.YStride+sx]
				cb = src.Cb[j*src.CStride+i]
				cr = src.Cr[j*src.CStride+i]
				rr, gg, bb = ycbcr.YCbCrToRGB(yy, cb, cr)
				dpix[x] = image.RGBAColor{rr, gg, bb, 255}
			}
		}
	default:
		// Default to 4:4:4 subsampling.
		for y, sy := r.Min.Y, sp.Y; y != r.Max.Y; y, sy = y+1, sy+1 {
			dpix := dst.Pix[y*dst.Stride : (y+1)*dst.Stride]
			for x, sx := r.Min.X, sp.X; x != r.Max.X; x, sx = x+1, sx+1 {
				yy = src.Y[sy*src.YStride+sx]
				cb = src.Cb[sy*src.CStride+sx]
				cr = src.Cr[sy*src.CStride+sx]
				rr, gg, bb = ycbcr.YCbCrToRGB(yy, cb, cr)
				dpix[x] = image.RGBAColor{rr, gg, bb, 255}
			}
		}
	}
}
Example #3
0
// resizeYCbCr returns a scaled copy of the YCbCr image slice r of m.
// The returned image has width w and height h.
func resizeYCbCr(m *ycbcr.YCbCr, r image.Rectangle, w, h int) (image.Image, bool) {
	var verticalRes int
	switch m.SubsampleRatio {
	case ycbcr.SubsampleRatio420:
		verticalRes = 2
	case ycbcr.SubsampleRatio422:
		verticalRes = 1
	default:
		return nil, false
	}
	ww, hh := uint64(w), uint64(h)
	dx, dy := uint64(r.Dx()), uint64(r.Dy())
	// See comment in Resize.
	n, sum := dx*dy, make([]uint64, 4*w*h)
	for y := r.Min.Y; y < r.Max.Y; y++ {
		Y := m.Y[y*m.YStride:]
		Cb := m.Cb[y/verticalRes*m.CStride:]
		Cr := m.Cr[y/verticalRes*m.CStride:]
		for x := r.Min.X; x < r.Max.X; x++ {
			// Get the source pixel.
			r8, g8, b8 := ycbcr.YCbCrToRGB(Y[x], Cb[x/2], Cr[x/2])
			r64 := uint64(r8)
			g64 := uint64(g8)
			b64 := uint64(b8)
			// Spread the source pixel over 1 or more destination rows.
			py := uint64(y) * hh
			for remy := hh; remy > 0; {
				qy := dy - (py % dy)
				if qy > remy {
					qy = remy
				}
				// Spread the source pixel over 1 or more destination columns.
				px := uint64(x) * ww
				index := 4 * ((py/dy)*ww + (px / dx))
				for remx := ww; remx > 0; {
					qx := dx - (px % dx)
					if qx > remx {
						qx = remx
					}
					qxy := qx * qy
					sum[index+0] += r64 * qxy
					sum[index+1] += g64 * qxy
					sum[index+2] += b64 * qxy
					sum[index+3] += 0xFFFF * qxy
					index += 4
					px += qx
					remx -= qx
				}
				py += qy
				remy -= qy
			}
		}
	}
	return average(sum, w, h, n), true
}