github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/image/draw/impl.go (about) 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. 15 if dr.Size() == sr.Size() { 16 Copy(dst, dr.Min, src, sr, op, opts) 17 return 18 } 19 20 var o Options 21 if opts != nil { 22 o = *opts 23 } 24 25 // adr is the affected destination pixels. 26 adr := dst.Bounds().Intersect(dr) 27 adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP) 28 if adr.Empty() || sr.Empty() { 29 return 30 } 31 // Make adr relative to dr.Min. 32 adr = adr.Sub(dr.Min) 33 if op == Over && o.SrcMask == nil && opaque(src) { 34 op = Src 35 } 36 37 // sr is the source pixels. If it extends beyond the src bounds, 38 // we cannot use the type-specific fast paths, as they access 39 // the Pix fields directly without bounds checking. 40 // 41 // Similarly, the fast paths assume that the masks are nil. 42 if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) { 43 switch op { 44 case Over: 45 z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o) 46 case Src: 47 z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o) 48 } 49 } else if _, ok := src.(*image.Uniform); ok { 50 Draw(dst, dr, src, src.Bounds().Min, op) 51 } else { 52 switch op { 53 case Over: 54 switch dst := dst.(type) { 55 case *image.RGBA: 56 switch src := src.(type) { 57 case *image.NRGBA: 58 z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o) 59 case *image.RGBA: 60 z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o) 61 default: 62 z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o) 63 } 64 default: 65 switch src := src.(type) { 66 default: 67 z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o) 68 } 69 } 70 case Src: 71 switch dst := dst.(type) { 72 case *image.RGBA: 73 switch src := src.(type) { 74 case *image.Gray: 75 z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o) 76 case *image.NRGBA: 77 z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o) 78 case *image.RGBA: 79 z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o) 80 case *image.YCbCr: 81 switch src.SubsampleRatio { 82 default: 83 z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o) 84 case image.YCbCrSubsampleRatio444: 85 z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o) 86 case image.YCbCrSubsampleRatio422: 87 z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o) 88 case image.YCbCrSubsampleRatio420: 89 z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o) 90 case image.YCbCrSubsampleRatio440: 91 z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o) 92 } 93 default: 94 z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o) 95 } 96 default: 97 switch src := src.(type) { 98 default: 99 z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o) 100 } 101 } 102 } 103 } 104 } 105 106 func (z nnInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) { 107 // Try to simplify a Transform to a Copy. 108 if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 { 109 dx := int(s2d[2]) 110 dy := int(s2d[5]) 111 if float64(dx) == s2d[2] && float64(dy) == s2d[5] { 112 Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts) 113 return 114 } 115 } 116 117 var o Options 118 if opts != nil { 119 o = *opts 120 } 121 122 dr := transformRect(&s2d, &sr) 123 // adr is the affected destination pixels. 124 adr := dst.Bounds().Intersect(dr) 125 adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP) 126 if adr.Empty() || sr.Empty() { 127 return 128 } 129 if op == Over && o.SrcMask == nil && opaque(src) { 130 op = Src 131 } 132 133 d2s := invert(&s2d) 134 // bias is a translation of the mapping from dst coordinates to src 135 // coordinates such that the latter temporarily have non-negative X 136 // and Y coordinates. This allows us to write int(f) instead of 137 // int(math.Floor(f)), since "round to zero" and "round down" are 138 // equivalent when f >= 0, but the former is much cheaper. The X-- 139 // and Y-- are because the TransformLeaf methods have a "sx -= 0.5" 140 // adjustment. 141 bias := transformRect(&d2s, &adr).Min 142 bias.X-- 143 bias.Y-- 144 d2s[2] -= float64(bias.X) 145 d2s[5] -= float64(bias.Y) 146 // Make adr relative to dr.Min. 147 adr = adr.Sub(dr.Min) 148 // sr is the source pixels. If it extends beyond the src bounds, 149 // we cannot use the type-specific fast paths, as they access 150 // the Pix fields directly without bounds checking. 151 // 152 // Similarly, the fast paths assume that the masks are nil. 153 if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) { 154 switch op { 155 case Over: 156 z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 157 case Src: 158 z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 159 } 160 } else if u, ok := src.(*image.Uniform); ok { 161 transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op) 162 } else { 163 switch op { 164 case Over: 165 switch dst := dst.(type) { 166 case *image.RGBA: 167 switch src := src.(type) { 168 case *image.NRGBA: 169 z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 170 case *image.RGBA: 171 z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 172 default: 173 z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 174 } 175 default: 176 switch src := src.(type) { 177 default: 178 z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 179 } 180 } 181 case Src: 182 switch dst := dst.(type) { 183 case *image.RGBA: 184 switch src := src.(type) { 185 case *image.Gray: 186 z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 187 case *image.NRGBA: 188 z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 189 case *image.RGBA: 190 z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 191 case *image.YCbCr: 192 switch src.SubsampleRatio { 193 default: 194 z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 195 case image.YCbCrSubsampleRatio444: 196 z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 197 case image.YCbCrSubsampleRatio422: 198 z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 199 case image.YCbCrSubsampleRatio420: 200 z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 201 case image.YCbCrSubsampleRatio440: 202 z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 203 } 204 default: 205 z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 206 } 207 default: 208 switch src := src.(type) { 209 default: 210 z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 211 } 212 } 213 } 214 } 215 } 216 217 func (nnInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) { 218 dw2 := uint64(dr.Dx()) * 2 219 dh2 := uint64(dr.Dy()) * 2 220 sw := uint64(sr.Dx()) 221 sh := uint64(sr.Dy()) 222 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 223 sy := (2*uint64(dy) + 1) * sh / dh2 224 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 225 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 226 sx := (2*uint64(dx) + 1) * sw / dw2 227 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx) - src.Rect.Min.X) 228 pr := uint32(src.Pix[pi]) * 0x101 229 out := uint8(pr >> 8) 230 dst.Pix[d+0] = out 231 dst.Pix[d+1] = out 232 dst.Pix[d+2] = out 233 dst.Pix[d+3] = 0xff 234 } 235 } 236 } 237 238 func (nnInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) { 239 dw2 := uint64(dr.Dx()) * 2 240 dh2 := uint64(dr.Dy()) * 2 241 sw := uint64(sr.Dx()) 242 sh := uint64(sr.Dy()) 243 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 244 sy := (2*uint64(dy) + 1) * sh / dh2 245 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 246 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 247 sx := (2*uint64(dx) + 1) * sw / dw2 248 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4 249 pa := uint32(src.Pix[pi+3]) * 0x101 250 pr := uint32(src.Pix[pi+0]) * pa / 0xff 251 pg := uint32(src.Pix[pi+1]) * pa / 0xff 252 pb := uint32(src.Pix[pi+2]) * pa / 0xff 253 pa1 := (0xffff - pa) * 0x101 254 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 255 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 256 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 257 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 258 } 259 } 260 } 261 262 func (nnInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) { 263 dw2 := uint64(dr.Dx()) * 2 264 dh2 := uint64(dr.Dy()) * 2 265 sw := uint64(sr.Dx()) 266 sh := uint64(sr.Dy()) 267 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 268 sy := (2*uint64(dy) + 1) * sh / dh2 269 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 270 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 271 sx := (2*uint64(dx) + 1) * sw / dw2 272 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4 273 pa := uint32(src.Pix[pi+3]) * 0x101 274 pr := uint32(src.Pix[pi+0]) * pa / 0xff 275 pg := uint32(src.Pix[pi+1]) * pa / 0xff 276 pb := uint32(src.Pix[pi+2]) * pa / 0xff 277 dst.Pix[d+0] = uint8(pr >> 8) 278 dst.Pix[d+1] = uint8(pg >> 8) 279 dst.Pix[d+2] = uint8(pb >> 8) 280 dst.Pix[d+3] = uint8(pa >> 8) 281 } 282 } 283 } 284 285 func (nnInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) { 286 dw2 := uint64(dr.Dx()) * 2 287 dh2 := uint64(dr.Dy()) * 2 288 sw := uint64(sr.Dx()) 289 sh := uint64(sr.Dy()) 290 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 291 sy := (2*uint64(dy) + 1) * sh / dh2 292 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 293 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 294 sx := (2*uint64(dx) + 1) * sw / dw2 295 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4 296 pr := uint32(src.Pix[pi+0]) * 0x101 297 pg := uint32(src.Pix[pi+1]) * 0x101 298 pb := uint32(src.Pix[pi+2]) * 0x101 299 pa := uint32(src.Pix[pi+3]) * 0x101 300 pa1 := (0xffff - pa) * 0x101 301 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 302 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 303 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 304 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 305 } 306 } 307 } 308 309 func (nnInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) { 310 dw2 := uint64(dr.Dx()) * 2 311 dh2 := uint64(dr.Dy()) * 2 312 sw := uint64(sr.Dx()) 313 sh := uint64(sr.Dy()) 314 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 315 sy := (2*uint64(dy) + 1) * sh / dh2 316 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 317 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 318 sx := (2*uint64(dx) + 1) * sw / dw2 319 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx)-src.Rect.Min.X)*4 320 pr := uint32(src.Pix[pi+0]) * 0x101 321 pg := uint32(src.Pix[pi+1]) * 0x101 322 pb := uint32(src.Pix[pi+2]) * 0x101 323 pa := uint32(src.Pix[pi+3]) * 0x101 324 dst.Pix[d+0] = uint8(pr >> 8) 325 dst.Pix[d+1] = uint8(pg >> 8) 326 dst.Pix[d+2] = uint8(pb >> 8) 327 dst.Pix[d+3] = uint8(pa >> 8) 328 } 329 } 330 } 331 332 func (nnInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 333 dw2 := uint64(dr.Dx()) * 2 334 dh2 := uint64(dr.Dy()) * 2 335 sw := uint64(sr.Dx()) 336 sh := uint64(sr.Dy()) 337 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 338 sy := (2*uint64(dy) + 1) * sh / dh2 339 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 340 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 341 sx := (2*uint64(dx) + 1) * sw / dw2 342 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X) 343 pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X) 344 345 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 346 pyy1 := int(src.Y[pi]) * 0x10100 347 pcb1 := int(src.Cb[pj]) - 128 348 pcr1 := int(src.Cr[pj]) - 128 349 pr := (pyy1 + 91881*pcr1) >> 8 350 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 351 pb := (pyy1 + 116130*pcb1) >> 8 352 if pr < 0 { 353 pr = 0 354 } else if pr > 0xffff { 355 pr = 0xffff 356 } 357 if pg < 0 { 358 pg = 0 359 } else if pg > 0xffff { 360 pg = 0xffff 361 } 362 if pb < 0 { 363 pb = 0 364 } else if pb > 0xffff { 365 pb = 0xffff 366 } 367 dst.Pix[d+0] = uint8(pr >> 8) 368 dst.Pix[d+1] = uint8(pg >> 8) 369 dst.Pix[d+2] = uint8(pb >> 8) 370 dst.Pix[d+3] = 0xff 371 } 372 } 373 } 374 375 func (nnInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 376 dw2 := uint64(dr.Dx()) * 2 377 dh2 := uint64(dr.Dy()) * 2 378 sw := uint64(sr.Dx()) 379 sh := uint64(sr.Dy()) 380 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 381 sy := (2*uint64(dy) + 1) * sh / dh2 382 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 383 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 384 sx := (2*uint64(dx) + 1) * sw / dw2 385 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X) 386 pj := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx))/2 - src.Rect.Min.X/2) 387 388 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 389 pyy1 := int(src.Y[pi]) * 0x10100 390 pcb1 := int(src.Cb[pj]) - 128 391 pcr1 := int(src.Cr[pj]) - 128 392 pr := (pyy1 + 91881*pcr1) >> 8 393 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 394 pb := (pyy1 + 116130*pcb1) >> 8 395 if pr < 0 { 396 pr = 0 397 } else if pr > 0xffff { 398 pr = 0xffff 399 } 400 if pg < 0 { 401 pg = 0 402 } else if pg > 0xffff { 403 pg = 0xffff 404 } 405 if pb < 0 { 406 pb = 0 407 } else if pb > 0xffff { 408 pb = 0xffff 409 } 410 dst.Pix[d+0] = uint8(pr >> 8) 411 dst.Pix[d+1] = uint8(pg >> 8) 412 dst.Pix[d+2] = uint8(pb >> 8) 413 dst.Pix[d+3] = 0xff 414 } 415 } 416 } 417 418 func (nnInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 419 dw2 := uint64(dr.Dx()) * 2 420 dh2 := uint64(dr.Dy()) * 2 421 sw := uint64(sr.Dx()) 422 sh := uint64(sr.Dy()) 423 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 424 sy := (2*uint64(dy) + 1) * sh / dh2 425 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 426 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 427 sx := (2*uint64(dx) + 1) * sw / dw2 428 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X) 429 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) 430 431 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 432 pyy1 := int(src.Y[pi]) * 0x10100 433 pcb1 := int(src.Cb[pj]) - 128 434 pcr1 := int(src.Cr[pj]) - 128 435 pr := (pyy1 + 91881*pcr1) >> 8 436 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 437 pb := (pyy1 + 116130*pcb1) >> 8 438 if pr < 0 { 439 pr = 0 440 } else if pr > 0xffff { 441 pr = 0xffff 442 } 443 if pg < 0 { 444 pg = 0 445 } else if pg > 0xffff { 446 pg = 0xffff 447 } 448 if pb < 0 { 449 pb = 0 450 } else if pb > 0xffff { 451 pb = 0xffff 452 } 453 dst.Pix[d+0] = uint8(pr >> 8) 454 dst.Pix[d+1] = uint8(pg >> 8) 455 dst.Pix[d+2] = uint8(pb >> 8) 456 dst.Pix[d+3] = 0xff 457 } 458 } 459 } 460 461 func (nnInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 462 dw2 := uint64(dr.Dx()) * 2 463 dh2 := uint64(dr.Dy()) * 2 464 sw := uint64(sr.Dx()) 465 sh := uint64(sr.Dy()) 466 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 467 sy := (2*uint64(dy) + 1) * sh / dh2 468 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 469 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 470 sx := (2*uint64(dx) + 1) * sw / dw2 471 pi := (sr.Min.Y+int(sy)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx) - src.Rect.Min.X) 472 pj := ((sr.Min.Y+int(sy))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx) - src.Rect.Min.X) 473 474 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 475 pyy1 := int(src.Y[pi]) * 0x10100 476 pcb1 := int(src.Cb[pj]) - 128 477 pcr1 := int(src.Cr[pj]) - 128 478 pr := (pyy1 + 91881*pcr1) >> 8 479 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 480 pb := (pyy1 + 116130*pcb1) >> 8 481 if pr < 0 { 482 pr = 0 483 } else if pr > 0xffff { 484 pr = 0xffff 485 } 486 if pg < 0 { 487 pg = 0 488 } else if pg > 0xffff { 489 pg = 0xffff 490 } 491 if pb < 0 { 492 pb = 0 493 } else if pb > 0xffff { 494 pb = 0xffff 495 } 496 dst.Pix[d+0] = uint8(pr >> 8) 497 dst.Pix[d+1] = uint8(pg >> 8) 498 dst.Pix[d+2] = uint8(pb >> 8) 499 dst.Pix[d+3] = 0xff 500 } 501 } 502 } 503 504 func (nnInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 505 dw2 := uint64(dr.Dx()) * 2 506 dh2 := uint64(dr.Dy()) * 2 507 sw := uint64(sr.Dx()) 508 sh := uint64(sr.Dy()) 509 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 510 sy := (2*uint64(dy) + 1) * sh / dh2 511 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 512 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 513 sx := (2*uint64(dx) + 1) * sw / dw2 514 pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA() 515 pa1 := (0xffff - pa) * 0x101 516 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 517 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 518 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 519 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 520 } 521 } 522 } 523 524 func (nnInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 525 dw2 := uint64(dr.Dx()) * 2 526 dh2 := uint64(dr.Dy()) * 2 527 sw := uint64(sr.Dx()) 528 sh := uint64(sr.Dy()) 529 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 530 sy := (2*uint64(dy) + 1) * sh / dh2 531 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 532 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 533 sx := (2*uint64(dx) + 1) * sw / dw2 534 pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA() 535 dst.Pix[d+0] = uint8(pr >> 8) 536 dst.Pix[d+1] = uint8(pg >> 8) 537 dst.Pix[d+2] = uint8(pb >> 8) 538 dst.Pix[d+3] = uint8(pa >> 8) 539 } 540 } 541 } 542 543 func (nnInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 544 dw2 := uint64(dr.Dx()) * 2 545 dh2 := uint64(dr.Dy()) * 2 546 sw := uint64(sr.Dx()) 547 sh := uint64(sr.Dy()) 548 srcMask, smp := opts.SrcMask, opts.SrcMaskP 549 dstMask, dmp := opts.DstMask, opts.DstMaskP 550 dstColorRGBA64 := &color.RGBA64{} 551 dstColor := color.Color(dstColorRGBA64) 552 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 553 sy := (2*uint64(dy) + 1) * sh / dh2 554 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 555 sx := (2*uint64(dx) + 1) * sw / dw2 556 pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA() 557 if srcMask != nil { 558 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA() 559 pr = pr * ma / 0xffff 560 pg = pg * ma / 0xffff 561 pb = pb * ma / 0xffff 562 pa = pa * ma / 0xffff 563 } 564 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 565 if dstMask != nil { 566 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 567 pr = pr * ma / 0xffff 568 pg = pg * ma / 0xffff 569 pb = pb * ma / 0xffff 570 pa = pa * ma / 0xffff 571 } 572 pa1 := 0xffff - pa 573 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 574 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 575 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 576 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 577 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 578 } 579 } 580 } 581 582 func (nnInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 583 dw2 := uint64(dr.Dx()) * 2 584 dh2 := uint64(dr.Dy()) * 2 585 sw := uint64(sr.Dx()) 586 sh := uint64(sr.Dy()) 587 srcMask, smp := opts.SrcMask, opts.SrcMaskP 588 dstMask, dmp := opts.DstMask, opts.DstMaskP 589 dstColorRGBA64 := &color.RGBA64{} 590 dstColor := color.Color(dstColorRGBA64) 591 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 592 sy := (2*uint64(dy) + 1) * sh / dh2 593 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 594 sx := (2*uint64(dx) + 1) * sw / dw2 595 pr, pg, pb, pa := src.At(sr.Min.X+int(sx), sr.Min.Y+int(sy)).RGBA() 596 if srcMask != nil { 597 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx), smp.Y+sr.Min.Y+int(sy)).RGBA() 598 pr = pr * ma / 0xffff 599 pg = pg * ma / 0xffff 600 pb = pb * ma / 0xffff 601 pa = pa * ma / 0xffff 602 } 603 if dstMask != nil { 604 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 605 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 606 pr = pr * ma / 0xffff 607 pg = pg * ma / 0xffff 608 pb = pb * ma / 0xffff 609 pa = pa * ma / 0xffff 610 pa1 := 0xffff - ma 611 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 612 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 613 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 614 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 615 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 616 } else { 617 dstColorRGBA64.R = uint16(pr) 618 dstColorRGBA64.G = uint16(pg) 619 dstColorRGBA64.B = uint16(pb) 620 dstColorRGBA64.A = uint16(pa) 621 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 622 } 623 } 624 } 625 } 626 627 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) { 628 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 629 dyf := float64(dr.Min.Y+int(dy)) + 0.5 630 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 631 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 632 dxf := float64(dr.Min.X+int(dx)) + 0.5 633 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 634 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 635 if !(image.Point{sx0, sy0}).In(sr) { 636 continue 637 } 638 pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X) 639 pr := uint32(src.Pix[pi]) * 0x101 640 out := uint8(pr >> 8) 641 dst.Pix[d+0] = out 642 dst.Pix[d+1] = out 643 dst.Pix[d+2] = out 644 dst.Pix[d+3] = 0xff 645 } 646 } 647 } 648 649 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) { 650 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 651 dyf := float64(dr.Min.Y+int(dy)) + 0.5 652 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 653 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 654 dxf := float64(dr.Min.X+int(dx)) + 0.5 655 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 656 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 657 if !(image.Point{sx0, sy0}).In(sr) { 658 continue 659 } 660 pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 661 pa := uint32(src.Pix[pi+3]) * 0x101 662 pr := uint32(src.Pix[pi+0]) * pa / 0xff 663 pg := uint32(src.Pix[pi+1]) * pa / 0xff 664 pb := uint32(src.Pix[pi+2]) * pa / 0xff 665 pa1 := (0xffff - pa) * 0x101 666 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 667 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 668 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 669 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 670 } 671 } 672 } 673 674 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) { 675 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 676 dyf := float64(dr.Min.Y+int(dy)) + 0.5 677 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 678 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 679 dxf := float64(dr.Min.X+int(dx)) + 0.5 680 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 681 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 682 if !(image.Point{sx0, sy0}).In(sr) { 683 continue 684 } 685 pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 686 pa := uint32(src.Pix[pi+3]) * 0x101 687 pr := uint32(src.Pix[pi+0]) * pa / 0xff 688 pg := uint32(src.Pix[pi+1]) * pa / 0xff 689 pb := uint32(src.Pix[pi+2]) * pa / 0xff 690 dst.Pix[d+0] = uint8(pr >> 8) 691 dst.Pix[d+1] = uint8(pg >> 8) 692 dst.Pix[d+2] = uint8(pb >> 8) 693 dst.Pix[d+3] = uint8(pa >> 8) 694 } 695 } 696 } 697 698 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) { 699 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 700 dyf := float64(dr.Min.Y+int(dy)) + 0.5 701 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 702 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 703 dxf := float64(dr.Min.X+int(dx)) + 0.5 704 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 705 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 706 if !(image.Point{sx0, sy0}).In(sr) { 707 continue 708 } 709 pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 710 pr := uint32(src.Pix[pi+0]) * 0x101 711 pg := uint32(src.Pix[pi+1]) * 0x101 712 pb := uint32(src.Pix[pi+2]) * 0x101 713 pa := uint32(src.Pix[pi+3]) * 0x101 714 pa1 := (0xffff - pa) * 0x101 715 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 716 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 717 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 718 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 719 } 720 } 721 } 722 723 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) { 724 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 725 dyf := float64(dr.Min.Y+int(dy)) + 0.5 726 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 727 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 728 dxf := float64(dr.Min.X+int(dx)) + 0.5 729 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 730 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 731 if !(image.Point{sx0, sy0}).In(sr) { 732 continue 733 } 734 pi := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 735 pr := uint32(src.Pix[pi+0]) * 0x101 736 pg := uint32(src.Pix[pi+1]) * 0x101 737 pb := uint32(src.Pix[pi+2]) * 0x101 738 pa := uint32(src.Pix[pi+3]) * 0x101 739 dst.Pix[d+0] = uint8(pr >> 8) 740 dst.Pix[d+1] = uint8(pg >> 8) 741 dst.Pix[d+2] = uint8(pb >> 8) 742 dst.Pix[d+3] = uint8(pa >> 8) 743 } 744 } 745 } 746 747 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) { 748 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 749 dyf := float64(dr.Min.Y+int(dy)) + 0.5 750 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 751 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 752 dxf := float64(dr.Min.X+int(dx)) + 0.5 753 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 754 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 755 if !(image.Point{sx0, sy0}).In(sr) { 756 continue 757 } 758 pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 759 pj := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X) 760 761 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 762 pyy1 := int(src.Y[pi]) * 0x10100 763 pcb1 := int(src.Cb[pj]) - 128 764 pcr1 := int(src.Cr[pj]) - 128 765 pr := (pyy1 + 91881*pcr1) >> 8 766 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 767 pb := (pyy1 + 116130*pcb1) >> 8 768 if pr < 0 { 769 pr = 0 770 } else if pr > 0xffff { 771 pr = 0xffff 772 } 773 if pg < 0 { 774 pg = 0 775 } else if pg > 0xffff { 776 pg = 0xffff 777 } 778 if pb < 0 { 779 pb = 0 780 } else if pb > 0xffff { 781 pb = 0xffff 782 } 783 dst.Pix[d+0] = uint8(pr >> 8) 784 dst.Pix[d+1] = uint8(pg >> 8) 785 dst.Pix[d+2] = uint8(pb >> 8) 786 dst.Pix[d+3] = 0xff 787 } 788 } 789 } 790 791 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) { 792 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 793 dyf := float64(dr.Min.Y+int(dy)) + 0.5 794 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 795 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 796 dxf := float64(dr.Min.X+int(dx)) + 0.5 797 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 798 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 799 if !(image.Point{sx0, sy0}).In(sr) { 800 continue 801 } 802 pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 803 pj := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2) 804 805 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 806 pyy1 := int(src.Y[pi]) * 0x10100 807 pcb1 := int(src.Cb[pj]) - 128 808 pcr1 := int(src.Cr[pj]) - 128 809 pr := (pyy1 + 91881*pcr1) >> 8 810 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 811 pb := (pyy1 + 116130*pcb1) >> 8 812 if pr < 0 { 813 pr = 0 814 } else if pr > 0xffff { 815 pr = 0xffff 816 } 817 if pg < 0 { 818 pg = 0 819 } else if pg > 0xffff { 820 pg = 0xffff 821 } 822 if pb < 0 { 823 pb = 0 824 } else if pb > 0xffff { 825 pb = 0xffff 826 } 827 dst.Pix[d+0] = uint8(pr >> 8) 828 dst.Pix[d+1] = uint8(pg >> 8) 829 dst.Pix[d+2] = uint8(pb >> 8) 830 dst.Pix[d+3] = 0xff 831 } 832 } 833 } 834 835 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) { 836 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 837 dyf := float64(dr.Min.Y+int(dy)) + 0.5 838 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 839 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 840 dxf := float64(dr.Min.X+int(dx)) + 0.5 841 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 842 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 843 if !(image.Point{sx0, sy0}).In(sr) { 844 continue 845 } 846 pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 847 pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2) 848 849 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 850 pyy1 := int(src.Y[pi]) * 0x10100 851 pcb1 := int(src.Cb[pj]) - 128 852 pcr1 := int(src.Cr[pj]) - 128 853 pr := (pyy1 + 91881*pcr1) >> 8 854 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 855 pb := (pyy1 + 116130*pcb1) >> 8 856 if pr < 0 { 857 pr = 0 858 } else if pr > 0xffff { 859 pr = 0xffff 860 } 861 if pg < 0 { 862 pg = 0 863 } else if pg > 0xffff { 864 pg = 0xffff 865 } 866 if pb < 0 { 867 pb = 0 868 } else if pb > 0xffff { 869 pb = 0xffff 870 } 871 dst.Pix[d+0] = uint8(pr >> 8) 872 dst.Pix[d+1] = uint8(pg >> 8) 873 dst.Pix[d+2] = uint8(pb >> 8) 874 dst.Pix[d+3] = 0xff 875 } 876 } 877 } 878 879 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) { 880 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 881 dyf := float64(dr.Min.Y+int(dy)) + 0.5 882 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 883 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 884 dxf := float64(dr.Min.X+int(dx)) + 0.5 885 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 886 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 887 if !(image.Point{sx0, sy0}).In(sr) { 888 continue 889 } 890 pi := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 891 pj := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X) 892 893 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 894 pyy1 := int(src.Y[pi]) * 0x10100 895 pcb1 := int(src.Cb[pj]) - 128 896 pcr1 := int(src.Cr[pj]) - 128 897 pr := (pyy1 + 91881*pcr1) >> 8 898 pg := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 899 pb := (pyy1 + 116130*pcb1) >> 8 900 if pr < 0 { 901 pr = 0 902 } else if pr > 0xffff { 903 pr = 0xffff 904 } 905 if pg < 0 { 906 pg = 0 907 } else if pg > 0xffff { 908 pg = 0xffff 909 } 910 if pb < 0 { 911 pb = 0 912 } else if pb > 0xffff { 913 pb = 0xffff 914 } 915 dst.Pix[d+0] = uint8(pr >> 8) 916 dst.Pix[d+1] = uint8(pg >> 8) 917 dst.Pix[d+2] = uint8(pb >> 8) 918 dst.Pix[d+3] = 0xff 919 } 920 } 921 } 922 923 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) { 924 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 925 dyf := float64(dr.Min.Y+int(dy)) + 0.5 926 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 927 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 928 dxf := float64(dr.Min.X+int(dx)) + 0.5 929 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 930 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 931 if !(image.Point{sx0, sy0}).In(sr) { 932 continue 933 } 934 pr, pg, pb, pa := src.At(sx0, sy0).RGBA() 935 pa1 := (0xffff - pa) * 0x101 936 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 937 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 938 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 939 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 940 } 941 } 942 } 943 944 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) { 945 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 946 dyf := float64(dr.Min.Y+int(dy)) + 0.5 947 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 948 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 949 dxf := float64(dr.Min.X+int(dx)) + 0.5 950 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 951 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 952 if !(image.Point{sx0, sy0}).In(sr) { 953 continue 954 } 955 pr, pg, pb, pa := src.At(sx0, sy0).RGBA() 956 dst.Pix[d+0] = uint8(pr >> 8) 957 dst.Pix[d+1] = uint8(pg >> 8) 958 dst.Pix[d+2] = uint8(pb >> 8) 959 dst.Pix[d+3] = uint8(pa >> 8) 960 } 961 } 962 } 963 964 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) { 965 srcMask, smp := opts.SrcMask, opts.SrcMaskP 966 dstMask, dmp := opts.DstMask, opts.DstMaskP 967 dstColorRGBA64 := &color.RGBA64{} 968 dstColor := color.Color(dstColorRGBA64) 969 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 970 dyf := float64(dr.Min.Y+int(dy)) + 0.5 971 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 972 dxf := float64(dr.Min.X+int(dx)) + 0.5 973 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 974 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 975 if !(image.Point{sx0, sy0}).In(sr) { 976 continue 977 } 978 pr, pg, pb, pa := src.At(sx0, sy0).RGBA() 979 if srcMask != nil { 980 _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA() 981 pr = pr * ma / 0xffff 982 pg = pg * ma / 0xffff 983 pb = pb * ma / 0xffff 984 pa = pa * ma / 0xffff 985 } 986 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 987 if dstMask != nil { 988 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 989 pr = pr * ma / 0xffff 990 pg = pg * ma / 0xffff 991 pb = pb * ma / 0xffff 992 pa = pa * ma / 0xffff 993 } 994 pa1 := 0xffff - pa 995 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 996 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 997 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 998 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 999 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 1000 } 1001 } 1002 } 1003 1004 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) { 1005 srcMask, smp := opts.SrcMask, opts.SrcMaskP 1006 dstMask, dmp := opts.DstMask, opts.DstMaskP 1007 dstColorRGBA64 := &color.RGBA64{} 1008 dstColor := color.Color(dstColorRGBA64) 1009 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1010 dyf := float64(dr.Min.Y+int(dy)) + 0.5 1011 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 1012 dxf := float64(dr.Min.X+int(dx)) + 0.5 1013 sx0 := int(d2s[0]*dxf+d2s[1]*dyf+d2s[2]) + bias.X 1014 sy0 := int(d2s[3]*dxf+d2s[4]*dyf+d2s[5]) + bias.Y 1015 if !(image.Point{sx0, sy0}).In(sr) { 1016 continue 1017 } 1018 pr, pg, pb, pa := src.At(sx0, sy0).RGBA() 1019 if srcMask != nil { 1020 _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA() 1021 pr = pr * ma / 0xffff 1022 pg = pg * ma / 0xffff 1023 pb = pb * ma / 0xffff 1024 pa = pa * ma / 0xffff 1025 } 1026 if dstMask != nil { 1027 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 1028 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 1029 pr = pr * ma / 0xffff 1030 pg = pg * ma / 0xffff 1031 pb = pb * ma / 0xffff 1032 pa = pa * ma / 0xffff 1033 pa1 := 0xffff - ma 1034 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 1035 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 1036 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 1037 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 1038 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 1039 } else { 1040 dstColorRGBA64.R = uint16(pr) 1041 dstColorRGBA64.G = uint16(pg) 1042 dstColorRGBA64.B = uint16(pb) 1043 dstColorRGBA64.A = uint16(pa) 1044 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 1045 } 1046 } 1047 } 1048 } 1049 1050 func (z ablInterpolator) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) { 1051 // Try to simplify a Scale to a Copy. 1052 if dr.Size() == sr.Size() { 1053 Copy(dst, dr.Min, src, sr, op, opts) 1054 return 1055 } 1056 1057 var o Options 1058 if opts != nil { 1059 o = *opts 1060 } 1061 1062 // adr is the affected destination pixels. 1063 adr := dst.Bounds().Intersect(dr) 1064 adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP) 1065 if adr.Empty() || sr.Empty() { 1066 return 1067 } 1068 // Make adr relative to dr.Min. 1069 adr = adr.Sub(dr.Min) 1070 if op == Over && o.SrcMask == nil && opaque(src) { 1071 op = Src 1072 } 1073 1074 // sr is the source pixels. If it extends beyond the src bounds, 1075 // we cannot use the type-specific fast paths, as they access 1076 // the Pix fields directly without bounds checking. 1077 // 1078 // Similarly, the fast paths assume that the masks are nil. 1079 if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) { 1080 switch op { 1081 case Over: 1082 z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o) 1083 case Src: 1084 z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o) 1085 } 1086 } else if _, ok := src.(*image.Uniform); ok { 1087 Draw(dst, dr, src, src.Bounds().Min, op) 1088 } else { 1089 switch op { 1090 case Over: 1091 switch dst := dst.(type) { 1092 case *image.RGBA: 1093 switch src := src.(type) { 1094 case *image.NRGBA: 1095 z.scale_RGBA_NRGBA_Over(dst, dr, adr, src, sr, &o) 1096 case *image.RGBA: 1097 z.scale_RGBA_RGBA_Over(dst, dr, adr, src, sr, &o) 1098 default: 1099 z.scale_RGBA_Image_Over(dst, dr, adr, src, sr, &o) 1100 } 1101 default: 1102 switch src := src.(type) { 1103 default: 1104 z.scale_Image_Image_Over(dst, dr, adr, src, sr, &o) 1105 } 1106 } 1107 case Src: 1108 switch dst := dst.(type) { 1109 case *image.RGBA: 1110 switch src := src.(type) { 1111 case *image.Gray: 1112 z.scale_RGBA_Gray_Src(dst, dr, adr, src, sr, &o) 1113 case *image.NRGBA: 1114 z.scale_RGBA_NRGBA_Src(dst, dr, adr, src, sr, &o) 1115 case *image.RGBA: 1116 z.scale_RGBA_RGBA_Src(dst, dr, adr, src, sr, &o) 1117 case *image.YCbCr: 1118 switch src.SubsampleRatio { 1119 default: 1120 z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o) 1121 case image.YCbCrSubsampleRatio444: 1122 z.scale_RGBA_YCbCr444_Src(dst, dr, adr, src, sr, &o) 1123 case image.YCbCrSubsampleRatio422: 1124 z.scale_RGBA_YCbCr422_Src(dst, dr, adr, src, sr, &o) 1125 case image.YCbCrSubsampleRatio420: 1126 z.scale_RGBA_YCbCr420_Src(dst, dr, adr, src, sr, &o) 1127 case image.YCbCrSubsampleRatio440: 1128 z.scale_RGBA_YCbCr440_Src(dst, dr, adr, src, sr, &o) 1129 } 1130 default: 1131 z.scale_RGBA_Image_Src(dst, dr, adr, src, sr, &o) 1132 } 1133 default: 1134 switch src := src.(type) { 1135 default: 1136 z.scale_Image_Image_Src(dst, dr, adr, src, sr, &o) 1137 } 1138 } 1139 } 1140 } 1141 } 1142 1143 func (z ablInterpolator) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) { 1144 // Try to simplify a Transform to a Copy. 1145 if s2d[0] == 1 && s2d[1] == 0 && s2d[3] == 0 && s2d[4] == 1 { 1146 dx := int(s2d[2]) 1147 dy := int(s2d[5]) 1148 if float64(dx) == s2d[2] && float64(dy) == s2d[5] { 1149 Copy(dst, image.Point{X: sr.Min.X + dx, Y: sr.Min.X + dy}, src, sr, op, opts) 1150 return 1151 } 1152 } 1153 1154 var o Options 1155 if opts != nil { 1156 o = *opts 1157 } 1158 1159 dr := transformRect(&s2d, &sr) 1160 // adr is the affected destination pixels. 1161 adr := dst.Bounds().Intersect(dr) 1162 adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP) 1163 if adr.Empty() || sr.Empty() { 1164 return 1165 } 1166 if op == Over && o.SrcMask == nil && opaque(src) { 1167 op = Src 1168 } 1169 1170 d2s := invert(&s2d) 1171 // bias is a translation of the mapping from dst coordinates to src 1172 // coordinates such that the latter temporarily have non-negative X 1173 // and Y coordinates. This allows us to write int(f) instead of 1174 // int(math.Floor(f)), since "round to zero" and "round down" are 1175 // equivalent when f >= 0, but the former is much cheaper. The X-- 1176 // and Y-- are because the TransformLeaf methods have a "sx -= 0.5" 1177 // adjustment. 1178 bias := transformRect(&d2s, &adr).Min 1179 bias.X-- 1180 bias.Y-- 1181 d2s[2] -= float64(bias.X) 1182 d2s[5] -= float64(bias.Y) 1183 // Make adr relative to dr.Min. 1184 adr = adr.Sub(dr.Min) 1185 // sr is the source pixels. If it extends beyond the src bounds, 1186 // we cannot use the type-specific fast paths, as they access 1187 // the Pix fields directly without bounds checking. 1188 // 1189 // Similarly, the fast paths assume that the masks are nil. 1190 if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) { 1191 switch op { 1192 case Over: 1193 z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 1194 case Src: 1195 z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1196 } 1197 } else if u, ok := src.(*image.Uniform); ok { 1198 transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op) 1199 } else { 1200 switch op { 1201 case Over: 1202 switch dst := dst.(type) { 1203 case *image.RGBA: 1204 switch src := src.(type) { 1205 case *image.NRGBA: 1206 z.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 1207 case *image.RGBA: 1208 z.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 1209 default: 1210 z.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 1211 } 1212 default: 1213 switch src := src.(type) { 1214 default: 1215 z.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, &o) 1216 } 1217 } 1218 case Src: 1219 switch dst := dst.(type) { 1220 case *image.RGBA: 1221 switch src := src.(type) { 1222 case *image.Gray: 1223 z.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1224 case *image.NRGBA: 1225 z.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1226 case *image.RGBA: 1227 z.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1228 case *image.YCbCr: 1229 switch src.SubsampleRatio { 1230 default: 1231 z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1232 case image.YCbCrSubsampleRatio444: 1233 z.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1234 case image.YCbCrSubsampleRatio422: 1235 z.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1236 case image.YCbCrSubsampleRatio420: 1237 z.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1238 case image.YCbCrSubsampleRatio440: 1239 z.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1240 } 1241 default: 1242 z.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1243 } 1244 default: 1245 switch src := src.(type) { 1246 default: 1247 z.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, &o) 1248 } 1249 } 1250 } 1251 } 1252 } 1253 1254 func (ablInterpolator) scale_RGBA_Gray_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.Gray, sr image.Rectangle, opts *Options) { 1255 sw := int32(sr.Dx()) 1256 sh := int32(sr.Dy()) 1257 yscale := float64(sh) / float64(dr.Dy()) 1258 xscale := float64(sw) / float64(dr.Dx()) 1259 swMinus1, shMinus1 := sw-1, sh-1 1260 1261 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1262 sy := (float64(dy)+0.5)*yscale - 0.5 1263 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1264 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1265 // sx, below. 1266 sy0 := int32(sy) 1267 yFrac0 := sy - float64(sy0) 1268 yFrac1 := 1 - yFrac0 1269 sy1 := sy0 + 1 1270 if sy < 0 { 1271 sy0, sy1 = 0, 0 1272 yFrac0, yFrac1 = 0, 1 1273 } else if sy1 > shMinus1 { 1274 sy0, sy1 = shMinus1, shMinus1 1275 yFrac0, yFrac1 = 1, 0 1276 } 1277 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1278 1279 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1280 sx := (float64(dx)+0.5)*xscale - 0.5 1281 sx0 := int32(sx) 1282 xFrac0 := sx - float64(sx0) 1283 xFrac1 := 1 - xFrac0 1284 sx1 := sx0 + 1 1285 if sx < 0 { 1286 sx0, sx1 = 0, 0 1287 xFrac0, xFrac1 = 0, 1 1288 } else if sx1 > swMinus1 { 1289 sx0, sx1 = swMinus1, swMinus1 1290 xFrac0, xFrac1 = 1, 0 1291 } 1292 1293 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1294 s00ru := uint32(src.Pix[s00i]) * 0x101 1295 s00r := float64(s00ru) 1296 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1297 s10ru := uint32(src.Pix[s10i]) * 0x101 1298 s10r := float64(s10ru) 1299 s10r = xFrac1*s00r + xFrac0*s10r 1300 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1301 s01ru := uint32(src.Pix[s01i]) * 0x101 1302 s01r := float64(s01ru) 1303 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1304 s11ru := uint32(src.Pix[s11i]) * 0x101 1305 s11r := float64(s11ru) 1306 s11r = xFrac1*s01r + xFrac0*s11r 1307 s11r = yFrac1*s10r + yFrac0*s11r 1308 pr := uint32(s11r) 1309 out := uint8(pr >> 8) 1310 dst.Pix[d+0] = out 1311 dst.Pix[d+1] = out 1312 dst.Pix[d+2] = out 1313 dst.Pix[d+3] = 0xff 1314 } 1315 } 1316 } 1317 1318 func (ablInterpolator) scale_RGBA_NRGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) { 1319 sw := int32(sr.Dx()) 1320 sh := int32(sr.Dy()) 1321 yscale := float64(sh) / float64(dr.Dy()) 1322 xscale := float64(sw) / float64(dr.Dx()) 1323 swMinus1, shMinus1 := sw-1, sh-1 1324 1325 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1326 sy := (float64(dy)+0.5)*yscale - 0.5 1327 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1328 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1329 // sx, below. 1330 sy0 := int32(sy) 1331 yFrac0 := sy - float64(sy0) 1332 yFrac1 := 1 - yFrac0 1333 sy1 := sy0 + 1 1334 if sy < 0 { 1335 sy0, sy1 = 0, 0 1336 yFrac0, yFrac1 = 0, 1 1337 } else if sy1 > shMinus1 { 1338 sy0, sy1 = shMinus1, shMinus1 1339 yFrac0, yFrac1 = 1, 0 1340 } 1341 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1342 1343 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1344 sx := (float64(dx)+0.5)*xscale - 0.5 1345 sx0 := int32(sx) 1346 xFrac0 := sx - float64(sx0) 1347 xFrac1 := 1 - xFrac0 1348 sx1 := sx0 + 1 1349 if sx < 0 { 1350 sx0, sx1 = 0, 0 1351 xFrac0, xFrac1 = 0, 1 1352 } else if sx1 > swMinus1 { 1353 sx0, sx1 = swMinus1, swMinus1 1354 xFrac0, xFrac1 = 1, 0 1355 } 1356 1357 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1358 s00au := uint32(src.Pix[s00i+3]) * 0x101 1359 s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff 1360 s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff 1361 s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff 1362 s00r := float64(s00ru) 1363 s00g := float64(s00gu) 1364 s00b := float64(s00bu) 1365 s00a := float64(s00au) 1366 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1367 s10au := uint32(src.Pix[s10i+3]) * 0x101 1368 s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff 1369 s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff 1370 s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff 1371 s10r := float64(s10ru) 1372 s10g := float64(s10gu) 1373 s10b := float64(s10bu) 1374 s10a := float64(s10au) 1375 s10r = xFrac1*s00r + xFrac0*s10r 1376 s10g = xFrac1*s00g + xFrac0*s10g 1377 s10b = xFrac1*s00b + xFrac0*s10b 1378 s10a = xFrac1*s00a + xFrac0*s10a 1379 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1380 s01au := uint32(src.Pix[s01i+3]) * 0x101 1381 s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff 1382 s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff 1383 s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff 1384 s01r := float64(s01ru) 1385 s01g := float64(s01gu) 1386 s01b := float64(s01bu) 1387 s01a := float64(s01au) 1388 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1389 s11au := uint32(src.Pix[s11i+3]) * 0x101 1390 s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff 1391 s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff 1392 s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff 1393 s11r := float64(s11ru) 1394 s11g := float64(s11gu) 1395 s11b := float64(s11bu) 1396 s11a := float64(s11au) 1397 s11r = xFrac1*s01r + xFrac0*s11r 1398 s11g = xFrac1*s01g + xFrac0*s11g 1399 s11b = xFrac1*s01b + xFrac0*s11b 1400 s11a = xFrac1*s01a + xFrac0*s11a 1401 s11r = yFrac1*s10r + yFrac0*s11r 1402 s11g = yFrac1*s10g + yFrac0*s11g 1403 s11b = yFrac1*s10b + yFrac0*s11b 1404 s11a = yFrac1*s10a + yFrac0*s11a 1405 pr := uint32(s11r) 1406 pg := uint32(s11g) 1407 pb := uint32(s11b) 1408 pa := uint32(s11a) 1409 pa1 := (0xffff - pa) * 0x101 1410 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 1411 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 1412 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 1413 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 1414 } 1415 } 1416 } 1417 1418 func (ablInterpolator) scale_RGBA_NRGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.NRGBA, sr image.Rectangle, opts *Options) { 1419 sw := int32(sr.Dx()) 1420 sh := int32(sr.Dy()) 1421 yscale := float64(sh) / float64(dr.Dy()) 1422 xscale := float64(sw) / float64(dr.Dx()) 1423 swMinus1, shMinus1 := sw-1, sh-1 1424 1425 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1426 sy := (float64(dy)+0.5)*yscale - 0.5 1427 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1428 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1429 // sx, below. 1430 sy0 := int32(sy) 1431 yFrac0 := sy - float64(sy0) 1432 yFrac1 := 1 - yFrac0 1433 sy1 := sy0 + 1 1434 if sy < 0 { 1435 sy0, sy1 = 0, 0 1436 yFrac0, yFrac1 = 0, 1 1437 } else if sy1 > shMinus1 { 1438 sy0, sy1 = shMinus1, shMinus1 1439 yFrac0, yFrac1 = 1, 0 1440 } 1441 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1442 1443 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1444 sx := (float64(dx)+0.5)*xscale - 0.5 1445 sx0 := int32(sx) 1446 xFrac0 := sx - float64(sx0) 1447 xFrac1 := 1 - xFrac0 1448 sx1 := sx0 + 1 1449 if sx < 0 { 1450 sx0, sx1 = 0, 0 1451 xFrac0, xFrac1 = 0, 1 1452 } else if sx1 > swMinus1 { 1453 sx0, sx1 = swMinus1, swMinus1 1454 xFrac0, xFrac1 = 1, 0 1455 } 1456 1457 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1458 s00au := uint32(src.Pix[s00i+3]) * 0x101 1459 s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff 1460 s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff 1461 s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff 1462 s00r := float64(s00ru) 1463 s00g := float64(s00gu) 1464 s00b := float64(s00bu) 1465 s00a := float64(s00au) 1466 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1467 s10au := uint32(src.Pix[s10i+3]) * 0x101 1468 s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff 1469 s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff 1470 s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff 1471 s10r := float64(s10ru) 1472 s10g := float64(s10gu) 1473 s10b := float64(s10bu) 1474 s10a := float64(s10au) 1475 s10r = xFrac1*s00r + xFrac0*s10r 1476 s10g = xFrac1*s00g + xFrac0*s10g 1477 s10b = xFrac1*s00b + xFrac0*s10b 1478 s10a = xFrac1*s00a + xFrac0*s10a 1479 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1480 s01au := uint32(src.Pix[s01i+3]) * 0x101 1481 s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff 1482 s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff 1483 s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff 1484 s01r := float64(s01ru) 1485 s01g := float64(s01gu) 1486 s01b := float64(s01bu) 1487 s01a := float64(s01au) 1488 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1489 s11au := uint32(src.Pix[s11i+3]) * 0x101 1490 s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff 1491 s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff 1492 s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff 1493 s11r := float64(s11ru) 1494 s11g := float64(s11gu) 1495 s11b := float64(s11bu) 1496 s11a := float64(s11au) 1497 s11r = xFrac1*s01r + xFrac0*s11r 1498 s11g = xFrac1*s01g + xFrac0*s11g 1499 s11b = xFrac1*s01b + xFrac0*s11b 1500 s11a = xFrac1*s01a + xFrac0*s11a 1501 s11r = yFrac1*s10r + yFrac0*s11r 1502 s11g = yFrac1*s10g + yFrac0*s11g 1503 s11b = yFrac1*s10b + yFrac0*s11b 1504 s11a = yFrac1*s10a + yFrac0*s11a 1505 pr := uint32(s11r) 1506 pg := uint32(s11g) 1507 pb := uint32(s11b) 1508 pa := uint32(s11a) 1509 dst.Pix[d+0] = uint8(pr >> 8) 1510 dst.Pix[d+1] = uint8(pg >> 8) 1511 dst.Pix[d+2] = uint8(pb >> 8) 1512 dst.Pix[d+3] = uint8(pa >> 8) 1513 } 1514 } 1515 } 1516 1517 func (ablInterpolator) scale_RGBA_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) { 1518 sw := int32(sr.Dx()) 1519 sh := int32(sr.Dy()) 1520 yscale := float64(sh) / float64(dr.Dy()) 1521 xscale := float64(sw) / float64(dr.Dx()) 1522 swMinus1, shMinus1 := sw-1, sh-1 1523 1524 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1525 sy := (float64(dy)+0.5)*yscale - 0.5 1526 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1527 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1528 // sx, below. 1529 sy0 := int32(sy) 1530 yFrac0 := sy - float64(sy0) 1531 yFrac1 := 1 - yFrac0 1532 sy1 := sy0 + 1 1533 if sy < 0 { 1534 sy0, sy1 = 0, 0 1535 yFrac0, yFrac1 = 0, 1 1536 } else if sy1 > shMinus1 { 1537 sy0, sy1 = shMinus1, shMinus1 1538 yFrac0, yFrac1 = 1, 0 1539 } 1540 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1541 1542 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1543 sx := (float64(dx)+0.5)*xscale - 0.5 1544 sx0 := int32(sx) 1545 xFrac0 := sx - float64(sx0) 1546 xFrac1 := 1 - xFrac0 1547 sx1 := sx0 + 1 1548 if sx < 0 { 1549 sx0, sx1 = 0, 0 1550 xFrac0, xFrac1 = 0, 1 1551 } else if sx1 > swMinus1 { 1552 sx0, sx1 = swMinus1, swMinus1 1553 xFrac0, xFrac1 = 1, 0 1554 } 1555 1556 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1557 s00ru := uint32(src.Pix[s00i+0]) * 0x101 1558 s00gu := uint32(src.Pix[s00i+1]) * 0x101 1559 s00bu := uint32(src.Pix[s00i+2]) * 0x101 1560 s00au := uint32(src.Pix[s00i+3]) * 0x101 1561 s00r := float64(s00ru) 1562 s00g := float64(s00gu) 1563 s00b := float64(s00bu) 1564 s00a := float64(s00au) 1565 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1566 s10ru := uint32(src.Pix[s10i+0]) * 0x101 1567 s10gu := uint32(src.Pix[s10i+1]) * 0x101 1568 s10bu := uint32(src.Pix[s10i+2]) * 0x101 1569 s10au := uint32(src.Pix[s10i+3]) * 0x101 1570 s10r := float64(s10ru) 1571 s10g := float64(s10gu) 1572 s10b := float64(s10bu) 1573 s10a := float64(s10au) 1574 s10r = xFrac1*s00r + xFrac0*s10r 1575 s10g = xFrac1*s00g + xFrac0*s10g 1576 s10b = xFrac1*s00b + xFrac0*s10b 1577 s10a = xFrac1*s00a + xFrac0*s10a 1578 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1579 s01ru := uint32(src.Pix[s01i+0]) * 0x101 1580 s01gu := uint32(src.Pix[s01i+1]) * 0x101 1581 s01bu := uint32(src.Pix[s01i+2]) * 0x101 1582 s01au := uint32(src.Pix[s01i+3]) * 0x101 1583 s01r := float64(s01ru) 1584 s01g := float64(s01gu) 1585 s01b := float64(s01bu) 1586 s01a := float64(s01au) 1587 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1588 s11ru := uint32(src.Pix[s11i+0]) * 0x101 1589 s11gu := uint32(src.Pix[s11i+1]) * 0x101 1590 s11bu := uint32(src.Pix[s11i+2]) * 0x101 1591 s11au := uint32(src.Pix[s11i+3]) * 0x101 1592 s11r := float64(s11ru) 1593 s11g := float64(s11gu) 1594 s11b := float64(s11bu) 1595 s11a := float64(s11au) 1596 s11r = xFrac1*s01r + xFrac0*s11r 1597 s11g = xFrac1*s01g + xFrac0*s11g 1598 s11b = xFrac1*s01b + xFrac0*s11b 1599 s11a = xFrac1*s01a + xFrac0*s11a 1600 s11r = yFrac1*s10r + yFrac0*s11r 1601 s11g = yFrac1*s10g + yFrac0*s11g 1602 s11b = yFrac1*s10b + yFrac0*s11b 1603 s11a = yFrac1*s10a + yFrac0*s11a 1604 pr := uint32(s11r) 1605 pg := uint32(s11g) 1606 pb := uint32(s11b) 1607 pa := uint32(s11a) 1608 pa1 := (0xffff - pa) * 0x101 1609 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 1610 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 1611 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 1612 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 1613 } 1614 } 1615 } 1616 1617 func (ablInterpolator) scale_RGBA_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.RGBA, sr image.Rectangle, opts *Options) { 1618 sw := int32(sr.Dx()) 1619 sh := int32(sr.Dy()) 1620 yscale := float64(sh) / float64(dr.Dy()) 1621 xscale := float64(sw) / float64(dr.Dx()) 1622 swMinus1, shMinus1 := sw-1, sh-1 1623 1624 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1625 sy := (float64(dy)+0.5)*yscale - 0.5 1626 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1627 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1628 // sx, below. 1629 sy0 := int32(sy) 1630 yFrac0 := sy - float64(sy0) 1631 yFrac1 := 1 - yFrac0 1632 sy1 := sy0 + 1 1633 if sy < 0 { 1634 sy0, sy1 = 0, 0 1635 yFrac0, yFrac1 = 0, 1 1636 } else if sy1 > shMinus1 { 1637 sy0, sy1 = shMinus1, shMinus1 1638 yFrac0, yFrac1 = 1, 0 1639 } 1640 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1641 1642 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1643 sx := (float64(dx)+0.5)*xscale - 0.5 1644 sx0 := int32(sx) 1645 xFrac0 := sx - float64(sx0) 1646 xFrac1 := 1 - xFrac0 1647 sx1 := sx0 + 1 1648 if sx < 0 { 1649 sx0, sx1 = 0, 0 1650 xFrac0, xFrac1 = 0, 1 1651 } else if sx1 > swMinus1 { 1652 sx0, sx1 = swMinus1, swMinus1 1653 xFrac0, xFrac1 = 1, 0 1654 } 1655 1656 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1657 s00ru := uint32(src.Pix[s00i+0]) * 0x101 1658 s00gu := uint32(src.Pix[s00i+1]) * 0x101 1659 s00bu := uint32(src.Pix[s00i+2]) * 0x101 1660 s00au := uint32(src.Pix[s00i+3]) * 0x101 1661 s00r := float64(s00ru) 1662 s00g := float64(s00gu) 1663 s00b := float64(s00bu) 1664 s00a := float64(s00au) 1665 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1666 s10ru := uint32(src.Pix[s10i+0]) * 0x101 1667 s10gu := uint32(src.Pix[s10i+1]) * 0x101 1668 s10bu := uint32(src.Pix[s10i+2]) * 0x101 1669 s10au := uint32(src.Pix[s10i+3]) * 0x101 1670 s10r := float64(s10ru) 1671 s10g := float64(s10gu) 1672 s10b := float64(s10bu) 1673 s10a := float64(s10au) 1674 s10r = xFrac1*s00r + xFrac0*s10r 1675 s10g = xFrac1*s00g + xFrac0*s10g 1676 s10b = xFrac1*s00b + xFrac0*s10b 1677 s10a = xFrac1*s00a + xFrac0*s10a 1678 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx0)-src.Rect.Min.X)*4 1679 s01ru := uint32(src.Pix[s01i+0]) * 0x101 1680 s01gu := uint32(src.Pix[s01i+1]) * 0x101 1681 s01bu := uint32(src.Pix[s01i+2]) * 0x101 1682 s01au := uint32(src.Pix[s01i+3]) * 0x101 1683 s01r := float64(s01ru) 1684 s01g := float64(s01gu) 1685 s01b := float64(s01bu) 1686 s01a := float64(s01au) 1687 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(sx1)-src.Rect.Min.X)*4 1688 s11ru := uint32(src.Pix[s11i+0]) * 0x101 1689 s11gu := uint32(src.Pix[s11i+1]) * 0x101 1690 s11bu := uint32(src.Pix[s11i+2]) * 0x101 1691 s11au := uint32(src.Pix[s11i+3]) * 0x101 1692 s11r := float64(s11ru) 1693 s11g := float64(s11gu) 1694 s11b := float64(s11bu) 1695 s11a := float64(s11au) 1696 s11r = xFrac1*s01r + xFrac0*s11r 1697 s11g = xFrac1*s01g + xFrac0*s11g 1698 s11b = xFrac1*s01b + xFrac0*s11b 1699 s11a = xFrac1*s01a + xFrac0*s11a 1700 s11r = yFrac1*s10r + yFrac0*s11r 1701 s11g = yFrac1*s10g + yFrac0*s11g 1702 s11b = yFrac1*s10b + yFrac0*s11b 1703 s11a = yFrac1*s10a + yFrac0*s11a 1704 pr := uint32(s11r) 1705 pg := uint32(s11g) 1706 pb := uint32(s11b) 1707 pa := uint32(s11a) 1708 dst.Pix[d+0] = uint8(pr >> 8) 1709 dst.Pix[d+1] = uint8(pg >> 8) 1710 dst.Pix[d+2] = uint8(pb >> 8) 1711 dst.Pix[d+3] = uint8(pa >> 8) 1712 } 1713 } 1714 } 1715 1716 func (ablInterpolator) scale_RGBA_YCbCr444_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 1717 sw := int32(sr.Dx()) 1718 sh := int32(sr.Dy()) 1719 yscale := float64(sh) / float64(dr.Dy()) 1720 xscale := float64(sw) / float64(dr.Dx()) 1721 swMinus1, shMinus1 := sw-1, sh-1 1722 1723 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1724 sy := (float64(dy)+0.5)*yscale - 0.5 1725 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1726 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1727 // sx, below. 1728 sy0 := int32(sy) 1729 yFrac0 := sy - float64(sy0) 1730 yFrac1 := 1 - yFrac0 1731 sy1 := sy0 + 1 1732 if sy < 0 { 1733 sy0, sy1 = 0, 0 1734 yFrac0, yFrac1 = 0, 1 1735 } else if sy1 > shMinus1 { 1736 sy0, sy1 = shMinus1, shMinus1 1737 yFrac0, yFrac1 = 1, 0 1738 } 1739 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1740 1741 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1742 sx := (float64(dx)+0.5)*xscale - 0.5 1743 sx0 := int32(sx) 1744 xFrac0 := sx - float64(sx0) 1745 xFrac1 := 1 - xFrac0 1746 sx1 := sx0 + 1 1747 if sx < 0 { 1748 sx0, sx1 = 0, 0 1749 xFrac0, xFrac1 = 0, 1 1750 } else if sx1 > swMinus1 { 1751 sx0, sx1 = swMinus1, swMinus1 1752 xFrac0, xFrac1 = 1, 0 1753 } 1754 1755 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1756 s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1757 1758 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1759 s00yy1 := int(src.Y[s00i]) * 0x10100 1760 s00cb1 := int(src.Cb[s00j]) - 128 1761 s00cr1 := int(src.Cr[s00j]) - 128 1762 s00ru := (s00yy1 + 91881*s00cr1) >> 8 1763 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 1764 s00bu := (s00yy1 + 116130*s00cb1) >> 8 1765 if s00ru < 0 { 1766 s00ru = 0 1767 } else if s00ru > 0xffff { 1768 s00ru = 0xffff 1769 } 1770 if s00gu < 0 { 1771 s00gu = 0 1772 } else if s00gu > 0xffff { 1773 s00gu = 0xffff 1774 } 1775 if s00bu < 0 { 1776 s00bu = 0 1777 } else if s00bu > 0xffff { 1778 s00bu = 0xffff 1779 } 1780 1781 s00r := float64(s00ru) 1782 s00g := float64(s00gu) 1783 s00b := float64(s00bu) 1784 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1785 s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1786 1787 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1788 s10yy1 := int(src.Y[s10i]) * 0x10100 1789 s10cb1 := int(src.Cb[s10j]) - 128 1790 s10cr1 := int(src.Cr[s10j]) - 128 1791 s10ru := (s10yy1 + 91881*s10cr1) >> 8 1792 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 1793 s10bu := (s10yy1 + 116130*s10cb1) >> 8 1794 if s10ru < 0 { 1795 s10ru = 0 1796 } else if s10ru > 0xffff { 1797 s10ru = 0xffff 1798 } 1799 if s10gu < 0 { 1800 s10gu = 0 1801 } else if s10gu > 0xffff { 1802 s10gu = 0xffff 1803 } 1804 if s10bu < 0 { 1805 s10bu = 0 1806 } else if s10bu > 0xffff { 1807 s10bu = 0xffff 1808 } 1809 1810 s10r := float64(s10ru) 1811 s10g := float64(s10gu) 1812 s10b := float64(s10bu) 1813 s10r = xFrac1*s00r + xFrac0*s10r 1814 s10g = xFrac1*s00g + xFrac0*s10g 1815 s10b = xFrac1*s00b + xFrac0*s10b 1816 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1817 s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1818 1819 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1820 s01yy1 := int(src.Y[s01i]) * 0x10100 1821 s01cb1 := int(src.Cb[s01j]) - 128 1822 s01cr1 := int(src.Cr[s01j]) - 128 1823 s01ru := (s01yy1 + 91881*s01cr1) >> 8 1824 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 1825 s01bu := (s01yy1 + 116130*s01cb1) >> 8 1826 if s01ru < 0 { 1827 s01ru = 0 1828 } else if s01ru > 0xffff { 1829 s01ru = 0xffff 1830 } 1831 if s01gu < 0 { 1832 s01gu = 0 1833 } else if s01gu > 0xffff { 1834 s01gu = 0xffff 1835 } 1836 if s01bu < 0 { 1837 s01bu = 0 1838 } else if s01bu > 0xffff { 1839 s01bu = 0xffff 1840 } 1841 1842 s01r := float64(s01ru) 1843 s01g := float64(s01gu) 1844 s01b := float64(s01bu) 1845 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1846 s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1847 1848 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1849 s11yy1 := int(src.Y[s11i]) * 0x10100 1850 s11cb1 := int(src.Cb[s11j]) - 128 1851 s11cr1 := int(src.Cr[s11j]) - 128 1852 s11ru := (s11yy1 + 91881*s11cr1) >> 8 1853 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 1854 s11bu := (s11yy1 + 116130*s11cb1) >> 8 1855 if s11ru < 0 { 1856 s11ru = 0 1857 } else if s11ru > 0xffff { 1858 s11ru = 0xffff 1859 } 1860 if s11gu < 0 { 1861 s11gu = 0 1862 } else if s11gu > 0xffff { 1863 s11gu = 0xffff 1864 } 1865 if s11bu < 0 { 1866 s11bu = 0 1867 } else if s11bu > 0xffff { 1868 s11bu = 0xffff 1869 } 1870 1871 s11r := float64(s11ru) 1872 s11g := float64(s11gu) 1873 s11b := float64(s11bu) 1874 s11r = xFrac1*s01r + xFrac0*s11r 1875 s11g = xFrac1*s01g + xFrac0*s11g 1876 s11b = xFrac1*s01b + xFrac0*s11b 1877 s11r = yFrac1*s10r + yFrac0*s11r 1878 s11g = yFrac1*s10g + yFrac0*s11g 1879 s11b = yFrac1*s10b + yFrac0*s11b 1880 pr := uint32(s11r) 1881 pg := uint32(s11g) 1882 pb := uint32(s11b) 1883 dst.Pix[d+0] = uint8(pr >> 8) 1884 dst.Pix[d+1] = uint8(pg >> 8) 1885 dst.Pix[d+2] = uint8(pb >> 8) 1886 dst.Pix[d+3] = 0xff 1887 } 1888 } 1889 } 1890 1891 func (ablInterpolator) scale_RGBA_YCbCr422_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 1892 sw := int32(sr.Dx()) 1893 sh := int32(sr.Dy()) 1894 yscale := float64(sh) / float64(dr.Dy()) 1895 xscale := float64(sw) / float64(dr.Dx()) 1896 swMinus1, shMinus1 := sw-1, sh-1 1897 1898 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 1899 sy := (float64(dy)+0.5)*yscale - 0.5 1900 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 1901 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 1902 // sx, below. 1903 sy0 := int32(sy) 1904 yFrac0 := sy - float64(sy0) 1905 yFrac1 := 1 - yFrac0 1906 sy1 := sy0 + 1 1907 if sy < 0 { 1908 sy0, sy1 = 0, 0 1909 yFrac0, yFrac1 = 0, 1 1910 } else if sy1 > shMinus1 { 1911 sy0, sy1 = shMinus1, shMinus1 1912 yFrac0, yFrac1 = 1, 0 1913 } 1914 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 1915 1916 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 1917 sx := (float64(dx)+0.5)*xscale - 0.5 1918 sx0 := int32(sx) 1919 xFrac0 := sx - float64(sx0) 1920 xFrac1 := 1 - xFrac0 1921 sx1 := sx0 + 1 1922 if sx < 0 { 1923 sx0, sx1 = 0, 0 1924 xFrac0, xFrac1 = 0, 1 1925 } else if sx1 > swMinus1 { 1926 sx0, sx1 = swMinus1, swMinus1 1927 xFrac0, xFrac1 = 1, 0 1928 } 1929 1930 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1931 s00j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2) 1932 1933 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1934 s00yy1 := int(src.Y[s00i]) * 0x10100 1935 s00cb1 := int(src.Cb[s00j]) - 128 1936 s00cr1 := int(src.Cr[s00j]) - 128 1937 s00ru := (s00yy1 + 91881*s00cr1) >> 8 1938 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 1939 s00bu := (s00yy1 + 116130*s00cb1) >> 8 1940 if s00ru < 0 { 1941 s00ru = 0 1942 } else if s00ru > 0xffff { 1943 s00ru = 0xffff 1944 } 1945 if s00gu < 0 { 1946 s00gu = 0 1947 } else if s00gu > 0xffff { 1948 s00gu = 0xffff 1949 } 1950 if s00bu < 0 { 1951 s00bu = 0 1952 } else if s00bu > 0xffff { 1953 s00bu = 0xffff 1954 } 1955 1956 s00r := float64(s00ru) 1957 s00g := float64(s00gu) 1958 s00b := float64(s00bu) 1959 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 1960 s10j := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2) 1961 1962 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1963 s10yy1 := int(src.Y[s10i]) * 0x10100 1964 s10cb1 := int(src.Cb[s10j]) - 128 1965 s10cr1 := int(src.Cr[s10j]) - 128 1966 s10ru := (s10yy1 + 91881*s10cr1) >> 8 1967 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 1968 s10bu := (s10yy1 + 116130*s10cb1) >> 8 1969 if s10ru < 0 { 1970 s10ru = 0 1971 } else if s10ru > 0xffff { 1972 s10ru = 0xffff 1973 } 1974 if s10gu < 0 { 1975 s10gu = 0 1976 } else if s10gu > 0xffff { 1977 s10gu = 0xffff 1978 } 1979 if s10bu < 0 { 1980 s10bu = 0 1981 } else if s10bu > 0xffff { 1982 s10bu = 0xffff 1983 } 1984 1985 s10r := float64(s10ru) 1986 s10g := float64(s10gu) 1987 s10b := float64(s10bu) 1988 s10r = xFrac1*s00r + xFrac0*s10r 1989 s10g = xFrac1*s00g + xFrac0*s10g 1990 s10b = xFrac1*s00b + xFrac0*s10b 1991 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 1992 s01j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx0))/2 - src.Rect.Min.X/2) 1993 1994 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 1995 s01yy1 := int(src.Y[s01i]) * 0x10100 1996 s01cb1 := int(src.Cb[s01j]) - 128 1997 s01cr1 := int(src.Cr[s01j]) - 128 1998 s01ru := (s01yy1 + 91881*s01cr1) >> 8 1999 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 2000 s01bu := (s01yy1 + 116130*s01cb1) >> 8 2001 if s01ru < 0 { 2002 s01ru = 0 2003 } else if s01ru > 0xffff { 2004 s01ru = 0xffff 2005 } 2006 if s01gu < 0 { 2007 s01gu = 0 2008 } else if s01gu > 0xffff { 2009 s01gu = 0xffff 2010 } 2011 if s01bu < 0 { 2012 s01bu = 0 2013 } else if s01bu > 0xffff { 2014 s01bu = 0xffff 2015 } 2016 2017 s01r := float64(s01ru) 2018 s01g := float64(s01gu) 2019 s01b := float64(s01bu) 2020 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2021 s11j := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(sx1))/2 - src.Rect.Min.X/2) 2022 2023 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2024 s11yy1 := int(src.Y[s11i]) * 0x10100 2025 s11cb1 := int(src.Cb[s11j]) - 128 2026 s11cr1 := int(src.Cr[s11j]) - 128 2027 s11ru := (s11yy1 + 91881*s11cr1) >> 8 2028 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 2029 s11bu := (s11yy1 + 116130*s11cb1) >> 8 2030 if s11ru < 0 { 2031 s11ru = 0 2032 } else if s11ru > 0xffff { 2033 s11ru = 0xffff 2034 } 2035 if s11gu < 0 { 2036 s11gu = 0 2037 } else if s11gu > 0xffff { 2038 s11gu = 0xffff 2039 } 2040 if s11bu < 0 { 2041 s11bu = 0 2042 } else if s11bu > 0xffff { 2043 s11bu = 0xffff 2044 } 2045 2046 s11r := float64(s11ru) 2047 s11g := float64(s11gu) 2048 s11b := float64(s11bu) 2049 s11r = xFrac1*s01r + xFrac0*s11r 2050 s11g = xFrac1*s01g + xFrac0*s11g 2051 s11b = xFrac1*s01b + xFrac0*s11b 2052 s11r = yFrac1*s10r + yFrac0*s11r 2053 s11g = yFrac1*s10g + yFrac0*s11g 2054 s11b = yFrac1*s10b + yFrac0*s11b 2055 pr := uint32(s11r) 2056 pg := uint32(s11g) 2057 pb := uint32(s11b) 2058 dst.Pix[d+0] = uint8(pr >> 8) 2059 dst.Pix[d+1] = uint8(pg >> 8) 2060 dst.Pix[d+2] = uint8(pb >> 8) 2061 dst.Pix[d+3] = 0xff 2062 } 2063 } 2064 } 2065 2066 func (ablInterpolator) scale_RGBA_YCbCr420_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 2067 sw := int32(sr.Dx()) 2068 sh := int32(sr.Dy()) 2069 yscale := float64(sh) / float64(dr.Dy()) 2070 xscale := float64(sw) / float64(dr.Dx()) 2071 swMinus1, shMinus1 := sw-1, sh-1 2072 2073 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2074 sy := (float64(dy)+0.5)*yscale - 0.5 2075 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 2076 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 2077 // sx, below. 2078 sy0 := int32(sy) 2079 yFrac0 := sy - float64(sy0) 2080 yFrac1 := 1 - yFrac0 2081 sy1 := sy0 + 1 2082 if sy < 0 { 2083 sy0, sy1 = 0, 0 2084 yFrac0, yFrac1 = 0, 1 2085 } else if sy1 > shMinus1 { 2086 sy0, sy1 = shMinus1, shMinus1 2087 yFrac0, yFrac1 = 1, 0 2088 } 2089 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 2090 2091 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 2092 sx := (float64(dx)+0.5)*xscale - 0.5 2093 sx0 := int32(sx) 2094 xFrac0 := sx - float64(sx0) 2095 xFrac1 := 1 - xFrac0 2096 sx1 := sx0 + 1 2097 if sx < 0 { 2098 sx0, sx1 = 0, 0 2099 xFrac0, xFrac1 = 0, 1 2100 } else if sx1 > swMinus1 { 2101 sx0, sx1 = swMinus1, swMinus1 2102 xFrac0, xFrac1 = 1, 0 2103 } 2104 2105 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 2106 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) 2107 2108 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2109 s00yy1 := int(src.Y[s00i]) * 0x10100 2110 s00cb1 := int(src.Cb[s00j]) - 128 2111 s00cr1 := int(src.Cr[s00j]) - 128 2112 s00ru := (s00yy1 + 91881*s00cr1) >> 8 2113 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 2114 s00bu := (s00yy1 + 116130*s00cb1) >> 8 2115 if s00ru < 0 { 2116 s00ru = 0 2117 } else if s00ru > 0xffff { 2118 s00ru = 0xffff 2119 } 2120 if s00gu < 0 { 2121 s00gu = 0 2122 } else if s00gu > 0xffff { 2123 s00gu = 0xffff 2124 } 2125 if s00bu < 0 { 2126 s00bu = 0 2127 } else if s00bu > 0xffff { 2128 s00bu = 0xffff 2129 } 2130 2131 s00r := float64(s00ru) 2132 s00g := float64(s00gu) 2133 s00b := float64(s00bu) 2134 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2135 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) 2136 2137 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2138 s10yy1 := int(src.Y[s10i]) * 0x10100 2139 s10cb1 := int(src.Cb[s10j]) - 128 2140 s10cr1 := int(src.Cr[s10j]) - 128 2141 s10ru := (s10yy1 + 91881*s10cr1) >> 8 2142 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 2143 s10bu := (s10yy1 + 116130*s10cb1) >> 8 2144 if s10ru < 0 { 2145 s10ru = 0 2146 } else if s10ru > 0xffff { 2147 s10ru = 0xffff 2148 } 2149 if s10gu < 0 { 2150 s10gu = 0 2151 } else if s10gu > 0xffff { 2152 s10gu = 0xffff 2153 } 2154 if s10bu < 0 { 2155 s10bu = 0 2156 } else if s10bu > 0xffff { 2157 s10bu = 0xffff 2158 } 2159 2160 s10r := float64(s10ru) 2161 s10g := float64(s10gu) 2162 s10b := float64(s10bu) 2163 s10r = xFrac1*s00r + xFrac0*s10r 2164 s10g = xFrac1*s00g + xFrac0*s10g 2165 s10b = xFrac1*s00b + xFrac0*s10b 2166 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 2167 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) 2168 2169 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2170 s01yy1 := int(src.Y[s01i]) * 0x10100 2171 s01cb1 := int(src.Cb[s01j]) - 128 2172 s01cr1 := int(src.Cr[s01j]) - 128 2173 s01ru := (s01yy1 + 91881*s01cr1) >> 8 2174 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 2175 s01bu := (s01yy1 + 116130*s01cb1) >> 8 2176 if s01ru < 0 { 2177 s01ru = 0 2178 } else if s01ru > 0xffff { 2179 s01ru = 0xffff 2180 } 2181 if s01gu < 0 { 2182 s01gu = 0 2183 } else if s01gu > 0xffff { 2184 s01gu = 0xffff 2185 } 2186 if s01bu < 0 { 2187 s01bu = 0 2188 } else if s01bu > 0xffff { 2189 s01bu = 0xffff 2190 } 2191 2192 s01r := float64(s01ru) 2193 s01g := float64(s01gu) 2194 s01b := float64(s01bu) 2195 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2196 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) 2197 2198 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2199 s11yy1 := int(src.Y[s11i]) * 0x10100 2200 s11cb1 := int(src.Cb[s11j]) - 128 2201 s11cr1 := int(src.Cr[s11j]) - 128 2202 s11ru := (s11yy1 + 91881*s11cr1) >> 8 2203 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 2204 s11bu := (s11yy1 + 116130*s11cb1) >> 8 2205 if s11ru < 0 { 2206 s11ru = 0 2207 } else if s11ru > 0xffff { 2208 s11ru = 0xffff 2209 } 2210 if s11gu < 0 { 2211 s11gu = 0 2212 } else if s11gu > 0xffff { 2213 s11gu = 0xffff 2214 } 2215 if s11bu < 0 { 2216 s11bu = 0 2217 } else if s11bu > 0xffff { 2218 s11bu = 0xffff 2219 } 2220 2221 s11r := float64(s11ru) 2222 s11g := float64(s11gu) 2223 s11b := float64(s11bu) 2224 s11r = xFrac1*s01r + xFrac0*s11r 2225 s11g = xFrac1*s01g + xFrac0*s11g 2226 s11b = xFrac1*s01b + xFrac0*s11b 2227 s11r = yFrac1*s10r + yFrac0*s11r 2228 s11g = yFrac1*s10g + yFrac0*s11g 2229 s11b = yFrac1*s10b + yFrac0*s11b 2230 pr := uint32(s11r) 2231 pg := uint32(s11g) 2232 pb := uint32(s11b) 2233 dst.Pix[d+0] = uint8(pr >> 8) 2234 dst.Pix[d+1] = uint8(pg >> 8) 2235 dst.Pix[d+2] = uint8(pb >> 8) 2236 dst.Pix[d+3] = 0xff 2237 } 2238 } 2239 } 2240 2241 func (ablInterpolator) scale_RGBA_YCbCr440_Src(dst *image.RGBA, dr, adr image.Rectangle, src *image.YCbCr, sr image.Rectangle, opts *Options) { 2242 sw := int32(sr.Dx()) 2243 sh := int32(sr.Dy()) 2244 yscale := float64(sh) / float64(dr.Dy()) 2245 xscale := float64(sw) / float64(dr.Dx()) 2246 swMinus1, shMinus1 := sw-1, sh-1 2247 2248 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2249 sy := (float64(dy)+0.5)*yscale - 0.5 2250 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 2251 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 2252 // sx, below. 2253 sy0 := int32(sy) 2254 yFrac0 := sy - float64(sy0) 2255 yFrac1 := 1 - yFrac0 2256 sy1 := sy0 + 1 2257 if sy < 0 { 2258 sy0, sy1 = 0, 0 2259 yFrac0, yFrac1 = 0, 1 2260 } else if sy1 > shMinus1 { 2261 sy0, sy1 = shMinus1, shMinus1 2262 yFrac0, yFrac1 = 1, 0 2263 } 2264 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 2265 2266 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 2267 sx := (float64(dx)+0.5)*xscale - 0.5 2268 sx0 := int32(sx) 2269 xFrac0 := sx - float64(sx0) 2270 xFrac1 := 1 - xFrac0 2271 sx1 := sx0 + 1 2272 if sx < 0 { 2273 sx0, sx1 = 0, 0 2274 xFrac0, xFrac1 = 0, 1 2275 } else if sx1 > swMinus1 { 2276 sx0, sx1 = swMinus1, swMinus1 2277 xFrac0, xFrac1 = 1, 0 2278 } 2279 2280 s00i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 2281 s00j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 2282 2283 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2284 s00yy1 := int(src.Y[s00i]) * 0x10100 2285 s00cb1 := int(src.Cb[s00j]) - 128 2286 s00cr1 := int(src.Cr[s00j]) - 128 2287 s00ru := (s00yy1 + 91881*s00cr1) >> 8 2288 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 2289 s00bu := (s00yy1 + 116130*s00cb1) >> 8 2290 if s00ru < 0 { 2291 s00ru = 0 2292 } else if s00ru > 0xffff { 2293 s00ru = 0xffff 2294 } 2295 if s00gu < 0 { 2296 s00gu = 0 2297 } else if s00gu > 0xffff { 2298 s00gu = 0xffff 2299 } 2300 if s00bu < 0 { 2301 s00bu = 0 2302 } else if s00bu > 0xffff { 2303 s00bu = 0xffff 2304 } 2305 2306 s00r := float64(s00ru) 2307 s00g := float64(s00gu) 2308 s00b := float64(s00bu) 2309 s10i := (sr.Min.Y+int(sy0)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2310 s10j := ((sr.Min.Y+int(sy0))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2311 2312 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2313 s10yy1 := int(src.Y[s10i]) * 0x10100 2314 s10cb1 := int(src.Cb[s10j]) - 128 2315 s10cr1 := int(src.Cr[s10j]) - 128 2316 s10ru := (s10yy1 + 91881*s10cr1) >> 8 2317 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 2318 s10bu := (s10yy1 + 116130*s10cb1) >> 8 2319 if s10ru < 0 { 2320 s10ru = 0 2321 } else if s10ru > 0xffff { 2322 s10ru = 0xffff 2323 } 2324 if s10gu < 0 { 2325 s10gu = 0 2326 } else if s10gu > 0xffff { 2327 s10gu = 0xffff 2328 } 2329 if s10bu < 0 { 2330 s10bu = 0 2331 } else if s10bu > 0xffff { 2332 s10bu = 0xffff 2333 } 2334 2335 s10r := float64(s10ru) 2336 s10g := float64(s10gu) 2337 s10b := float64(s10bu) 2338 s10r = xFrac1*s00r + xFrac0*s10r 2339 s10g = xFrac1*s00g + xFrac0*s10g 2340 s10b = xFrac1*s00b + xFrac0*s10b 2341 s01i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 2342 s01j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx0) - src.Rect.Min.X) 2343 2344 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2345 s01yy1 := int(src.Y[s01i]) * 0x10100 2346 s01cb1 := int(src.Cb[s01j]) - 128 2347 s01cr1 := int(src.Cr[s01j]) - 128 2348 s01ru := (s01yy1 + 91881*s01cr1) >> 8 2349 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 2350 s01bu := (s01yy1 + 116130*s01cb1) >> 8 2351 if s01ru < 0 { 2352 s01ru = 0 2353 } else if s01ru > 0xffff { 2354 s01ru = 0xffff 2355 } 2356 if s01gu < 0 { 2357 s01gu = 0 2358 } else if s01gu > 0xffff { 2359 s01gu = 0xffff 2360 } 2361 if s01bu < 0 { 2362 s01bu = 0 2363 } else if s01bu > 0xffff { 2364 s01bu = 0xffff 2365 } 2366 2367 s01r := float64(s01ru) 2368 s01g := float64(s01gu) 2369 s01b := float64(s01bu) 2370 s11i := (sr.Min.Y+int(sy1)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2371 s11j := ((sr.Min.Y+int(sy1))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(sx1) - src.Rect.Min.X) 2372 2373 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 2374 s11yy1 := int(src.Y[s11i]) * 0x10100 2375 s11cb1 := int(src.Cb[s11j]) - 128 2376 s11cr1 := int(src.Cr[s11j]) - 128 2377 s11ru := (s11yy1 + 91881*s11cr1) >> 8 2378 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 2379 s11bu := (s11yy1 + 116130*s11cb1) >> 8 2380 if s11ru < 0 { 2381 s11ru = 0 2382 } else if s11ru > 0xffff { 2383 s11ru = 0xffff 2384 } 2385 if s11gu < 0 { 2386 s11gu = 0 2387 } else if s11gu > 0xffff { 2388 s11gu = 0xffff 2389 } 2390 if s11bu < 0 { 2391 s11bu = 0 2392 } else if s11bu > 0xffff { 2393 s11bu = 0xffff 2394 } 2395 2396 s11r := float64(s11ru) 2397 s11g := float64(s11gu) 2398 s11b := float64(s11bu) 2399 s11r = xFrac1*s01r + xFrac0*s11r 2400 s11g = xFrac1*s01g + xFrac0*s11g 2401 s11b = xFrac1*s01b + xFrac0*s11b 2402 s11r = yFrac1*s10r + yFrac0*s11r 2403 s11g = yFrac1*s10g + yFrac0*s11g 2404 s11b = yFrac1*s10b + yFrac0*s11b 2405 pr := uint32(s11r) 2406 pg := uint32(s11g) 2407 pb := uint32(s11b) 2408 dst.Pix[d+0] = uint8(pr >> 8) 2409 dst.Pix[d+1] = uint8(pg >> 8) 2410 dst.Pix[d+2] = uint8(pb >> 8) 2411 dst.Pix[d+3] = 0xff 2412 } 2413 } 2414 } 2415 2416 func (ablInterpolator) scale_RGBA_Image_Over(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 2417 sw := int32(sr.Dx()) 2418 sh := int32(sr.Dy()) 2419 yscale := float64(sh) / float64(dr.Dy()) 2420 xscale := float64(sw) / float64(dr.Dx()) 2421 swMinus1, shMinus1 := sw-1, sh-1 2422 2423 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2424 sy := (float64(dy)+0.5)*yscale - 0.5 2425 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 2426 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 2427 // sx, below. 2428 sy0 := int32(sy) 2429 yFrac0 := sy - float64(sy0) 2430 yFrac1 := 1 - yFrac0 2431 sy1 := sy0 + 1 2432 if sy < 0 { 2433 sy0, sy1 = 0, 0 2434 yFrac0, yFrac1 = 0, 1 2435 } else if sy1 > shMinus1 { 2436 sy0, sy1 = shMinus1, shMinus1 2437 yFrac0, yFrac1 = 1, 0 2438 } 2439 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 2440 2441 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 2442 sx := (float64(dx)+0.5)*xscale - 0.5 2443 sx0 := int32(sx) 2444 xFrac0 := sx - float64(sx0) 2445 xFrac1 := 1 - xFrac0 2446 sx1 := sx0 + 1 2447 if sx < 0 { 2448 sx0, sx1 = 0, 0 2449 xFrac0, xFrac1 = 0, 1 2450 } else if sx1 > swMinus1 { 2451 sx0, sx1 = swMinus1, swMinus1 2452 xFrac0, xFrac1 = 1, 0 2453 } 2454 2455 s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA() 2456 s00r := float64(s00ru) 2457 s00g := float64(s00gu) 2458 s00b := float64(s00bu) 2459 s00a := float64(s00au) 2460 s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA() 2461 s10r := float64(s10ru) 2462 s10g := float64(s10gu) 2463 s10b := float64(s10bu) 2464 s10a := float64(s10au) 2465 s10r = xFrac1*s00r + xFrac0*s10r 2466 s10g = xFrac1*s00g + xFrac0*s10g 2467 s10b = xFrac1*s00b + xFrac0*s10b 2468 s10a = xFrac1*s00a + xFrac0*s10a 2469 s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA() 2470 s01r := float64(s01ru) 2471 s01g := float64(s01gu) 2472 s01b := float64(s01bu) 2473 s01a := float64(s01au) 2474 s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA() 2475 s11r := float64(s11ru) 2476 s11g := float64(s11gu) 2477 s11b := float64(s11bu) 2478 s11a := float64(s11au) 2479 s11r = xFrac1*s01r + xFrac0*s11r 2480 s11g = xFrac1*s01g + xFrac0*s11g 2481 s11b = xFrac1*s01b + xFrac0*s11b 2482 s11a = xFrac1*s01a + xFrac0*s11a 2483 s11r = yFrac1*s10r + yFrac0*s11r 2484 s11g = yFrac1*s10g + yFrac0*s11g 2485 s11b = yFrac1*s10b + yFrac0*s11b 2486 s11a = yFrac1*s10a + yFrac0*s11a 2487 pr := uint32(s11r) 2488 pg := uint32(s11g) 2489 pb := uint32(s11b) 2490 pa := uint32(s11a) 2491 pa1 := (0xffff - pa) * 0x101 2492 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 2493 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 2494 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 2495 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 2496 } 2497 } 2498 } 2499 2500 func (ablInterpolator) scale_RGBA_Image_Src(dst *image.RGBA, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 2501 sw := int32(sr.Dx()) 2502 sh := int32(sr.Dy()) 2503 yscale := float64(sh) / float64(dr.Dy()) 2504 xscale := float64(sw) / float64(dr.Dx()) 2505 swMinus1, shMinus1 := sw-1, sh-1 2506 2507 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2508 sy := (float64(dy)+0.5)*yscale - 0.5 2509 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 2510 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 2511 // sx, below. 2512 sy0 := int32(sy) 2513 yFrac0 := sy - float64(sy0) 2514 yFrac1 := 1 - yFrac0 2515 sy1 := sy0 + 1 2516 if sy < 0 { 2517 sy0, sy1 = 0, 0 2518 yFrac0, yFrac1 = 0, 1 2519 } else if sy1 > shMinus1 { 2520 sy0, sy1 = shMinus1, shMinus1 2521 yFrac0, yFrac1 = 1, 0 2522 } 2523 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 2524 2525 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 2526 sx := (float64(dx)+0.5)*xscale - 0.5 2527 sx0 := int32(sx) 2528 xFrac0 := sx - float64(sx0) 2529 xFrac1 := 1 - xFrac0 2530 sx1 := sx0 + 1 2531 if sx < 0 { 2532 sx0, sx1 = 0, 0 2533 xFrac0, xFrac1 = 0, 1 2534 } else if sx1 > swMinus1 { 2535 sx0, sx1 = swMinus1, swMinus1 2536 xFrac0, xFrac1 = 1, 0 2537 } 2538 2539 s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA() 2540 s00r := float64(s00ru) 2541 s00g := float64(s00gu) 2542 s00b := float64(s00bu) 2543 s00a := float64(s00au) 2544 s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA() 2545 s10r := float64(s10ru) 2546 s10g := float64(s10gu) 2547 s10b := float64(s10bu) 2548 s10a := float64(s10au) 2549 s10r = xFrac1*s00r + xFrac0*s10r 2550 s10g = xFrac1*s00g + xFrac0*s10g 2551 s10b = xFrac1*s00b + xFrac0*s10b 2552 s10a = xFrac1*s00a + xFrac0*s10a 2553 s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA() 2554 s01r := float64(s01ru) 2555 s01g := float64(s01gu) 2556 s01b := float64(s01bu) 2557 s01a := float64(s01au) 2558 s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA() 2559 s11r := float64(s11ru) 2560 s11g := float64(s11gu) 2561 s11b := float64(s11bu) 2562 s11a := float64(s11au) 2563 s11r = xFrac1*s01r + xFrac0*s11r 2564 s11g = xFrac1*s01g + xFrac0*s11g 2565 s11b = xFrac1*s01b + xFrac0*s11b 2566 s11a = xFrac1*s01a + xFrac0*s11a 2567 s11r = yFrac1*s10r + yFrac0*s11r 2568 s11g = yFrac1*s10g + yFrac0*s11g 2569 s11b = yFrac1*s10b + yFrac0*s11b 2570 s11a = yFrac1*s10a + yFrac0*s11a 2571 pr := uint32(s11r) 2572 pg := uint32(s11g) 2573 pb := uint32(s11b) 2574 pa := uint32(s11a) 2575 dst.Pix[d+0] = uint8(pr >> 8) 2576 dst.Pix[d+1] = uint8(pg >> 8) 2577 dst.Pix[d+2] = uint8(pb >> 8) 2578 dst.Pix[d+3] = uint8(pa >> 8) 2579 } 2580 } 2581 } 2582 2583 func (ablInterpolator) scale_Image_Image_Over(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 2584 sw := int32(sr.Dx()) 2585 sh := int32(sr.Dy()) 2586 yscale := float64(sh) / float64(dr.Dy()) 2587 xscale := float64(sw) / float64(dr.Dx()) 2588 swMinus1, shMinus1 := sw-1, sh-1 2589 srcMask, smp := opts.SrcMask, opts.SrcMaskP 2590 dstMask, dmp := opts.DstMask, opts.DstMaskP 2591 dstColorRGBA64 := &color.RGBA64{} 2592 dstColor := color.Color(dstColorRGBA64) 2593 2594 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2595 sy := (float64(dy)+0.5)*yscale - 0.5 2596 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 2597 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 2598 // sx, below. 2599 sy0 := int32(sy) 2600 yFrac0 := sy - float64(sy0) 2601 yFrac1 := 1 - yFrac0 2602 sy1 := sy0 + 1 2603 if sy < 0 { 2604 sy0, sy1 = 0, 0 2605 yFrac0, yFrac1 = 0, 1 2606 } else if sy1 > shMinus1 { 2607 sy0, sy1 = shMinus1, shMinus1 2608 yFrac0, yFrac1 = 1, 0 2609 } 2610 2611 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 2612 sx := (float64(dx)+0.5)*xscale - 0.5 2613 sx0 := int32(sx) 2614 xFrac0 := sx - float64(sx0) 2615 xFrac1 := 1 - xFrac0 2616 sx1 := sx0 + 1 2617 if sx < 0 { 2618 sx0, sx1 = 0, 0 2619 xFrac0, xFrac1 = 0, 1 2620 } else if sx1 > swMinus1 { 2621 sx0, sx1 = swMinus1, swMinus1 2622 xFrac0, xFrac1 = 1, 0 2623 } 2624 2625 s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA() 2626 if srcMask != nil { 2627 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA() 2628 s00ru = s00ru * ma / 0xffff 2629 s00gu = s00gu * ma / 0xffff 2630 s00bu = s00bu * ma / 0xffff 2631 s00au = s00au * ma / 0xffff 2632 } 2633 s00r := float64(s00ru) 2634 s00g := float64(s00gu) 2635 s00b := float64(s00bu) 2636 s00a := float64(s00au) 2637 s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA() 2638 if srcMask != nil { 2639 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA() 2640 s10ru = s10ru * ma / 0xffff 2641 s10gu = s10gu * ma / 0xffff 2642 s10bu = s10bu * ma / 0xffff 2643 s10au = s10au * ma / 0xffff 2644 } 2645 s10r := float64(s10ru) 2646 s10g := float64(s10gu) 2647 s10b := float64(s10bu) 2648 s10a := float64(s10au) 2649 s10r = xFrac1*s00r + xFrac0*s10r 2650 s10g = xFrac1*s00g + xFrac0*s10g 2651 s10b = xFrac1*s00b + xFrac0*s10b 2652 s10a = xFrac1*s00a + xFrac0*s10a 2653 s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA() 2654 if srcMask != nil { 2655 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA() 2656 s01ru = s01ru * ma / 0xffff 2657 s01gu = s01gu * ma / 0xffff 2658 s01bu = s01bu * ma / 0xffff 2659 s01au = s01au * ma / 0xffff 2660 } 2661 s01r := float64(s01ru) 2662 s01g := float64(s01gu) 2663 s01b := float64(s01bu) 2664 s01a := float64(s01au) 2665 s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA() 2666 if srcMask != nil { 2667 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA() 2668 s11ru = s11ru * ma / 0xffff 2669 s11gu = s11gu * ma / 0xffff 2670 s11bu = s11bu * ma / 0xffff 2671 s11au = s11au * ma / 0xffff 2672 } 2673 s11r := float64(s11ru) 2674 s11g := float64(s11gu) 2675 s11b := float64(s11bu) 2676 s11a := float64(s11au) 2677 s11r = xFrac1*s01r + xFrac0*s11r 2678 s11g = xFrac1*s01g + xFrac0*s11g 2679 s11b = xFrac1*s01b + xFrac0*s11b 2680 s11a = xFrac1*s01a + xFrac0*s11a 2681 s11r = yFrac1*s10r + yFrac0*s11r 2682 s11g = yFrac1*s10g + yFrac0*s11g 2683 s11b = yFrac1*s10b + yFrac0*s11b 2684 s11a = yFrac1*s10a + yFrac0*s11a 2685 pr := uint32(s11r) 2686 pg := uint32(s11g) 2687 pb := uint32(s11b) 2688 pa := uint32(s11a) 2689 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 2690 if dstMask != nil { 2691 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 2692 pr = pr * ma / 0xffff 2693 pg = pg * ma / 0xffff 2694 pb = pb * ma / 0xffff 2695 pa = pa * ma / 0xffff 2696 } 2697 pa1 := 0xffff - pa 2698 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 2699 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 2700 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 2701 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 2702 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 2703 } 2704 } 2705 } 2706 2707 func (ablInterpolator) scale_Image_Image_Src(dst Image, dr, adr image.Rectangle, src image.Image, sr image.Rectangle, opts *Options) { 2708 sw := int32(sr.Dx()) 2709 sh := int32(sr.Dy()) 2710 yscale := float64(sh) / float64(dr.Dy()) 2711 xscale := float64(sw) / float64(dr.Dx()) 2712 swMinus1, shMinus1 := sw-1, sh-1 2713 srcMask, smp := opts.SrcMask, opts.SrcMaskP 2714 dstMask, dmp := opts.DstMask, opts.DstMaskP 2715 dstColorRGBA64 := &color.RGBA64{} 2716 dstColor := color.Color(dstColorRGBA64) 2717 2718 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2719 sy := (float64(dy)+0.5)*yscale - 0.5 2720 // If sy < 0, we will clamp sy0 to 0 anyway, so it doesn't matter if 2721 // we say int32(sy) instead of int32(math.Floor(sy)). Similarly for 2722 // sx, below. 2723 sy0 := int32(sy) 2724 yFrac0 := sy - float64(sy0) 2725 yFrac1 := 1 - yFrac0 2726 sy1 := sy0 + 1 2727 if sy < 0 { 2728 sy0, sy1 = 0, 0 2729 yFrac0, yFrac1 = 0, 1 2730 } else if sy1 > shMinus1 { 2731 sy0, sy1 = shMinus1, shMinus1 2732 yFrac0, yFrac1 = 1, 0 2733 } 2734 2735 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 2736 sx := (float64(dx)+0.5)*xscale - 0.5 2737 sx0 := int32(sx) 2738 xFrac0 := sx - float64(sx0) 2739 xFrac1 := 1 - xFrac0 2740 sx1 := sx0 + 1 2741 if sx < 0 { 2742 sx0, sx1 = 0, 0 2743 xFrac0, xFrac1 = 0, 1 2744 } else if sx1 > swMinus1 { 2745 sx0, sx1 = swMinus1, swMinus1 2746 xFrac0, xFrac1 = 1, 0 2747 } 2748 2749 s00ru, s00gu, s00bu, s00au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy0)).RGBA() 2750 if srcMask != nil { 2751 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy0)).RGBA() 2752 s00ru = s00ru * ma / 0xffff 2753 s00gu = s00gu * ma / 0xffff 2754 s00bu = s00bu * ma / 0xffff 2755 s00au = s00au * ma / 0xffff 2756 } 2757 s00r := float64(s00ru) 2758 s00g := float64(s00gu) 2759 s00b := float64(s00bu) 2760 s00a := float64(s00au) 2761 s10ru, s10gu, s10bu, s10au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy0)).RGBA() 2762 if srcMask != nil { 2763 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy0)).RGBA() 2764 s10ru = s10ru * ma / 0xffff 2765 s10gu = s10gu * ma / 0xffff 2766 s10bu = s10bu * ma / 0xffff 2767 s10au = s10au * ma / 0xffff 2768 } 2769 s10r := float64(s10ru) 2770 s10g := float64(s10gu) 2771 s10b := float64(s10bu) 2772 s10a := float64(s10au) 2773 s10r = xFrac1*s00r + xFrac0*s10r 2774 s10g = xFrac1*s00g + xFrac0*s10g 2775 s10b = xFrac1*s00b + xFrac0*s10b 2776 s10a = xFrac1*s00a + xFrac0*s10a 2777 s01ru, s01gu, s01bu, s01au := src.At(sr.Min.X+int(sx0), sr.Min.Y+int(sy1)).RGBA() 2778 if srcMask != nil { 2779 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx0), smp.Y+sr.Min.Y+int(sy1)).RGBA() 2780 s01ru = s01ru * ma / 0xffff 2781 s01gu = s01gu * ma / 0xffff 2782 s01bu = s01bu * ma / 0xffff 2783 s01au = s01au * ma / 0xffff 2784 } 2785 s01r := float64(s01ru) 2786 s01g := float64(s01gu) 2787 s01b := float64(s01bu) 2788 s01a := float64(s01au) 2789 s11ru, s11gu, s11bu, s11au := src.At(sr.Min.X+int(sx1), sr.Min.Y+int(sy1)).RGBA() 2790 if srcMask != nil { 2791 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(sx1), smp.Y+sr.Min.Y+int(sy1)).RGBA() 2792 s11ru = s11ru * ma / 0xffff 2793 s11gu = s11gu * ma / 0xffff 2794 s11bu = s11bu * ma / 0xffff 2795 s11au = s11au * ma / 0xffff 2796 } 2797 s11r := float64(s11ru) 2798 s11g := float64(s11gu) 2799 s11b := float64(s11bu) 2800 s11a := float64(s11au) 2801 s11r = xFrac1*s01r + xFrac0*s11r 2802 s11g = xFrac1*s01g + xFrac0*s11g 2803 s11b = xFrac1*s01b + xFrac0*s11b 2804 s11a = xFrac1*s01a + xFrac0*s11a 2805 s11r = yFrac1*s10r + yFrac0*s11r 2806 s11g = yFrac1*s10g + yFrac0*s11g 2807 s11b = yFrac1*s10b + yFrac0*s11b 2808 s11a = yFrac1*s10a + yFrac0*s11a 2809 pr := uint32(s11r) 2810 pg := uint32(s11g) 2811 pb := uint32(s11b) 2812 pa := uint32(s11a) 2813 if dstMask != nil { 2814 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 2815 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 2816 pr = pr * ma / 0xffff 2817 pg = pg * ma / 0xffff 2818 pb = pb * ma / 0xffff 2819 pa = pa * ma / 0xffff 2820 pa1 := 0xffff - ma 2821 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 2822 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 2823 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 2824 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 2825 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 2826 } else { 2827 dstColorRGBA64.R = uint16(pr) 2828 dstColorRGBA64.G = uint16(pg) 2829 dstColorRGBA64.B = uint16(pb) 2830 dstColorRGBA64.A = uint16(pa) 2831 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 2832 } 2833 } 2834 } 2835 } 2836 2837 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) { 2838 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2839 dyf := float64(dr.Min.Y+int(dy)) + 0.5 2840 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 2841 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 2842 dxf := float64(dr.Min.X+int(dx)) + 0.5 2843 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 2844 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 2845 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 2846 continue 2847 } 2848 2849 sx -= 0.5 2850 sx0 := int(sx) 2851 xFrac0 := sx - float64(sx0) 2852 xFrac1 := 1 - xFrac0 2853 sx0 += bias.X 2854 sx1 := sx0 + 1 2855 if sx0 < sr.Min.X { 2856 sx0, sx1 = sr.Min.X, sr.Min.X 2857 xFrac0, xFrac1 = 0, 1 2858 } else if sx1 >= sr.Max.X { 2859 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 2860 xFrac0, xFrac1 = 1, 0 2861 } 2862 2863 sy -= 0.5 2864 sy0 := int(sy) 2865 yFrac0 := sy - float64(sy0) 2866 yFrac1 := 1 - yFrac0 2867 sy0 += bias.Y 2868 sy1 := sy0 + 1 2869 if sy0 < sr.Min.Y { 2870 sy0, sy1 = sr.Min.Y, sr.Min.Y 2871 yFrac0, yFrac1 = 0, 1 2872 } else if sy1 >= sr.Max.Y { 2873 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 2874 yFrac0, yFrac1 = 1, 0 2875 } 2876 2877 s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X) 2878 s00ru := uint32(src.Pix[s00i]) * 0x101 2879 s00r := float64(s00ru) 2880 s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X) 2881 s10ru := uint32(src.Pix[s10i]) * 0x101 2882 s10r := float64(s10ru) 2883 s10r = xFrac1*s00r + xFrac0*s10r 2884 s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0 - src.Rect.Min.X) 2885 s01ru := uint32(src.Pix[s01i]) * 0x101 2886 s01r := float64(s01ru) 2887 s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1 - src.Rect.Min.X) 2888 s11ru := uint32(src.Pix[s11i]) * 0x101 2889 s11r := float64(s11ru) 2890 s11r = xFrac1*s01r + xFrac0*s11r 2891 s11r = yFrac1*s10r + yFrac0*s11r 2892 pr := uint32(s11r) 2893 out := uint8(pr >> 8) 2894 dst.Pix[d+0] = out 2895 dst.Pix[d+1] = out 2896 dst.Pix[d+2] = out 2897 dst.Pix[d+3] = 0xff 2898 } 2899 } 2900 } 2901 2902 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) { 2903 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 2904 dyf := float64(dr.Min.Y+int(dy)) + 0.5 2905 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 2906 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 2907 dxf := float64(dr.Min.X+int(dx)) + 0.5 2908 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 2909 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 2910 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 2911 continue 2912 } 2913 2914 sx -= 0.5 2915 sx0 := int(sx) 2916 xFrac0 := sx - float64(sx0) 2917 xFrac1 := 1 - xFrac0 2918 sx0 += bias.X 2919 sx1 := sx0 + 1 2920 if sx0 < sr.Min.X { 2921 sx0, sx1 = sr.Min.X, sr.Min.X 2922 xFrac0, xFrac1 = 0, 1 2923 } else if sx1 >= sr.Max.X { 2924 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 2925 xFrac0, xFrac1 = 1, 0 2926 } 2927 2928 sy -= 0.5 2929 sy0 := int(sy) 2930 yFrac0 := sy - float64(sy0) 2931 yFrac1 := 1 - yFrac0 2932 sy0 += bias.Y 2933 sy1 := sy0 + 1 2934 if sy0 < sr.Min.Y { 2935 sy0, sy1 = sr.Min.Y, sr.Min.Y 2936 yFrac0, yFrac1 = 0, 1 2937 } else if sy1 >= sr.Max.Y { 2938 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 2939 yFrac0, yFrac1 = 1, 0 2940 } 2941 2942 s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 2943 s00au := uint32(src.Pix[s00i+3]) * 0x101 2944 s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff 2945 s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff 2946 s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff 2947 s00r := float64(s00ru) 2948 s00g := float64(s00gu) 2949 s00b := float64(s00bu) 2950 s00a := float64(s00au) 2951 s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 2952 s10au := uint32(src.Pix[s10i+3]) * 0x101 2953 s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff 2954 s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff 2955 s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff 2956 s10r := float64(s10ru) 2957 s10g := float64(s10gu) 2958 s10b := float64(s10bu) 2959 s10a := float64(s10au) 2960 s10r = xFrac1*s00r + xFrac0*s10r 2961 s10g = xFrac1*s00g + xFrac0*s10g 2962 s10b = xFrac1*s00b + xFrac0*s10b 2963 s10a = xFrac1*s00a + xFrac0*s10a 2964 s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 2965 s01au := uint32(src.Pix[s01i+3]) * 0x101 2966 s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff 2967 s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff 2968 s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff 2969 s01r := float64(s01ru) 2970 s01g := float64(s01gu) 2971 s01b := float64(s01bu) 2972 s01a := float64(s01au) 2973 s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 2974 s11au := uint32(src.Pix[s11i+3]) * 0x101 2975 s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff 2976 s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff 2977 s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff 2978 s11r := float64(s11ru) 2979 s11g := float64(s11gu) 2980 s11b := float64(s11bu) 2981 s11a := float64(s11au) 2982 s11r = xFrac1*s01r + xFrac0*s11r 2983 s11g = xFrac1*s01g + xFrac0*s11g 2984 s11b = xFrac1*s01b + xFrac0*s11b 2985 s11a = xFrac1*s01a + xFrac0*s11a 2986 s11r = yFrac1*s10r + yFrac0*s11r 2987 s11g = yFrac1*s10g + yFrac0*s11g 2988 s11b = yFrac1*s10b + yFrac0*s11b 2989 s11a = yFrac1*s10a + yFrac0*s11a 2990 pr := uint32(s11r) 2991 pg := uint32(s11g) 2992 pb := uint32(s11b) 2993 pa := uint32(s11a) 2994 pa1 := (0xffff - pa) * 0x101 2995 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 2996 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 2997 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 2998 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 2999 } 3000 } 3001 } 3002 3003 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) { 3004 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3005 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3006 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3007 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3008 dxf := float64(dr.Min.X+int(dx)) + 0.5 3009 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3010 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3011 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3012 continue 3013 } 3014 3015 sx -= 0.5 3016 sx0 := int(sx) 3017 xFrac0 := sx - float64(sx0) 3018 xFrac1 := 1 - xFrac0 3019 sx0 += bias.X 3020 sx1 := sx0 + 1 3021 if sx0 < sr.Min.X { 3022 sx0, sx1 = sr.Min.X, sr.Min.X 3023 xFrac0, xFrac1 = 0, 1 3024 } else if sx1 >= sr.Max.X { 3025 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3026 xFrac0, xFrac1 = 1, 0 3027 } 3028 3029 sy -= 0.5 3030 sy0 := int(sy) 3031 yFrac0 := sy - float64(sy0) 3032 yFrac1 := 1 - yFrac0 3033 sy0 += bias.Y 3034 sy1 := sy0 + 1 3035 if sy0 < sr.Min.Y { 3036 sy0, sy1 = sr.Min.Y, sr.Min.Y 3037 yFrac0, yFrac1 = 0, 1 3038 } else if sy1 >= sr.Max.Y { 3039 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3040 yFrac0, yFrac1 = 1, 0 3041 } 3042 3043 s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 3044 s00au := uint32(src.Pix[s00i+3]) * 0x101 3045 s00ru := uint32(src.Pix[s00i+0]) * s00au / 0xff 3046 s00gu := uint32(src.Pix[s00i+1]) * s00au / 0xff 3047 s00bu := uint32(src.Pix[s00i+2]) * s00au / 0xff 3048 s00r := float64(s00ru) 3049 s00g := float64(s00gu) 3050 s00b := float64(s00bu) 3051 s00a := float64(s00au) 3052 s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 3053 s10au := uint32(src.Pix[s10i+3]) * 0x101 3054 s10ru := uint32(src.Pix[s10i+0]) * s10au / 0xff 3055 s10gu := uint32(src.Pix[s10i+1]) * s10au / 0xff 3056 s10bu := uint32(src.Pix[s10i+2]) * s10au / 0xff 3057 s10r := float64(s10ru) 3058 s10g := float64(s10gu) 3059 s10b := float64(s10bu) 3060 s10a := float64(s10au) 3061 s10r = xFrac1*s00r + xFrac0*s10r 3062 s10g = xFrac1*s00g + xFrac0*s10g 3063 s10b = xFrac1*s00b + xFrac0*s10b 3064 s10a = xFrac1*s00a + xFrac0*s10a 3065 s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 3066 s01au := uint32(src.Pix[s01i+3]) * 0x101 3067 s01ru := uint32(src.Pix[s01i+0]) * s01au / 0xff 3068 s01gu := uint32(src.Pix[s01i+1]) * s01au / 0xff 3069 s01bu := uint32(src.Pix[s01i+2]) * s01au / 0xff 3070 s01r := float64(s01ru) 3071 s01g := float64(s01gu) 3072 s01b := float64(s01bu) 3073 s01a := float64(s01au) 3074 s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 3075 s11au := uint32(src.Pix[s11i+3]) * 0x101 3076 s11ru := uint32(src.Pix[s11i+0]) * s11au / 0xff 3077 s11gu := uint32(src.Pix[s11i+1]) * s11au / 0xff 3078 s11bu := uint32(src.Pix[s11i+2]) * s11au / 0xff 3079 s11r := float64(s11ru) 3080 s11g := float64(s11gu) 3081 s11b := float64(s11bu) 3082 s11a := float64(s11au) 3083 s11r = xFrac1*s01r + xFrac0*s11r 3084 s11g = xFrac1*s01g + xFrac0*s11g 3085 s11b = xFrac1*s01b + xFrac0*s11b 3086 s11a = xFrac1*s01a + xFrac0*s11a 3087 s11r = yFrac1*s10r + yFrac0*s11r 3088 s11g = yFrac1*s10g + yFrac0*s11g 3089 s11b = yFrac1*s10b + yFrac0*s11b 3090 s11a = yFrac1*s10a + yFrac0*s11a 3091 pr := uint32(s11r) 3092 pg := uint32(s11g) 3093 pb := uint32(s11b) 3094 pa := uint32(s11a) 3095 dst.Pix[d+0] = uint8(pr >> 8) 3096 dst.Pix[d+1] = uint8(pg >> 8) 3097 dst.Pix[d+2] = uint8(pb >> 8) 3098 dst.Pix[d+3] = uint8(pa >> 8) 3099 } 3100 } 3101 } 3102 3103 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) { 3104 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3105 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3106 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3107 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3108 dxf := float64(dr.Min.X+int(dx)) + 0.5 3109 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3110 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3111 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3112 continue 3113 } 3114 3115 sx -= 0.5 3116 sx0 := int(sx) 3117 xFrac0 := sx - float64(sx0) 3118 xFrac1 := 1 - xFrac0 3119 sx0 += bias.X 3120 sx1 := sx0 + 1 3121 if sx0 < sr.Min.X { 3122 sx0, sx1 = sr.Min.X, sr.Min.X 3123 xFrac0, xFrac1 = 0, 1 3124 } else if sx1 >= sr.Max.X { 3125 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3126 xFrac0, xFrac1 = 1, 0 3127 } 3128 3129 sy -= 0.5 3130 sy0 := int(sy) 3131 yFrac0 := sy - float64(sy0) 3132 yFrac1 := 1 - yFrac0 3133 sy0 += bias.Y 3134 sy1 := sy0 + 1 3135 if sy0 < sr.Min.Y { 3136 sy0, sy1 = sr.Min.Y, sr.Min.Y 3137 yFrac0, yFrac1 = 0, 1 3138 } else if sy1 >= sr.Max.Y { 3139 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3140 yFrac0, yFrac1 = 1, 0 3141 } 3142 3143 s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 3144 s00ru := uint32(src.Pix[s00i+0]) * 0x101 3145 s00gu := uint32(src.Pix[s00i+1]) * 0x101 3146 s00bu := uint32(src.Pix[s00i+2]) * 0x101 3147 s00au := uint32(src.Pix[s00i+3]) * 0x101 3148 s00r := float64(s00ru) 3149 s00g := float64(s00gu) 3150 s00b := float64(s00bu) 3151 s00a := float64(s00au) 3152 s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 3153 s10ru := uint32(src.Pix[s10i+0]) * 0x101 3154 s10gu := uint32(src.Pix[s10i+1]) * 0x101 3155 s10bu := uint32(src.Pix[s10i+2]) * 0x101 3156 s10au := uint32(src.Pix[s10i+3]) * 0x101 3157 s10r := float64(s10ru) 3158 s10g := float64(s10gu) 3159 s10b := float64(s10bu) 3160 s10a := float64(s10au) 3161 s10r = xFrac1*s00r + xFrac0*s10r 3162 s10g = xFrac1*s00g + xFrac0*s10g 3163 s10b = xFrac1*s00b + xFrac0*s10b 3164 s10a = xFrac1*s00a + xFrac0*s10a 3165 s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 3166 s01ru := uint32(src.Pix[s01i+0]) * 0x101 3167 s01gu := uint32(src.Pix[s01i+1]) * 0x101 3168 s01bu := uint32(src.Pix[s01i+2]) * 0x101 3169 s01au := uint32(src.Pix[s01i+3]) * 0x101 3170 s01r := float64(s01ru) 3171 s01g := float64(s01gu) 3172 s01b := float64(s01bu) 3173 s01a := float64(s01au) 3174 s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 3175 s11ru := uint32(src.Pix[s11i+0]) * 0x101 3176 s11gu := uint32(src.Pix[s11i+1]) * 0x101 3177 s11bu := uint32(src.Pix[s11i+2]) * 0x101 3178 s11au := uint32(src.Pix[s11i+3]) * 0x101 3179 s11r := float64(s11ru) 3180 s11g := float64(s11gu) 3181 s11b := float64(s11bu) 3182 s11a := float64(s11au) 3183 s11r = xFrac1*s01r + xFrac0*s11r 3184 s11g = xFrac1*s01g + xFrac0*s11g 3185 s11b = xFrac1*s01b + xFrac0*s11b 3186 s11a = xFrac1*s01a + xFrac0*s11a 3187 s11r = yFrac1*s10r + yFrac0*s11r 3188 s11g = yFrac1*s10g + yFrac0*s11g 3189 s11b = yFrac1*s10b + yFrac0*s11b 3190 s11a = yFrac1*s10a + yFrac0*s11a 3191 pr := uint32(s11r) 3192 pg := uint32(s11g) 3193 pb := uint32(s11b) 3194 pa := uint32(s11a) 3195 pa1 := (0xffff - pa) * 0x101 3196 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 3197 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 3198 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 3199 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 3200 } 3201 } 3202 } 3203 3204 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) { 3205 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3206 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3207 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3208 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3209 dxf := float64(dr.Min.X+int(dx)) + 0.5 3210 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3211 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3212 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3213 continue 3214 } 3215 3216 sx -= 0.5 3217 sx0 := int(sx) 3218 xFrac0 := sx - float64(sx0) 3219 xFrac1 := 1 - xFrac0 3220 sx0 += bias.X 3221 sx1 := sx0 + 1 3222 if sx0 < sr.Min.X { 3223 sx0, sx1 = sr.Min.X, sr.Min.X 3224 xFrac0, xFrac1 = 0, 1 3225 } else if sx1 >= sr.Max.X { 3226 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3227 xFrac0, xFrac1 = 1, 0 3228 } 3229 3230 sy -= 0.5 3231 sy0 := int(sy) 3232 yFrac0 := sy - float64(sy0) 3233 yFrac1 := 1 - yFrac0 3234 sy0 += bias.Y 3235 sy1 := sy0 + 1 3236 if sy0 < sr.Min.Y { 3237 sy0, sy1 = sr.Min.Y, sr.Min.Y 3238 yFrac0, yFrac1 = 0, 1 3239 } else if sy1 >= sr.Max.Y { 3240 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3241 yFrac0, yFrac1 = 1, 0 3242 } 3243 3244 s00i := (sy0-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 3245 s00ru := uint32(src.Pix[s00i+0]) * 0x101 3246 s00gu := uint32(src.Pix[s00i+1]) * 0x101 3247 s00bu := uint32(src.Pix[s00i+2]) * 0x101 3248 s00au := uint32(src.Pix[s00i+3]) * 0x101 3249 s00r := float64(s00ru) 3250 s00g := float64(s00gu) 3251 s00b := float64(s00bu) 3252 s00a := float64(s00au) 3253 s10i := (sy0-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 3254 s10ru := uint32(src.Pix[s10i+0]) * 0x101 3255 s10gu := uint32(src.Pix[s10i+1]) * 0x101 3256 s10bu := uint32(src.Pix[s10i+2]) * 0x101 3257 s10au := uint32(src.Pix[s10i+3]) * 0x101 3258 s10r := float64(s10ru) 3259 s10g := float64(s10gu) 3260 s10b := float64(s10bu) 3261 s10a := float64(s10au) 3262 s10r = xFrac1*s00r + xFrac0*s10r 3263 s10g = xFrac1*s00g + xFrac0*s10g 3264 s10b = xFrac1*s00b + xFrac0*s10b 3265 s10a = xFrac1*s00a + xFrac0*s10a 3266 s01i := (sy1-src.Rect.Min.Y)*src.Stride + (sx0-src.Rect.Min.X)*4 3267 s01ru := uint32(src.Pix[s01i+0]) * 0x101 3268 s01gu := uint32(src.Pix[s01i+1]) * 0x101 3269 s01bu := uint32(src.Pix[s01i+2]) * 0x101 3270 s01au := uint32(src.Pix[s01i+3]) * 0x101 3271 s01r := float64(s01ru) 3272 s01g := float64(s01gu) 3273 s01b := float64(s01bu) 3274 s01a := float64(s01au) 3275 s11i := (sy1-src.Rect.Min.Y)*src.Stride + (sx1-src.Rect.Min.X)*4 3276 s11ru := uint32(src.Pix[s11i+0]) * 0x101 3277 s11gu := uint32(src.Pix[s11i+1]) * 0x101 3278 s11bu := uint32(src.Pix[s11i+2]) * 0x101 3279 s11au := uint32(src.Pix[s11i+3]) * 0x101 3280 s11r := float64(s11ru) 3281 s11g := float64(s11gu) 3282 s11b := float64(s11bu) 3283 s11a := float64(s11au) 3284 s11r = xFrac1*s01r + xFrac0*s11r 3285 s11g = xFrac1*s01g + xFrac0*s11g 3286 s11b = xFrac1*s01b + xFrac0*s11b 3287 s11a = xFrac1*s01a + xFrac0*s11a 3288 s11r = yFrac1*s10r + yFrac0*s11r 3289 s11g = yFrac1*s10g + yFrac0*s11g 3290 s11b = yFrac1*s10b + yFrac0*s11b 3291 s11a = yFrac1*s10a + yFrac0*s11a 3292 pr := uint32(s11r) 3293 pg := uint32(s11g) 3294 pb := uint32(s11b) 3295 pa := uint32(s11a) 3296 dst.Pix[d+0] = uint8(pr >> 8) 3297 dst.Pix[d+1] = uint8(pg >> 8) 3298 dst.Pix[d+2] = uint8(pb >> 8) 3299 dst.Pix[d+3] = uint8(pa >> 8) 3300 } 3301 } 3302 } 3303 3304 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) { 3305 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3306 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3307 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3308 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3309 dxf := float64(dr.Min.X+int(dx)) + 0.5 3310 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3311 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3312 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3313 continue 3314 } 3315 3316 sx -= 0.5 3317 sx0 := int(sx) 3318 xFrac0 := sx - float64(sx0) 3319 xFrac1 := 1 - xFrac0 3320 sx0 += bias.X 3321 sx1 := sx0 + 1 3322 if sx0 < sr.Min.X { 3323 sx0, sx1 = sr.Min.X, sr.Min.X 3324 xFrac0, xFrac1 = 0, 1 3325 } else if sx1 >= sr.Max.X { 3326 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3327 xFrac0, xFrac1 = 1, 0 3328 } 3329 3330 sy -= 0.5 3331 sy0 := int(sy) 3332 yFrac0 := sy - float64(sy0) 3333 yFrac1 := 1 - yFrac0 3334 sy0 += bias.Y 3335 sy1 := sy0 + 1 3336 if sy0 < sr.Min.Y { 3337 sy0, sy1 = sr.Min.Y, sr.Min.Y 3338 yFrac0, yFrac1 = 0, 1 3339 } else if sy1 >= sr.Max.Y { 3340 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3341 yFrac0, yFrac1 = 1, 0 3342 } 3343 3344 s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3345 s00j := (sy0-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X) 3346 3347 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3348 s00yy1 := int(src.Y[s00i]) * 0x10100 3349 s00cb1 := int(src.Cb[s00j]) - 128 3350 s00cr1 := int(src.Cr[s00j]) - 128 3351 s00ru := (s00yy1 + 91881*s00cr1) >> 8 3352 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 3353 s00bu := (s00yy1 + 116130*s00cb1) >> 8 3354 if s00ru < 0 { 3355 s00ru = 0 3356 } else if s00ru > 0xffff { 3357 s00ru = 0xffff 3358 } 3359 if s00gu < 0 { 3360 s00gu = 0 3361 } else if s00gu > 0xffff { 3362 s00gu = 0xffff 3363 } 3364 if s00bu < 0 { 3365 s00bu = 0 3366 } else if s00bu > 0xffff { 3367 s00bu = 0xffff 3368 } 3369 3370 s00r := float64(s00ru) 3371 s00g := float64(s00gu) 3372 s00b := float64(s00bu) 3373 s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3374 s10j := (sy0-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X) 3375 3376 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3377 s10yy1 := int(src.Y[s10i]) * 0x10100 3378 s10cb1 := int(src.Cb[s10j]) - 128 3379 s10cr1 := int(src.Cr[s10j]) - 128 3380 s10ru := (s10yy1 + 91881*s10cr1) >> 8 3381 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 3382 s10bu := (s10yy1 + 116130*s10cb1) >> 8 3383 if s10ru < 0 { 3384 s10ru = 0 3385 } else if s10ru > 0xffff { 3386 s10ru = 0xffff 3387 } 3388 if s10gu < 0 { 3389 s10gu = 0 3390 } else if s10gu > 0xffff { 3391 s10gu = 0xffff 3392 } 3393 if s10bu < 0 { 3394 s10bu = 0 3395 } else if s10bu > 0xffff { 3396 s10bu = 0xffff 3397 } 3398 3399 s10r := float64(s10ru) 3400 s10g := float64(s10gu) 3401 s10b := float64(s10bu) 3402 s10r = xFrac1*s00r + xFrac0*s10r 3403 s10g = xFrac1*s00g + xFrac0*s10g 3404 s10b = xFrac1*s00b + xFrac0*s10b 3405 s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3406 s01j := (sy1-src.Rect.Min.Y)*src.CStride + (sx0 - src.Rect.Min.X) 3407 3408 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3409 s01yy1 := int(src.Y[s01i]) * 0x10100 3410 s01cb1 := int(src.Cb[s01j]) - 128 3411 s01cr1 := int(src.Cr[s01j]) - 128 3412 s01ru := (s01yy1 + 91881*s01cr1) >> 8 3413 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 3414 s01bu := (s01yy1 + 116130*s01cb1) >> 8 3415 if s01ru < 0 { 3416 s01ru = 0 3417 } else if s01ru > 0xffff { 3418 s01ru = 0xffff 3419 } 3420 if s01gu < 0 { 3421 s01gu = 0 3422 } else if s01gu > 0xffff { 3423 s01gu = 0xffff 3424 } 3425 if s01bu < 0 { 3426 s01bu = 0 3427 } else if s01bu > 0xffff { 3428 s01bu = 0xffff 3429 } 3430 3431 s01r := float64(s01ru) 3432 s01g := float64(s01gu) 3433 s01b := float64(s01bu) 3434 s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3435 s11j := (sy1-src.Rect.Min.Y)*src.CStride + (sx1 - src.Rect.Min.X) 3436 3437 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3438 s11yy1 := int(src.Y[s11i]) * 0x10100 3439 s11cb1 := int(src.Cb[s11j]) - 128 3440 s11cr1 := int(src.Cr[s11j]) - 128 3441 s11ru := (s11yy1 + 91881*s11cr1) >> 8 3442 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 3443 s11bu := (s11yy1 + 116130*s11cb1) >> 8 3444 if s11ru < 0 { 3445 s11ru = 0 3446 } else if s11ru > 0xffff { 3447 s11ru = 0xffff 3448 } 3449 if s11gu < 0 { 3450 s11gu = 0 3451 } else if s11gu > 0xffff { 3452 s11gu = 0xffff 3453 } 3454 if s11bu < 0 { 3455 s11bu = 0 3456 } else if s11bu > 0xffff { 3457 s11bu = 0xffff 3458 } 3459 3460 s11r := float64(s11ru) 3461 s11g := float64(s11gu) 3462 s11b := float64(s11bu) 3463 s11r = xFrac1*s01r + xFrac0*s11r 3464 s11g = xFrac1*s01g + xFrac0*s11g 3465 s11b = xFrac1*s01b + xFrac0*s11b 3466 s11r = yFrac1*s10r + yFrac0*s11r 3467 s11g = yFrac1*s10g + yFrac0*s11g 3468 s11b = yFrac1*s10b + yFrac0*s11b 3469 pr := uint32(s11r) 3470 pg := uint32(s11g) 3471 pb := uint32(s11b) 3472 dst.Pix[d+0] = uint8(pr >> 8) 3473 dst.Pix[d+1] = uint8(pg >> 8) 3474 dst.Pix[d+2] = uint8(pb >> 8) 3475 dst.Pix[d+3] = 0xff 3476 } 3477 } 3478 } 3479 3480 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) { 3481 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3482 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3483 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3484 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3485 dxf := float64(dr.Min.X+int(dx)) + 0.5 3486 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3487 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3488 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3489 continue 3490 } 3491 3492 sx -= 0.5 3493 sx0 := int(sx) 3494 xFrac0 := sx - float64(sx0) 3495 xFrac1 := 1 - xFrac0 3496 sx0 += bias.X 3497 sx1 := sx0 + 1 3498 if sx0 < sr.Min.X { 3499 sx0, sx1 = sr.Min.X, sr.Min.X 3500 xFrac0, xFrac1 = 0, 1 3501 } else if sx1 >= sr.Max.X { 3502 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3503 xFrac0, xFrac1 = 1, 0 3504 } 3505 3506 sy -= 0.5 3507 sy0 := int(sy) 3508 yFrac0 := sy - float64(sy0) 3509 yFrac1 := 1 - yFrac0 3510 sy0 += bias.Y 3511 sy1 := sy0 + 1 3512 if sy0 < sr.Min.Y { 3513 sy0, sy1 = sr.Min.Y, sr.Min.Y 3514 yFrac0, yFrac1 = 0, 1 3515 } else if sy1 >= sr.Max.Y { 3516 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3517 yFrac0, yFrac1 = 1, 0 3518 } 3519 3520 s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3521 s00j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2) 3522 3523 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3524 s00yy1 := int(src.Y[s00i]) * 0x10100 3525 s00cb1 := int(src.Cb[s00j]) - 128 3526 s00cr1 := int(src.Cr[s00j]) - 128 3527 s00ru := (s00yy1 + 91881*s00cr1) >> 8 3528 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 3529 s00bu := (s00yy1 + 116130*s00cb1) >> 8 3530 if s00ru < 0 { 3531 s00ru = 0 3532 } else if s00ru > 0xffff { 3533 s00ru = 0xffff 3534 } 3535 if s00gu < 0 { 3536 s00gu = 0 3537 } else if s00gu > 0xffff { 3538 s00gu = 0xffff 3539 } 3540 if s00bu < 0 { 3541 s00bu = 0 3542 } else if s00bu > 0xffff { 3543 s00bu = 0xffff 3544 } 3545 3546 s00r := float64(s00ru) 3547 s00g := float64(s00gu) 3548 s00b := float64(s00bu) 3549 s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3550 s10j := (sy0-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2) 3551 3552 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3553 s10yy1 := int(src.Y[s10i]) * 0x10100 3554 s10cb1 := int(src.Cb[s10j]) - 128 3555 s10cr1 := int(src.Cr[s10j]) - 128 3556 s10ru := (s10yy1 + 91881*s10cr1) >> 8 3557 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 3558 s10bu := (s10yy1 + 116130*s10cb1) >> 8 3559 if s10ru < 0 { 3560 s10ru = 0 3561 } else if s10ru > 0xffff { 3562 s10ru = 0xffff 3563 } 3564 if s10gu < 0 { 3565 s10gu = 0 3566 } else if s10gu > 0xffff { 3567 s10gu = 0xffff 3568 } 3569 if s10bu < 0 { 3570 s10bu = 0 3571 } else if s10bu > 0xffff { 3572 s10bu = 0xffff 3573 } 3574 3575 s10r := float64(s10ru) 3576 s10g := float64(s10gu) 3577 s10b := float64(s10bu) 3578 s10r = xFrac1*s00r + xFrac0*s10r 3579 s10g = xFrac1*s00g + xFrac0*s10g 3580 s10b = xFrac1*s00b + xFrac0*s10b 3581 s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3582 s01j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2) 3583 3584 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3585 s01yy1 := int(src.Y[s01i]) * 0x10100 3586 s01cb1 := int(src.Cb[s01j]) - 128 3587 s01cr1 := int(src.Cr[s01j]) - 128 3588 s01ru := (s01yy1 + 91881*s01cr1) >> 8 3589 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 3590 s01bu := (s01yy1 + 116130*s01cb1) >> 8 3591 if s01ru < 0 { 3592 s01ru = 0 3593 } else if s01ru > 0xffff { 3594 s01ru = 0xffff 3595 } 3596 if s01gu < 0 { 3597 s01gu = 0 3598 } else if s01gu > 0xffff { 3599 s01gu = 0xffff 3600 } 3601 if s01bu < 0 { 3602 s01bu = 0 3603 } else if s01bu > 0xffff { 3604 s01bu = 0xffff 3605 } 3606 3607 s01r := float64(s01ru) 3608 s01g := float64(s01gu) 3609 s01b := float64(s01bu) 3610 s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3611 s11j := (sy1-src.Rect.Min.Y)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2) 3612 3613 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3614 s11yy1 := int(src.Y[s11i]) * 0x10100 3615 s11cb1 := int(src.Cb[s11j]) - 128 3616 s11cr1 := int(src.Cr[s11j]) - 128 3617 s11ru := (s11yy1 + 91881*s11cr1) >> 8 3618 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 3619 s11bu := (s11yy1 + 116130*s11cb1) >> 8 3620 if s11ru < 0 { 3621 s11ru = 0 3622 } else if s11ru > 0xffff { 3623 s11ru = 0xffff 3624 } 3625 if s11gu < 0 { 3626 s11gu = 0 3627 } else if s11gu > 0xffff { 3628 s11gu = 0xffff 3629 } 3630 if s11bu < 0 { 3631 s11bu = 0 3632 } else if s11bu > 0xffff { 3633 s11bu = 0xffff 3634 } 3635 3636 s11r := float64(s11ru) 3637 s11g := float64(s11gu) 3638 s11b := float64(s11bu) 3639 s11r = xFrac1*s01r + xFrac0*s11r 3640 s11g = xFrac1*s01g + xFrac0*s11g 3641 s11b = xFrac1*s01b + xFrac0*s11b 3642 s11r = yFrac1*s10r + yFrac0*s11r 3643 s11g = yFrac1*s10g + yFrac0*s11g 3644 s11b = yFrac1*s10b + yFrac0*s11b 3645 pr := uint32(s11r) 3646 pg := uint32(s11g) 3647 pb := uint32(s11b) 3648 dst.Pix[d+0] = uint8(pr >> 8) 3649 dst.Pix[d+1] = uint8(pg >> 8) 3650 dst.Pix[d+2] = uint8(pb >> 8) 3651 dst.Pix[d+3] = 0xff 3652 } 3653 } 3654 } 3655 3656 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) { 3657 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3658 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3659 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3660 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3661 dxf := float64(dr.Min.X+int(dx)) + 0.5 3662 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3663 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3664 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3665 continue 3666 } 3667 3668 sx -= 0.5 3669 sx0 := int(sx) 3670 xFrac0 := sx - float64(sx0) 3671 xFrac1 := 1 - xFrac0 3672 sx0 += bias.X 3673 sx1 := sx0 + 1 3674 if sx0 < sr.Min.X { 3675 sx0, sx1 = sr.Min.X, sr.Min.X 3676 xFrac0, xFrac1 = 0, 1 3677 } else if sx1 >= sr.Max.X { 3678 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3679 xFrac0, xFrac1 = 1, 0 3680 } 3681 3682 sy -= 0.5 3683 sy0 := int(sy) 3684 yFrac0 := sy - float64(sy0) 3685 yFrac1 := 1 - yFrac0 3686 sy0 += bias.Y 3687 sy1 := sy0 + 1 3688 if sy0 < sr.Min.Y { 3689 sy0, sy1 = sr.Min.Y, sr.Min.Y 3690 yFrac0, yFrac1 = 0, 1 3691 } else if sy1 >= sr.Max.Y { 3692 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3693 yFrac0, yFrac1 = 1, 0 3694 } 3695 3696 s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3697 s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2) 3698 3699 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3700 s00yy1 := int(src.Y[s00i]) * 0x10100 3701 s00cb1 := int(src.Cb[s00j]) - 128 3702 s00cr1 := int(src.Cr[s00j]) - 128 3703 s00ru := (s00yy1 + 91881*s00cr1) >> 8 3704 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 3705 s00bu := (s00yy1 + 116130*s00cb1) >> 8 3706 if s00ru < 0 { 3707 s00ru = 0 3708 } else if s00ru > 0xffff { 3709 s00ru = 0xffff 3710 } 3711 if s00gu < 0 { 3712 s00gu = 0 3713 } else if s00gu > 0xffff { 3714 s00gu = 0xffff 3715 } 3716 if s00bu < 0 { 3717 s00bu = 0 3718 } else if s00bu > 0xffff { 3719 s00bu = 0xffff 3720 } 3721 3722 s00r := float64(s00ru) 3723 s00g := float64(s00gu) 3724 s00b := float64(s00bu) 3725 s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3726 s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2) 3727 3728 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3729 s10yy1 := int(src.Y[s10i]) * 0x10100 3730 s10cb1 := int(src.Cb[s10j]) - 128 3731 s10cr1 := int(src.Cr[s10j]) - 128 3732 s10ru := (s10yy1 + 91881*s10cr1) >> 8 3733 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 3734 s10bu := (s10yy1 + 116130*s10cb1) >> 8 3735 if s10ru < 0 { 3736 s10ru = 0 3737 } else if s10ru > 0xffff { 3738 s10ru = 0xffff 3739 } 3740 if s10gu < 0 { 3741 s10gu = 0 3742 } else if s10gu > 0xffff { 3743 s10gu = 0xffff 3744 } 3745 if s10bu < 0 { 3746 s10bu = 0 3747 } else if s10bu > 0xffff { 3748 s10bu = 0xffff 3749 } 3750 3751 s10r := float64(s10ru) 3752 s10g := float64(s10gu) 3753 s10b := float64(s10bu) 3754 s10r = xFrac1*s00r + xFrac0*s10r 3755 s10g = xFrac1*s00g + xFrac0*s10g 3756 s10b = xFrac1*s00b + xFrac0*s10b 3757 s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3758 s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx0)/2 - src.Rect.Min.X/2) 3759 3760 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3761 s01yy1 := int(src.Y[s01i]) * 0x10100 3762 s01cb1 := int(src.Cb[s01j]) - 128 3763 s01cr1 := int(src.Cr[s01j]) - 128 3764 s01ru := (s01yy1 + 91881*s01cr1) >> 8 3765 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 3766 s01bu := (s01yy1 + 116130*s01cb1) >> 8 3767 if s01ru < 0 { 3768 s01ru = 0 3769 } else if s01ru > 0xffff { 3770 s01ru = 0xffff 3771 } 3772 if s01gu < 0 { 3773 s01gu = 0 3774 } else if s01gu > 0xffff { 3775 s01gu = 0xffff 3776 } 3777 if s01bu < 0 { 3778 s01bu = 0 3779 } else if s01bu > 0xffff { 3780 s01bu = 0xffff 3781 } 3782 3783 s01r := float64(s01ru) 3784 s01g := float64(s01gu) 3785 s01b := float64(s01bu) 3786 s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3787 s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + ((sx1)/2 - src.Rect.Min.X/2) 3788 3789 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3790 s11yy1 := int(src.Y[s11i]) * 0x10100 3791 s11cb1 := int(src.Cb[s11j]) - 128 3792 s11cr1 := int(src.Cr[s11j]) - 128 3793 s11ru := (s11yy1 + 91881*s11cr1) >> 8 3794 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 3795 s11bu := (s11yy1 + 116130*s11cb1) >> 8 3796 if s11ru < 0 { 3797 s11ru = 0 3798 } else if s11ru > 0xffff { 3799 s11ru = 0xffff 3800 } 3801 if s11gu < 0 { 3802 s11gu = 0 3803 } else if s11gu > 0xffff { 3804 s11gu = 0xffff 3805 } 3806 if s11bu < 0 { 3807 s11bu = 0 3808 } else if s11bu > 0xffff { 3809 s11bu = 0xffff 3810 } 3811 3812 s11r := float64(s11ru) 3813 s11g := float64(s11gu) 3814 s11b := float64(s11bu) 3815 s11r = xFrac1*s01r + xFrac0*s11r 3816 s11g = xFrac1*s01g + xFrac0*s11g 3817 s11b = xFrac1*s01b + xFrac0*s11b 3818 s11r = yFrac1*s10r + yFrac0*s11r 3819 s11g = yFrac1*s10g + yFrac0*s11g 3820 s11b = yFrac1*s10b + yFrac0*s11b 3821 pr := uint32(s11r) 3822 pg := uint32(s11g) 3823 pb := uint32(s11b) 3824 dst.Pix[d+0] = uint8(pr >> 8) 3825 dst.Pix[d+1] = uint8(pg >> 8) 3826 dst.Pix[d+2] = uint8(pb >> 8) 3827 dst.Pix[d+3] = 0xff 3828 } 3829 } 3830 } 3831 3832 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) { 3833 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 3834 dyf := float64(dr.Min.Y+int(dy)) + 0.5 3835 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 3836 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 3837 dxf := float64(dr.Min.X+int(dx)) + 0.5 3838 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 3839 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 3840 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 3841 continue 3842 } 3843 3844 sx -= 0.5 3845 sx0 := int(sx) 3846 xFrac0 := sx - float64(sx0) 3847 xFrac1 := 1 - xFrac0 3848 sx0 += bias.X 3849 sx1 := sx0 + 1 3850 if sx0 < sr.Min.X { 3851 sx0, sx1 = sr.Min.X, sr.Min.X 3852 xFrac0, xFrac1 = 0, 1 3853 } else if sx1 >= sr.Max.X { 3854 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 3855 xFrac0, xFrac1 = 1, 0 3856 } 3857 3858 sy -= 0.5 3859 sy0 := int(sy) 3860 yFrac0 := sy - float64(sy0) 3861 yFrac1 := 1 - yFrac0 3862 sy0 += bias.Y 3863 sy1 := sy0 + 1 3864 if sy0 < sr.Min.Y { 3865 sy0, sy1 = sr.Min.Y, sr.Min.Y 3866 yFrac0, yFrac1 = 0, 1 3867 } else if sy1 >= sr.Max.Y { 3868 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 3869 yFrac0, yFrac1 = 1, 0 3870 } 3871 3872 s00i := (sy0-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3873 s00j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X) 3874 3875 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3876 s00yy1 := int(src.Y[s00i]) * 0x10100 3877 s00cb1 := int(src.Cb[s00j]) - 128 3878 s00cr1 := int(src.Cr[s00j]) - 128 3879 s00ru := (s00yy1 + 91881*s00cr1) >> 8 3880 s00gu := (s00yy1 - 22554*s00cb1 - 46802*s00cr1) >> 8 3881 s00bu := (s00yy1 + 116130*s00cb1) >> 8 3882 if s00ru < 0 { 3883 s00ru = 0 3884 } else if s00ru > 0xffff { 3885 s00ru = 0xffff 3886 } 3887 if s00gu < 0 { 3888 s00gu = 0 3889 } else if s00gu > 0xffff { 3890 s00gu = 0xffff 3891 } 3892 if s00bu < 0 { 3893 s00bu = 0 3894 } else if s00bu > 0xffff { 3895 s00bu = 0xffff 3896 } 3897 3898 s00r := float64(s00ru) 3899 s00g := float64(s00gu) 3900 s00b := float64(s00bu) 3901 s10i := (sy0-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3902 s10j := ((sy0)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X) 3903 3904 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3905 s10yy1 := int(src.Y[s10i]) * 0x10100 3906 s10cb1 := int(src.Cb[s10j]) - 128 3907 s10cr1 := int(src.Cr[s10j]) - 128 3908 s10ru := (s10yy1 + 91881*s10cr1) >> 8 3909 s10gu := (s10yy1 - 22554*s10cb1 - 46802*s10cr1) >> 8 3910 s10bu := (s10yy1 + 116130*s10cb1) >> 8 3911 if s10ru < 0 { 3912 s10ru = 0 3913 } else if s10ru > 0xffff { 3914 s10ru = 0xffff 3915 } 3916 if s10gu < 0 { 3917 s10gu = 0 3918 } else if s10gu > 0xffff { 3919 s10gu = 0xffff 3920 } 3921 if s10bu < 0 { 3922 s10bu = 0 3923 } else if s10bu > 0xffff { 3924 s10bu = 0xffff 3925 } 3926 3927 s10r := float64(s10ru) 3928 s10g := float64(s10gu) 3929 s10b := float64(s10bu) 3930 s10r = xFrac1*s00r + xFrac0*s10r 3931 s10g = xFrac1*s00g + xFrac0*s10g 3932 s10b = xFrac1*s00b + xFrac0*s10b 3933 s01i := (sy1-src.Rect.Min.Y)*src.YStride + (sx0 - src.Rect.Min.X) 3934 s01j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx0 - src.Rect.Min.X) 3935 3936 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3937 s01yy1 := int(src.Y[s01i]) * 0x10100 3938 s01cb1 := int(src.Cb[s01j]) - 128 3939 s01cr1 := int(src.Cr[s01j]) - 128 3940 s01ru := (s01yy1 + 91881*s01cr1) >> 8 3941 s01gu := (s01yy1 - 22554*s01cb1 - 46802*s01cr1) >> 8 3942 s01bu := (s01yy1 + 116130*s01cb1) >> 8 3943 if s01ru < 0 { 3944 s01ru = 0 3945 } else if s01ru > 0xffff { 3946 s01ru = 0xffff 3947 } 3948 if s01gu < 0 { 3949 s01gu = 0 3950 } else if s01gu > 0xffff { 3951 s01gu = 0xffff 3952 } 3953 if s01bu < 0 { 3954 s01bu = 0 3955 } else if s01bu > 0xffff { 3956 s01bu = 0xffff 3957 } 3958 3959 s01r := float64(s01ru) 3960 s01g := float64(s01gu) 3961 s01b := float64(s01bu) 3962 s11i := (sy1-src.Rect.Min.Y)*src.YStride + (sx1 - src.Rect.Min.X) 3963 s11j := ((sy1)/2-src.Rect.Min.Y/2)*src.CStride + (sx1 - src.Rect.Min.X) 3964 3965 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 3966 s11yy1 := int(src.Y[s11i]) * 0x10100 3967 s11cb1 := int(src.Cb[s11j]) - 128 3968 s11cr1 := int(src.Cr[s11j]) - 128 3969 s11ru := (s11yy1 + 91881*s11cr1) >> 8 3970 s11gu := (s11yy1 - 22554*s11cb1 - 46802*s11cr1) >> 8 3971 s11bu := (s11yy1 + 116130*s11cb1) >> 8 3972 if s11ru < 0 { 3973 s11ru = 0 3974 } else if s11ru > 0xffff { 3975 s11ru = 0xffff 3976 } 3977 if s11gu < 0 { 3978 s11gu = 0 3979 } else if s11gu > 0xffff { 3980 s11gu = 0xffff 3981 } 3982 if s11bu < 0 { 3983 s11bu = 0 3984 } else if s11bu > 0xffff { 3985 s11bu = 0xffff 3986 } 3987 3988 s11r := float64(s11ru) 3989 s11g := float64(s11gu) 3990 s11b := float64(s11bu) 3991 s11r = xFrac1*s01r + xFrac0*s11r 3992 s11g = xFrac1*s01g + xFrac0*s11g 3993 s11b = xFrac1*s01b + xFrac0*s11b 3994 s11r = yFrac1*s10r + yFrac0*s11r 3995 s11g = yFrac1*s10g + yFrac0*s11g 3996 s11b = yFrac1*s10b + yFrac0*s11b 3997 pr := uint32(s11r) 3998 pg := uint32(s11g) 3999 pb := uint32(s11b) 4000 dst.Pix[d+0] = uint8(pr >> 8) 4001 dst.Pix[d+1] = uint8(pg >> 8) 4002 dst.Pix[d+2] = uint8(pb >> 8) 4003 dst.Pix[d+3] = 0xff 4004 } 4005 } 4006 } 4007 4008 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) { 4009 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 4010 dyf := float64(dr.Min.Y+int(dy)) + 0.5 4011 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 4012 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 4013 dxf := float64(dr.Min.X+int(dx)) + 0.5 4014 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 4015 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 4016 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 4017 continue 4018 } 4019 4020 sx -= 0.5 4021 sx0 := int(sx) 4022 xFrac0 := sx - float64(sx0) 4023 xFrac1 := 1 - xFrac0 4024 sx0 += bias.X 4025 sx1 := sx0 + 1 4026 if sx0 < sr.Min.X { 4027 sx0, sx1 = sr.Min.X, sr.Min.X 4028 xFrac0, xFrac1 = 0, 1 4029 } else if sx1 >= sr.Max.X { 4030 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 4031 xFrac0, xFrac1 = 1, 0 4032 } 4033 4034 sy -= 0.5 4035 sy0 := int(sy) 4036 yFrac0 := sy - float64(sy0) 4037 yFrac1 := 1 - yFrac0 4038 sy0 += bias.Y 4039 sy1 := sy0 + 1 4040 if sy0 < sr.Min.Y { 4041 sy0, sy1 = sr.Min.Y, sr.Min.Y 4042 yFrac0, yFrac1 = 0, 1 4043 } else if sy1 >= sr.Max.Y { 4044 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 4045 yFrac0, yFrac1 = 1, 0 4046 } 4047 4048 s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA() 4049 s00r := float64(s00ru) 4050 s00g := float64(s00gu) 4051 s00b := float64(s00bu) 4052 s00a := float64(s00au) 4053 s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA() 4054 s10r := float64(s10ru) 4055 s10g := float64(s10gu) 4056 s10b := float64(s10bu) 4057 s10a := float64(s10au) 4058 s10r = xFrac1*s00r + xFrac0*s10r 4059 s10g = xFrac1*s00g + xFrac0*s10g 4060 s10b = xFrac1*s00b + xFrac0*s10b 4061 s10a = xFrac1*s00a + xFrac0*s10a 4062 s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA() 4063 s01r := float64(s01ru) 4064 s01g := float64(s01gu) 4065 s01b := float64(s01bu) 4066 s01a := float64(s01au) 4067 s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA() 4068 s11r := float64(s11ru) 4069 s11g := float64(s11gu) 4070 s11b := float64(s11bu) 4071 s11a := float64(s11au) 4072 s11r = xFrac1*s01r + xFrac0*s11r 4073 s11g = xFrac1*s01g + xFrac0*s11g 4074 s11b = xFrac1*s01b + xFrac0*s11b 4075 s11a = xFrac1*s01a + xFrac0*s11a 4076 s11r = yFrac1*s10r + yFrac0*s11r 4077 s11g = yFrac1*s10g + yFrac0*s11g 4078 s11b = yFrac1*s10b + yFrac0*s11b 4079 s11a = yFrac1*s10a + yFrac0*s11a 4080 pr := uint32(s11r) 4081 pg := uint32(s11g) 4082 pb := uint32(s11b) 4083 pa := uint32(s11a) 4084 pa1 := (0xffff - pa) * 0x101 4085 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr) >> 8) 4086 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg) >> 8) 4087 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb) >> 8) 4088 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa) >> 8) 4089 } 4090 } 4091 } 4092 4093 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) { 4094 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 4095 dyf := float64(dr.Min.Y+int(dy)) + 0.5 4096 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 4097 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 4098 dxf := float64(dr.Min.X+int(dx)) + 0.5 4099 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 4100 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 4101 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 4102 continue 4103 } 4104 4105 sx -= 0.5 4106 sx0 := int(sx) 4107 xFrac0 := sx - float64(sx0) 4108 xFrac1 := 1 - xFrac0 4109 sx0 += bias.X 4110 sx1 := sx0 + 1 4111 if sx0 < sr.Min.X { 4112 sx0, sx1 = sr.Min.X, sr.Min.X 4113 xFrac0, xFrac1 = 0, 1 4114 } else if sx1 >= sr.Max.X { 4115 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 4116 xFrac0, xFrac1 = 1, 0 4117 } 4118 4119 sy -= 0.5 4120 sy0 := int(sy) 4121 yFrac0 := sy - float64(sy0) 4122 yFrac1 := 1 - yFrac0 4123 sy0 += bias.Y 4124 sy1 := sy0 + 1 4125 if sy0 < sr.Min.Y { 4126 sy0, sy1 = sr.Min.Y, sr.Min.Y 4127 yFrac0, yFrac1 = 0, 1 4128 } else if sy1 >= sr.Max.Y { 4129 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 4130 yFrac0, yFrac1 = 1, 0 4131 } 4132 4133 s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA() 4134 s00r := float64(s00ru) 4135 s00g := float64(s00gu) 4136 s00b := float64(s00bu) 4137 s00a := float64(s00au) 4138 s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA() 4139 s10r := float64(s10ru) 4140 s10g := float64(s10gu) 4141 s10b := float64(s10bu) 4142 s10a := float64(s10au) 4143 s10r = xFrac1*s00r + xFrac0*s10r 4144 s10g = xFrac1*s00g + xFrac0*s10g 4145 s10b = xFrac1*s00b + xFrac0*s10b 4146 s10a = xFrac1*s00a + xFrac0*s10a 4147 s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA() 4148 s01r := float64(s01ru) 4149 s01g := float64(s01gu) 4150 s01b := float64(s01bu) 4151 s01a := float64(s01au) 4152 s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA() 4153 s11r := float64(s11ru) 4154 s11g := float64(s11gu) 4155 s11b := float64(s11bu) 4156 s11a := float64(s11au) 4157 s11r = xFrac1*s01r + xFrac0*s11r 4158 s11g = xFrac1*s01g + xFrac0*s11g 4159 s11b = xFrac1*s01b + xFrac0*s11b 4160 s11a = xFrac1*s01a + xFrac0*s11a 4161 s11r = yFrac1*s10r + yFrac0*s11r 4162 s11g = yFrac1*s10g + yFrac0*s11g 4163 s11b = yFrac1*s10b + yFrac0*s11b 4164 s11a = yFrac1*s10a + yFrac0*s11a 4165 pr := uint32(s11r) 4166 pg := uint32(s11g) 4167 pb := uint32(s11b) 4168 pa := uint32(s11a) 4169 dst.Pix[d+0] = uint8(pr >> 8) 4170 dst.Pix[d+1] = uint8(pg >> 8) 4171 dst.Pix[d+2] = uint8(pb >> 8) 4172 dst.Pix[d+3] = uint8(pa >> 8) 4173 } 4174 } 4175 } 4176 4177 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) { 4178 srcMask, smp := opts.SrcMask, opts.SrcMaskP 4179 dstMask, dmp := opts.DstMask, opts.DstMaskP 4180 dstColorRGBA64 := &color.RGBA64{} 4181 dstColor := color.Color(dstColorRGBA64) 4182 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 4183 dyf := float64(dr.Min.Y+int(dy)) + 0.5 4184 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 4185 dxf := float64(dr.Min.X+int(dx)) + 0.5 4186 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 4187 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 4188 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 4189 continue 4190 } 4191 4192 sx -= 0.5 4193 sx0 := int(sx) 4194 xFrac0 := sx - float64(sx0) 4195 xFrac1 := 1 - xFrac0 4196 sx0 += bias.X 4197 sx1 := sx0 + 1 4198 if sx0 < sr.Min.X { 4199 sx0, sx1 = sr.Min.X, sr.Min.X 4200 xFrac0, xFrac1 = 0, 1 4201 } else if sx1 >= sr.Max.X { 4202 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 4203 xFrac0, xFrac1 = 1, 0 4204 } 4205 4206 sy -= 0.5 4207 sy0 := int(sy) 4208 yFrac0 := sy - float64(sy0) 4209 yFrac1 := 1 - yFrac0 4210 sy0 += bias.Y 4211 sy1 := sy0 + 1 4212 if sy0 < sr.Min.Y { 4213 sy0, sy1 = sr.Min.Y, sr.Min.Y 4214 yFrac0, yFrac1 = 0, 1 4215 } else if sy1 >= sr.Max.Y { 4216 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 4217 yFrac0, yFrac1 = 1, 0 4218 } 4219 4220 s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA() 4221 if srcMask != nil { 4222 _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA() 4223 s00ru = s00ru * ma / 0xffff 4224 s00gu = s00gu * ma / 0xffff 4225 s00bu = s00bu * ma / 0xffff 4226 s00au = s00au * ma / 0xffff 4227 } 4228 s00r := float64(s00ru) 4229 s00g := float64(s00gu) 4230 s00b := float64(s00bu) 4231 s00a := float64(s00au) 4232 s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA() 4233 if srcMask != nil { 4234 _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA() 4235 s10ru = s10ru * ma / 0xffff 4236 s10gu = s10gu * ma / 0xffff 4237 s10bu = s10bu * ma / 0xffff 4238 s10au = s10au * ma / 0xffff 4239 } 4240 s10r := float64(s10ru) 4241 s10g := float64(s10gu) 4242 s10b := float64(s10bu) 4243 s10a := float64(s10au) 4244 s10r = xFrac1*s00r + xFrac0*s10r 4245 s10g = xFrac1*s00g + xFrac0*s10g 4246 s10b = xFrac1*s00b + xFrac0*s10b 4247 s10a = xFrac1*s00a + xFrac0*s10a 4248 s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA() 4249 if srcMask != nil { 4250 _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA() 4251 s01ru = s01ru * ma / 0xffff 4252 s01gu = s01gu * ma / 0xffff 4253 s01bu = s01bu * ma / 0xffff 4254 s01au = s01au * ma / 0xffff 4255 } 4256 s01r := float64(s01ru) 4257 s01g := float64(s01gu) 4258 s01b := float64(s01bu) 4259 s01a := float64(s01au) 4260 s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA() 4261 if srcMask != nil { 4262 _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA() 4263 s11ru = s11ru * ma / 0xffff 4264 s11gu = s11gu * ma / 0xffff 4265 s11bu = s11bu * ma / 0xffff 4266 s11au = s11au * ma / 0xffff 4267 } 4268 s11r := float64(s11ru) 4269 s11g := float64(s11gu) 4270 s11b := float64(s11bu) 4271 s11a := float64(s11au) 4272 s11r = xFrac1*s01r + xFrac0*s11r 4273 s11g = xFrac1*s01g + xFrac0*s11g 4274 s11b = xFrac1*s01b + xFrac0*s11b 4275 s11a = xFrac1*s01a + xFrac0*s11a 4276 s11r = yFrac1*s10r + yFrac0*s11r 4277 s11g = yFrac1*s10g + yFrac0*s11g 4278 s11b = yFrac1*s10b + yFrac0*s11b 4279 s11a = yFrac1*s10a + yFrac0*s11a 4280 pr := uint32(s11r) 4281 pg := uint32(s11g) 4282 pb := uint32(s11b) 4283 pa := uint32(s11a) 4284 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 4285 if dstMask != nil { 4286 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 4287 pr = pr * ma / 0xffff 4288 pg = pg * ma / 0xffff 4289 pb = pb * ma / 0xffff 4290 pa = pa * ma / 0xffff 4291 } 4292 pa1 := 0xffff - pa 4293 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 4294 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 4295 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 4296 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 4297 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 4298 } 4299 } 4300 } 4301 4302 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) { 4303 srcMask, smp := opts.SrcMask, opts.SrcMaskP 4304 dstMask, dmp := opts.DstMask, opts.DstMaskP 4305 dstColorRGBA64 := &color.RGBA64{} 4306 dstColor := color.Color(dstColorRGBA64) 4307 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 4308 dyf := float64(dr.Min.Y+int(dy)) + 0.5 4309 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 4310 dxf := float64(dr.Min.X+int(dx)) + 0.5 4311 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 4312 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 4313 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 4314 continue 4315 } 4316 4317 sx -= 0.5 4318 sx0 := int(sx) 4319 xFrac0 := sx - float64(sx0) 4320 xFrac1 := 1 - xFrac0 4321 sx0 += bias.X 4322 sx1 := sx0 + 1 4323 if sx0 < sr.Min.X { 4324 sx0, sx1 = sr.Min.X, sr.Min.X 4325 xFrac0, xFrac1 = 0, 1 4326 } else if sx1 >= sr.Max.X { 4327 sx0, sx1 = sr.Max.X-1, sr.Max.X-1 4328 xFrac0, xFrac1 = 1, 0 4329 } 4330 4331 sy -= 0.5 4332 sy0 := int(sy) 4333 yFrac0 := sy - float64(sy0) 4334 yFrac1 := 1 - yFrac0 4335 sy0 += bias.Y 4336 sy1 := sy0 + 1 4337 if sy0 < sr.Min.Y { 4338 sy0, sy1 = sr.Min.Y, sr.Min.Y 4339 yFrac0, yFrac1 = 0, 1 4340 } else if sy1 >= sr.Max.Y { 4341 sy0, sy1 = sr.Max.Y-1, sr.Max.Y-1 4342 yFrac0, yFrac1 = 1, 0 4343 } 4344 4345 s00ru, s00gu, s00bu, s00au := src.At(sx0, sy0).RGBA() 4346 if srcMask != nil { 4347 _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy0).RGBA() 4348 s00ru = s00ru * ma / 0xffff 4349 s00gu = s00gu * ma / 0xffff 4350 s00bu = s00bu * ma / 0xffff 4351 s00au = s00au * ma / 0xffff 4352 } 4353 s00r := float64(s00ru) 4354 s00g := float64(s00gu) 4355 s00b := float64(s00bu) 4356 s00a := float64(s00au) 4357 s10ru, s10gu, s10bu, s10au := src.At(sx1, sy0).RGBA() 4358 if srcMask != nil { 4359 _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy0).RGBA() 4360 s10ru = s10ru * ma / 0xffff 4361 s10gu = s10gu * ma / 0xffff 4362 s10bu = s10bu * ma / 0xffff 4363 s10au = s10au * ma / 0xffff 4364 } 4365 s10r := float64(s10ru) 4366 s10g := float64(s10gu) 4367 s10b := float64(s10bu) 4368 s10a := float64(s10au) 4369 s10r = xFrac1*s00r + xFrac0*s10r 4370 s10g = xFrac1*s00g + xFrac0*s10g 4371 s10b = xFrac1*s00b + xFrac0*s10b 4372 s10a = xFrac1*s00a + xFrac0*s10a 4373 s01ru, s01gu, s01bu, s01au := src.At(sx0, sy1).RGBA() 4374 if srcMask != nil { 4375 _, _, _, ma := srcMask.At(smp.X+sx0, smp.Y+sy1).RGBA() 4376 s01ru = s01ru * ma / 0xffff 4377 s01gu = s01gu * ma / 0xffff 4378 s01bu = s01bu * ma / 0xffff 4379 s01au = s01au * ma / 0xffff 4380 } 4381 s01r := float64(s01ru) 4382 s01g := float64(s01gu) 4383 s01b := float64(s01bu) 4384 s01a := float64(s01au) 4385 s11ru, s11gu, s11bu, s11au := src.At(sx1, sy1).RGBA() 4386 if srcMask != nil { 4387 _, _, _, ma := srcMask.At(smp.X+sx1, smp.Y+sy1).RGBA() 4388 s11ru = s11ru * ma / 0xffff 4389 s11gu = s11gu * ma / 0xffff 4390 s11bu = s11bu * ma / 0xffff 4391 s11au = s11au * ma / 0xffff 4392 } 4393 s11r := float64(s11ru) 4394 s11g := float64(s11gu) 4395 s11b := float64(s11bu) 4396 s11a := float64(s11au) 4397 s11r = xFrac1*s01r + xFrac0*s11r 4398 s11g = xFrac1*s01g + xFrac0*s11g 4399 s11b = xFrac1*s01b + xFrac0*s11b 4400 s11a = xFrac1*s01a + xFrac0*s11a 4401 s11r = yFrac1*s10r + yFrac0*s11r 4402 s11g = yFrac1*s10g + yFrac0*s11g 4403 s11b = yFrac1*s10b + yFrac0*s11b 4404 s11a = yFrac1*s10a + yFrac0*s11a 4405 pr := uint32(s11r) 4406 pg := uint32(s11g) 4407 pb := uint32(s11b) 4408 pa := uint32(s11a) 4409 if dstMask != nil { 4410 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 4411 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 4412 pr = pr * ma / 0xffff 4413 pg = pg * ma / 0xffff 4414 pb = pb * ma / 0xffff 4415 pa = pa * ma / 0xffff 4416 pa1 := 0xffff - ma 4417 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 4418 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 4419 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 4420 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 4421 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 4422 } else { 4423 dstColorRGBA64.R = uint16(pr) 4424 dstColorRGBA64.G = uint16(pg) 4425 dstColorRGBA64.B = uint16(pb) 4426 dstColorRGBA64.A = uint16(pa) 4427 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 4428 } 4429 } 4430 } 4431 } 4432 4433 func (z *kernelScaler) Scale(dst Image, dr image.Rectangle, src image.Image, sr image.Rectangle, op Op, opts *Options) { 4434 if z.dw != int32(dr.Dx()) || z.dh != int32(dr.Dy()) || z.sw != int32(sr.Dx()) || z.sh != int32(sr.Dy()) { 4435 z.kernel.Scale(dst, dr, src, sr, op, opts) 4436 return 4437 } 4438 4439 var o Options 4440 if opts != nil { 4441 o = *opts 4442 } 4443 4444 // adr is the affected destination pixels. 4445 adr := dst.Bounds().Intersect(dr) 4446 adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP) 4447 if adr.Empty() || sr.Empty() { 4448 return 4449 } 4450 // Make adr relative to dr.Min. 4451 adr = adr.Sub(dr.Min) 4452 if op == Over && o.SrcMask == nil && opaque(src) { 4453 op = Src 4454 } 4455 4456 if _, ok := src.(*image.Uniform); ok && o.DstMask == nil && o.SrcMask == nil && sr.In(src.Bounds()) { 4457 Draw(dst, dr, src, src.Bounds().Min, op) 4458 return 4459 } 4460 4461 // Create a temporary buffer: 4462 // scaleX distributes the source image's columns over the temporary image. 4463 // scaleY distributes the temporary image's rows over the destination image. 4464 var tmp [][4]float64 4465 if z.pool.New != nil { 4466 tmpp := z.pool.Get().(*[][4]float64) 4467 defer z.pool.Put(tmpp) 4468 tmp = *tmpp 4469 } else { 4470 tmp = z.makeTmpBuf() 4471 } 4472 4473 // sr is the source pixels. If it extends beyond the src bounds, 4474 // we cannot use the type-specific fast paths, as they access 4475 // the Pix fields directly without bounds checking. 4476 // 4477 // Similarly, the fast paths assume that the masks are nil. 4478 if o.SrcMask != nil || !sr.In(src.Bounds()) { 4479 z.scaleX_Image(tmp, src, sr, &o) 4480 } else { 4481 switch src := src.(type) { 4482 case *image.Gray: 4483 z.scaleX_Gray(tmp, src, sr, &o) 4484 case *image.NRGBA: 4485 z.scaleX_NRGBA(tmp, src, sr, &o) 4486 case *image.RGBA: 4487 z.scaleX_RGBA(tmp, src, sr, &o) 4488 case *image.YCbCr: 4489 switch src.SubsampleRatio { 4490 default: 4491 z.scaleX_Image(tmp, src, sr, &o) 4492 case image.YCbCrSubsampleRatio444: 4493 z.scaleX_YCbCr444(tmp, src, sr, &o) 4494 case image.YCbCrSubsampleRatio422: 4495 z.scaleX_YCbCr422(tmp, src, sr, &o) 4496 case image.YCbCrSubsampleRatio420: 4497 z.scaleX_YCbCr420(tmp, src, sr, &o) 4498 case image.YCbCrSubsampleRatio440: 4499 z.scaleX_YCbCr440(tmp, src, sr, &o) 4500 } 4501 default: 4502 z.scaleX_Image(tmp, src, sr, &o) 4503 } 4504 } 4505 4506 if o.DstMask != nil { 4507 switch op { 4508 case Over: 4509 z.scaleY_Image_Over(dst, dr, adr, tmp, &o) 4510 case Src: 4511 z.scaleY_Image_Src(dst, dr, adr, tmp, &o) 4512 } 4513 } else { 4514 switch op { 4515 case Over: 4516 switch dst := dst.(type) { 4517 case *image.RGBA: 4518 z.scaleY_RGBA_Over(dst, dr, adr, tmp, &o) 4519 default: 4520 z.scaleY_Image_Over(dst, dr, adr, tmp, &o) 4521 } 4522 case Src: 4523 switch dst := dst.(type) { 4524 case *image.RGBA: 4525 z.scaleY_RGBA_Src(dst, dr, adr, tmp, &o) 4526 default: 4527 z.scaleY_Image_Src(dst, dr, adr, tmp, &o) 4528 } 4529 } 4530 } 4531 } 4532 4533 func (q *Kernel) Transform(dst Image, s2d f64.Aff3, src image.Image, sr image.Rectangle, op Op, opts *Options) { 4534 var o Options 4535 if opts != nil { 4536 o = *opts 4537 } 4538 4539 dr := transformRect(&s2d, &sr) 4540 // adr is the affected destination pixels. 4541 adr := dst.Bounds().Intersect(dr) 4542 adr, o.DstMask = clipAffectedDestRect(adr, o.DstMask, o.DstMaskP) 4543 if adr.Empty() || sr.Empty() { 4544 return 4545 } 4546 if op == Over && o.SrcMask == nil && opaque(src) { 4547 op = Src 4548 } 4549 d2s := invert(&s2d) 4550 // bias is a translation of the mapping from dst coordinates to src 4551 // coordinates such that the latter temporarily have non-negative X 4552 // and Y coordinates. This allows us to write int(f) instead of 4553 // int(math.Floor(f)), since "round to zero" and "round down" are 4554 // equivalent when f >= 0, but the former is much cheaper. The X-- 4555 // and Y-- are because the TransformLeaf methods have a "sx -= 0.5" 4556 // adjustment. 4557 bias := transformRect(&d2s, &adr).Min 4558 bias.X-- 4559 bias.Y-- 4560 d2s[2] -= float64(bias.X) 4561 d2s[5] -= float64(bias.Y) 4562 // Make adr relative to dr.Min. 4563 adr = adr.Sub(dr.Min) 4564 4565 if u, ok := src.(*image.Uniform); ok && o.DstMask != nil && o.SrcMask != nil && sr.In(src.Bounds()) { 4566 transform_Uniform(dst, dr, adr, &d2s, u, sr, bias, op) 4567 return 4568 } 4569 4570 xscale := abs(d2s[0]) 4571 if s := abs(d2s[1]); xscale < s { 4572 xscale = s 4573 } 4574 yscale := abs(d2s[3]) 4575 if s := abs(d2s[4]); yscale < s { 4576 yscale = s 4577 } 4578 4579 // sr is the source pixels. If it extends beyond the src bounds, 4580 // we cannot use the type-specific fast paths, as they access 4581 // the Pix fields directly without bounds checking. 4582 // 4583 // Similarly, the fast paths assume that the masks are nil. 4584 if o.DstMask != nil || o.SrcMask != nil || !sr.In(src.Bounds()) { 4585 switch op { 4586 case Over: 4587 q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4588 case Src: 4589 q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4590 } 4591 } else { 4592 switch op { 4593 case Over: 4594 switch dst := dst.(type) { 4595 case *image.RGBA: 4596 switch src := src.(type) { 4597 case *image.NRGBA: 4598 q.transform_RGBA_NRGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4599 case *image.RGBA: 4600 q.transform_RGBA_RGBA_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4601 default: 4602 q.transform_RGBA_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4603 } 4604 default: 4605 switch src := src.(type) { 4606 default: 4607 q.transform_Image_Image_Over(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4608 } 4609 } 4610 case Src: 4611 switch dst := dst.(type) { 4612 case *image.RGBA: 4613 switch src := src.(type) { 4614 case *image.Gray: 4615 q.transform_RGBA_Gray_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4616 case *image.NRGBA: 4617 q.transform_RGBA_NRGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4618 case *image.RGBA: 4619 q.transform_RGBA_RGBA_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4620 case *image.YCbCr: 4621 switch src.SubsampleRatio { 4622 default: 4623 q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4624 case image.YCbCrSubsampleRatio444: 4625 q.transform_RGBA_YCbCr444_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4626 case image.YCbCrSubsampleRatio422: 4627 q.transform_RGBA_YCbCr422_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4628 case image.YCbCrSubsampleRatio420: 4629 q.transform_RGBA_YCbCr420_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4630 case image.YCbCrSubsampleRatio440: 4631 q.transform_RGBA_YCbCr440_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4632 } 4633 default: 4634 q.transform_RGBA_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4635 } 4636 default: 4637 switch src := src.(type) { 4638 default: 4639 q.transform_Image_Image_Src(dst, dr, adr, &d2s, src, sr, bias, xscale, yscale, &o) 4640 } 4641 } 4642 } 4643 } 4644 } 4645 4646 func (z *kernelScaler) scaleX_Gray(tmp [][4]float64, src *image.Gray, sr image.Rectangle, opts *Options) { 4647 t := 0 4648 for y := int32(0); y < z.sh; y++ { 4649 for _, s := range z.horizontal.sources { 4650 var pr float64 4651 for _, c := range z.horizontal.contribs[s.i:s.j] { 4652 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4653 pru := uint32(src.Pix[pi]) * 0x101 4654 pr += float64(pru) * c.weight 4655 } 4656 pr *= s.invTotalWeightFFFF 4657 tmp[t] = [4]float64{ 4658 pr, 4659 pr, 4660 pr, 4661 1, 4662 } 4663 t++ 4664 } 4665 } 4666 } 4667 4668 func (z *kernelScaler) scaleX_NRGBA(tmp [][4]float64, src *image.NRGBA, sr image.Rectangle, opts *Options) { 4669 t := 0 4670 for y := int32(0); y < z.sh; y++ { 4671 for _, s := range z.horizontal.sources { 4672 var pr, pg, pb, pa float64 4673 for _, c := range z.horizontal.contribs[s.i:s.j] { 4674 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4 4675 pau := uint32(src.Pix[pi+3]) * 0x101 4676 pru := uint32(src.Pix[pi+0]) * pau / 0xff 4677 pgu := uint32(src.Pix[pi+1]) * pau / 0xff 4678 pbu := uint32(src.Pix[pi+2]) * pau / 0xff 4679 pr += float64(pru) * c.weight 4680 pg += float64(pgu) * c.weight 4681 pb += float64(pbu) * c.weight 4682 pa += float64(pau) * c.weight 4683 } 4684 tmp[t] = [4]float64{ 4685 pr * s.invTotalWeightFFFF, 4686 pg * s.invTotalWeightFFFF, 4687 pb * s.invTotalWeightFFFF, 4688 pa * s.invTotalWeightFFFF, 4689 } 4690 t++ 4691 } 4692 } 4693 } 4694 4695 func (z *kernelScaler) scaleX_RGBA(tmp [][4]float64, src *image.RGBA, sr image.Rectangle, opts *Options) { 4696 t := 0 4697 for y := int32(0); y < z.sh; y++ { 4698 for _, s := range z.horizontal.sources { 4699 var pr, pg, pb, pa float64 4700 for _, c := range z.horizontal.contribs[s.i:s.j] { 4701 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.Stride + (sr.Min.X+int(c.coord)-src.Rect.Min.X)*4 4702 pru := uint32(src.Pix[pi+0]) * 0x101 4703 pgu := uint32(src.Pix[pi+1]) * 0x101 4704 pbu := uint32(src.Pix[pi+2]) * 0x101 4705 pau := uint32(src.Pix[pi+3]) * 0x101 4706 pr += float64(pru) * c.weight 4707 pg += float64(pgu) * c.weight 4708 pb += float64(pbu) * c.weight 4709 pa += float64(pau) * c.weight 4710 } 4711 tmp[t] = [4]float64{ 4712 pr * s.invTotalWeightFFFF, 4713 pg * s.invTotalWeightFFFF, 4714 pb * s.invTotalWeightFFFF, 4715 pa * s.invTotalWeightFFFF, 4716 } 4717 t++ 4718 } 4719 } 4720 } 4721 4722 func (z *kernelScaler) scaleX_YCbCr444(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) { 4723 t := 0 4724 for y := int32(0); y < z.sh; y++ { 4725 for _, s := range z.horizontal.sources { 4726 var pr, pg, pb float64 4727 for _, c := range z.horizontal.contribs[s.i:s.j] { 4728 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4729 pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4730 4731 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 4732 pyy1 := int(src.Y[pi]) * 0x10100 4733 pcb1 := int(src.Cb[pj]) - 128 4734 pcr1 := int(src.Cr[pj]) - 128 4735 pru := (pyy1 + 91881*pcr1) >> 8 4736 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 4737 pbu := (pyy1 + 116130*pcb1) >> 8 4738 if pru < 0 { 4739 pru = 0 4740 } else if pru > 0xffff { 4741 pru = 0xffff 4742 } 4743 if pgu < 0 { 4744 pgu = 0 4745 } else if pgu > 0xffff { 4746 pgu = 0xffff 4747 } 4748 if pbu < 0 { 4749 pbu = 0 4750 } else if pbu > 0xffff { 4751 pbu = 0xffff 4752 } 4753 4754 pr += float64(pru) * c.weight 4755 pg += float64(pgu) * c.weight 4756 pb += float64(pbu) * c.weight 4757 } 4758 tmp[t] = [4]float64{ 4759 pr * s.invTotalWeightFFFF, 4760 pg * s.invTotalWeightFFFF, 4761 pb * s.invTotalWeightFFFF, 4762 1, 4763 } 4764 t++ 4765 } 4766 } 4767 } 4768 4769 func (z *kernelScaler) scaleX_YCbCr422(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) { 4770 t := 0 4771 for y := int32(0); y < z.sh; y++ { 4772 for _, s := range z.horizontal.sources { 4773 var pr, pg, pb float64 4774 for _, c := range z.horizontal.contribs[s.i:s.j] { 4775 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4776 pj := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.CStride + ((sr.Min.X+int(c.coord))/2 - src.Rect.Min.X/2) 4777 4778 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 4779 pyy1 := int(src.Y[pi]) * 0x10100 4780 pcb1 := int(src.Cb[pj]) - 128 4781 pcr1 := int(src.Cr[pj]) - 128 4782 pru := (pyy1 + 91881*pcr1) >> 8 4783 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 4784 pbu := (pyy1 + 116130*pcb1) >> 8 4785 if pru < 0 { 4786 pru = 0 4787 } else if pru > 0xffff { 4788 pru = 0xffff 4789 } 4790 if pgu < 0 { 4791 pgu = 0 4792 } else if pgu > 0xffff { 4793 pgu = 0xffff 4794 } 4795 if pbu < 0 { 4796 pbu = 0 4797 } else if pbu > 0xffff { 4798 pbu = 0xffff 4799 } 4800 4801 pr += float64(pru) * c.weight 4802 pg += float64(pgu) * c.weight 4803 pb += float64(pbu) * c.weight 4804 } 4805 tmp[t] = [4]float64{ 4806 pr * s.invTotalWeightFFFF, 4807 pg * s.invTotalWeightFFFF, 4808 pb * s.invTotalWeightFFFF, 4809 1, 4810 } 4811 t++ 4812 } 4813 } 4814 } 4815 4816 func (z *kernelScaler) scaleX_YCbCr420(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) { 4817 t := 0 4818 for y := int32(0); y < z.sh; y++ { 4819 for _, s := range z.horizontal.sources { 4820 var pr, pg, pb float64 4821 for _, c := range z.horizontal.contribs[s.i:s.j] { 4822 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4823 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) 4824 4825 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 4826 pyy1 := int(src.Y[pi]) * 0x10100 4827 pcb1 := int(src.Cb[pj]) - 128 4828 pcr1 := int(src.Cr[pj]) - 128 4829 pru := (pyy1 + 91881*pcr1) >> 8 4830 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 4831 pbu := (pyy1 + 116130*pcb1) >> 8 4832 if pru < 0 { 4833 pru = 0 4834 } else if pru > 0xffff { 4835 pru = 0xffff 4836 } 4837 if pgu < 0 { 4838 pgu = 0 4839 } else if pgu > 0xffff { 4840 pgu = 0xffff 4841 } 4842 if pbu < 0 { 4843 pbu = 0 4844 } else if pbu > 0xffff { 4845 pbu = 0xffff 4846 } 4847 4848 pr += float64(pru) * c.weight 4849 pg += float64(pgu) * c.weight 4850 pb += float64(pbu) * c.weight 4851 } 4852 tmp[t] = [4]float64{ 4853 pr * s.invTotalWeightFFFF, 4854 pg * s.invTotalWeightFFFF, 4855 pb * s.invTotalWeightFFFF, 4856 1, 4857 } 4858 t++ 4859 } 4860 } 4861 } 4862 4863 func (z *kernelScaler) scaleX_YCbCr440(tmp [][4]float64, src *image.YCbCr, sr image.Rectangle, opts *Options) { 4864 t := 0 4865 for y := int32(0); y < z.sh; y++ { 4866 for _, s := range z.horizontal.sources { 4867 var pr, pg, pb float64 4868 for _, c := range z.horizontal.contribs[s.i:s.j] { 4869 pi := (sr.Min.Y+int(y)-src.Rect.Min.Y)*src.YStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4870 pj := ((sr.Min.Y+int(y))/2-src.Rect.Min.Y/2)*src.CStride + (sr.Min.X + int(c.coord) - src.Rect.Min.X) 4871 4872 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 4873 pyy1 := int(src.Y[pi]) * 0x10100 4874 pcb1 := int(src.Cb[pj]) - 128 4875 pcr1 := int(src.Cr[pj]) - 128 4876 pru := (pyy1 + 91881*pcr1) >> 8 4877 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 4878 pbu := (pyy1 + 116130*pcb1) >> 8 4879 if pru < 0 { 4880 pru = 0 4881 } else if pru > 0xffff { 4882 pru = 0xffff 4883 } 4884 if pgu < 0 { 4885 pgu = 0 4886 } else if pgu > 0xffff { 4887 pgu = 0xffff 4888 } 4889 if pbu < 0 { 4890 pbu = 0 4891 } else if pbu > 0xffff { 4892 pbu = 0xffff 4893 } 4894 4895 pr += float64(pru) * c.weight 4896 pg += float64(pgu) * c.weight 4897 pb += float64(pbu) * c.weight 4898 } 4899 tmp[t] = [4]float64{ 4900 pr * s.invTotalWeightFFFF, 4901 pg * s.invTotalWeightFFFF, 4902 pb * s.invTotalWeightFFFF, 4903 1, 4904 } 4905 t++ 4906 } 4907 } 4908 } 4909 4910 func (z *kernelScaler) scaleX_Image(tmp [][4]float64, src image.Image, sr image.Rectangle, opts *Options) { 4911 t := 0 4912 srcMask, smp := opts.SrcMask, opts.SrcMaskP 4913 for y := int32(0); y < z.sh; y++ { 4914 for _, s := range z.horizontal.sources { 4915 var pr, pg, pb, pa float64 4916 for _, c := range z.horizontal.contribs[s.i:s.j] { 4917 pru, pgu, pbu, pau := src.At(sr.Min.X+int(c.coord), sr.Min.Y+int(y)).RGBA() 4918 if srcMask != nil { 4919 _, _, _, ma := srcMask.At(smp.X+sr.Min.X+int(c.coord), smp.Y+sr.Min.Y+int(y)).RGBA() 4920 pru = pru * ma / 0xffff 4921 pgu = pgu * ma / 0xffff 4922 pbu = pbu * ma / 0xffff 4923 pau = pau * ma / 0xffff 4924 } 4925 pr += float64(pru) * c.weight 4926 pg += float64(pgu) * c.weight 4927 pb += float64(pbu) * c.weight 4928 pa += float64(pau) * c.weight 4929 } 4930 tmp[t] = [4]float64{ 4931 pr * s.invTotalWeightFFFF, 4932 pg * s.invTotalWeightFFFF, 4933 pb * s.invTotalWeightFFFF, 4934 pa * s.invTotalWeightFFFF, 4935 } 4936 t++ 4937 } 4938 } 4939 } 4940 4941 func (z *kernelScaler) scaleY_RGBA_Over(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) { 4942 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 4943 d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4 4944 for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] { 4945 var pr, pg, pb, pa float64 4946 for _, c := range z.vertical.contribs[s.i:s.j] { 4947 p := &tmp[c.coord*z.dw+dx] 4948 pr += p[0] * c.weight 4949 pg += p[1] * c.weight 4950 pb += p[2] * c.weight 4951 pa += p[3] * c.weight 4952 } 4953 4954 if pr > pa { 4955 pr = pa 4956 } 4957 if pg > pa { 4958 pg = pa 4959 } 4960 if pb > pa { 4961 pb = pa 4962 } 4963 4964 pr0 := uint32(ftou(pr * s.invTotalWeight)) 4965 pg0 := uint32(ftou(pg * s.invTotalWeight)) 4966 pb0 := uint32(ftou(pb * s.invTotalWeight)) 4967 pa0 := uint32(ftou(pa * s.invTotalWeight)) 4968 pa1 := (0xffff - uint32(pa0)) * 0x101 4969 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8) 4970 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8) 4971 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8) 4972 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8) 4973 d += dst.Stride 4974 } 4975 } 4976 } 4977 4978 func (z *kernelScaler) scaleY_RGBA_Src(dst *image.RGBA, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) { 4979 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 4980 d := (dr.Min.Y+adr.Min.Y-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+int(dx)-dst.Rect.Min.X)*4 4981 for _, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] { 4982 var pr, pg, pb, pa float64 4983 for _, c := range z.vertical.contribs[s.i:s.j] { 4984 p := &tmp[c.coord*z.dw+dx] 4985 pr += p[0] * c.weight 4986 pg += p[1] * c.weight 4987 pb += p[2] * c.weight 4988 pa += p[3] * c.weight 4989 } 4990 4991 if pr > pa { 4992 pr = pa 4993 } 4994 if pg > pa { 4995 pg = pa 4996 } 4997 if pb > pa { 4998 pb = pa 4999 } 5000 5001 dst.Pix[d+0] = uint8(ftou(pr*s.invTotalWeight) >> 8) 5002 dst.Pix[d+1] = uint8(ftou(pg*s.invTotalWeight) >> 8) 5003 dst.Pix[d+2] = uint8(ftou(pb*s.invTotalWeight) >> 8) 5004 dst.Pix[d+3] = uint8(ftou(pa*s.invTotalWeight) >> 8) 5005 d += dst.Stride 5006 } 5007 } 5008 } 5009 5010 func (z *kernelScaler) scaleY_Image_Over(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) { 5011 dstMask, dmp := opts.DstMask, opts.DstMaskP 5012 dstColorRGBA64 := &color.RGBA64{} 5013 dstColor := color.Color(dstColorRGBA64) 5014 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 5015 for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] { 5016 var pr, pg, pb, pa float64 5017 for _, c := range z.vertical.contribs[s.i:s.j] { 5018 p := &tmp[c.coord*z.dw+dx] 5019 pr += p[0] * c.weight 5020 pg += p[1] * c.weight 5021 pb += p[2] * c.weight 5022 pa += p[3] * c.weight 5023 } 5024 5025 if pr > pa { 5026 pr = pa 5027 } 5028 if pg > pa { 5029 pg = pa 5030 } 5031 if pb > pa { 5032 pb = pa 5033 } 5034 5035 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA() 5036 pr0 := uint32(ftou(pr * s.invTotalWeight)) 5037 pg0 := uint32(ftou(pg * s.invTotalWeight)) 5038 pb0 := uint32(ftou(pb * s.invTotalWeight)) 5039 pa0 := uint32(ftou(pa * s.invTotalWeight)) 5040 if dstMask != nil { 5041 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA() 5042 pr0 = pr0 * ma / 0xffff 5043 pg0 = pg0 * ma / 0xffff 5044 pb0 = pb0 * ma / 0xffff 5045 pa0 = pa0 * ma / 0xffff 5046 } 5047 pa1 := 0xffff - pa0 5048 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0) 5049 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0) 5050 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0) 5051 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0) 5052 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor) 5053 } 5054 } 5055 } 5056 5057 func (z *kernelScaler) scaleY_Image_Src(dst Image, dr, adr image.Rectangle, tmp [][4]float64, opts *Options) { 5058 dstMask, dmp := opts.DstMask, opts.DstMaskP 5059 dstColorRGBA64 := &color.RGBA64{} 5060 dstColor := color.Color(dstColorRGBA64) 5061 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 5062 for dy, s := range z.vertical.sources[adr.Min.Y:adr.Max.Y] { 5063 var pr, pg, pb, pa float64 5064 for _, c := range z.vertical.contribs[s.i:s.j] { 5065 p := &tmp[c.coord*z.dw+dx] 5066 pr += p[0] * c.weight 5067 pg += p[1] * c.weight 5068 pb += p[2] * c.weight 5069 pa += p[3] * c.weight 5070 } 5071 5072 if pr > pa { 5073 pr = pa 5074 } 5075 if pg > pa { 5076 pg = pa 5077 } 5078 if pb > pa { 5079 pb = pa 5080 } 5081 5082 if dstMask != nil { 5083 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy)).RGBA() 5084 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(adr.Min.Y+dy)).RGBA() 5085 pr := uint32(ftou(pr*s.invTotalWeight)) * ma / 0xffff 5086 pg := uint32(ftou(pg*s.invTotalWeight)) * ma / 0xffff 5087 pb := uint32(ftou(pb*s.invTotalWeight)) * ma / 0xffff 5088 pa := uint32(ftou(pa*s.invTotalWeight)) * ma / 0xffff 5089 pa1 := 0xffff - ma 5090 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 5091 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 5092 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 5093 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 5094 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor) 5095 } else { 5096 dstColorRGBA64.R = ftou(pr * s.invTotalWeight) 5097 dstColorRGBA64.G = ftou(pg * s.invTotalWeight) 5098 dstColorRGBA64.B = ftou(pb * s.invTotalWeight) 5099 dstColorRGBA64.A = ftou(pa * s.invTotalWeight) 5100 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(adr.Min.Y+dy), dstColor) 5101 } 5102 } 5103 } 5104 } 5105 5106 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) { 5107 // When shrinking, broaden the effective kernel support so that we still 5108 // visit every source pixel. 5109 xHalfWidth, xKernelArgScale := q.Support, 1.0 5110 if xscale > 1 { 5111 xHalfWidth *= xscale 5112 xKernelArgScale = 1 / xscale 5113 } 5114 yHalfWidth, yKernelArgScale := q.Support, 1.0 5115 if yscale > 1 { 5116 yHalfWidth *= yscale 5117 yKernelArgScale = 1 / yscale 5118 } 5119 5120 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5121 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5122 5123 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5124 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5125 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5126 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5127 dxf := float64(dr.Min.X+int(dx)) + 0.5 5128 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5129 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5130 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5131 continue 5132 } 5133 5134 // TODO: adjust the bias so that we can use int(f) instead 5135 // of math.Floor(f) and math.Ceil(f). 5136 sx += float64(bias.X) 5137 sx -= 0.5 5138 ix := int(math.Floor(sx - xHalfWidth)) 5139 if ix < sr.Min.X { 5140 ix = sr.Min.X 5141 } 5142 jx := int(math.Ceil(sx + xHalfWidth)) 5143 if jx > sr.Max.X { 5144 jx = sr.Max.X 5145 } 5146 5147 totalXWeight := 0.0 5148 for kx := ix; kx < jx; kx++ { 5149 xWeight := 0.0 5150 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5151 xWeight = q.At(t) 5152 } 5153 xWeights[kx-ix] = xWeight 5154 totalXWeight += xWeight 5155 } 5156 for x := range xWeights[:jx-ix] { 5157 xWeights[x] /= totalXWeight 5158 } 5159 5160 sy += float64(bias.Y) 5161 sy -= 0.5 5162 iy := int(math.Floor(sy - yHalfWidth)) 5163 if iy < sr.Min.Y { 5164 iy = sr.Min.Y 5165 } 5166 jy := int(math.Ceil(sy + yHalfWidth)) 5167 if jy > sr.Max.Y { 5168 jy = sr.Max.Y 5169 } 5170 5171 totalYWeight := 0.0 5172 for ky := iy; ky < jy; ky++ { 5173 yWeight := 0.0 5174 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5175 yWeight = q.At(t) 5176 } 5177 yWeights[ky-iy] = yWeight 5178 totalYWeight += yWeight 5179 } 5180 for y := range yWeights[:jy-iy] { 5181 yWeights[y] /= totalYWeight 5182 } 5183 5184 var pr float64 5185 for ky := iy; ky < jy; ky++ { 5186 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5187 for kx := ix; kx < jx; kx++ { 5188 if w := xWeights[kx-ix] * yWeight; w != 0 { 5189 pi := (ky-src.Rect.Min.Y)*src.Stride + (kx - src.Rect.Min.X) 5190 pru := uint32(src.Pix[pi]) * 0x101 5191 pr += float64(pru) * w 5192 } 5193 } 5194 } 5195 } 5196 out := uint8(fffftou(pr) >> 8) 5197 dst.Pix[d+0] = out 5198 dst.Pix[d+1] = out 5199 dst.Pix[d+2] = out 5200 dst.Pix[d+3] = 0xff 5201 } 5202 } 5203 } 5204 5205 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) { 5206 // When shrinking, broaden the effective kernel support so that we still 5207 // visit every source pixel. 5208 xHalfWidth, xKernelArgScale := q.Support, 1.0 5209 if xscale > 1 { 5210 xHalfWidth *= xscale 5211 xKernelArgScale = 1 / xscale 5212 } 5213 yHalfWidth, yKernelArgScale := q.Support, 1.0 5214 if yscale > 1 { 5215 yHalfWidth *= yscale 5216 yKernelArgScale = 1 / yscale 5217 } 5218 5219 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5220 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5221 5222 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5223 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5224 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5225 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5226 dxf := float64(dr.Min.X+int(dx)) + 0.5 5227 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5228 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5229 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5230 continue 5231 } 5232 5233 // TODO: adjust the bias so that we can use int(f) instead 5234 // of math.Floor(f) and math.Ceil(f). 5235 sx += float64(bias.X) 5236 sx -= 0.5 5237 ix := int(math.Floor(sx - xHalfWidth)) 5238 if ix < sr.Min.X { 5239 ix = sr.Min.X 5240 } 5241 jx := int(math.Ceil(sx + xHalfWidth)) 5242 if jx > sr.Max.X { 5243 jx = sr.Max.X 5244 } 5245 5246 totalXWeight := 0.0 5247 for kx := ix; kx < jx; kx++ { 5248 xWeight := 0.0 5249 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5250 xWeight = q.At(t) 5251 } 5252 xWeights[kx-ix] = xWeight 5253 totalXWeight += xWeight 5254 } 5255 for x := range xWeights[:jx-ix] { 5256 xWeights[x] /= totalXWeight 5257 } 5258 5259 sy += float64(bias.Y) 5260 sy -= 0.5 5261 iy := int(math.Floor(sy - yHalfWidth)) 5262 if iy < sr.Min.Y { 5263 iy = sr.Min.Y 5264 } 5265 jy := int(math.Ceil(sy + yHalfWidth)) 5266 if jy > sr.Max.Y { 5267 jy = sr.Max.Y 5268 } 5269 5270 totalYWeight := 0.0 5271 for ky := iy; ky < jy; ky++ { 5272 yWeight := 0.0 5273 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5274 yWeight = q.At(t) 5275 } 5276 yWeights[ky-iy] = yWeight 5277 totalYWeight += yWeight 5278 } 5279 for y := range yWeights[:jy-iy] { 5280 yWeights[y] /= totalYWeight 5281 } 5282 5283 var pr, pg, pb, pa float64 5284 for ky := iy; ky < jy; ky++ { 5285 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5286 for kx := ix; kx < jx; kx++ { 5287 if w := xWeights[kx-ix] * yWeight; w != 0 { 5288 pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4 5289 pau := uint32(src.Pix[pi+3]) * 0x101 5290 pru := uint32(src.Pix[pi+0]) * pau / 0xff 5291 pgu := uint32(src.Pix[pi+1]) * pau / 0xff 5292 pbu := uint32(src.Pix[pi+2]) * pau / 0xff 5293 pr += float64(pru) * w 5294 pg += float64(pgu) * w 5295 pb += float64(pbu) * w 5296 pa += float64(pau) * w 5297 } 5298 } 5299 } 5300 } 5301 5302 if pr > pa { 5303 pr = pa 5304 } 5305 if pg > pa { 5306 pg = pa 5307 } 5308 if pb > pa { 5309 pb = pa 5310 } 5311 5312 pr0 := uint32(fffftou(pr)) 5313 pg0 := uint32(fffftou(pg)) 5314 pb0 := uint32(fffftou(pb)) 5315 pa0 := uint32(fffftou(pa)) 5316 pa1 := (0xffff - uint32(pa0)) * 0x101 5317 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8) 5318 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8) 5319 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8) 5320 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8) 5321 } 5322 } 5323 } 5324 5325 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) { 5326 // When shrinking, broaden the effective kernel support so that we still 5327 // visit every source pixel. 5328 xHalfWidth, xKernelArgScale := q.Support, 1.0 5329 if xscale > 1 { 5330 xHalfWidth *= xscale 5331 xKernelArgScale = 1 / xscale 5332 } 5333 yHalfWidth, yKernelArgScale := q.Support, 1.0 5334 if yscale > 1 { 5335 yHalfWidth *= yscale 5336 yKernelArgScale = 1 / yscale 5337 } 5338 5339 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5340 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5341 5342 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5343 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5344 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5345 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5346 dxf := float64(dr.Min.X+int(dx)) + 0.5 5347 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5348 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5349 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5350 continue 5351 } 5352 5353 // TODO: adjust the bias so that we can use int(f) instead 5354 // of math.Floor(f) and math.Ceil(f). 5355 sx += float64(bias.X) 5356 sx -= 0.5 5357 ix := int(math.Floor(sx - xHalfWidth)) 5358 if ix < sr.Min.X { 5359 ix = sr.Min.X 5360 } 5361 jx := int(math.Ceil(sx + xHalfWidth)) 5362 if jx > sr.Max.X { 5363 jx = sr.Max.X 5364 } 5365 5366 totalXWeight := 0.0 5367 for kx := ix; kx < jx; kx++ { 5368 xWeight := 0.0 5369 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5370 xWeight = q.At(t) 5371 } 5372 xWeights[kx-ix] = xWeight 5373 totalXWeight += xWeight 5374 } 5375 for x := range xWeights[:jx-ix] { 5376 xWeights[x] /= totalXWeight 5377 } 5378 5379 sy += float64(bias.Y) 5380 sy -= 0.5 5381 iy := int(math.Floor(sy - yHalfWidth)) 5382 if iy < sr.Min.Y { 5383 iy = sr.Min.Y 5384 } 5385 jy := int(math.Ceil(sy + yHalfWidth)) 5386 if jy > sr.Max.Y { 5387 jy = sr.Max.Y 5388 } 5389 5390 totalYWeight := 0.0 5391 for ky := iy; ky < jy; ky++ { 5392 yWeight := 0.0 5393 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5394 yWeight = q.At(t) 5395 } 5396 yWeights[ky-iy] = yWeight 5397 totalYWeight += yWeight 5398 } 5399 for y := range yWeights[:jy-iy] { 5400 yWeights[y] /= totalYWeight 5401 } 5402 5403 var pr, pg, pb, pa float64 5404 for ky := iy; ky < jy; ky++ { 5405 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5406 for kx := ix; kx < jx; kx++ { 5407 if w := xWeights[kx-ix] * yWeight; w != 0 { 5408 pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4 5409 pau := uint32(src.Pix[pi+3]) * 0x101 5410 pru := uint32(src.Pix[pi+0]) * pau / 0xff 5411 pgu := uint32(src.Pix[pi+1]) * pau / 0xff 5412 pbu := uint32(src.Pix[pi+2]) * pau / 0xff 5413 pr += float64(pru) * w 5414 pg += float64(pgu) * w 5415 pb += float64(pbu) * w 5416 pa += float64(pau) * w 5417 } 5418 } 5419 } 5420 } 5421 5422 if pr > pa { 5423 pr = pa 5424 } 5425 if pg > pa { 5426 pg = pa 5427 } 5428 if pb > pa { 5429 pb = pa 5430 } 5431 5432 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 5433 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 5434 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 5435 dst.Pix[d+3] = uint8(fffftou(pa) >> 8) 5436 } 5437 } 5438 } 5439 5440 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) { 5441 // When shrinking, broaden the effective kernel support so that we still 5442 // visit every source pixel. 5443 xHalfWidth, xKernelArgScale := q.Support, 1.0 5444 if xscale > 1 { 5445 xHalfWidth *= xscale 5446 xKernelArgScale = 1 / xscale 5447 } 5448 yHalfWidth, yKernelArgScale := q.Support, 1.0 5449 if yscale > 1 { 5450 yHalfWidth *= yscale 5451 yKernelArgScale = 1 / yscale 5452 } 5453 5454 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5455 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5456 5457 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5458 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5459 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5460 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5461 dxf := float64(dr.Min.X+int(dx)) + 0.5 5462 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5463 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5464 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5465 continue 5466 } 5467 5468 // TODO: adjust the bias so that we can use int(f) instead 5469 // of math.Floor(f) and math.Ceil(f). 5470 sx += float64(bias.X) 5471 sx -= 0.5 5472 ix := int(math.Floor(sx - xHalfWidth)) 5473 if ix < sr.Min.X { 5474 ix = sr.Min.X 5475 } 5476 jx := int(math.Ceil(sx + xHalfWidth)) 5477 if jx > sr.Max.X { 5478 jx = sr.Max.X 5479 } 5480 5481 totalXWeight := 0.0 5482 for kx := ix; kx < jx; kx++ { 5483 xWeight := 0.0 5484 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5485 xWeight = q.At(t) 5486 } 5487 xWeights[kx-ix] = xWeight 5488 totalXWeight += xWeight 5489 } 5490 for x := range xWeights[:jx-ix] { 5491 xWeights[x] /= totalXWeight 5492 } 5493 5494 sy += float64(bias.Y) 5495 sy -= 0.5 5496 iy := int(math.Floor(sy - yHalfWidth)) 5497 if iy < sr.Min.Y { 5498 iy = sr.Min.Y 5499 } 5500 jy := int(math.Ceil(sy + yHalfWidth)) 5501 if jy > sr.Max.Y { 5502 jy = sr.Max.Y 5503 } 5504 5505 totalYWeight := 0.0 5506 for ky := iy; ky < jy; ky++ { 5507 yWeight := 0.0 5508 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5509 yWeight = q.At(t) 5510 } 5511 yWeights[ky-iy] = yWeight 5512 totalYWeight += yWeight 5513 } 5514 for y := range yWeights[:jy-iy] { 5515 yWeights[y] /= totalYWeight 5516 } 5517 5518 var pr, pg, pb, pa float64 5519 for ky := iy; ky < jy; ky++ { 5520 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5521 for kx := ix; kx < jx; kx++ { 5522 if w := xWeights[kx-ix] * yWeight; w != 0 { 5523 pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4 5524 pru := uint32(src.Pix[pi+0]) * 0x101 5525 pgu := uint32(src.Pix[pi+1]) * 0x101 5526 pbu := uint32(src.Pix[pi+2]) * 0x101 5527 pau := uint32(src.Pix[pi+3]) * 0x101 5528 pr += float64(pru) * w 5529 pg += float64(pgu) * w 5530 pb += float64(pbu) * w 5531 pa += float64(pau) * w 5532 } 5533 } 5534 } 5535 } 5536 5537 if pr > pa { 5538 pr = pa 5539 } 5540 if pg > pa { 5541 pg = pa 5542 } 5543 if pb > pa { 5544 pb = pa 5545 } 5546 5547 pr0 := uint32(fffftou(pr)) 5548 pg0 := uint32(fffftou(pg)) 5549 pb0 := uint32(fffftou(pb)) 5550 pa0 := uint32(fffftou(pa)) 5551 pa1 := (0xffff - uint32(pa0)) * 0x101 5552 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8) 5553 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8) 5554 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8) 5555 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8) 5556 } 5557 } 5558 } 5559 5560 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) { 5561 // When shrinking, broaden the effective kernel support so that we still 5562 // visit every source pixel. 5563 xHalfWidth, xKernelArgScale := q.Support, 1.0 5564 if xscale > 1 { 5565 xHalfWidth *= xscale 5566 xKernelArgScale = 1 / xscale 5567 } 5568 yHalfWidth, yKernelArgScale := q.Support, 1.0 5569 if yscale > 1 { 5570 yHalfWidth *= yscale 5571 yKernelArgScale = 1 / yscale 5572 } 5573 5574 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5575 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5576 5577 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5578 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5579 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5580 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5581 dxf := float64(dr.Min.X+int(dx)) + 0.5 5582 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5583 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5584 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5585 continue 5586 } 5587 5588 // TODO: adjust the bias so that we can use int(f) instead 5589 // of math.Floor(f) and math.Ceil(f). 5590 sx += float64(bias.X) 5591 sx -= 0.5 5592 ix := int(math.Floor(sx - xHalfWidth)) 5593 if ix < sr.Min.X { 5594 ix = sr.Min.X 5595 } 5596 jx := int(math.Ceil(sx + xHalfWidth)) 5597 if jx > sr.Max.X { 5598 jx = sr.Max.X 5599 } 5600 5601 totalXWeight := 0.0 5602 for kx := ix; kx < jx; kx++ { 5603 xWeight := 0.0 5604 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5605 xWeight = q.At(t) 5606 } 5607 xWeights[kx-ix] = xWeight 5608 totalXWeight += xWeight 5609 } 5610 for x := range xWeights[:jx-ix] { 5611 xWeights[x] /= totalXWeight 5612 } 5613 5614 sy += float64(bias.Y) 5615 sy -= 0.5 5616 iy := int(math.Floor(sy - yHalfWidth)) 5617 if iy < sr.Min.Y { 5618 iy = sr.Min.Y 5619 } 5620 jy := int(math.Ceil(sy + yHalfWidth)) 5621 if jy > sr.Max.Y { 5622 jy = sr.Max.Y 5623 } 5624 5625 totalYWeight := 0.0 5626 for ky := iy; ky < jy; ky++ { 5627 yWeight := 0.0 5628 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5629 yWeight = q.At(t) 5630 } 5631 yWeights[ky-iy] = yWeight 5632 totalYWeight += yWeight 5633 } 5634 for y := range yWeights[:jy-iy] { 5635 yWeights[y] /= totalYWeight 5636 } 5637 5638 var pr, pg, pb, pa float64 5639 for ky := iy; ky < jy; ky++ { 5640 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5641 for kx := ix; kx < jx; kx++ { 5642 if w := xWeights[kx-ix] * yWeight; w != 0 { 5643 pi := (ky-src.Rect.Min.Y)*src.Stride + (kx-src.Rect.Min.X)*4 5644 pru := uint32(src.Pix[pi+0]) * 0x101 5645 pgu := uint32(src.Pix[pi+1]) * 0x101 5646 pbu := uint32(src.Pix[pi+2]) * 0x101 5647 pau := uint32(src.Pix[pi+3]) * 0x101 5648 pr += float64(pru) * w 5649 pg += float64(pgu) * w 5650 pb += float64(pbu) * w 5651 pa += float64(pau) * w 5652 } 5653 } 5654 } 5655 } 5656 5657 if pr > pa { 5658 pr = pa 5659 } 5660 if pg > pa { 5661 pg = pa 5662 } 5663 if pb > pa { 5664 pb = pa 5665 } 5666 5667 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 5668 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 5669 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 5670 dst.Pix[d+3] = uint8(fffftou(pa) >> 8) 5671 } 5672 } 5673 } 5674 5675 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) { 5676 // When shrinking, broaden the effective kernel support so that we still 5677 // visit every source pixel. 5678 xHalfWidth, xKernelArgScale := q.Support, 1.0 5679 if xscale > 1 { 5680 xHalfWidth *= xscale 5681 xKernelArgScale = 1 / xscale 5682 } 5683 yHalfWidth, yKernelArgScale := q.Support, 1.0 5684 if yscale > 1 { 5685 yHalfWidth *= yscale 5686 yKernelArgScale = 1 / yscale 5687 } 5688 5689 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5690 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5691 5692 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5693 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5694 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5695 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5696 dxf := float64(dr.Min.X+int(dx)) + 0.5 5697 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5698 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5699 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5700 continue 5701 } 5702 5703 // TODO: adjust the bias so that we can use int(f) instead 5704 // of math.Floor(f) and math.Ceil(f). 5705 sx += float64(bias.X) 5706 sx -= 0.5 5707 ix := int(math.Floor(sx - xHalfWidth)) 5708 if ix < sr.Min.X { 5709 ix = sr.Min.X 5710 } 5711 jx := int(math.Ceil(sx + xHalfWidth)) 5712 if jx > sr.Max.X { 5713 jx = sr.Max.X 5714 } 5715 5716 totalXWeight := 0.0 5717 for kx := ix; kx < jx; kx++ { 5718 xWeight := 0.0 5719 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5720 xWeight = q.At(t) 5721 } 5722 xWeights[kx-ix] = xWeight 5723 totalXWeight += xWeight 5724 } 5725 for x := range xWeights[:jx-ix] { 5726 xWeights[x] /= totalXWeight 5727 } 5728 5729 sy += float64(bias.Y) 5730 sy -= 0.5 5731 iy := int(math.Floor(sy - yHalfWidth)) 5732 if iy < sr.Min.Y { 5733 iy = sr.Min.Y 5734 } 5735 jy := int(math.Ceil(sy + yHalfWidth)) 5736 if jy > sr.Max.Y { 5737 jy = sr.Max.Y 5738 } 5739 5740 totalYWeight := 0.0 5741 for ky := iy; ky < jy; ky++ { 5742 yWeight := 0.0 5743 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5744 yWeight = q.At(t) 5745 } 5746 yWeights[ky-iy] = yWeight 5747 totalYWeight += yWeight 5748 } 5749 for y := range yWeights[:jy-iy] { 5750 yWeights[y] /= totalYWeight 5751 } 5752 5753 var pr, pg, pb float64 5754 for ky := iy; ky < jy; ky++ { 5755 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5756 for kx := ix; kx < jx; kx++ { 5757 if w := xWeights[kx-ix] * yWeight; w != 0 { 5758 pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X) 5759 pj := (ky-src.Rect.Min.Y)*src.CStride + (kx - src.Rect.Min.X) 5760 5761 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 5762 pyy1 := int(src.Y[pi]) * 0x10100 5763 pcb1 := int(src.Cb[pj]) - 128 5764 pcr1 := int(src.Cr[pj]) - 128 5765 pru := (pyy1 + 91881*pcr1) >> 8 5766 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 5767 pbu := (pyy1 + 116130*pcb1) >> 8 5768 if pru < 0 { 5769 pru = 0 5770 } else if pru > 0xffff { 5771 pru = 0xffff 5772 } 5773 if pgu < 0 { 5774 pgu = 0 5775 } else if pgu > 0xffff { 5776 pgu = 0xffff 5777 } 5778 if pbu < 0 { 5779 pbu = 0 5780 } else if pbu > 0xffff { 5781 pbu = 0xffff 5782 } 5783 5784 pr += float64(pru) * w 5785 pg += float64(pgu) * w 5786 pb += float64(pbu) * w 5787 } 5788 } 5789 } 5790 } 5791 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 5792 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 5793 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 5794 dst.Pix[d+3] = 0xff 5795 } 5796 } 5797 } 5798 5799 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) { 5800 // When shrinking, broaden the effective kernel support so that we still 5801 // visit every source pixel. 5802 xHalfWidth, xKernelArgScale := q.Support, 1.0 5803 if xscale > 1 { 5804 xHalfWidth *= xscale 5805 xKernelArgScale = 1 / xscale 5806 } 5807 yHalfWidth, yKernelArgScale := q.Support, 1.0 5808 if yscale > 1 { 5809 yHalfWidth *= yscale 5810 yKernelArgScale = 1 / yscale 5811 } 5812 5813 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5814 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5815 5816 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5817 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5818 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5819 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5820 dxf := float64(dr.Min.X+int(dx)) + 0.5 5821 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5822 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5823 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5824 continue 5825 } 5826 5827 // TODO: adjust the bias so that we can use int(f) instead 5828 // of math.Floor(f) and math.Ceil(f). 5829 sx += float64(bias.X) 5830 sx -= 0.5 5831 ix := int(math.Floor(sx - xHalfWidth)) 5832 if ix < sr.Min.X { 5833 ix = sr.Min.X 5834 } 5835 jx := int(math.Ceil(sx + xHalfWidth)) 5836 if jx > sr.Max.X { 5837 jx = sr.Max.X 5838 } 5839 5840 totalXWeight := 0.0 5841 for kx := ix; kx < jx; kx++ { 5842 xWeight := 0.0 5843 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5844 xWeight = q.At(t) 5845 } 5846 xWeights[kx-ix] = xWeight 5847 totalXWeight += xWeight 5848 } 5849 for x := range xWeights[:jx-ix] { 5850 xWeights[x] /= totalXWeight 5851 } 5852 5853 sy += float64(bias.Y) 5854 sy -= 0.5 5855 iy := int(math.Floor(sy - yHalfWidth)) 5856 if iy < sr.Min.Y { 5857 iy = sr.Min.Y 5858 } 5859 jy := int(math.Ceil(sy + yHalfWidth)) 5860 if jy > sr.Max.Y { 5861 jy = sr.Max.Y 5862 } 5863 5864 totalYWeight := 0.0 5865 for ky := iy; ky < jy; ky++ { 5866 yWeight := 0.0 5867 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5868 yWeight = q.At(t) 5869 } 5870 yWeights[ky-iy] = yWeight 5871 totalYWeight += yWeight 5872 } 5873 for y := range yWeights[:jy-iy] { 5874 yWeights[y] /= totalYWeight 5875 } 5876 5877 var pr, pg, pb float64 5878 for ky := iy; ky < jy; ky++ { 5879 if yWeight := yWeights[ky-iy]; yWeight != 0 { 5880 for kx := ix; kx < jx; kx++ { 5881 if w := xWeights[kx-ix] * yWeight; w != 0 { 5882 pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X) 5883 pj := (ky-src.Rect.Min.Y)*src.CStride + ((kx)/2 - src.Rect.Min.X/2) 5884 5885 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 5886 pyy1 := int(src.Y[pi]) * 0x10100 5887 pcb1 := int(src.Cb[pj]) - 128 5888 pcr1 := int(src.Cr[pj]) - 128 5889 pru := (pyy1 + 91881*pcr1) >> 8 5890 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 5891 pbu := (pyy1 + 116130*pcb1) >> 8 5892 if pru < 0 { 5893 pru = 0 5894 } else if pru > 0xffff { 5895 pru = 0xffff 5896 } 5897 if pgu < 0 { 5898 pgu = 0 5899 } else if pgu > 0xffff { 5900 pgu = 0xffff 5901 } 5902 if pbu < 0 { 5903 pbu = 0 5904 } else if pbu > 0xffff { 5905 pbu = 0xffff 5906 } 5907 5908 pr += float64(pru) * w 5909 pg += float64(pgu) * w 5910 pb += float64(pbu) * w 5911 } 5912 } 5913 } 5914 } 5915 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 5916 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 5917 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 5918 dst.Pix[d+3] = 0xff 5919 } 5920 } 5921 } 5922 5923 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) { 5924 // When shrinking, broaden the effective kernel support so that we still 5925 // visit every source pixel. 5926 xHalfWidth, xKernelArgScale := q.Support, 1.0 5927 if xscale > 1 { 5928 xHalfWidth *= xscale 5929 xKernelArgScale = 1 / xscale 5930 } 5931 yHalfWidth, yKernelArgScale := q.Support, 1.0 5932 if yscale > 1 { 5933 yHalfWidth *= yscale 5934 yKernelArgScale = 1 / yscale 5935 } 5936 5937 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 5938 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 5939 5940 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 5941 dyf := float64(dr.Min.Y+int(dy)) + 0.5 5942 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 5943 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 5944 dxf := float64(dr.Min.X+int(dx)) + 0.5 5945 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 5946 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 5947 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 5948 continue 5949 } 5950 5951 // TODO: adjust the bias so that we can use int(f) instead 5952 // of math.Floor(f) and math.Ceil(f). 5953 sx += float64(bias.X) 5954 sx -= 0.5 5955 ix := int(math.Floor(sx - xHalfWidth)) 5956 if ix < sr.Min.X { 5957 ix = sr.Min.X 5958 } 5959 jx := int(math.Ceil(sx + xHalfWidth)) 5960 if jx > sr.Max.X { 5961 jx = sr.Max.X 5962 } 5963 5964 totalXWeight := 0.0 5965 for kx := ix; kx < jx; kx++ { 5966 xWeight := 0.0 5967 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 5968 xWeight = q.At(t) 5969 } 5970 xWeights[kx-ix] = xWeight 5971 totalXWeight += xWeight 5972 } 5973 for x := range xWeights[:jx-ix] { 5974 xWeights[x] /= totalXWeight 5975 } 5976 5977 sy += float64(bias.Y) 5978 sy -= 0.5 5979 iy := int(math.Floor(sy - yHalfWidth)) 5980 if iy < sr.Min.Y { 5981 iy = sr.Min.Y 5982 } 5983 jy := int(math.Ceil(sy + yHalfWidth)) 5984 if jy > sr.Max.Y { 5985 jy = sr.Max.Y 5986 } 5987 5988 totalYWeight := 0.0 5989 for ky := iy; ky < jy; ky++ { 5990 yWeight := 0.0 5991 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 5992 yWeight = q.At(t) 5993 } 5994 yWeights[ky-iy] = yWeight 5995 totalYWeight += yWeight 5996 } 5997 for y := range yWeights[:jy-iy] { 5998 yWeights[y] /= totalYWeight 5999 } 6000 6001 var pr, pg, pb float64 6002 for ky := iy; ky < jy; ky++ { 6003 if yWeight := yWeights[ky-iy]; yWeight != 0 { 6004 for kx := ix; kx < jx; kx++ { 6005 if w := xWeights[kx-ix] * yWeight; w != 0 { 6006 pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X) 6007 pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + ((kx)/2 - src.Rect.Min.X/2) 6008 6009 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 6010 pyy1 := int(src.Y[pi]) * 0x10100 6011 pcb1 := int(src.Cb[pj]) - 128 6012 pcr1 := int(src.Cr[pj]) - 128 6013 pru := (pyy1 + 91881*pcr1) >> 8 6014 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 6015 pbu := (pyy1 + 116130*pcb1) >> 8 6016 if pru < 0 { 6017 pru = 0 6018 } else if pru > 0xffff { 6019 pru = 0xffff 6020 } 6021 if pgu < 0 { 6022 pgu = 0 6023 } else if pgu > 0xffff { 6024 pgu = 0xffff 6025 } 6026 if pbu < 0 { 6027 pbu = 0 6028 } else if pbu > 0xffff { 6029 pbu = 0xffff 6030 } 6031 6032 pr += float64(pru) * w 6033 pg += float64(pgu) * w 6034 pb += float64(pbu) * w 6035 } 6036 } 6037 } 6038 } 6039 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 6040 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 6041 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 6042 dst.Pix[d+3] = 0xff 6043 } 6044 } 6045 } 6046 6047 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) { 6048 // When shrinking, broaden the effective kernel support so that we still 6049 // visit every source pixel. 6050 xHalfWidth, xKernelArgScale := q.Support, 1.0 6051 if xscale > 1 { 6052 xHalfWidth *= xscale 6053 xKernelArgScale = 1 / xscale 6054 } 6055 yHalfWidth, yKernelArgScale := q.Support, 1.0 6056 if yscale > 1 { 6057 yHalfWidth *= yscale 6058 yKernelArgScale = 1 / yscale 6059 } 6060 6061 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 6062 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 6063 6064 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 6065 dyf := float64(dr.Min.Y+int(dy)) + 0.5 6066 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 6067 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 6068 dxf := float64(dr.Min.X+int(dx)) + 0.5 6069 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 6070 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 6071 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 6072 continue 6073 } 6074 6075 // TODO: adjust the bias so that we can use int(f) instead 6076 // of math.Floor(f) and math.Ceil(f). 6077 sx += float64(bias.X) 6078 sx -= 0.5 6079 ix := int(math.Floor(sx - xHalfWidth)) 6080 if ix < sr.Min.X { 6081 ix = sr.Min.X 6082 } 6083 jx := int(math.Ceil(sx + xHalfWidth)) 6084 if jx > sr.Max.X { 6085 jx = sr.Max.X 6086 } 6087 6088 totalXWeight := 0.0 6089 for kx := ix; kx < jx; kx++ { 6090 xWeight := 0.0 6091 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 6092 xWeight = q.At(t) 6093 } 6094 xWeights[kx-ix] = xWeight 6095 totalXWeight += xWeight 6096 } 6097 for x := range xWeights[:jx-ix] { 6098 xWeights[x] /= totalXWeight 6099 } 6100 6101 sy += float64(bias.Y) 6102 sy -= 0.5 6103 iy := int(math.Floor(sy - yHalfWidth)) 6104 if iy < sr.Min.Y { 6105 iy = sr.Min.Y 6106 } 6107 jy := int(math.Ceil(sy + yHalfWidth)) 6108 if jy > sr.Max.Y { 6109 jy = sr.Max.Y 6110 } 6111 6112 totalYWeight := 0.0 6113 for ky := iy; ky < jy; ky++ { 6114 yWeight := 0.0 6115 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 6116 yWeight = q.At(t) 6117 } 6118 yWeights[ky-iy] = yWeight 6119 totalYWeight += yWeight 6120 } 6121 for y := range yWeights[:jy-iy] { 6122 yWeights[y] /= totalYWeight 6123 } 6124 6125 var pr, pg, pb float64 6126 for ky := iy; ky < jy; ky++ { 6127 if yWeight := yWeights[ky-iy]; yWeight != 0 { 6128 for kx := ix; kx < jx; kx++ { 6129 if w := xWeights[kx-ix] * yWeight; w != 0 { 6130 pi := (ky-src.Rect.Min.Y)*src.YStride + (kx - src.Rect.Min.X) 6131 pj := ((ky)/2-src.Rect.Min.Y/2)*src.CStride + (kx - src.Rect.Min.X) 6132 6133 // This is an inline version of image/color/ycbcr.go's YCbCr.RGBA method. 6134 pyy1 := int(src.Y[pi]) * 0x10100 6135 pcb1 := int(src.Cb[pj]) - 128 6136 pcr1 := int(src.Cr[pj]) - 128 6137 pru := (pyy1 + 91881*pcr1) >> 8 6138 pgu := (pyy1 - 22554*pcb1 - 46802*pcr1) >> 8 6139 pbu := (pyy1 + 116130*pcb1) >> 8 6140 if pru < 0 { 6141 pru = 0 6142 } else if pru > 0xffff { 6143 pru = 0xffff 6144 } 6145 if pgu < 0 { 6146 pgu = 0 6147 } else if pgu > 0xffff { 6148 pgu = 0xffff 6149 } 6150 if pbu < 0 { 6151 pbu = 0 6152 } else if pbu > 0xffff { 6153 pbu = 0xffff 6154 } 6155 6156 pr += float64(pru) * w 6157 pg += float64(pgu) * w 6158 pb += float64(pbu) * w 6159 } 6160 } 6161 } 6162 } 6163 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 6164 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 6165 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 6166 dst.Pix[d+3] = 0xff 6167 } 6168 } 6169 } 6170 6171 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) { 6172 // When shrinking, broaden the effective kernel support so that we still 6173 // visit every source pixel. 6174 xHalfWidth, xKernelArgScale := q.Support, 1.0 6175 if xscale > 1 { 6176 xHalfWidth *= xscale 6177 xKernelArgScale = 1 / xscale 6178 } 6179 yHalfWidth, yKernelArgScale := q.Support, 1.0 6180 if yscale > 1 { 6181 yHalfWidth *= yscale 6182 yKernelArgScale = 1 / yscale 6183 } 6184 6185 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 6186 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 6187 6188 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 6189 dyf := float64(dr.Min.Y+int(dy)) + 0.5 6190 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 6191 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 6192 dxf := float64(dr.Min.X+int(dx)) + 0.5 6193 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 6194 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 6195 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 6196 continue 6197 } 6198 6199 // TODO: adjust the bias so that we can use int(f) instead 6200 // of math.Floor(f) and math.Ceil(f). 6201 sx += float64(bias.X) 6202 sx -= 0.5 6203 ix := int(math.Floor(sx - xHalfWidth)) 6204 if ix < sr.Min.X { 6205 ix = sr.Min.X 6206 } 6207 jx := int(math.Ceil(sx + xHalfWidth)) 6208 if jx > sr.Max.X { 6209 jx = sr.Max.X 6210 } 6211 6212 totalXWeight := 0.0 6213 for kx := ix; kx < jx; kx++ { 6214 xWeight := 0.0 6215 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 6216 xWeight = q.At(t) 6217 } 6218 xWeights[kx-ix] = xWeight 6219 totalXWeight += xWeight 6220 } 6221 for x := range xWeights[:jx-ix] { 6222 xWeights[x] /= totalXWeight 6223 } 6224 6225 sy += float64(bias.Y) 6226 sy -= 0.5 6227 iy := int(math.Floor(sy - yHalfWidth)) 6228 if iy < sr.Min.Y { 6229 iy = sr.Min.Y 6230 } 6231 jy := int(math.Ceil(sy + yHalfWidth)) 6232 if jy > sr.Max.Y { 6233 jy = sr.Max.Y 6234 } 6235 6236 totalYWeight := 0.0 6237 for ky := iy; ky < jy; ky++ { 6238 yWeight := 0.0 6239 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 6240 yWeight = q.At(t) 6241 } 6242 yWeights[ky-iy] = yWeight 6243 totalYWeight += yWeight 6244 } 6245 for y := range yWeights[:jy-iy] { 6246 yWeights[y] /= totalYWeight 6247 } 6248 6249 var pr, pg, pb, pa float64 6250 for ky := iy; ky < jy; ky++ { 6251 if yWeight := yWeights[ky-iy]; yWeight != 0 { 6252 for kx := ix; kx < jx; kx++ { 6253 if w := xWeights[kx-ix] * yWeight; w != 0 { 6254 pru, pgu, pbu, pau := src.At(kx, ky).RGBA() 6255 pr += float64(pru) * w 6256 pg += float64(pgu) * w 6257 pb += float64(pbu) * w 6258 pa += float64(pau) * w 6259 } 6260 } 6261 } 6262 } 6263 6264 if pr > pa { 6265 pr = pa 6266 } 6267 if pg > pa { 6268 pg = pa 6269 } 6270 if pb > pa { 6271 pb = pa 6272 } 6273 6274 pr0 := uint32(fffftou(pr)) 6275 pg0 := uint32(fffftou(pg)) 6276 pb0 := uint32(fffftou(pb)) 6277 pa0 := uint32(fffftou(pa)) 6278 pa1 := (0xffff - uint32(pa0)) * 0x101 6279 dst.Pix[d+0] = uint8((uint32(dst.Pix[d+0])*pa1/0xffff + pr0) >> 8) 6280 dst.Pix[d+1] = uint8((uint32(dst.Pix[d+1])*pa1/0xffff + pg0) >> 8) 6281 dst.Pix[d+2] = uint8((uint32(dst.Pix[d+2])*pa1/0xffff + pb0) >> 8) 6282 dst.Pix[d+3] = uint8((uint32(dst.Pix[d+3])*pa1/0xffff + pa0) >> 8) 6283 } 6284 } 6285 } 6286 6287 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) { 6288 // When shrinking, broaden the effective kernel support so that we still 6289 // visit every source pixel. 6290 xHalfWidth, xKernelArgScale := q.Support, 1.0 6291 if xscale > 1 { 6292 xHalfWidth *= xscale 6293 xKernelArgScale = 1 / xscale 6294 } 6295 yHalfWidth, yKernelArgScale := q.Support, 1.0 6296 if yscale > 1 { 6297 yHalfWidth *= yscale 6298 yKernelArgScale = 1 / yscale 6299 } 6300 6301 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 6302 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 6303 6304 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 6305 dyf := float64(dr.Min.Y+int(dy)) + 0.5 6306 d := (dr.Min.Y+int(dy)-dst.Rect.Min.Y)*dst.Stride + (dr.Min.X+adr.Min.X-dst.Rect.Min.X)*4 6307 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx, d = dx+1, d+4 { 6308 dxf := float64(dr.Min.X+int(dx)) + 0.5 6309 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 6310 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 6311 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 6312 continue 6313 } 6314 6315 // TODO: adjust the bias so that we can use int(f) instead 6316 // of math.Floor(f) and math.Ceil(f). 6317 sx += float64(bias.X) 6318 sx -= 0.5 6319 ix := int(math.Floor(sx - xHalfWidth)) 6320 if ix < sr.Min.X { 6321 ix = sr.Min.X 6322 } 6323 jx := int(math.Ceil(sx + xHalfWidth)) 6324 if jx > sr.Max.X { 6325 jx = sr.Max.X 6326 } 6327 6328 totalXWeight := 0.0 6329 for kx := ix; kx < jx; kx++ { 6330 xWeight := 0.0 6331 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 6332 xWeight = q.At(t) 6333 } 6334 xWeights[kx-ix] = xWeight 6335 totalXWeight += xWeight 6336 } 6337 for x := range xWeights[:jx-ix] { 6338 xWeights[x] /= totalXWeight 6339 } 6340 6341 sy += float64(bias.Y) 6342 sy -= 0.5 6343 iy := int(math.Floor(sy - yHalfWidth)) 6344 if iy < sr.Min.Y { 6345 iy = sr.Min.Y 6346 } 6347 jy := int(math.Ceil(sy + yHalfWidth)) 6348 if jy > sr.Max.Y { 6349 jy = sr.Max.Y 6350 } 6351 6352 totalYWeight := 0.0 6353 for ky := iy; ky < jy; ky++ { 6354 yWeight := 0.0 6355 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 6356 yWeight = q.At(t) 6357 } 6358 yWeights[ky-iy] = yWeight 6359 totalYWeight += yWeight 6360 } 6361 for y := range yWeights[:jy-iy] { 6362 yWeights[y] /= totalYWeight 6363 } 6364 6365 var pr, pg, pb, pa float64 6366 for ky := iy; ky < jy; ky++ { 6367 if yWeight := yWeights[ky-iy]; yWeight != 0 { 6368 for kx := ix; kx < jx; kx++ { 6369 if w := xWeights[kx-ix] * yWeight; w != 0 { 6370 pru, pgu, pbu, pau := src.At(kx, ky).RGBA() 6371 pr += float64(pru) * w 6372 pg += float64(pgu) * w 6373 pb += float64(pbu) * w 6374 pa += float64(pau) * w 6375 } 6376 } 6377 } 6378 } 6379 6380 if pr > pa { 6381 pr = pa 6382 } 6383 if pg > pa { 6384 pg = pa 6385 } 6386 if pb > pa { 6387 pb = pa 6388 } 6389 6390 dst.Pix[d+0] = uint8(fffftou(pr) >> 8) 6391 dst.Pix[d+1] = uint8(fffftou(pg) >> 8) 6392 dst.Pix[d+2] = uint8(fffftou(pb) >> 8) 6393 dst.Pix[d+3] = uint8(fffftou(pa) >> 8) 6394 } 6395 } 6396 } 6397 6398 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) { 6399 // When shrinking, broaden the effective kernel support so that we still 6400 // visit every source pixel. 6401 xHalfWidth, xKernelArgScale := q.Support, 1.0 6402 if xscale > 1 { 6403 xHalfWidth *= xscale 6404 xKernelArgScale = 1 / xscale 6405 } 6406 yHalfWidth, yKernelArgScale := q.Support, 1.0 6407 if yscale > 1 { 6408 yHalfWidth *= yscale 6409 yKernelArgScale = 1 / yscale 6410 } 6411 6412 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 6413 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 6414 6415 srcMask, smp := opts.SrcMask, opts.SrcMaskP 6416 dstMask, dmp := opts.DstMask, opts.DstMaskP 6417 dstColorRGBA64 := &color.RGBA64{} 6418 dstColor := color.Color(dstColorRGBA64) 6419 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 6420 dyf := float64(dr.Min.Y+int(dy)) + 0.5 6421 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 6422 dxf := float64(dr.Min.X+int(dx)) + 0.5 6423 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 6424 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 6425 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 6426 continue 6427 } 6428 6429 // TODO: adjust the bias so that we can use int(f) instead 6430 // of math.Floor(f) and math.Ceil(f). 6431 sx += float64(bias.X) 6432 sx -= 0.5 6433 ix := int(math.Floor(sx - xHalfWidth)) 6434 if ix < sr.Min.X { 6435 ix = sr.Min.X 6436 } 6437 jx := int(math.Ceil(sx + xHalfWidth)) 6438 if jx > sr.Max.X { 6439 jx = sr.Max.X 6440 } 6441 6442 totalXWeight := 0.0 6443 for kx := ix; kx < jx; kx++ { 6444 xWeight := 0.0 6445 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 6446 xWeight = q.At(t) 6447 } 6448 xWeights[kx-ix] = xWeight 6449 totalXWeight += xWeight 6450 } 6451 for x := range xWeights[:jx-ix] { 6452 xWeights[x] /= totalXWeight 6453 } 6454 6455 sy += float64(bias.Y) 6456 sy -= 0.5 6457 iy := int(math.Floor(sy - yHalfWidth)) 6458 if iy < sr.Min.Y { 6459 iy = sr.Min.Y 6460 } 6461 jy := int(math.Ceil(sy + yHalfWidth)) 6462 if jy > sr.Max.Y { 6463 jy = sr.Max.Y 6464 } 6465 6466 totalYWeight := 0.0 6467 for ky := iy; ky < jy; ky++ { 6468 yWeight := 0.0 6469 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 6470 yWeight = q.At(t) 6471 } 6472 yWeights[ky-iy] = yWeight 6473 totalYWeight += yWeight 6474 } 6475 for y := range yWeights[:jy-iy] { 6476 yWeights[y] /= totalYWeight 6477 } 6478 6479 var pr, pg, pb, pa float64 6480 for ky := iy; ky < jy; ky++ { 6481 if yWeight := yWeights[ky-iy]; yWeight != 0 { 6482 for kx := ix; kx < jx; kx++ { 6483 if w := xWeights[kx-ix] * yWeight; w != 0 { 6484 pru, pgu, pbu, pau := src.At(kx, ky).RGBA() 6485 if srcMask != nil { 6486 _, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA() 6487 pru = pru * ma / 0xffff 6488 pgu = pgu * ma / 0xffff 6489 pbu = pbu * ma / 0xffff 6490 pau = pau * ma / 0xffff 6491 } 6492 pr += float64(pru) * w 6493 pg += float64(pgu) * w 6494 pb += float64(pbu) * w 6495 pa += float64(pau) * w 6496 } 6497 } 6498 } 6499 } 6500 6501 if pr > pa { 6502 pr = pa 6503 } 6504 if pg > pa { 6505 pg = pa 6506 } 6507 if pb > pa { 6508 pb = pa 6509 } 6510 6511 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 6512 pr0 := uint32(fffftou(pr)) 6513 pg0 := uint32(fffftou(pg)) 6514 pb0 := uint32(fffftou(pb)) 6515 pa0 := uint32(fffftou(pa)) 6516 if dstMask != nil { 6517 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 6518 pr0 = pr0 * ma / 0xffff 6519 pg0 = pg0 * ma / 0xffff 6520 pb0 = pb0 * ma / 0xffff 6521 pa0 = pa0 * ma / 0xffff 6522 } 6523 pa1 := 0xffff - pa0 6524 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr0) 6525 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg0) 6526 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb0) 6527 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa0) 6528 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 6529 } 6530 } 6531 } 6532 6533 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) { 6534 // When shrinking, broaden the effective kernel support so that we still 6535 // visit every source pixel. 6536 xHalfWidth, xKernelArgScale := q.Support, 1.0 6537 if xscale > 1 { 6538 xHalfWidth *= xscale 6539 xKernelArgScale = 1 / xscale 6540 } 6541 yHalfWidth, yKernelArgScale := q.Support, 1.0 6542 if yscale > 1 { 6543 yHalfWidth *= yscale 6544 yKernelArgScale = 1 / yscale 6545 } 6546 6547 xWeights := make([]float64, 1+2*int(math.Ceil(xHalfWidth))) 6548 yWeights := make([]float64, 1+2*int(math.Ceil(yHalfWidth))) 6549 6550 srcMask, smp := opts.SrcMask, opts.SrcMaskP 6551 dstMask, dmp := opts.DstMask, opts.DstMaskP 6552 dstColorRGBA64 := &color.RGBA64{} 6553 dstColor := color.Color(dstColorRGBA64) 6554 for dy := int32(adr.Min.Y); dy < int32(adr.Max.Y); dy++ { 6555 dyf := float64(dr.Min.Y+int(dy)) + 0.5 6556 for dx := int32(adr.Min.X); dx < int32(adr.Max.X); dx++ { 6557 dxf := float64(dr.Min.X+int(dx)) + 0.5 6558 sx := d2s[0]*dxf + d2s[1]*dyf + d2s[2] 6559 sy := d2s[3]*dxf + d2s[4]*dyf + d2s[5] 6560 if !(image.Point{int(sx) + bias.X, int(sy) + bias.Y}).In(sr) { 6561 continue 6562 } 6563 6564 // TODO: adjust the bias so that we can use int(f) instead 6565 // of math.Floor(f) and math.Ceil(f). 6566 sx += float64(bias.X) 6567 sx -= 0.5 6568 ix := int(math.Floor(sx - xHalfWidth)) 6569 if ix < sr.Min.X { 6570 ix = sr.Min.X 6571 } 6572 jx := int(math.Ceil(sx + xHalfWidth)) 6573 if jx > sr.Max.X { 6574 jx = sr.Max.X 6575 } 6576 6577 totalXWeight := 0.0 6578 for kx := ix; kx < jx; kx++ { 6579 xWeight := 0.0 6580 if t := abs((sx - float64(kx)) * xKernelArgScale); t < q.Support { 6581 xWeight = q.At(t) 6582 } 6583 xWeights[kx-ix] = xWeight 6584 totalXWeight += xWeight 6585 } 6586 for x := range xWeights[:jx-ix] { 6587 xWeights[x] /= totalXWeight 6588 } 6589 6590 sy += float64(bias.Y) 6591 sy -= 0.5 6592 iy := int(math.Floor(sy - yHalfWidth)) 6593 if iy < sr.Min.Y { 6594 iy = sr.Min.Y 6595 } 6596 jy := int(math.Ceil(sy + yHalfWidth)) 6597 if jy > sr.Max.Y { 6598 jy = sr.Max.Y 6599 } 6600 6601 totalYWeight := 0.0 6602 for ky := iy; ky < jy; ky++ { 6603 yWeight := 0.0 6604 if t := abs((sy - float64(ky)) * yKernelArgScale); t < q.Support { 6605 yWeight = q.At(t) 6606 } 6607 yWeights[ky-iy] = yWeight 6608 totalYWeight += yWeight 6609 } 6610 for y := range yWeights[:jy-iy] { 6611 yWeights[y] /= totalYWeight 6612 } 6613 6614 var pr, pg, pb, pa float64 6615 for ky := iy; ky < jy; ky++ { 6616 if yWeight := yWeights[ky-iy]; yWeight != 0 { 6617 for kx := ix; kx < jx; kx++ { 6618 if w := xWeights[kx-ix] * yWeight; w != 0 { 6619 pru, pgu, pbu, pau := src.At(kx, ky).RGBA() 6620 if srcMask != nil { 6621 _, _, _, ma := srcMask.At(smp.X+kx, smp.Y+ky).RGBA() 6622 pru = pru * ma / 0xffff 6623 pgu = pgu * ma / 0xffff 6624 pbu = pbu * ma / 0xffff 6625 pau = pau * ma / 0xffff 6626 } 6627 pr += float64(pru) * w 6628 pg += float64(pgu) * w 6629 pb += float64(pbu) * w 6630 pa += float64(pau) * w 6631 } 6632 } 6633 } 6634 } 6635 6636 if pr > pa { 6637 pr = pa 6638 } 6639 if pg > pa { 6640 pg = pa 6641 } 6642 if pb > pa { 6643 pb = pa 6644 } 6645 6646 if dstMask != nil { 6647 qr, qg, qb, qa := dst.At(dr.Min.X+int(dx), dr.Min.Y+int(dy)).RGBA() 6648 _, _, _, ma := dstMask.At(dmp.X+dr.Min.X+int(dx), dmp.Y+dr.Min.Y+int(dy)).RGBA() 6649 pr := uint32(fffftou(pr)) * ma / 0xffff 6650 pg := uint32(fffftou(pg)) * ma / 0xffff 6651 pb := uint32(fffftou(pb)) * ma / 0xffff 6652 pa := uint32(fffftou(pa)) * ma / 0xffff 6653 pa1 := 0xffff - ma 6654 dstColorRGBA64.R = uint16(qr*pa1/0xffff + pr) 6655 dstColorRGBA64.G = uint16(qg*pa1/0xffff + pg) 6656 dstColorRGBA64.B = uint16(qb*pa1/0xffff + pb) 6657 dstColorRGBA64.A = uint16(qa*pa1/0xffff + pa) 6658 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 6659 } else { 6660 dstColorRGBA64.R = fffftou(pr) 6661 dstColorRGBA64.G = fffftou(pg) 6662 dstColorRGBA64.B = fffftou(pb) 6663 dstColorRGBA64.A = fffftou(pa) 6664 dst.Set(dr.Min.X+int(dx), dr.Min.Y+int(dy), dstColor) 6665 } 6666 } 6667 } 6668 }