git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

draw/impl.go (272.8K)

   1 // generated by "go run gen.go". DO NOT EDIT.
   2 
   3 package draw
   4 
   5 import (
   6 	"image"
   7 	"image/color"
   8 	"math"
   9 
  10 	"golang.org/x/image/math/f64"
  11 )
  12 
  13 func (z nnInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
  14 	// Try to simplify a Scale to a Copy when DstMask is not specified.
  15 	// If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
  16 	if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
  17 		Copy(dst, dr.Min, src, sr, op, opts)
  18 		return
  19 	}
  20 
  21 	var o Options
  22 	if opts != nil {
  23 		o = *opts
  24 	}
  25 
  26 	// adr is the affected destination pixels.
  27 	adr := dst.Bounds().Intersect(dr)
  28 	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
  29 	if adr.Empty() || sr.Empty() {
  30 		return
  31 	}
  32 	// Make adr relative to dr.Min.
  33 	adr = adr.Sub(dr.Min)
  34 	if op == Over && o.SrcMask == nil && opaque(src) {
  35 		op = Src
  36 	}
  37 
  38 	// sr is the source pixels. If it extends beyond the src bounds,
  39 	// we cannot use the type-specific fast paths, as they access
  40 	// the Pix fields directly without bounds checking.
  41 	//
  42 	// Similarly, the fast paths assume that the masks are nil.
  43 	if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
  44 		switch op {
  45 		case Over:
  46 			z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
  47 		case Src:
  48 			z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
  49 		}
  50 	} else if _, ok := src.(*image.Uniform); ok {
  51 		Draw(dst, dr, src, src.Bounds().Min, op)
  52 	} else {
  53 		switch op {
  54 		case Over:
  55 			switch dst := dst.(type) {
  56 			case *image.RGBA:
  57 				switch src := src.(type) {
  58 				case *image.NRGBA:
  59 					z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o)
  60 				case *image.RGBA:
  61 					z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o)
  62 				case image.RGBA64Image:
  63 					z.scale_RGBA_RGBA64Image_Over(dst, dr, adr, src, sr, &o)
  64 				default:
  65 					z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o)
  66 				}
  67 			case RGBA64Image:
  68 				switch src := src.(type) {
  69 				case image.RGBA64Image:
  70 					z.scale_RGBA64Image_RGBA64Image_Over(dst, dr, adr, src, sr, &o)
  71 				}
  72 			default:
  73 				switch src := src.(type) {
  74 				default:
  75 					z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
  76 				}
  77 			}
  78 		case Src:
  79 			switch dst := dst.(type) {
  80 			case *image.RGBA:
  81 				switch src := src.(type) {
  82 				case *image.Gray:
  83 					z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o)
  84 				case *image.NRGBA:
  85 					z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o)
  86 				case *image.RGBA:
  87 					z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o)
  88 				case *image.YCbCr:
  89 					switch src.SubsampleRatio {
  90 					default:
  91 						z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
  92 					case image.YCbCrSubsampleRatio444:
  93 						z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o)
  94 					case image.YCbCrSubsampleRatio422:
  95 						z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o)
  96 					case image.YCbCrSubsampleRatio420:
  97 						z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o)
  98 					case image.YCbCrSubsampleRatio440:
  99 						z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o)
 100 					}
 101 				case image.RGBA64Image:
 102 					z.scale_RGBA_RGBA64Image_Src(dst, dr, adr, src, sr, &o)
 103 				default:
 104 					z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
 105 				}
 106 			case RGBA64Image:
 107 				switch src := src.(type) {
 108 				case image.RGBA64Image:
 109 					z.scale_RGBA64Image_RGBA64Image_Src(dst, dr, adr, src, sr, &o)
 110 				}
 111 			default:
 112 				switch src := src.(type) {
 113 				default:
 114 					z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
 115 				}
 116 			}
 117 		}
 118 	}
 119 }
 120 
 121 func (z nnInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
 122 	// Try to simplify a Transform to a Copy.
 123 	if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
 124 		dx := int(s2d[2])
 125 		dy := int(s2d[5])
 126 		if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
 127 			Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
 128 			return
 129 		}
 130 	}
 131 
 132 	var o Options
 133 	if opts != nil {
 134 		o = *opts
 135 	}
 136 
 137 	dr := transformRect(&s2d, &sr)
 138 	// adr is the affected destination pixels.
 139 	adr := dst.Bounds().Intersect(dr)
 140 	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
 141 	if adr.Empty() || sr.Empty() {
 142 		return
 143 	}
 144 	if op == Over && o.SrcMask == nil && opaque(src) {
 145 		op = Src
 146 	}
 147 
 148 	d2s := invert(&s2d)
 149 	// bias is a translation of the mapping from dst coordinates to src
 150 	// coordinates such that the latter temporarily have non-negative X
 151 	// and Y coordinates. This allows us to write int(f) instead of
 152 	// int(math.Floor(f)), since "round to zero" and "round down" are
 153 	// equivalent when f >= 0, but the former is much cheaper. The X--
 154 	// and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
 155 	// adjustment.
 156 	bias := transformRect(&d2s, &adr).Min
 157 	bias.X--
 158 	bias.Y--
 159 	d2s[2] -= float64(bias.X)
 160 	d2s[5] -= float64(bias.Y)
 161 	// Make adr relative to dr.Min.
 162 	adr = adr.Sub(dr.Min)
 163 	// sr is the source pixels. If it extends beyond the src bounds,
 164 	// we cannot use the type-specific fast paths, as they access
 165 	// the Pix fields directly without bounds checking.
 166 	//
 167 	// Similarly, the fast paths assume that the masks are nil.
 168 	if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
 169 		switch op {
 170 		case Over:
 171 			z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 172 		case Src:
 173 			z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 174 		}
 175 	} else if u, ok := src.(*image.Uniform); ok {
 176 		transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
 177 	} else {
 178 		switch op {
 179 		case Over:
 180 			switch dst := dst.(type) {
 181 			case *image.RGBA:
 182 				switch src := src.(type) {
 183 				case *image.NRGBA:
 184 					z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 185 				case *image.RGBA:
 186 					z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 187 				case image.RGBA64Image:
 188 					z.transform_RGBA_RGBA64Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 189 				default:
 190 					z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 191 				}
 192 			case RGBA64Image:
 193 				switch src := src.(type) {
 194 				case image.RGBA64Image:
 195 					z.transform_RGBA64Image_RGBA64Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 196 				}
 197 			default:
 198 				switch src := src.(type) {
 199 				default:
 200 					z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
 201 				}
 202 			}
 203 		case Src:
 204 			switch dst := dst.(type) {
 205 			case *image.RGBA:
 206 				switch src := src.(type) {
 207 				case *image.Gray:
 208 					z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 209 				case *image.NRGBA:
 210 					z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 211 				case *image.RGBA:
 212 					z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 213 				case *image.YCbCr:
 214 					switch src.SubsampleRatio {
 215 					default:
 216 						z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 217 					case image.YCbCrSubsampleRatio444:
 218 						z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 219 					case image.YCbCrSubsampleRatio422:
 220 						z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 221 					case image.YCbCrSubsampleRatio420:
 222 						z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 223 					case image.YCbCrSubsampleRatio440:
 224 						z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 225 					}
 226 				case image.RGBA64Image:
 227 					z.transform_RGBA_RGBA64Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 228 				default:
 229 					z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 230 				}
 231 			case RGBA64Image:
 232 				switch src := src.(type) {
 233 				case image.RGBA64Image:
 234 					z.transform_RGBA64Image_RGBA64Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 235 				}
 236 			default:
 237 				switch src := src.(type) {
 238 				default:
 239 					z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
 240 				}
 241 			}
 242 		}
 243 	}
 244 }
 245 
 246 func (nnInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) {
 247 	dw2 := uint64(dr.Dx()) * 2
 248 	dh2 := uint64(dr.Dy()) * 2
 249 	sw := uint64(sr.Dx())
 250 	sh := uint64(sr.Dy())
 251 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 252 		sy := (2*uint64(dy) + 1) * sh / dh2
 253 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 254 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 255 			sx := (2*uint64(dx) + 1) * sw / dw2
 256 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 257 			pr := uint32(src.Pix[pi]) * 0x101
 258 			out := uint8(pr >> 8)
 259 			dst.Pix[d+0] = out
 260 			dst.Pix[d+1] = out
 261 			dst.Pix[d+2] = out
 262 			dst.Pix[d+3] = 0xff
 263 		}
 264 	}
 265 }
 266 
 267 func (nnInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
 268 	dw2 := uint64(dr.Dx()) * 2
 269 	dh2 := uint64(dr.Dy()) * 2
 270 	sw := uint64(sr.Dx())
 271 	sh := uint64(sr.Dy())
 272 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 273 		sy := (2*uint64(dy) + 1) * sh / dh2
 274 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 275 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 276 			sx := (2*uint64(dx) + 1) * sw / dw2
 277 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
 278 			pa := uint32(src.Pix[pi+3]) * 0x101
 279 			pr := uint32(src.Pix[pi+0]) * pa / 0xff
 280 			pg := uint32(src.Pix[pi+1]) * pa / 0xff
 281 			pb := uint32(src.Pix[pi+2]) * pa / 0xff
 282 			pa1 := (0xffff - pa) * 0x101
 283 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
 284 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
 285 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
 286 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
 287 		}
 288 	}
 289 }
 290 
 291 func (nnInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
 292 	dw2 := uint64(dr.Dx()) * 2
 293 	dh2 := uint64(dr.Dy()) * 2
 294 	sw := uint64(sr.Dx())
 295 	sh := uint64(sr.Dy())
 296 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 297 		sy := (2*uint64(dy) + 1) * sh / dh2
 298 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 299 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 300 			sx := (2*uint64(dx) + 1) * sw / dw2
 301 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
 302 			pa := uint32(src.Pix[pi+3]) * 0x101
 303 			pr := uint32(src.Pix[pi+0]) * pa / 0xff
 304 			pg := uint32(src.Pix[pi+1]) * pa / 0xff
 305 			pb := uint32(src.Pix[pi+2]) * pa / 0xff
 306 			dst.Pix[d+0] = uint8(pr >> 8)
 307 			dst.Pix[d+1] = uint8(pg >> 8)
 308 			dst.Pix[d+2] = uint8(pb >> 8)
 309 			dst.Pix[d+3] = uint8(pa >> 8)
 310 		}
 311 	}
 312 }
 313 
 314 func (nnInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
 315 	dw2 := uint64(dr.Dx()) * 2
 316 	dh2 := uint64(dr.Dy()) * 2
 317 	sw := uint64(sr.Dx())
 318 	sh := uint64(sr.Dy())
 319 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 320 		sy := (2*uint64(dy) + 1) * sh / dh2
 321 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 322 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 323 			sx := (2*uint64(dx) + 1) * sw / dw2
 324 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
 325 			pr := uint32(src.Pix[pi+0]) * 0x101
 326 			pg := uint32(src.Pix[pi+1]) * 0x101
 327 			pb := uint32(src.Pix[pi+2]) * 0x101
 328 			pa := uint32(src.Pix[pi+3]) * 0x101
 329 			pa1 := (0xffff - pa) * 0x101
 330 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
 331 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
 332 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
 333 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
 334 		}
 335 	}
 336 }
 337 
 338 func (nnInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
 339 	dw2 := uint64(dr.Dx()) * 2
 340 	dh2 := uint64(dr.Dy()) * 2
 341 	sw := uint64(sr.Dx())
 342 	sh := uint64(sr.Dy())
 343 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 344 		sy := (2*uint64(dy) + 1) * sh / dh2
 345 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 346 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 347 			sx := (2*uint64(dx) + 1) * sw / dw2
 348 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4
 349 			pr := uint32(src.Pix[pi+0]) * 0x101
 350 			pg := uint32(src.Pix[pi+1]) * 0x101
 351 			pb := uint32(src.Pix[pi+2]) * 0x101
 352 			pa := uint32(src.Pix[pi+3]) * 0x101
 353 			dst.Pix[d+0] = uint8(pr >> 8)
 354 			dst.Pix[d+1] = uint8(pg >> 8)
 355 			dst.Pix[d+2] = uint8(pb >> 8)
 356 			dst.Pix[d+3] = uint8(pa >> 8)
 357 		}
 358 	}
 359 }
 360 
 361 func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
 362 	dw2 := uint64(dr.Dx()) * 2
 363 	dh2 := uint64(dr.Dy()) * 2
 364 	sw := uint64(sr.Dx())
 365 	sh := uint64(sr.Dy())
 366 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 367 		sy := (2*uint64(dy) + 1) * sh / dh2
 368 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 369 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 370 			sx := (2*uint64(dx) + 1) * sw / dw2
 371 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 372 			pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 373 
 374 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 375 			pyy1 := int(src.Y[pi]) * 0x10101
 376 			pcb1 := int(src.Cb[pj]) - 128
 377 			pcr1 := int(src.Cr[pj]) - 128
 378 			pr := (pyy1 + 91881*pcr1) >> 8
 379 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
 380 			pb := (pyy1 + 116130*pcb1) >> 8
 381 			if pr < 0 {
 382 				pr = 0
 383 			} else if pr > 0xffff {
 384 				pr = 0xffff
 385 			}
 386 			if pg < 0 {
 387 				pg = 0
 388 			} else if pg > 0xffff {
 389 				pg = 0xffff
 390 			}
 391 			if pb < 0 {
 392 				pb = 0
 393 			} else if pb > 0xffff {
 394 				pb = 0xffff
 395 			}
 396 			dst.Pix[d+0] = uint8(pr >> 8)
 397 			dst.Pix[d+1] = uint8(pg >> 8)
 398 			dst.Pix[d+2] = uint8(pb >> 8)
 399 			dst.Pix[d+3] = 0xff
 400 		}
 401 	}
 402 }
 403 
 404 func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
 405 	dw2 := uint64(dr.Dx()) * 2
 406 	dh2 := uint64(dr.Dy()) * 2
 407 	sw := uint64(sr.Dx())
 408 	sh := uint64(sr.Dy())
 409 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 410 		sy := (2*uint64(dy) + 1) * sh / dh2
 411 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 412 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 413 			sx := (2*uint64(dx) + 1) * sw / dw2
 414 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 415 			pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
 416 
 417 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 418 			pyy1 := int(src.Y[pi]) * 0x10101
 419 			pcb1 := int(src.Cb[pj]) - 128
 420 			pcr1 := int(src.Cr[pj]) - 128
 421 			pr := (pyy1 + 91881*pcr1) >> 8
 422 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
 423 			pb := (pyy1 + 116130*pcb1) >> 8
 424 			if pr < 0 {
 425 				pr = 0
 426 			} else if pr > 0xffff {
 427 				pr = 0xffff
 428 			}
 429 			if pg < 0 {
 430 				pg = 0
 431 			} else if pg > 0xffff {
 432 				pg = 0xffff
 433 			}
 434 			if pb < 0 {
 435 				pb = 0
 436 			} else if pb > 0xffff {
 437 				pb = 0xffff
 438 			}
 439 			dst.Pix[d+0] = uint8(pr >> 8)
 440 			dst.Pix[d+1] = uint8(pg >> 8)
 441 			dst.Pix[d+2] = uint8(pb >> 8)
 442 			dst.Pix[d+3] = 0xff
 443 		}
 444 	}
 445 }
 446 
 447 func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
 448 	dw2 := uint64(dr.Dx()) * 2
 449 	dh2 := uint64(dr.Dy()) * 2
 450 	sw := uint64(sr.Dx())
 451 	sh := uint64(sr.Dy())
 452 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 453 		sy := (2*uint64(dy) + 1) * sh / dh2
 454 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 455 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 456 			sx := (2*uint64(dx) + 1) * sw / dw2
 457 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 458 			pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2)
 459 
 460 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 461 			pyy1 := int(src.Y[pi]) * 0x10101
 462 			pcb1 := int(src.Cb[pj]) - 128
 463 			pcr1 := int(src.Cr[pj]) - 128
 464 			pr := (pyy1 + 91881*pcr1) >> 8
 465 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
 466 			pb := (pyy1 + 116130*pcb1) >> 8
 467 			if pr < 0 {
 468 				pr = 0
 469 			} else if pr > 0xffff {
 470 				pr = 0xffff
 471 			}
 472 			if pg < 0 {
 473 				pg = 0
 474 			} else if pg > 0xffff {
 475 				pg = 0xffff
 476 			}
 477 			if pb < 0 {
 478 				pb = 0
 479 			} else if pb > 0xffff {
 480 				pb = 0xffff
 481 			}
 482 			dst.Pix[d+0] = uint8(pr >> 8)
 483 			dst.Pix[d+1] = uint8(pg >> 8)
 484 			dst.Pix[d+2] = uint8(pb >> 8)
 485 			dst.Pix[d+3] = 0xff
 486 		}
 487 	}
 488 }
 489 
 490 func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
 491 	dw2 := uint64(dr.Dx()) * 2
 492 	dh2 := uint64(dr.Dy()) * 2
 493 	sw := uint64(sr.Dx())
 494 	sh := uint64(sr.Dy())
 495 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 496 		sy := (2*uint64(dy) + 1) * sh / dh2
 497 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 498 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 499 			sx := (2*uint64(dx) + 1) * sw / dw2
 500 			pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 501 			pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X)
 502 
 503 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 504 			pyy1 := int(src.Y[pi]) * 0x10101
 505 			pcb1 := int(src.Cb[pj]) - 128
 506 			pcr1 := int(src.Cr[pj]) - 128
 507 			pr := (pyy1 + 91881*pcr1) >> 8
 508 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
 509 			pb := (pyy1 + 116130*pcb1) >> 8
 510 			if pr < 0 {
 511 				pr = 0
 512 			} else if pr > 0xffff {
 513 				pr = 0xffff
 514 			}
 515 			if pg < 0 {
 516 				pg = 0
 517 			} else if pg > 0xffff {
 518 				pg = 0xffff
 519 			}
 520 			if pb < 0 {
 521 				pb = 0
 522 			} else if pb > 0xffff {
 523 				pb = 0xffff
 524 			}
 525 			dst.Pix[d+0] = uint8(pr >> 8)
 526 			dst.Pix[d+1] = uint8(pg >> 8)
 527 			dst.Pix[d+2] = uint8(pb >> 8)
 528 			dst.Pix[d+3] = 0xff
 529 		}
 530 	}
 531 }
 532 
 533 func (nnInterpolator) scale_RGBA_RGBA64Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
 534 	dw2 := uint64(dr.Dx()) * 2
 535 	dh2 := uint64(dr.Dy()) * 2
 536 	sw := uint64(sr.Dx())
 537 	sh := uint64(sr.Dy())
 538 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 539 		sy := (2*uint64(dy) + 1) * sh / dh2
 540 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 541 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 542 			sx := (2*uint64(dx) + 1) * sw / dw2
 543 			p := src.RGBA64At(sr.Min.X+int(sx), sr.Min.Y+int(sy))
 544 			pa1 := (0xffff - uint32(p.A)) * 0x101
 545 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + uint32(p.R)) >> 8)
 546 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + uint32(p.G)) >> 8)
 547 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + uint32(p.B)) >> 8)
 548 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + uint32(p.A)) >> 8)
 549 		}
 550 	}
 551 }
 552 
 553 func (nnInterpolator) scale_RGBA_RGBA64Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
 554 	dw2 := uint64(dr.Dx()) * 2
 555 	dh2 := uint64(dr.Dy()) * 2
 556 	sw := uint64(sr.Dx())
 557 	sh := uint64(sr.Dy())
 558 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 559 		sy := (2*uint64(dy) + 1) * sh / dh2
 560 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 561 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 562 			sx := (2*uint64(dx) + 1) * sw / dw2
 563 			p := src.RGBA64At(sr.Min.X+int(sx), sr.Min.Y+int(sy))
 564 			dst.Pix[d+0] = uint8(p.R >> 8)
 565 			dst.Pix[d+1] = uint8(p.G >> 8)
 566 			dst.Pix[d+2] = uint8(p.B >> 8)
 567 			dst.Pix[d+3] = uint8(p.A >> 8)
 568 		}
 569 	}
 570 }
 571 
 572 func (nnInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
 573 	dw2 := uint64(dr.Dx()) * 2
 574 	dh2 := uint64(dr.Dy()) * 2
 575 	sw := uint64(sr.Dx())
 576 	sh := uint64(sr.Dy())
 577 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 578 		sy := (2*uint64(dy) + 1) * sh / dh2
 579 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 580 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 581 			sx := (2*uint64(dx) + 1) * sw / dw2
 582 			pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
 583 			pa1 := (0xffff - pa) * 0x101
 584 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
 585 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
 586 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
 587 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
 588 		}
 589 	}
 590 }
 591 
 592 func (nnInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
 593 	dw2 := uint64(dr.Dx()) * 2
 594 	dh2 := uint64(dr.Dy()) * 2
 595 	sw := uint64(sr.Dx())
 596 	sh := uint64(sr.Dy())
 597 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 598 		sy := (2*uint64(dy) + 1) * sh / dh2
 599 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 600 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 601 			sx := (2*uint64(dx) + 1) * sw / dw2
 602 			pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
 603 			dst.Pix[d+0] = uint8(pr >> 8)
 604 			dst.Pix[d+1] = uint8(pg >> 8)
 605 			dst.Pix[d+2] = uint8(pb >> 8)
 606 			dst.Pix[d+3] = uint8(pa >> 8)
 607 		}
 608 	}
 609 }
 610 
 611 func (nnInterpolator) scale_RGBA64Image_RGBA64Image_Over(dst RGBA64Image, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
 612 	dw2 := uint64(dr.Dx()) * 2
 613 	dh2 := uint64(dr.Dy()) * 2
 614 	sw := uint64(sr.Dx())
 615 	sh := uint64(sr.Dy())
 616 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
 617 	dstMask, dmp := opts.DstMask, opts.DstMaskP
 618 	dstColorRGBA64 := color.RGBA64{}
 619 
 620 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 621 		sy := (2*uint64(dy) + 1) * sh / dh2
 622 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
 623 			sx := (2*uint64(dx) + 1) * sw / dw2
 624 			p := src.RGBA64At(sr.Min.X+int(sx), sr.Min.Y+int(sy))
 625 			if srcMask != nil {
 626 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
 627 				p.R = uint16(uint32(p.R) * ma / 0xffff)
 628 				p.G = uint16(uint32(p.G) * ma / 0xffff)
 629 				p.B = uint16(uint32(p.B) * ma / 0xffff)
 630 				p.A = uint16(uint32(p.A) * ma / 0xffff)
 631 			}
 632 			q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
 633 			if dstMask != nil {
 634 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
 635 				p.R = uint16(uint32(p.R) * ma / 0xffff)
 636 				p.G = uint16(uint32(p.G) * ma / 0xffff)
 637 				p.B = uint16(uint32(p.B) * ma / 0xffff)
 638 				p.A = uint16(uint32(p.A) * ma / 0xffff)
 639 			}
 640 			pa1 := 0xffff - uint32(p.A)
 641 			dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
 642 			dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
 643 			dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
 644 			dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
 645 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
 646 		}
 647 	}
 648 }
 649 
 650 func (nnInterpolator) scale_RGBA64Image_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
 651 	dw2 := uint64(dr.Dx()) * 2
 652 	dh2 := uint64(dr.Dy()) * 2
 653 	sw := uint64(sr.Dx())
 654 	sh := uint64(sr.Dy())
 655 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
 656 	dstMask, dmp := opts.DstMask, opts.DstMaskP
 657 	dstColorRGBA64 := color.RGBA64{}
 658 
 659 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 660 		sy := (2*uint64(dy) + 1) * sh / dh2
 661 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
 662 			sx := (2*uint64(dx) + 1) * sw / dw2
 663 			p := src.RGBA64At(sr.Min.X+int(sx), sr.Min.Y+int(sy))
 664 			if srcMask != nil {
 665 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
 666 				p.R = uint16(uint32(p.R) * ma / 0xffff)
 667 				p.G = uint16(uint32(p.G) * ma / 0xffff)
 668 				p.B = uint16(uint32(p.B) * ma / 0xffff)
 669 				p.A = uint16(uint32(p.A) * ma / 0xffff)
 670 			}
 671 			if dstMask != nil {
 672 				q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
 673 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
 674 				p.R = uint16(uint32(p.R) * ma / 0xffff)
 675 				p.G = uint16(uint32(p.G) * ma / 0xffff)
 676 				p.B = uint16(uint32(p.B) * ma / 0xffff)
 677 				p.A = uint16(uint32(p.A) * ma / 0xffff)
 678 				pa1 := 0xffff - ma
 679 				dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
 680 				dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
 681 				dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
 682 				dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
 683 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
 684 			} else {
 685 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), p)
 686 			}
 687 		}
 688 	}
 689 }
 690 
 691 func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
 692 	dw2 := uint64(dr.Dx()) * 2
 693 	dh2 := uint64(dr.Dy()) * 2
 694 	sw := uint64(sr.Dx())
 695 	sh := uint64(sr.Dy())
 696 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
 697 	dstMask, dmp := opts.DstMask, opts.DstMaskP
 698 	dstColorRGBA64 := &color.RGBA64{}
 699 	dstColor := color.Color(dstColorRGBA64)
 700 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 701 		sy := (2*uint64(dy) + 1) * sh / dh2
 702 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
 703 			sx := (2*uint64(dx) + 1) * sw / dw2
 704 			pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
 705 			if srcMask != nil {
 706 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
 707 				pr = pr * ma / 0xffff
 708 				pg = pg * ma / 0xffff
 709 				pb = pb * ma / 0xffff
 710 				pa = pa * ma / 0xffff
 711 			}
 712 			qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
 713 			if dstMask != nil {
 714 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
 715 				pr = pr * ma / 0xffff
 716 				pg = pg * ma / 0xffff
 717 				pb = pb * ma / 0xffff
 718 				pa = pa * ma / 0xffff
 719 			}
 720 			pa1 := 0xffff - pa
 721 			dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
 722 			dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
 723 			dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
 724 			dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
 725 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
 726 		}
 727 	}
 728 }
 729 
 730 func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
 731 	dw2 := uint64(dr.Dx()) * 2
 732 	dh2 := uint64(dr.Dy()) * 2
 733 	sw := uint64(sr.Dx())
 734 	sh := uint64(sr.Dy())
 735 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
 736 	dstMask, dmp := opts.DstMask, opts.DstMaskP
 737 	dstColorRGBA64 := &color.RGBA64{}
 738 	dstColor := color.Color(dstColorRGBA64)
 739 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 740 		sy := (2*uint64(dy) + 1) * sh / dh2
 741 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
 742 			sx := (2*uint64(dx) + 1) * sw / dw2
 743 			pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA()
 744 			if srcMask != nil {
 745 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA()
 746 				pr = pr * ma / 0xffff
 747 				pg = pg * ma / 0xffff
 748 				pb = pb * ma / 0xffff
 749 				pa = pa * ma / 0xffff
 750 			}
 751 			if dstMask != nil {
 752 				qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
 753 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
 754 				pr = pr * ma / 0xffff
 755 				pg = pg * ma / 0xffff
 756 				pb = pb * ma / 0xffff
 757 				pa = pa * ma / 0xffff
 758 				pa1 := 0xffff - ma
 759 				dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
 760 				dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
 761 				dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
 762 				dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
 763 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
 764 			} else {
 765 				dstColorRGBA64.R = uint16(pr)
 766 				dstColorRGBA64.G = uint16(pg)
 767 				dstColorRGBA64.B = uint16(pb)
 768 				dstColorRGBA64.A = uint16(pa)
 769 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
 770 			}
 771 		}
 772 	}
 773 }
 774 
 775 func (nnInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
 776 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 777 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 778 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 779 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 780 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 781 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 782 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 783 			if !(image.Point{sx0, sy0}).In(sr) {
 784 				continue
 785 			}
 786 			pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
 787 			pr := uint32(src.Pix[pi]) * 0x101
 788 			out := uint8(pr >> 8)
 789 			dst.Pix[d+0] = out
 790 			dst.Pix[d+1] = out
 791 			dst.Pix[d+2] = out
 792 			dst.Pix[d+3] = 0xff
 793 		}
 794 	}
 795 }
 796 
 797 func (nnInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
 798 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 799 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 800 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 801 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 802 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 803 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 804 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 805 			if !(image.Point{sx0, sy0}).In(sr) {
 806 				continue
 807 			}
 808 			pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
 809 			pa := uint32(src.Pix[pi+3]) * 0x101
 810 			pr := uint32(src.Pix[pi+0]) * pa / 0xff
 811 			pg := uint32(src.Pix[pi+1]) * pa / 0xff
 812 			pb := uint32(src.Pix[pi+2]) * pa / 0xff
 813 			pa1 := (0xffff - pa) * 0x101
 814 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
 815 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
 816 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
 817 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
 818 		}
 819 	}
 820 }
 821 
 822 func (nnInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
 823 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 824 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 825 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 826 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 827 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 828 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 829 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 830 			if !(image.Point{sx0, sy0}).In(sr) {
 831 				continue
 832 			}
 833 			pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
 834 			pa := uint32(src.Pix[pi+3]) * 0x101
 835 			pr := uint32(src.Pix[pi+0]) * pa / 0xff
 836 			pg := uint32(src.Pix[pi+1]) * pa / 0xff
 837 			pb := uint32(src.Pix[pi+2]) * pa / 0xff
 838 			dst.Pix[d+0] = uint8(pr >> 8)
 839 			dst.Pix[d+1] = uint8(pg >> 8)
 840 			dst.Pix[d+2] = uint8(pb >> 8)
 841 			dst.Pix[d+3] = uint8(pa >> 8)
 842 		}
 843 	}
 844 }
 845 
 846 func (nnInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
 847 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 848 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 849 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 850 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 851 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 852 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 853 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 854 			if !(image.Point{sx0, sy0}).In(sr) {
 855 				continue
 856 			}
 857 			pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
 858 			pr := uint32(src.Pix[pi+0]) * 0x101
 859 			pg := uint32(src.Pix[pi+1]) * 0x101
 860 			pb := uint32(src.Pix[pi+2]) * 0x101
 861 			pa := uint32(src.Pix[pi+3]) * 0x101
 862 			pa1 := (0xffff - pa) * 0x101
 863 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
 864 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
 865 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
 866 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
 867 		}
 868 	}
 869 }
 870 
 871 func (nnInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
 872 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 873 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 874 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 875 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 876 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 877 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 878 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 879 			if !(image.Point{sx0, sy0}).In(sr) {
 880 				continue
 881 			}
 882 			pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
 883 			pr := uint32(src.Pix[pi+0]) * 0x101
 884 			pg := uint32(src.Pix[pi+1]) * 0x101
 885 			pb := uint32(src.Pix[pi+2]) * 0x101
 886 			pa := uint32(src.Pix[pi+3]) * 0x101
 887 			dst.Pix[d+0] = uint8(pr >> 8)
 888 			dst.Pix[d+1] = uint8(pg >> 8)
 889 			dst.Pix[d+2] = uint8(pb >> 8)
 890 			dst.Pix[d+3] = uint8(pa >> 8)
 891 		}
 892 	}
 893 }
 894 
 895 func (nnInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
 896 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 897 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 898 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 899 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 900 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 901 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 902 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 903 			if !(image.Point{sx0, sy0}).In(sr) {
 904 				continue
 905 			}
 906 			pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
 907 			pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
 908 
 909 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 910 			pyy1 := int(src.Y[pi]) * 0x10101
 911 			pcb1 := int(src.Cb[pj]) - 128
 912 			pcr1 := int(src.Cr[pj]) - 128
 913 			pr := (pyy1 + 91881*pcr1) >> 8
 914 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
 915 			pb := (pyy1 + 116130*pcb1) >> 8
 916 			if pr < 0 {
 917 				pr = 0
 918 			} else if pr > 0xffff {
 919 				pr = 0xffff
 920 			}
 921 			if pg < 0 {
 922 				pg = 0
 923 			} else if pg > 0xffff {
 924 				pg = 0xffff
 925 			}
 926 			if pb < 0 {
 927 				pb = 0
 928 			} else if pb > 0xffff {
 929 				pb = 0xffff
 930 			}
 931 			dst.Pix[d+0] = uint8(pr >> 8)
 932 			dst.Pix[d+1] = uint8(pg >> 8)
 933 			dst.Pix[d+2] = uint8(pb >> 8)
 934 			dst.Pix[d+3] = 0xff
 935 		}
 936 	}
 937 }
 938 
 939 func (nnInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
 940 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 941 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 942 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 943 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 944 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 945 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 946 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 947 			if !(image.Point{sx0, sy0}).In(sr) {
 948 				continue
 949 			}
 950 			pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
 951 			pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
 952 
 953 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 954 			pyy1 := int(src.Y[pi]) * 0x10101
 955 			pcb1 := int(src.Cb[pj]) - 128
 956 			pcr1 := int(src.Cr[pj]) - 128
 957 			pr := (pyy1 + 91881*pcr1) >> 8
 958 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
 959 			pb := (pyy1 + 116130*pcb1) >> 8
 960 			if pr < 0 {
 961 				pr = 0
 962 			} else if pr > 0xffff {
 963 				pr = 0xffff
 964 			}
 965 			if pg < 0 {
 966 				pg = 0
 967 			} else if pg > 0xffff {
 968 				pg = 0xffff
 969 			}
 970 			if pb < 0 {
 971 				pb = 0
 972 			} else if pb > 0xffff {
 973 				pb = 0xffff
 974 			}
 975 			dst.Pix[d+0] = uint8(pr >> 8)
 976 			dst.Pix[d+1] = uint8(pg >> 8)
 977 			dst.Pix[d+2] = uint8(pb >> 8)
 978 			dst.Pix[d+3] = 0xff
 979 		}
 980 	}
 981 }
 982 
 983 func (nnInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
 984 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
 985 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
 986 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
 987 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
 988 			dxf := float64(dr.Min.X+int(dx)) + 0.5
 989 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
 990 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
 991 			if !(image.Point{sx0, sy0}).In(sr) {
 992 				continue
 993 			}
 994 			pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
 995 			pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
 996 
 997 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
 998 			pyy1 := int(src.Y[pi]) * 0x10101
 999 			pcb1 := int(src.Cb[pj]) - 128
1000 			pcr1 := int(src.Cr[pj]) - 128
1001 			pr := (pyy1 + 91881*pcr1) >> 8
1002 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
1003 			pb := (pyy1 + 116130*pcb1) >> 8
1004 			if pr < 0 {
1005 				pr = 0
1006 			} else if pr > 0xffff {
1007 				pr = 0xffff
1008 			}
1009 			if pg < 0 {
1010 				pg = 0
1011 			} else if pg > 0xffff {
1012 				pg = 0xffff
1013 			}
1014 			if pb < 0 {
1015 				pb = 0
1016 			} else if pb > 0xffff {
1017 				pb = 0xffff
1018 			}
1019 			dst.Pix[d+0] = uint8(pr >> 8)
1020 			dst.Pix[d+1] = uint8(pg >> 8)
1021 			dst.Pix[d+2] = uint8(pb >> 8)
1022 			dst.Pix[d+3] = 0xff
1023 		}
1024 	}
1025 }
1026 
1027 func (nnInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
1028 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1029 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1030 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1031 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1032 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1033 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1034 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1035 			if !(image.Point{sx0, sy0}).In(sr) {
1036 				continue
1037 			}
1038 			pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
1039 			pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
1040 
1041 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
1042 			pyy1 := int(src.Y[pi]) * 0x10101
1043 			pcb1 := int(src.Cb[pj]) - 128
1044 			pcr1 := int(src.Cr[pj]) - 128
1045 			pr := (pyy1 + 91881*pcr1) >> 8
1046 			pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
1047 			pb := (pyy1 + 116130*pcb1) >> 8
1048 			if pr < 0 {
1049 				pr = 0
1050 			} else if pr > 0xffff {
1051 				pr = 0xffff
1052 			}
1053 			if pg < 0 {
1054 				pg = 0
1055 			} else if pg > 0xffff {
1056 				pg = 0xffff
1057 			}
1058 			if pb < 0 {
1059 				pb = 0
1060 			} else if pb > 0xffff {
1061 				pb = 0xffff
1062 			}
1063 			dst.Pix[d+0] = uint8(pr >> 8)
1064 			dst.Pix[d+1] = uint8(pg >> 8)
1065 			dst.Pix[d+2] = uint8(pb >> 8)
1066 			dst.Pix[d+3] = 0xff
1067 		}
1068 	}
1069 }
1070 
1071 func (nnInterpolator) transform_RGBA_RGBA64Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
1072 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1073 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1074 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1075 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1076 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1077 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1078 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1079 			if !(image.Point{sx0, sy0}).In(sr) {
1080 				continue
1081 			}
1082 			p := src.RGBA64At(sx0, sy0)
1083 			pa1 := (0xffff - uint32(p.A)) * 0x101
1084 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + uint32(p.R)) >> 8)
1085 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + uint32(p.G)) >> 8)
1086 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + uint32(p.B)) >> 8)
1087 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + uint32(p.A)) >> 8)
1088 		}
1089 	}
1090 }
1091 
1092 func (nnInterpolator) transform_RGBA_RGBA64Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
1093 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1094 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1095 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1096 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1097 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1098 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1099 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1100 			if !(image.Point{sx0, sy0}).In(sr) {
1101 				continue
1102 			}
1103 			p := src.RGBA64At(sx0, sy0)
1104 			dst.Pix[d+0] = uint8(p.R >> 8)
1105 			dst.Pix[d+1] = uint8(p.G >> 8)
1106 			dst.Pix[d+2] = uint8(p.B >> 8)
1107 			dst.Pix[d+3] = uint8(p.A >> 8)
1108 		}
1109 	}
1110 }
1111 
1112 func (nnInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
1113 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1114 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1115 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1116 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1117 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1118 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1119 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1120 			if !(image.Point{sx0, sy0}).In(sr) {
1121 				continue
1122 			}
1123 			pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
1124 			pa1 := (0xffff - pa) * 0x101
1125 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
1126 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
1127 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
1128 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
1129 		}
1130 	}
1131 }
1132 
1133 func (nnInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
1134 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1135 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1136 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1137 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1138 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1139 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1140 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1141 			if !(image.Point{sx0, sy0}).In(sr) {
1142 				continue
1143 			}
1144 			pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
1145 			dst.Pix[d+0] = uint8(pr >> 8)
1146 			dst.Pix[d+1] = uint8(pg >> 8)
1147 			dst.Pix[d+2] = uint8(pb >> 8)
1148 			dst.Pix[d+3] = uint8(pa >> 8)
1149 		}
1150 	}
1151 }
1152 
1153 func (nnInterpolator) transform_RGBA64Image_RGBA64Image_Over(dst RGBA64Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
1154 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
1155 	dstMask, dmp := opts.DstMask, opts.DstMaskP
1156 	dstColorRGBA64 := color.RGBA64{}
1157 
1158 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1159 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1160 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
1161 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1162 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1163 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1164 			if !(image.Point{sx0, sy0}).In(sr) {
1165 				continue
1166 			}
1167 			p := src.RGBA64At(sx0, sy0)
1168 			if srcMask != nil {
1169 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
1170 				p.R = uint16(uint32(p.R) * ma / 0xffff)
1171 				p.G = uint16(uint32(p.G) * ma / 0xffff)
1172 				p.B = uint16(uint32(p.B) * ma / 0xffff)
1173 				p.A = uint16(uint32(p.A) * ma / 0xffff)
1174 			}
1175 			q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
1176 			if dstMask != nil {
1177 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
1178 				p.R = uint16(uint32(p.R) * ma / 0xffff)
1179 				p.G = uint16(uint32(p.G) * ma / 0xffff)
1180 				p.B = uint16(uint32(p.B) * ma / 0xffff)
1181 				p.A = uint16(uint32(p.A) * ma / 0xffff)
1182 			}
1183 			pa1 := 0xffff - uint32(p.A)
1184 			dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
1185 			dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
1186 			dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
1187 			dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
1188 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
1189 		}
1190 	}
1191 }
1192 
1193 func (nnInterpolator) transform_RGBA64Image_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
1194 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
1195 	dstMask, dmp := opts.DstMask, opts.DstMaskP
1196 	dstColorRGBA64 := color.RGBA64{}
1197 
1198 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1199 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1200 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
1201 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1202 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1203 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1204 			if !(image.Point{sx0, sy0}).In(sr) {
1205 				continue
1206 			}
1207 			p := src.RGBA64At(sx0, sy0)
1208 			if srcMask != nil {
1209 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
1210 				p.R = uint16(uint32(p.R) * ma / 0xffff)
1211 				p.G = uint16(uint32(p.G) * ma / 0xffff)
1212 				p.B = uint16(uint32(p.B) * ma / 0xffff)
1213 				p.A = uint16(uint32(p.A) * ma / 0xffff)
1214 			}
1215 			if dstMask != nil {
1216 				q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
1217 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
1218 				p.R = uint16(uint32(p.R) * ma / 0xffff)
1219 				p.G = uint16(uint32(p.G) * ma / 0xffff)
1220 				p.B = uint16(uint32(p.B) * ma / 0xffff)
1221 				p.A = uint16(uint32(p.A) * ma / 0xffff)
1222 				pa1 := 0xffff - ma
1223 				dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
1224 				dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
1225 				dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
1226 				dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
1227 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
1228 			} else {
1229 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), p)
1230 			}
1231 		}
1232 	}
1233 }
1234 
1235 func (nnInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
1236 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
1237 	dstMask, dmp := opts.DstMask, opts.DstMaskP
1238 	dstColorRGBA64 := &color.RGBA64{}
1239 	dstColor := color.Color(dstColorRGBA64)
1240 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1241 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1242 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
1243 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1244 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1245 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1246 			if !(image.Point{sx0, sy0}).In(sr) {
1247 				continue
1248 			}
1249 			pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
1250 			if srcMask != nil {
1251 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
1252 				pr = pr * ma / 0xffff
1253 				pg = pg * ma / 0xffff
1254 				pb = pb * ma / 0xffff
1255 				pa = pa * ma / 0xffff
1256 			}
1257 			qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
1258 			if dstMask != nil {
1259 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
1260 				pr = pr * ma / 0xffff
1261 				pg = pg * ma / 0xffff
1262 				pb = pb * ma / 0xffff
1263 				pa = pa * ma / 0xffff
1264 			}
1265 			pa1 := 0xffff - pa
1266 			dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
1267 			dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
1268 			dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
1269 			dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
1270 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
1271 		}
1272 	}
1273 }
1274 
1275 func (nnInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
1276 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
1277 	dstMask, dmp := opts.DstMask, opts.DstMaskP
1278 	dstColorRGBA64 := &color.RGBA64{}
1279 	dstColor := color.Color(dstColorRGBA64)
1280 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1281 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
1282 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
1283 			dxf := float64(dr.Min.X+int(dx)) + 0.5
1284 			sx0 := int(float64(d2s[0]*dxf)+float64(d2s[1]*dyf)+d2s[2]) + bias.X
1285 			sy0 := int(float64(d2s[3]*dxf)+float64(d2s[4]*dyf)+d2s[5]) + bias.Y
1286 			if !(image.Point{sx0, sy0}).In(sr) {
1287 				continue
1288 			}
1289 			pr, pg, pb, pa := src.At(sx0, sy0).RGBA()
1290 			if srcMask != nil {
1291 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
1292 				pr = pr * ma / 0xffff
1293 				pg = pg * ma / 0xffff
1294 				pb = pb * ma / 0xffff
1295 				pa = pa * ma / 0xffff
1296 			}
1297 			if dstMask != nil {
1298 				qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
1299 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
1300 				pr = pr * ma / 0xffff
1301 				pg = pg * ma / 0xffff
1302 				pb = pb * ma / 0xffff
1303 				pa = pa * ma / 0xffff
1304 				pa1 := 0xffff - ma
1305 				dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
1306 				dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
1307 				dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
1308 				dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
1309 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
1310 			} else {
1311 				dstColorRGBA64.R = uint16(pr)
1312 				dstColorRGBA64.G = uint16(pg)
1313 				dstColorRGBA64.B = uint16(pb)
1314 				dstColorRGBA64.A = uint16(pa)
1315 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
1316 			}
1317 		}
1318 	}
1319 }
1320 
1321 func (z ablInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
1322 	// Try to simplify a Scale to a Copy when DstMask is not specified.
1323 	// If DstMask is not nil, Copy will call Scale back with same dr and sr, and cause stack overflow.
1324 	if dr.Size() == sr.Size() && (opts == nil || opts.DstMask == nil) {
1325 		Copy(dst, dr.Min, src, sr, op, opts)
1326 		return
1327 	}
1328 
1329 	var o Options
1330 	if opts != nil {
1331 		o = *opts
1332 	}
1333 
1334 	// adr is the affected destination pixels.
1335 	adr := dst.Bounds().Intersect(dr)
1336 	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
1337 	if adr.Empty() || sr.Empty() {
1338 		return
1339 	}
1340 	// Make adr relative to dr.Min.
1341 	adr = adr.Sub(dr.Min)
1342 	if op == Over && o.SrcMask == nil && opaque(src) {
1343 		op = Src
1344 	}
1345 
1346 	// sr is the source pixels. If it extends beyond the src bounds,
1347 	// we cannot use the type-specific fast paths, as they access
1348 	// the Pix fields directly without bounds checking.
1349 	//
1350 	// Similarly, the fast paths assume that the masks are nil.
1351 	if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
1352 		switch op {
1353 		case Over:
1354 			z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
1355 		case Src:
1356 			z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
1357 		}
1358 	} else if _, ok := src.(*image.Uniform); ok {
1359 		Draw(dst, dr, src, src.Bounds().Min, op)
1360 	} else {
1361 		switch op {
1362 		case Over:
1363 			switch dst := dst.(type) {
1364 			case *image.RGBA:
1365 				switch src := src.(type) {
1366 				case *image.NRGBA:
1367 					z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o)
1368 				case *image.RGBA:
1369 					z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o)
1370 				case image.RGBA64Image:
1371 					z.scale_RGBA_RGBA64Image_Over(dst, dr, adr, src, sr, &o)
1372 				default:
1373 					z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o)
1374 				}
1375 			case RGBA64Image:
1376 				switch src := src.(type) {
1377 				case image.RGBA64Image:
1378 					z.scale_RGBA64Image_RGBA64Image_Over(dst, dr, adr, src, sr, &o)
1379 				}
1380 			default:
1381 				switch src := src.(type) {
1382 				default:
1383 					z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o)
1384 				}
1385 			}
1386 		case Src:
1387 			switch dst := dst.(type) {
1388 			case *image.RGBA:
1389 				switch src := src.(type) {
1390 				case *image.Gray:
1391 					z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o)
1392 				case *image.NRGBA:
1393 					z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o)
1394 				case *image.RGBA:
1395 					z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o)
1396 				case *image.YCbCr:
1397 					switch src.SubsampleRatio {
1398 					default:
1399 						z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
1400 					case image.YCbCrSubsampleRatio444:
1401 						z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o)
1402 					case image.YCbCrSubsampleRatio422:
1403 						z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o)
1404 					case image.YCbCrSubsampleRatio420:
1405 						z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o)
1406 					case image.YCbCrSubsampleRatio440:
1407 						z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o)
1408 					}
1409 				case image.RGBA64Image:
1410 					z.scale_RGBA_RGBA64Image_Src(dst, dr, adr, src, sr, &o)
1411 				default:
1412 					z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o)
1413 				}
1414 			case RGBA64Image:
1415 				switch src := src.(type) {
1416 				case image.RGBA64Image:
1417 					z.scale_RGBA64Image_RGBA64Image_Src(dst, dr, adr, src, sr, &o)
1418 				}
1419 			default:
1420 				switch src := src.(type) {
1421 				default:
1422 					z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o)
1423 				}
1424 			}
1425 		}
1426 	}
1427 }
1428 
1429 func (z ablInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
1430 	// Try to simplify a Transform to a Copy.
1431 	if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 {
1432 		dx := int(s2d[2])
1433 		dy := int(s2d[5])
1434 		if float64(dx) == s2d[2] && float64(dy) == s2d[5] {
1435 			Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts)
1436 			return
1437 		}
1438 	}
1439 
1440 	var o Options
1441 	if opts != nil {
1442 		o = *opts
1443 	}
1444 
1445 	dr := transformRect(&s2d, &sr)
1446 	// adr is the affected destination pixels.
1447 	adr := dst.Bounds().Intersect(dr)
1448 	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
1449 	if adr.Empty() || sr.Empty() {
1450 		return
1451 	}
1452 	if op == Over && o.SrcMask == nil && opaque(src) {
1453 		op = Src
1454 	}
1455 
1456 	d2s := invert(&s2d)
1457 	// bias is a translation of the mapping from dst coordinates to src
1458 	// coordinates such that the latter temporarily have non-negative X
1459 	// and Y coordinates. This allows us to write int(f) instead of
1460 	// int(math.Floor(f)), since "round to zero" and "round down" are
1461 	// equivalent when f >= 0, but the former is much cheaper. The X--
1462 	// and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
1463 	// adjustment.
1464 	bias := transformRect(&d2s, &adr).Min
1465 	bias.X--
1466 	bias.Y--
1467 	d2s[2] -= float64(bias.X)
1468 	d2s[5] -= float64(bias.Y)
1469 	// Make adr relative to dr.Min.
1470 	adr = adr.Sub(dr.Min)
1471 	// sr is the source pixels. If it extends beyond the src bounds,
1472 	// we cannot use the type-specific fast paths, as they access
1473 	// the Pix fields directly without bounds checking.
1474 	//
1475 	// Similarly, the fast paths assume that the masks are nil.
1476 	if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
1477 		switch op {
1478 		case Over:
1479 			z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1480 		case Src:
1481 			z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1482 		}
1483 	} else if u, ok := src.(*image.Uniform); ok {
1484 		transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
1485 	} else {
1486 		switch op {
1487 		case Over:
1488 			switch dst := dst.(type) {
1489 			case *image.RGBA:
1490 				switch src := src.(type) {
1491 				case *image.NRGBA:
1492 					z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1493 				case *image.RGBA:
1494 					z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1495 				case image.RGBA64Image:
1496 					z.transform_RGBA_RGBA64Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1497 				default:
1498 					z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1499 				}
1500 			case RGBA64Image:
1501 				switch src := src.(type) {
1502 				case image.RGBA64Image:
1503 					z.transform_RGBA64Image_RGBA64Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1504 				}
1505 			default:
1506 				switch src := src.(type) {
1507 				default:
1508 					z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o)
1509 				}
1510 			}
1511 		case Src:
1512 			switch dst := dst.(type) {
1513 			case *image.RGBA:
1514 				switch src := src.(type) {
1515 				case *image.Gray:
1516 					z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1517 				case *image.NRGBA:
1518 					z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1519 				case *image.RGBA:
1520 					z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1521 				case *image.YCbCr:
1522 					switch src.SubsampleRatio {
1523 					default:
1524 						z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1525 					case image.YCbCrSubsampleRatio444:
1526 						z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1527 					case image.YCbCrSubsampleRatio422:
1528 						z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1529 					case image.YCbCrSubsampleRatio420:
1530 						z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1531 					case image.YCbCrSubsampleRatio440:
1532 						z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1533 					}
1534 				case image.RGBA64Image:
1535 					z.transform_RGBA_RGBA64Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1536 				default:
1537 					z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1538 				}
1539 			case RGBA64Image:
1540 				switch src := src.(type) {
1541 				case image.RGBA64Image:
1542 					z.transform_RGBA64Image_RGBA64Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1543 				}
1544 			default:
1545 				switch src := src.(type) {
1546 				default:
1547 					z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o)
1548 				}
1549 			}
1550 		}
1551 	}
1552 }
1553 
1554 func (ablInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) {
1555 	sw := int32(sr.Dx())
1556 	sh := int32(sr.Dy())
1557 	yscale := float64(sh) / float64(dr.Dy())
1558 	xscale := float64(sw) / float64(dr.Dx())
1559 	swMinus1, shMinus1 := sw-1, sh-1
1560 
1561 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1562 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
1563 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
1564 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
1565 		// sx, below.
1566 		sy0 := int32(sy)
1567 		yFrac0 := sy - float64(sy0)
1568 		yFrac1 := 1 - yFrac0
1569 		sy1 := sy0 + 1
1570 		if sy < 0 {
1571 			sy0, sy1 = 0, 0
1572 			yFrac0, yFrac1 = 0, 1
1573 		} else if sy1 > shMinus1 {
1574 			sy0, sy1 = shMinus1, shMinus1
1575 			yFrac0, yFrac1 = 1, 0
1576 		}
1577 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1578 
1579 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1580 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
1581 			sx0 := int32(sx)
1582 			xFrac0 := sx - float64(sx0)
1583 			xFrac1 := 1 - xFrac0
1584 			sx1 := sx0 + 1
1585 			if sx < 0 {
1586 				sx0, sx1 = 0, 0
1587 				xFrac0, xFrac1 = 0, 1
1588 			} else if sx1 > swMinus1 {
1589 				sx0, sx1 = swMinus1, swMinus1
1590 				xFrac0, xFrac1 = 1, 0
1591 			}
1592 
1593 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
1594 			s00ru := uint32(src.Pix[s00i]) * 0x101
1595 			s00r := float64(s00ru)
1596 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
1597 			s10ru := uint32(src.Pix[s10i]) * 0x101
1598 			s10r := float64(s10ru)
1599 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
1600 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
1601 			s01ru := uint32(src.Pix[s01i]) * 0x101
1602 			s01r := float64(s01ru)
1603 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
1604 			s11ru := uint32(src.Pix[s11i]) * 0x101
1605 			s11r := float64(s11ru)
1606 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
1607 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
1608 			pr := uint32(s11r)
1609 			out := uint8(pr >> 8)
1610 			dst.Pix[d+0] = out
1611 			dst.Pix[d+1] = out
1612 			dst.Pix[d+2] = out
1613 			dst.Pix[d+3] = 0xff
1614 		}
1615 	}
1616 }
1617 
1618 func (ablInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
1619 	sw := int32(sr.Dx())
1620 	sh := int32(sr.Dy())
1621 	yscale := float64(sh) / float64(dr.Dy())
1622 	xscale := float64(sw) / float64(dr.Dx())
1623 	swMinus1, shMinus1 := sw-1, sh-1
1624 
1625 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1626 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
1627 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
1628 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
1629 		// sx, below.
1630 		sy0 := int32(sy)
1631 		yFrac0 := sy - float64(sy0)
1632 		yFrac1 := 1 - yFrac0
1633 		sy1 := sy0 + 1
1634 		if sy < 0 {
1635 			sy0, sy1 = 0, 0
1636 			yFrac0, yFrac1 = 0, 1
1637 		} else if sy1 > shMinus1 {
1638 			sy0, sy1 = shMinus1, shMinus1
1639 			yFrac0, yFrac1 = 1, 0
1640 		}
1641 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1642 
1643 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1644 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
1645 			sx0 := int32(sx)
1646 			xFrac0 := sx - float64(sx0)
1647 			xFrac1 := 1 - xFrac0
1648 			sx1 := sx0 + 1
1649 			if sx < 0 {
1650 				sx0, sx1 = 0, 0
1651 				xFrac0, xFrac1 = 0, 1
1652 			} else if sx1 > swMinus1 {
1653 				sx0, sx1 = swMinus1, swMinus1
1654 				xFrac0, xFrac1 = 1, 0
1655 			}
1656 
1657 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1658 			s00au := uint32(src.Pix[s00i+3]) * 0x101
1659 			s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
1660 			s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
1661 			s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
1662 			s00r := float64(s00ru)
1663 			s00g := float64(s00gu)
1664 			s00b := float64(s00bu)
1665 			s00a := float64(s00au)
1666 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1667 			s10au := uint32(src.Pix[s10i+3]) * 0x101
1668 			s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
1669 			s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
1670 			s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
1671 			s10r := float64(s10ru)
1672 			s10g := float64(s10gu)
1673 			s10b := float64(s10bu)
1674 			s10a := float64(s10au)
1675 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
1676 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
1677 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
1678 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
1679 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1680 			s01au := uint32(src.Pix[s01i+3]) * 0x101
1681 			s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
1682 			s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
1683 			s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
1684 			s01r := float64(s01ru)
1685 			s01g := float64(s01gu)
1686 			s01b := float64(s01bu)
1687 			s01a := float64(s01au)
1688 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1689 			s11au := uint32(src.Pix[s11i+3]) * 0x101
1690 			s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
1691 			s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
1692 			s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
1693 			s11r := float64(s11ru)
1694 			s11g := float64(s11gu)
1695 			s11b := float64(s11bu)
1696 			s11a := float64(s11au)
1697 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
1698 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
1699 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
1700 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
1701 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
1702 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
1703 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
1704 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
1705 			pr := uint32(s11r)
1706 			pg := uint32(s11g)
1707 			pb := uint32(s11b)
1708 			pa := uint32(s11a)
1709 			pa1 := (0xffff - pa) * 0x101
1710 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
1711 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
1712 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
1713 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
1714 		}
1715 	}
1716 }
1717 
1718 func (ablInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) {
1719 	sw := int32(sr.Dx())
1720 	sh := int32(sr.Dy())
1721 	yscale := float64(sh) / float64(dr.Dy())
1722 	xscale := float64(sw) / float64(dr.Dx())
1723 	swMinus1, shMinus1 := sw-1, sh-1
1724 
1725 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1726 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
1727 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
1728 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
1729 		// sx, below.
1730 		sy0 := int32(sy)
1731 		yFrac0 := sy - float64(sy0)
1732 		yFrac1 := 1 - yFrac0
1733 		sy1 := sy0 + 1
1734 		if sy < 0 {
1735 			sy0, sy1 = 0, 0
1736 			yFrac0, yFrac1 = 0, 1
1737 		} else if sy1 > shMinus1 {
1738 			sy0, sy1 = shMinus1, shMinus1
1739 			yFrac0, yFrac1 = 1, 0
1740 		}
1741 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1742 
1743 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1744 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
1745 			sx0 := int32(sx)
1746 			xFrac0 := sx - float64(sx0)
1747 			xFrac1 := 1 - xFrac0
1748 			sx1 := sx0 + 1
1749 			if sx < 0 {
1750 				sx0, sx1 = 0, 0
1751 				xFrac0, xFrac1 = 0, 1
1752 			} else if sx1 > swMinus1 {
1753 				sx0, sx1 = swMinus1, swMinus1
1754 				xFrac0, xFrac1 = 1, 0
1755 			}
1756 
1757 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1758 			s00au := uint32(src.Pix[s00i+3]) * 0x101
1759 			s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
1760 			s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
1761 			s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
1762 			s00r := float64(s00ru)
1763 			s00g := float64(s00gu)
1764 			s00b := float64(s00bu)
1765 			s00a := float64(s00au)
1766 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1767 			s10au := uint32(src.Pix[s10i+3]) * 0x101
1768 			s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
1769 			s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
1770 			s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
1771 			s10r := float64(s10ru)
1772 			s10g := float64(s10gu)
1773 			s10b := float64(s10bu)
1774 			s10a := float64(s10au)
1775 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
1776 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
1777 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
1778 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
1779 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1780 			s01au := uint32(src.Pix[s01i+3]) * 0x101
1781 			s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
1782 			s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
1783 			s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
1784 			s01r := float64(s01ru)
1785 			s01g := float64(s01gu)
1786 			s01b := float64(s01bu)
1787 			s01a := float64(s01au)
1788 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1789 			s11au := uint32(src.Pix[s11i+3]) * 0x101
1790 			s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
1791 			s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
1792 			s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
1793 			s11r := float64(s11ru)
1794 			s11g := float64(s11gu)
1795 			s11b := float64(s11bu)
1796 			s11a := float64(s11au)
1797 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
1798 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
1799 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
1800 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
1801 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
1802 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
1803 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
1804 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
1805 			pr := uint32(s11r)
1806 			pg := uint32(s11g)
1807 			pb := uint32(s11b)
1808 			pa := uint32(s11a)
1809 			dst.Pix[d+0] = uint8(pr >> 8)
1810 			dst.Pix[d+1] = uint8(pg >> 8)
1811 			dst.Pix[d+2] = uint8(pb >> 8)
1812 			dst.Pix[d+3] = uint8(pa >> 8)
1813 		}
1814 	}
1815 }
1816 
1817 func (ablInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
1818 	sw := int32(sr.Dx())
1819 	sh := int32(sr.Dy())
1820 	yscale := float64(sh) / float64(dr.Dy())
1821 	xscale := float64(sw) / float64(dr.Dx())
1822 	swMinus1, shMinus1 := sw-1, sh-1
1823 
1824 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1825 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
1826 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
1827 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
1828 		// sx, below.
1829 		sy0 := int32(sy)
1830 		yFrac0 := sy - float64(sy0)
1831 		yFrac1 := 1 - yFrac0
1832 		sy1 := sy0 + 1
1833 		if sy < 0 {
1834 			sy0, sy1 = 0, 0
1835 			yFrac0, yFrac1 = 0, 1
1836 		} else if sy1 > shMinus1 {
1837 			sy0, sy1 = shMinus1, shMinus1
1838 			yFrac0, yFrac1 = 1, 0
1839 		}
1840 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1841 
1842 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1843 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
1844 			sx0 := int32(sx)
1845 			xFrac0 := sx - float64(sx0)
1846 			xFrac1 := 1 - xFrac0
1847 			sx1 := sx0 + 1
1848 			if sx < 0 {
1849 				sx0, sx1 = 0, 0
1850 				xFrac0, xFrac1 = 0, 1
1851 			} else if sx1 > swMinus1 {
1852 				sx0, sx1 = swMinus1, swMinus1
1853 				xFrac0, xFrac1 = 1, 0
1854 			}
1855 
1856 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1857 			s00ru := uint32(src.Pix[s00i+0]) * 0x101
1858 			s00gu := uint32(src.Pix[s00i+1]) * 0x101
1859 			s00bu := uint32(src.Pix[s00i+2]) * 0x101
1860 			s00au := uint32(src.Pix[s00i+3]) * 0x101
1861 			s00r := float64(s00ru)
1862 			s00g := float64(s00gu)
1863 			s00b := float64(s00bu)
1864 			s00a := float64(s00au)
1865 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1866 			s10ru := uint32(src.Pix[s10i+0]) * 0x101
1867 			s10gu := uint32(src.Pix[s10i+1]) * 0x101
1868 			s10bu := uint32(src.Pix[s10i+2]) * 0x101
1869 			s10au := uint32(src.Pix[s10i+3]) * 0x101
1870 			s10r := float64(s10ru)
1871 			s10g := float64(s10gu)
1872 			s10b := float64(s10bu)
1873 			s10a := float64(s10au)
1874 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
1875 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
1876 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
1877 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
1878 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1879 			s01ru := uint32(src.Pix[s01i+0]) * 0x101
1880 			s01gu := uint32(src.Pix[s01i+1]) * 0x101
1881 			s01bu := uint32(src.Pix[s01i+2]) * 0x101
1882 			s01au := uint32(src.Pix[s01i+3]) * 0x101
1883 			s01r := float64(s01ru)
1884 			s01g := float64(s01gu)
1885 			s01b := float64(s01bu)
1886 			s01a := float64(s01au)
1887 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1888 			s11ru := uint32(src.Pix[s11i+0]) * 0x101
1889 			s11gu := uint32(src.Pix[s11i+1]) * 0x101
1890 			s11bu := uint32(src.Pix[s11i+2]) * 0x101
1891 			s11au := uint32(src.Pix[s11i+3]) * 0x101
1892 			s11r := float64(s11ru)
1893 			s11g := float64(s11gu)
1894 			s11b := float64(s11bu)
1895 			s11a := float64(s11au)
1896 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
1897 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
1898 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
1899 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
1900 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
1901 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
1902 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
1903 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
1904 			pr := uint32(s11r)
1905 			pg := uint32(s11g)
1906 			pb := uint32(s11b)
1907 			pa := uint32(s11a)
1908 			pa1 := (0xffff - pa) * 0x101
1909 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
1910 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
1911 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
1912 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
1913 		}
1914 	}
1915 }
1916 
1917 func (ablInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) {
1918 	sw := int32(sr.Dx())
1919 	sh := int32(sr.Dy())
1920 	yscale := float64(sh) / float64(dr.Dy())
1921 	xscale := float64(sw) / float64(dr.Dx())
1922 	swMinus1, shMinus1 := sw-1, sh-1
1923 
1924 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
1925 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
1926 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
1927 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
1928 		// sx, below.
1929 		sy0 := int32(sy)
1930 		yFrac0 := sy - float64(sy0)
1931 		yFrac1 := 1 - yFrac0
1932 		sy1 := sy0 + 1
1933 		if sy < 0 {
1934 			sy0, sy1 = 0, 0
1935 			yFrac0, yFrac1 = 0, 1
1936 		} else if sy1 > shMinus1 {
1937 			sy0, sy1 = shMinus1, shMinus1
1938 			yFrac0, yFrac1 = 1, 0
1939 		}
1940 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
1941 
1942 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
1943 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
1944 			sx0 := int32(sx)
1945 			xFrac0 := sx - float64(sx0)
1946 			xFrac1 := 1 - xFrac0
1947 			sx1 := sx0 + 1
1948 			if sx < 0 {
1949 				sx0, sx1 = 0, 0
1950 				xFrac0, xFrac1 = 0, 1
1951 			} else if sx1 > swMinus1 {
1952 				sx0, sx1 = swMinus1, swMinus1
1953 				xFrac0, xFrac1 = 1, 0
1954 			}
1955 
1956 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1957 			s00ru := uint32(src.Pix[s00i+0]) * 0x101
1958 			s00gu := uint32(src.Pix[s00i+1]) * 0x101
1959 			s00bu := uint32(src.Pix[s00i+2]) * 0x101
1960 			s00au := uint32(src.Pix[s00i+3]) * 0x101
1961 			s00r := float64(s00ru)
1962 			s00g := float64(s00gu)
1963 			s00b := float64(s00bu)
1964 			s00a := float64(s00au)
1965 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1966 			s10ru := uint32(src.Pix[s10i+0]) * 0x101
1967 			s10gu := uint32(src.Pix[s10i+1]) * 0x101
1968 			s10bu := uint32(src.Pix[s10i+2]) * 0x101
1969 			s10au := uint32(src.Pix[s10i+3]) * 0x101
1970 			s10r := float64(s10ru)
1971 			s10g := float64(s10gu)
1972 			s10b := float64(s10bu)
1973 			s10a := float64(s10au)
1974 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
1975 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
1976 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
1977 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
1978 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4
1979 			s01ru := uint32(src.Pix[s01i+0]) * 0x101
1980 			s01gu := uint32(src.Pix[s01i+1]) * 0x101
1981 			s01bu := uint32(src.Pix[s01i+2]) * 0x101
1982 			s01au := uint32(src.Pix[s01i+3]) * 0x101
1983 			s01r := float64(s01ru)
1984 			s01g := float64(s01gu)
1985 			s01b := float64(s01bu)
1986 			s01a := float64(s01au)
1987 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4
1988 			s11ru := uint32(src.Pix[s11i+0]) * 0x101
1989 			s11gu := uint32(src.Pix[s11i+1]) * 0x101
1990 			s11bu := uint32(src.Pix[s11i+2]) * 0x101
1991 			s11au := uint32(src.Pix[s11i+3]) * 0x101
1992 			s11r := float64(s11ru)
1993 			s11g := float64(s11gu)
1994 			s11b := float64(s11bu)
1995 			s11a := float64(s11au)
1996 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
1997 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
1998 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
1999 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
2000 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2001 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2002 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2003 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
2004 			pr := uint32(s11r)
2005 			pg := uint32(s11g)
2006 			pb := uint32(s11b)
2007 			pa := uint32(s11a)
2008 			dst.Pix[d+0] = uint8(pr >> 8)
2009 			dst.Pix[d+1] = uint8(pg >> 8)
2010 			dst.Pix[d+2] = uint8(pb >> 8)
2011 			dst.Pix[d+3] = uint8(pa >> 8)
2012 		}
2013 	}
2014 }
2015 
2016 func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
2017 	sw := int32(sr.Dx())
2018 	sh := int32(sr.Dy())
2019 	yscale := float64(sh) / float64(dr.Dy())
2020 	xscale := float64(sw) / float64(dr.Dx())
2021 	swMinus1, shMinus1 := sw-1, sh-1
2022 
2023 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2024 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2025 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2026 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2027 		// sx, below.
2028 		sy0 := int32(sy)
2029 		yFrac0 := sy - float64(sy0)
2030 		yFrac1 := 1 - yFrac0
2031 		sy1 := sy0 + 1
2032 		if sy < 0 {
2033 			sy0, sy1 = 0, 0
2034 			yFrac0, yFrac1 = 0, 1
2035 		} else if sy1 > shMinus1 {
2036 			sy0, sy1 = shMinus1, shMinus1
2037 			yFrac0, yFrac1 = 1, 0
2038 		}
2039 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2040 
2041 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2042 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2043 			sx0 := int32(sx)
2044 			xFrac0 := sx - float64(sx0)
2045 			xFrac1 := 1 - xFrac0
2046 			sx1 := sx0 + 1
2047 			if sx < 0 {
2048 				sx0, sx1 = 0, 0
2049 				xFrac0, xFrac1 = 0, 1
2050 			} else if sx1 > swMinus1 {
2051 				sx0, sx1 = swMinus1, swMinus1
2052 				xFrac0, xFrac1 = 1, 0
2053 			}
2054 
2055 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2056 			s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2057 
2058 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2059 			s00yy1 := int(src.Y[s00i]) * 0x10101
2060 			s00cb1 := int(src.Cb[s00j]) - 128
2061 			s00cr1 := int(src.Cr[s00j]) - 128
2062 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
2063 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
2064 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
2065 			if s00ru < 0 {
2066 				s00ru = 0
2067 			} else if s00ru > 0xffff {
2068 				s00ru = 0xffff
2069 			}
2070 			if s00gu < 0 {
2071 				s00gu = 0
2072 			} else if s00gu > 0xffff {
2073 				s00gu = 0xffff
2074 			}
2075 			if s00bu < 0 {
2076 				s00bu = 0
2077 			} else if s00bu > 0xffff {
2078 				s00bu = 0xffff
2079 			}
2080 
2081 			s00r := float64(s00ru)
2082 			s00g := float64(s00gu)
2083 			s00b := float64(s00bu)
2084 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2085 			s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2086 
2087 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2088 			s10yy1 := int(src.Y[s10i]) * 0x10101
2089 			s10cb1 := int(src.Cb[s10j]) - 128
2090 			s10cr1 := int(src.Cr[s10j]) - 128
2091 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
2092 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
2093 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
2094 			if s10ru < 0 {
2095 				s10ru = 0
2096 			} else if s10ru > 0xffff {
2097 				s10ru = 0xffff
2098 			}
2099 			if s10gu < 0 {
2100 				s10gu = 0
2101 			} else if s10gu > 0xffff {
2102 				s10gu = 0xffff
2103 			}
2104 			if s10bu < 0 {
2105 				s10bu = 0
2106 			} else if s10bu > 0xffff {
2107 				s10bu = 0xffff
2108 			}
2109 
2110 			s10r := float64(s10ru)
2111 			s10g := float64(s10gu)
2112 			s10b := float64(s10bu)
2113 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2114 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2115 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2116 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2117 			s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2118 
2119 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2120 			s01yy1 := int(src.Y[s01i]) * 0x10101
2121 			s01cb1 := int(src.Cb[s01j]) - 128
2122 			s01cr1 := int(src.Cr[s01j]) - 128
2123 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
2124 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
2125 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
2126 			if s01ru < 0 {
2127 				s01ru = 0
2128 			} else if s01ru > 0xffff {
2129 				s01ru = 0xffff
2130 			}
2131 			if s01gu < 0 {
2132 				s01gu = 0
2133 			} else if s01gu > 0xffff {
2134 				s01gu = 0xffff
2135 			}
2136 			if s01bu < 0 {
2137 				s01bu = 0
2138 			} else if s01bu > 0xffff {
2139 				s01bu = 0xffff
2140 			}
2141 
2142 			s01r := float64(s01ru)
2143 			s01g := float64(s01gu)
2144 			s01b := float64(s01bu)
2145 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2146 			s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2147 
2148 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2149 			s11yy1 := int(src.Y[s11i]) * 0x10101
2150 			s11cb1 := int(src.Cb[s11j]) - 128
2151 			s11cr1 := int(src.Cr[s11j]) - 128
2152 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
2153 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
2154 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
2155 			if s11ru < 0 {
2156 				s11ru = 0
2157 			} else if s11ru > 0xffff {
2158 				s11ru = 0xffff
2159 			}
2160 			if s11gu < 0 {
2161 				s11gu = 0
2162 			} else if s11gu > 0xffff {
2163 				s11gu = 0xffff
2164 			}
2165 			if s11bu < 0 {
2166 				s11bu = 0
2167 			} else if s11bu > 0xffff {
2168 				s11bu = 0xffff
2169 			}
2170 
2171 			s11r := float64(s11ru)
2172 			s11g := float64(s11gu)
2173 			s11b := float64(s11bu)
2174 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2175 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2176 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2177 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2178 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2179 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2180 			pr := uint32(s11r)
2181 			pg := uint32(s11g)
2182 			pb := uint32(s11b)
2183 			dst.Pix[d+0] = uint8(pr >> 8)
2184 			dst.Pix[d+1] = uint8(pg >> 8)
2185 			dst.Pix[d+2] = uint8(pb >> 8)
2186 			dst.Pix[d+3] = 0xff
2187 		}
2188 	}
2189 }
2190 
2191 func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
2192 	sw := int32(sr.Dx())
2193 	sh := int32(sr.Dy())
2194 	yscale := float64(sh) / float64(dr.Dy())
2195 	xscale := float64(sw) / float64(dr.Dx())
2196 	swMinus1, shMinus1 := sw-1, sh-1
2197 
2198 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2199 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2200 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2201 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2202 		// sx, below.
2203 		sy0 := int32(sy)
2204 		yFrac0 := sy - float64(sy0)
2205 		yFrac1 := 1 - yFrac0
2206 		sy1 := sy0 + 1
2207 		if sy < 0 {
2208 			sy0, sy1 = 0, 0
2209 			yFrac0, yFrac1 = 0, 1
2210 		} else if sy1 > shMinus1 {
2211 			sy0, sy1 = shMinus1, shMinus1
2212 			yFrac0, yFrac1 = 1, 0
2213 		}
2214 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2215 
2216 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2217 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2218 			sx0 := int32(sx)
2219 			xFrac0 := sx - float64(sx0)
2220 			xFrac1 := 1 - xFrac0
2221 			sx1 := sx0 + 1
2222 			if sx < 0 {
2223 				sx0, sx1 = 0, 0
2224 				xFrac0, xFrac1 = 0, 1
2225 			} else if sx1 > swMinus1 {
2226 				sx0, sx1 = swMinus1, swMinus1
2227 				xFrac0, xFrac1 = 1, 0
2228 			}
2229 
2230 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2231 			s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
2232 
2233 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2234 			s00yy1 := int(src.Y[s00i]) * 0x10101
2235 			s00cb1 := int(src.Cb[s00j]) - 128
2236 			s00cr1 := int(src.Cr[s00j]) - 128
2237 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
2238 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
2239 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
2240 			if s00ru < 0 {
2241 				s00ru = 0
2242 			} else if s00ru > 0xffff {
2243 				s00ru = 0xffff
2244 			}
2245 			if s00gu < 0 {
2246 				s00gu = 0
2247 			} else if s00gu > 0xffff {
2248 				s00gu = 0xffff
2249 			}
2250 			if s00bu < 0 {
2251 				s00bu = 0
2252 			} else if s00bu > 0xffff {
2253 				s00bu = 0xffff
2254 			}
2255 
2256 			s00r := float64(s00ru)
2257 			s00g := float64(s00gu)
2258 			s00b := float64(s00bu)
2259 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2260 			s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
2261 
2262 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2263 			s10yy1 := int(src.Y[s10i]) * 0x10101
2264 			s10cb1 := int(src.Cb[s10j]) - 128
2265 			s10cr1 := int(src.Cr[s10j]) - 128
2266 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
2267 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
2268 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
2269 			if s10ru < 0 {
2270 				s10ru = 0
2271 			} else if s10ru > 0xffff {
2272 				s10ru = 0xffff
2273 			}
2274 			if s10gu < 0 {
2275 				s10gu = 0
2276 			} else if s10gu > 0xffff {
2277 				s10gu = 0xffff
2278 			}
2279 			if s10bu < 0 {
2280 				s10bu = 0
2281 			} else if s10bu > 0xffff {
2282 				s10bu = 0xffff
2283 			}
2284 
2285 			s10r := float64(s10ru)
2286 			s10g := float64(s10gu)
2287 			s10b := float64(s10bu)
2288 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2289 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2290 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2291 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2292 			s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
2293 
2294 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2295 			s01yy1 := int(src.Y[s01i]) * 0x10101
2296 			s01cb1 := int(src.Cb[s01j]) - 128
2297 			s01cr1 := int(src.Cr[s01j]) - 128
2298 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
2299 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
2300 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
2301 			if s01ru < 0 {
2302 				s01ru = 0
2303 			} else if s01ru > 0xffff {
2304 				s01ru = 0xffff
2305 			}
2306 			if s01gu < 0 {
2307 				s01gu = 0
2308 			} else if s01gu > 0xffff {
2309 				s01gu = 0xffff
2310 			}
2311 			if s01bu < 0 {
2312 				s01bu = 0
2313 			} else if s01bu > 0xffff {
2314 				s01bu = 0xffff
2315 			}
2316 
2317 			s01r := float64(s01ru)
2318 			s01g := float64(s01gu)
2319 			s01b := float64(s01bu)
2320 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2321 			s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
2322 
2323 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2324 			s11yy1 := int(src.Y[s11i]) * 0x10101
2325 			s11cb1 := int(src.Cb[s11j]) - 128
2326 			s11cr1 := int(src.Cr[s11j]) - 128
2327 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
2328 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
2329 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
2330 			if s11ru < 0 {
2331 				s11ru = 0
2332 			} else if s11ru > 0xffff {
2333 				s11ru = 0xffff
2334 			}
2335 			if s11gu < 0 {
2336 				s11gu = 0
2337 			} else if s11gu > 0xffff {
2338 				s11gu = 0xffff
2339 			}
2340 			if s11bu < 0 {
2341 				s11bu = 0
2342 			} else if s11bu > 0xffff {
2343 				s11bu = 0xffff
2344 			}
2345 
2346 			s11r := float64(s11ru)
2347 			s11g := float64(s11gu)
2348 			s11b := float64(s11bu)
2349 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2350 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2351 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2352 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2353 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2354 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2355 			pr := uint32(s11r)
2356 			pg := uint32(s11g)
2357 			pb := uint32(s11b)
2358 			dst.Pix[d+0] = uint8(pr >> 8)
2359 			dst.Pix[d+1] = uint8(pg >> 8)
2360 			dst.Pix[d+2] = uint8(pb >> 8)
2361 			dst.Pix[d+3] = 0xff
2362 		}
2363 	}
2364 }
2365 
2366 func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
2367 	sw := int32(sr.Dx())
2368 	sh := int32(sr.Dy())
2369 	yscale := float64(sh) / float64(dr.Dy())
2370 	xscale := float64(sw) / float64(dr.Dx())
2371 	swMinus1, shMinus1 := sw-1, sh-1
2372 
2373 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2374 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2375 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2376 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2377 		// sx, below.
2378 		sy0 := int32(sy)
2379 		yFrac0 := sy - float64(sy0)
2380 		yFrac1 := 1 - yFrac0
2381 		sy1 := sy0 + 1
2382 		if sy < 0 {
2383 			sy0, sy1 = 0, 0
2384 			yFrac0, yFrac1 = 0, 1
2385 		} else if sy1 > shMinus1 {
2386 			sy0, sy1 = shMinus1, shMinus1
2387 			yFrac0, yFrac1 = 1, 0
2388 		}
2389 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2390 
2391 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2392 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2393 			sx0 := int32(sx)
2394 			xFrac0 := sx - float64(sx0)
2395 			xFrac1 := 1 - xFrac0
2396 			sx1 := sx0 + 1
2397 			if sx < 0 {
2398 				sx0, sx1 = 0, 0
2399 				xFrac0, xFrac1 = 0, 1
2400 			} else if sx1 > swMinus1 {
2401 				sx0, sx1 = swMinus1, swMinus1
2402 				xFrac0, xFrac1 = 1, 0
2403 			}
2404 
2405 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2406 			s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
2407 
2408 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2409 			s00yy1 := int(src.Y[s00i]) * 0x10101
2410 			s00cb1 := int(src.Cb[s00j]) - 128
2411 			s00cr1 := int(src.Cr[s00j]) - 128
2412 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
2413 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
2414 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
2415 			if s00ru < 0 {
2416 				s00ru = 0
2417 			} else if s00ru > 0xffff {
2418 				s00ru = 0xffff
2419 			}
2420 			if s00gu < 0 {
2421 				s00gu = 0
2422 			} else if s00gu > 0xffff {
2423 				s00gu = 0xffff
2424 			}
2425 			if s00bu < 0 {
2426 				s00bu = 0
2427 			} else if s00bu > 0xffff {
2428 				s00bu = 0xffff
2429 			}
2430 
2431 			s00r := float64(s00ru)
2432 			s00g := float64(s00gu)
2433 			s00b := float64(s00bu)
2434 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2435 			s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
2436 
2437 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2438 			s10yy1 := int(src.Y[s10i]) * 0x10101
2439 			s10cb1 := int(src.Cb[s10j]) - 128
2440 			s10cr1 := int(src.Cr[s10j]) - 128
2441 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
2442 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
2443 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
2444 			if s10ru < 0 {
2445 				s10ru = 0
2446 			} else if s10ru > 0xffff {
2447 				s10ru = 0xffff
2448 			}
2449 			if s10gu < 0 {
2450 				s10gu = 0
2451 			} else if s10gu > 0xffff {
2452 				s10gu = 0xffff
2453 			}
2454 			if s10bu < 0 {
2455 				s10bu = 0
2456 			} else if s10bu > 0xffff {
2457 				s10bu = 0xffff
2458 			}
2459 
2460 			s10r := float64(s10ru)
2461 			s10g := float64(s10gu)
2462 			s10b := float64(s10bu)
2463 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2464 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2465 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2466 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2467 			s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2)
2468 
2469 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2470 			s01yy1 := int(src.Y[s01i]) * 0x10101
2471 			s01cb1 := int(src.Cb[s01j]) - 128
2472 			s01cr1 := int(src.Cr[s01j]) - 128
2473 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
2474 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
2475 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
2476 			if s01ru < 0 {
2477 				s01ru = 0
2478 			} else if s01ru > 0xffff {
2479 				s01ru = 0xffff
2480 			}
2481 			if s01gu < 0 {
2482 				s01gu = 0
2483 			} else if s01gu > 0xffff {
2484 				s01gu = 0xffff
2485 			}
2486 			if s01bu < 0 {
2487 				s01bu = 0
2488 			} else if s01bu > 0xffff {
2489 				s01bu = 0xffff
2490 			}
2491 
2492 			s01r := float64(s01ru)
2493 			s01g := float64(s01gu)
2494 			s01b := float64(s01bu)
2495 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2496 			s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2)
2497 
2498 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2499 			s11yy1 := int(src.Y[s11i]) * 0x10101
2500 			s11cb1 := int(src.Cb[s11j]) - 128
2501 			s11cr1 := int(src.Cr[s11j]) - 128
2502 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
2503 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
2504 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
2505 			if s11ru < 0 {
2506 				s11ru = 0
2507 			} else if s11ru > 0xffff {
2508 				s11ru = 0xffff
2509 			}
2510 			if s11gu < 0 {
2511 				s11gu = 0
2512 			} else if s11gu > 0xffff {
2513 				s11gu = 0xffff
2514 			}
2515 			if s11bu < 0 {
2516 				s11bu = 0
2517 			} else if s11bu > 0xffff {
2518 				s11bu = 0xffff
2519 			}
2520 
2521 			s11r := float64(s11ru)
2522 			s11g := float64(s11gu)
2523 			s11b := float64(s11bu)
2524 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2525 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2526 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2527 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2528 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2529 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2530 			pr := uint32(s11r)
2531 			pg := uint32(s11g)
2532 			pb := uint32(s11b)
2533 			dst.Pix[d+0] = uint8(pr >> 8)
2534 			dst.Pix[d+1] = uint8(pg >> 8)
2535 			dst.Pix[d+2] = uint8(pb >> 8)
2536 			dst.Pix[d+3] = 0xff
2537 		}
2538 	}
2539 }
2540 
2541 func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) {
2542 	sw := int32(sr.Dx())
2543 	sh := int32(sr.Dy())
2544 	yscale := float64(sh) / float64(dr.Dy())
2545 	xscale := float64(sw) / float64(dr.Dx())
2546 	swMinus1, shMinus1 := sw-1, sh-1
2547 
2548 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2549 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2550 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2551 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2552 		// sx, below.
2553 		sy0 := int32(sy)
2554 		yFrac0 := sy - float64(sy0)
2555 		yFrac1 := 1 - yFrac0
2556 		sy1 := sy0 + 1
2557 		if sy < 0 {
2558 			sy0, sy1 = 0, 0
2559 			yFrac0, yFrac1 = 0, 1
2560 		} else if sy1 > shMinus1 {
2561 			sy0, sy1 = shMinus1, shMinus1
2562 			yFrac0, yFrac1 = 1, 0
2563 		}
2564 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2565 
2566 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2567 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2568 			sx0 := int32(sx)
2569 			xFrac0 := sx - float64(sx0)
2570 			xFrac1 := 1 - xFrac0
2571 			sx1 := sx0 + 1
2572 			if sx < 0 {
2573 				sx0, sx1 = 0, 0
2574 				xFrac0, xFrac1 = 0, 1
2575 			} else if sx1 > swMinus1 {
2576 				sx0, sx1 = swMinus1, swMinus1
2577 				xFrac0, xFrac1 = 1, 0
2578 			}
2579 
2580 			s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2581 			s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2582 
2583 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2584 			s00yy1 := int(src.Y[s00i]) * 0x10101
2585 			s00cb1 := int(src.Cb[s00j]) - 128
2586 			s00cr1 := int(src.Cr[s00j]) - 128
2587 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
2588 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
2589 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
2590 			if s00ru < 0 {
2591 				s00ru = 0
2592 			} else if s00ru > 0xffff {
2593 				s00ru = 0xffff
2594 			}
2595 			if s00gu < 0 {
2596 				s00gu = 0
2597 			} else if s00gu > 0xffff {
2598 				s00gu = 0xffff
2599 			}
2600 			if s00bu < 0 {
2601 				s00bu = 0
2602 			} else if s00bu > 0xffff {
2603 				s00bu = 0xffff
2604 			}
2605 
2606 			s00r := float64(s00ru)
2607 			s00g := float64(s00gu)
2608 			s00b := float64(s00bu)
2609 			s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2610 			s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2611 
2612 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2613 			s10yy1 := int(src.Y[s10i]) * 0x10101
2614 			s10cb1 := int(src.Cb[s10j]) - 128
2615 			s10cr1 := int(src.Cr[s10j]) - 128
2616 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
2617 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
2618 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
2619 			if s10ru < 0 {
2620 				s10ru = 0
2621 			} else if s10ru > 0xffff {
2622 				s10ru = 0xffff
2623 			}
2624 			if s10gu < 0 {
2625 				s10gu = 0
2626 			} else if s10gu > 0xffff {
2627 				s10gu = 0xffff
2628 			}
2629 			if s10bu < 0 {
2630 				s10bu = 0
2631 			} else if s10bu > 0xffff {
2632 				s10bu = 0xffff
2633 			}
2634 
2635 			s10r := float64(s10ru)
2636 			s10g := float64(s10gu)
2637 			s10b := float64(s10bu)
2638 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2639 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2640 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2641 			s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2642 			s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X)
2643 
2644 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2645 			s01yy1 := int(src.Y[s01i]) * 0x10101
2646 			s01cb1 := int(src.Cb[s01j]) - 128
2647 			s01cr1 := int(src.Cr[s01j]) - 128
2648 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
2649 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
2650 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
2651 			if s01ru < 0 {
2652 				s01ru = 0
2653 			} else if s01ru > 0xffff {
2654 				s01ru = 0xffff
2655 			}
2656 			if s01gu < 0 {
2657 				s01gu = 0
2658 			} else if s01gu > 0xffff {
2659 				s01gu = 0xffff
2660 			}
2661 			if s01bu < 0 {
2662 				s01bu = 0
2663 			} else if s01bu > 0xffff {
2664 				s01bu = 0xffff
2665 			}
2666 
2667 			s01r := float64(s01ru)
2668 			s01g := float64(s01gu)
2669 			s01b := float64(s01bu)
2670 			s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2671 			s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X)
2672 
2673 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
2674 			s11yy1 := int(src.Y[s11i]) * 0x10101
2675 			s11cb1 := int(src.Cb[s11j]) - 128
2676 			s11cr1 := int(src.Cr[s11j]) - 128
2677 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
2678 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
2679 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
2680 			if s11ru < 0 {
2681 				s11ru = 0
2682 			} else if s11ru > 0xffff {
2683 				s11ru = 0xffff
2684 			}
2685 			if s11gu < 0 {
2686 				s11gu = 0
2687 			} else if s11gu > 0xffff {
2688 				s11gu = 0xffff
2689 			}
2690 			if s11bu < 0 {
2691 				s11bu = 0
2692 			} else if s11bu > 0xffff {
2693 				s11bu = 0xffff
2694 			}
2695 
2696 			s11r := float64(s11ru)
2697 			s11g := float64(s11gu)
2698 			s11b := float64(s11bu)
2699 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2700 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2701 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2702 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2703 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2704 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2705 			pr := uint32(s11r)
2706 			pg := uint32(s11g)
2707 			pb := uint32(s11b)
2708 			dst.Pix[d+0] = uint8(pr >> 8)
2709 			dst.Pix[d+1] = uint8(pg >> 8)
2710 			dst.Pix[d+2] = uint8(pb >> 8)
2711 			dst.Pix[d+3] = 0xff
2712 		}
2713 	}
2714 }
2715 
2716 func (ablInterpolator) scale_RGBA_RGBA64Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
2717 	sw := int32(sr.Dx())
2718 	sh := int32(sr.Dy())
2719 	yscale := float64(sh) / float64(dr.Dy())
2720 	xscale := float64(sw) / float64(dr.Dx())
2721 	swMinus1, shMinus1 := sw-1, sh-1
2722 
2723 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2724 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2725 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2726 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2727 		// sx, below.
2728 		sy0 := int32(sy)
2729 		yFrac0 := sy - float64(sy0)
2730 		yFrac1 := 1 - yFrac0
2731 		sy1 := sy0 + 1
2732 		if sy < 0 {
2733 			sy0, sy1 = 0, 0
2734 			yFrac0, yFrac1 = 0, 1
2735 		} else if sy1 > shMinus1 {
2736 			sy0, sy1 = shMinus1, shMinus1
2737 			yFrac0, yFrac1 = 1, 0
2738 		}
2739 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2740 
2741 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2742 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2743 			sx0 := int32(sx)
2744 			xFrac0 := sx - float64(sx0)
2745 			xFrac1 := 1 - xFrac0
2746 			sx1 := sx0 + 1
2747 			if sx < 0 {
2748 				sx0, sx1 = 0, 0
2749 				xFrac0, xFrac1 = 0, 1
2750 			} else if sx1 > swMinus1 {
2751 				sx0, sx1 = swMinus1, swMinus1
2752 				xFrac0, xFrac1 = 1, 0
2753 			}
2754 
2755 			s00u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0))
2756 			s00r := float64(s00u.R)
2757 			s00g := float64(s00u.G)
2758 			s00b := float64(s00u.B)
2759 			s00a := float64(s00u.A)
2760 			s10u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0))
2761 			s10r := float64(s10u.R)
2762 			s10g := float64(s10u.G)
2763 			s10b := float64(s10u.B)
2764 			s10a := float64(s10u.A)
2765 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2766 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2767 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2768 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
2769 			s01u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1))
2770 			s01r := float64(s01u.R)
2771 			s01g := float64(s01u.G)
2772 			s01b := float64(s01u.B)
2773 			s01a := float64(s01u.A)
2774 			s11u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1))
2775 			s11r := float64(s11u.R)
2776 			s11g := float64(s11u.G)
2777 			s11b := float64(s11u.B)
2778 			s11a := float64(s11u.A)
2779 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2780 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2781 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2782 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
2783 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2784 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2785 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2786 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
2787 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
2788 			pa1 := (0xffff - uint32(p.A)) * 0x101
2789 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + uint32(p.R)) >> 8)
2790 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + uint32(p.G)) >> 8)
2791 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + uint32(p.B)) >> 8)
2792 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + uint32(p.A)) >> 8)
2793 		}
2794 	}
2795 }
2796 
2797 func (ablInterpolator) scale_RGBA_RGBA64Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
2798 	sw := int32(sr.Dx())
2799 	sh := int32(sr.Dy())
2800 	yscale := float64(sh) / float64(dr.Dy())
2801 	xscale := float64(sw) / float64(dr.Dx())
2802 	swMinus1, shMinus1 := sw-1, sh-1
2803 
2804 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2805 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2806 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2807 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2808 		// sx, below.
2809 		sy0 := int32(sy)
2810 		yFrac0 := sy - float64(sy0)
2811 		yFrac1 := 1 - yFrac0
2812 		sy1 := sy0 + 1
2813 		if sy < 0 {
2814 			sy0, sy1 = 0, 0
2815 			yFrac0, yFrac1 = 0, 1
2816 		} else if sy1 > shMinus1 {
2817 			sy0, sy1 = shMinus1, shMinus1
2818 			yFrac0, yFrac1 = 1, 0
2819 		}
2820 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2821 
2822 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2823 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2824 			sx0 := int32(sx)
2825 			xFrac0 := sx - float64(sx0)
2826 			xFrac1 := 1 - xFrac0
2827 			sx1 := sx0 + 1
2828 			if sx < 0 {
2829 				sx0, sx1 = 0, 0
2830 				xFrac0, xFrac1 = 0, 1
2831 			} else if sx1 > swMinus1 {
2832 				sx0, sx1 = swMinus1, swMinus1
2833 				xFrac0, xFrac1 = 1, 0
2834 			}
2835 
2836 			s00u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0))
2837 			s00r := float64(s00u.R)
2838 			s00g := float64(s00u.G)
2839 			s00b := float64(s00u.B)
2840 			s00a := float64(s00u.A)
2841 			s10u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0))
2842 			s10r := float64(s10u.R)
2843 			s10g := float64(s10u.G)
2844 			s10b := float64(s10u.B)
2845 			s10a := float64(s10u.A)
2846 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2847 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2848 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2849 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
2850 			s01u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1))
2851 			s01r := float64(s01u.R)
2852 			s01g := float64(s01u.G)
2853 			s01b := float64(s01u.B)
2854 			s01a := float64(s01u.A)
2855 			s11u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1))
2856 			s11r := float64(s11u.R)
2857 			s11g := float64(s11u.G)
2858 			s11b := float64(s11u.B)
2859 			s11a := float64(s11u.A)
2860 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2861 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2862 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2863 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
2864 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2865 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2866 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2867 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
2868 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
2869 			dst.Pix[d+0] = uint8(p.R >> 8)
2870 			dst.Pix[d+1] = uint8(p.G >> 8)
2871 			dst.Pix[d+2] = uint8(p.B >> 8)
2872 			dst.Pix[d+3] = uint8(p.A >> 8)
2873 		}
2874 	}
2875 }
2876 
2877 func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
2878 	sw := int32(sr.Dx())
2879 	sh := int32(sr.Dy())
2880 	yscale := float64(sh) / float64(dr.Dy())
2881 	xscale := float64(sw) / float64(dr.Dx())
2882 	swMinus1, shMinus1 := sw-1, sh-1
2883 
2884 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2885 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2886 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2887 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2888 		// sx, below.
2889 		sy0 := int32(sy)
2890 		yFrac0 := sy - float64(sy0)
2891 		yFrac1 := 1 - yFrac0
2892 		sy1 := sy0 + 1
2893 		if sy < 0 {
2894 			sy0, sy1 = 0, 0
2895 			yFrac0, yFrac1 = 0, 1
2896 		} else if sy1 > shMinus1 {
2897 			sy0, sy1 = shMinus1, shMinus1
2898 			yFrac0, yFrac1 = 1, 0
2899 		}
2900 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2901 
2902 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2903 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2904 			sx0 := int32(sx)
2905 			xFrac0 := sx - float64(sx0)
2906 			xFrac1 := 1 - xFrac0
2907 			sx1 := sx0 + 1
2908 			if sx < 0 {
2909 				sx0, sx1 = 0, 0
2910 				xFrac0, xFrac1 = 0, 1
2911 			} else if sx1 > swMinus1 {
2912 				sx0, sx1 = swMinus1, swMinus1
2913 				xFrac0, xFrac1 = 1, 0
2914 			}
2915 
2916 			s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
2917 			s00r := float64(s00ru)
2918 			s00g := float64(s00gu)
2919 			s00b := float64(s00bu)
2920 			s00a := float64(s00au)
2921 			s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
2922 			s10r := float64(s10ru)
2923 			s10g := float64(s10gu)
2924 			s10b := float64(s10bu)
2925 			s10a := float64(s10au)
2926 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
2927 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
2928 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
2929 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
2930 			s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
2931 			s01r := float64(s01ru)
2932 			s01g := float64(s01gu)
2933 			s01b := float64(s01bu)
2934 			s01a := float64(s01au)
2935 			s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
2936 			s11r := float64(s11ru)
2937 			s11g := float64(s11gu)
2938 			s11b := float64(s11bu)
2939 			s11a := float64(s11au)
2940 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
2941 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
2942 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
2943 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
2944 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
2945 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
2946 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
2947 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
2948 			pr := uint32(s11r)
2949 			pg := uint32(s11g)
2950 			pb := uint32(s11b)
2951 			pa := uint32(s11a)
2952 			pa1 := (0xffff - pa) * 0x101
2953 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
2954 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
2955 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
2956 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
2957 		}
2958 	}
2959 }
2960 
2961 func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
2962 	sw := int32(sr.Dx())
2963 	sh := int32(sr.Dy())
2964 	yscale := float64(sh) / float64(dr.Dy())
2965 	xscale := float64(sw) / float64(dr.Dx())
2966 	swMinus1, shMinus1 := sw-1, sh-1
2967 
2968 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
2969 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
2970 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
2971 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
2972 		// sx, below.
2973 		sy0 := int32(sy)
2974 		yFrac0 := sy - float64(sy0)
2975 		yFrac1 := 1 - yFrac0
2976 		sy1 := sy0 + 1
2977 		if sy < 0 {
2978 			sy0, sy1 = 0, 0
2979 			yFrac0, yFrac1 = 0, 1
2980 		} else if sy1 > shMinus1 {
2981 			sy0, sy1 = shMinus1, shMinus1
2982 			yFrac0, yFrac1 = 1, 0
2983 		}
2984 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
2985 
2986 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
2987 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
2988 			sx0 := int32(sx)
2989 			xFrac0 := sx - float64(sx0)
2990 			xFrac1 := 1 - xFrac0
2991 			sx1 := sx0 + 1
2992 			if sx < 0 {
2993 				sx0, sx1 = 0, 0
2994 				xFrac0, xFrac1 = 0, 1
2995 			} else if sx1 > swMinus1 {
2996 				sx0, sx1 = swMinus1, swMinus1
2997 				xFrac0, xFrac1 = 1, 0
2998 			}
2999 
3000 			s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
3001 			s00r := float64(s00ru)
3002 			s00g := float64(s00gu)
3003 			s00b := float64(s00bu)
3004 			s00a := float64(s00au)
3005 			s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
3006 			s10r := float64(s10ru)
3007 			s10g := float64(s10gu)
3008 			s10b := float64(s10bu)
3009 			s10a := float64(s10au)
3010 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3011 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3012 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3013 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3014 			s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
3015 			s01r := float64(s01ru)
3016 			s01g := float64(s01gu)
3017 			s01b := float64(s01bu)
3018 			s01a := float64(s01au)
3019 			s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
3020 			s11r := float64(s11ru)
3021 			s11g := float64(s11gu)
3022 			s11b := float64(s11bu)
3023 			s11a := float64(s11au)
3024 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3025 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3026 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3027 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3028 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3029 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3030 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3031 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3032 			pr := uint32(s11r)
3033 			pg := uint32(s11g)
3034 			pb := uint32(s11b)
3035 			pa := uint32(s11a)
3036 			dst.Pix[d+0] = uint8(pr >> 8)
3037 			dst.Pix[d+1] = uint8(pg >> 8)
3038 			dst.Pix[d+2] = uint8(pb >> 8)
3039 			dst.Pix[d+3] = uint8(pa >> 8)
3040 		}
3041 	}
3042 }
3043 
3044 func (ablInterpolator) scale_RGBA64Image_RGBA64Image_Over(dst RGBA64Image, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
3045 	sw := int32(sr.Dx())
3046 	sh := int32(sr.Dy())
3047 	yscale := float64(sh) / float64(dr.Dy())
3048 	xscale := float64(sw) / float64(dr.Dx())
3049 	swMinus1, shMinus1 := sw-1, sh-1
3050 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
3051 	dstMask, dmp := opts.DstMask, opts.DstMaskP
3052 	dstColorRGBA64 := color.RGBA64{}
3053 
3054 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3055 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
3056 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
3057 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
3058 		// sx, below.
3059 		sy0 := int32(sy)
3060 		yFrac0 := sy - float64(sy0)
3061 		yFrac1 := 1 - yFrac0
3062 		sy1 := sy0 + 1
3063 		if sy < 0 {
3064 			sy0, sy1 = 0, 0
3065 			yFrac0, yFrac1 = 0, 1
3066 		} else if sy1 > shMinus1 {
3067 			sy0, sy1 = shMinus1, shMinus1
3068 			yFrac0, yFrac1 = 1, 0
3069 		}
3070 
3071 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
3072 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
3073 			sx0 := int32(sx)
3074 			xFrac0 := sx - float64(sx0)
3075 			xFrac1 := 1 - xFrac0
3076 			sx1 := sx0 + 1
3077 			if sx < 0 {
3078 				sx0, sx1 = 0, 0
3079 				xFrac0, xFrac1 = 0, 1
3080 			} else if sx1 > swMinus1 {
3081 				sx0, sx1 = swMinus1, swMinus1
3082 				xFrac0, xFrac1 = 1, 0
3083 			}
3084 
3085 			s00u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0))
3086 			if srcMask != nil {
3087 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3088 				s00u.R = uint16(uint32(s00u.R) * ma / 0xffff)
3089 				s00u.G = uint16(uint32(s00u.G) * ma / 0xffff)
3090 				s00u.B = uint16(uint32(s00u.B) * ma / 0xffff)
3091 				s00u.A = uint16(uint32(s00u.A) * ma / 0xffff)
3092 			}
3093 			s00r := float64(s00u.R)
3094 			s00g := float64(s00u.G)
3095 			s00b := float64(s00u.B)
3096 			s00a := float64(s00u.A)
3097 			s10u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0))
3098 			if srcMask != nil {
3099 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3100 				s10u.R = uint16(uint32(s10u.R) * ma / 0xffff)
3101 				s10u.G = uint16(uint32(s10u.G) * ma / 0xffff)
3102 				s10u.B = uint16(uint32(s10u.B) * ma / 0xffff)
3103 				s10u.A = uint16(uint32(s10u.A) * ma / 0xffff)
3104 			}
3105 			s10r := float64(s10u.R)
3106 			s10g := float64(s10u.G)
3107 			s10b := float64(s10u.B)
3108 			s10a := float64(s10u.A)
3109 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3110 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3111 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3112 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3113 			s01u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1))
3114 			if srcMask != nil {
3115 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3116 				s01u.R = uint16(uint32(s01u.R) * ma / 0xffff)
3117 				s01u.G = uint16(uint32(s01u.G) * ma / 0xffff)
3118 				s01u.B = uint16(uint32(s01u.B) * ma / 0xffff)
3119 				s01u.A = uint16(uint32(s01u.A) * ma / 0xffff)
3120 			}
3121 			s01r := float64(s01u.R)
3122 			s01g := float64(s01u.G)
3123 			s01b := float64(s01u.B)
3124 			s01a := float64(s01u.A)
3125 			s11u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1))
3126 			if srcMask != nil {
3127 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3128 				s11u.R = uint16(uint32(s11u.R) * ma / 0xffff)
3129 				s11u.G = uint16(uint32(s11u.G) * ma / 0xffff)
3130 				s11u.B = uint16(uint32(s11u.B) * ma / 0xffff)
3131 				s11u.A = uint16(uint32(s11u.A) * ma / 0xffff)
3132 			}
3133 			s11r := float64(s11u.R)
3134 			s11g := float64(s11u.G)
3135 			s11b := float64(s11u.B)
3136 			s11a := float64(s11u.A)
3137 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3138 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3139 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3140 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3141 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3142 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3143 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3144 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3145 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
3146 			q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
3147 			if dstMask != nil {
3148 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
3149 				p.R = uint16(uint32(p.R) * ma / 0xffff)
3150 				p.G = uint16(uint32(p.G) * ma / 0xffff)
3151 				p.B = uint16(uint32(p.B) * ma / 0xffff)
3152 				p.A = uint16(uint32(p.A) * ma / 0xffff)
3153 			}
3154 			pa1 := 0xffff - uint32(p.A)
3155 			dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
3156 			dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
3157 			dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
3158 			dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
3159 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
3160 		}
3161 	}
3162 }
3163 
3164 func (ablInterpolator) scale_RGBA64Image_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rectangle, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
3165 	sw := int32(sr.Dx())
3166 	sh := int32(sr.Dy())
3167 	yscale := float64(sh) / float64(dr.Dy())
3168 	xscale := float64(sw) / float64(dr.Dx())
3169 	swMinus1, shMinus1 := sw-1, sh-1
3170 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
3171 	dstMask, dmp := opts.DstMask, opts.DstMaskP
3172 	dstColorRGBA64 := color.RGBA64{}
3173 
3174 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3175 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
3176 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
3177 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
3178 		// sx, below.
3179 		sy0 := int32(sy)
3180 		yFrac0 := sy - float64(sy0)
3181 		yFrac1 := 1 - yFrac0
3182 		sy1 := sy0 + 1
3183 		if sy < 0 {
3184 			sy0, sy1 = 0, 0
3185 			yFrac0, yFrac1 = 0, 1
3186 		} else if sy1 > shMinus1 {
3187 			sy0, sy1 = shMinus1, shMinus1
3188 			yFrac0, yFrac1 = 1, 0
3189 		}
3190 
3191 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
3192 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
3193 			sx0 := int32(sx)
3194 			xFrac0 := sx - float64(sx0)
3195 			xFrac1 := 1 - xFrac0
3196 			sx1 := sx0 + 1
3197 			if sx < 0 {
3198 				sx0, sx1 = 0, 0
3199 				xFrac0, xFrac1 = 0, 1
3200 			} else if sx1 > swMinus1 {
3201 				sx0, sx1 = swMinus1, swMinus1
3202 				xFrac0, xFrac1 = 1, 0
3203 			}
3204 
3205 			s00u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0))
3206 			if srcMask != nil {
3207 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3208 				s00u.R = uint16(uint32(s00u.R) * ma / 0xffff)
3209 				s00u.G = uint16(uint32(s00u.G) * ma / 0xffff)
3210 				s00u.B = uint16(uint32(s00u.B) * ma / 0xffff)
3211 				s00u.A = uint16(uint32(s00u.A) * ma / 0xffff)
3212 			}
3213 			s00r := float64(s00u.R)
3214 			s00g := float64(s00u.G)
3215 			s00b := float64(s00u.B)
3216 			s00a := float64(s00u.A)
3217 			s10u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0))
3218 			if srcMask != nil {
3219 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3220 				s10u.R = uint16(uint32(s10u.R) * ma / 0xffff)
3221 				s10u.G = uint16(uint32(s10u.G) * ma / 0xffff)
3222 				s10u.B = uint16(uint32(s10u.B) * ma / 0xffff)
3223 				s10u.A = uint16(uint32(s10u.A) * ma / 0xffff)
3224 			}
3225 			s10r := float64(s10u.R)
3226 			s10g := float64(s10u.G)
3227 			s10b := float64(s10u.B)
3228 			s10a := float64(s10u.A)
3229 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3230 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3231 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3232 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3233 			s01u := src.RGBA64At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1))
3234 			if srcMask != nil {
3235 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3236 				s01u.R = uint16(uint32(s01u.R) * ma / 0xffff)
3237 				s01u.G = uint16(uint32(s01u.G) * ma / 0xffff)
3238 				s01u.B = uint16(uint32(s01u.B) * ma / 0xffff)
3239 				s01u.A = uint16(uint32(s01u.A) * ma / 0xffff)
3240 			}
3241 			s01r := float64(s01u.R)
3242 			s01g := float64(s01u.G)
3243 			s01b := float64(s01u.B)
3244 			s01a := float64(s01u.A)
3245 			s11u := src.RGBA64At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1))
3246 			if srcMask != nil {
3247 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3248 				s11u.R = uint16(uint32(s11u.R) * ma / 0xffff)
3249 				s11u.G = uint16(uint32(s11u.G) * ma / 0xffff)
3250 				s11u.B = uint16(uint32(s11u.B) * ma / 0xffff)
3251 				s11u.A = uint16(uint32(s11u.A) * ma / 0xffff)
3252 			}
3253 			s11r := float64(s11u.R)
3254 			s11g := float64(s11u.G)
3255 			s11b := float64(s11u.B)
3256 			s11a := float64(s11u.A)
3257 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3258 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3259 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3260 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3261 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3262 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3263 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3264 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3265 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
3266 			if dstMask != nil {
3267 				q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
3268 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
3269 				p.R = uint16(uint32(p.R) * ma / 0xffff)
3270 				p.G = uint16(uint32(p.G) * ma / 0xffff)
3271 				p.B = uint16(uint32(p.B) * ma / 0xffff)
3272 				p.A = uint16(uint32(p.A) * ma / 0xffff)
3273 				pa1 := 0xffff - ma
3274 				dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
3275 				dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
3276 				dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
3277 				dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
3278 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
3279 			} else {
3280 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), p)
3281 			}
3282 		}
3283 	}
3284 }
3285 
3286 func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
3287 	sw := int32(sr.Dx())
3288 	sh := int32(sr.Dy())
3289 	yscale := float64(sh) / float64(dr.Dy())
3290 	xscale := float64(sw) / float64(dr.Dx())
3291 	swMinus1, shMinus1 := sw-1, sh-1
3292 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
3293 	dstMask, dmp := opts.DstMask, opts.DstMaskP
3294 	dstColorRGBA64 := &color.RGBA64{}
3295 	dstColor := color.Color(dstColorRGBA64)
3296 
3297 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3298 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
3299 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
3300 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
3301 		// sx, below.
3302 		sy0 := int32(sy)
3303 		yFrac0 := sy - float64(sy0)
3304 		yFrac1 := 1 - yFrac0
3305 		sy1 := sy0 + 1
3306 		if sy < 0 {
3307 			sy0, sy1 = 0, 0
3308 			yFrac0, yFrac1 = 0, 1
3309 		} else if sy1 > shMinus1 {
3310 			sy0, sy1 = shMinus1, shMinus1
3311 			yFrac0, yFrac1 = 1, 0
3312 		}
3313 
3314 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
3315 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
3316 			sx0 := int32(sx)
3317 			xFrac0 := sx - float64(sx0)
3318 			xFrac1 := 1 - xFrac0
3319 			sx1 := sx0 + 1
3320 			if sx < 0 {
3321 				sx0, sx1 = 0, 0
3322 				xFrac0, xFrac1 = 0, 1
3323 			} else if sx1 > swMinus1 {
3324 				sx0, sx1 = swMinus1, swMinus1
3325 				xFrac0, xFrac1 = 1, 0
3326 			}
3327 
3328 			s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
3329 			if srcMask != nil {
3330 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3331 				s00ru = s00ru * ma / 0xffff
3332 				s00gu = s00gu * ma / 0xffff
3333 				s00bu = s00bu * ma / 0xffff
3334 				s00au = s00au * ma / 0xffff
3335 			}
3336 			s00r := float64(s00ru)
3337 			s00g := float64(s00gu)
3338 			s00b := float64(s00bu)
3339 			s00a := float64(s00au)
3340 			s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
3341 			if srcMask != nil {
3342 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3343 				s10ru = s10ru * ma / 0xffff
3344 				s10gu = s10gu * ma / 0xffff
3345 				s10bu = s10bu * ma / 0xffff
3346 				s10au = s10au * ma / 0xffff
3347 			}
3348 			s10r := float64(s10ru)
3349 			s10g := float64(s10gu)
3350 			s10b := float64(s10bu)
3351 			s10a := float64(s10au)
3352 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3353 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3354 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3355 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3356 			s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
3357 			if srcMask != nil {
3358 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3359 				s01ru = s01ru * ma / 0xffff
3360 				s01gu = s01gu * ma / 0xffff
3361 				s01bu = s01bu * ma / 0xffff
3362 				s01au = s01au * ma / 0xffff
3363 			}
3364 			s01r := float64(s01ru)
3365 			s01g := float64(s01gu)
3366 			s01b := float64(s01bu)
3367 			s01a := float64(s01au)
3368 			s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
3369 			if srcMask != nil {
3370 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3371 				s11ru = s11ru * ma / 0xffff
3372 				s11gu = s11gu * ma / 0xffff
3373 				s11bu = s11bu * ma / 0xffff
3374 				s11au = s11au * ma / 0xffff
3375 			}
3376 			s11r := float64(s11ru)
3377 			s11g := float64(s11gu)
3378 			s11b := float64(s11bu)
3379 			s11a := float64(s11au)
3380 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3381 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3382 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3383 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3384 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3385 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3386 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3387 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3388 			pr := uint32(s11r)
3389 			pg := uint32(s11g)
3390 			pb := uint32(s11b)
3391 			pa := uint32(s11a)
3392 			qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
3393 			if dstMask != nil {
3394 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
3395 				pr = pr * ma / 0xffff
3396 				pg = pg * ma / 0xffff
3397 				pb = pb * ma / 0xffff
3398 				pa = pa * ma / 0xffff
3399 			}
3400 			pa1 := 0xffff - pa
3401 			dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
3402 			dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
3403 			dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
3404 			dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
3405 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
3406 		}
3407 	}
3408 }
3409 
3410 func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) {
3411 	sw := int32(sr.Dx())
3412 	sh := int32(sr.Dy())
3413 	yscale := float64(sh) / float64(dr.Dy())
3414 	xscale := float64(sw) / float64(dr.Dx())
3415 	swMinus1, shMinus1 := sw-1, sh-1
3416 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
3417 	dstMask, dmp := opts.DstMask, opts.DstMaskP
3418 	dstColorRGBA64 := &color.RGBA64{}
3419 	dstColor := color.Color(dstColorRGBA64)
3420 
3421 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3422 		sy := float64((float64(dy)+0.5)*yscale) - 0.5
3423 		// If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if
3424 		// we say int32(sy) instead of int32(math.Floor(sy)). Similarly for
3425 		// sx, below.
3426 		sy0 := int32(sy)
3427 		yFrac0 := sy - float64(sy0)
3428 		yFrac1 := 1 - yFrac0
3429 		sy1 := sy0 + 1
3430 		if sy < 0 {
3431 			sy0, sy1 = 0, 0
3432 			yFrac0, yFrac1 = 0, 1
3433 		} else if sy1 > shMinus1 {
3434 			sy0, sy1 = shMinus1, shMinus1
3435 			yFrac0, yFrac1 = 1, 0
3436 		}
3437 
3438 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
3439 			sx := float64((float64(dx)+0.5)*xscale) - 0.5
3440 			sx0 := int32(sx)
3441 			xFrac0 := sx - float64(sx0)
3442 			xFrac1 := 1 - xFrac0
3443 			sx1 := sx0 + 1
3444 			if sx < 0 {
3445 				sx0, sx1 = 0, 0
3446 				xFrac0, xFrac1 = 0, 1
3447 			} else if sx1 > swMinus1 {
3448 				sx0, sx1 = swMinus1, swMinus1
3449 				xFrac0, xFrac1 = 1, 0
3450 			}
3451 
3452 			s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA()
3453 			if srcMask != nil {
3454 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3455 				s00ru = s00ru * ma / 0xffff
3456 				s00gu = s00gu * ma / 0xffff
3457 				s00bu = s00bu * ma / 0xffff
3458 				s00au = s00au * ma / 0xffff
3459 			}
3460 			s00r := float64(s00ru)
3461 			s00g := float64(s00gu)
3462 			s00b := float64(s00bu)
3463 			s00a := float64(s00au)
3464 			s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA()
3465 			if srcMask != nil {
3466 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA()
3467 				s10ru = s10ru * ma / 0xffff
3468 				s10gu = s10gu * ma / 0xffff
3469 				s10bu = s10bu * ma / 0xffff
3470 				s10au = s10au * ma / 0xffff
3471 			}
3472 			s10r := float64(s10ru)
3473 			s10g := float64(s10gu)
3474 			s10b := float64(s10bu)
3475 			s10a := float64(s10au)
3476 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3477 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3478 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3479 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3480 			s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA()
3481 			if srcMask != nil {
3482 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3483 				s01ru = s01ru * ma / 0xffff
3484 				s01gu = s01gu * ma / 0xffff
3485 				s01bu = s01bu * ma / 0xffff
3486 				s01au = s01au * ma / 0xffff
3487 			}
3488 			s01r := float64(s01ru)
3489 			s01g := float64(s01gu)
3490 			s01b := float64(s01bu)
3491 			s01a := float64(s01au)
3492 			s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA()
3493 			if srcMask != nil {
3494 				_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA()
3495 				s11ru = s11ru * ma / 0xffff
3496 				s11gu = s11gu * ma / 0xffff
3497 				s11bu = s11bu * ma / 0xffff
3498 				s11au = s11au * ma / 0xffff
3499 			}
3500 			s11r := float64(s11ru)
3501 			s11g := float64(s11gu)
3502 			s11b := float64(s11bu)
3503 			s11a := float64(s11au)
3504 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3505 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3506 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3507 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3508 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3509 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3510 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3511 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3512 			pr := uint32(s11r)
3513 			pg := uint32(s11g)
3514 			pb := uint32(s11b)
3515 			pa := uint32(s11a)
3516 			if dstMask != nil {
3517 				qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
3518 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
3519 				pr = pr * ma / 0xffff
3520 				pg = pg * ma / 0xffff
3521 				pb = pb * ma / 0xffff
3522 				pa = pa * ma / 0xffff
3523 				pa1 := 0xffff - ma
3524 				dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
3525 				dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
3526 				dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
3527 				dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
3528 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
3529 			} else {
3530 				dstColorRGBA64.R = uint16(pr)
3531 				dstColorRGBA64.G = uint16(pg)
3532 				dstColorRGBA64.B = uint16(pb)
3533 				dstColorRGBA64.A = uint16(pa)
3534 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
3535 			}
3536 		}
3537 	}
3538 }
3539 
3540 func (ablInterpolator) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, opts *Options) {
3541 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3542 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
3543 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
3544 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
3545 			dxf := float64(dr.Min.X+int(dx)) + 0.5
3546 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
3547 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
3548 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
3549 				continue
3550 			}
3551 
3552 			sx -= 0.5
3553 			sx0 := int(sx)
3554 			xFrac0 := sx - float64(sx0)
3555 			xFrac1 := 1 - xFrac0
3556 			sx0 += bias.X
3557 			sx1 := sx0 + 1
3558 			if sx0 < sr.Min.X {
3559 				sx0, sx1 = sr.Min.X, sr.Min.X
3560 				xFrac0, xFrac1 = 0, 1
3561 			} else if sx1 >= sr.Max.X {
3562 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
3563 				xFrac0, xFrac1 = 1, 0
3564 			}
3565 
3566 			sy -= 0.5
3567 			sy0 := int(sy)
3568 			yFrac0 := sy - float64(sy0)
3569 			yFrac1 := 1 - yFrac0
3570 			sy0 += bias.Y
3571 			sy1 := sy0 + 1
3572 			if sy0 < sr.Min.Y {
3573 				sy0, sy1 = sr.Min.Y, sr.Min.Y
3574 				yFrac0, yFrac1 = 0, 1
3575 			} else if sy1 >= sr.Max.Y {
3576 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
3577 				yFrac0, yFrac1 = 1, 0
3578 			}
3579 
3580 			s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
3581 			s00ru := uint32(src.Pix[s00i]) * 0x101
3582 			s00r := float64(s00ru)
3583 			s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
3584 			s10ru := uint32(src.Pix[s10i]) * 0x101
3585 			s10r := float64(s10ru)
3586 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3587 			s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X)
3588 			s01ru := uint32(src.Pix[s01i]) * 0x101
3589 			s01r := float64(s01ru)
3590 			s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X)
3591 			s11ru := uint32(src.Pix[s11i]) * 0x101
3592 			s11r := float64(s11ru)
3593 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3594 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3595 			pr := uint32(s11r)
3596 			out := uint8(pr >> 8)
3597 			dst.Pix[d+0] = out
3598 			dst.Pix[d+1] = out
3599 			dst.Pix[d+2] = out
3600 			dst.Pix[d+3] = 0xff
3601 		}
3602 	}
3603 }
3604 
3605 func (ablInterpolator) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
3606 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3607 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
3608 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
3609 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
3610 			dxf := float64(dr.Min.X+int(dx)) + 0.5
3611 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
3612 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
3613 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
3614 				continue
3615 			}
3616 
3617 			sx -= 0.5
3618 			sx0 := int(sx)
3619 			xFrac0 := sx - float64(sx0)
3620 			xFrac1 := 1 - xFrac0
3621 			sx0 += bias.X
3622 			sx1 := sx0 + 1
3623 			if sx0 < sr.Min.X {
3624 				sx0, sx1 = sr.Min.X, sr.Min.X
3625 				xFrac0, xFrac1 = 0, 1
3626 			} else if sx1 >= sr.Max.X {
3627 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
3628 				xFrac0, xFrac1 = 1, 0
3629 			}
3630 
3631 			sy -= 0.5
3632 			sy0 := int(sy)
3633 			yFrac0 := sy - float64(sy0)
3634 			yFrac1 := 1 - yFrac0
3635 			sy0 += bias.Y
3636 			sy1 := sy0 + 1
3637 			if sy0 < sr.Min.Y {
3638 				sy0, sy1 = sr.Min.Y, sr.Min.Y
3639 				yFrac0, yFrac1 = 0, 1
3640 			} else if sy1 >= sr.Max.Y {
3641 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
3642 				yFrac0, yFrac1 = 1, 0
3643 			}
3644 
3645 			s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3646 			s00au := uint32(src.Pix[s00i+3]) * 0x101
3647 			s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
3648 			s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
3649 			s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
3650 			s00r := float64(s00ru)
3651 			s00g := float64(s00gu)
3652 			s00b := float64(s00bu)
3653 			s00a := float64(s00au)
3654 			s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3655 			s10au := uint32(src.Pix[s10i+3]) * 0x101
3656 			s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
3657 			s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
3658 			s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
3659 			s10r := float64(s10ru)
3660 			s10g := float64(s10gu)
3661 			s10b := float64(s10bu)
3662 			s10a := float64(s10au)
3663 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3664 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3665 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3666 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3667 			s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3668 			s01au := uint32(src.Pix[s01i+3]) * 0x101
3669 			s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
3670 			s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
3671 			s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
3672 			s01r := float64(s01ru)
3673 			s01g := float64(s01gu)
3674 			s01b := float64(s01bu)
3675 			s01a := float64(s01au)
3676 			s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3677 			s11au := uint32(src.Pix[s11i+3]) * 0x101
3678 			s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
3679 			s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
3680 			s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
3681 			s11r := float64(s11ru)
3682 			s11g := float64(s11gu)
3683 			s11b := float64(s11bu)
3684 			s11a := float64(s11au)
3685 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3686 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3687 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3688 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3689 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3690 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3691 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3692 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3693 			pr := uint32(s11r)
3694 			pg := uint32(s11g)
3695 			pb := uint32(s11b)
3696 			pa := uint32(s11a)
3697 			pa1 := (0xffff - pa) * 0x101
3698 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
3699 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
3700 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
3701 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
3702 		}
3703 	}
3704 }
3705 
3706 func (ablInterpolator) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, opts *Options) {
3707 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3708 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
3709 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
3710 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
3711 			dxf := float64(dr.Min.X+int(dx)) + 0.5
3712 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
3713 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
3714 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
3715 				continue
3716 			}
3717 
3718 			sx -= 0.5
3719 			sx0 := int(sx)
3720 			xFrac0 := sx - float64(sx0)
3721 			xFrac1 := 1 - xFrac0
3722 			sx0 += bias.X
3723 			sx1 := sx0 + 1
3724 			if sx0 < sr.Min.X {
3725 				sx0, sx1 = sr.Min.X, sr.Min.X
3726 				xFrac0, xFrac1 = 0, 1
3727 			} else if sx1 >= sr.Max.X {
3728 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
3729 				xFrac0, xFrac1 = 1, 0
3730 			}
3731 
3732 			sy -= 0.5
3733 			sy0 := int(sy)
3734 			yFrac0 := sy - float64(sy0)
3735 			yFrac1 := 1 - yFrac0
3736 			sy0 += bias.Y
3737 			sy1 := sy0 + 1
3738 			if sy0 < sr.Min.Y {
3739 				sy0, sy1 = sr.Min.Y, sr.Min.Y
3740 				yFrac0, yFrac1 = 0, 1
3741 			} else if sy1 >= sr.Max.Y {
3742 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
3743 				yFrac0, yFrac1 = 1, 0
3744 			}
3745 
3746 			s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3747 			s00au := uint32(src.Pix[s00i+3]) * 0x101
3748 			s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff
3749 			s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff
3750 			s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff
3751 			s00r := float64(s00ru)
3752 			s00g := float64(s00gu)
3753 			s00b := float64(s00bu)
3754 			s00a := float64(s00au)
3755 			s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3756 			s10au := uint32(src.Pix[s10i+3]) * 0x101
3757 			s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff
3758 			s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff
3759 			s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff
3760 			s10r := float64(s10ru)
3761 			s10g := float64(s10gu)
3762 			s10b := float64(s10bu)
3763 			s10a := float64(s10au)
3764 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3765 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3766 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3767 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3768 			s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3769 			s01au := uint32(src.Pix[s01i+3]) * 0x101
3770 			s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff
3771 			s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff
3772 			s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff
3773 			s01r := float64(s01ru)
3774 			s01g := float64(s01gu)
3775 			s01b := float64(s01bu)
3776 			s01a := float64(s01au)
3777 			s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3778 			s11au := uint32(src.Pix[s11i+3]) * 0x101
3779 			s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff
3780 			s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff
3781 			s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff
3782 			s11r := float64(s11ru)
3783 			s11g := float64(s11gu)
3784 			s11b := float64(s11bu)
3785 			s11a := float64(s11au)
3786 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3787 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3788 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3789 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3790 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3791 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3792 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3793 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3794 			pr := uint32(s11r)
3795 			pg := uint32(s11g)
3796 			pb := uint32(s11b)
3797 			pa := uint32(s11a)
3798 			dst.Pix[d+0] = uint8(pr >> 8)
3799 			dst.Pix[d+1] = uint8(pg >> 8)
3800 			dst.Pix[d+2] = uint8(pb >> 8)
3801 			dst.Pix[d+3] = uint8(pa >> 8)
3802 		}
3803 	}
3804 }
3805 
3806 func (ablInterpolator) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
3807 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3808 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
3809 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
3810 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
3811 			dxf := float64(dr.Min.X+int(dx)) + 0.5
3812 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
3813 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
3814 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
3815 				continue
3816 			}
3817 
3818 			sx -= 0.5
3819 			sx0 := int(sx)
3820 			xFrac0 := sx - float64(sx0)
3821 			xFrac1 := 1 - xFrac0
3822 			sx0 += bias.X
3823 			sx1 := sx0 + 1
3824 			if sx0 < sr.Min.X {
3825 				sx0, sx1 = sr.Min.X, sr.Min.X
3826 				xFrac0, xFrac1 = 0, 1
3827 			} else if sx1 >= sr.Max.X {
3828 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
3829 				xFrac0, xFrac1 = 1, 0
3830 			}
3831 
3832 			sy -= 0.5
3833 			sy0 := int(sy)
3834 			yFrac0 := sy - float64(sy0)
3835 			yFrac1 := 1 - yFrac0
3836 			sy0 += bias.Y
3837 			sy1 := sy0 + 1
3838 			if sy0 < sr.Min.Y {
3839 				sy0, sy1 = sr.Min.Y, sr.Min.Y
3840 				yFrac0, yFrac1 = 0, 1
3841 			} else if sy1 >= sr.Max.Y {
3842 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
3843 				yFrac0, yFrac1 = 1, 0
3844 			}
3845 
3846 			s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3847 			s00ru := uint32(src.Pix[s00i+0]) * 0x101
3848 			s00gu := uint32(src.Pix[s00i+1]) * 0x101
3849 			s00bu := uint32(src.Pix[s00i+2]) * 0x101
3850 			s00au := uint32(src.Pix[s00i+3]) * 0x101
3851 			s00r := float64(s00ru)
3852 			s00g := float64(s00gu)
3853 			s00b := float64(s00bu)
3854 			s00a := float64(s00au)
3855 			s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3856 			s10ru := uint32(src.Pix[s10i+0]) * 0x101
3857 			s10gu := uint32(src.Pix[s10i+1]) * 0x101
3858 			s10bu := uint32(src.Pix[s10i+2]) * 0x101
3859 			s10au := uint32(src.Pix[s10i+3]) * 0x101
3860 			s10r := float64(s10ru)
3861 			s10g := float64(s10gu)
3862 			s10b := float64(s10bu)
3863 			s10a := float64(s10au)
3864 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3865 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3866 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3867 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3868 			s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3869 			s01ru := uint32(src.Pix[s01i+0]) * 0x101
3870 			s01gu := uint32(src.Pix[s01i+1]) * 0x101
3871 			s01bu := uint32(src.Pix[s01i+2]) * 0x101
3872 			s01au := uint32(src.Pix[s01i+3]) * 0x101
3873 			s01r := float64(s01ru)
3874 			s01g := float64(s01gu)
3875 			s01b := float64(s01bu)
3876 			s01a := float64(s01au)
3877 			s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3878 			s11ru := uint32(src.Pix[s11i+0]) * 0x101
3879 			s11gu := uint32(src.Pix[s11i+1]) * 0x101
3880 			s11bu := uint32(src.Pix[s11i+2]) * 0x101
3881 			s11au := uint32(src.Pix[s11i+3]) * 0x101
3882 			s11r := float64(s11ru)
3883 			s11g := float64(s11gu)
3884 			s11b := float64(s11bu)
3885 			s11a := float64(s11au)
3886 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3887 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3888 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3889 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3890 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3891 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3892 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3893 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3894 			pr := uint32(s11r)
3895 			pg := uint32(s11g)
3896 			pb := uint32(s11b)
3897 			pa := uint32(s11a)
3898 			pa1 := (0xffff - pa) * 0x101
3899 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
3900 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
3901 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
3902 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
3903 		}
3904 	}
3905 }
3906 
3907 func (ablInterpolator) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, opts *Options) {
3908 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
3909 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
3910 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
3911 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
3912 			dxf := float64(dr.Min.X+int(dx)) + 0.5
3913 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
3914 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
3915 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
3916 				continue
3917 			}
3918 
3919 			sx -= 0.5
3920 			sx0 := int(sx)
3921 			xFrac0 := sx - float64(sx0)
3922 			xFrac1 := 1 - xFrac0
3923 			sx0 += bias.X
3924 			sx1 := sx0 + 1
3925 			if sx0 < sr.Min.X {
3926 				sx0, sx1 = sr.Min.X, sr.Min.X
3927 				xFrac0, xFrac1 = 0, 1
3928 			} else if sx1 >= sr.Max.X {
3929 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
3930 				xFrac0, xFrac1 = 1, 0
3931 			}
3932 
3933 			sy -= 0.5
3934 			sy0 := int(sy)
3935 			yFrac0 := sy - float64(sy0)
3936 			yFrac1 := 1 - yFrac0
3937 			sy0 += bias.Y
3938 			sy1 := sy0 + 1
3939 			if sy0 < sr.Min.Y {
3940 				sy0, sy1 = sr.Min.Y, sr.Min.Y
3941 				yFrac0, yFrac1 = 0, 1
3942 			} else if sy1 >= sr.Max.Y {
3943 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
3944 				yFrac0, yFrac1 = 1, 0
3945 			}
3946 
3947 			s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3948 			s00ru := uint32(src.Pix[s00i+0]) * 0x101
3949 			s00gu := uint32(src.Pix[s00i+1]) * 0x101
3950 			s00bu := uint32(src.Pix[s00i+2]) * 0x101
3951 			s00au := uint32(src.Pix[s00i+3]) * 0x101
3952 			s00r := float64(s00ru)
3953 			s00g := float64(s00gu)
3954 			s00b := float64(s00bu)
3955 			s00a := float64(s00au)
3956 			s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3957 			s10ru := uint32(src.Pix[s10i+0]) * 0x101
3958 			s10gu := uint32(src.Pix[s10i+1]) * 0x101
3959 			s10bu := uint32(src.Pix[s10i+2]) * 0x101
3960 			s10au := uint32(src.Pix[s10i+3]) * 0x101
3961 			s10r := float64(s10ru)
3962 			s10g := float64(s10gu)
3963 			s10b := float64(s10bu)
3964 			s10a := float64(s10au)
3965 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
3966 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
3967 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
3968 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
3969 			s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4
3970 			s01ru := uint32(src.Pix[s01i+0]) * 0x101
3971 			s01gu := uint32(src.Pix[s01i+1]) * 0x101
3972 			s01bu := uint32(src.Pix[s01i+2]) * 0x101
3973 			s01au := uint32(src.Pix[s01i+3]) * 0x101
3974 			s01r := float64(s01ru)
3975 			s01g := float64(s01gu)
3976 			s01b := float64(s01bu)
3977 			s01a := float64(s01au)
3978 			s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4
3979 			s11ru := uint32(src.Pix[s11i+0]) * 0x101
3980 			s11gu := uint32(src.Pix[s11i+1]) * 0x101
3981 			s11bu := uint32(src.Pix[s11i+2]) * 0x101
3982 			s11au := uint32(src.Pix[s11i+3]) * 0x101
3983 			s11r := float64(s11ru)
3984 			s11g := float64(s11gu)
3985 			s11b := float64(s11bu)
3986 			s11a := float64(s11au)
3987 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
3988 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
3989 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
3990 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
3991 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
3992 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
3993 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
3994 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
3995 			pr := uint32(s11r)
3996 			pg := uint32(s11g)
3997 			pb := uint32(s11b)
3998 			pa := uint32(s11a)
3999 			dst.Pix[d+0] = uint8(pr >> 8)
4000 			dst.Pix[d+1] = uint8(pg >> 8)
4001 			dst.Pix[d+2] = uint8(pb >> 8)
4002 			dst.Pix[d+3] = uint8(pa >> 8)
4003 		}
4004 	}
4005 }
4006 
4007 func (ablInterpolator) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
4008 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4009 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4010 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4011 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4012 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4013 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4014 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4015 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4016 				continue
4017 			}
4018 
4019 			sx -= 0.5
4020 			sx0 := int(sx)
4021 			xFrac0 := sx - float64(sx0)
4022 			xFrac1 := 1 - xFrac0
4023 			sx0 += bias.X
4024 			sx1 := sx0 + 1
4025 			if sx0 < sr.Min.X {
4026 				sx0, sx1 = sr.Min.X, sr.Min.X
4027 				xFrac0, xFrac1 = 0, 1
4028 			} else if sx1 >= sr.Max.X {
4029 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4030 				xFrac0, xFrac1 = 1, 0
4031 			}
4032 
4033 			sy -= 0.5
4034 			sy0 := int(sy)
4035 			yFrac0 := sy - float64(sy0)
4036 			yFrac1 := 1 - yFrac0
4037 			sy0 += bias.Y
4038 			sy1 := sy0 + 1
4039 			if sy0 < sr.Min.Y {
4040 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4041 				yFrac0, yFrac1 = 0, 1
4042 			} else if sy1 >= sr.Max.Y {
4043 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4044 				yFrac0, yFrac1 = 1, 0
4045 			}
4046 
4047 			s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4048 			s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
4049 
4050 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4051 			s00yy1 := int(src.Y[s00i]) * 0x10101
4052 			s00cb1 := int(src.Cb[s00j]) - 128
4053 			s00cr1 := int(src.Cr[s00j]) - 128
4054 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
4055 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
4056 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
4057 			if s00ru < 0 {
4058 				s00ru = 0
4059 			} else if s00ru > 0xffff {
4060 				s00ru = 0xffff
4061 			}
4062 			if s00gu < 0 {
4063 				s00gu = 0
4064 			} else if s00gu > 0xffff {
4065 				s00gu = 0xffff
4066 			}
4067 			if s00bu < 0 {
4068 				s00bu = 0
4069 			} else if s00bu > 0xffff {
4070 				s00bu = 0xffff
4071 			}
4072 
4073 			s00r := float64(s00ru)
4074 			s00g := float64(s00gu)
4075 			s00b := float64(s00bu)
4076 			s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4077 			s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
4078 
4079 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4080 			s10yy1 := int(src.Y[s10i]) * 0x10101
4081 			s10cb1 := int(src.Cb[s10j]) - 128
4082 			s10cr1 := int(src.Cr[s10j]) - 128
4083 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
4084 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
4085 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
4086 			if s10ru < 0 {
4087 				s10ru = 0
4088 			} else if s10ru > 0xffff {
4089 				s10ru = 0xffff
4090 			}
4091 			if s10gu < 0 {
4092 				s10gu = 0
4093 			} else if s10gu > 0xffff {
4094 				s10gu = 0xffff
4095 			}
4096 			if s10bu < 0 {
4097 				s10bu = 0
4098 			} else if s10bu > 0xffff {
4099 				s10bu = 0xffff
4100 			}
4101 
4102 			s10r := float64(s10ru)
4103 			s10g := float64(s10gu)
4104 			s10b := float64(s10bu)
4105 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4106 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4107 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4108 			s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4109 			s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X)
4110 
4111 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4112 			s01yy1 := int(src.Y[s01i]) * 0x10101
4113 			s01cb1 := int(src.Cb[s01j]) - 128
4114 			s01cr1 := int(src.Cr[s01j]) - 128
4115 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
4116 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
4117 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
4118 			if s01ru < 0 {
4119 				s01ru = 0
4120 			} else if s01ru > 0xffff {
4121 				s01ru = 0xffff
4122 			}
4123 			if s01gu < 0 {
4124 				s01gu = 0
4125 			} else if s01gu > 0xffff {
4126 				s01gu = 0xffff
4127 			}
4128 			if s01bu < 0 {
4129 				s01bu = 0
4130 			} else if s01bu > 0xffff {
4131 				s01bu = 0xffff
4132 			}
4133 
4134 			s01r := float64(s01ru)
4135 			s01g := float64(s01gu)
4136 			s01b := float64(s01bu)
4137 			s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4138 			s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X)
4139 
4140 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4141 			s11yy1 := int(src.Y[s11i]) * 0x10101
4142 			s11cb1 := int(src.Cb[s11j]) - 128
4143 			s11cr1 := int(src.Cr[s11j]) - 128
4144 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
4145 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
4146 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
4147 			if s11ru < 0 {
4148 				s11ru = 0
4149 			} else if s11ru > 0xffff {
4150 				s11ru = 0xffff
4151 			}
4152 			if s11gu < 0 {
4153 				s11gu = 0
4154 			} else if s11gu > 0xffff {
4155 				s11gu = 0xffff
4156 			}
4157 			if s11bu < 0 {
4158 				s11bu = 0
4159 			} else if s11bu > 0xffff {
4160 				s11bu = 0xffff
4161 			}
4162 
4163 			s11r := float64(s11ru)
4164 			s11g := float64(s11gu)
4165 			s11b := float64(s11bu)
4166 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4167 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4168 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4169 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4170 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4171 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4172 			pr := uint32(s11r)
4173 			pg := uint32(s11g)
4174 			pb := uint32(s11b)
4175 			dst.Pix[d+0] = uint8(pr >> 8)
4176 			dst.Pix[d+1] = uint8(pg >> 8)
4177 			dst.Pix[d+2] = uint8(pb >> 8)
4178 			dst.Pix[d+3] = 0xff
4179 		}
4180 	}
4181 }
4182 
4183 func (ablInterpolator) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
4184 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4185 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4186 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4187 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4188 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4189 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4190 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4191 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4192 				continue
4193 			}
4194 
4195 			sx -= 0.5
4196 			sx0 := int(sx)
4197 			xFrac0 := sx - float64(sx0)
4198 			xFrac1 := 1 - xFrac0
4199 			sx0 += bias.X
4200 			sx1 := sx0 + 1
4201 			if sx0 < sr.Min.X {
4202 				sx0, sx1 = sr.Min.X, sr.Min.X
4203 				xFrac0, xFrac1 = 0, 1
4204 			} else if sx1 >= sr.Max.X {
4205 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4206 				xFrac0, xFrac1 = 1, 0
4207 			}
4208 
4209 			sy -= 0.5
4210 			sy0 := int(sy)
4211 			yFrac0 := sy - float64(sy0)
4212 			yFrac1 := 1 - yFrac0
4213 			sy0 += bias.Y
4214 			sy1 := sy0 + 1
4215 			if sy0 < sr.Min.Y {
4216 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4217 				yFrac0, yFrac1 = 0, 1
4218 			} else if sy1 >= sr.Max.Y {
4219 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4220 				yFrac0, yFrac1 = 1, 0
4221 			}
4222 
4223 			s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4224 			s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
4225 
4226 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4227 			s00yy1 := int(src.Y[s00i]) * 0x10101
4228 			s00cb1 := int(src.Cb[s00j]) - 128
4229 			s00cr1 := int(src.Cr[s00j]) - 128
4230 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
4231 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
4232 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
4233 			if s00ru < 0 {
4234 				s00ru = 0
4235 			} else if s00ru > 0xffff {
4236 				s00ru = 0xffff
4237 			}
4238 			if s00gu < 0 {
4239 				s00gu = 0
4240 			} else if s00gu > 0xffff {
4241 				s00gu = 0xffff
4242 			}
4243 			if s00bu < 0 {
4244 				s00bu = 0
4245 			} else if s00bu > 0xffff {
4246 				s00bu = 0xffff
4247 			}
4248 
4249 			s00r := float64(s00ru)
4250 			s00g := float64(s00gu)
4251 			s00b := float64(s00bu)
4252 			s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4253 			s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
4254 
4255 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4256 			s10yy1 := int(src.Y[s10i]) * 0x10101
4257 			s10cb1 := int(src.Cb[s10j]) - 128
4258 			s10cr1 := int(src.Cr[s10j]) - 128
4259 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
4260 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
4261 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
4262 			if s10ru < 0 {
4263 				s10ru = 0
4264 			} else if s10ru > 0xffff {
4265 				s10ru = 0xffff
4266 			}
4267 			if s10gu < 0 {
4268 				s10gu = 0
4269 			} else if s10gu > 0xffff {
4270 				s10gu = 0xffff
4271 			}
4272 			if s10bu < 0 {
4273 				s10bu = 0
4274 			} else if s10bu > 0xffff {
4275 				s10bu = 0xffff
4276 			}
4277 
4278 			s10r := float64(s10ru)
4279 			s10g := float64(s10gu)
4280 			s10b := float64(s10bu)
4281 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4282 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4283 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4284 			s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4285 			s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
4286 
4287 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4288 			s01yy1 := int(src.Y[s01i]) * 0x10101
4289 			s01cb1 := int(src.Cb[s01j]) - 128
4290 			s01cr1 := int(src.Cr[s01j]) - 128
4291 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
4292 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
4293 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
4294 			if s01ru < 0 {
4295 				s01ru = 0
4296 			} else if s01ru > 0xffff {
4297 				s01ru = 0xffff
4298 			}
4299 			if s01gu < 0 {
4300 				s01gu = 0
4301 			} else if s01gu > 0xffff {
4302 				s01gu = 0xffff
4303 			}
4304 			if s01bu < 0 {
4305 				s01bu = 0
4306 			} else if s01bu > 0xffff {
4307 				s01bu = 0xffff
4308 			}
4309 
4310 			s01r := float64(s01ru)
4311 			s01g := float64(s01gu)
4312 			s01b := float64(s01bu)
4313 			s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4314 			s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
4315 
4316 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4317 			s11yy1 := int(src.Y[s11i]) * 0x10101
4318 			s11cb1 := int(src.Cb[s11j]) - 128
4319 			s11cr1 := int(src.Cr[s11j]) - 128
4320 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
4321 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
4322 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
4323 			if s11ru < 0 {
4324 				s11ru = 0
4325 			} else if s11ru > 0xffff {
4326 				s11ru = 0xffff
4327 			}
4328 			if s11gu < 0 {
4329 				s11gu = 0
4330 			} else if s11gu > 0xffff {
4331 				s11gu = 0xffff
4332 			}
4333 			if s11bu < 0 {
4334 				s11bu = 0
4335 			} else if s11bu > 0xffff {
4336 				s11bu = 0xffff
4337 			}
4338 
4339 			s11r := float64(s11ru)
4340 			s11g := float64(s11gu)
4341 			s11b := float64(s11bu)
4342 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4343 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4344 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4345 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4346 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4347 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4348 			pr := uint32(s11r)
4349 			pg := uint32(s11g)
4350 			pb := uint32(s11b)
4351 			dst.Pix[d+0] = uint8(pr >> 8)
4352 			dst.Pix[d+1] = uint8(pg >> 8)
4353 			dst.Pix[d+2] = uint8(pb >> 8)
4354 			dst.Pix[d+3] = 0xff
4355 		}
4356 	}
4357 }
4358 
4359 func (ablInterpolator) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
4360 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4361 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4362 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4363 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4364 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4365 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4366 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4367 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4368 				continue
4369 			}
4370 
4371 			sx -= 0.5
4372 			sx0 := int(sx)
4373 			xFrac0 := sx - float64(sx0)
4374 			xFrac1 := 1 - xFrac0
4375 			sx0 += bias.X
4376 			sx1 := sx0 + 1
4377 			if sx0 < sr.Min.X {
4378 				sx0, sx1 = sr.Min.X, sr.Min.X
4379 				xFrac0, xFrac1 = 0, 1
4380 			} else if sx1 >= sr.Max.X {
4381 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4382 				xFrac0, xFrac1 = 1, 0
4383 			}
4384 
4385 			sy -= 0.5
4386 			sy0 := int(sy)
4387 			yFrac0 := sy - float64(sy0)
4388 			yFrac1 := 1 - yFrac0
4389 			sy0 += bias.Y
4390 			sy1 := sy0 + 1
4391 			if sy0 < sr.Min.Y {
4392 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4393 				yFrac0, yFrac1 = 0, 1
4394 			} else if sy1 >= sr.Max.Y {
4395 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4396 				yFrac0, yFrac1 = 1, 0
4397 			}
4398 
4399 			s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4400 			s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
4401 
4402 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4403 			s00yy1 := int(src.Y[s00i]) * 0x10101
4404 			s00cb1 := int(src.Cb[s00j]) - 128
4405 			s00cr1 := int(src.Cr[s00j]) - 128
4406 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
4407 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
4408 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
4409 			if s00ru < 0 {
4410 				s00ru = 0
4411 			} else if s00ru > 0xffff {
4412 				s00ru = 0xffff
4413 			}
4414 			if s00gu < 0 {
4415 				s00gu = 0
4416 			} else if s00gu > 0xffff {
4417 				s00gu = 0xffff
4418 			}
4419 			if s00bu < 0 {
4420 				s00bu = 0
4421 			} else if s00bu > 0xffff {
4422 				s00bu = 0xffff
4423 			}
4424 
4425 			s00r := float64(s00ru)
4426 			s00g := float64(s00gu)
4427 			s00b := float64(s00bu)
4428 			s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4429 			s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
4430 
4431 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4432 			s10yy1 := int(src.Y[s10i]) * 0x10101
4433 			s10cb1 := int(src.Cb[s10j]) - 128
4434 			s10cr1 := int(src.Cr[s10j]) - 128
4435 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
4436 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
4437 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
4438 			if s10ru < 0 {
4439 				s10ru = 0
4440 			} else if s10ru > 0xffff {
4441 				s10ru = 0xffff
4442 			}
4443 			if s10gu < 0 {
4444 				s10gu = 0
4445 			} else if s10gu > 0xffff {
4446 				s10gu = 0xffff
4447 			}
4448 			if s10bu < 0 {
4449 				s10bu = 0
4450 			} else if s10bu > 0xffff {
4451 				s10bu = 0xffff
4452 			}
4453 
4454 			s10r := float64(s10ru)
4455 			s10g := float64(s10gu)
4456 			s10b := float64(s10bu)
4457 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4458 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4459 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4460 			s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4461 			s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2)
4462 
4463 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4464 			s01yy1 := int(src.Y[s01i]) * 0x10101
4465 			s01cb1 := int(src.Cb[s01j]) - 128
4466 			s01cr1 := int(src.Cr[s01j]) - 128
4467 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
4468 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
4469 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
4470 			if s01ru < 0 {
4471 				s01ru = 0
4472 			} else if s01ru > 0xffff {
4473 				s01ru = 0xffff
4474 			}
4475 			if s01gu < 0 {
4476 				s01gu = 0
4477 			} else if s01gu > 0xffff {
4478 				s01gu = 0xffff
4479 			}
4480 			if s01bu < 0 {
4481 				s01bu = 0
4482 			} else if s01bu > 0xffff {
4483 				s01bu = 0xffff
4484 			}
4485 
4486 			s01r := float64(s01ru)
4487 			s01g := float64(s01gu)
4488 			s01b := float64(s01bu)
4489 			s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4490 			s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2)
4491 
4492 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4493 			s11yy1 := int(src.Y[s11i]) * 0x10101
4494 			s11cb1 := int(src.Cb[s11j]) - 128
4495 			s11cr1 := int(src.Cr[s11j]) - 128
4496 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
4497 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
4498 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
4499 			if s11ru < 0 {
4500 				s11ru = 0
4501 			} else if s11ru > 0xffff {
4502 				s11ru = 0xffff
4503 			}
4504 			if s11gu < 0 {
4505 				s11gu = 0
4506 			} else if s11gu > 0xffff {
4507 				s11gu = 0xffff
4508 			}
4509 			if s11bu < 0 {
4510 				s11bu = 0
4511 			} else if s11bu > 0xffff {
4512 				s11bu = 0xffff
4513 			}
4514 
4515 			s11r := float64(s11ru)
4516 			s11g := float64(s11gu)
4517 			s11b := float64(s11bu)
4518 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4519 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4520 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4521 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4522 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4523 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4524 			pr := uint32(s11r)
4525 			pg := uint32(s11g)
4526 			pb := uint32(s11b)
4527 			dst.Pix[d+0] = uint8(pr >> 8)
4528 			dst.Pix[d+1] = uint8(pg >> 8)
4529 			dst.Pix[d+2] = uint8(pb >> 8)
4530 			dst.Pix[d+3] = 0xff
4531 		}
4532 	}
4533 }
4534 
4535 func (ablInterpolator) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, opts *Options) {
4536 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4537 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4538 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4539 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4540 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4541 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4542 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4543 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4544 				continue
4545 			}
4546 
4547 			sx -= 0.5
4548 			sx0 := int(sx)
4549 			xFrac0 := sx - float64(sx0)
4550 			xFrac1 := 1 - xFrac0
4551 			sx0 += bias.X
4552 			sx1 := sx0 + 1
4553 			if sx0 < sr.Min.X {
4554 				sx0, sx1 = sr.Min.X, sr.Min.X
4555 				xFrac0, xFrac1 = 0, 1
4556 			} else if sx1 >= sr.Max.X {
4557 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4558 				xFrac0, xFrac1 = 1, 0
4559 			}
4560 
4561 			sy -= 0.5
4562 			sy0 := int(sy)
4563 			yFrac0 := sy - float64(sy0)
4564 			yFrac1 := 1 - yFrac0
4565 			sy0 += bias.Y
4566 			sy1 := sy0 + 1
4567 			if sy0 < sr.Min.Y {
4568 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4569 				yFrac0, yFrac1 = 0, 1
4570 			} else if sy1 >= sr.Max.Y {
4571 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4572 				yFrac0, yFrac1 = 1, 0
4573 			}
4574 
4575 			s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4576 			s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
4577 
4578 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4579 			s00yy1 := int(src.Y[s00i]) * 0x10101
4580 			s00cb1 := int(src.Cb[s00j]) - 128
4581 			s00cr1 := int(src.Cr[s00j]) - 128
4582 			s00ru := (s00yy1 + 91881*s00cr1) >> 8
4583 			s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8
4584 			s00bu := (s00yy1 + 116130*s00cb1) >> 8
4585 			if s00ru < 0 {
4586 				s00ru = 0
4587 			} else if s00ru > 0xffff {
4588 				s00ru = 0xffff
4589 			}
4590 			if s00gu < 0 {
4591 				s00gu = 0
4592 			} else if s00gu > 0xffff {
4593 				s00gu = 0xffff
4594 			}
4595 			if s00bu < 0 {
4596 				s00bu = 0
4597 			} else if s00bu > 0xffff {
4598 				s00bu = 0xffff
4599 			}
4600 
4601 			s00r := float64(s00ru)
4602 			s00g := float64(s00gu)
4603 			s00b := float64(s00bu)
4604 			s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4605 			s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
4606 
4607 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4608 			s10yy1 := int(src.Y[s10i]) * 0x10101
4609 			s10cb1 := int(src.Cb[s10j]) - 128
4610 			s10cr1 := int(src.Cr[s10j]) - 128
4611 			s10ru := (s10yy1 + 91881*s10cr1) >> 8
4612 			s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8
4613 			s10bu := (s10yy1 + 116130*s10cb1) >> 8
4614 			if s10ru < 0 {
4615 				s10ru = 0
4616 			} else if s10ru > 0xffff {
4617 				s10ru = 0xffff
4618 			}
4619 			if s10gu < 0 {
4620 				s10gu = 0
4621 			} else if s10gu > 0xffff {
4622 				s10gu = 0xffff
4623 			}
4624 			if s10bu < 0 {
4625 				s10bu = 0
4626 			} else if s10bu > 0xffff {
4627 				s10bu = 0xffff
4628 			}
4629 
4630 			s10r := float64(s10ru)
4631 			s10g := float64(s10gu)
4632 			s10b := float64(s10bu)
4633 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4634 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4635 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4636 			s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X)
4637 			s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X)
4638 
4639 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4640 			s01yy1 := int(src.Y[s01i]) * 0x10101
4641 			s01cb1 := int(src.Cb[s01j]) - 128
4642 			s01cr1 := int(src.Cr[s01j]) - 128
4643 			s01ru := (s01yy1 + 91881*s01cr1) >> 8
4644 			s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8
4645 			s01bu := (s01yy1 + 116130*s01cb1) >> 8
4646 			if s01ru < 0 {
4647 				s01ru = 0
4648 			} else if s01ru > 0xffff {
4649 				s01ru = 0xffff
4650 			}
4651 			if s01gu < 0 {
4652 				s01gu = 0
4653 			} else if s01gu > 0xffff {
4654 				s01gu = 0xffff
4655 			}
4656 			if s01bu < 0 {
4657 				s01bu = 0
4658 			} else if s01bu > 0xffff {
4659 				s01bu = 0xffff
4660 			}
4661 
4662 			s01r := float64(s01ru)
4663 			s01g := float64(s01gu)
4664 			s01b := float64(s01bu)
4665 			s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X)
4666 			s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X)
4667 
4668 			// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
4669 			s11yy1 := int(src.Y[s11i]) * 0x10101
4670 			s11cb1 := int(src.Cb[s11j]) - 128
4671 			s11cr1 := int(src.Cr[s11j]) - 128
4672 			s11ru := (s11yy1 + 91881*s11cr1) >> 8
4673 			s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8
4674 			s11bu := (s11yy1 + 116130*s11cb1) >> 8
4675 			if s11ru < 0 {
4676 				s11ru = 0
4677 			} else if s11ru > 0xffff {
4678 				s11ru = 0xffff
4679 			}
4680 			if s11gu < 0 {
4681 				s11gu = 0
4682 			} else if s11gu > 0xffff {
4683 				s11gu = 0xffff
4684 			}
4685 			if s11bu < 0 {
4686 				s11bu = 0
4687 			} else if s11bu > 0xffff {
4688 				s11bu = 0xffff
4689 			}
4690 
4691 			s11r := float64(s11ru)
4692 			s11g := float64(s11gu)
4693 			s11b := float64(s11bu)
4694 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4695 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4696 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4697 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4698 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4699 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4700 			pr := uint32(s11r)
4701 			pg := uint32(s11g)
4702 			pb := uint32(s11b)
4703 			dst.Pix[d+0] = uint8(pr >> 8)
4704 			dst.Pix[d+1] = uint8(pg >> 8)
4705 			dst.Pix[d+2] = uint8(pb >> 8)
4706 			dst.Pix[d+3] = 0xff
4707 		}
4708 	}
4709 }
4710 
4711 func (ablInterpolator) transform_RGBA_RGBA64Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
4712 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4713 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4714 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4715 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4716 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4717 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4718 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4719 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4720 				continue
4721 			}
4722 
4723 			sx -= 0.5
4724 			sx0 := int(sx)
4725 			xFrac0 := sx - float64(sx0)
4726 			xFrac1 := 1 - xFrac0
4727 			sx0 += bias.X
4728 			sx1 := sx0 + 1
4729 			if sx0 < sr.Min.X {
4730 				sx0, sx1 = sr.Min.X, sr.Min.X
4731 				xFrac0, xFrac1 = 0, 1
4732 			} else if sx1 >= sr.Max.X {
4733 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4734 				xFrac0, xFrac1 = 1, 0
4735 			}
4736 
4737 			sy -= 0.5
4738 			sy0 := int(sy)
4739 			yFrac0 := sy - float64(sy0)
4740 			yFrac1 := 1 - yFrac0
4741 			sy0 += bias.Y
4742 			sy1 := sy0 + 1
4743 			if sy0 < sr.Min.Y {
4744 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4745 				yFrac0, yFrac1 = 0, 1
4746 			} else if sy1 >= sr.Max.Y {
4747 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4748 				yFrac0, yFrac1 = 1, 0
4749 			}
4750 
4751 			s00u := src.RGBA64At(sx0, sy0)
4752 			s00r := float64(s00u.R)
4753 			s00g := float64(s00u.G)
4754 			s00b := float64(s00u.B)
4755 			s00a := float64(s00u.A)
4756 			s10u := src.RGBA64At(sx1, sy0)
4757 			s10r := float64(s10u.R)
4758 			s10g := float64(s10u.G)
4759 			s10b := float64(s10u.B)
4760 			s10a := float64(s10u.A)
4761 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4762 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4763 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4764 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
4765 			s01u := src.RGBA64At(sx0, sy1)
4766 			s01r := float64(s01u.R)
4767 			s01g := float64(s01u.G)
4768 			s01b := float64(s01u.B)
4769 			s01a := float64(s01u.A)
4770 			s11u := src.RGBA64At(sx1, sy1)
4771 			s11r := float64(s11u.R)
4772 			s11g := float64(s11u.G)
4773 			s11b := float64(s11u.B)
4774 			s11a := float64(s11u.A)
4775 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4776 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4777 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4778 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
4779 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4780 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4781 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4782 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
4783 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
4784 			pa1 := (0xffff - uint32(p.A)) * 0x101
4785 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + uint32(p.R)) >> 8)
4786 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + uint32(p.G)) >> 8)
4787 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + uint32(p.B)) >> 8)
4788 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + uint32(p.A)) >> 8)
4789 		}
4790 	}
4791 }
4792 
4793 func (ablInterpolator) transform_RGBA_RGBA64Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
4794 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4795 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4796 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4797 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4798 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4799 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4800 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4801 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4802 				continue
4803 			}
4804 
4805 			sx -= 0.5
4806 			sx0 := int(sx)
4807 			xFrac0 := sx - float64(sx0)
4808 			xFrac1 := 1 - xFrac0
4809 			sx0 += bias.X
4810 			sx1 := sx0 + 1
4811 			if sx0 < sr.Min.X {
4812 				sx0, sx1 = sr.Min.X, sr.Min.X
4813 				xFrac0, xFrac1 = 0, 1
4814 			} else if sx1 >= sr.Max.X {
4815 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4816 				xFrac0, xFrac1 = 1, 0
4817 			}
4818 
4819 			sy -= 0.5
4820 			sy0 := int(sy)
4821 			yFrac0 := sy - float64(sy0)
4822 			yFrac1 := 1 - yFrac0
4823 			sy0 += bias.Y
4824 			sy1 := sy0 + 1
4825 			if sy0 < sr.Min.Y {
4826 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4827 				yFrac0, yFrac1 = 0, 1
4828 			} else if sy1 >= sr.Max.Y {
4829 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4830 				yFrac0, yFrac1 = 1, 0
4831 			}
4832 
4833 			s00u := src.RGBA64At(sx0, sy0)
4834 			s00r := float64(s00u.R)
4835 			s00g := float64(s00u.G)
4836 			s00b := float64(s00u.B)
4837 			s00a := float64(s00u.A)
4838 			s10u := src.RGBA64At(sx1, sy0)
4839 			s10r := float64(s10u.R)
4840 			s10g := float64(s10u.G)
4841 			s10b := float64(s10u.B)
4842 			s10a := float64(s10u.A)
4843 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4844 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4845 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4846 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
4847 			s01u := src.RGBA64At(sx0, sy1)
4848 			s01r := float64(s01u.R)
4849 			s01g := float64(s01u.G)
4850 			s01b := float64(s01u.B)
4851 			s01a := float64(s01u.A)
4852 			s11u := src.RGBA64At(sx1, sy1)
4853 			s11r := float64(s11u.R)
4854 			s11g := float64(s11u.G)
4855 			s11b := float64(s11u.B)
4856 			s11a := float64(s11u.A)
4857 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4858 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4859 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4860 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
4861 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4862 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4863 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4864 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
4865 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
4866 			dst.Pix[d+0] = uint8(p.R >> 8)
4867 			dst.Pix[d+1] = uint8(p.G >> 8)
4868 			dst.Pix[d+2] = uint8(p.B >> 8)
4869 			dst.Pix[d+3] = uint8(p.A >> 8)
4870 		}
4871 	}
4872 }
4873 
4874 func (ablInterpolator) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
4875 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4876 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4877 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4878 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4879 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4880 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4881 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4882 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4883 				continue
4884 			}
4885 
4886 			sx -= 0.5
4887 			sx0 := int(sx)
4888 			xFrac0 := sx - float64(sx0)
4889 			xFrac1 := 1 - xFrac0
4890 			sx0 += bias.X
4891 			sx1 := sx0 + 1
4892 			if sx0 < sr.Min.X {
4893 				sx0, sx1 = sr.Min.X, sr.Min.X
4894 				xFrac0, xFrac1 = 0, 1
4895 			} else if sx1 >= sr.Max.X {
4896 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4897 				xFrac0, xFrac1 = 1, 0
4898 			}
4899 
4900 			sy -= 0.5
4901 			sy0 := int(sy)
4902 			yFrac0 := sy - float64(sy0)
4903 			yFrac1 := 1 - yFrac0
4904 			sy0 += bias.Y
4905 			sy1 := sy0 + 1
4906 			if sy0 < sr.Min.Y {
4907 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4908 				yFrac0, yFrac1 = 0, 1
4909 			} else if sy1 >= sr.Max.Y {
4910 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4911 				yFrac0, yFrac1 = 1, 0
4912 			}
4913 
4914 			s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
4915 			s00r := float64(s00ru)
4916 			s00g := float64(s00gu)
4917 			s00b := float64(s00bu)
4918 			s00a := float64(s00au)
4919 			s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
4920 			s10r := float64(s10ru)
4921 			s10g := float64(s10gu)
4922 			s10b := float64(s10bu)
4923 			s10a := float64(s10au)
4924 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
4925 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
4926 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
4927 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
4928 			s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
4929 			s01r := float64(s01ru)
4930 			s01g := float64(s01gu)
4931 			s01b := float64(s01bu)
4932 			s01a := float64(s01au)
4933 			s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
4934 			s11r := float64(s11ru)
4935 			s11g := float64(s11gu)
4936 			s11b := float64(s11bu)
4937 			s11a := float64(s11au)
4938 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
4939 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
4940 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
4941 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
4942 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
4943 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
4944 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
4945 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
4946 			pr := uint32(s11r)
4947 			pg := uint32(s11g)
4948 			pb := uint32(s11b)
4949 			pa := uint32(s11a)
4950 			pa1 := (0xffff - pa) * 0x101
4951 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8)
4952 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8)
4953 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8)
4954 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8)
4955 		}
4956 	}
4957 }
4958 
4959 func (ablInterpolator) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
4960 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
4961 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
4962 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
4963 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
4964 			dxf := float64(dr.Min.X+int(dx)) + 0.5
4965 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
4966 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
4967 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
4968 				continue
4969 			}
4970 
4971 			sx -= 0.5
4972 			sx0 := int(sx)
4973 			xFrac0 := sx - float64(sx0)
4974 			xFrac1 := 1 - xFrac0
4975 			sx0 += bias.X
4976 			sx1 := sx0 + 1
4977 			if sx0 < sr.Min.X {
4978 				sx0, sx1 = sr.Min.X, sr.Min.X
4979 				xFrac0, xFrac1 = 0, 1
4980 			} else if sx1 >= sr.Max.X {
4981 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
4982 				xFrac0, xFrac1 = 1, 0
4983 			}
4984 
4985 			sy -= 0.5
4986 			sy0 := int(sy)
4987 			yFrac0 := sy - float64(sy0)
4988 			yFrac1 := 1 - yFrac0
4989 			sy0 += bias.Y
4990 			sy1 := sy0 + 1
4991 			if sy0 < sr.Min.Y {
4992 				sy0, sy1 = sr.Min.Y, sr.Min.Y
4993 				yFrac0, yFrac1 = 0, 1
4994 			} else if sy1 >= sr.Max.Y {
4995 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
4996 				yFrac0, yFrac1 = 1, 0
4997 			}
4998 
4999 			s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
5000 			s00r := float64(s00ru)
5001 			s00g := float64(s00gu)
5002 			s00b := float64(s00bu)
5003 			s00a := float64(s00au)
5004 			s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
5005 			s10r := float64(s10ru)
5006 			s10g := float64(s10gu)
5007 			s10b := float64(s10bu)
5008 			s10a := float64(s10au)
5009 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
5010 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
5011 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
5012 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
5013 			s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
5014 			s01r := float64(s01ru)
5015 			s01g := float64(s01gu)
5016 			s01b := float64(s01bu)
5017 			s01a := float64(s01au)
5018 			s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
5019 			s11r := float64(s11ru)
5020 			s11g := float64(s11gu)
5021 			s11b := float64(s11bu)
5022 			s11a := float64(s11au)
5023 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
5024 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
5025 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
5026 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
5027 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
5028 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
5029 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
5030 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
5031 			pr := uint32(s11r)
5032 			pg := uint32(s11g)
5033 			pb := uint32(s11b)
5034 			pa := uint32(s11a)
5035 			dst.Pix[d+0] = uint8(pr >> 8)
5036 			dst.Pix[d+1] = uint8(pg >> 8)
5037 			dst.Pix[d+2] = uint8(pb >> 8)
5038 			dst.Pix[d+3] = uint8(pa >> 8)
5039 		}
5040 	}
5041 }
5042 
5043 func (ablInterpolator) transform_RGBA64Image_RGBA64Image_Over(dst RGBA64Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
5044 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
5045 	dstMask, dmp := opts.DstMask, opts.DstMaskP
5046 	dstColorRGBA64 := color.RGBA64{}
5047 
5048 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
5049 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
5050 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
5051 			dxf := float64(dr.Min.X+int(dx)) + 0.5
5052 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
5053 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
5054 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
5055 				continue
5056 			}
5057 
5058 			sx -= 0.5
5059 			sx0 := int(sx)
5060 			xFrac0 := sx - float64(sx0)
5061 			xFrac1 := 1 - xFrac0
5062 			sx0 += bias.X
5063 			sx1 := sx0 + 1
5064 			if sx0 < sr.Min.X {
5065 				sx0, sx1 = sr.Min.X, sr.Min.X
5066 				xFrac0, xFrac1 = 0, 1
5067 			} else if sx1 >= sr.Max.X {
5068 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
5069 				xFrac0, xFrac1 = 1, 0
5070 			}
5071 
5072 			sy -= 0.5
5073 			sy0 := int(sy)
5074 			yFrac0 := sy - float64(sy0)
5075 			yFrac1 := 1 - yFrac0
5076 			sy0 += bias.Y
5077 			sy1 := sy0 + 1
5078 			if sy0 < sr.Min.Y {
5079 				sy0, sy1 = sr.Min.Y, sr.Min.Y
5080 				yFrac0, yFrac1 = 0, 1
5081 			} else if sy1 >= sr.Max.Y {
5082 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
5083 				yFrac0, yFrac1 = 1, 0
5084 			}
5085 
5086 			s00u := src.RGBA64At(sx0, sy0)
5087 			if srcMask != nil {
5088 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
5089 				s00u.R = uint16(uint32(s00u.R) * ma / 0xffff)
5090 				s00u.G = uint16(uint32(s00u.G) * ma / 0xffff)
5091 				s00u.B = uint16(uint32(s00u.B) * ma / 0xffff)
5092 				s00u.A = uint16(uint32(s00u.A) * ma / 0xffff)
5093 			}
5094 			s00r := float64(s00u.R)
5095 			s00g := float64(s00u.G)
5096 			s00b := float64(s00u.B)
5097 			s00a := float64(s00u.A)
5098 			s10u := src.RGBA64At(sx1, sy0)
5099 			if srcMask != nil {
5100 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
5101 				s10u.R = uint16(uint32(s10u.R) * ma / 0xffff)
5102 				s10u.G = uint16(uint32(s10u.G) * ma / 0xffff)
5103 				s10u.B = uint16(uint32(s10u.B) * ma / 0xffff)
5104 				s10u.A = uint16(uint32(s10u.A) * ma / 0xffff)
5105 			}
5106 			s10r := float64(s10u.R)
5107 			s10g := float64(s10u.G)
5108 			s10b := float64(s10u.B)
5109 			s10a := float64(s10u.A)
5110 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
5111 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
5112 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
5113 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
5114 			s01u := src.RGBA64At(sx0, sy1)
5115 			if srcMask != nil {
5116 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
5117 				s01u.R = uint16(uint32(s01u.R) * ma / 0xffff)
5118 				s01u.G = uint16(uint32(s01u.G) * ma / 0xffff)
5119 				s01u.B = uint16(uint32(s01u.B) * ma / 0xffff)
5120 				s01u.A = uint16(uint32(s01u.A) * ma / 0xffff)
5121 			}
5122 			s01r := float64(s01u.R)
5123 			s01g := float64(s01u.G)
5124 			s01b := float64(s01u.B)
5125 			s01a := float64(s01u.A)
5126 			s11u := src.RGBA64At(sx1, sy1)
5127 			if srcMask != nil {
5128 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
5129 				s11u.R = uint16(uint32(s11u.R) * ma / 0xffff)
5130 				s11u.G = uint16(uint32(s11u.G) * ma / 0xffff)
5131 				s11u.B = uint16(uint32(s11u.B) * ma / 0xffff)
5132 				s11u.A = uint16(uint32(s11u.A) * ma / 0xffff)
5133 			}
5134 			s11r := float64(s11u.R)
5135 			s11g := float64(s11u.G)
5136 			s11b := float64(s11u.B)
5137 			s11a := float64(s11u.A)
5138 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
5139 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
5140 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
5141 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
5142 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
5143 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
5144 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
5145 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
5146 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
5147 			q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
5148 			if dstMask != nil {
5149 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
5150 				p.R = uint16(uint32(p.R) * ma / 0xffff)
5151 				p.G = uint16(uint32(p.G) * ma / 0xffff)
5152 				p.B = uint16(uint32(p.B) * ma / 0xffff)
5153 				p.A = uint16(uint32(p.A) * ma / 0xffff)
5154 			}
5155 			pa1 := 0xffff - uint32(p.A)
5156 			dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
5157 			dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
5158 			dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
5159 			dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
5160 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
5161 		}
5162 	}
5163 }
5164 
5165 func (ablInterpolator) transform_RGBA64Image_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, opts *Options) {
5166 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
5167 	dstMask, dmp := opts.DstMask, opts.DstMaskP
5168 	dstColorRGBA64 := color.RGBA64{}
5169 
5170 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
5171 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
5172 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
5173 			dxf := float64(dr.Min.X+int(dx)) + 0.5
5174 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
5175 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
5176 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
5177 				continue
5178 			}
5179 
5180 			sx -= 0.5
5181 			sx0 := int(sx)
5182 			xFrac0 := sx - float64(sx0)
5183 			xFrac1 := 1 - xFrac0
5184 			sx0 += bias.X
5185 			sx1 := sx0 + 1
5186 			if sx0 < sr.Min.X {
5187 				sx0, sx1 = sr.Min.X, sr.Min.X
5188 				xFrac0, xFrac1 = 0, 1
5189 			} else if sx1 >= sr.Max.X {
5190 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
5191 				xFrac0, xFrac1 = 1, 0
5192 			}
5193 
5194 			sy -= 0.5
5195 			sy0 := int(sy)
5196 			yFrac0 := sy - float64(sy0)
5197 			yFrac1 := 1 - yFrac0
5198 			sy0 += bias.Y
5199 			sy1 := sy0 + 1
5200 			if sy0 < sr.Min.Y {
5201 				sy0, sy1 = sr.Min.Y, sr.Min.Y
5202 				yFrac0, yFrac1 = 0, 1
5203 			} else if sy1 >= sr.Max.Y {
5204 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
5205 				yFrac0, yFrac1 = 1, 0
5206 			}
5207 
5208 			s00u := src.RGBA64At(sx0, sy0)
5209 			if srcMask != nil {
5210 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
5211 				s00u.R = uint16(uint32(s00u.R) * ma / 0xffff)
5212 				s00u.G = uint16(uint32(s00u.G) * ma / 0xffff)
5213 				s00u.B = uint16(uint32(s00u.B) * ma / 0xffff)
5214 				s00u.A = uint16(uint32(s00u.A) * ma / 0xffff)
5215 			}
5216 			s00r := float64(s00u.R)
5217 			s00g := float64(s00u.G)
5218 			s00b := float64(s00u.B)
5219 			s00a := float64(s00u.A)
5220 			s10u := src.RGBA64At(sx1, sy0)
5221 			if srcMask != nil {
5222 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
5223 				s10u.R = uint16(uint32(s10u.R) * ma / 0xffff)
5224 				s10u.G = uint16(uint32(s10u.G) * ma / 0xffff)
5225 				s10u.B = uint16(uint32(s10u.B) * ma / 0xffff)
5226 				s10u.A = uint16(uint32(s10u.A) * ma / 0xffff)
5227 			}
5228 			s10r := float64(s10u.R)
5229 			s10g := float64(s10u.G)
5230 			s10b := float64(s10u.B)
5231 			s10a := float64(s10u.A)
5232 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
5233 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
5234 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
5235 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
5236 			s01u := src.RGBA64At(sx0, sy1)
5237 			if srcMask != nil {
5238 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
5239 				s01u.R = uint16(uint32(s01u.R) * ma / 0xffff)
5240 				s01u.G = uint16(uint32(s01u.G) * ma / 0xffff)
5241 				s01u.B = uint16(uint32(s01u.B) * ma / 0xffff)
5242 				s01u.A = uint16(uint32(s01u.A) * ma / 0xffff)
5243 			}
5244 			s01r := float64(s01u.R)
5245 			s01g := float64(s01u.G)
5246 			s01b := float64(s01u.B)
5247 			s01a := float64(s01u.A)
5248 			s11u := src.RGBA64At(sx1, sy1)
5249 			if srcMask != nil {
5250 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
5251 				s11u.R = uint16(uint32(s11u.R) * ma / 0xffff)
5252 				s11u.G = uint16(uint32(s11u.G) * ma / 0xffff)
5253 				s11u.B = uint16(uint32(s11u.B) * ma / 0xffff)
5254 				s11u.A = uint16(uint32(s11u.A) * ma / 0xffff)
5255 			}
5256 			s11r := float64(s11u.R)
5257 			s11g := float64(s11u.G)
5258 			s11b := float64(s11u.B)
5259 			s11a := float64(s11u.A)
5260 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
5261 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
5262 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
5263 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
5264 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
5265 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
5266 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
5267 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
5268 			p := color.RGBA64{uint16(s11r), uint16(s11g), uint16(s11b), uint16(s11a)}
5269 			if dstMask != nil {
5270 				q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
5271 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
5272 				p.R = uint16(uint32(p.R) * ma / 0xffff)
5273 				p.G = uint16(uint32(p.G) * ma / 0xffff)
5274 				p.B = uint16(uint32(p.B) * ma / 0xffff)
5275 				p.A = uint16(uint32(p.A) * ma / 0xffff)
5276 				pa1 := 0xffff - ma
5277 				dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + uint32(p.R))
5278 				dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + uint32(p.G))
5279 				dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + uint32(p.B))
5280 				dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + uint32(p.A))
5281 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
5282 			} else {
5283 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), p)
5284 			}
5285 		}
5286 	}
5287 }
5288 
5289 func (ablInterpolator) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
5290 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
5291 	dstMask, dmp := opts.DstMask, opts.DstMaskP
5292 	dstColorRGBA64 := &color.RGBA64{}
5293 	dstColor := color.Color(dstColorRGBA64)
5294 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
5295 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
5296 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
5297 			dxf := float64(dr.Min.X+int(dx)) + 0.5
5298 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
5299 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
5300 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
5301 				continue
5302 			}
5303 
5304 			sx -= 0.5
5305 			sx0 := int(sx)
5306 			xFrac0 := sx - float64(sx0)
5307 			xFrac1 := 1 - xFrac0
5308 			sx0 += bias.X
5309 			sx1 := sx0 + 1
5310 			if sx0 < sr.Min.X {
5311 				sx0, sx1 = sr.Min.X, sr.Min.X
5312 				xFrac0, xFrac1 = 0, 1
5313 			} else if sx1 >= sr.Max.X {
5314 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
5315 				xFrac0, xFrac1 = 1, 0
5316 			}
5317 
5318 			sy -= 0.5
5319 			sy0 := int(sy)
5320 			yFrac0 := sy - float64(sy0)
5321 			yFrac1 := 1 - yFrac0
5322 			sy0 += bias.Y
5323 			sy1 := sy0 + 1
5324 			if sy0 < sr.Min.Y {
5325 				sy0, sy1 = sr.Min.Y, sr.Min.Y
5326 				yFrac0, yFrac1 = 0, 1
5327 			} else if sy1 >= sr.Max.Y {
5328 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
5329 				yFrac0, yFrac1 = 1, 0
5330 			}
5331 
5332 			s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
5333 			if srcMask != nil {
5334 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
5335 				s00ru = s00ru * ma / 0xffff
5336 				s00gu = s00gu * ma / 0xffff
5337 				s00bu = s00bu * ma / 0xffff
5338 				s00au = s00au * ma / 0xffff
5339 			}
5340 			s00r := float64(s00ru)
5341 			s00g := float64(s00gu)
5342 			s00b := float64(s00bu)
5343 			s00a := float64(s00au)
5344 			s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
5345 			if srcMask != nil {
5346 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
5347 				s10ru = s10ru * ma / 0xffff
5348 				s10gu = s10gu * ma / 0xffff
5349 				s10bu = s10bu * ma / 0xffff
5350 				s10au = s10au * ma / 0xffff
5351 			}
5352 			s10r := float64(s10ru)
5353 			s10g := float64(s10gu)
5354 			s10b := float64(s10bu)
5355 			s10a := float64(s10au)
5356 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
5357 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
5358 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
5359 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
5360 			s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
5361 			if srcMask != nil {
5362 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
5363 				s01ru = s01ru * ma / 0xffff
5364 				s01gu = s01gu * ma / 0xffff
5365 				s01bu = s01bu * ma / 0xffff
5366 				s01au = s01au * ma / 0xffff
5367 			}
5368 			s01r := float64(s01ru)
5369 			s01g := float64(s01gu)
5370 			s01b := float64(s01bu)
5371 			s01a := float64(s01au)
5372 			s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
5373 			if srcMask != nil {
5374 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
5375 				s11ru = s11ru * ma / 0xffff
5376 				s11gu = s11gu * ma / 0xffff
5377 				s11bu = s11bu * ma / 0xffff
5378 				s11au = s11au * ma / 0xffff
5379 			}
5380 			s11r := float64(s11ru)
5381 			s11g := float64(s11gu)
5382 			s11b := float64(s11bu)
5383 			s11a := float64(s11au)
5384 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
5385 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
5386 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
5387 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
5388 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
5389 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
5390 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
5391 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
5392 			pr := uint32(s11r)
5393 			pg := uint32(s11g)
5394 			pb := uint32(s11b)
5395 			pa := uint32(s11a)
5396 			qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
5397 			if dstMask != nil {
5398 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
5399 				pr = pr * ma / 0xffff
5400 				pg = pg * ma / 0xffff
5401 				pb = pb * ma / 0xffff
5402 				pa = pa * ma / 0xffff
5403 			}
5404 			pa1 := 0xffff - pa
5405 			dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
5406 			dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
5407 			dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
5408 			dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
5409 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
5410 		}
5411 	}
5412 }
5413 
5414 func (ablInterpolator) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, opts *Options) {
5415 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
5416 	dstMask, dmp := opts.DstMask, opts.DstMaskP
5417 	dstColorRGBA64 := &color.RGBA64{}
5418 	dstColor := color.Color(dstColorRGBA64)
5419 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
5420 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
5421 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
5422 			dxf := float64(dr.Min.X+int(dx)) + 0.5
5423 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
5424 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
5425 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
5426 				continue
5427 			}
5428 
5429 			sx -= 0.5
5430 			sx0 := int(sx)
5431 			xFrac0 := sx - float64(sx0)
5432 			xFrac1 := 1 - xFrac0
5433 			sx0 += bias.X
5434 			sx1 := sx0 + 1
5435 			if sx0 < sr.Min.X {
5436 				sx0, sx1 = sr.Min.X, sr.Min.X
5437 				xFrac0, xFrac1 = 0, 1
5438 			} else if sx1 >= sr.Max.X {
5439 				sx0, sx1 = sr.Max.X-1, sr.Max.X-1
5440 				xFrac0, xFrac1 = 1, 0
5441 			}
5442 
5443 			sy -= 0.5
5444 			sy0 := int(sy)
5445 			yFrac0 := sy - float64(sy0)
5446 			yFrac1 := 1 - yFrac0
5447 			sy0 += bias.Y
5448 			sy1 := sy0 + 1
5449 			if sy0 < sr.Min.Y {
5450 				sy0, sy1 = sr.Min.Y, sr.Min.Y
5451 				yFrac0, yFrac1 = 0, 1
5452 			} else if sy1 >= sr.Max.Y {
5453 				sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1
5454 				yFrac0, yFrac1 = 1, 0
5455 			}
5456 
5457 			s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA()
5458 			if srcMask != nil {
5459 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA()
5460 				s00ru = s00ru * ma / 0xffff
5461 				s00gu = s00gu * ma / 0xffff
5462 				s00bu = s00bu * ma / 0xffff
5463 				s00au = s00au * ma / 0xffff
5464 			}
5465 			s00r := float64(s00ru)
5466 			s00g := float64(s00gu)
5467 			s00b := float64(s00bu)
5468 			s00a := float64(s00au)
5469 			s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA()
5470 			if srcMask != nil {
5471 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA()
5472 				s10ru = s10ru * ma / 0xffff
5473 				s10gu = s10gu * ma / 0xffff
5474 				s10bu = s10bu * ma / 0xffff
5475 				s10au = s10au * ma / 0xffff
5476 			}
5477 			s10r := float64(s10ru)
5478 			s10g := float64(s10gu)
5479 			s10b := float64(s10bu)
5480 			s10a := float64(s10au)
5481 			s10r = float64(xFrac1*s00r) + float64(xFrac0*s10r)
5482 			s10g = float64(xFrac1*s00g) + float64(xFrac0*s10g)
5483 			s10b = float64(xFrac1*s00b) + float64(xFrac0*s10b)
5484 			s10a = float64(xFrac1*s00a) + float64(xFrac0*s10a)
5485 			s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA()
5486 			if srcMask != nil {
5487 				_, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA()
5488 				s01ru = s01ru * ma / 0xffff
5489 				s01gu = s01gu * ma / 0xffff
5490 				s01bu = s01bu * ma / 0xffff
5491 				s01au = s01au * ma / 0xffff
5492 			}
5493 			s01r := float64(s01ru)
5494 			s01g := float64(s01gu)
5495 			s01b := float64(s01bu)
5496 			s01a := float64(s01au)
5497 			s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA()
5498 			if srcMask != nil {
5499 				_, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA()
5500 				s11ru = s11ru * ma / 0xffff
5501 				s11gu = s11gu * ma / 0xffff
5502 				s11bu = s11bu * ma / 0xffff
5503 				s11au = s11au * ma / 0xffff
5504 			}
5505 			s11r := float64(s11ru)
5506 			s11g := float64(s11gu)
5507 			s11b := float64(s11bu)
5508 			s11a := float64(s11au)
5509 			s11r = float64(xFrac1*s01r) + float64(xFrac0*s11r)
5510 			s11g = float64(xFrac1*s01g) + float64(xFrac0*s11g)
5511 			s11b = float64(xFrac1*s01b) + float64(xFrac0*s11b)
5512 			s11a = float64(xFrac1*s01a) + float64(xFrac0*s11a)
5513 			s11r = float64(yFrac1*s10r) + float64(yFrac0*s11r)
5514 			s11g = float64(yFrac1*s10g) + float64(yFrac0*s11g)
5515 			s11b = float64(yFrac1*s10b) + float64(yFrac0*s11b)
5516 			s11a = float64(yFrac1*s10a) + float64(yFrac0*s11a)
5517 			pr := uint32(s11r)
5518 			pg := uint32(s11g)
5519 			pb := uint32(s11b)
5520 			pa := uint32(s11a)
5521 			if dstMask != nil {
5522 				qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
5523 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
5524 				pr = pr * ma / 0xffff
5525 				pg = pg * ma / 0xffff
5526 				pb = pb * ma / 0xffff
5527 				pa = pa * ma / 0xffff
5528 				pa1 := 0xffff - ma
5529 				dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
5530 				dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
5531 				dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
5532 				dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
5533 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
5534 			} else {
5535 				dstColorRGBA64.R = uint16(pr)
5536 				dstColorRGBA64.G = uint16(pg)
5537 				dstColorRGBA64.B = uint16(pb)
5538 				dstColorRGBA64.A = uint16(pa)
5539 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
5540 			}
5541 		}
5542 	}
5543 }
5544 
5545 func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) {
5546 	if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) {
5547 		z.kernel.Scale(dst, dr, src, sr, op, opts)
5548 		return
5549 	}
5550 
5551 	var o Options
5552 	if opts != nil {
5553 		o = *opts
5554 	}
5555 
5556 	// adr is the affected destination pixels.
5557 	adr := dst.Bounds().Intersect(dr)
5558 	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
5559 	if adr.Empty() || sr.Empty() {
5560 		return
5561 	}
5562 	// Make adr relative to dr.Min.
5563 	adr = adr.Sub(dr.Min)
5564 	if op == Over && o.SrcMask == nil && opaque(src) {
5565 		op = Src
5566 	}
5567 
5568 	if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) {
5569 		Draw(dst, dr, src, src.Bounds().Min, op)
5570 		return
5571 	}
5572 
5573 	// Create a temporary buffer:
5574 	// scaleX distributes the source image's columns over the temporary image.
5575 	// scaleY distributes the temporary image's rows over the destination image.
5576 	var tmp [][4]float64
5577 	if z.pool.New != nil {
5578 		tmpp := z.pool.Get().(*[][4]float64)
5579 		defer z.pool.Put(tmpp)
5580 		tmp = *tmpp
5581 	} else {
5582 		tmp = z.makeTmpBuf()
5583 	}
5584 
5585 	// sr is the source pixels. If it extends beyond the src bounds,
5586 	// we cannot use the type-specific fast paths, as they access
5587 	// the Pix fields directly without bounds checking.
5588 	//
5589 	// Similarly, the fast paths assume that the masks are nil.
5590 	if o.SrcMask != nil || !sr.In(src.Bounds()) {
5591 		z.scaleX_Image(tmp, src, sr, &o)
5592 	} else {
5593 		switch src := src.(type) {
5594 		case *image.Gray:
5595 			z.scaleX_Gray(tmp, src, sr, &o)
5596 		case *image.NRGBA:
5597 			z.scaleX_NRGBA(tmp, src, sr, &o)
5598 		case *image.RGBA:
5599 			z.scaleX_RGBA(tmp, src, sr, &o)
5600 		case *image.YCbCr:
5601 			switch src.SubsampleRatio {
5602 			default:
5603 				z.scaleX_Image(tmp, src, sr, &o)
5604 			case image.YCbCrSubsampleRatio444:
5605 				z.scaleX_YCbCr444(tmp, src, sr, &o)
5606 			case image.YCbCrSubsampleRatio422:
5607 				z.scaleX_YCbCr422(tmp, src, sr, &o)
5608 			case image.YCbCrSubsampleRatio420:
5609 				z.scaleX_YCbCr420(tmp, src, sr, &o)
5610 			case image.YCbCrSubsampleRatio440:
5611 				z.scaleX_YCbCr440(tmp, src, sr, &o)
5612 			}
5613 		case image.RGBA64Image:
5614 			z.scaleX_RGBA64Image(tmp, src, sr, &o)
5615 		default:
5616 			z.scaleX_Image(tmp, src, sr, &o)
5617 		}
5618 	}
5619 
5620 	if o.DstMask != nil {
5621 		switch op {
5622 		case Over:
5623 			z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
5624 		case Src:
5625 			z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
5626 		}
5627 	} else {
5628 		switch op {
5629 		case Over:
5630 			switch dst := dst.(type) {
5631 			case *image.RGBA:
5632 				z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o)
5633 			case RGBA64Image:
5634 				z.scaleY_RGBA64Image_Over(dst, dr, adr, tmp, &o)
5635 			default:
5636 				z.scaleY_Image_Over(dst, dr, adr, tmp, &o)
5637 			}
5638 		case Src:
5639 			switch dst := dst.(type) {
5640 			case *image.RGBA:
5641 				z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o)
5642 			case RGBA64Image:
5643 				z.scaleY_RGBA64Image_Src(dst, dr, adr, tmp, &o)
5644 			default:
5645 				z.scaleY_Image_Src(dst, dr, adr, tmp, &o)
5646 			}
5647 		}
5648 	}
5649 }
5650 
5651 func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) {
5652 	var o Options
5653 	if opts != nil {
5654 		o = *opts
5655 	}
5656 
5657 	dr := transformRect(&s2d, &sr)
5658 	// adr is the affected destination pixels.
5659 	adr := dst.Bounds().Intersect(dr)
5660 	adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP)
5661 	if adr.Empty() || sr.Empty() {
5662 		return
5663 	}
5664 	if op == Over && o.SrcMask == nil && opaque(src) {
5665 		op = Src
5666 	}
5667 	d2s := invert(&s2d)
5668 	// bias is a translation of the mapping from dst coordinates to src
5669 	// coordinates such that the latter temporarily have non-negative X
5670 	// and Y coordinates. This allows us to write int(f) instead of
5671 	// int(math.Floor(f)), since "round to zero" and "round down" are
5672 	// equivalent when f >= 0, but the former is much cheaper. The X--
5673 	// and Y-- are because the TransformLeaf methods have a "sx -= 0.5"
5674 	// adjustment.
5675 	bias := transformRect(&d2s, &adr).Min
5676 	bias.X--
5677 	bias.Y--
5678 	d2s[2] -= float64(bias.X)
5679 	d2s[5] -= float64(bias.Y)
5680 	// Make adr relative to dr.Min.
5681 	adr = adr.Sub(dr.Min)
5682 
5683 	if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) {
5684 		transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op)
5685 		return
5686 	}
5687 
5688 	xscale := abs(d2s[0])
5689 	if s := abs(d2s[1]); xscale < s {
5690 		xscale = s
5691 	}
5692 	yscale := abs(d2s[3])
5693 	if s := abs(d2s[4]); yscale < s {
5694 		yscale = s
5695 	}
5696 
5697 	// sr is the source pixels. If it extends beyond the src bounds,
5698 	// we cannot use the type-specific fast paths, as they access
5699 	// the Pix fields directly without bounds checking.
5700 	//
5701 	// Similarly, the fast paths assume that the masks are nil.
5702 	if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) {
5703 		switch op {
5704 		case Over:
5705 			q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5706 		case Src:
5707 			q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5708 		}
5709 	} else {
5710 		switch op {
5711 		case Over:
5712 			switch dst := dst.(type) {
5713 			case *image.RGBA:
5714 				switch src := src.(type) {
5715 				case *image.NRGBA:
5716 					q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5717 				case *image.RGBA:
5718 					q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5719 				case image.RGBA64Image:
5720 					q.transform_RGBA_RGBA64Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5721 				default:
5722 					q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5723 				}
5724 			case RGBA64Image:
5725 				switch src := src.(type) {
5726 				case image.RGBA64Image:
5727 					q.transform_RGBA64Image_RGBA64Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5728 				}
5729 			default:
5730 				switch src := src.(type) {
5731 				default:
5732 					q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5733 				}
5734 			}
5735 		case Src:
5736 			switch dst := dst.(type) {
5737 			case *image.RGBA:
5738 				switch src := src.(type) {
5739 				case *image.Gray:
5740 					q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5741 				case *image.NRGBA:
5742 					q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5743 				case *image.RGBA:
5744 					q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5745 				case *image.YCbCr:
5746 					switch src.SubsampleRatio {
5747 					default:
5748 						q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5749 					case image.YCbCrSubsampleRatio444:
5750 						q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5751 					case image.YCbCrSubsampleRatio422:
5752 						q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5753 					case image.YCbCrSubsampleRatio420:
5754 						q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5755 					case image.YCbCrSubsampleRatio440:
5756 						q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5757 					}
5758 				case image.RGBA64Image:
5759 					q.transform_RGBA_RGBA64Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5760 				default:
5761 					q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5762 				}
5763 			case RGBA64Image:
5764 				switch src := src.(type) {
5765 				case image.RGBA64Image:
5766 					q.transform_RGBA64Image_RGBA64Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5767 				}
5768 			default:
5769 				switch src := src.(type) {
5770 				default:
5771 					q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o)
5772 				}
5773 			}
5774 		}
5775 	}
5776 }
5777 
5778 func (z *kernelScaler) scaleX_Gray(tmp [][4]float64, src *image.Gray, sr image.Rectangle, opts *Options) {
5779 	t := 0
5780 	for y := int32(0); y < z.sh; y++ {
5781 		for _, s := range z.horizontal.sources {
5782 			var pr float64
5783 			for _, c := range z.horizontal.contribs[s.i:s.j] {
5784 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
5785 				pru := uint32(src.Pix[pi]) * 0x101
5786 				pr += float64(float64(pru) * c.weight)
5787 			}
5788 			pr *= s.invTotalWeightFFFF
5789 			tmp[t] = [4]float64{
5790 				pr,
5791 				pr,
5792 				pr,
5793 				1,
5794 			}
5795 			t++
5796 		}
5797 	}
5798 }
5799 
5800 func (z *kernelScaler) scaleX_NRGBA(tmp [][4]float64, src *image.NRGBA, sr image.Rectangle, opts *Options) {
5801 	t := 0
5802 	for y := int32(0); y < z.sh; y++ {
5803 		for _, s := range z.horizontal.sources {
5804 			var pr, pg, pb, pa float64
5805 			for _, c := range z.horizontal.contribs[s.i:s.j] {
5806 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
5807 				pau := uint32(src.Pix[pi+3]) * 0x101
5808 				pru := uint32(src.Pix[pi+0]) * pau / 0xff
5809 				pgu := uint32(src.Pix[pi+1]) * pau / 0xff
5810 				pbu := uint32(src.Pix[pi+2]) * pau / 0xff
5811 				pr += float64(float64(pru) * c.weight)
5812 				pg += float64(float64(pgu) * c.weight)
5813 				pb += float64(float64(pbu) * c.weight)
5814 				pa += float64(float64(pau) * c.weight)
5815 			}
5816 			tmp[t] = [4]float64{
5817 				pr * s.invTotalWeightFFFF,
5818 				pg * s.invTotalWeightFFFF,
5819 				pb * s.invTotalWeightFFFF,
5820 				pa * s.invTotalWeightFFFF,
5821 			}
5822 			t++
5823 		}
5824 	}
5825 }
5826 
5827 func (z *kernelScaler) scaleX_RGBA(tmp [][4]float64, src *image.RGBA, sr image.Rectangle, opts *Options) {
5828 	t := 0
5829 	for y := int32(0); y < z.sh; y++ {
5830 		for _, s := range z.horizontal.sources {
5831 			var pr, pg, pb, pa float64
5832 			for _, c := range z.horizontal.contribs[s.i:s.j] {
5833 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4
5834 				pru := uint32(src.Pix[pi+0]) * 0x101
5835 				pgu := uint32(src.Pix[pi+1]) * 0x101
5836 				pbu := uint32(src.Pix[pi+2]) * 0x101
5837 				pau := uint32(src.Pix[pi+3]) * 0x101
5838 				pr += float64(float64(pru) * c.weight)
5839 				pg += float64(float64(pgu) * c.weight)
5840 				pb += float64(float64(pbu) * c.weight)
5841 				pa += float64(float64(pau) * c.weight)
5842 			}
5843 			tmp[t] = [4]float64{
5844 				pr * s.invTotalWeightFFFF,
5845 				pg * s.invTotalWeightFFFF,
5846 				pb * s.invTotalWeightFFFF,
5847 				pa * s.invTotalWeightFFFF,
5848 			}
5849 			t++
5850 		}
5851 	}
5852 }
5853 
5854 func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
5855 	t := 0
5856 	for y := int32(0); y < z.sh; y++ {
5857 		for _, s := range z.horizontal.sources {
5858 			var pr, pg, pb float64
5859 			for _, c := range z.horizontal.contribs[s.i:s.j] {
5860 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
5861 				pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
5862 
5863 				// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
5864 				pyy1 := int(src.Y[pi]) * 0x10101
5865 				pcb1 := int(src.Cb[pj]) - 128
5866 				pcr1 := int(src.Cr[pj]) - 128
5867 				pru := (pyy1 + 91881*pcr1) >> 8
5868 				pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
5869 				pbu := (pyy1 + 116130*pcb1) >> 8
5870 				if pru < 0 {
5871 					pru = 0
5872 				} else if pru > 0xffff {
5873 					pru = 0xffff
5874 				}
5875 				if pgu < 0 {
5876 					pgu = 0
5877 				} else if pgu > 0xffff {
5878 					pgu = 0xffff
5879 				}
5880 				if pbu < 0 {
5881 					pbu = 0
5882 				} else if pbu > 0xffff {
5883 					pbu = 0xffff
5884 				}
5885 
5886 				pr += float64(float64(pru) * c.weight)
5887 				pg += float64(float64(pgu) * c.weight)
5888 				pb += float64(float64(pbu) * c.weight)
5889 			}
5890 			tmp[t] = [4]float64{
5891 				pr * s.invTotalWeightFFFF,
5892 				pg * s.invTotalWeightFFFF,
5893 				pb * s.invTotalWeightFFFF,
5894 				1,
5895 			}
5896 			t++
5897 		}
5898 	}
5899 }
5900 
5901 func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
5902 	t := 0
5903 	for y := int32(0); y < z.sh; y++ {
5904 		for _, s := range z.horizontal.sources {
5905 			var pr, pg, pb float64
5906 			for _, c := range z.horizontal.contribs[s.i:s.j] {
5907 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
5908 				pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
5909 
5910 				// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
5911 				pyy1 := int(src.Y[pi]) * 0x10101
5912 				pcb1 := int(src.Cb[pj]) - 128
5913 				pcr1 := int(src.Cr[pj]) - 128
5914 				pru := (pyy1 + 91881*pcr1) >> 8
5915 				pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
5916 				pbu := (pyy1 + 116130*pcb1) >> 8
5917 				if pru < 0 {
5918 					pru = 0
5919 				} else if pru > 0xffff {
5920 					pru = 0xffff
5921 				}
5922 				if pgu < 0 {
5923 					pgu = 0
5924 				} else if pgu > 0xffff {
5925 					pgu = 0xffff
5926 				}
5927 				if pbu < 0 {
5928 					pbu = 0
5929 				} else if pbu > 0xffff {
5930 					pbu = 0xffff
5931 				}
5932 
5933 				pr += float64(float64(pru) * c.weight)
5934 				pg += float64(float64(pgu) * c.weight)
5935 				pb += float64(float64(pbu) * c.weight)
5936 			}
5937 			tmp[t] = [4]float64{
5938 				pr * s.invTotalWeightFFFF,
5939 				pg * s.invTotalWeightFFFF,
5940 				pb * s.invTotalWeightFFFF,
5941 				1,
5942 			}
5943 			t++
5944 		}
5945 	}
5946 }
5947 
5948 func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
5949 	t := 0
5950 	for y := int32(0); y < z.sh; y++ {
5951 		for _, s := range z.horizontal.sources {
5952 			var pr, pg, pb float64
5953 			for _, c := range z.horizontal.contribs[s.i:s.j] {
5954 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
5955 				pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2)
5956 
5957 				// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
5958 				pyy1 := int(src.Y[pi]) * 0x10101
5959 				pcb1 := int(src.Cb[pj]) - 128
5960 				pcr1 := int(src.Cr[pj]) - 128
5961 				pru := (pyy1 + 91881*pcr1) >> 8
5962 				pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
5963 				pbu := (pyy1 + 116130*pcb1) >> 8
5964 				if pru < 0 {
5965 					pru = 0
5966 				} else if pru > 0xffff {
5967 					pru = 0xffff
5968 				}
5969 				if pgu < 0 {
5970 					pgu = 0
5971 				} else if pgu > 0xffff {
5972 					pgu = 0xffff
5973 				}
5974 				if pbu < 0 {
5975 					pbu = 0
5976 				} else if pbu > 0xffff {
5977 					pbu = 0xffff
5978 				}
5979 
5980 				pr += float64(float64(pru) * c.weight)
5981 				pg += float64(float64(pgu) * c.weight)
5982 				pb += float64(float64(pbu) * c.weight)
5983 			}
5984 			tmp[t] = [4]float64{
5985 				pr * s.invTotalWeightFFFF,
5986 				pg * s.invTotalWeightFFFF,
5987 				pb * s.invTotalWeightFFFF,
5988 				1,
5989 			}
5990 			t++
5991 		}
5992 	}
5993 }
5994 
5995 func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) {
5996 	t := 0
5997 	for y := int32(0); y < z.sh; y++ {
5998 		for _, s := range z.horizontal.sources {
5999 			var pr, pg, pb float64
6000 			for _, c := range z.horizontal.contribs[s.i:s.j] {
6001 				pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
6002 				pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X)
6003 
6004 				// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
6005 				pyy1 := int(src.Y[pi]) * 0x10101
6006 				pcb1 := int(src.Cb[pj]) - 128
6007 				pcr1 := int(src.Cr[pj]) - 128
6008 				pru := (pyy1 + 91881*pcr1) >> 8
6009 				pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
6010 				pbu := (pyy1 + 116130*pcb1) >> 8
6011 				if pru < 0 {
6012 					pru = 0
6013 				} else if pru > 0xffff {
6014 					pru = 0xffff
6015 				}
6016 				if pgu < 0 {
6017 					pgu = 0
6018 				} else if pgu > 0xffff {
6019 					pgu = 0xffff
6020 				}
6021 				if pbu < 0 {
6022 					pbu = 0
6023 				} else if pbu > 0xffff {
6024 					pbu = 0xffff
6025 				}
6026 
6027 				pr += float64(float64(pru) * c.weight)
6028 				pg += float64(float64(pgu) * c.weight)
6029 				pb += float64(float64(pbu) * c.weight)
6030 			}
6031 			tmp[t] = [4]float64{
6032 				pr * s.invTotalWeightFFFF,
6033 				pg * s.invTotalWeightFFFF,
6034 				pb * s.invTotalWeightFFFF,
6035 				1,
6036 			}
6037 			t++
6038 		}
6039 	}
6040 }
6041 
6042 func (z *kernelScaler) scaleX_RGBA64Image(tmp [][4]float64, src image.RGBA64Image, sr image.Rectangle, opts *Options) {
6043 	t := 0
6044 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
6045 	for y := int32(0); y < z.sh; y++ {
6046 		for _, s := range z.horizontal.sources {
6047 			var pr, pg, pb, pa float64
6048 			for _, c := range z.horizontal.contribs[s.i:s.j] {
6049 				pu := src.RGBA64At(sr.Min.X+int(c.coord), sr.Min.Y+int(y))
6050 				if srcMask != nil {
6051 					_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(c.coord), smp.Y+sr.Min.Y+int(y)).RGBA()
6052 					pu.R = uint16(uint32(pu.R) * ma / 0xffff)
6053 					pu.G = uint16(uint32(pu.G) * ma / 0xffff)
6054 					pu.B = uint16(uint32(pu.B) * ma / 0xffff)
6055 					pu.A = uint16(uint32(pu.A) * ma / 0xffff)
6056 				}
6057 				pr += float64(float64(pu.R) * c.weight)
6058 				pg += float64(float64(pu.G) * c.weight)
6059 				pb += float64(float64(pu.B) * c.weight)
6060 				pa += float64(float64(pu.A) * c.weight)
6061 			}
6062 			tmp[t] = [4]float64{
6063 				pr * s.invTotalWeightFFFF,
6064 				pg * s.invTotalWeightFFFF,
6065 				pb * s.invTotalWeightFFFF,
6066 				pa * s.invTotalWeightFFFF,
6067 			}
6068 			t++
6069 		}
6070 	}
6071 }
6072 
6073 func (z *kernelScaler) scaleX_Image(tmp [][4]float64, src image.Image, sr image.Rectangle, opts *Options) {
6074 	t := 0
6075 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
6076 	for y := int32(0); y < z.sh; y++ {
6077 		for _, s := range z.horizontal.sources {
6078 			var pr, pg, pb, pa float64
6079 			for _, c := range z.horizontal.contribs[s.i:s.j] {
6080 				pru, pgu, pbu, pau := src.At(sr.Min.X+int(c.coord), sr.Min.Y+int(y)).RGBA()
6081 				if srcMask != nil {
6082 					_, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(c.coord), smp.Y+sr.Min.Y+int(y)).RGBA()
6083 					pru = pru * ma / 0xffff
6084 					pgu = pgu * ma / 0xffff
6085 					pbu = pbu * ma / 0xffff
6086 					pau = pau * ma / 0xffff
6087 				}
6088 				pr += float64(float64(pru) * c.weight)
6089 				pg += float64(float64(pgu) * c.weight)
6090 				pb += float64(float64(pbu) * c.weight)
6091 				pa += float64(float64(pau) * c.weight)
6092 			}
6093 			tmp[t] = [4]float64{
6094 				pr * s.invTotalWeightFFFF,
6095 				pg * s.invTotalWeightFFFF,
6096 				pb * s.invTotalWeightFFFF,
6097 				pa * s.invTotalWeightFFFF,
6098 			}
6099 			t++
6100 		}
6101 	}
6102 }
6103 
6104 func (z *kernelScaler) scaleY_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
6105 	for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
6106 		d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
6107 		for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
6108 			var pr, pg, pb, pa float64
6109 			for _, c := range z.vertical.contribs[s.i:s.j] {
6110 				p := &tmp[c.coord*z.dw+dx]
6111 				pr += float64(p[0] * c.weight)
6112 				pg += float64(p[1] * c.weight)
6113 				pb += float64(p[2] * c.weight)
6114 				pa += float64(p[3] * c.weight)
6115 			}
6116 
6117 			if pr > pa {
6118 				pr = pa
6119 			}
6120 			if pg > pa {
6121 				pg = pa
6122 			}
6123 			if pb > pa {
6124 				pb = pa
6125 			}
6126 
6127 			pr0 := uint32(ftou(pr * s.invTotalWeight))
6128 			pg0 := uint32(ftou(pg * s.invTotalWeight))
6129 			pb0 := uint32(ftou(pb * s.invTotalWeight))
6130 			pa0 := uint32(ftou(pa * s.invTotalWeight))
6131 			pa1 := (0xffff - uint32(pa0)) * 0x101
6132 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
6133 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
6134 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
6135 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
6136 			d += dst.Stride
6137 		}
6138 	}
6139 }
6140 
6141 func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
6142 	for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
6143 		d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4
6144 		for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
6145 			var pr, pg, pb, pa float64
6146 			for _, c := range z.vertical.contribs[s.i:s.j] {
6147 				p := &tmp[c.coord*z.dw+dx]
6148 				pr += float64(p[0] * c.weight)
6149 				pg += float64(p[1] * c.weight)
6150 				pb += float64(p[2] * c.weight)
6151 				pa += float64(p[3] * c.weight)
6152 			}
6153 
6154 			if pr > pa {
6155 				pr = pa
6156 			}
6157 			if pg > pa {
6158 				pg = pa
6159 			}
6160 			if pb > pa {
6161 				pb = pa
6162 			}
6163 
6164 			dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8)
6165 			dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8)
6166 			dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8)
6167 			dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8)
6168 			d += dst.Stride
6169 		}
6170 	}
6171 }
6172 
6173 func (z *kernelScaler) scaleY_RGBA64Image_Over(dst RGBA64Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
6174 	dstMask, dmp := opts.DstMask, opts.DstMaskP
6175 	dstColorRGBA64 := color.RGBA64{}
6176 
6177 	for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
6178 		for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
6179 			var pr, pg, pb, pa float64
6180 			for _, c := range z.vertical.contribs[s.i:s.j] {
6181 				p := &tmp[c.coord*z.dw+dx]
6182 				pr += float64(p[0] * c.weight)
6183 				pg += float64(p[1] * c.weight)
6184 				pb += float64(p[2] * c.weight)
6185 				pa += float64(p[3] * c.weight)
6186 			}
6187 
6188 			if pr > pa {
6189 				pr = pa
6190 			}
6191 			if pg > pa {
6192 				pg = pa
6193 			}
6194 			if pb > pa {
6195 				pb = pa
6196 			}
6197 
6198 			q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy))
6199 			pr0 := uint32(ftou(pr * s.invTotalWeight))
6200 			pg0 := uint32(ftou(pg * s.invTotalWeight))
6201 			pb0 := uint32(ftou(pb * s.invTotalWeight))
6202 			pa0 := uint32(ftou(pa * s.invTotalWeight))
6203 			if dstMask != nil {
6204 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
6205 				pr0 = pr0 * ma / 0xffff
6206 				pg0 = pg0 * ma / 0xffff
6207 				pb0 = pb0 * ma / 0xffff
6208 				pa0 = pa0 * ma / 0xffff
6209 			}
6210 			pa1 := 0xffff - pa0
6211 			dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + pr0)
6212 			dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + pg0)
6213 			dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + pb0)
6214 			dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + pa0)
6215 			dst.SetRGBA64(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColorRGBA64)
6216 		}
6217 	}
6218 }
6219 
6220 func (z *kernelScaler) scaleY_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
6221 	dstMask, dmp := opts.DstMask, opts.DstMaskP
6222 	dstColorRGBA64 := color.RGBA64{}
6223 
6224 	for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
6225 		for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
6226 			var pr, pg, pb, pa float64
6227 			for _, c := range z.vertical.contribs[s.i:s.j] {
6228 				p := &tmp[c.coord*z.dw+dx]
6229 				pr += float64(p[0] * c.weight)
6230 				pg += float64(p[1] * c.weight)
6231 				pb += float64(p[2] * c.weight)
6232 				pa += float64(p[3] * c.weight)
6233 			}
6234 
6235 			if pr > pa {
6236 				pr = pa
6237 			}
6238 			if pg > pa {
6239 				pg = pa
6240 			}
6241 			if pb > pa {
6242 				pb = pa
6243 			}
6244 
6245 			if dstMask != nil {
6246 				q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy))
6247 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
6248 				pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff
6249 				pg := uint32(ftou(pg*s.invTotalWeight)) * ma / 0xffff
6250 				pb := uint32(ftou(pb*s.invTotalWeight)) * ma / 0xffff
6251 				pa := uint32(ftou(pa*s.invTotalWeight)) * ma / 0xffff
6252 				pa1 := 0xffff - ma
6253 				dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + pr)
6254 				dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + pg)
6255 				dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + pb)
6256 				dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + pa)
6257 				dst.SetRGBA64(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColorRGBA64)
6258 			} else {
6259 				dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
6260 				dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
6261 				dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
6262 				dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
6263 				dst.SetRGBA64(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColorRGBA64)
6264 			}
6265 		}
6266 	}
6267 }
6268 
6269 func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
6270 	dstMask, dmp := opts.DstMask, opts.DstMaskP
6271 	dstColorRGBA64 := &color.RGBA64{}
6272 	dstColor := color.Color(dstColorRGBA64)
6273 	for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
6274 		for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
6275 			var pr, pg, pb, pa float64
6276 			for _, c := range z.vertical.contribs[s.i:s.j] {
6277 				p := &tmp[c.coord*z.dw+dx]
6278 				pr += float64(p[0] * c.weight)
6279 				pg += float64(p[1] * c.weight)
6280 				pb += float64(p[2] * c.weight)
6281 				pa += float64(p[3] * c.weight)
6282 			}
6283 
6284 			if pr > pa {
6285 				pr = pa
6286 			}
6287 			if pg > pa {
6288 				pg = pa
6289 			}
6290 			if pb > pa {
6291 				pb = pa
6292 			}
6293 
6294 			qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
6295 			pr0 := uint32(ftou(pr * s.invTotalWeight))
6296 			pg0 := uint32(ftou(pg * s.invTotalWeight))
6297 			pb0 := uint32(ftou(pb * s.invTotalWeight))
6298 			pa0 := uint32(ftou(pa * s.invTotalWeight))
6299 			if dstMask != nil {
6300 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
6301 				pr0 = pr0 * ma / 0xffff
6302 				pg0 = pg0 * ma / 0xffff
6303 				pb0 = pb0 * ma / 0xffff
6304 				pa0 = pa0 * ma / 0xffff
6305 			}
6306 			pa1 := 0xffff - pa0
6307 			dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
6308 			dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
6309 			dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0)
6310 			dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0)
6311 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
6312 		}
6313 	}
6314 }
6315 
6316 func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) {
6317 	dstMask, dmp := opts.DstMask, opts.DstMaskP
6318 	dstColorRGBA64 := &color.RGBA64{}
6319 	dstColor := color.Color(dstColorRGBA64)
6320 	for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
6321 		for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] {
6322 			var pr, pg, pb, pa float64
6323 			for _, c := range z.vertical.contribs[s.i:s.j] {
6324 				p := &tmp[c.coord*z.dw+dx]
6325 				pr += float64(p[0] * c.weight)
6326 				pg += float64(p[1] * c.weight)
6327 				pb += float64(p[2] * c.weight)
6328 				pa += float64(p[3] * c.weight)
6329 			}
6330 
6331 			if pr > pa {
6332 				pr = pa
6333 			}
6334 			if pg > pa {
6335 				pg = pa
6336 			}
6337 			if pb > pa {
6338 				pb = pa
6339 			}
6340 
6341 			if dstMask != nil {
6342 				qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
6343 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA()
6344 				pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff
6345 				pg := uint32(ftou(pg*s.invTotalWeight)) * ma / 0xffff
6346 				pb := uint32(ftou(pb*s.invTotalWeight)) * ma / 0xffff
6347 				pa := uint32(ftou(pa*s.invTotalWeight)) * ma / 0xffff
6348 				pa1 := 0xffff - ma
6349 				dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
6350 				dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
6351 				dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
6352 				dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
6353 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
6354 			} else {
6355 				dstColorRGBA64.R = ftou(pr * s.invTotalWeight)
6356 				dstColorRGBA64.G = ftou(pg * s.invTotalWeight)
6357 				dstColorRGBA64.B = ftou(pb * s.invTotalWeight)
6358 				dstColorRGBA64.A = ftou(pa * s.invTotalWeight)
6359 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor)
6360 			}
6361 		}
6362 	}
6363 }
6364 
6365 func (q *Kernel) transform_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.Gray, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
6366 	// When shrinking, broaden the effective kernel support so that we still
6367 	// visit every source pixel.
6368 	xHalfWidth, xKernelArgScale := q.Support, 1.0
6369 	if xscale > 1 {
6370 		xHalfWidth *= xscale
6371 		xKernelArgScale = 1 / xscale
6372 	}
6373 	yHalfWidth, yKernelArgScale := q.Support, 1.0
6374 	if yscale > 1 {
6375 		yHalfWidth *= yscale
6376 		yKernelArgScale = 1 / yscale
6377 	}
6378 
6379 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
6380 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
6381 
6382 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
6383 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
6384 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
6385 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
6386 			dxf := float64(dr.Min.X+int(dx)) + 0.5
6387 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
6388 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
6389 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
6390 				continue
6391 			}
6392 
6393 			// TODO: adjust the bias so that we can use int(f) instead
6394 			// of math.Floor(f) and math.Ceil(f).
6395 			sx += float64(bias.X)
6396 			sx -= 0.5
6397 			ix := int(math.Floor(sx - xHalfWidth))
6398 			if ix < sr.Min.X {
6399 				ix = sr.Min.X
6400 			}
6401 			jx := int(math.Ceil(sx + xHalfWidth))
6402 			if jx > sr.Max.X {
6403 				jx = sr.Max.X
6404 			}
6405 
6406 			totalXWeight := 0.0
6407 			for kx := ix; kx < jx; kx++ {
6408 				xWeight := 0.0
6409 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
6410 					xWeight = q.At(t)
6411 				}
6412 				xWeights[kx-ix] = xWeight
6413 				totalXWeight += xWeight
6414 			}
6415 			for x := range xWeights[:jx-ix] {
6416 				xWeights[x] /= totalXWeight
6417 			}
6418 
6419 			sy += float64(bias.Y)
6420 			sy -= 0.5
6421 			iy := int(math.Floor(sy - yHalfWidth))
6422 			if iy < sr.Min.Y {
6423 				iy = sr.Min.Y
6424 			}
6425 			jy := int(math.Ceil(sy + yHalfWidth))
6426 			if jy > sr.Max.Y {
6427 				jy = sr.Max.Y
6428 			}
6429 
6430 			totalYWeight := 0.0
6431 			for ky := iy; ky < jy; ky++ {
6432 				yWeight := 0.0
6433 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
6434 					yWeight = q.At(t)
6435 				}
6436 				yWeights[ky-iy] = yWeight
6437 				totalYWeight += yWeight
6438 			}
6439 			for y := range yWeights[:jy-iy] {
6440 				yWeights[y] /= totalYWeight
6441 			}
6442 
6443 			var pr float64
6444 			for ky := iy; ky < jy; ky++ {
6445 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
6446 					for kx := ix; kx < jx; kx++ {
6447 						if w := xWeights[kx-ix] * yWeight; w != 0 {
6448 							pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X)
6449 							pru := uint32(src.Pix[pi]) * 0x101
6450 							pr += float64(float64(pru) * w)
6451 						}
6452 					}
6453 				}
6454 			}
6455 			out := uint8(fffftou(pr) >> 8)
6456 			dst.Pix[d+0] = out
6457 			dst.Pix[d+1] = out
6458 			dst.Pix[d+2] = out
6459 			dst.Pix[d+3] = 0xff
6460 		}
6461 	}
6462 }
6463 
6464 func (q *Kernel) transform_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
6465 	// When shrinking, broaden the effective kernel support so that we still
6466 	// visit every source pixel.
6467 	xHalfWidth, xKernelArgScale := q.Support, 1.0
6468 	if xscale > 1 {
6469 		xHalfWidth *= xscale
6470 		xKernelArgScale = 1 / xscale
6471 	}
6472 	yHalfWidth, yKernelArgScale := q.Support, 1.0
6473 	if yscale > 1 {
6474 		yHalfWidth *= yscale
6475 		yKernelArgScale = 1 / yscale
6476 	}
6477 
6478 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
6479 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
6480 
6481 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
6482 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
6483 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
6484 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
6485 			dxf := float64(dr.Min.X+int(dx)) + 0.5
6486 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
6487 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
6488 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
6489 				continue
6490 			}
6491 
6492 			// TODO: adjust the bias so that we can use int(f) instead
6493 			// of math.Floor(f) and math.Ceil(f).
6494 			sx += float64(bias.X)
6495 			sx -= 0.5
6496 			ix := int(math.Floor(sx - xHalfWidth))
6497 			if ix < sr.Min.X {
6498 				ix = sr.Min.X
6499 			}
6500 			jx := int(math.Ceil(sx + xHalfWidth))
6501 			if jx > sr.Max.X {
6502 				jx = sr.Max.X
6503 			}
6504 
6505 			totalXWeight := 0.0
6506 			for kx := ix; kx < jx; kx++ {
6507 				xWeight := 0.0
6508 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
6509 					xWeight = q.At(t)
6510 				}
6511 				xWeights[kx-ix] = xWeight
6512 				totalXWeight += xWeight
6513 			}
6514 			for x := range xWeights[:jx-ix] {
6515 				xWeights[x] /= totalXWeight
6516 			}
6517 
6518 			sy += float64(bias.Y)
6519 			sy -= 0.5
6520 			iy := int(math.Floor(sy - yHalfWidth))
6521 			if iy < sr.Min.Y {
6522 				iy = sr.Min.Y
6523 			}
6524 			jy := int(math.Ceil(sy + yHalfWidth))
6525 			if jy > sr.Max.Y {
6526 				jy = sr.Max.Y
6527 			}
6528 
6529 			totalYWeight := 0.0
6530 			for ky := iy; ky < jy; ky++ {
6531 				yWeight := 0.0
6532 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
6533 					yWeight = q.At(t)
6534 				}
6535 				yWeights[ky-iy] = yWeight
6536 				totalYWeight += yWeight
6537 			}
6538 			for y := range yWeights[:jy-iy] {
6539 				yWeights[y] /= totalYWeight
6540 			}
6541 
6542 			var pr, pg, pb, pa float64
6543 			for ky := iy; ky < jy; ky++ {
6544 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
6545 					for kx := ix; kx < jx; kx++ {
6546 						if w := xWeights[kx-ix] * yWeight; w != 0 {
6547 							pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
6548 							pau := uint32(src.Pix[pi+3]) * 0x101
6549 							pru := uint32(src.Pix[pi+0]) * pau / 0xff
6550 							pgu := uint32(src.Pix[pi+1]) * pau / 0xff
6551 							pbu := uint32(src.Pix[pi+2]) * pau / 0xff
6552 							pr += float64(float64(pru) * w)
6553 							pg += float64(float64(pgu) * w)
6554 							pb += float64(float64(pbu) * w)
6555 							pa += float64(float64(pau) * w)
6556 						}
6557 					}
6558 				}
6559 			}
6560 
6561 			if pr > pa {
6562 				pr = pa
6563 			}
6564 			if pg > pa {
6565 				pg = pa
6566 			}
6567 			if pb > pa {
6568 				pb = pa
6569 			}
6570 
6571 			pr0 := uint32(fffftou(pr))
6572 			pg0 := uint32(fffftou(pg))
6573 			pb0 := uint32(fffftou(pb))
6574 			pa0 := uint32(fffftou(pa))
6575 			pa1 := (0xffff - uint32(pa0)) * 0x101
6576 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
6577 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
6578 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
6579 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
6580 		}
6581 	}
6582 }
6583 
6584 func (q *Kernel) transform_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.NRGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
6585 	// When shrinking, broaden the effective kernel support so that we still
6586 	// visit every source pixel.
6587 	xHalfWidth, xKernelArgScale := q.Support, 1.0
6588 	if xscale > 1 {
6589 		xHalfWidth *= xscale
6590 		xKernelArgScale = 1 / xscale
6591 	}
6592 	yHalfWidth, yKernelArgScale := q.Support, 1.0
6593 	if yscale > 1 {
6594 		yHalfWidth *= yscale
6595 		yKernelArgScale = 1 / yscale
6596 	}
6597 
6598 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
6599 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
6600 
6601 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
6602 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
6603 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
6604 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
6605 			dxf := float64(dr.Min.X+int(dx)) + 0.5
6606 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
6607 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
6608 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
6609 				continue
6610 			}
6611 
6612 			// TODO: adjust the bias so that we can use int(f) instead
6613 			// of math.Floor(f) and math.Ceil(f).
6614 			sx += float64(bias.X)
6615 			sx -= 0.5
6616 			ix := int(math.Floor(sx - xHalfWidth))
6617 			if ix < sr.Min.X {
6618 				ix = sr.Min.X
6619 			}
6620 			jx := int(math.Ceil(sx + xHalfWidth))
6621 			if jx > sr.Max.X {
6622 				jx = sr.Max.X
6623 			}
6624 
6625 			totalXWeight := 0.0
6626 			for kx := ix; kx < jx; kx++ {
6627 				xWeight := 0.0
6628 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
6629 					xWeight = q.At(t)
6630 				}
6631 				xWeights[kx-ix] = xWeight
6632 				totalXWeight += xWeight
6633 			}
6634 			for x := range xWeights[:jx-ix] {
6635 				xWeights[x] /= totalXWeight
6636 			}
6637 
6638 			sy += float64(bias.Y)
6639 			sy -= 0.5
6640 			iy := int(math.Floor(sy - yHalfWidth))
6641 			if iy < sr.Min.Y {
6642 				iy = sr.Min.Y
6643 			}
6644 			jy := int(math.Ceil(sy + yHalfWidth))
6645 			if jy > sr.Max.Y {
6646 				jy = sr.Max.Y
6647 			}
6648 
6649 			totalYWeight := 0.0
6650 			for ky := iy; ky < jy; ky++ {
6651 				yWeight := 0.0
6652 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
6653 					yWeight = q.At(t)
6654 				}
6655 				yWeights[ky-iy] = yWeight
6656 				totalYWeight += yWeight
6657 			}
6658 			for y := range yWeights[:jy-iy] {
6659 				yWeights[y] /= totalYWeight
6660 			}
6661 
6662 			var pr, pg, pb, pa float64
6663 			for ky := iy; ky < jy; ky++ {
6664 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
6665 					for kx := ix; kx < jx; kx++ {
6666 						if w := xWeights[kx-ix] * yWeight; w != 0 {
6667 							pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
6668 							pau := uint32(src.Pix[pi+3]) * 0x101
6669 							pru := uint32(src.Pix[pi+0]) * pau / 0xff
6670 							pgu := uint32(src.Pix[pi+1]) * pau / 0xff
6671 							pbu := uint32(src.Pix[pi+2]) * pau / 0xff
6672 							pr += float64(float64(pru) * w)
6673 							pg += float64(float64(pgu) * w)
6674 							pb += float64(float64(pbu) * w)
6675 							pa += float64(float64(pau) * w)
6676 						}
6677 					}
6678 				}
6679 			}
6680 
6681 			if pr > pa {
6682 				pr = pa
6683 			}
6684 			if pg > pa {
6685 				pg = pa
6686 			}
6687 			if pb > pa {
6688 				pb = pa
6689 			}
6690 
6691 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
6692 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
6693 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
6694 			dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
6695 		}
6696 	}
6697 }
6698 
6699 func (q *Kernel) transform_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
6700 	// When shrinking, broaden the effective kernel support so that we still
6701 	// visit every source pixel.
6702 	xHalfWidth, xKernelArgScale := q.Support, 1.0
6703 	if xscale > 1 {
6704 		xHalfWidth *= xscale
6705 		xKernelArgScale = 1 / xscale
6706 	}
6707 	yHalfWidth, yKernelArgScale := q.Support, 1.0
6708 	if yscale > 1 {
6709 		yHalfWidth *= yscale
6710 		yKernelArgScale = 1 / yscale
6711 	}
6712 
6713 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
6714 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
6715 
6716 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
6717 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
6718 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
6719 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
6720 			dxf := float64(dr.Min.X+int(dx)) + 0.5
6721 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
6722 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
6723 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
6724 				continue
6725 			}
6726 
6727 			// TODO: adjust the bias so that we can use int(f) instead
6728 			// of math.Floor(f) and math.Ceil(f).
6729 			sx += float64(bias.X)
6730 			sx -= 0.5
6731 			ix := int(math.Floor(sx - xHalfWidth))
6732 			if ix < sr.Min.X {
6733 				ix = sr.Min.X
6734 			}
6735 			jx := int(math.Ceil(sx + xHalfWidth))
6736 			if jx > sr.Max.X {
6737 				jx = sr.Max.X
6738 			}
6739 
6740 			totalXWeight := 0.0
6741 			for kx := ix; kx < jx; kx++ {
6742 				xWeight := 0.0
6743 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
6744 					xWeight = q.At(t)
6745 				}
6746 				xWeights[kx-ix] = xWeight
6747 				totalXWeight += xWeight
6748 			}
6749 			for x := range xWeights[:jx-ix] {
6750 				xWeights[x] /= totalXWeight
6751 			}
6752 
6753 			sy += float64(bias.Y)
6754 			sy -= 0.5
6755 			iy := int(math.Floor(sy - yHalfWidth))
6756 			if iy < sr.Min.Y {
6757 				iy = sr.Min.Y
6758 			}
6759 			jy := int(math.Ceil(sy + yHalfWidth))
6760 			if jy > sr.Max.Y {
6761 				jy = sr.Max.Y
6762 			}
6763 
6764 			totalYWeight := 0.0
6765 			for ky := iy; ky < jy; ky++ {
6766 				yWeight := 0.0
6767 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
6768 					yWeight = q.At(t)
6769 				}
6770 				yWeights[ky-iy] = yWeight
6771 				totalYWeight += yWeight
6772 			}
6773 			for y := range yWeights[:jy-iy] {
6774 				yWeights[y] /= totalYWeight
6775 			}
6776 
6777 			var pr, pg, pb, pa float64
6778 			for ky := iy; ky < jy; ky++ {
6779 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
6780 					for kx := ix; kx < jx; kx++ {
6781 						if w := xWeights[kx-ix] * yWeight; w != 0 {
6782 							pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
6783 							pru := uint32(src.Pix[pi+0]) * 0x101
6784 							pgu := uint32(src.Pix[pi+1]) * 0x101
6785 							pbu := uint32(src.Pix[pi+2]) * 0x101
6786 							pau := uint32(src.Pix[pi+3]) * 0x101
6787 							pr += float64(float64(pru) * w)
6788 							pg += float64(float64(pgu) * w)
6789 							pb += float64(float64(pbu) * w)
6790 							pa += float64(float64(pau) * w)
6791 						}
6792 					}
6793 				}
6794 			}
6795 
6796 			if pr > pa {
6797 				pr = pa
6798 			}
6799 			if pg > pa {
6800 				pg = pa
6801 			}
6802 			if pb > pa {
6803 				pb = pa
6804 			}
6805 
6806 			pr0 := uint32(fffftou(pr))
6807 			pg0 := uint32(fffftou(pg))
6808 			pb0 := uint32(fffftou(pb))
6809 			pa0 := uint32(fffftou(pa))
6810 			pa1 := (0xffff - uint32(pa0)) * 0x101
6811 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
6812 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
6813 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
6814 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
6815 		}
6816 	}
6817 }
6818 
6819 func (q *Kernel) transform_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.RGBA, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
6820 	// When shrinking, broaden the effective kernel support so that we still
6821 	// visit every source pixel.
6822 	xHalfWidth, xKernelArgScale := q.Support, 1.0
6823 	if xscale > 1 {
6824 		xHalfWidth *= xscale
6825 		xKernelArgScale = 1 / xscale
6826 	}
6827 	yHalfWidth, yKernelArgScale := q.Support, 1.0
6828 	if yscale > 1 {
6829 		yHalfWidth *= yscale
6830 		yKernelArgScale = 1 / yscale
6831 	}
6832 
6833 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
6834 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
6835 
6836 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
6837 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
6838 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
6839 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
6840 			dxf := float64(dr.Min.X+int(dx)) + 0.5
6841 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
6842 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
6843 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
6844 				continue
6845 			}
6846 
6847 			// TODO: adjust the bias so that we can use int(f) instead
6848 			// of math.Floor(f) and math.Ceil(f).
6849 			sx += float64(bias.X)
6850 			sx -= 0.5
6851 			ix := int(math.Floor(sx - xHalfWidth))
6852 			if ix < sr.Min.X {
6853 				ix = sr.Min.X
6854 			}
6855 			jx := int(math.Ceil(sx + xHalfWidth))
6856 			if jx > sr.Max.X {
6857 				jx = sr.Max.X
6858 			}
6859 
6860 			totalXWeight := 0.0
6861 			for kx := ix; kx < jx; kx++ {
6862 				xWeight := 0.0
6863 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
6864 					xWeight = q.At(t)
6865 				}
6866 				xWeights[kx-ix] = xWeight
6867 				totalXWeight += xWeight
6868 			}
6869 			for x := range xWeights[:jx-ix] {
6870 				xWeights[x] /= totalXWeight
6871 			}
6872 
6873 			sy += float64(bias.Y)
6874 			sy -= 0.5
6875 			iy := int(math.Floor(sy - yHalfWidth))
6876 			if iy < sr.Min.Y {
6877 				iy = sr.Min.Y
6878 			}
6879 			jy := int(math.Ceil(sy + yHalfWidth))
6880 			if jy > sr.Max.Y {
6881 				jy = sr.Max.Y
6882 			}
6883 
6884 			totalYWeight := 0.0
6885 			for ky := iy; ky < jy; ky++ {
6886 				yWeight := 0.0
6887 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
6888 					yWeight = q.At(t)
6889 				}
6890 				yWeights[ky-iy] = yWeight
6891 				totalYWeight += yWeight
6892 			}
6893 			for y := range yWeights[:jy-iy] {
6894 				yWeights[y] /= totalYWeight
6895 			}
6896 
6897 			var pr, pg, pb, pa float64
6898 			for ky := iy; ky < jy; ky++ {
6899 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
6900 					for kx := ix; kx < jx; kx++ {
6901 						if w := xWeights[kx-ix] * yWeight; w != 0 {
6902 							pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4
6903 							pru := uint32(src.Pix[pi+0]) * 0x101
6904 							pgu := uint32(src.Pix[pi+1]) * 0x101
6905 							pbu := uint32(src.Pix[pi+2]) * 0x101
6906 							pau := uint32(src.Pix[pi+3]) * 0x101
6907 							pr += float64(float64(pru) * w)
6908 							pg += float64(float64(pgu) * w)
6909 							pb += float64(float64(pbu) * w)
6910 							pa += float64(float64(pau) * w)
6911 						}
6912 					}
6913 				}
6914 			}
6915 
6916 			if pr > pa {
6917 				pr = pa
6918 			}
6919 			if pg > pa {
6920 				pg = pa
6921 			}
6922 			if pb > pa {
6923 				pb = pa
6924 			}
6925 
6926 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
6927 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
6928 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
6929 			dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
6930 		}
6931 	}
6932 }
6933 
6934 func (q *Kernel) transform_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
6935 	// When shrinking, broaden the effective kernel support so that we still
6936 	// visit every source pixel.
6937 	xHalfWidth, xKernelArgScale := q.Support, 1.0
6938 	if xscale > 1 {
6939 		xHalfWidth *= xscale
6940 		xKernelArgScale = 1 / xscale
6941 	}
6942 	yHalfWidth, yKernelArgScale := q.Support, 1.0
6943 	if yscale > 1 {
6944 		yHalfWidth *= yscale
6945 		yKernelArgScale = 1 / yscale
6946 	}
6947 
6948 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
6949 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
6950 
6951 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
6952 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
6953 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
6954 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
6955 			dxf := float64(dr.Min.X+int(dx)) + 0.5
6956 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
6957 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
6958 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
6959 				continue
6960 			}
6961 
6962 			// TODO: adjust the bias so that we can use int(f) instead
6963 			// of math.Floor(f) and math.Ceil(f).
6964 			sx += float64(bias.X)
6965 			sx -= 0.5
6966 			ix := int(math.Floor(sx - xHalfWidth))
6967 			if ix < sr.Min.X {
6968 				ix = sr.Min.X
6969 			}
6970 			jx := int(math.Ceil(sx + xHalfWidth))
6971 			if jx > sr.Max.X {
6972 				jx = sr.Max.X
6973 			}
6974 
6975 			totalXWeight := 0.0
6976 			for kx := ix; kx < jx; kx++ {
6977 				xWeight := 0.0
6978 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
6979 					xWeight = q.At(t)
6980 				}
6981 				xWeights[kx-ix] = xWeight
6982 				totalXWeight += xWeight
6983 			}
6984 			for x := range xWeights[:jx-ix] {
6985 				xWeights[x] /= totalXWeight
6986 			}
6987 
6988 			sy += float64(bias.Y)
6989 			sy -= 0.5
6990 			iy := int(math.Floor(sy - yHalfWidth))
6991 			if iy < sr.Min.Y {
6992 				iy = sr.Min.Y
6993 			}
6994 			jy := int(math.Ceil(sy + yHalfWidth))
6995 			if jy > sr.Max.Y {
6996 				jy = sr.Max.Y
6997 			}
6998 
6999 			totalYWeight := 0.0
7000 			for ky := iy; ky < jy; ky++ {
7001 				yWeight := 0.0
7002 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7003 					yWeight = q.At(t)
7004 				}
7005 				yWeights[ky-iy] = yWeight
7006 				totalYWeight += yWeight
7007 			}
7008 			for y := range yWeights[:jy-iy] {
7009 				yWeights[y] /= totalYWeight
7010 			}
7011 
7012 			var pr, pg, pb float64
7013 			for ky := iy; ky < jy; ky++ {
7014 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7015 					for kx := ix; kx < jx; kx++ {
7016 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7017 							pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
7018 							pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X)
7019 
7020 							// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
7021 							pyy1 := int(src.Y[pi]) * 0x10101
7022 							pcb1 := int(src.Cb[pj]) - 128
7023 							pcr1 := int(src.Cr[pj]) - 128
7024 							pru := (pyy1 + 91881*pcr1) >> 8
7025 							pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
7026 							pbu := (pyy1 + 116130*pcb1) >> 8
7027 							if pru < 0 {
7028 								pru = 0
7029 							} else if pru > 0xffff {
7030 								pru = 0xffff
7031 							}
7032 							if pgu < 0 {
7033 								pgu = 0
7034 							} else if pgu > 0xffff {
7035 								pgu = 0xffff
7036 							}
7037 							if pbu < 0 {
7038 								pbu = 0
7039 							} else if pbu > 0xffff {
7040 								pbu = 0xffff
7041 							}
7042 
7043 							pr += float64(float64(pru) * w)
7044 							pg += float64(float64(pgu) * w)
7045 							pb += float64(float64(pbu) * w)
7046 						}
7047 					}
7048 				}
7049 			}
7050 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
7051 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
7052 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
7053 			dst.Pix[d+3] = 0xff
7054 		}
7055 	}
7056 }
7057 
7058 func (q *Kernel) transform_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7059 	// When shrinking, broaden the effective kernel support so that we still
7060 	// visit every source pixel.
7061 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7062 	if xscale > 1 {
7063 		xHalfWidth *= xscale
7064 		xKernelArgScale = 1 / xscale
7065 	}
7066 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7067 	if yscale > 1 {
7068 		yHalfWidth *= yscale
7069 		yKernelArgScale = 1 / yscale
7070 	}
7071 
7072 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7073 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7074 
7075 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7076 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7077 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7078 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7079 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7080 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7081 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7082 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7083 				continue
7084 			}
7085 
7086 			// TODO: adjust the bias so that we can use int(f) instead
7087 			// of math.Floor(f) and math.Ceil(f).
7088 			sx += float64(bias.X)
7089 			sx -= 0.5
7090 			ix := int(math.Floor(sx - xHalfWidth))
7091 			if ix < sr.Min.X {
7092 				ix = sr.Min.X
7093 			}
7094 			jx := int(math.Ceil(sx + xHalfWidth))
7095 			if jx > sr.Max.X {
7096 				jx = sr.Max.X
7097 			}
7098 
7099 			totalXWeight := 0.0
7100 			for kx := ix; kx < jx; kx++ {
7101 				xWeight := 0.0
7102 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7103 					xWeight = q.At(t)
7104 				}
7105 				xWeights[kx-ix] = xWeight
7106 				totalXWeight += xWeight
7107 			}
7108 			for x := range xWeights[:jx-ix] {
7109 				xWeights[x] /= totalXWeight
7110 			}
7111 
7112 			sy += float64(bias.Y)
7113 			sy -= 0.5
7114 			iy := int(math.Floor(sy - yHalfWidth))
7115 			if iy < sr.Min.Y {
7116 				iy = sr.Min.Y
7117 			}
7118 			jy := int(math.Ceil(sy + yHalfWidth))
7119 			if jy > sr.Max.Y {
7120 				jy = sr.Max.Y
7121 			}
7122 
7123 			totalYWeight := 0.0
7124 			for ky := iy; ky < jy; ky++ {
7125 				yWeight := 0.0
7126 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7127 					yWeight = q.At(t)
7128 				}
7129 				yWeights[ky-iy] = yWeight
7130 				totalYWeight += yWeight
7131 			}
7132 			for y := range yWeights[:jy-iy] {
7133 				yWeights[y] /= totalYWeight
7134 			}
7135 
7136 			var pr, pg, pb float64
7137 			for ky := iy; ky < jy; ky++ {
7138 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7139 					for kx := ix; kx < jx; kx++ {
7140 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7141 							pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
7142 							pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
7143 
7144 							// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
7145 							pyy1 := int(src.Y[pi]) * 0x10101
7146 							pcb1 := int(src.Cb[pj]) - 128
7147 							pcr1 := int(src.Cr[pj]) - 128
7148 							pru := (pyy1 + 91881*pcr1) >> 8
7149 							pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
7150 							pbu := (pyy1 + 116130*pcb1) >> 8
7151 							if pru < 0 {
7152 								pru = 0
7153 							} else if pru > 0xffff {
7154 								pru = 0xffff
7155 							}
7156 							if pgu < 0 {
7157 								pgu = 0
7158 							} else if pgu > 0xffff {
7159 								pgu = 0xffff
7160 							}
7161 							if pbu < 0 {
7162 								pbu = 0
7163 							} else if pbu > 0xffff {
7164 								pbu = 0xffff
7165 							}
7166 
7167 							pr += float64(float64(pru) * w)
7168 							pg += float64(float64(pgu) * w)
7169 							pb += float64(float64(pbu) * w)
7170 						}
7171 					}
7172 				}
7173 			}
7174 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
7175 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
7176 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
7177 			dst.Pix[d+3] = 0xff
7178 		}
7179 	}
7180 }
7181 
7182 func (q *Kernel) transform_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7183 	// When shrinking, broaden the effective kernel support so that we still
7184 	// visit every source pixel.
7185 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7186 	if xscale > 1 {
7187 		xHalfWidth *= xscale
7188 		xKernelArgScale = 1 / xscale
7189 	}
7190 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7191 	if yscale > 1 {
7192 		yHalfWidth *= yscale
7193 		yKernelArgScale = 1 / yscale
7194 	}
7195 
7196 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7197 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7198 
7199 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7200 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7201 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7202 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7203 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7204 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7205 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7206 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7207 				continue
7208 			}
7209 
7210 			// TODO: adjust the bias so that we can use int(f) instead
7211 			// of math.Floor(f) and math.Ceil(f).
7212 			sx += float64(bias.X)
7213 			sx -= 0.5
7214 			ix := int(math.Floor(sx - xHalfWidth))
7215 			if ix < sr.Min.X {
7216 				ix = sr.Min.X
7217 			}
7218 			jx := int(math.Ceil(sx + xHalfWidth))
7219 			if jx > sr.Max.X {
7220 				jx = sr.Max.X
7221 			}
7222 
7223 			totalXWeight := 0.0
7224 			for kx := ix; kx < jx; kx++ {
7225 				xWeight := 0.0
7226 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7227 					xWeight = q.At(t)
7228 				}
7229 				xWeights[kx-ix] = xWeight
7230 				totalXWeight += xWeight
7231 			}
7232 			for x := range xWeights[:jx-ix] {
7233 				xWeights[x] /= totalXWeight
7234 			}
7235 
7236 			sy += float64(bias.Y)
7237 			sy -= 0.5
7238 			iy := int(math.Floor(sy - yHalfWidth))
7239 			if iy < sr.Min.Y {
7240 				iy = sr.Min.Y
7241 			}
7242 			jy := int(math.Ceil(sy + yHalfWidth))
7243 			if jy > sr.Max.Y {
7244 				jy = sr.Max.Y
7245 			}
7246 
7247 			totalYWeight := 0.0
7248 			for ky := iy; ky < jy; ky++ {
7249 				yWeight := 0.0
7250 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7251 					yWeight = q.At(t)
7252 				}
7253 				yWeights[ky-iy] = yWeight
7254 				totalYWeight += yWeight
7255 			}
7256 			for y := range yWeights[:jy-iy] {
7257 				yWeights[y] /= totalYWeight
7258 			}
7259 
7260 			var pr, pg, pb float64
7261 			for ky := iy; ky < jy; ky++ {
7262 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7263 					for kx := ix; kx < jx; kx++ {
7264 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7265 							pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
7266 							pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2)
7267 
7268 							// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
7269 							pyy1 := int(src.Y[pi]) * 0x10101
7270 							pcb1 := int(src.Cb[pj]) - 128
7271 							pcr1 := int(src.Cr[pj]) - 128
7272 							pru := (pyy1 + 91881*pcr1) >> 8
7273 							pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
7274 							pbu := (pyy1 + 116130*pcb1) >> 8
7275 							if pru < 0 {
7276 								pru = 0
7277 							} else if pru > 0xffff {
7278 								pru = 0xffff
7279 							}
7280 							if pgu < 0 {
7281 								pgu = 0
7282 							} else if pgu > 0xffff {
7283 								pgu = 0xffff
7284 							}
7285 							if pbu < 0 {
7286 								pbu = 0
7287 							} else if pbu > 0xffff {
7288 								pbu = 0xffff
7289 							}
7290 
7291 							pr += float64(float64(pru) * w)
7292 							pg += float64(float64(pgu) * w)
7293 							pb += float64(float64(pbu) * w)
7294 						}
7295 					}
7296 				}
7297 			}
7298 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
7299 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
7300 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
7301 			dst.Pix[d+3] = 0xff
7302 		}
7303 	}
7304 }
7305 
7306 func (q *Kernel) transform_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src *image.YCbCr, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7307 	// When shrinking, broaden the effective kernel support so that we still
7308 	// visit every source pixel.
7309 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7310 	if xscale > 1 {
7311 		xHalfWidth *= xscale
7312 		xKernelArgScale = 1 / xscale
7313 	}
7314 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7315 	if yscale > 1 {
7316 		yHalfWidth *= yscale
7317 		yKernelArgScale = 1 / yscale
7318 	}
7319 
7320 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7321 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7322 
7323 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7324 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7325 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7326 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7327 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7328 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7329 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7330 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7331 				continue
7332 			}
7333 
7334 			// TODO: adjust the bias so that we can use int(f) instead
7335 			// of math.Floor(f) and math.Ceil(f).
7336 			sx += float64(bias.X)
7337 			sx -= 0.5
7338 			ix := int(math.Floor(sx - xHalfWidth))
7339 			if ix < sr.Min.X {
7340 				ix = sr.Min.X
7341 			}
7342 			jx := int(math.Ceil(sx + xHalfWidth))
7343 			if jx > sr.Max.X {
7344 				jx = sr.Max.X
7345 			}
7346 
7347 			totalXWeight := 0.0
7348 			for kx := ix; kx < jx; kx++ {
7349 				xWeight := 0.0
7350 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7351 					xWeight = q.At(t)
7352 				}
7353 				xWeights[kx-ix] = xWeight
7354 				totalXWeight += xWeight
7355 			}
7356 			for x := range xWeights[:jx-ix] {
7357 				xWeights[x] /= totalXWeight
7358 			}
7359 
7360 			sy += float64(bias.Y)
7361 			sy -= 0.5
7362 			iy := int(math.Floor(sy - yHalfWidth))
7363 			if iy < sr.Min.Y {
7364 				iy = sr.Min.Y
7365 			}
7366 			jy := int(math.Ceil(sy + yHalfWidth))
7367 			if jy > sr.Max.Y {
7368 				jy = sr.Max.Y
7369 			}
7370 
7371 			totalYWeight := 0.0
7372 			for ky := iy; ky < jy; ky++ {
7373 				yWeight := 0.0
7374 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7375 					yWeight = q.At(t)
7376 				}
7377 				yWeights[ky-iy] = yWeight
7378 				totalYWeight += yWeight
7379 			}
7380 			for y := range yWeights[:jy-iy] {
7381 				yWeights[y] /= totalYWeight
7382 			}
7383 
7384 			var pr, pg, pb float64
7385 			for ky := iy; ky < jy; ky++ {
7386 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7387 					for kx := ix; kx < jx; kx++ {
7388 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7389 							pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X)
7390 							pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X)
7391 
7392 							// This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method.
7393 							pyy1 := int(src.Y[pi]) * 0x10101
7394 							pcb1 := int(src.Cb[pj]) - 128
7395 							pcr1 := int(src.Cr[pj]) - 128
7396 							pru := (pyy1 + 91881*pcr1) >> 8
7397 							pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8
7398 							pbu := (pyy1 + 116130*pcb1) >> 8
7399 							if pru < 0 {
7400 								pru = 0
7401 							} else if pru > 0xffff {
7402 								pru = 0xffff
7403 							}
7404 							if pgu < 0 {
7405 								pgu = 0
7406 							} else if pgu > 0xffff {
7407 								pgu = 0xffff
7408 							}
7409 							if pbu < 0 {
7410 								pbu = 0
7411 							} else if pbu > 0xffff {
7412 								pbu = 0xffff
7413 							}
7414 
7415 							pr += float64(float64(pru) * w)
7416 							pg += float64(float64(pgu) * w)
7417 							pb += float64(float64(pbu) * w)
7418 						}
7419 					}
7420 				}
7421 			}
7422 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
7423 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
7424 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
7425 			dst.Pix[d+3] = 0xff
7426 		}
7427 	}
7428 }
7429 
7430 func (q *Kernel) transform_RGBA_RGBA64Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7431 	// When shrinking, broaden the effective kernel support so that we still
7432 	// visit every source pixel.
7433 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7434 	if xscale > 1 {
7435 		xHalfWidth *= xscale
7436 		xKernelArgScale = 1 / xscale
7437 	}
7438 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7439 	if yscale > 1 {
7440 		yHalfWidth *= yscale
7441 		yKernelArgScale = 1 / yscale
7442 	}
7443 
7444 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7445 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7446 
7447 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7448 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7449 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7450 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7451 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7452 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7453 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7454 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7455 				continue
7456 			}
7457 
7458 			// TODO: adjust the bias so that we can use int(f) instead
7459 			// of math.Floor(f) and math.Ceil(f).
7460 			sx += float64(bias.X)
7461 			sx -= 0.5
7462 			ix := int(math.Floor(sx - xHalfWidth))
7463 			if ix < sr.Min.X {
7464 				ix = sr.Min.X
7465 			}
7466 			jx := int(math.Ceil(sx + xHalfWidth))
7467 			if jx > sr.Max.X {
7468 				jx = sr.Max.X
7469 			}
7470 
7471 			totalXWeight := 0.0
7472 			for kx := ix; kx < jx; kx++ {
7473 				xWeight := 0.0
7474 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7475 					xWeight = q.At(t)
7476 				}
7477 				xWeights[kx-ix] = xWeight
7478 				totalXWeight += xWeight
7479 			}
7480 			for x := range xWeights[:jx-ix] {
7481 				xWeights[x] /= totalXWeight
7482 			}
7483 
7484 			sy += float64(bias.Y)
7485 			sy -= 0.5
7486 			iy := int(math.Floor(sy - yHalfWidth))
7487 			if iy < sr.Min.Y {
7488 				iy = sr.Min.Y
7489 			}
7490 			jy := int(math.Ceil(sy + yHalfWidth))
7491 			if jy > sr.Max.Y {
7492 				jy = sr.Max.Y
7493 			}
7494 
7495 			totalYWeight := 0.0
7496 			for ky := iy; ky < jy; ky++ {
7497 				yWeight := 0.0
7498 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7499 					yWeight = q.At(t)
7500 				}
7501 				yWeights[ky-iy] = yWeight
7502 				totalYWeight += yWeight
7503 			}
7504 			for y := range yWeights[:jy-iy] {
7505 				yWeights[y] /= totalYWeight
7506 			}
7507 
7508 			var pr, pg, pb, pa float64
7509 			for ky := iy; ky < jy; ky++ {
7510 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7511 					for kx := ix; kx < jx; kx++ {
7512 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7513 							pu := src.RGBA64At(kx, ky)
7514 							pr += float64(float64(pu.R) * w)
7515 							pg += float64(float64(pu.G) * w)
7516 							pb += float64(float64(pu.B) * w)
7517 							pa += float64(float64(pu.A) * w)
7518 						}
7519 					}
7520 				}
7521 			}
7522 
7523 			if pr > pa {
7524 				pr = pa
7525 			}
7526 			if pg > pa {
7527 				pg = pa
7528 			}
7529 			if pb > pa {
7530 				pb = pa
7531 			}
7532 
7533 			pr0 := uint32(fffftou(pr))
7534 			pg0 := uint32(fffftou(pg))
7535 			pb0 := uint32(fffftou(pb))
7536 			pa0 := uint32(fffftou(pa))
7537 			pa1 := (0xffff - uint32(pa0)) * 0x101
7538 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
7539 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
7540 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
7541 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
7542 		}
7543 	}
7544 }
7545 
7546 func (q *Kernel) transform_RGBA_RGBA64Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7547 	// When shrinking, broaden the effective kernel support so that we still
7548 	// visit every source pixel.
7549 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7550 	if xscale > 1 {
7551 		xHalfWidth *= xscale
7552 		xKernelArgScale = 1 / xscale
7553 	}
7554 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7555 	if yscale > 1 {
7556 		yHalfWidth *= yscale
7557 		yKernelArgScale = 1 / yscale
7558 	}
7559 
7560 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7561 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7562 
7563 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7564 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7565 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7566 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7567 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7568 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7569 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7570 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7571 				continue
7572 			}
7573 
7574 			// TODO: adjust the bias so that we can use int(f) instead
7575 			// of math.Floor(f) and math.Ceil(f).
7576 			sx += float64(bias.X)
7577 			sx -= 0.5
7578 			ix := int(math.Floor(sx - xHalfWidth))
7579 			if ix < sr.Min.X {
7580 				ix = sr.Min.X
7581 			}
7582 			jx := int(math.Ceil(sx + xHalfWidth))
7583 			if jx > sr.Max.X {
7584 				jx = sr.Max.X
7585 			}
7586 
7587 			totalXWeight := 0.0
7588 			for kx := ix; kx < jx; kx++ {
7589 				xWeight := 0.0
7590 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7591 					xWeight = q.At(t)
7592 				}
7593 				xWeights[kx-ix] = xWeight
7594 				totalXWeight += xWeight
7595 			}
7596 			for x := range xWeights[:jx-ix] {
7597 				xWeights[x] /= totalXWeight
7598 			}
7599 
7600 			sy += float64(bias.Y)
7601 			sy -= 0.5
7602 			iy := int(math.Floor(sy - yHalfWidth))
7603 			if iy < sr.Min.Y {
7604 				iy = sr.Min.Y
7605 			}
7606 			jy := int(math.Ceil(sy + yHalfWidth))
7607 			if jy > sr.Max.Y {
7608 				jy = sr.Max.Y
7609 			}
7610 
7611 			totalYWeight := 0.0
7612 			for ky := iy; ky < jy; ky++ {
7613 				yWeight := 0.0
7614 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7615 					yWeight = q.At(t)
7616 				}
7617 				yWeights[ky-iy] = yWeight
7618 				totalYWeight += yWeight
7619 			}
7620 			for y := range yWeights[:jy-iy] {
7621 				yWeights[y] /= totalYWeight
7622 			}
7623 
7624 			var pr, pg, pb, pa float64
7625 			for ky := iy; ky < jy; ky++ {
7626 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7627 					for kx := ix; kx < jx; kx++ {
7628 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7629 							pu := src.RGBA64At(kx, ky)
7630 							pr += float64(float64(pu.R) * w)
7631 							pg += float64(float64(pu.G) * w)
7632 							pb += float64(float64(pu.B) * w)
7633 							pa += float64(float64(pu.A) * w)
7634 						}
7635 					}
7636 				}
7637 			}
7638 
7639 			if pr > pa {
7640 				pr = pa
7641 			}
7642 			if pg > pa {
7643 				pg = pa
7644 			}
7645 			if pb > pa {
7646 				pb = pa
7647 			}
7648 
7649 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
7650 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
7651 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
7652 			dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
7653 		}
7654 	}
7655 }
7656 
7657 func (q *Kernel) transform_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7658 	// When shrinking, broaden the effective kernel support so that we still
7659 	// visit every source pixel.
7660 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7661 	if xscale > 1 {
7662 		xHalfWidth *= xscale
7663 		xKernelArgScale = 1 / xscale
7664 	}
7665 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7666 	if yscale > 1 {
7667 		yHalfWidth *= yscale
7668 		yKernelArgScale = 1 / yscale
7669 	}
7670 
7671 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7672 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7673 
7674 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7675 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7676 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7677 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7678 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7679 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7680 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7681 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7682 				continue
7683 			}
7684 
7685 			// TODO: adjust the bias so that we can use int(f) instead
7686 			// of math.Floor(f) and math.Ceil(f).
7687 			sx += float64(bias.X)
7688 			sx -= 0.5
7689 			ix := int(math.Floor(sx - xHalfWidth))
7690 			if ix < sr.Min.X {
7691 				ix = sr.Min.X
7692 			}
7693 			jx := int(math.Ceil(sx + xHalfWidth))
7694 			if jx > sr.Max.X {
7695 				jx = sr.Max.X
7696 			}
7697 
7698 			totalXWeight := 0.0
7699 			for kx := ix; kx < jx; kx++ {
7700 				xWeight := 0.0
7701 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7702 					xWeight = q.At(t)
7703 				}
7704 				xWeights[kx-ix] = xWeight
7705 				totalXWeight += xWeight
7706 			}
7707 			for x := range xWeights[:jx-ix] {
7708 				xWeights[x] /= totalXWeight
7709 			}
7710 
7711 			sy += float64(bias.Y)
7712 			sy -= 0.5
7713 			iy := int(math.Floor(sy - yHalfWidth))
7714 			if iy < sr.Min.Y {
7715 				iy = sr.Min.Y
7716 			}
7717 			jy := int(math.Ceil(sy + yHalfWidth))
7718 			if jy > sr.Max.Y {
7719 				jy = sr.Max.Y
7720 			}
7721 
7722 			totalYWeight := 0.0
7723 			for ky := iy; ky < jy; ky++ {
7724 				yWeight := 0.0
7725 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7726 					yWeight = q.At(t)
7727 				}
7728 				yWeights[ky-iy] = yWeight
7729 				totalYWeight += yWeight
7730 			}
7731 			for y := range yWeights[:jy-iy] {
7732 				yWeights[y] /= totalYWeight
7733 			}
7734 
7735 			var pr, pg, pb, pa float64
7736 			for ky := iy; ky < jy; ky++ {
7737 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7738 					for kx := ix; kx < jx; kx++ {
7739 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7740 							pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
7741 							pr += float64(float64(pru) * w)
7742 							pg += float64(float64(pgu) * w)
7743 							pb += float64(float64(pbu) * w)
7744 							pa += float64(float64(pau) * w)
7745 						}
7746 					}
7747 				}
7748 			}
7749 
7750 			if pr > pa {
7751 				pr = pa
7752 			}
7753 			if pg > pa {
7754 				pg = pa
7755 			}
7756 			if pb > pa {
7757 				pb = pa
7758 			}
7759 
7760 			pr0 := uint32(fffftou(pr))
7761 			pg0 := uint32(fffftou(pg))
7762 			pb0 := uint32(fffftou(pb))
7763 			pa0 := uint32(fffftou(pa))
7764 			pa1 := (0xffff - uint32(pa0)) * 0x101
7765 			dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8)
7766 			dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8)
7767 			dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8)
7768 			dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8)
7769 		}
7770 	}
7771 }
7772 
7773 func (q *Kernel) transform_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7774 	// When shrinking, broaden the effective kernel support so that we still
7775 	// visit every source pixel.
7776 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7777 	if xscale > 1 {
7778 		xHalfWidth *= xscale
7779 		xKernelArgScale = 1 / xscale
7780 	}
7781 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7782 	if yscale > 1 {
7783 		yHalfWidth *= yscale
7784 		yKernelArgScale = 1 / yscale
7785 	}
7786 
7787 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7788 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7789 
7790 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7791 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7792 		d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4
7793 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 {
7794 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7795 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7796 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7797 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7798 				continue
7799 			}
7800 
7801 			// TODO: adjust the bias so that we can use int(f) instead
7802 			// of math.Floor(f) and math.Ceil(f).
7803 			sx += float64(bias.X)
7804 			sx -= 0.5
7805 			ix := int(math.Floor(sx - xHalfWidth))
7806 			if ix < sr.Min.X {
7807 				ix = sr.Min.X
7808 			}
7809 			jx := int(math.Ceil(sx + xHalfWidth))
7810 			if jx > sr.Max.X {
7811 				jx = sr.Max.X
7812 			}
7813 
7814 			totalXWeight := 0.0
7815 			for kx := ix; kx < jx; kx++ {
7816 				xWeight := 0.0
7817 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7818 					xWeight = q.At(t)
7819 				}
7820 				xWeights[kx-ix] = xWeight
7821 				totalXWeight += xWeight
7822 			}
7823 			for x := range xWeights[:jx-ix] {
7824 				xWeights[x] /= totalXWeight
7825 			}
7826 
7827 			sy += float64(bias.Y)
7828 			sy -= 0.5
7829 			iy := int(math.Floor(sy - yHalfWidth))
7830 			if iy < sr.Min.Y {
7831 				iy = sr.Min.Y
7832 			}
7833 			jy := int(math.Ceil(sy + yHalfWidth))
7834 			if jy > sr.Max.Y {
7835 				jy = sr.Max.Y
7836 			}
7837 
7838 			totalYWeight := 0.0
7839 			for ky := iy; ky < jy; ky++ {
7840 				yWeight := 0.0
7841 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7842 					yWeight = q.At(t)
7843 				}
7844 				yWeights[ky-iy] = yWeight
7845 				totalYWeight += yWeight
7846 			}
7847 			for y := range yWeights[:jy-iy] {
7848 				yWeights[y] /= totalYWeight
7849 			}
7850 
7851 			var pr, pg, pb, pa float64
7852 			for ky := iy; ky < jy; ky++ {
7853 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7854 					for kx := ix; kx < jx; kx++ {
7855 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7856 							pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
7857 							pr += float64(float64(pru) * w)
7858 							pg += float64(float64(pgu) * w)
7859 							pb += float64(float64(pbu) * w)
7860 							pa += float64(float64(pau) * w)
7861 						}
7862 					}
7863 				}
7864 			}
7865 
7866 			if pr > pa {
7867 				pr = pa
7868 			}
7869 			if pg > pa {
7870 				pg = pa
7871 			}
7872 			if pb > pa {
7873 				pb = pa
7874 			}
7875 
7876 			dst.Pix[d+0] = uint8(fffftou(pr) >> 8)
7877 			dst.Pix[d+1] = uint8(fffftou(pg) >> 8)
7878 			dst.Pix[d+2] = uint8(fffftou(pb) >> 8)
7879 			dst.Pix[d+3] = uint8(fffftou(pa) >> 8)
7880 		}
7881 	}
7882 }
7883 
7884 func (q *Kernel) transform_RGBA64Image_RGBA64Image_Over(dst RGBA64Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
7885 	// When shrinking, broaden the effective kernel support so that we still
7886 	// visit every source pixel.
7887 	xHalfWidth, xKernelArgScale := q.Support, 1.0
7888 	if xscale > 1 {
7889 		xHalfWidth *= xscale
7890 		xKernelArgScale = 1 / xscale
7891 	}
7892 	yHalfWidth, yKernelArgScale := q.Support, 1.0
7893 	if yscale > 1 {
7894 		yHalfWidth *= yscale
7895 		yKernelArgScale = 1 / yscale
7896 	}
7897 
7898 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
7899 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
7900 
7901 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
7902 	dstMask, dmp := opts.DstMask, opts.DstMaskP
7903 	dstColorRGBA64 := color.RGBA64{}
7904 
7905 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
7906 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
7907 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
7908 			dxf := float64(dr.Min.X+int(dx)) + 0.5
7909 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
7910 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
7911 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
7912 				continue
7913 			}
7914 
7915 			// TODO: adjust the bias so that we can use int(f) instead
7916 			// of math.Floor(f) and math.Ceil(f).
7917 			sx += float64(bias.X)
7918 			sx -= 0.5
7919 			ix := int(math.Floor(sx - xHalfWidth))
7920 			if ix < sr.Min.X {
7921 				ix = sr.Min.X
7922 			}
7923 			jx := int(math.Ceil(sx + xHalfWidth))
7924 			if jx > sr.Max.X {
7925 				jx = sr.Max.X
7926 			}
7927 
7928 			totalXWeight := 0.0
7929 			for kx := ix; kx < jx; kx++ {
7930 				xWeight := 0.0
7931 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
7932 					xWeight = q.At(t)
7933 				}
7934 				xWeights[kx-ix] = xWeight
7935 				totalXWeight += xWeight
7936 			}
7937 			for x := range xWeights[:jx-ix] {
7938 				xWeights[x] /= totalXWeight
7939 			}
7940 
7941 			sy += float64(bias.Y)
7942 			sy -= 0.5
7943 			iy := int(math.Floor(sy - yHalfWidth))
7944 			if iy < sr.Min.Y {
7945 				iy = sr.Min.Y
7946 			}
7947 			jy := int(math.Ceil(sy + yHalfWidth))
7948 			if jy > sr.Max.Y {
7949 				jy = sr.Max.Y
7950 			}
7951 
7952 			totalYWeight := 0.0
7953 			for ky := iy; ky < jy; ky++ {
7954 				yWeight := 0.0
7955 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
7956 					yWeight = q.At(t)
7957 				}
7958 				yWeights[ky-iy] = yWeight
7959 				totalYWeight += yWeight
7960 			}
7961 			for y := range yWeights[:jy-iy] {
7962 				yWeights[y] /= totalYWeight
7963 			}
7964 
7965 			var pr, pg, pb, pa float64
7966 			for ky := iy; ky < jy; ky++ {
7967 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
7968 					for kx := ix; kx < jx; kx++ {
7969 						if w := xWeights[kx-ix] * yWeight; w != 0 {
7970 							pu := src.RGBA64At(kx, ky)
7971 							if srcMask != nil {
7972 								_, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
7973 								pu.R = uint16(uint32(pu.R) * ma / 0xffff)
7974 								pu.G = uint16(uint32(pu.G) * ma / 0xffff)
7975 								pu.B = uint16(uint32(pu.B) * ma / 0xffff)
7976 								pu.A = uint16(uint32(pu.A) * ma / 0xffff)
7977 							}
7978 							pr += float64(float64(pu.R) * w)
7979 							pg += float64(float64(pu.G) * w)
7980 							pb += float64(float64(pu.B) * w)
7981 							pa += float64(float64(pu.A) * w)
7982 						}
7983 					}
7984 				}
7985 			}
7986 
7987 			if pr > pa {
7988 				pr = pa
7989 			}
7990 			if pg > pa {
7991 				pg = pa
7992 			}
7993 			if pb > pa {
7994 				pb = pa
7995 			}
7996 
7997 			q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
7998 			pr0 := uint32(fffftou(pr))
7999 			pg0 := uint32(fffftou(pg))
8000 			pb0 := uint32(fffftou(pb))
8001 			pa0 := uint32(fffftou(pa))
8002 			if dstMask != nil {
8003 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
8004 				pr0 = pr0 * ma / 0xffff
8005 				pg0 = pg0 * ma / 0xffff
8006 				pb0 = pb0 * ma / 0xffff
8007 				pa0 = pa0 * ma / 0xffff
8008 			}
8009 			pa1 := 0xffff - pa0
8010 			dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + pr0)
8011 			dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + pg0)
8012 			dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + pb0)
8013 			dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + pa0)
8014 			dst.SetRGBA64(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
8015 		}
8016 	}
8017 }
8018 
8019 func (q *Kernel) transform_RGBA64Image_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.RGBA64Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
8020 	// When shrinking, broaden the effective kernel support so that we still
8021 	// visit every source pixel.
8022 	xHalfWidth, xKernelArgScale := q.Support, 1.0
8023 	if xscale > 1 {
8024 		xHalfWidth *= xscale
8025 		xKernelArgScale = 1 / xscale
8026 	}
8027 	yHalfWidth, yKernelArgScale := q.Support, 1.0
8028 	if yscale > 1 {
8029 		yHalfWidth *= yscale
8030 		yKernelArgScale = 1 / yscale
8031 	}
8032 
8033 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
8034 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
8035 
8036 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
8037 	dstMask, dmp := opts.DstMask, opts.DstMaskP
8038 	dstColorRGBA64 := color.RGBA64{}
8039 
8040 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
8041 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
8042 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
8043 			dxf := float64(dr.Min.X+int(dx)) + 0.5
8044 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
8045 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
8046 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
8047 				continue
8048 			}
8049 
8050 			// TODO: adjust the bias so that we can use int(f) instead
8051 			// of math.Floor(f) and math.Ceil(f).
8052 			sx += float64(bias.X)
8053 			sx -= 0.5
8054 			ix := int(math.Floor(sx - xHalfWidth))
8055 			if ix < sr.Min.X {
8056 				ix = sr.Min.X
8057 			}
8058 			jx := int(math.Ceil(sx + xHalfWidth))
8059 			if jx > sr.Max.X {
8060 				jx = sr.Max.X
8061 			}
8062 
8063 			totalXWeight := 0.0
8064 			for kx := ix; kx < jx; kx++ {
8065 				xWeight := 0.0
8066 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
8067 					xWeight = q.At(t)
8068 				}
8069 				xWeights[kx-ix] = xWeight
8070 				totalXWeight += xWeight
8071 			}
8072 			for x := range xWeights[:jx-ix] {
8073 				xWeights[x] /= totalXWeight
8074 			}
8075 
8076 			sy += float64(bias.Y)
8077 			sy -= 0.5
8078 			iy := int(math.Floor(sy - yHalfWidth))
8079 			if iy < sr.Min.Y {
8080 				iy = sr.Min.Y
8081 			}
8082 			jy := int(math.Ceil(sy + yHalfWidth))
8083 			if jy > sr.Max.Y {
8084 				jy = sr.Max.Y
8085 			}
8086 
8087 			totalYWeight := 0.0
8088 			for ky := iy; ky < jy; ky++ {
8089 				yWeight := 0.0
8090 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
8091 					yWeight = q.At(t)
8092 				}
8093 				yWeights[ky-iy] = yWeight
8094 				totalYWeight += yWeight
8095 			}
8096 			for y := range yWeights[:jy-iy] {
8097 				yWeights[y] /= totalYWeight
8098 			}
8099 
8100 			var pr, pg, pb, pa float64
8101 			for ky := iy; ky < jy; ky++ {
8102 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
8103 					for kx := ix; kx < jx; kx++ {
8104 						if w := xWeights[kx-ix] * yWeight; w != 0 {
8105 							pu := src.RGBA64At(kx, ky)
8106 							if srcMask != nil {
8107 								_, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
8108 								pu.R = uint16(uint32(pu.R) * ma / 0xffff)
8109 								pu.G = uint16(uint32(pu.G) * ma / 0xffff)
8110 								pu.B = uint16(uint32(pu.B) * ma / 0xffff)
8111 								pu.A = uint16(uint32(pu.A) * ma / 0xffff)
8112 							}
8113 							pr += float64(float64(pu.R) * w)
8114 							pg += float64(float64(pu.G) * w)
8115 							pb += float64(float64(pu.B) * w)
8116 							pa += float64(float64(pu.A) * w)
8117 						}
8118 					}
8119 				}
8120 			}
8121 
8122 			if pr > pa {
8123 				pr = pa
8124 			}
8125 			if pg > pa {
8126 				pg = pa
8127 			}
8128 			if pb > pa {
8129 				pb = pa
8130 			}
8131 
8132 			if dstMask != nil {
8133 				q := dst.RGBA64At(dr.Min.X+int(dx), dr.Min.Y+int(dy))
8134 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
8135 				pr := uint32(fffftou(pr)) * ma / 0xffff
8136 				pg := uint32(fffftou(pg)) * ma / 0xffff
8137 				pb := uint32(fffftou(pb)) * ma / 0xffff
8138 				pa := uint32(fffftou(pa)) * ma / 0xffff
8139 				pa1 := 0xffff - ma
8140 				dstColorRGBA64.R = uint16(uint32(q.R)*pa1/0xffff + pr)
8141 				dstColorRGBA64.G = uint16(uint32(q.G)*pa1/0xffff + pg)
8142 				dstColorRGBA64.B = uint16(uint32(q.B)*pa1/0xffff + pb)
8143 				dstColorRGBA64.A = uint16(uint32(q.A)*pa1/0xffff + pa)
8144 				dst.SetRGBA64(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
8145 			} else {
8146 				dstColorRGBA64.R = fffftou(pr)
8147 				dstColorRGBA64.G = fffftou(pg)
8148 				dstColorRGBA64.B = fffftou(pb)
8149 				dstColorRGBA64.A = fffftou(pa)
8150 				dst.SetRGBA64(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColorRGBA64)
8151 			}
8152 		}
8153 	}
8154 }
8155 
8156 func (q *Kernel) transform_Image_Image_Over(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
8157 	// When shrinking, broaden the effective kernel support so that we still
8158 	// visit every source pixel.
8159 	xHalfWidth, xKernelArgScale := q.Support, 1.0
8160 	if xscale > 1 {
8161 		xHalfWidth *= xscale
8162 		xKernelArgScale = 1 / xscale
8163 	}
8164 	yHalfWidth, yKernelArgScale := q.Support, 1.0
8165 	if yscale > 1 {
8166 		yHalfWidth *= yscale
8167 		yKernelArgScale = 1 / yscale
8168 	}
8169 
8170 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
8171 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
8172 
8173 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
8174 	dstMask, dmp := opts.DstMask, opts.DstMaskP
8175 	dstColorRGBA64 := &color.RGBA64{}
8176 	dstColor := color.Color(dstColorRGBA64)
8177 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
8178 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
8179 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
8180 			dxf := float64(dr.Min.X+int(dx)) + 0.5
8181 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
8182 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
8183 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
8184 				continue
8185 			}
8186 
8187 			// TODO: adjust the bias so that we can use int(f) instead
8188 			// of math.Floor(f) and math.Ceil(f).
8189 			sx += float64(bias.X)
8190 			sx -= 0.5
8191 			ix := int(math.Floor(sx - xHalfWidth))
8192 			if ix < sr.Min.X {
8193 				ix = sr.Min.X
8194 			}
8195 			jx := int(math.Ceil(sx + xHalfWidth))
8196 			if jx > sr.Max.X {
8197 				jx = sr.Max.X
8198 			}
8199 
8200 			totalXWeight := 0.0
8201 			for kx := ix; kx < jx; kx++ {
8202 				xWeight := 0.0
8203 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
8204 					xWeight = q.At(t)
8205 				}
8206 				xWeights[kx-ix] = xWeight
8207 				totalXWeight += xWeight
8208 			}
8209 			for x := range xWeights[:jx-ix] {
8210 				xWeights[x] /= totalXWeight
8211 			}
8212 
8213 			sy += float64(bias.Y)
8214 			sy -= 0.5
8215 			iy := int(math.Floor(sy - yHalfWidth))
8216 			if iy < sr.Min.Y {
8217 				iy = sr.Min.Y
8218 			}
8219 			jy := int(math.Ceil(sy + yHalfWidth))
8220 			if jy > sr.Max.Y {
8221 				jy = sr.Max.Y
8222 			}
8223 
8224 			totalYWeight := 0.0
8225 			for ky := iy; ky < jy; ky++ {
8226 				yWeight := 0.0
8227 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
8228 					yWeight = q.At(t)
8229 				}
8230 				yWeights[ky-iy] = yWeight
8231 				totalYWeight += yWeight
8232 			}
8233 			for y := range yWeights[:jy-iy] {
8234 				yWeights[y] /= totalYWeight
8235 			}
8236 
8237 			var pr, pg, pb, pa float64
8238 			for ky := iy; ky < jy; ky++ {
8239 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
8240 					for kx := ix; kx < jx; kx++ {
8241 						if w := xWeights[kx-ix] * yWeight; w != 0 {
8242 							pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
8243 							if srcMask != nil {
8244 								_, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
8245 								pru = pru * ma / 0xffff
8246 								pgu = pgu * ma / 0xffff
8247 								pbu = pbu * ma / 0xffff
8248 								pau = pau * ma / 0xffff
8249 							}
8250 							pr += float64(float64(pru) * w)
8251 							pg += float64(float64(pgu) * w)
8252 							pb += float64(float64(pbu) * w)
8253 							pa += float64(float64(pau) * w)
8254 						}
8255 					}
8256 				}
8257 			}
8258 
8259 			if pr > pa {
8260 				pr = pa
8261 			}
8262 			if pg > pa {
8263 				pg = pa
8264 			}
8265 			if pb > pa {
8266 				pb = pa
8267 			}
8268 
8269 			qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
8270 			pr0 := uint32(fffftou(pr))
8271 			pg0 := uint32(fffftou(pg))
8272 			pb0 := uint32(fffftou(pb))
8273 			pa0 := uint32(fffftou(pa))
8274 			if dstMask != nil {
8275 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
8276 				pr0 = pr0 * ma / 0xffff
8277 				pg0 = pg0 * ma / 0xffff
8278 				pb0 = pb0 * ma / 0xffff
8279 				pa0 = pa0 * ma / 0xffff
8280 			}
8281 			pa1 := 0xffff - pa0
8282 			dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0)
8283 			dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0)
8284 			dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0)
8285 			dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0)
8286 			dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
8287 		}
8288 	}
8289 }
8290 
8291 func (q *Kernel) transform_Image_Image_Src(dst Image, dr, adr image.Rectangle, d2s *f64.Aff3, src image.Image, sr image.Rectangle, bias image.Point, xscale, yscale float64, opts *Options) {
8292 	// When shrinking, broaden the effective kernel support so that we still
8293 	// visit every source pixel.
8294 	xHalfWidth, xKernelArgScale := q.Support, 1.0
8295 	if xscale > 1 {
8296 		xHalfWidth *= xscale
8297 		xKernelArgScale = 1 / xscale
8298 	}
8299 	yHalfWidth, yKernelArgScale := q.Support, 1.0
8300 	if yscale > 1 {
8301 		yHalfWidth *= yscale
8302 		yKernelArgScale = 1 / yscale
8303 	}
8304 
8305 	xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth)))
8306 	yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth)))
8307 
8308 	srcMask, smp := opts.SrcMask, opts.SrcMaskP
8309 	dstMask, dmp := opts.DstMask, opts.DstMaskP
8310 	dstColorRGBA64 := &color.RGBA64{}
8311 	dstColor := color.Color(dstColorRGBA64)
8312 	for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ {
8313 		dyf := float64(dr.Min.Y+int(dy)) + 0.5
8314 		for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ {
8315 			dxf := float64(dr.Min.X+int(dx)) + 0.5
8316 			sx := float64(d2s[0]*dxf) + float64(d2s[1]*dyf) + d2s[2]
8317 			sy := float64(d2s[3]*dxf) + float64(d2s[4]*dyf) + d2s[5]
8318 			if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) {
8319 				continue
8320 			}
8321 
8322 			// TODO: adjust the bias so that we can use int(f) instead
8323 			// of math.Floor(f) and math.Ceil(f).
8324 			sx += float64(bias.X)
8325 			sx -= 0.5
8326 			ix := int(math.Floor(sx - xHalfWidth))
8327 			if ix < sr.Min.X {
8328 				ix = sr.Min.X
8329 			}
8330 			jx := int(math.Ceil(sx + xHalfWidth))
8331 			if jx > sr.Max.X {
8332 				jx = sr.Max.X
8333 			}
8334 
8335 			totalXWeight := 0.0
8336 			for kx := ix; kx < jx; kx++ {
8337 				xWeight := 0.0
8338 				if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support {
8339 					xWeight = q.At(t)
8340 				}
8341 				xWeights[kx-ix] = xWeight
8342 				totalXWeight += xWeight
8343 			}
8344 			for x := range xWeights[:jx-ix] {
8345 				xWeights[x] /= totalXWeight
8346 			}
8347 
8348 			sy += float64(bias.Y)
8349 			sy -= 0.5
8350 			iy := int(math.Floor(sy - yHalfWidth))
8351 			if iy < sr.Min.Y {
8352 				iy = sr.Min.Y
8353 			}
8354 			jy := int(math.Ceil(sy + yHalfWidth))
8355 			if jy > sr.Max.Y {
8356 				jy = sr.Max.Y
8357 			}
8358 
8359 			totalYWeight := 0.0
8360 			for ky := iy; ky < jy; ky++ {
8361 				yWeight := 0.0
8362 				if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support {
8363 					yWeight = q.At(t)
8364 				}
8365 				yWeights[ky-iy] = yWeight
8366 				totalYWeight += yWeight
8367 			}
8368 			for y := range yWeights[:jy-iy] {
8369 				yWeights[y] /= totalYWeight
8370 			}
8371 
8372 			var pr, pg, pb, pa float64
8373 			for ky := iy; ky < jy; ky++ {
8374 				if yWeight := yWeights[ky-iy]; yWeight != 0 {
8375 					for kx := ix; kx < jx; kx++ {
8376 						if w := xWeights[kx-ix] * yWeight; w != 0 {
8377 							pru, pgu, pbu, pau := src.At(kx, ky).RGBA()
8378 							if srcMask != nil {
8379 								_, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA()
8380 								pru = pru * ma / 0xffff
8381 								pgu = pgu * ma / 0xffff
8382 								pbu = pbu * ma / 0xffff
8383 								pau = pau * ma / 0xffff
8384 							}
8385 							pr += float64(float64(pru) * w)
8386 							pg += float64(float64(pgu) * w)
8387 							pb += float64(float64(pbu) * w)
8388 							pa += float64(float64(pau) * w)
8389 						}
8390 					}
8391 				}
8392 			}
8393 
8394 			if pr > pa {
8395 				pr = pa
8396 			}
8397 			if pg > pa {
8398 				pg = pa
8399 			}
8400 			if pb > pa {
8401 				pb = pa
8402 			}
8403 
8404 			if dstMask != nil {
8405 				qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA()
8406 				_, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA()
8407 				pr := uint32(fffftou(pr)) * ma / 0xffff
8408 				pg := uint32(fffftou(pg)) * ma / 0xffff
8409 				pb := uint32(fffftou(pb)) * ma / 0xffff
8410 				pa := uint32(fffftou(pa)) * ma / 0xffff
8411 				pa1 := 0xffff - ma
8412 				dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr)
8413 				dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg)
8414 				dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb)
8415 				dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa)
8416 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
8417 			} else {
8418 				dstColorRGBA64.R = fffftou(pr)
8419 				dstColorRGBA64.G = fffftou(pg)
8420 				dstColorRGBA64.B = fffftou(pb)
8421 				dstColorRGBA64.A = fffftou(pa)
8422 				dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor)
8423 			}
8424 		}
8425 	}
8426 }