...

Source file src/golang.org/x/image/draw/impl.go

Documentation: golang.org/x/image/draw

     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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   782  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   804  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   829  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   853  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   878  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   902  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   946  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
   990  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1034  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1078  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1099  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1119  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1140  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1163  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1203  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1245  			sy0 := int(d2s[3]*dxf+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(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X
  1285  			sy0 := int(d2s[3]*dxf+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(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(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 = xFrac1*s00r + 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 = xFrac1*s01r + xFrac0*s11r
  1607  			s11r = yFrac1*s10r + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  1676  			s10g = xFrac1*s00g + xFrac0*s10g
  1677  			s10b = xFrac1*s00b + xFrac0*s10b
  1678  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  1698  			s11g = xFrac1*s01g + xFrac0*s11g
  1699  			s11b = xFrac1*s01b + xFrac0*s11b
  1700  			s11a = xFrac1*s01a + xFrac0*s11a
  1701  			s11r = yFrac1*s10r + yFrac0*s11r
  1702  			s11g = yFrac1*s10g + yFrac0*s11g
  1703  			s11b = yFrac1*s10b + yFrac0*s11b
  1704  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  1776  			s10g = xFrac1*s00g + xFrac0*s10g
  1777  			s10b = xFrac1*s00b + xFrac0*s10b
  1778  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  1798  			s11g = xFrac1*s01g + xFrac0*s11g
  1799  			s11b = xFrac1*s01b + xFrac0*s11b
  1800  			s11a = xFrac1*s01a + xFrac0*s11a
  1801  			s11r = yFrac1*s10r + yFrac0*s11r
  1802  			s11g = yFrac1*s10g + yFrac0*s11g
  1803  			s11b = yFrac1*s10b + yFrac0*s11b
  1804  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  1875  			s10g = xFrac1*s00g + xFrac0*s10g
  1876  			s10b = xFrac1*s00b + xFrac0*s10b
  1877  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  1897  			s11g = xFrac1*s01g + xFrac0*s11g
  1898  			s11b = xFrac1*s01b + xFrac0*s11b
  1899  			s11a = xFrac1*s01a + xFrac0*s11a
  1900  			s11r = yFrac1*s10r + yFrac0*s11r
  1901  			s11g = yFrac1*s10g + yFrac0*s11g
  1902  			s11b = yFrac1*s10b + yFrac0*s11b
  1903  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  1975  			s10g = xFrac1*s00g + xFrac0*s10g
  1976  			s10b = xFrac1*s00b + xFrac0*s10b
  1977  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  1997  			s11g = xFrac1*s01g + xFrac0*s11g
  1998  			s11b = xFrac1*s01b + xFrac0*s11b
  1999  			s11a = xFrac1*s01a + xFrac0*s11a
  2000  			s11r = yFrac1*s10r + yFrac0*s11r
  2001  			s11g = yFrac1*s10g + yFrac0*s11g
  2002  			s11b = yFrac1*s10b + yFrac0*s11b
  2003  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2114  			s10g = xFrac1*s00g + xFrac0*s10g
  2115  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  2175  			s11g = xFrac1*s01g + xFrac0*s11g
  2176  			s11b = xFrac1*s01b + xFrac0*s11b
  2177  			s11r = yFrac1*s10r + yFrac0*s11r
  2178  			s11g = yFrac1*s10g + yFrac0*s11g
  2179  			s11b = yFrac1*s10b + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2289  			s10g = xFrac1*s00g + xFrac0*s10g
  2290  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  2350  			s11g = xFrac1*s01g + xFrac0*s11g
  2351  			s11b = xFrac1*s01b + xFrac0*s11b
  2352  			s11r = yFrac1*s10r + yFrac0*s11r
  2353  			s11g = yFrac1*s10g + yFrac0*s11g
  2354  			s11b = yFrac1*s10b + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2464  			s10g = xFrac1*s00g + xFrac0*s10g
  2465  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  2525  			s11g = xFrac1*s01g + xFrac0*s11g
  2526  			s11b = xFrac1*s01b + xFrac0*s11b
  2527  			s11r = yFrac1*s10r + yFrac0*s11r
  2528  			s11g = yFrac1*s10g + yFrac0*s11g
  2529  			s11b = yFrac1*s10b + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2639  			s10g = xFrac1*s00g + xFrac0*s10g
  2640  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  2700  			s11g = xFrac1*s01g + xFrac0*s11g
  2701  			s11b = xFrac1*s01b + xFrac0*s11b
  2702  			s11r = yFrac1*s10r + yFrac0*s11r
  2703  			s11g = yFrac1*s10g + yFrac0*s11g
  2704  			s11b = yFrac1*s10b + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2766  			s10g = xFrac1*s00g + xFrac0*s10g
  2767  			s10b = xFrac1*s00b + xFrac0*s10b
  2768  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  2780  			s11g = xFrac1*s01g + xFrac0*s11g
  2781  			s11b = xFrac1*s01b + xFrac0*s11b
  2782  			s11a = xFrac1*s01a + xFrac0*s11a
  2783  			s11r = yFrac1*s10r + yFrac0*s11r
  2784  			s11g = yFrac1*s10g + yFrac0*s11g
  2785  			s11b = yFrac1*s10b + yFrac0*s11b
  2786  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2847  			s10g = xFrac1*s00g + xFrac0*s10g
  2848  			s10b = xFrac1*s00b + xFrac0*s10b
  2849  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  2861  			s11g = xFrac1*s01g + xFrac0*s11g
  2862  			s11b = xFrac1*s01b + xFrac0*s11b
  2863  			s11a = xFrac1*s01a + xFrac0*s11a
  2864  			s11r = yFrac1*s10r + yFrac0*s11r
  2865  			s11g = yFrac1*s10g + yFrac0*s11g
  2866  			s11b = yFrac1*s10b + yFrac0*s11b
  2867  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  2927  			s10g = xFrac1*s00g + xFrac0*s10g
  2928  			s10b = xFrac1*s00b + xFrac0*s10b
  2929  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  2941  			s11g = xFrac1*s01g + xFrac0*s11g
  2942  			s11b = xFrac1*s01b + xFrac0*s11b
  2943  			s11a = xFrac1*s01a + xFrac0*s11a
  2944  			s11r = yFrac1*s10r + yFrac0*s11r
  2945  			s11g = yFrac1*s10g + yFrac0*s11g
  2946  			s11b = yFrac1*s10b + yFrac0*s11b
  2947  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  3011  			s10g = xFrac1*s00g + xFrac0*s10g
  3012  			s10b = xFrac1*s00b + xFrac0*s10b
  3013  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3025  			s11g = xFrac1*s01g + xFrac0*s11g
  3026  			s11b = xFrac1*s01b + xFrac0*s11b
  3027  			s11a = xFrac1*s01a + xFrac0*s11a
  3028  			s11r = yFrac1*s10r + yFrac0*s11r
  3029  			s11g = yFrac1*s10g + yFrac0*s11g
  3030  			s11b = yFrac1*s10b + yFrac0*s11b
  3031  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  3110  			s10g = xFrac1*s00g + xFrac0*s10g
  3111  			s10b = xFrac1*s00b + xFrac0*s10b
  3112  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3138  			s11g = xFrac1*s01g + xFrac0*s11g
  3139  			s11b = xFrac1*s01b + xFrac0*s11b
  3140  			s11a = xFrac1*s01a + xFrac0*s11a
  3141  			s11r = yFrac1*s10r + yFrac0*s11r
  3142  			s11g = yFrac1*s10g + yFrac0*s11g
  3143  			s11b = yFrac1*s10b + yFrac0*s11b
  3144  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  3230  			s10g = xFrac1*s00g + xFrac0*s10g
  3231  			s10b = xFrac1*s00b + xFrac0*s10b
  3232  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3258  			s11g = xFrac1*s01g + xFrac0*s11g
  3259  			s11b = xFrac1*s01b + xFrac0*s11b
  3260  			s11a = xFrac1*s01a + xFrac0*s11a
  3261  			s11r = yFrac1*s10r + yFrac0*s11r
  3262  			s11g = yFrac1*s10g + yFrac0*s11g
  3263  			s11b = yFrac1*s10b + yFrac0*s11b
  3264  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  3353  			s10g = xFrac1*s00g + xFrac0*s10g
  3354  			s10b = xFrac1*s00b + xFrac0*s10b
  3355  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3381  			s11g = xFrac1*s01g + xFrac0*s11g
  3382  			s11b = xFrac1*s01b + xFrac0*s11b
  3383  			s11a = xFrac1*s01a + xFrac0*s11a
  3384  			s11r = yFrac1*s10r + yFrac0*s11r
  3385  			s11g = yFrac1*s10g + yFrac0*s11g
  3386  			s11b = yFrac1*s10b + yFrac0*s11b
  3387  			s11a = yFrac1*s10a + 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(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(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 = xFrac1*s00r + xFrac0*s10r
  3477  			s10g = xFrac1*s00g + xFrac0*s10g
  3478  			s10b = xFrac1*s00b + xFrac0*s10b
  3479  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3505  			s11g = xFrac1*s01g + xFrac0*s11g
  3506  			s11b = xFrac1*s01b + xFrac0*s11b
  3507  			s11a = xFrac1*s01a + xFrac0*s11a
  3508  			s11r = yFrac1*s10r + yFrac0*s11r
  3509  			s11g = yFrac1*s10g + yFrac0*s11g
  3510  			s11b = yFrac1*s10b + yFrac0*s11b
  3511  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  3547  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + 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 = xFrac1*s01r + xFrac0*s11r
  3594  			s11r = yFrac1*s10r + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  3612  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  3664  			s10g = xFrac1*s00g + xFrac0*s10g
  3665  			s10b = xFrac1*s00b + xFrac0*s10b
  3666  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3686  			s11g = xFrac1*s01g + xFrac0*s11g
  3687  			s11b = xFrac1*s01b + xFrac0*s11b
  3688  			s11a = xFrac1*s01a + xFrac0*s11a
  3689  			s11r = yFrac1*s10r + yFrac0*s11r
  3690  			s11g = yFrac1*s10g + yFrac0*s11g
  3691  			s11b = yFrac1*s10b + yFrac0*s11b
  3692  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  3713  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  3765  			s10g = xFrac1*s00g + xFrac0*s10g
  3766  			s10b = xFrac1*s00b + xFrac0*s10b
  3767  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3787  			s11g = xFrac1*s01g + xFrac0*s11g
  3788  			s11b = xFrac1*s01b + xFrac0*s11b
  3789  			s11a = xFrac1*s01a + xFrac0*s11a
  3790  			s11r = yFrac1*s10r + yFrac0*s11r
  3791  			s11g = yFrac1*s10g + yFrac0*s11g
  3792  			s11b = yFrac1*s10b + yFrac0*s11b
  3793  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  3813  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  3865  			s10g = xFrac1*s00g + xFrac0*s10g
  3866  			s10b = xFrac1*s00b + xFrac0*s10b
  3867  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3887  			s11g = xFrac1*s01g + xFrac0*s11g
  3888  			s11b = xFrac1*s01b + xFrac0*s11b
  3889  			s11a = xFrac1*s01a + xFrac0*s11a
  3890  			s11r = yFrac1*s10r + yFrac0*s11r
  3891  			s11g = yFrac1*s10g + yFrac0*s11g
  3892  			s11b = yFrac1*s10b + yFrac0*s11b
  3893  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  3914  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  3966  			s10g = xFrac1*s00g + xFrac0*s10g
  3967  			s10b = xFrac1*s00b + xFrac0*s10b
  3968  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  3988  			s11g = xFrac1*s01g + xFrac0*s11g
  3989  			s11b = xFrac1*s01b + xFrac0*s11b
  3990  			s11a = xFrac1*s01a + xFrac0*s11a
  3991  			s11r = yFrac1*s10r + yFrac0*s11r
  3992  			s11g = yFrac1*s10g + yFrac0*s11g
  3993  			s11b = yFrac1*s10b + yFrac0*s11b
  3994  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4014  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4106  			s10g = xFrac1*s00g + xFrac0*s10g
  4107  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  4167  			s11g = xFrac1*s01g + xFrac0*s11g
  4168  			s11b = xFrac1*s01b + xFrac0*s11b
  4169  			s11r = yFrac1*s10r + yFrac0*s11r
  4170  			s11g = yFrac1*s10g + yFrac0*s11g
  4171  			s11b = yFrac1*s10b + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4190  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4282  			s10g = xFrac1*s00g + xFrac0*s10g
  4283  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  4343  			s11g = xFrac1*s01g + xFrac0*s11g
  4344  			s11b = xFrac1*s01b + xFrac0*s11b
  4345  			s11r = yFrac1*s10r + yFrac0*s11r
  4346  			s11g = yFrac1*s10g + yFrac0*s11g
  4347  			s11b = yFrac1*s10b + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4366  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4458  			s10g = xFrac1*s00g + xFrac0*s10g
  4459  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  4519  			s11g = xFrac1*s01g + xFrac0*s11g
  4520  			s11b = xFrac1*s01b + xFrac0*s11b
  4521  			s11r = yFrac1*s10r + yFrac0*s11r
  4522  			s11g = yFrac1*s10g + yFrac0*s11g
  4523  			s11b = yFrac1*s10b + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4542  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4634  			s10g = xFrac1*s00g + xFrac0*s10g
  4635  			s10b = xFrac1*s00b + 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 = xFrac1*s01r + xFrac0*s11r
  4695  			s11g = xFrac1*s01g + xFrac0*s11g
  4696  			s11b = xFrac1*s01b + xFrac0*s11b
  4697  			s11r = yFrac1*s10r + yFrac0*s11r
  4698  			s11g = yFrac1*s10g + yFrac0*s11g
  4699  			s11b = yFrac1*s10b + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4718  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4762  			s10g = xFrac1*s00g + xFrac0*s10g
  4763  			s10b = xFrac1*s00b + xFrac0*s10b
  4764  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  4776  			s11g = xFrac1*s01g + xFrac0*s11g
  4777  			s11b = xFrac1*s01b + xFrac0*s11b
  4778  			s11a = xFrac1*s01a + xFrac0*s11a
  4779  			s11r = yFrac1*s10r + yFrac0*s11r
  4780  			s11g = yFrac1*s10g + yFrac0*s11g
  4781  			s11b = yFrac1*s10b + yFrac0*s11b
  4782  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4800  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4844  			s10g = xFrac1*s00g + xFrac0*s10g
  4845  			s10b = xFrac1*s00b + xFrac0*s10b
  4846  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  4858  			s11g = xFrac1*s01g + xFrac0*s11g
  4859  			s11b = xFrac1*s01b + xFrac0*s11b
  4860  			s11a = xFrac1*s01a + xFrac0*s11a
  4861  			s11r = yFrac1*s10r + yFrac0*s11r
  4862  			s11g = yFrac1*s10g + yFrac0*s11g
  4863  			s11b = yFrac1*s10b + yFrac0*s11b
  4864  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4881  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  4925  			s10g = xFrac1*s00g + xFrac0*s10g
  4926  			s10b = xFrac1*s00b + xFrac0*s10b
  4927  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  4939  			s11g = xFrac1*s01g + xFrac0*s11g
  4940  			s11b = xFrac1*s01b + xFrac0*s11b
  4941  			s11a = xFrac1*s01a + xFrac0*s11a
  4942  			s11r = yFrac1*s10r + yFrac0*s11r
  4943  			s11g = yFrac1*s10g + yFrac0*s11g
  4944  			s11b = yFrac1*s10b + yFrac0*s11b
  4945  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  4966  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  5010  			s10g = xFrac1*s00g + xFrac0*s10g
  5011  			s10b = xFrac1*s00b + xFrac0*s10b
  5012  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  5024  			s11g = xFrac1*s01g + xFrac0*s11g
  5025  			s11b = xFrac1*s01b + xFrac0*s11b
  5026  			s11a = xFrac1*s01a + xFrac0*s11a
  5027  			s11r = yFrac1*s10r + yFrac0*s11r
  5028  			s11g = yFrac1*s10g + yFrac0*s11g
  5029  			s11b = yFrac1*s10b + yFrac0*s11b
  5030  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  5053  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  5111  			s10g = xFrac1*s00g + xFrac0*s10g
  5112  			s10b = xFrac1*s00b + xFrac0*s10b
  5113  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  5139  			s11g = xFrac1*s01g + xFrac0*s11g
  5140  			s11b = xFrac1*s01b + xFrac0*s11b
  5141  			s11a = xFrac1*s01a + xFrac0*s11a
  5142  			s11r = yFrac1*s10r + yFrac0*s11r
  5143  			s11g = yFrac1*s10g + yFrac0*s11g
  5144  			s11b = yFrac1*s10b + yFrac0*s11b
  5145  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  5175  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  5233  			s10g = xFrac1*s00g + xFrac0*s10g
  5234  			s10b = xFrac1*s00b + xFrac0*s10b
  5235  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  5261  			s11g = xFrac1*s01g + xFrac0*s11g
  5262  			s11b = xFrac1*s01b + xFrac0*s11b
  5263  			s11a = xFrac1*s01a + xFrac0*s11a
  5264  			s11r = yFrac1*s10r + yFrac0*s11r
  5265  			s11g = yFrac1*s10g + yFrac0*s11g
  5266  			s11b = yFrac1*s10b + yFrac0*s11b
  5267  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  5299  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  5357  			s10g = xFrac1*s00g + xFrac0*s10g
  5358  			s10b = xFrac1*s00b + xFrac0*s10b
  5359  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  5385  			s11g = xFrac1*s01g + xFrac0*s11g
  5386  			s11b = xFrac1*s01b + xFrac0*s11b
  5387  			s11a = xFrac1*s01a + xFrac0*s11a
  5388  			s11r = yFrac1*s10r + yFrac0*s11r
  5389  			s11g = yFrac1*s10g + yFrac0*s11g
  5390  			s11b = yFrac1*s10b + yFrac0*s11b
  5391  			s11a = yFrac1*s10a + 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  5424  			sy := d2s[3]*dxf + 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 = xFrac1*s00r + xFrac0*s10r
  5482  			s10g = xFrac1*s00g + xFrac0*s10g
  5483  			s10b = xFrac1*s00b + xFrac0*s10b
  5484  			s10a = xFrac1*s00a + 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 = xFrac1*s01r + xFrac0*s11r
  5510  			s11g = xFrac1*s01g + xFrac0*s11g
  5511  			s11b = xFrac1*s01b + xFrac0*s11b
  5512  			s11a = xFrac1*s01a + xFrac0*s11a
  5513  			s11r = yFrac1*s10r + yFrac0*s11r
  5514  			s11g = yFrac1*s10g + yFrac0*s11g
  5515  			s11b = yFrac1*s10b + yFrac0*s11b
  5516  			s11a = yFrac1*s10a + 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(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(pru) * c.weight
  5812  				pg += float64(pgu) * c.weight
  5813  				pb += float64(pbu) * c.weight
  5814  				pa += 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(pru) * c.weight
  5839  				pg += float64(pgu) * c.weight
  5840  				pb += float64(pbu) * c.weight
  5841  				pa += 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(pru) * c.weight
  5887  				pg += float64(pgu) * c.weight
  5888  				pb += 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(pru) * c.weight
  5934  				pg += float64(pgu) * c.weight
  5935  				pb += 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(pru) * c.weight
  5981  				pg += float64(pgu) * c.weight
  5982  				pb += 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(pru) * c.weight
  6028  				pg += float64(pgu) * c.weight
  6029  				pb += 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(pu.R) * c.weight
  6058  				pg += float64(pu.G) * c.weight
  6059  				pb += float64(pu.B) * c.weight
  6060  				pa += 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(pru) * c.weight
  6089  				pg += float64(pgu) * c.weight
  6090  				pb += float64(pbu) * c.weight
  6091  				pa += 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 += p[0] * c.weight
  6112  				pg += p[1] * c.weight
  6113  				pb += p[2] * c.weight
  6114  				pa += 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 += p[0] * c.weight
  6149  				pg += p[1] * c.weight
  6150  				pb += p[2] * c.weight
  6151  				pa += 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 += p[0] * c.weight
  6183  				pg += p[1] * c.weight
  6184  				pb += p[2] * c.weight
  6185  				pa += 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 += p[0] * c.weight
  6230  				pg += p[1] * c.weight
  6231  				pb += p[2] * c.weight
  6232  				pa += 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 += p[0] * c.weight
  6279  				pg += p[1] * c.weight
  6280  				pb += p[2] * c.weight
  6281  				pa += 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 += p[0] * c.weight
  6326  				pg += p[1] * c.weight
  6327  				pb += p[2] * c.weight
  6328  				pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  6388  			sy := d2s[3]*dxf + 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(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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  6487  			sy := d2s[3]*dxf + 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(pru) * w
  6553  							pg += float64(pgu) * w
  6554  							pb += float64(pbu) * w
  6555  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  6607  			sy := d2s[3]*dxf + 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(pru) * w
  6673  							pg += float64(pgu) * w
  6674  							pb += float64(pbu) * w
  6675  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  6722  			sy := d2s[3]*dxf + 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(pru) * w
  6788  							pg += float64(pgu) * w
  6789  							pb += float64(pbu) * w
  6790  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  6842  			sy := d2s[3]*dxf + 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(pru) * w
  6908  							pg += float64(pgu) * w
  6909  							pb += float64(pbu) * w
  6910  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  6957  			sy := d2s[3]*dxf + 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(pru) * w
  7044  							pg += float64(pgu) * w
  7045  							pb += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7081  			sy := d2s[3]*dxf + 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(pru) * w
  7168  							pg += float64(pgu) * w
  7169  							pb += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7205  			sy := d2s[3]*dxf + 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(pru) * w
  7292  							pg += float64(pgu) * w
  7293  							pb += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7329  			sy := d2s[3]*dxf + 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(pru) * w
  7416  							pg += float64(pgu) * w
  7417  							pb += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7453  			sy := d2s[3]*dxf + 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(pu.R) * w
  7515  							pg += float64(pu.G) * w
  7516  							pb += float64(pu.B) * w
  7517  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7569  			sy := d2s[3]*dxf + 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(pu.R) * w
  7631  							pg += float64(pu.G) * w
  7632  							pb += float64(pu.B) * w
  7633  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7680  			sy := d2s[3]*dxf + 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(pru) * w
  7742  							pg += float64(pgu) * w
  7743  							pb += float64(pbu) * w
  7744  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7796  			sy := d2s[3]*dxf + 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(pru) * w
  7858  							pg += float64(pgu) * w
  7859  							pb += float64(pbu) * w
  7860  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  7910  			sy := d2s[3]*dxf + 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(pu.R) * w
  7979  							pg += float64(pu.G) * w
  7980  							pb += float64(pu.B) * w
  7981  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  8045  			sy := d2s[3]*dxf + 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(pu.R) * w
  8114  							pg += float64(pu.G) * w
  8115  							pb += float64(pu.B) * w
  8116  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  8182  			sy := d2s[3]*dxf + 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(pru) * w
  8251  							pg += float64(pgu) * w
  8252  							pb += float64(pbu) * w
  8253  							pa += 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 := d2s[0]*dxf + d2s[1]*dyf + d2s[2]
  8317  			sy := d2s[3]*dxf + 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(pru) * w
  8386  							pg += float64(pgu) * w
  8387  							pb += float64(pbu) * w
  8388  							pa += 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  }
  8427  

View as plain text