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