func()

in draw/impl.go [4435:4533]


func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
	if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
		z.kernel.Scale(dst, dr, src, sr, op, opts)
		return
	}

	var o Options
	if opts != nil {
		o = *opts
	}

	// adr is the affected destination pixels.
	adr := dst.Bounds().Intersect(dr)
	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
	if adr.Empty() || sr.Empty() {
		return
	}
	// Make adr relative to dr.Min.
	adr = adr.Sub(dr.Min)
	if op == Over && o.SrcMask == nil && opaque(src) {
		op = Src
	}

	if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) {
		Draw(dst, dr, src, src.Bounds().Min, op)
		return
	}

	// Create a temporary buffer:
	// scaleX distributes the source image's columns over the temporary image.
	// scaleY distributes the temporary image's rows over the destination image.
	var tmp [][4]float64
	if z.pool.New != nil {
		tmpp := z.pool.Get().(*[][4]float64)
		defer z.pool.Put(tmpp)
		tmp = *tmpp
	} else {
		tmp = z.makeTmpBuf()
	}

	// sr is the source pixels. If it extends beyond the src bounds,
	// we cannot use the type-specific fast paths, as they access
	// the Pix fields directly without bounds checking.
	//
	// Similarly, the fast paths assume that the masks are nil.
	if o.SrcMask != nil || !sr.In(src.Bounds()) {
		z.scaleX_Image(tmp, src, sr, &o)
	} else {
		switch src := src.(type) {
		case *image.Gray:
			z.scaleX_Gray(tmp, src, sr, &o)
		case *image.NRGBA:
			z.scaleX_NRGBA(tmp, src, sr, &o)
		case *image.RGBA:
			z.scaleX_RGBA(tmp, src, sr, &o)
		case *image.YCbCr:
			switch src.SubsampleRatio {
			default:
				z.scaleX_Image(tmp, src, sr, &o)
			case image.YCbCrSubsampleRatio444:
				z.scaleX_YCbCr444(tmp, src, sr, &o)
			case image.YCbCrSubsampleRatio422:
				z.scaleX_YCbCr422(tmp, src, sr, &o)
			case image.YCbCrSubsampleRatio420:
				z.scaleX_YCbCr420(tmp, src, sr, &o)
			case image.YCbCrSubsampleRatio440:
				z.scaleX_YCbCr440(tmp, src, sr, &o)
			}
		default:
			z.scaleX_Image(tmp, src, sr, &o)
		}
	}

	if o.DstMask != nil {
		switch op {
		case Over:
			z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
		case Src:
			z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
		}
	} else {
		switch op {
		case Over:
			switch dst := dst.(type) {
			case *image.RGBA:
				z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o)
			default:
				z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
			}
		case Src:
			switch dst := dst.(type) {
			case *image.RGBA:
				z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o)
			default:
				z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
			}
		}
	}
}